1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//! [![Documentation](https://docs.rs/oursh/badge.svg)](https://docs.rs/oursh)
//! [![CI](https://github.com/nixpulvis/oursh/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/nixpulvis/oursh/actions/workflows/ci.yml)
//! [![Dependencies](https://deps.rs/repo/github/nixpulvis/oursh/status.svg)](https://deps.rs/repo/github/nixpulvis/oursh)
//!
//!
//! This shell should be both POSIX compatible and yet modern and exciting.
//! Fancy features should not be prevented by POSIX compatibility. This will
//! effect the design of the shell.
//!
//! The name of the shell is `oursh` which is both somewhat unique, and
//! memorable.  It's also a nice name to play with pseudo-satirical themes...
//! right comrade?  It's short (ish) and sneakily fits `rs` in it, which is the
//! extension of Rust programs, the language this will be written in.
//!
//! ## Features
//!
//! - [ ] POSIX compatibility
//!     - [x] Simple commands `ls`
//!     - [ ] Quotes `echo "foo"; echo 'bar'`
//!     - [x] Assignment `LOG=trace cargo run`
//!     - [x] Variables `echo $foo`
//!     - [ ] Special variables `echo $?; echo $1`
//!     - [x] Boolean status syntax `! true && false || true`
//!     - [x] Conditionals `if ; then ; elif ; then ; else ; fi`
//!     - [ ] Compound commands `{ ls; date; }`
//!     - [ ] Subshells `(sleep 1; date)`
//!     - [x] Background jobs `{ sleep 1; date; }& date`
//!     - [x] Redirection `date > now.txt`
//!     - [ ] Pipes `ls | wc -l`
//! - [ ] Shebang block programs
//!     - [ ] Alternate syntax `{# ...}`
//!     - [ ] Hashlang syntax `{#lang; ...}`, i.e. `{#posix ls}`
//!     - [x] Shebang syntax `{#!/usr/bin/env ruby; puts :sym}`
//! - [ ] bash/zsh autocomplete compatibility
//!     - [x] Command completion
//!     - [ ] Path completion
//!     - [ ] Variable completion
//!     - [ ] Job completion
//!     - [ ] Syntax completion
//!     - [ ] `man` / `-h` / `--help` parsing
//! - [ ] Multi-line input
//! - [ ] Modern scripting language
//!     - [ ] Macros
//!     - [ ] Types
//!     - [ ] Higher-order functions
//!     - [ ] Threading?
//! - [ ] Obfuscated strings (`!'password'!`)
//! - [ ] mosh like remote session support
//! - [ ] Smart history, sync'd across devices
//! - [ ] Pipe old commands without rerunning
//! - [ ] Package manager
//! - Sane defaults
//! - Fast
//!
//!
//! ## [POSIX Reference][posix-ref]
//!
//! See the following sections for building the POSIX `sh` compliant program
//! language, and interactive terminal based REPL. While this mainly defines the
//! [`posix`][program::posix] module, there are a lot of common concepts to all
//! shells here.
//!
//! - 3§2 Shell Command Language
//!     - 10.2 Shell Grammar Rules
//! - 2§2.5 Standard I/O Streams
//! - 3§1.6 Built-In Utilities
//! - 3§1.4 Utility Description Defaults
//! - 2§2.3 Error Numbers
//! - 1§11 General Terminal Interface
//! - 2§2.4 Signal Concepts
//!
//!
//! ## Implementation
//!
//! This shell will be written in Rust with minimal dependencies. Notably
//! `termios` and `libc` will likely be used. The parsing library will be
//! `lalrpop`, which should support the syntax we want somewhat easily, though
//! grammar's in general can be a tricky beast.
//!
//! We will want to create a few internal modules for the shell.
//!
//! **This design is subject to change.**
//!
//! - `process` - sub-process execution management.
//! - `program` - parser and interpreter for the syntax of the shell.
//!     - `posix` - POSIX (`sh`-like) syntax.
//!     - `modern` - Modified syntax for supporting "modern" features, like lambdas.
//! - `repl` - syntax aware, read eval print loop for an underlying terminal.
//!     - `history` - records previous execution to a shared DB.
//!     - `completion` - searches for autocompletions based on partial syntax.
//!         - `bash` - bash completion support.
//!         - `zsh` - zsh completion support.
//!         - `parse` - dynamic completion generation, from `man` for example.
//!     - `sync` - remote session and DB synchronization.
//! - `invocation` - loading for `.ourshrc` and others.
//! - `package` - simplistic package manager support (builtin function).
//!
//!
//! [documentation]: https://nixpulvis.com/oursh/oursh
//! [rustup]: https://github.com/rust-lang-nursery/rustup.rs
//! [posix-ref]: http://pubs.opengroup.org/onlinepubs/9699919799/
#![feature(box_syntax, box_patterns, with_options)]

extern crate nix;
extern crate pwd;
extern crate termion;

#[macro_use]
extern crate lalrpop_util;

/// Print debug information to stderr.
///
/// ### Examples
///
/// ```
/// use oursh::debug;
///
/// debug!(1 + 2);
///
/// let msg = "because.";
/// debug!("why!? {}", msg);
/// ```
#[macro_export]
macro_rules! debug {
    ($e:expr) => {
        if let Ok(_level) = ::std::env::var("LOG") {
            eprintln!("{:#?}", $e);
        }
    };
    ($format:expr, $($e:expr),*) => {
        if let Ok(_level) = ::std::env::var("LOG") {
            eprintln!($format, $($e),*);
        }
    };
}

pub mod invocation;
pub mod process;
pub mod program;

// pub mod repl;


#[macro_use]
#[cfg(test)]
extern crate assert_matches;

#[cfg(test)]
mod tests {
    // This just tests syntax.
    #[test]
    fn debug_macro() {
        debug!(1);
        debug!(1 + 2);
        debug!("addition: {}", 1 + 2);
        debug!("{}", vec![1,2,3,4][2]);
        debug!("{} = {} * {}", 15, 3, 5);
    }
}