environment stuff

This commit is contained in:
Arthur Beck 2025-05-04 10:49:40 -05:00
parent ed84cb33df
commit 4d73a9cd7f
Signed by: ArthurB
GPG key ID: CA200B389F0F6BC9
3 changed files with 70 additions and 4 deletions

3
.gitignore vendored
View file

@ -20,3 +20,6 @@ Cargo.lock
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# ignore files used for testing stuff like loadf
/test*

View file

@ -6,7 +6,7 @@ pub const BUILTINS: [(
&str,
fn(args: Vec<String>, unsplit_args: String, state: &mut super::State) -> i32,
&str,
); 8] = [
); 11] = [
("cd", cd, "[dir]"),
("exit", exit, ""),
("echo", echo, "[-e] [text ...]"),
@ -15,7 +15,9 @@ pub const BUILTINS: [(
("source", eval, "filename [arguments]"),
("loadf", loadf, "filename [...]"),
("splitf", splitf, "[character] [-e]"),
("set", set, "name=value [name=value ...]"),
("dumpvars", dumpvars, ""),
("unset", unset, "var [var ...]"),
];
/// Change the directory
@ -203,3 +205,51 @@ pub fn splitf(mut args: Vec<String>, _: String, state: &mut super::State) -> i32
0
}
/// Set variable(s)
pub fn set(args: Vec<String>, _: String, state: &mut super::State) -> i32 {
if args.len() < 2 {
println!("sesh: {}: at least one variable required", args[0]);
println!("sesh: {0}: usage: {0} name=value [name=value ...]", args[0]);
return 1;
}
for var in &args[1..] {
let split = var.split_once("=");
if split.is_none() {
println!("sesh: {}: var=name pairs required", args[0]);
println!("sesh: {0}: usage: {0} name=value [name=value ...]", args[0]);
return 2;
}
let (name, value) = split.unwrap();
state.shell_env.push(super::ShellVar {
name: name.to_string(),
value: value.to_string(),
});
}
0
}
/// Dump all variables.
pub fn dumpvars(_: Vec<String>, _: String, state: &mut super::State) -> i32 {
for super::ShellVar { name, value } in &state.shell_env {
println!("{}: \"{}\"", name, value);
}
0
}
/// Unset variable(s)
pub fn unset(args: Vec<String>, _: String, state: &mut super::State) -> i32 {
if args.len() < 2 {
println!("sesh: {}: at least one variable required", args[0]);
println!("sesh: {0}: usage: {0} name [name ...]", args[0]);
return 1;
}
for (i, ele) in state.shell_env.clone().into_iter().enumerate() {
if args[1..].contains(&ele.name) {
state.shell_env.remove(i);
}
}
0
}

View file

@ -169,7 +169,7 @@ fn split_lines(lines: &str) -> Vec<String> {
if ch == '\\' {
escape_line = true;
}
if i >= out.len() {
while i >= out.len() {
out.push(String::new());
}
out[i].push(ch);
@ -257,6 +257,9 @@ fn eval(statement: &str, state: &mut State) {
let writer = raw_term.write().unwrap();
let _ = writer.suspend_raw_mode();
}
for env in &state.shell_env {
unsafe { std::env::set_var(env.name.clone(), env.value.clone()); }
}
match std::process::Command::new(program_name.clone())
.args(&statement_split[1..])
.current_dir(state.working_dir.clone())
@ -280,7 +283,17 @@ fn eval(statement: &str, state: &mut State) {
continue;
}
Err(error) => {
println!("sesh: error spawning program: {}\x0D", error);
println!("sesh: error spawning program: {}", error);
for (i, var) in state.shell_env.clone().into_iter().enumerate() {
if var.name == "STATUS" {
state.shell_env.swap_remove(i);
}
}
state.shell_env.push(ShellVar {
name: "STATUS".to_string(),
value: "127".to_string(),
});
if let Some(raw_term) = state.raw_term.clone() {
let writer = raw_term.write().unwrap();
let _ = writer.activate_raw_mode();