diff --git a/Cargo.toml b/Cargo.toml index 15bdcef..787c8a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2024" [dependencies] arboard = "3.5.0" clap = { version = "4.5.37", features = ["derive", "env"] } +ctrlc = "3.4.6" hostname = "0.4.1" termion = "4.0.5" users = "0.11.0" diff --git a/src/builtins.rs b/src/builtins.rs index 2b5f305..c652a6f 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -8,7 +8,7 @@ pub const BUILTINS: [( &str, fn(args: Vec, unsplit_args: String, state: &mut super::State) -> i32, &str, -); 17] = [ +); 19] = [ ("cd", cd, "[dir]"), ("exit", exit, ""), ("echo", echo, "[-e] [text ...]"), @@ -25,7 +25,9 @@ pub const BUILTINS: [( ("setf", setf, "var [var ...]"), ("getf", getf, "var"), ("()", nop, ""), - ("if", _if, "condition ( statement ) [ ( else_statement )"), + ("if", _if, "condition (statement) [ (else_statement)"), + ("while", _while, "condition (statement)"), + ("gay", gay, "") ]; /// Change the directory @@ -113,6 +115,9 @@ pub fn help(_: Vec, _: String, _: &mut super::State) -> i32 { builtins.sort_by(|v1, v2| v1.0.cmp(v2.0)); for builtin in builtins { + if builtin.0 == "gay" { + continue; + } println!("{} {}", builtin.0, builtin.2); } 0 @@ -363,3 +368,39 @@ pub fn _if(args: Vec, _: String, state: &mut super::State) -> i32 { 0 } + +/// loop while a condition is true +pub fn _while(args: Vec, _: String, state: &mut super::State) -> i32 { + if args.len() < 3 { + println!( + "sesh: {0}: usage: {0} condition (statement)", + args[0] + ); + return 1; + } + + fn test(condition: String, state: &mut super::State) -> bool { + super::eval(&condition, state); + state.shell_env.reverse(); + let mut status = 0i32; + for var in &state.shell_env { + if var.name == "STATUS" { + status = var.value.parse().unwrap(); + } + } + state.shell_env.sort_by(|v1, v2| v1.name.cmp(&v2.name)); + status == 0 + } + + while test(args[1].clone(), state) { + super::eval(&args[2].clone(), state); + } + + 0 +} + +/// shh +pub fn gay(_: Vec, _: String, state: &mut super::State) -> i32 { + state.in_mode = true; + 0 +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ce2c1dd..fe8ed95 100644 --- a/src/main.rs +++ b/src/main.rs @@ -96,6 +96,10 @@ struct State { focus: Focus, /// Raw terminal. raw_term: Option>>>, + /// sh + in_mode: bool, + /// sh + entries: usize } unsafe impl Sync for State {} @@ -318,7 +322,7 @@ fn eval(statement: &str, state: &mut State) { state.shell_env.push(ShellVar { name: "STATUS".to_string(), - value: child.wait().unwrap().code().unwrap().to_string(), + value: child.wait().unwrap().code().unwrap_or(255i32).to_string(), }); if let Some(raw_term) = state.raw_term.clone() { let writer = raw_term.write().unwrap(); @@ -380,6 +384,18 @@ fn write_prompt(state: State) -> Result<(), Box> { .unwrap_or(OsStr::new("?")) .to_string_lossy(), ); + if state.in_mode { + let table = [ + "\x1b[31;1m", + "\x1b[33;1m", + "\x1b[32;1m", + "\x1b[34;1m", + "\x1b[36;1m", + "\x1b[35;1m" + ]; + let idx = state.entries.saturating_sub(1)%table.len(); + prompt += table[idx]; + } print!("{}", prompt); std::io::stdout().flush()?; @@ -410,6 +426,8 @@ fn main() -> Result<(), Box> { .unwrap_or(std::env::home_dir().unwrap_or(PathBuf::from("/"))), aliases: Vec::new(), raw_term: None, + in_mode: false, + entries: 0 }; state.shell_env.push(ShellVar { name: "PROMPT1".to_string(), @@ -434,6 +452,7 @@ fn main() -> Result<(), Box> { value: "true".to_string(), }); } + let _ = ctrlc::set_handler(|| println!()); let rc = std::fs::read(std::env::home_dir().unwrap().join(".seshrc")); if rc.is_err() { @@ -608,6 +627,7 @@ fn main() -> Result<(), Box> { history.push(input.clone().trim().to_string()); hist_ptr = history.len(); + state.entries += 1; eval(&input, &mut state); } }