From 3ea67221ef973944c7cc21afcc1bd6685a41ace3 Mon Sep 17 00:00:00 2001 From: Josh Megnauth Date: Tue, 6 Aug 2024 02:22:09 -0400 Subject: [PATCH] Add option to toggle open in CWD to Profiles The option is enabled by default on Unix but settable per profile. Windows is currently unsupported and defaults to the old behavior. --- i18n/en/cosmic_term.ftl | 4 +- src/config.rs | 16 ++++++-- src/main.rs | 85 ++++++++++++++++++++++++----------------- 3 files changed, 64 insertions(+), 41 deletions(-) diff --git a/i18n/en/cosmic_term.ftl b/i18n/en/cosmic_term.ftl index 7bc3b55..bfe2322 100644 --- a/i18n/en/cosmic_term.ftl +++ b/i18n/en/cosmic_term.ftl @@ -26,6 +26,8 @@ make-default = Make default working-directory = Working directory hold = Hold remain-open = Remain open after child process exits. +open-in-cwd = Use parent CWD +open-in-cwd-description = Open new terminals using the focused tab's working directory. ## Settings settings = Settings @@ -60,8 +62,6 @@ focus-follow-mouse = Typing focus follows mouse advanced = Advanced show-headerbar = Show header show-header-description = Reveal the header from the right-click menu. -open-in-cwd = Use parent CWD -open-in-cwd-description = Start new terms using the focused tab's working directory. # Find find-placeholder = Find... diff --git a/src/config.rs b/src/config.rs index 0832dcd..0f62d59 100644 --- a/src/config.rs +++ b/src/config.rs @@ -198,6 +198,9 @@ pub struct Profile { pub tab_title: String, #[serde(default)] pub working_directory: String, + /// Open new terminal with the current working directory of the focused term + #[serde(default = "cwd_default")] + pub open_in_cwd: bool, #[serde(default)] pub hold: bool, } @@ -212,10 +215,20 @@ impl Default for Profile { tab_title: String::new(), working_directory: String::new(), hold: false, + open_in_cwd: cwd_default(), } } } +#[cfg(not(windows))] +const fn cwd_default() -> bool { + true +} +#[cfg(windows)] +const fn cwd_default() -> bool { + false +} + #[derive(Clone, CosmicConfigEntry, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct Config { pub app_theme: AppTheme, @@ -229,8 +242,6 @@ pub struct Config { pub font_stretch: u16, pub font_size_zoom_step_mul_100: u16, pub opacity: u8, - /// Open new terminal with the current working directory of the focused term - pub open_in_cwd: bool, pub profiles: BTreeMap, pub show_headerbar: bool, pub use_bright_bold: bool, @@ -255,7 +266,6 @@ impl Default for Config { font_stretch: Stretch::Normal.to_number(), font_weight: Weight::NORMAL.0, opacity: 100, - open_in_cwd: true, profiles: BTreeMap::new(), show_headerbar: true, syntax_theme_dark: COSMIC_THEME_DARK.to_string(), diff --git a/src/main.rs b/src/main.rs index 7b9cbd9..cfc0ad2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -331,11 +331,11 @@ pub enum Message { ProfileName(ProfileId, String), ProfileNew, ProfileOpen(ProfileId), + ProfileOpenInCWD(ProfileId, bool), ProfileRemove(ProfileId), ProfileSyntaxTheme(ProfileId, ColorSchemeKind, usize), ProfileTabTitle(ProfileId, String), SelectAll(Option), - SetOpenInCWD(bool), ShowAdvancedFontSettings(bool), ShowHeaderBar(bool), SyntaxTheme(ColorSchemeKind, usize), @@ -992,6 +992,13 @@ impl App { ]) .align_items(Alignment::Center) .padding([0, space_s]), + ) + .add( + widget::settings::item::builder(fl!("open-in-cwd")) + .description(fl!("open-in-cwd-description")) + .toggler(profile.open_in_cwd, move |open_in_cwd| { + Message::ProfileOpenInCWD(profile_id, open_in_cwd) + }), ); let padding = Padding { @@ -1197,17 +1204,11 @@ impl App { .toggler(self.config.focus_follow_mouse, Message::FocusFollowMouse), ); - let advanced_section = widget::settings::view_section(fl!("advanced")) - .add( - widget::settings::item::builder(fl!("show-headerbar")) - .description(fl!("show-header-description")) - .toggler(self.config.show_headerbar, Message::ShowHeaderBar), - ) - .add( - widget::settings::item::builder(fl!("open-in-cwd")) - .description(fl!("open-in-cwd-description")) - .toggler(self.config.open_in_cwd, Message::SetOpenInCWD), - ); + let advanced_section = widget::settings::view_section(fl!("advanced")).add( + widget::settings::item::builder(fl!("show-headerbar")) + .description(fl!("show-header-description")) + .toggler(self.config.show_headerbar, Message::ShowHeaderBar), + ); widget::settings::view_column(vec![ appearance_section.into(), @@ -1245,22 +1246,6 @@ impl App { Some(colors) => { let current_pane = self.pane_model.focus; if let Some(tab_model) = self.pane_model.active_mut() { - // Current working directory of the selected tab/terminal - #[cfg(not(windows))] - let cwd = self - .config - .open_in_cwd - .then(|| { - tab_model.active_data::>().and_then( - |terminal| { - terminal.lock().unwrap().current_working_directory() - }, - ) - }) - .flatten(); - #[cfg(windows)] - let cwd: Option = None; - // Use the profile options, startup options, or defaults let (options, tab_title_override) = match profile_id_opt .and_then(|profile_id| self.config.profiles.get(&profile_id)) @@ -1273,8 +1258,27 @@ impl App { shell = Some(tty::Shell::new(command, args)); } } - let working_directory = cwd + + #[cfg(not(windows))] + let working_directory = profile + .open_in_cwd + // Evaluate current working working directory based on + // selected tab/terminal + .then(|| { + tab_model.active_data::>().and_then( + |terminal| { + terminal + .lock() + .unwrap() + .current_working_directory() + }, + ) + }) + .flatten() .or_else(|| Some(profile.working_directory.clone().into())); + #[cfg(windows)] + let working_directory = (!profile.working_directory.is_empty()) + .then(|| profile.working_directory.clone().into()); let options = tty::Options { shell, @@ -1292,7 +1296,15 @@ impl App { None => { let mut options = self.startup_options.take().unwrap_or_default(); - options.working_directory = cwd; + #[cfg(not(windows))] + { + // Eval CWD since it's the default option + options.working_directory = tab_model + .active_data::>() + .and_then(|terminal| { + terminal.lock().unwrap().current_working_directory() + }); + } (options, None) } }; @@ -2161,6 +2173,13 @@ impl Application for App { Message::ProfileOpen(profile_id) => { return self.create_and_focus_new_terminal(self.pane_model.focus, Some(profile_id)); } + Message::ProfileOpenInCWD(profile_id, open_in_cwd) => { + #[cfg(not(windows))] + if let Some(profile) = self.config.profiles.get_mut(&profile_id) { + profile.open_in_cwd = open_in_cwd; + return self.save_profiles(); + } + } Message::ProfileRemove(profile_id) => { // Reset matching terminals to default profile for (_pane, tab_model) in self.pane_model.panes.iter() { @@ -2219,12 +2238,6 @@ impl Application for App { } return self.update_focus(); } - Message::SetOpenInCWD(open_in_cwd) => { - if open_in_cwd != self.config.open_in_cwd { - self.config.open_in_cwd = open_in_cwd; - return self.update_config(); - } - } Message::ShowHeaderBar(show_headerbar) => { if show_headerbar != self.config.show_headerbar { config_set!(show_headerbar, show_headerbar);