This commit is contained in:
Arthur Beck 2025-05-02 21:04:13 -05:00
parent 98e3fb15db
commit bfa67385ef
Signed by: ArthurB
GPG key ID: CA200B389F0F6BC9
3 changed files with 59 additions and 15 deletions

View file

@ -1,17 +1,20 @@
//! builtins to sesh //! builtins to sesh
#![allow(clippy::type_complexity)] #![allow(clippy::type_complexity)]
use std::sync::{Arc, Mutex};
/// List of builtins /// List of builtins
pub const BUILTINS: [( pub const BUILTINS: [(
&str, &str,
fn(args: Vec<String>, unsplit_args: String, state: &mut super::State) -> i32, fn(args: Vec<String>, unsplit_args: String, state: &mut super::State) -> i32,
&str, &str,
); 5] = [ ); 6] = [
("cd", cd, "[dir]"), ("cd", cd, "[dir]"),
("exit", exit, ""), ("exit", exit, ""),
("echo", echo, "[-e] [text ...]"), ("echo", echo, "[-e] [text ...]"),
("alias", alias, "[name] [value]"), ("alias", alias, "[name] [value]"),
("help", help, ""), ("help", help, ""),
("source", eval, "filename [arguments]"),
]; ];
/// Change the directory /// Change the directory
@ -86,8 +89,51 @@ pub fn help(_: Vec<String>, _: String, _: &mut super::State) -> i32 {
println!("Use `man sesh` to find out more about the shell in general."); println!("Use `man sesh` to find out more about the shell in general.");
println!("Use `man -k' or `info' to find out more about commands not in this list."); println!("Use `man -k' or `info' to find out more about commands not in this list.");
println!(); println!();
for builtin in BUILTINS { let mut builtins = BUILTINS.clone();
builtins.sort_by(|v1, v2| v1.0.cmp(v2.0));
for builtin in builtins {
println!("{} {}", builtin.0, builtin.2); println!("{} {}", builtin.0, builtin.2);
} }
0 0
} }
/// Run a file.
pub fn eval(args: Vec<String>, _: String, state: &mut super::State) -> i32 {
if args.len() < 2 {
println!("sesh: {}: filename argument required", args[0]);
println!("sesh: {0}: usage: {0} filename [arguments]", args[0]);
return 1;
}
let file = std::fs::read(args[1].clone());
if file.is_err() {
println!(
"sesh: {}: error opening file: {}",
args[0],
file.unwrap_err()
);
return 2;
}
let file = String::from_utf8(file.unwrap());
if file.is_err() {
println!("sesh: {}: invalid UTF-8: {}", args[0], file.unwrap_err());
return 3;
}
let file = file.unwrap();
let mut state2 = state.clone();
let mut i = 0usize;
for arg in &args[1..] {
state2.shell_env.push(super::ShellVar {
name: format!("{}", i),
value: arg.clone(),
});
i += 1;
}
super::eval(&file, &mut state2);
0
}

View file

@ -38,14 +38,6 @@ struct ShellVar {
/// A lot of [ShellVar]s. /// A lot of [ShellVar]s.
type ShellVars = Vec<ShellVar>; type ShellVars = Vec<ShellVar>;
/// Whether a variable is local or not.
#[derive(Clone, Debug, PartialEq, Eq)]
enum VariableLocality {
/// A local variable.
Local,
/// A nonlocal variable.
Nonlocal,
}
/// A reference to a variable. /// A reference to a variable.
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
enum Variable { enum Variable {
@ -66,8 +58,6 @@ struct Alias {
/// The state of the shell /// The state of the shell
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct State { struct State {
/// Environment variables
env: Arc<Mutex<std::env::VarsOs>>,
/// Shell-local variables only accessible via builtins. /// Shell-local variables only accessible via builtins.
shell_env: ShellVars, shell_env: ShellVars,
/// The focused variable. /// The focused variable.
@ -170,11 +160,20 @@ fn split_statements(statement: &str) -> Vec<String> {
.concat() .concat()
} }
/// Substitute in shell variables
fn substitute_vars(statement: &str, state: State) -> String {
let mut out = statement.to_string();
for ShellVar { name, value } in state.shell_env {
out = out.replace(&("$".to_owned()+&name), &value);
}
out
}
#[allow(clippy::arc_with_non_send_sync)] #[allow(clippy::arc_with_non_send_sync)]
/// Evaluate a statement. May include multiple. /// Evaluate a statement. May include multiple.
fn eval(statement: &str, state: &mut State) { fn eval(statement: &str, state: &mut State) {
let statement = remove_comments(statement); let statement = remove_comments(statement);
let statements = split_statements(&statement); let statements = split_statements(&substitute_vars(&statement, state.clone()));
for statement in statements { for statement in statements {
let mut statement_split = split_statement(&statement); let mut statement_split = split_statement(&statement);
@ -236,7 +235,6 @@ fn eval(statement: &str, state: &mut State) {
} }
} }
state.env = Arc::new(Mutex::new(std::env::vars_os()));
let s = state.clone(); let s = state.clone();
state.history.push(s); state.history.push(s);
} }
@ -284,7 +282,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let options = Args::parse(); let options = Args::parse();
let mut state = State { let mut state = State {
env: Arc::new(Mutex::new(std::env::vars_os())),
shell_env: Vec::new(), shell_env: Vec::new(),
focus: Variable::Local(String::new()), focus: Variable::Local(String::new()),
history: Vec::new(), history: Vec::new(),

1
test.sesh Normal file
View file

@ -0,0 +1 @@
echo test $0 $1