configurable cd hook
Signed-off-by: Ava Affine <ava@sunnypup.io>
This commit is contained in:
parent
6351ac63d2
commit
50ebfd2e37
4 changed files with 77 additions and 29 deletions
|
|
@ -63,6 +63,7 @@ use {
|
|||
};
|
||||
|
||||
pub const POSIX_LOAD_NAME: &str = "load";
|
||||
pub const CD_USER_CB: &str = "CFG_FLESH_CD_CB";
|
||||
|
||||
pub struct ShellState {
|
||||
pub parent_pid: Pid,
|
||||
|
|
@ -714,38 +715,69 @@ fn fg_callback(
|
|||
}
|
||||
|
||||
const CD_DOCSTRING: &str =
|
||||
"Expects 1 argument (a string). Changes to a new directory";
|
||||
"Expects 1 argument (a string). Changes to a new directory.
|
||||
If CFG_RELISH_CD_CB is defined, cd will evaluate it.
|
||||
cd returns the result that CFG_RELISH_CD_CB returns.";
|
||||
fn cd_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
|
||||
if let Ctr::String(ref dir) = *ast.car {
|
||||
let dirp = Path::new(dir);
|
||||
if let Err(s) = set_current_dir(dirp) {
|
||||
Err(start_trace(
|
||||
("cd", s.to_string())
|
||||
.into()))
|
||||
} else {
|
||||
if let Ok(abs) = canonicalize(dirp) {
|
||||
let dir: &String;
|
||||
match *ast.car {
|
||||
Ctr::String(ref d) => dir = d,
|
||||
Ctr::Symbol(ref d) => dir = d,
|
||||
Ctr::Seg(ref s) => {
|
||||
match eval(s, syms) {
|
||||
Ok(r) => {
|
||||
if r == ast.car {
|
||||
return Err(start_trace(("cd", "innapropriate input.").into()));
|
||||
}
|
||||
return cd_callback(&Seg::from_mono(r), syms);
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(e.with_trace(("cd", "couldnt evaluate input").into()));
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => return Err(start_trace(
|
||||
("cd", "expected input to be a string or symbol")
|
||||
.into()))
|
||||
}
|
||||
|
||||
let dirp = Path::new(dir);
|
||||
match canonicalize(dirp) {
|
||||
Ok(abs) => {
|
||||
if let Err(s) = set_current_dir(dirp) {
|
||||
Err(start_trace(
|
||||
("cd", s.to_string())
|
||||
.into()))
|
||||
} else {
|
||||
syms.insert(
|
||||
String::from("PWD"),
|
||||
Symbol::from_ast(
|
||||
&String::from("PWD"),
|
||||
&String::from("current working directory"),
|
||||
&String::from("current working directory, set by cd"),
|
||||
&Seg::from_mono(Box::new(
|
||||
Ctr::String(abs.to_string_lossy().into()))),
|
||||
None,
|
||||
));
|
||||
|
||||
// Run configurable user function
|
||||
|
||||
Ok(Ctr::None)
|
||||
} else {
|
||||
Err(start_trace(
|
||||
("cd", "cannot make absolute path").into()))
|
||||
match syms.call_symbol(
|
||||
&CD_USER_CB.to_string(),
|
||||
&Seg::new(),
|
||||
true,
|
||||
) {
|
||||
Ok(r) => {
|
||||
Ok(*r)
|
||||
},
|
||||
Err(s) => {
|
||||
Err(s.with_trace(("cd", "failed to call callback").into()))
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
Err(
|
||||
start_trace( ("cd", e.to_string()).into())
|
||||
.with_trace(("cd", "could not make absolute path").into()))
|
||||
}
|
||||
} else {
|
||||
Err(start_trace(
|
||||
("cd", "expected input to be a string")
|
||||
.into()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -948,11 +980,25 @@ pub fn load_posix_shell(syms: &mut SymTable, shell_state: Rc<RefCell<ShellState>
|
|||
"cd".to_string(),
|
||||
Symbol {
|
||||
name: String::from("cd"),
|
||||
args: Args::Strict(vec![Type::String]),
|
||||
conditional_branches: false,
|
||||
args: Args::Lazy(1),
|
||||
conditional_branches: true,
|
||||
docs: CD_DOCSTRING.to_string(),
|
||||
value: ValueType::Internal(Rc::new(cd_callback)),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
String::from(CD_USER_CB),
|
||||
Symbol {
|
||||
name: String::from(CD_USER_CB),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: String::from("lambda called at each invocation of cd"),
|
||||
value: ValueType::Internal(Rc::new(move |_ast: &Seg, _sym: &mut SymTable| -> Result<Ctr, Traceback> {
|
||||
Ok(Ctr::None)
|
||||
})),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue