Add help and some command line args

This commit is contained in:
Arthur Beck 2025-05-02 20:34:57 -05:00
parent fdfddec576
commit 98e3fb15db
Signed by: ArthurB
GPG key ID: CA200B389F0F6BC9
3 changed files with 77 additions and 2 deletions

View file

@ -3,6 +3,11 @@ use roff::{Roff, bold, italic, roman};
use std::{env, path::PathBuf};
fn main() {
println!(
"cargo:rustc-env=TARGET={}",
std::env::var("TARGET").unwrap()
);
let page = Roff::new()
.control("TH", ["SESH", "1"])
.control("SH", ["NAME"])

View file

@ -5,7 +5,14 @@
pub const BUILTINS: [(
&str,
fn(args: Vec<String>, unsplit_args: String, state: &mut super::State) -> i32,
); 4] = [("cd", cd), ("exit", exit), ("echo", echo), ("alias", alias)];
&str,
); 5] = [
("cd", cd, "[dir]"),
("exit", exit, ""),
("echo", echo, "[-e] [text ...]"),
("alias", alias, "[name] [value]"),
("help", help, ""),
];
/// Change the directory
pub fn cd(args: Vec<String>, _: String, state: &mut super::State) -> i32 {
@ -67,3 +74,20 @@ pub fn alias(args: Vec<String>, _: String, state: &mut super::State) -> i32 {
0
}
/// Output help on builtins.
pub fn help(_: Vec<String>, _: String, _: &mut super::State) -> i32 {
println!(
"sesh, version {} ({})",
env!("CARGO_PKG_VERSION"),
env!("TARGET")
);
println!("This provides a list of built-in shell commands.");
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!();
for builtin in BUILTINS {
println!("{} {}", builtin.0, builtin.2);
}
0
}

View file

@ -18,7 +18,14 @@ mod escapes;
/// sesh is a shell designed to be as semantic to use as possible
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {}
struct Args {
/// Run an expression. This will not open an interactive shell. Takes precedence over --before
#[arg(long="run", short='c', default_value_t=("".to_string()))]
run_expr: String,
/// Run an expression before opening an interactive shell.
#[arg(long="before", short='b', default_value_t=("".to_string()))]
run_before: String,
}
/// A single shell variable
#[derive(Clone, Debug, PartialEq, Eq)]
@ -274,6 +281,8 @@ fn write_prompt(state: State) -> Result<(), Box<dyn std::error::Error>> {
#[allow(clippy::arc_with_non_send_sync)]
fn main() -> Result<(), Box<dyn std::error::Error>> {
let options = Args::parse();
let mut state = State {
env: Arc::new(Mutex::new(std::env::vars_os())),
shell_env: Vec::new(),
@ -292,6 +301,43 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
value: "> ".to_string(),
});
let mut interactive = true;
if !options.run_expr.is_empty() {
interactive = false;
state.shell_env.push(ShellVar {
name: "INTERACTIVE".to_string(),
value: "false".to_string(),
});
} else {
state.shell_env.push(ShellVar {
name: "INTERACTIVE".to_string(),
value: "true".to_string(),
});
}
let rc = std::fs::read(std::env::home_dir().unwrap().join(".seshrc"));
if rc.is_err() {
println!("sesh: reading ~/.seshrc failed: {}", rc.unwrap_err());
println!("sesh: not running .seshrc")
} else {
let rc = String::from_utf8(rc.unwrap());
if rc.is_err() {
println!("sesh: reading ~/.seshrc failed: not valid UTF-8");
println!("sesh: not running .seshrc")
} else {
let rc = rc.unwrap();
eval(&rc, &mut state);
}
}
if !interactive {
eval(&options.run_expr, &mut state);
return Ok(());
} else if !options.run_before.is_empty() {
eval(&options.run_before, &mut state)
}
let ctrlc_cont = Arc::new(RwLock::new(false));
let cc2 = ctrlc_cont.clone();