New tab opens on current directory
This patch add a new feature, now tab behavior now inherits the active tab’s current directory on Linux controlled by a settings toggle, and default is off
This commit is contained in:
parent
7ce2974273
commit
75714dedee
4 changed files with 81 additions and 15 deletions
|
|
@ -63,6 +63,8 @@ focus-follow-mouse = Typing focus follows mouse
|
||||||
advanced = Advanced
|
advanced = Advanced
|
||||||
show-headerbar = Show header
|
show-headerbar = Show header
|
||||||
show-header-description = Reveal the header from the right-click menu
|
show-header-description = Reveal the header from the right-click menu
|
||||||
|
tab-new-inherit-working-directory = New tabs use current directory
|
||||||
|
tab-new-inherit-working-directory-description = Open new tabs in the active tab's working directory
|
||||||
|
|
||||||
### Keyboard shortcuts
|
### Keyboard shortcuts
|
||||||
add-another-keybinding = Add another keybinding
|
add-another-keybinding = Add another keybinding
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,8 @@ pub struct Config {
|
||||||
pub syntax_theme_dark: String,
|
pub syntax_theme_dark: String,
|
||||||
pub syntax_theme_light: String,
|
pub syntax_theme_light: String,
|
||||||
pub focus_follow_mouse: bool,
|
pub focus_follow_mouse: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
pub tab_new_inherit_working_directory: bool,
|
||||||
pub default_profile: Option<ProfileId>,
|
pub default_profile: Option<ProfileId>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub shortcuts_custom: Shortcuts,
|
pub shortcuts_custom: Shortcuts,
|
||||||
|
|
@ -249,6 +251,7 @@ impl Default for Config {
|
||||||
color_schemes_light: BTreeMap::new(),
|
color_schemes_light: BTreeMap::new(),
|
||||||
dim_font_weight: Weight::NORMAL.0,
|
dim_font_weight: Weight::NORMAL.0,
|
||||||
focus_follow_mouse: false,
|
focus_follow_mouse: false,
|
||||||
|
tab_new_inherit_working_directory: false,
|
||||||
font_name: "Noto Sans Mono".to_string(),
|
font_name: "Noto Sans Mono".to_string(),
|
||||||
font_size: 14,
|
font_size: 14,
|
||||||
font_size_zoom_step_mul_100: 100,
|
font_size_zoom_step_mul_100: 100,
|
||||||
|
|
|
||||||
70
src/main.rs
70
src/main.rs
|
|
@ -431,6 +431,7 @@ pub enum Message {
|
||||||
ShowHeaderBar(bool),
|
ShowHeaderBar(bool),
|
||||||
SyntaxTheme(ColorSchemeKind, usize),
|
SyntaxTheme(ColorSchemeKind, usize),
|
||||||
SystemThemeChange,
|
SystemThemeChange,
|
||||||
|
TabNewInheritWorkingDirectory(bool),
|
||||||
TabActivate(segmented_button::Entity),
|
TabActivate(segmented_button::Entity),
|
||||||
TabActivateJump(usize),
|
TabActivateJump(usize),
|
||||||
TabClose(Option<segmented_button::Entity>),
|
TabClose(Option<segmented_button::Entity>),
|
||||||
|
|
@ -1483,11 +1484,21 @@ impl App {
|
||||||
.toggler(self.config.focus_follow_mouse, Message::FocusFollowMouse),
|
.toggler(self.config.focus_follow_mouse, Message::FocusFollowMouse),
|
||||||
);
|
);
|
||||||
|
|
||||||
let advanced_section = widget::settings::section().title(fl!("advanced")).add(
|
let advanced_section = widget::settings::section()
|
||||||
widget::settings::item::builder(fl!("show-headerbar"))
|
.title(fl!("advanced"))
|
||||||
.description(fl!("show-header-description"))
|
.add(
|
||||||
.toggler(self.config.show_headerbar, Message::ShowHeaderBar),
|
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!("tab-new-inherit-working-directory"))
|
||||||
|
.description(fl!("tab-new-inherit-working-directory-description"))
|
||||||
|
.toggler(
|
||||||
|
self.config.tab_new_inherit_working_directory,
|
||||||
|
Message::TabNewInheritWorkingDirectory,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
widget::settings::view_column(vec![
|
widget::settings::view_column(vec![
|
||||||
appearance_section.into(),
|
appearance_section.into(),
|
||||||
|
|
@ -1501,11 +1512,23 @@ impl App {
|
||||||
self.config.default_profile
|
self.config.default_profile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn active_terminal_working_directory(&self) -> Option<PathBuf> {
|
||||||
|
let tab_model = self.pane_model.active()?;
|
||||||
|
let entity = tab_model.active();
|
||||||
|
let terminal = tab_model.data::<Mutex<Terminal>>(entity)?;
|
||||||
|
let terminal = terminal.lock().unwrap();
|
||||||
|
terminal.working_directory()
|
||||||
|
}
|
||||||
|
|
||||||
fn create_and_focus_new_terminal(
|
fn create_and_focus_new_terminal(
|
||||||
&mut self,
|
&mut self,
|
||||||
pane: pane_grid::Pane,
|
pane: pane_grid::Pane,
|
||||||
profile_id_opt: Option<ProfileId>,
|
profile_id_opt: Option<ProfileId>,
|
||||||
|
inherit_working_directory: bool,
|
||||||
) -> Task<Message> {
|
) -> Task<Message> {
|
||||||
|
let inherited_working_directory = inherit_working_directory
|
||||||
|
.then(|| self.active_terminal_working_directory())
|
||||||
|
.flatten();
|
||||||
self.pane_model.set_focus(pane);
|
self.pane_model.set_focus(pane);
|
||||||
match &self.term_event_tx_opt {
|
match &self.term_event_tx_opt {
|
||||||
Some(term_event_tx) => {
|
Some(term_event_tx) => {
|
||||||
|
|
@ -1542,12 +1565,13 @@ impl App {
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}),
|
}),
|
||||||
working_directory: startup_options.working_directory.or_else(
|
working_directory: startup_options
|
||||||
|| {
|
.working_directory
|
||||||
|
.or_else(|| inherited_working_directory.clone())
|
||||||
|
.or_else(|| {
|
||||||
(!profile.working_directory.is_empty())
|
(!profile.working_directory.is_empty())
|
||||||
.then(|| profile.working_directory.clone().into())
|
.then(|| profile.working_directory.clone().into())
|
||||||
},
|
}),
|
||||||
),
|
|
||||||
drain_on_exit: startup_options.drain_on_exit
|
drain_on_exit: startup_options.drain_on_exit
|
||||||
|| profile.drain_on_exit,
|
|| profile.drain_on_exit,
|
||||||
..startup_options
|
..startup_options
|
||||||
|
|
@ -1559,7 +1583,11 @@ impl App {
|
||||||
};
|
};
|
||||||
(options, tab_title_override)
|
(options, tab_title_override)
|
||||||
} else {
|
} else {
|
||||||
(self.startup_options.take().unwrap_or_default(), None)
|
let mut options = self.startup_options.take().unwrap_or_default();
|
||||||
|
if options.working_directory.is_none() {
|
||||||
|
options.working_directory = inherited_working_directory.clone();
|
||||||
|
}
|
||||||
|
(options, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
let entity = tab_model
|
let entity = tab_model
|
||||||
|
|
@ -2541,7 +2569,7 @@ impl Application for App {
|
||||||
if let Some((pane, _)) = result {
|
if let Some((pane, _)) = result {
|
||||||
self.terminal_ids.insert(pane, widget::Id::unique());
|
self.terminal_ids.insert(pane, widget::Id::unique());
|
||||||
let command =
|
let command =
|
||||||
self.create_and_focus_new_terminal(pane, self.get_default_profile());
|
self.create_and_focus_new_terminal(pane, self.get_default_profile(), false);
|
||||||
self.pane_model.panes_created += 1;
|
self.pane_model.panes_created += 1;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
@ -2653,8 +2681,11 @@ impl Application for App {
|
||||||
return self.save_profiles();
|
return self.save_profiles();
|
||||||
}
|
}
|
||||||
Message::ProfileOpen(profile_id) => {
|
Message::ProfileOpen(profile_id) => {
|
||||||
return self
|
return self.create_and_focus_new_terminal(
|
||||||
.create_and_focus_new_terminal(self.pane_model.focused(), Some(profile_id));
|
self.pane_model.focused(),
|
||||||
|
Some(profile_id),
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Message::ProfileRemove(profile_id) => {
|
Message::ProfileRemove(profile_id) => {
|
||||||
// Reset matching terminals to default profile
|
// Reset matching terminals to default profile
|
||||||
|
|
@ -2720,6 +2751,12 @@ impl Application for App {
|
||||||
return self.update_config();
|
return self.update_config();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Message::TabNewInheritWorkingDirectory(tab_new_inherit_working_directory) => {
|
||||||
|
config_set!(
|
||||||
|
tab_new_inherit_working_directory,
|
||||||
|
tab_new_inherit_working_directory
|
||||||
|
);
|
||||||
|
}
|
||||||
Message::UseBrightBold(use_bright_bold) => {
|
Message::UseBrightBold(use_bright_bold) => {
|
||||||
if use_bright_bold != self.config.use_bright_bold {
|
if use_bright_bold != self.config.use_bright_bold {
|
||||||
config_set!(use_bright_bold, use_bright_bold);
|
config_set!(use_bright_bold, use_bright_bold);
|
||||||
|
|
@ -2863,10 +2900,15 @@ impl Application for App {
|
||||||
return self.create_and_focus_new_terminal(
|
return self.create_and_focus_new_terminal(
|
||||||
self.pane_model.focused(),
|
self.pane_model.focused(),
|
||||||
self.get_default_profile(),
|
self.get_default_profile(),
|
||||||
|
self.config.tab_new_inherit_working_directory,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Message::TabNewNoProfile => {
|
Message::TabNewNoProfile => {
|
||||||
return self.create_and_focus_new_terminal(self.pane_model.focused(), None);
|
return self.create_and_focus_new_terminal(
|
||||||
|
self.pane_model.focused(),
|
||||||
|
None,
|
||||||
|
self.config.tab_new_inherit_working_directory,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Message::TabNext => {
|
Message::TabNext => {
|
||||||
if let Some(tab_model) = self.pane_model.active() {
|
if let Some(tab_model) = self.pane_model.active() {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ use indexmap::IndexSet;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io, mem,
|
fs, io, mem,
|
||||||
|
path::PathBuf,
|
||||||
sync::{
|
sync::{
|
||||||
Arc, Mutex, Weak,
|
Arc, Mutex, Weak,
|
||||||
atomic::{AtomicU32, Ordering},
|
atomic::{AtomicU32, Ordering},
|
||||||
|
|
@ -257,6 +258,7 @@ pub struct Terminal {
|
||||||
notifier: Notifier,
|
notifier: Notifier,
|
||||||
search_regex_opt: Option<RegexSearch>,
|
search_regex_opt: Option<RegexSearch>,
|
||||||
search_value: String,
|
search_value: String,
|
||||||
|
shell_pid: Option<u32>,
|
||||||
size: Size,
|
size: Size,
|
||||||
use_bright_bold: bool,
|
use_bright_bold: bool,
|
||||||
zoom_adj: i8,
|
zoom_adj: i8,
|
||||||
|
|
@ -328,6 +330,10 @@ impl Terminal {
|
||||||
|
|
||||||
let window_id = 0;
|
let window_id = 0;
|
||||||
let pty = tty::new(&options, size.into(), window_id)?;
|
let pty = tty::new(&options, size.into(), window_id)?;
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
let shell_pid = Some(pty.child().id());
|
||||||
|
#[cfg(windows)]
|
||||||
|
let shell_pid = pty.child_watcher().pid().map(|pid| pid.get());
|
||||||
|
|
||||||
let pty_event_loop =
|
let pty_event_loop =
|
||||||
EventLoop::new(term.clone(), event_proxy, pty, options.drain_on_exit, false)?;
|
EventLoop::new(term.clone(), event_proxy, pty, options.drain_on_exit, false)?;
|
||||||
|
|
@ -352,6 +358,7 @@ impl Terminal {
|
||||||
profile_id_opt,
|
profile_id_opt,
|
||||||
search_regex_opt: None,
|
search_regex_opt: None,
|
||||||
search_value: String::new(),
|
search_value: String::new(),
|
||||||
|
shell_pid,
|
||||||
size,
|
size,
|
||||||
tab_title_override,
|
tab_title_override,
|
||||||
term,
|
term,
|
||||||
|
|
@ -407,6 +414,18 @@ impl Terminal {
|
||||||
self.notifier.notify(input);
|
self.notifier.notify(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn working_directory(&self) -> Option<PathBuf> {
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
{
|
||||||
|
let shell_pid = self.shell_pid?;
|
||||||
|
fs::read_link(format!("/proc/{shell_pid}/cwd")).ok()
|
||||||
|
}
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn input_scroll<I: Into<Cow<'static, [u8]>>>(&self, input: I) {
|
pub fn input_scroll<I: Into<Cow<'static, [u8]>>>(&self, input: I) {
|
||||||
self.input_no_scroll(input);
|
self.input_no_scroll(input);
|
||||||
self.scroll(TerminalScroll::Bottom);
|
self.scroll(TerminalScroll::Bottom);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue