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:
parent
825854fd42
commit
6969ea63bc
7 changed files with 309 additions and 131 deletions
|
|
@ -16,3 +16,5 @@ nix = "0.26.2"
|
|||
# string escaping in the lexer
|
||||
phf = { version = "0.11", default-features = false, features = ["macros"] }
|
||||
libc = "0.2.144"
|
||||
# used by main shell to update consol dimensions
|
||||
termion = "2.0.1"
|
||||
|
|
|
|||
10
Readme.org
10
Readme.org
|
|
@ -488,12 +488,18 @@ Note: this section will not show the status of each item unless you are viewing
|
|||
Note: this section only tracks the state of incomplete TODO items. Having everything on here would be cluttered.
|
||||
|
||||
** TODO alpha tasks
|
||||
- env prints without using columns
|
||||
- lambdas shouldn't hit the env
|
||||
- circuit should actually be ~(reduce (lambda (form state) (and state (bool form))) my-args)~
|
||||
- error display must improve at all costs
|
||||
- exit function (causes program to shut down and return code)
|
||||
- probably push the symtable inserts into functions in individual stl modules (like posix.rs does)
|
||||
- fix the links in the readme like the ones in shell.org
|
||||
|
||||
** TODO v1.0 tasks
|
||||
- Be able to use features to compile without env or posix stuff
|
||||
- add a new binary target that is a simple posix repl demo
|
||||
- I think you'll need to refactor userlib to hide set behind a conditional
|
||||
based on whether CFG_RELISH_POSIX is set or not
|
||||
- add a compilation task to CI
|
||||
- finish basic goals in file:snippets/interactive-devel.rls
|
||||
- Investigate has_next member function for &Seg and maybe simplify stdlib and probably also eval/sym
|
||||
- Rename to Flesh
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
18
src/lib.rs
18
src/lib.rs
|
|
@ -23,7 +23,7 @@ mod stl;
|
|||
mod sym;
|
||||
|
||||
pub mod ast {
|
||||
pub use crate::run::{run, load_defaults, load_environment};
|
||||
pub use crate::run::run;
|
||||
pub use crate::eval::eval;
|
||||
pub use crate::lex::lex;
|
||||
pub use crate::segment::{Ctr, Seg, Type};
|
||||
|
|
@ -31,7 +31,21 @@ pub mod ast {
|
|||
}
|
||||
|
||||
pub mod stdlib {
|
||||
pub use crate::stl::{dynamic_stdlib, static_stdlib};
|
||||
pub use crate::stl::{};
|
||||
pub use crate::stl::{
|
||||
dynamic_stdlib, static_stdlib,
|
||||
load_defaults, load_environment,
|
||||
CONSOLE_XDIM_VNAME,
|
||||
CONSOLE_YDIM_VNAME,
|
||||
POSIX_CFG_VNAME,
|
||||
MODENV_CFG_VNAME,
|
||||
L_PROMPT_VNAME,
|
||||
R_PROMPT_VNAME,
|
||||
PROMPT_DELIM_VNAME,
|
||||
CFG_FILE_VNAME,
|
||||
RELISH_DEFAULT_CONS_HEIGHT,
|
||||
RELISH_DEFAULT_CONS_WIDTH,
|
||||
};
|
||||
}
|
||||
|
||||
pub mod aux {
|
||||
|
|
|
|||
108
src/run.rs
108
src/run.rs
|
|
@ -18,24 +18,11 @@
|
|||
use crate::eval::eval;
|
||||
use crate::lex::lex;
|
||||
use crate::segment::{Ctr, Seg};
|
||||
use crate::sym::{Args, SymTable, Symbol, ValueType};
|
||||
use std::path::{Path};
|
||||
use crate::sym::SymTable;
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
use std::iter::FromIterator;
|
||||
use std::env::{vars, var, current_dir};
|
||||
use std::rc::Rc;
|
||||
|
||||
fn l_prompt_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
|
||||
Ok(Ctr::String(">".to_string()))
|
||||
}
|
||||
|
||||
fn r_prompt_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
|
||||
Ok(Ctr::String(String::new()))
|
||||
}
|
||||
|
||||
fn prompt_delimiter_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
|
||||
Ok(Ctr::String("λ ".to_string()))
|
||||
}
|
||||
use std::env::{var, current_dir};
|
||||
|
||||
fn get_paths() -> Vec<String> {
|
||||
Vec::from_iter(var("PATH")
|
||||
|
|
@ -44,95 +31,6 @@ fn get_paths() -> Vec<String> {
|
|||
.map(String::from))
|
||||
}
|
||||
|
||||
pub fn load_defaults(syms: &mut SymTable) {
|
||||
syms.insert(
|
||||
"CFG_RELISH_POSIX".to_string(),
|
||||
Symbol {
|
||||
name: String::from("CFG_RELISH_POSIX"),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: "variable holding whether or not POSIX job control functions are to be loaded.
|
||||
checked at shell startup by configuration daemon. not used afterwards.
|
||||
|
||||
default value: false".to_string(),
|
||||
value: ValueType::VarForm(Box::new(Ctr::Bool(false))),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
"CFG_RELISH_ENV".to_string(),
|
||||
Symbol {
|
||||
name: String::from("CFG_RELISH_ENV"),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: "variable holding whether or not vars and other symbols should be linked to process environment variables.
|
||||
If set/defined all calls to def will result in additions or subtractions from user environment variables.
|
||||
checked at shell startup by configuration daemon. not used afterwards.
|
||||
|
||||
default value: 1 (set)
|
||||
".to_string(),
|
||||
value: ValueType::VarForm(Box::new(Ctr::Bool(true))),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
"CFG_RELISH_L_PROMPT".to_string(),
|
||||
Symbol {
|
||||
name: String::from("default relish left prompt"),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: "function called to output prompt on left hand. this function is called with no arguments."
|
||||
.to_string(),
|
||||
value: ValueType::Internal(Rc::new(l_prompt_default_callback)),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
"CFG_RELISH_R_PROMPT".to_string(),
|
||||
Symbol {
|
||||
name: String::from("default relish right prompt"),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: "function called to output prompt on right hand. this function is called with no arguments."
|
||||
.to_string(),
|
||||
value: ValueType::Internal(Rc::new(r_prompt_default_callback)),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
"CFG_RELISH_PROMPT_DELIMITER".to_string(),
|
||||
Symbol {
|
||||
name: String::from("default relish prompt delimiter"),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: "function called to output prompt delimiter. this function is called with no arguments."
|
||||
.to_string(),
|
||||
value: ValueType::Internal(Rc::new(prompt_delimiter_default_callback)),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn load_environment(syms: &mut SymTable) {
|
||||
for (key, value) in vars() {
|
||||
syms.insert(
|
||||
key.clone(),
|
||||
Symbol{
|
||||
name: key,
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: String::from("from env vars at time of load"),
|
||||
value: ValueType::VarForm(Box::new(Ctr::String(value))),
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_on_path(filename: String) -> Option<String> {
|
||||
let mut prefixes = get_paths();
|
||||
if let Ok(s) = current_dir() {
|
||||
|
|
|
|||
143
src/stl.rs
143
src/stl.rs
|
|
@ -20,6 +20,7 @@ use crate::run::{run_callback, RUN_DOCSTRING};
|
|||
use crate::sym::{Args, SymTable, Symbol, ValueType};
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::env::vars;
|
||||
|
||||
pub mod posix;
|
||||
pub mod append;
|
||||
|
|
@ -29,6 +30,29 @@ pub mod decl;
|
|||
pub mod math;
|
||||
pub mod strings;
|
||||
|
||||
pub const CONSOLE_XDIM_VNAME: &str = "_RELISH_WIDTH";
|
||||
pub const CONSOLE_YDIM_VNAME: &str = "_RELISH_HEIGHT";
|
||||
pub const POSIX_CFG_VNAME: &str = "CFG_RELISH_POSIX";
|
||||
pub const MODENV_CFG_VNAME: &str = "CFG_RELISH_ENV";
|
||||
pub const L_PROMPT_VNAME: &str = "CFG_RELISH_L_PROMPT";
|
||||
pub const R_PROMPT_VNAME: &str = "CFG_RELISH_R_PROMPT";
|
||||
pub const PROMPT_DELIM_VNAME: &str = "CFG_RELISH_PROMPT_DELIMITER";
|
||||
pub const CFG_FILE_VNAME: &str = "RELISH_CFG_FILE";
|
||||
pub const RELISH_DEFAULT_CONS_HEIGHT: i16 = 24;
|
||||
pub const RELISH_DEFAULT_CONS_WIDTH: i16 = 80;
|
||||
|
||||
fn l_prompt_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
|
||||
Ok(Ctr::String(">".to_string()))
|
||||
}
|
||||
|
||||
fn r_prompt_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
|
||||
Ok(Ctr::String(String::new()))
|
||||
}
|
||||
|
||||
fn prompt_delimiter_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
|
||||
Ok(Ctr::String("λ ".to_string()))
|
||||
}
|
||||
|
||||
/// static_stdlib
|
||||
/// inserts all stdlib functions that can be inserted without
|
||||
/// any kind of further configuration data into a symtable
|
||||
|
|
@ -618,11 +642,12 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> {
|
|||
pub fn dynamic_stdlib(syms: &mut SymTable, shell: Option<Rc<RefCell<posix::ShellState>>>) -> Result<(), String> {
|
||||
//get CFG_RELISH_ENV from syms
|
||||
let env_cfg_user_form = syms
|
||||
.call_symbol(&"CFG_RELISH_ENV".to_string(), &Seg::new(), true)
|
||||
.call_symbol(&MODENV_CFG_VNAME.to_string(), &Seg::new(), true)
|
||||
.unwrap_or_else(|_: String| Box::new(Ctr::None))
|
||||
.to_string()
|
||||
.eq("true");
|
||||
|
||||
// this also depends on the value of CFG_RELISH_ENV
|
||||
syms.insert(
|
||||
"def".to_string(),
|
||||
Symbol {
|
||||
|
|
@ -639,9 +664,10 @@ pub fn dynamic_stdlib(syms: &mut SymTable, shell: Option<Rc<RefCell<posix::Shell
|
|||
},
|
||||
);
|
||||
|
||||
// This should be replaced by actual compiler conditionals in the future
|
||||
if let Some(shell_state) = shell {
|
||||
let posix_cfg_user_form = syms
|
||||
.call_symbol(&"CFG_RELISH_POSIX".to_string(), &Seg::new(), true)
|
||||
.call_symbol(&POSIX_CFG_VNAME.to_string(), &Seg::new(), true)
|
||||
.unwrap_or_else(|_: String| Box::new(Ctr::None))
|
||||
.to_string()
|
||||
.eq("true");
|
||||
|
|
@ -664,3 +690,116 @@ pub fn dynamic_stdlib(syms: &mut SymTable, shell: Option<Rc<RefCell<posix::Shell
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_environment(syms: &mut SymTable) {
|
||||
for (key, value) in vars() {
|
||||
syms.insert(
|
||||
key.clone(),
|
||||
Symbol{
|
||||
name: key,
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: String::from("from env vars at time of load"),
|
||||
value: ValueType::VarForm(Box::new(Ctr::String(value))),
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_defaults(syms: &mut SymTable) {
|
||||
syms.insert(
|
||||
POSIX_CFG_VNAME.to_string(),
|
||||
Symbol {
|
||||
name: String::from(POSIX_CFG_VNAME),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: "variable holding whether or not POSIX job control functions are to be loaded.
|
||||
checked at shell startup by configuration daemon. not used afterwards.
|
||||
|
||||
default value: false".to_string(),
|
||||
value: ValueType::VarForm(Box::new(Ctr::Bool(false))),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
MODENV_CFG_VNAME.to_string(),
|
||||
Symbol {
|
||||
name: String::from(MODENV_CFG_VNAME),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: "variable holding whether or not vars and other symbols should be linked to process environment variables.
|
||||
If set/defined all calls to def will result in additions or subtractions from user environment variables.
|
||||
checked at shell startup by configuration daemon. not used afterwards.
|
||||
|
||||
default value: 1 (set)
|
||||
".to_string(),
|
||||
value: ValueType::VarForm(Box::new(Ctr::Bool(true))),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
L_PROMPT_VNAME.to_string(),
|
||||
Symbol {
|
||||
name: String::from(L_PROMPT_VNAME),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: "function called to output prompt on left hand. this function is called with no arguments."
|
||||
.to_string(),
|
||||
value: ValueType::Internal(Rc::new(l_prompt_default_callback)),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
R_PROMPT_VNAME.to_string(),
|
||||
Symbol {
|
||||
name: String::from(R_PROMPT_VNAME),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: "function called to output prompt on right hand. this function is called with no arguments."
|
||||
.to_string(),
|
||||
value: ValueType::Internal(Rc::new(r_prompt_default_callback)),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
PROMPT_DELIM_VNAME.to_string(),
|
||||
Symbol {
|
||||
name: String::from(PROMPT_DELIM_VNAME),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
docs: "function called to output prompt delimiter. this function is called with no arguments."
|
||||
.to_string(),
|
||||
value: ValueType::Internal(Rc::new(prompt_delimiter_default_callback)),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
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(RELISH_DEFAULT_CONS_WIDTH.into())
|
||||
)),
|
||||
None,
|
||||
)
|
||||
);
|
||||
|
||||
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(RELISH_DEFAULT_CONS_HEIGHT.into())
|
||||
)),
|
||||
None,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@
|
|||
*/
|
||||
|
||||
use crate::eval::eval;
|
||||
use crate::segment::{Ctr, Seg};
|
||||
use crate::segment::{Ctr, Seg, Type};
|
||||
use crate::stdlib::{CONSOLE_XDIM_VNAME, RELISH_DEFAULT_CONS_WIDTH};
|
||||
use crate::sym::{SymTable, Symbol, UserFn, ValueType};
|
||||
use std::env;
|
||||
|
||||
|
|
@ -129,19 +130,76 @@ pub const ENV_DOCSTRING: &str = "takes no arguments
|
|||
prints out all available symbols and their associated values";
|
||||
|
||||
pub fn env_callback(_ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
||||
// get width of current output
|
||||
let xdim: i128;
|
||||
if let Ctr::Integer(dim) = *syms
|
||||
.call_symbol(&CONSOLE_XDIM_VNAME.to_string(), &Seg::new(), true)
|
||||
.unwrap_or_else(|_: String| Box::new(Ctr::None)) {
|
||||
xdim = dim;
|
||||
} else {
|
||||
println!("{} contains non integer value, defaulting to {}",
|
||||
CONSOLE_XDIM_VNAME, RELISH_DEFAULT_CONS_WIDTH);
|
||||
xdim = RELISH_DEFAULT_CONS_WIDTH as i128;
|
||||
}
|
||||
|
||||
let mut v_col_len = 0;
|
||||
let mut f_col_len = 0;
|
||||
let mut functions = vec![];
|
||||
println!("VARIABLES:");
|
||||
let mut variables = vec![];
|
||||
for (name, val) in syms.iter() {
|
||||
match val.value {
|
||||
ValueType::VarForm(_) => {
|
||||
println!(" {}: {}", &name, val.value);
|
||||
if let ValueType::VarForm(l) = &val.value {
|
||||
let token: String;
|
||||
match l.to_type() {
|
||||
Type::Lambda => token = format!("{}: <lambda>", name),
|
||||
Type::Seg => token = format!("{}: <form>", name),
|
||||
_ => token = format!("{}: {}", name, val.value.to_string()),
|
||||
}
|
||||
_ => functions.push(name.clone()),
|
||||
|
||||
if token.len() > v_col_len && token.len() < xdim as usize {
|
||||
v_col_len = token.len();
|
||||
}
|
||||
|
||||
variables.push(token);
|
||||
} else {
|
||||
if f_col_len < name.len() && name.len() < xdim as usize {
|
||||
f_col_len = name.len();
|
||||
}
|
||||
functions.push(name.clone());
|
||||
}
|
||||
}
|
||||
println!("FUNCTIONS:");
|
||||
|
||||
let mut n_v_cols = xdim / v_col_len as i128;
|
||||
// now decrement to make sure theres room for two spaces of padding
|
||||
while n_v_cols > 1 && xdim % (v_col_len as i128) < (2 * n_v_cols) {
|
||||
n_v_cols -= 1;
|
||||
}
|
||||
// again for functions
|
||||
let mut n_f_cols = xdim / f_col_len as i128;
|
||||
while n_f_cols > 1 && xdim & (f_col_len as i128) < (2 * n_f_cols) {
|
||||
n_f_cols -= 1;
|
||||
}
|
||||
|
||||
let mut col_iter = 0;
|
||||
println!("VARIABLES:");
|
||||
for var in variables {
|
||||
print!("{:v_col_len$}", var);
|
||||
col_iter += 1;
|
||||
if col_iter % n_v_cols == 0 {
|
||||
print!("\n");
|
||||
} else {
|
||||
print!(" ");
|
||||
}
|
||||
}
|
||||
println!("\nFUNCTIONS:");
|
||||
col_iter = 0;
|
||||
for func in functions {
|
||||
println!(" {}", func);
|
||||
print!("{:f_col_len$}", func);
|
||||
col_iter += 1;
|
||||
if col_iter % n_f_cols == 0 {
|
||||
print!("\n");
|
||||
} else {
|
||||
print!(" ");
|
||||
}
|
||||
}
|
||||
Ok(Ctr::None)
|
||||
}
|
||||
|
|
@ -335,7 +393,7 @@ pub fn store_callback(ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Result<C
|
|||
var_val_form = &outer_scope_val;
|
||||
},
|
||||
_ if !is_var => return Err("arg list must at least be a list".to_string()),
|
||||
_ => unimplemented!(), // rustc is haunted
|
||||
_ => unimplemented!(), // rustc is haunted and cursed
|
||||
}
|
||||
|
||||
if is_var {
|
||||
|
|
@ -353,12 +411,18 @@ pub fn store_callback(ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Result<C
|
|||
Symbol::from_ast(&name, &docs, &outer_seg, None),
|
||||
);
|
||||
if env_cfg {
|
||||
match var_val.to_type() {
|
||||
Type::Lambda => {},
|
||||
Type::Seg => {},
|
||||
_ => {
|
||||
let mut s = var_val.to_string();
|
||||
if let Ctr::String(tok) = var_val {
|
||||
s = tok;
|
||||
}
|
||||
env::set_var(name.clone(), s);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ok(Ctr::None)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue