WIP early start on pipe command

This commit is contained in:
Ava Apples Affine 2023-04-05 21:18:40 -07:00
parent ba38fbde04
commit 9c0f88ec91
Signed by: affine
GPG key ID: 3A4645B8CF806069
2 changed files with 71 additions and 2 deletions

View file

@ -452,7 +452,7 @@ Representation of code trees, traversals, and type annotations all live here.
*** lib: file:src/lib.rs *** lib: file:src/lib.rs
This defines a library that can be included to provide an interpreter interface within any Rust project. This defines a library that can be included to provide an interpreter interface within any Rust project.
The components defined here can certainly be used to support language development for other LISP (or non LISP) langauges. The components defined here can certainly be used to support language development for other LISP (or non LISP) langauges.`
Your project can use or not use any number of these components. Your project can use or not use any number of these components.
*** sym: file:src/sym.rs *** sym: file:src/sym.rs

View file

@ -165,6 +165,57 @@ fn load_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Resu
} }
} }
// TODO: maybe flesh out this docstring a bit
const PIPE_DOCSTRING: &str = "Calls a sequence of shell commands.
Each one has their output redirected to the input of the next one.
Example:
(pipe
(ls -la)
(grep '*.rs')
(tr -d '.rs'))";
fn pipe_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Result<Ctr, String> {
if ast.is_empty() {
return Err("need at least one argument".to_string())
}
let mut input = Stdio::inherit();
if !ast.circuit(&mut |arg: &Ctr| -> bool {
if let Ctr::Seg(command_form) = arg {
let args = VecDeque::from(args_from_ast(ast, syms));
if args.is_empty() {
return false
}
if let Some(filepath) = run::find_on_path(args.pop_front().unwrap()) {
let tmp = Stdio::piped();
// TODO Youll just have to break open launch_command here
// youll need seperate calls for .stdin and .stdout anyways
// and also the move semantics are not working
launch_command(
filepath,
&Vec::from(args.make_contiguous()),
input,
Stdio::inherit(),
tmp,
false,
state,
).unwrap();
input = tmp;
true
} else {
eprintln!("file not found");
false
}
} else {
false
}
}) {
Err("all arguments must be full shell commands".to_string())
} else {
Ok(Ctr::None)
}
}
const LOAD_TO_STRING_DOCSTRING: &str = "Calls a binary off disk with given arguments. 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. Arguments may be of any type except lambda. If a symbol is not defined it will be passed as a string.
@ -208,7 +259,25 @@ fn load_to_string_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellStat
} }
// TODO: rework this callback to reduce spaghett // TODO: rework this callback to reduce spaghett
const LOAD_WITH_DOCSTRING: &str = ""; const LOAD_WITH_DOCSTRING: &str = "Takes two arguments.
1. a list of up to three redirects
- A redirect looks like a variable declaration in a let form
Ex: ('stdout' '/dev/null')
- The first value is one of 'stdout', 'stdin', or 'stderr'
- The second value is a filename.
The file must exist for stdin redirects.
For other redirects the file will be created if not existing.
Example: (('stdin' '/path/to/myinput.txt')
('stdout' '/dev/null'))
2. a shell command
- exactly as would be passed to load
Example: (ping -c 4 google.com)
Example invocation:
(load-with (('stdout' '/dev/null'))
(ping -c 4 google.com))";
fn load_with_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Result<Ctr, String> { fn load_with_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Result<Ctr, String> {
if ast.len() != 2 { if ast.len() != 2 {
Err("exactly two arguments needed".to_string()) Err("exactly two arguments needed".to_string())