feat: add immediate new tab option

refs #123
This commit is contained in:
Ogulcan Celik 2026-05-16 18:41:36 +03:00
parent 7b8f699083
commit b173a86e34
7 changed files with 48 additions and 1 deletions

View File

@ -3,6 +3,7 @@
## Unreleased
### Added
- Added `ui.prompt_new_tab_name = false` for creating new tabs immediately with generated names instead of opening the rename dialog.
- Added optional `keys.edit_scrollback` to open the focused pane's retained scrollback in `$EDITOR` inside a temporary zoomed pane.
### Fixed

View File

@ -296,6 +296,7 @@ for `panel_bg`, you can also use `reset`, `default`, `none`, or `transparent` to
sidebar_width = 26
mouse_capture = true
confirm_close = true
prompt_new_tab_name = true
show_agent_labels_on_pane_borders = false
agent_panel_scope = "all"
accent = "cyan"
@ -308,6 +309,7 @@ accent = "cyan"
| `sidebar_width` | `26` | base sidebar width before auto-scaling |
| `mouse_capture` | `true` | capture mouse input for Herdr's mouse UI; set false to let the terminal handle normal clicks while still forwarding mouse to pane apps that request it |
| `confirm_close` | `true` | ask before closing a workspace |
| `prompt_new_tab_name` | `true` | ask for a tab name before creating a new tab; set false to create tabs immediately with generated names |
| `show_agent_labels_on_pane_borders` | `false` | show detected/reported agent labels in split pane borders when no manual pane name is set |
| `agent_panel_scope` | `all` | sidebar agent list scope: `current` or `all` |
| `accent` | `cyan` | highlight and border color |

View File

@ -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();
@ -1206,6 +1213,19 @@ mod tests {
assert_eq!(state.workspaces[0].tabs.len(), 1);
}
#[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();

View File

@ -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 =

View File

@ -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,

View File

@ -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(),
@ -297,6 +300,19 @@ show_agent_labels_on_pane_borders = true
assert!(config.ui.show_agent_labels_on_pane_borders);
}
#[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();

View File

@ -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