usability improvements to env and def

* env prints variables and functions in seperate columns
* run/stl seperation of concerns significantly better
* def doesnt store lists or lambdas in the environment
This commit is contained in:
Ava Apples Affine 2023-05-21 23:53:00 +00:00
parent 825854fd42
commit 6969ea63bc
7 changed files with 309 additions and 131 deletions

View file

@ -19,11 +19,13 @@ use {
relish::{
ast::{
eval, lex, run,
Ctr, Seg, SymTable,
load_defaults, load_environment
Ctr, Seg, SymTable, Symbol,
},
stdlib::{
static_stdlib, dynamic_stdlib
static_stdlib, dynamic_stdlib, load_defaults,
load_environment,
CONSOLE_XDIM_VNAME, CONSOLE_YDIM_VNAME, CFG_FILE_VNAME,
L_PROMPT_VNAME, R_PROMPT_VNAME, PROMPT_DELIM_VNAME,
},
aux::{ShellState, check_jobs},
},
@ -46,6 +48,7 @@ use {
nix::unistd,
nu_ansi_term::{Color, Style},
dirs::home_dir,
termion::terminal_size,
};
#[derive(Clone)]
@ -252,7 +255,7 @@ fn main() {
// this is a user shell. attempt to load configuration
{
// scope the below borrow of syms
let cfg_file = env::var("RELISH_CFG_FILE").unwrap_or(cfg_file_name);
let cfg_file = env::var(CFG_FILE_VNAME).unwrap_or(cfg_file_name);
run(cfg_file.clone(), &mut syms)
.unwrap_or_else(|err: String| eprintln!("failed to load script {}\n{}", cfg_file, err));
}
@ -284,8 +287,11 @@ fn main() {
.with_style(Style::new().italic().fg(Color::LightGray)),
)).with_validator(Box::new(DefaultValidator));
let mut xdimension: u16 = 0;
let mut ydimension: u16 = 0;
loop {
{
// update state
check_jobs(&mut prompt_ss.borrow_mut());
}
let readline_prompt = make_prompt(&mut syms);
@ -293,6 +299,11 @@ fn main() {
// realloc with each loop because syms can change
rl = rl.with_completer(Box::new(completer));
let user_doc = rl.read_line(&readline_prompt).unwrap();
// doing this update here prevents needing to update twice before dimensions take effect
(xdimension, ydimension) =
check_and_update_console_dimensions(&mut syms, xdimension, ydimension);
match user_doc {
Signal::Success(line) => {
println!(""); // add a new line before output gets printed
@ -320,19 +331,19 @@ fn main() {
fn make_prompt(syms: &mut SymTable) -> CustomPrompt {
let l_ctr = *syms
.call_symbol(&"CFG_RELISH_L_PROMPT".to_string(), &Seg::new(), true)
.call_symbol(&L_PROMPT_VNAME.to_string(), &Seg::new(), true)
.unwrap_or_else(|err: String| {
eprintln!("{}", err);
Box::new(Ctr::String("<prompt broken!>".to_string()))
});
let r_ctr = *syms
.call_symbol(&"CFG_RELISH_R_PROMPT".to_string(), &Seg::new(), true)
.call_symbol(&R_PROMPT_VNAME.to_string(), &Seg::new(), true)
.unwrap_or_else(|err: String| {
eprintln!("{}", err);
Box::new(Ctr::String("<prompt broken!>".to_string()))
});
let d_ctr = *syms
.call_symbol(&"CFG_RELISH_PROMPT_DELIMITER".to_string(), &Seg::new(), true)
.call_symbol(&PROMPT_DELIM_VNAME.to_string(), &Seg::new(), true)
.unwrap_or_else(|err: String| {
eprintln!("{}", err);
Box::new(Ctr::String("<prompt broken!>".to_string()))
@ -397,3 +408,47 @@ fn get_token_to_complete(line: &str, pos: usize) -> (String, bool, usize) {
return (res, is_str, start_idx)
}
/* It was considered that a SIGWINCH handler would be a more
* elegant solution to this. Such a solution would need to
* modify the current libc based approach to use a state-enclosing
* closure as a signal handler. As of May 2023 there is no clear
* way of doing such a thing.
*
* Luckily this data is only used within Relish, so we can simply
* rely on it only being read during the evaluation phase of the REPL.
* This method will at least work for that. (ava)
*/
fn check_and_update_console_dimensions(
syms: &mut SymTable,
last_xdim: u16,
last_ydim: u16
) -> (u16, u16) {
let (xdim, ydim) = terminal_size().expect("Couldnt get console dimensions");
if xdim != last_xdim {
syms.insert(
String::from(CONSOLE_XDIM_VNAME),
Symbol::from_ast(
&String::from(CONSOLE_XDIM_VNAME),
&String::from("Length of current console"),
&Seg::from_mono(Box::new(Ctr::Integer(xdim.into()))),
None,
)
);
}
if ydim != last_ydim {
syms.insert(
String::from(CONSOLE_YDIM_VNAME),
Symbol::from_ast(
&String::from(CONSOLE_YDIM_VNAME),
&String::from("Height of current console"),
&Seg::from_mono(Box::new(Ctr::Integer(ydim.into()))),
None,
)
);
}
(xdim, ydim)
}