diff --git a/Cargo.toml b/Cargo.toml index d456d25..7ceedba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,36 +1,12 @@ -Readme.org:65:Function calls are executed as soon as the tree is evaluated. See the following example: -Readme.org:324:You can use it by calling it in your shell config (See file:snippets/basic_minimal_configuration.rls for more info). -Readme.org:382:See file:snippets/basic_minimal_configuration.rls for an example of a basic minimal configuration file. -snippets/userlib.rls:13:;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/userlib.rls:45: See the userlib tests for an easy to follow example of this.' -snippets/userlib-tests.rls:13:;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/eval_draft2.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/eval.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/bin/main.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/func.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/segment.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/control.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/stl.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/str.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/config.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/lib.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/lex.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/append.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/initial_rough_spaghetti_implementation/vars.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/seperate_tables/func.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -snippets/legacy/seperate_tables/vars.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/eval.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/bin/main.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/run.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/segment.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/sym.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/stl.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/stl/posix.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/stl/decl.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/stl/strings.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/stl/control.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/stl/math.rs:10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/stl/boolean.rs:10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/stl/append.rs:10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/lib.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -src/lex.rs:11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +[package] +name = "relish" +version = "0.1.0" +authors = ["Ava "] +edition = "2018" + +[dependencies] +dirs = "3.0" +nu-ansi-term = "0.47.0" +reedline = "0.17.0" +nix = "0.26.2" +ctrlc = { version = "3.0", features = ["termination"] } \ No newline at end of file diff --git a/Readme.org b/Readme.org index 5c56b36..ea63737 100644 --- a/Readme.org +++ b/Readme.org @@ -483,8 +483,6 @@ Note: this section only tracks the state of incomplete TODO items. Having everyt ** TODO Pre-alpha tasks - Shell module - - call-with (let style fd redirection) - - load-to-string function (userlib extension of call-with) - pipe control flow construct - ignore job control signals (if needed) - background processes @@ -495,7 +493,7 @@ Note: this section only tracks the state of incomplete TODO items. Having everyt - pwd - Documentation! - Do I need some linemode management stuff? - - Fake load in pre-posix shell outputs "shell not yet configured!" + - Function stubs for all posix functions go into minimal shell (posix stub functions) - Escape sequences in strings - logging library - make const all the error messages diff --git a/src/stl/posix.rs b/src/stl/posix.rs index 4f0bc46..ddc8531 100644 --- a/src/stl/posix.rs +++ b/src/stl/posix.rs @@ -165,6 +165,48 @@ fn load_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Resu } } + +const LOAD_TO_STRING_DOCSTRING: &str = "Calls a binary off disk with given arguments. +Arguments may be of any type except lambda. If a symbol is not defined it will be passed as a string. +first argument (command name) will be found on path (or an error returned). + +examples: + (l ping google.com) + (let ((ping-count 4)) + (l ping -c ping-count google.com)) + (l emacs -nw (concat HOME '/.relishrc')) + +Unlike with the normal load function, the load to string function collects stdout output and returns it as a string. +"; +fn load_to_string_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Result { + if ast.is_empty() { + Err("need at least one argument".to_string()) + } else { + let mut args = VecDeque::from(args_from_ast(ast, syms)); + if args.is_empty() { + Err("empty command".to_string()) + } else { + if let Some(filepath) = run::find_on_path(args.pop_front().unwrap()) { + let res = Command::new(filepath).args(args).output(); + if let Ok(output) = res { + if let Some(code) = output.status.code() { + state.last_exit_code = code; + } + if let Ok(string) = String::from_utf8(output.stdout) { + Ok(Ctr::String(string)) + } else { + Err(format!("could'nt marshall utf-8 command output into a string")) + } + } else { + Err(format!("{}", res.err().unwrap())) + } + } else { + Err("file not found".to_string()) + } + } + } +} + // TODO: rework this callback to reduce spaghett const LOAD_WITH_DOCSTRING: &str = ""; fn load_with_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Result { @@ -346,6 +388,7 @@ pub fn load_posix_shell(syms: &mut SymTable, shell_state: Rc let bg_ss = shell_state.clone(); let q_ss = shell_state.clone(); let lw_ss = shell_state.clone(); + let lts_ss = shell_state.clone(); syms.insert( String::from("l"), @@ -417,6 +460,19 @@ pub fn load_posix_shell(syms: &mut SymTable, shell_state: Rc }, ); + syms.insert( + String::from("load-to-string"), + Symbol { + name: String::from("load-to-string"), + args: Args::Infinite, + conditional_branches: true, + docs: String::from(LOAD_TO_STRING_DOCSTRING), + value: ValueType::Internal(Rc::new(move |ast: &Seg, symtable: &mut SymTable| -> Result { + load_to_string_callback(ast, symtable, &mut lts_ss.clone().borrow_mut()) + })), + ..Default::default() + }, + ); if let Err(e) = ctrlc::set_handler(move || println!("POSIX layer caught SIG-something")) { eprintln!("WARNING: couldn't set sig handler: {}", e);