aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-16 18:41:36 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-16 18:41:36 +0300
commitb173a86e34343a94c2941fa960b9c7e6a3bcb26a (patch)
tree79c663eec285f5181ffd06d03261e7d33221f4c4 /src
parent7b8f6990837ed2df63b533c7bbcd5bf6835efef7 (diff)
feat: add immediate new tab option
refs #123
Diffstat (limited to 'src')
-rw-r--r--src/app/input/navigate.rs22
-rw-r--r--src/app/mod.rs2
-rw-r--r--src/app/state.rs2
-rw-r--r--src/config/model.rs16
-rw-r--r--src/main.rs4
5 files changed, 45 insertions, 1 deletions
diff --git a/src/app/input/navigate.rs b/src/app/input/navigate.rs
index 7eb5b8d9..f5a0bcaa 100644
--- a/src/app/input/navigate.rs
+++ b/src/app/input/navigate.rs
@@ -682,7 +682,14 @@ pub(super) fn execute_navigate_action(state: &mut AppState, action: NavigateActi
state.next_agent();
leave_navigate_mode(state);
}
- NavigateAction::NewTab => super::modal::open_new_tab_dialog(state),
+ NavigateAction::NewTab => {
+ if state.prompt_new_tab_name {
+ super::modal::open_new_tab_dialog(state);
+ } else {
+ state.request_new_tab = true;
+ leave_navigate_mode(state);
+ }
+ }
NavigateAction::RenameTab => super::modal::open_rename_active_tab(state, false),
NavigateAction::PreviousTab => {
state.previous_tab();
@@ -1207,6 +1214,19 @@ mod tests {
}
#[test]
+ fn new_tab_action_can_skip_rename_dialog() {
+ let mut state = state_with_workspaces(&["test"]);
+ state.prompt_new_tab_name = false;
+
+ execute_navigate_action(&mut state, NavigateAction::NewTab);
+
+ assert_eq!(state.mode, Mode::Terminal);
+ assert!(!state.creating_new_tab);
+ assert!(state.request_new_tab);
+ assert!(state.requested_new_tab_name.is_none());
+ }
+
+ #[test]
fn persistence_mode_navigate_q_detaches_instead_of_quitting_server() {
let mut state = crate::app::state::AppState::test_new();
state.quit_detaches = true;
diff --git a/src/app/mod.rs b/src/app/mod.rs
index 644329ab..bc732f57 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -371,6 +371,7 @@ impl App {
agent_panel_scope,
mouse_capture: config.ui.mouse_capture,
confirm_close: config.ui.confirm_close,
+ prompt_new_tab_name: config.ui.prompt_new_tab_name,
show_agent_labels_on_pane_borders: config.ui.show_agent_labels_on_pane_borders,
kitty_graphics_enabled: config.experimental.kitty_graphics,
pane_scrollback_limit_bytes: config.advanced.scrollback_limit_bytes,
@@ -716,6 +717,7 @@ impl App {
}
self.state.mouse_capture = config.ui.mouse_capture;
self.state.confirm_close = config.ui.confirm_close;
+ self.state.prompt_new_tab_name = config.ui.prompt_new_tab_name;
self.state.show_agent_labels_on_pane_borders =
config.ui.show_agent_labels_on_pane_borders;
self.state.agent_panel_scope =
diff --git a/src/app/state.rs b/src/app/state.rs
index b51d500f..237e25a0 100644
--- a/src/app/state.rs
+++ b/src/app/state.rs
@@ -881,6 +881,7 @@ pub struct AppState {
/// captures mouse while the focused pane app requests mouse reporting.
pub mouse_capture: bool,
pub confirm_close: bool,
+ pub prompt_new_tab_name: bool,
pub show_agent_labels_on_pane_borders: bool,
pub kitty_graphics_enabled: bool,
pub pane_scrollback_limit_bytes: usize,
@@ -1064,6 +1065,7 @@ impl AppState {
agent_panel_scope: AgentPanelScope::AllWorkspaces,
mouse_capture: true,
confirm_close: true,
+ prompt_new_tab_name: true,
show_agent_labels_on_pane_borders: false,
kitty_graphics_enabled: false,
pane_scrollback_limit_bytes: crate::config::DEFAULT_SCROLLBACK_LIMIT_BYTES,
diff --git a/src/config/model.rs b/src/config/model.rs
index f389b18b..f9522e41 100644
--- a/src/config/model.rs
+++ b/src/config/model.rs
@@ -150,6 +150,8 @@ pub struct UiConfig {
pub mouse_capture: bool,
/// Ask for confirmation before closing a workspace. Default: true.
pub confirm_close: bool,
+ /// Ask for a tab name before creating a new tab. Default: true.
+ pub prompt_new_tab_name: bool,
/// Show agent labels in split pane borders when no manual pane label is set. Default: false.
pub show_agent_labels_on_pane_borders: bool,
/// Agent sidebar scope. Saved values are "current" or "all". Default: "all".
@@ -223,6 +225,7 @@ impl Default for UiConfig {
sidebar_width: 26,
mouse_capture: true,
confirm_close: true,
+ prompt_new_tab_name: true,
show_agent_labels_on_pane_borders: false,
agent_panel_scope: AgentPanelScopeConfig::All,
accent: "cyan".into(),
@@ -298,6 +301,19 @@ show_agent_labels_on_pane_borders = true
}
#[test]
+ fn prompt_new_tab_name_defaults_on_and_parses() {
+ let default_config = Config::default();
+ assert!(default_config.ui.prompt_new_tab_name);
+
+ let toml = r#"
+[ui]
+prompt_new_tab_name = false
+"#;
+ let config: Config = toml::from_str(toml).unwrap();
+ assert!(!config.ui.prompt_new_tab_name);
+ }
+
+ #[test]
fn mouse_capture_default_on_and_parse() {
let default_config = Config::default();
assert!(default_config.ui.mouse_capture);
diff --git a/src/main.rs b/src/main.rs
index 7d268a4d..33461e4d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -136,6 +136,10 @@ const DEFAULT_CONFIG: &str = r##"# herdr configuration
# Ask for confirmation before closing a workspace
# confirm_close = true
+# Ask for a tab name before creating a new tab.
+# Set false to create tabs immediately with generated names.
+# prompt_new_tab_name = true
+
# Show detected/reported agent labels in split pane borders when no manual pane name is set.
# show_agent_labels_on_pane_borders = false