Big project dir refactor

* split into multi member workspace in preparation for a no_std core
* env and posix stuff neatly crammed into a seperate shell project
* some pokes at interactive-devel.f
* updated ci
* removed 'l' shortcut for 'load' and update docs
* remove out of date readme content
* updated tests
* more sensible cond implementation and extra tests
* substr stdlib function with tests

Signed-off-by: Ava Affine <ava@sunnypup.io>
This commit is contained in:
Ava Apples Affine 2024-07-10 13:22:28 -07:00
parent aa56570d7d
commit 6d2925984f
44 changed files with 967 additions and 779 deletions

View file

@ -1,227 +0,0 @@
/* Flesh: Flexible Shell
* Copyright (C) 2021 Ava Affine
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use crate::segment::{Ctr, Seg, Type};
use crate::run::{run_callback, RUN_DOCSTRING};
use crate::sym::{Args, SymTable, Symbol, ValueType};
use crate::error::Traceback;
use std::rc::Rc;
use std::cell::RefCell;
use std::env::vars;
#[cfg(feature = "posix")]
pub mod posix;
pub mod append;
pub mod boolean;
pub mod control;
pub mod decl;
pub mod math;
pub mod strings;
pub mod file;
pub const CONSOLE_XDIM_VNAME: &str = "_FLESH_WIDTH";
pub const CONSOLE_YDIM_VNAME: &str = "_FLESH_HEIGHT";
pub const POSIX_CFG_VNAME: &str = "CFG_FLESH_POSIX";
pub const MODENV_CFG_VNAME: &str = "CFG_FLESH_ENV";
pub const L_PROMPT_VNAME: &str = "CFG_FLESH_L_PROMPT";
pub const R_PROMPT_VNAME: &str = "CFG_FLESH_R_PROMPT";
pub const PROMPT_DELIM_VNAME: &str = "CFG_FLESH_PROMPT_DELIMITER";
pub const CFG_FILE_VNAME: &str = "FLESH_CFG_FILE";
pub const FLESH_DEFAULT_CONS_HEIGHT: i16 = 24;
pub const FLESH_DEFAULT_CONS_WIDTH: i16 = 80;
fn l_prompt_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, Traceback> {
Ok(Ctr::String(">".to_string()))
}
fn r_prompt_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, Traceback> {
Ok(Ctr::String(String::new()))
}
fn prompt_delimiter_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, Traceback> {
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
pub fn static_stdlib(syms: &mut SymTable) {
append::add_list_lib(syms);
strings::add_string_lib(syms);
decl::add_decl_lib_static(syms);
control::add_control_lib(syms);
boolean::add_bool_lib(syms);
math::add_math_lib(syms);
file::add_file_lib(syms);
syms.insert(
"call".to_string(),
Symbol {
name: String::from("call"),
args: Args::Strict(vec![Type::String]),
conditional_branches: false,
docs: RUN_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(run_callback)),
..Default::default()
}
);
}
/// dynamic_stdlib
/// takes configuration data and uses it to insert dynamic
/// callbacks with configuration into a symtable
#[cfg(feature="posix")]
pub fn dynamic_stdlib(syms: &mut SymTable, shell: Option<Rc<RefCell<posix::ShellState>>>) {
// get CFG_FLESH_ENV from syms
let env_cfg_user_form = syms
.call_symbol(&MODENV_CFG_VNAME.to_string(), &Seg::new(), true)
.unwrap_or_else(|_: Traceback| Box::new(Ctr::None))
.to_string()
.eq("true");
decl::add_decl_lib_dynamic(syms, env_cfg_user_form);
if let Some(shell_state) = shell {
let posix_cfg_user_form = syms
.call_symbol(&POSIX_CFG_VNAME.to_string(), &Seg::new(), true)
.unwrap_or_else(|_: Traceback| Box::new(Ctr::None))
.to_string()
.eq("true");
if posix_cfg_user_form {
posix::load_posix_shell(syms, shell_state);
}
}
}
#[cfg(not(feature="posix"))]
pub fn dynamic_stdlib(syms: &mut SymTable) {
decl::add_decl_lib_dynamic(syms, false);
}
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: true".to_string(),
value: ValueType::VarForm(Box::new(Ctr::Bool(true))),
..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(FLESH_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(FLESH_DEFAULT_CONS_HEIGHT.into())
)),
None,
)
);
}