diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-04-09 04:31:21 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-04-09 04:32:45 +0300 |
| commit | 5460a9601ea8dd3d05e64e97040c71c6be29172b (patch) | |
| tree | a3bfa468c2112ab2eb843c7a1bef46fe3b901599 /src | |
| parent | b5b61c14841fda60f289cfd9c782580ea099a2a2 (diff) | |
fix(tabs): keep default numeric labels auto-generated
Diffstat (limited to 'src')
| -rw-r--r-- | src/app/input.rs | 87 | ||||
| -rw-r--r-- | src/ui.rs | 43 | ||||
| -rw-r--r-- | src/workspace.rs | 4 |
3 files changed, 119 insertions, 15 deletions
diff --git a/src/app/input.rs b/src/app/input.rs index ada8e6d9..d1c20d8d 100644 --- a/src/app/input.rs +++ b/src/app/input.rs @@ -940,15 +940,18 @@ fn open_rename_active_tab(state: &mut AppState, replace_on_type: bool) { } } -fn open_new_tab_dialog(state: &mut AppState) { - let next_tab_name = state +fn next_new_tab_default_name(state: &AppState) -> String { + state .active .and_then(|i| state.workspaces.get(i)) .map(|ws| (ws.tabs.len() + 1).to_string()) - .unwrap_or_else(|| "1".to_string()); + .unwrap_or_else(|| "1".to_string()) +} + +fn open_new_tab_dialog(state: &mut AppState) { state.creating_new_tab = true; state.requested_new_tab_name = None; - state.name_input = next_tab_name; + state.name_input = next_new_tab_default_name(state); state.name_input_replace_on_type = true; state.mode = Mode::RenameTab; } @@ -1049,16 +1052,20 @@ fn apply_rename_action(state: &mut AppState, action: ModalAction) { } Mode::RenameTab if state.creating_new_tab => { state.request_new_tab = true; - state.requested_new_tab_name = if new_name.is_empty() { - None - } else { - Some(new_name) - }; + let default_name = next_new_tab_default_name(state); + state.requested_new_tab_name = + if new_name.is_empty() || new_name == default_name { + None + } else { + Some(new_name) + }; } Mode::RenameTab => { - if !new_name.is_empty() { - if let Some(ws) = state.active.and_then(|i| state.workspaces.get_mut(i)) { - if let Some(tab) = ws.active_tab_mut() { + if let Some(ws) = state.active.and_then(|i| state.workspaces.get_mut(i)) { + if let Some(tab) = ws.active_tab_mut() { + let keep_auto_name = + tab.is_auto_named() && new_name == tab.number.to_string(); + if !new_name.is_empty() && !keep_auto_name { tab.set_custom_name(new_name); state.mark_session_dirty(); } @@ -3427,6 +3434,62 @@ mod tests { } #[test] + fn saving_new_tab_dialog_with_default_name_keeps_tab_auto_named() { + let mut state = state_with_workspaces(&["test"]); + open_new_tab_dialog(&mut state); + + handle_rename_key( + &mut state, + KeyEvent::new(KeyCode::Enter, KeyModifiers::empty()), + ); + + 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 closing_first_auto_tab_resets_remaining_auto_tab_and_next_prompt() { + let mut state = state_with_workspaces(&["test"]); + open_new_tab_dialog(&mut state); + handle_rename_key( + &mut state, + KeyEvent::new(KeyCode::Enter, KeyModifiers::empty()), + ); + + state.workspaces[0].test_add_tab(state.requested_new_tab_name.as_deref()); + state.request_new_tab = false; + state.requested_new_tab_name = None; + + state.workspaces[0].close_tab(0); + state.workspaces[0].switch_tab(0); + + assert_eq!(state.workspaces[0].tabs[0].display_name(), "1"); + assert!(state.workspaces[0].tabs[0].custom_name.is_none()); + + open_new_tab_dialog(&mut state); + assert_eq!(state.name_input, "2"); + } + + #[test] + fn renaming_auto_tab_to_its_default_number_keeps_it_auto_named() { + let mut state = state_with_workspaces(&["test"]); + state.workspaces[0].test_add_tab(None); + state.workspaces[0].switch_tab(1); + + open_rename_active_tab(&mut state, false); + handle_rename_key( + &mut state, + KeyEvent::new(KeyCode::Enter, KeyModifiers::empty()), + ); + + assert_eq!(state.mode, Mode::Terminal); + assert!(state.workspaces[0].tabs[1].custom_name.is_none()); + assert_eq!(state.workspaces[0].tabs[1].display_name(), "2"); + } + + #[test] fn confirm_close_keyboard_actions_are_direct_not_focused() { let mut state = state_with_workspaces(&["a", "b"]); state.mode = Mode::ConfirmClose; @@ -558,10 +558,17 @@ fn render_tab_bar(app: &AppState, frame: &mut Frame, area: Rect) { }; let active = idx == ws.active_tab; let style = if active { + let base = Style::default().fg(p.panel_bg).bg(p.accent); + if tab.is_auto_named() { + base.add_modifier(Modifier::DIM) + } else { + base.add_modifier(Modifier::BOLD) + } + } else if tab.is_auto_named() { Style::default() - .fg(p.panel_bg) - .bg(p.accent) - .add_modifier(Modifier::BOLD) + .fg(p.overlay0) + .bg(p.surface0) + .add_modifier(Modifier::DIM) } else { Style::default().fg(p.overlay1).bg(p.surface0) }; @@ -3139,6 +3146,36 @@ mod tests { } #[test] + fn tab_bar_dims_auto_named_tabs_and_emphasizes_custom_tabs() { + let mut app = crate::app::state::AppState::test_new(); + let mut ws = Workspace::test_new("test"); + let custom_tab = ws.test_add_tab(Some("logs")); + ws.switch_tab(custom_tab); + + app.workspaces = vec![ws]; + app.active = Some(0); + app.selected = 0; + app.mode = Mode::Terminal; + + compute_view(&mut app, Rect::new(0, 0, 80, 20)); + + let backend = TestBackend::new(80, 20); + let mut terminal = Terminal::new(backend).unwrap(); + terminal.draw(|frame| render(&app, frame)).unwrap(); + let buffer = terminal.backend().buffer(); + + let auto_rect = app.view.tab_hit_areas[0]; + let custom_rect = app.view.tab_hit_areas[1]; + let auto_style = buffer[(auto_rect.x + 1, auto_rect.y)].style(); + let custom_style = buffer[(custom_rect.x + 1, custom_rect.y)].style(); + + assert_eq!(auto_style.fg, Some(app.palette.overlay0)); + assert!(auto_style.add_modifier.contains(Modifier::DIM)); + assert_eq!(custom_style.fg, Some(app.palette.panel_bg)); + assert!(custom_style.add_modifier.contains(Modifier::BOLD)); + } + + #[test] fn all_workspaces_agent_panel_entries_use_workspace_and_optional_tab_labels() { let mut app = crate::app::state::AppState::test_new(); let mut first = Workspace::test_new("one"); diff --git a/src/workspace.rs b/src/workspace.rs index 02f971b0..447e6061 100644 --- a/src/workspace.rs +++ b/src/workspace.rs @@ -105,6 +105,10 @@ impl Tab { .unwrap_or_else(|| self.number.to_string()) } + pub fn is_auto_named(&self) -> bool { + self.custom_name.is_none() + } + pub fn set_custom_name(&mut self, name: String) { self.custom_name = Some(name); } |
