diff --git a/src/cli.rs b/src/cli.rs index 691d5cb..62feacd 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -95,9 +95,10 @@ pub struct CliArgs { #[arg(short = 'f', long, value_parser = clap::value_parser!(u8).range(4..=15))] pub fps: Option, - /// Shell or program to launch. Defaults to $SHELL - #[arg()] - pub program: Option, + /// Shell or program to launch with optional arguments. Defaults to $SHELL. + /// Use -- to separate t-rec options from shell arguments (e.g., t-rec -- /bin/bash -l) + #[arg(trailing_var_arg = true, allow_hyphen_values = true)] + pub program: Vec, // --- Config-related args (not part of recording settings) --- /// Use a named profile from the config file diff --git a/src/main.rs b/src/main.rs index aad9206..53cdd99 100644 --- a/src/main.rs +++ b/src/main.rs @@ -89,14 +89,16 @@ fn main() -> Result<()> { let settings = resolve_profiled_settings(&args)?; - let program: String = { - if let Some(prog) = &args.program { - prog.to_string() - } else { - let default = DEFAULT_SHELL.to_owned(); - env::var("SHELL").unwrap_or(default) - } - }; + let (program, program_args): (String, Vec) = args + .program + .split_first() + .map(|(prog, rest)| (prog.clone(), rest.to_vec())) + .unwrap_or_else(|| { + ( + env::var("SHELL").unwrap_or_else(|_| DEFAULT_SHELL.to_owned()), + vec![], + ) + }); let (win_id, window_name) = current_win_id(&args)?; let mut api = setup()?; api.calibrate(win_id)?; @@ -137,7 +139,9 @@ fn main() -> Result<()> { }; thread::spawn(move || -> Result<()> { capture_thread(&rx, api, ctx) }) }; - let interact = thread::spawn(move || -> Result<()> { sub_shell_thread(&program).map(|_| ()) }); + let interact = thread::spawn(move || -> Result<()> { + sub_shell_thread(&program, &program_args).map(|_| ()) + }); clear_screen(); io::stdout().flush().unwrap(); diff --git a/src/utils.rs b/src/utils.rs index da81369..68de970 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -13,8 +13,12 @@ pub fn file_name_for(tc: &u128, ext: &str) -> String { /// starts the main program and keeps interacting with the user /// blocks until termination -pub fn sub_shell_thread + Clone>(program: T) -> Result { +pub fn sub_shell_thread + Clone, A: AsRef>( + program: T, + args: &[A], +) -> Result { Command::new(program.clone()) + .args(args) .spawn() .context(format!("failed to start {:?}", program.as_ref()))? .wait()