From 5fedabd9f59d1d3825ee597d378d9f2fc20f210a Mon Sep 17 00:00:00 2001 From: Adil Hanney Date: Wed, 24 Dec 2025 21:07:26 +0000 Subject: [PATCH 1/5] feat: add `--working-directory` arg --- src/main.rs | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/main.rs b/src/main.rs index 33b717b..5c636a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,6 +36,7 @@ use std::{ fs, process, rc::Rc, sync::{LazyLock, Mutex, atomic::Ordering}, + path::PathBuf, }; use tokio::sync::mpsc; @@ -90,9 +91,11 @@ fn main() -> Result<(), Box> { let mut shell_program_opt = None; let mut shell_args = Vec::new(); let mut daemonize = true; + let mut working_directory = None; // Parse the arguments using clap_lex while let Some(arg) = raw_args.next_os(&mut cursor) { - match arg.to_str() { + let arg_str = arg.to_str(); + match arg_str { Some("--help") | Some("-h") => { print_help(); return Ok(()); @@ -104,6 +107,14 @@ fn main() -> Result<(), Box> { ); return Ok(()); } + Some("--working-directory") | Some("-w") => { + if let Some(dir_arg) = raw_args.next_os(&mut cursor) { + working_directory = Some(PathBuf::from(dir_arg)); + } else { + eprintln!("Missing argument for {}", arg_str.unwrap()); + process::exit(1); + } + } Some("--no-daemon") => { daemonize = false; } @@ -159,15 +170,16 @@ fn main() -> Result<(), Box> { } }; - let startup_options = if let Some(shell_program) = shell_program_opt { - let options = tty::Options { - shell: Some(tty::Shell::new(shell_program, shell_args)), - ..tty::Options::default() - }; - Some(options) + let shell = if let Some(shell_program) = shell_program_opt { + Some(tty::Shell::new(shell_program, shell_args)) } else { None }; + let startup_options = Some(tty::Options { + shell, + working_directory, + ..tty::Options::default() + }); // Terminal config setup let term_config = term::Config::default(); @@ -204,8 +216,9 @@ Designed for the COSMICâ„¢ desktop environment, cosmic-term is a libcosmic-based Project home page: https://github.com/pop-os/cosmic-term Options: - --help Show this message - --version Show the version of cosmic-term"# + --help Show this message + --version Show the version of cosmic-term + -w | --working-directory Set the working directory for the terminal"# ); } From 719c0c5aa3aab5281e5cc2cc520c579661aa9daf Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 15 Jan 2026 20:27:52 +0000 Subject: [PATCH 2/5] ref: avoid unwrap by using an intermediate variable Co-Authored-By: Adil Hanney --- src/main.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5c636a0..66cb7a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -94,8 +94,7 @@ fn main() -> Result<(), Box> { let mut working_directory = None; // Parse the arguments using clap_lex while let Some(arg) = raw_args.next_os(&mut cursor) { - let arg_str = arg.to_str(); - match arg_str { + match arg.to_str() { Some("--help") | Some("-h") => { print_help(); return Ok(()); @@ -107,11 +106,11 @@ fn main() -> Result<(), Box> { ); return Ok(()); } - Some("--working-directory") | Some("-w") => { + Some(arg_str @ "--working-directory") | Some(arg_str @ "-w") => { if let Some(dir_arg) = raw_args.next_os(&mut cursor) { working_directory = Some(PathBuf::from(dir_arg)); } else { - eprintln!("Missing argument for {}", arg_str.unwrap()); + eprintln!("Missing argument for {arg_str}"); process::exit(1); } } From 42ddc92370284fc7dce9fa44083b5862bf0a5161 Mon Sep 17 00:00:00 2001 From: Adil Hanney Date: Thu, 15 Jan 2026 20:35:05 +0000 Subject: [PATCH 3/5] tweak: match format of gnome-terminal and konsole's help message --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 66cb7a3..6aace5a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -217,7 +217,7 @@ Project home page: https://github.com/pop-os/cosmic-term Options: --help Show this message --version Show the version of cosmic-term - -w | --working-directory Set the working directory for the terminal"# + -w, --working-directory Set the working directory for the terminal"# ); } From 75cfa526730dddb361161e724fdc8e2db67208e3 Mon Sep 17 00:00:00 2001 From: Adil Hanney Date: Mon, 16 Feb 2026 23:32:19 +0000 Subject: [PATCH 4/5] fix: merge profile and startup options --- src/main.rs | 57 +++++++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/src/main.rs b/src/main.rs index db3aecf..6ed5806 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,10 +37,11 @@ use std::{ collections::{BTreeMap, BTreeSet, HashMap}, env, error::Error, - fs, process, + fs, + path::PathBuf, + process, rc::Rc, sync::{LazyLock, Mutex, atomic::Ordering}, - path::PathBuf, }; use tokio::sync::mpsc; @@ -1522,40 +1523,36 @@ impl App { Some(colors) => { let current_pane = self.pane_model.focused(); if let Some(tab_model) = self.pane_model.active_mut() { - // Use the startup options, profile options, or defaults - let (options, tab_title_override) = match self.startup_options.take() { - Some(options) => (options, None), - None => match profile_id_opt - .and_then(|profile_id| self.config.profiles.get(&profile_id)) - { - Some(profile) => { - let mut shell = None; + let mut options = self.startup_options.take().unwrap_or_default(); + let mut tab_title_override = None; + if let Some(profile) = profile_id_opt + .and_then(|profile_id| self.config.profiles.get(&profile_id)) + { + // Merge profile and startup options, preferring startup options + options = tty::Options { + shell: options.shell.or_else(|| { if let Some(mut args) = shlex::split(&profile.command) { if !args.is_empty() { let command = args.remove(0); - shell = Some(tty::Shell::new(command, args)); + return Some(tty::Shell::new(command, args)); } } - let working_directory = - (!profile.working_directory.is_empty()) - .then(|| profile.working_directory.clone().into()); + return None; + }), + working_directory: options.working_directory.or_else(|| { + (!profile.working_directory.is_empty()) + .then(|| profile.working_directory.clone().into()) + }), + drain_on_exit: options.drain_on_exit || profile.drain_on_exit, + ..options + }; + tab_title_override = if profile.tab_title.is_empty() { + None + } else { + Some(profile.tab_title.clone()) + }; + } - let options = tty::Options { - shell, - working_directory, - drain_on_exit: profile.drain_on_exit, - env: HashMap::new(), - }; - let tab_title_override = if profile.tab_title.is_empty() { - None - } else { - Some(profile.tab_title.clone()) - }; - (options, tab_title_override) - } - None => (Options::default(), None), - }, - }; let entity = tab_model .insert() .text( From 7848e64bab3dfcc800209151579421eb66b73d04 Mon Sep 17 00:00:00 2001 From: Adil Hanney Date: Mon, 16 Feb 2026 23:47:47 +0000 Subject: [PATCH 5/5] tweak: make options and tab_title_override not mut --- src/main.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6ed5806..5561da9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1523,14 +1523,13 @@ impl App { Some(colors) => { let current_pane = self.pane_model.focused(); if let Some(tab_model) = self.pane_model.active_mut() { - let mut options = self.startup_options.take().unwrap_or_default(); - let mut tab_title_override = None; - if let Some(profile) = profile_id_opt + let (options, tab_title_override) = if let Some(profile) = profile_id_opt .and_then(|profile_id| self.config.profiles.get(&profile_id)) { // Merge profile and startup options, preferring startup options - options = tty::Options { - shell: options.shell.or_else(|| { + let startup_options = self.startup_options.take().unwrap_or_default(); + let options = tty::Options { + shell: startup_options.shell.or_else(|| { if let Some(mut args) = shlex::split(&profile.command) { if !args.is_empty() { let command = args.remove(0); @@ -1539,19 +1538,22 @@ impl App { } return None; }), - working_directory: options.working_directory.or_else(|| { + working_directory: startup_options.working_directory.or_else(|| { (!profile.working_directory.is_empty()) .then(|| profile.working_directory.clone().into()) }), - drain_on_exit: options.drain_on_exit || profile.drain_on_exit, - ..options + drain_on_exit: startup_options.drain_on_exit || profile.drain_on_exit, + ..startup_options }; - tab_title_override = if profile.tab_title.is_empty() { + let tab_title_override = if profile.tab_title.is_empty() { None } else { Some(profile.tab_title.clone()) }; - } + (options, tab_title_override) + } else { + (self.startup_options.take().unwrap_or_default(), None) + }; let entity = tab_model .insert()