diff options
Diffstat (limited to 'src/app/input')
| -rw-r--r-- | src/app/input/mod.rs | 5 | ||||
| -rw-r--r-- | src/app/input/modal.rs | 53 | ||||
| -rw-r--r-- | src/app/input/mouse.rs | 16 | ||||
| -rw-r--r-- | src/app/input/navigate.rs | 16 | ||||
| -rw-r--r-- | src/app/input/settings.rs | 43 |
5 files changed, 126 insertions, 7 deletions
diff --git a/src/app/input/mod.rs b/src/app/input/mod.rs index aa607c78..575b373d 100644 --- a/src/app/input/mod.rs +++ b/src/app/input/mod.rs @@ -63,7 +63,7 @@ impl App { Mode::Onboarding => self.handle_onboarding_key(key), Mode::ReleaseNotes => self.handle_release_notes_key(key), Mode::Navigate => unreachable!(), - Mode::RenameWorkspace | Mode::RenameTab => { + Mode::RenameWorkspace | Mode::RenameTab | Mode::RenamePane => { handle_rename_key(&mut self.state, key) } Mode::Resize => handle_resize_key(&mut self.state, key), @@ -159,6 +159,9 @@ impl App { SettingsAction::SaveTheme(name) => self.save_theme(&name), SettingsAction::SaveSound(enabled) => self.save_sound(enabled), SettingsAction::SaveToastDelivery(delivery) => self.save_toast_delivery(delivery), + SettingsAction::SaveAgentBorderLabels(enabled) => { + self.save_agent_border_labels(enabled) + } } } if self.state.agent_panel_scope != previous_agent_panel_scope { diff --git a/src/app/input/modal.rs b/src/app/input/modal.rs index a76576bf..367e7e84 100644 --- a/src/app/input/modal.rs +++ b/src/app/input/modal.rs @@ -164,6 +164,7 @@ pub(crate) fn handle_keybind_help_key(state: &mut AppState, key: KeyEvent) { pub(super) fn open_rename_workspace(state: &mut AppState, ws_idx: usize) { state.selected = ws_idx; + state.rename_pane_target = None; state.name_input = state.workspaces[ws_idx].display_name(); state.name_input_replace_on_type = false; state.mode = Mode::RenameWorkspace; @@ -172,6 +173,7 @@ pub(super) fn open_rename_workspace(state: &mut AppState, ws_idx: usize) { pub(super) fn open_rename_active_tab(state: &mut AppState, replace_on_type: bool) { state.creating_new_tab = false; state.requested_new_tab_name = None; + state.rename_pane_target = None; if let Some(ws) = state.active.and_then(|i| state.workspaces.get(i)) { if let Some(name) = ws.active_tab_display_name() { state.name_input = name; @@ -181,6 +183,21 @@ pub(super) fn open_rename_active_tab(state: &mut AppState, replace_on_type: bool } } +pub(super) fn open_rename_pane(state: &mut AppState, pane_id: crate::layout::PaneId) { + let Some(ws) = state.active.and_then(|i| state.workspaces.get(i)) else { + return; + }; + let Some(pane) = ws.pane_state(pane_id) else { + return; + }; + state.creating_new_tab = false; + state.requested_new_tab_name = None; + state.rename_pane_target = Some(pane_id); + state.name_input = pane.manual_label.clone().unwrap_or_default(); + state.name_input_replace_on_type = pane.manual_label.is_none(); + state.mode = Mode::RenamePane; +} + fn next_new_tab_default_name(state: &AppState) -> String { state .active @@ -192,6 +209,7 @@ fn next_new_tab_default_name(state: &AppState) -> String { pub(super) fn open_new_tab_dialog(state: &mut AppState) { state.creating_new_tab = true; state.requested_new_tab_name = None; + state.rename_pane_target = None; state.name_input = next_new_tab_default_name(state); state.name_input_replace_on_type = true; state.mode = Mode::RenameTab; @@ -295,9 +313,21 @@ pub(super) fn apply_rename_action(state: &mut AppState, action: ModalAction) { } } } + Mode::RenamePane => { + if let (Some(ws_idx), Some(pane_id)) = (state.active, state.rename_pane_target) + { + if let Some(ws) = state.workspaces.get_mut(ws_idx) { + if let Some(pane) = ws.pane_state_mut(pane_id) { + pane.set_manual_label(new_name); + state.mark_session_dirty(); + } + } + } + } _ => {} } state.creating_new_tab = false; + state.rename_pane_target = None; state.name_input.clear(); state.name_input_replace_on_type = false; leave_modal(state); @@ -309,6 +339,7 @@ pub(super) fn apply_rename_action(state: &mut AppState, action: ModalAction) { ModalAction::Cancel => { state.creating_new_tab = false; state.requested_new_tab_name = None; + state.rename_pane_target = None; state.name_input.clear(); state.name_input_replace_on_type = false; leave_modal(state); @@ -432,19 +463,33 @@ pub(super) fn apply_context_menu_action(state: &mut AppState, menu: ContextMenuS Mode::Navigate }; } - (ContextMenuKind::Pane, Some("Split vertical")) => { + (ContextMenuKind::Pane { pane_id, .. }, Some("Rename pane")) => { + open_rename_pane(state, pane_id); + } + (ContextMenuKind::Pane { pane_id, .. }, Some("Clear pane name")) => { + if let Some(ws_idx) = state.active { + if let Some(ws) = state.workspaces.get_mut(ws_idx) { + if let Some(pane) = ws.pane_state_mut(pane_id) { + pane.clear_manual_label(); + state.mark_session_dirty(); + } + } + } + state.mode = Mode::Terminal; + } + (ContextMenuKind::Pane { .. }, Some("Split vertical")) => { state.split_pane(Direction::Horizontal); state.mode = Mode::Terminal; } - (ContextMenuKind::Pane, Some("Split horizontal")) => { + (ContextMenuKind::Pane { .. }, Some("Split horizontal")) => { state.split_pane(Direction::Vertical); state.mode = Mode::Terminal; } - (ContextMenuKind::Pane, Some("Fullscreen")) => { + (ContextMenuKind::Pane { .. }, Some("Fullscreen")) => { state.toggle_fullscreen(); state.mode = Mode::Terminal; } - (ContextMenuKind::Pane, Some("Close pane")) => { + (ContextMenuKind::Pane { .. }, Some("Close pane")) => { state.close_pane(); state.mode = if state.active.is_some() { Mode::Terminal diff --git a/src/app/input/mouse.rs b/src/app/input/mouse.rs index 4a074a2e..f7997807 100644 --- a/src/app/input/mouse.rs +++ b/src/app/input/mouse.rs @@ -137,7 +137,10 @@ impl AppState { return None; } - if matches!(self.mode, Mode::RenameWorkspace | Mode::RenameTab) { + if matches!( + self.mode, + Mode::RenameWorkspace | Mode::RenameTab | Mode::RenamePane + ) { let action = self .rename_modal_inner() .map(crate::ui::rename_button_rects) @@ -678,8 +681,17 @@ impl AppState { MouseEventKind::Down(MouseButton::Right) if !in_sidebar => { if let Some(info) = self.pane_mouse_target(mouse.column, mouse.row).cloned() { self.focus_pane(info.id); + let has_manual_label = self + .active + .and_then(|ws_idx| self.workspaces.get(ws_idx)) + .and_then(|ws| ws.pane_state(info.id)) + .and_then(|pane| pane.manual_label.as_ref()) + .is_some(); self.context_menu = Some(ContextMenuState { - kind: ContextMenuKind::Pane, + kind: ContextMenuKind::Pane { + pane_id: info.id, + has_manual_label, + }, x: mouse.column, y: mouse.row, list: MenuListState::new(0), diff --git a/src/app/input/navigate.rs b/src/app/input/navigate.rs index 3bc8da78..bb88c46b 100644 --- a/src/app/input/navigate.rs +++ b/src/app/input/navigate.rs @@ -368,6 +368,7 @@ pub(crate) enum NavigateAction { PreviousTab, NextTab, CloseTab, + RenamePane, FocusPaneLeft, FocusPaneDown, FocusPaneUp, @@ -432,6 +433,12 @@ fn navigate_action_for_key(state: &AppState, key: &KeyEvent) -> Option<NavigateA { return Some(NavigateAction::CloseTab); } + if kb + .rename_pane + .is_some_and(|(code, mods)| key_matches(key, code, mods)) + { + return Some(NavigateAction::RenamePane); + } if key_matches(key, kb.split_vertical.0, kb.split_vertical.1) { return Some(NavigateAction::SplitVertical); } @@ -508,6 +515,15 @@ pub(super) fn execute_navigate_action(state: &mut AppState, action: NavigateActi state.close_tab(); leave_navigate_mode(state); } + NavigateAction::RenamePane => { + if let Some(pane_id) = state + .active + .and_then(|ws_idx| state.workspaces.get(ws_idx)) + .and_then(|ws| ws.focused_pane_id()) + { + super::modal::open_rename_pane(state, pane_id); + } + } NavigateAction::FocusPaneLeft => state.navigate_pane(NavDirection::Left), NavigateAction::FocusPaneDown => state.navigate_pane(NavDirection::Down), NavigateAction::FocusPaneUp => state.navigate_pane(NavDirection::Up), diff --git a/src/app/input/settings.rs b/src/app/input/settings.rs index 67144a28..9e89e515 100644 --- a/src/app/input/settings.rs +++ b/src/app/input/settings.rs @@ -16,6 +16,7 @@ pub(super) enum SettingsAction { SaveTheme(String), SaveSound(bool), SaveToastDelivery(ToastDelivery), + SaveAgentBorderLabels(bool), } impl App { @@ -25,6 +26,9 @@ impl App { SettingsAction::SaveTheme(name) => self.save_theme(&name), SettingsAction::SaveSound(enabled) => self.save_sound(enabled), SettingsAction::SaveToastDelivery(delivery) => self.save_toast_delivery(delivery), + SettingsAction::SaveAgentBorderLabels(enabled) => { + self.save_agent_border_labels(enabled) + } } } } @@ -157,6 +161,30 @@ pub(super) fn update_settings_state(state: &mut AppState, key: KeyEvent) -> Opti state.settings.list.selected = usize::from(!state.sound_enabled()); } KeyCode::Tab | KeyCode::Right | KeyCode::Char('l') => { + state.settings.section = SettingsSection::PaneLabels; + state.settings.list.selected = usize::from(!state.agent_border_labels_enabled()); + } + _ => { + if let Some(super::modal::ModalAction::Close) = + super::modal::modal_action_from_key(&key, super::modal::SETTINGS_ACTIONS) + { + cancel_settings(state); + } + } + }, + SettingsSection::PaneLabels => match key.code { + KeyCode::Up | KeyCode::Char('k') | KeyCode::Down | KeyCode::Char('j') => { + state.settings.list.selected = 1 - state.settings.list.selected.min(1); + } + KeyCode::Enter | KeyCode::Char(' ') => { + let enabled = state.settings.list.selected == 0; + return Some(SettingsAction::SaveAgentBorderLabels(enabled)); + } + KeyCode::BackTab | KeyCode::Left | KeyCode::Char('h') => { + state.settings.section = SettingsSection::Toast; + state.settings.list.selected = toast_delivery_index(state.toast_delivery()); + } + KeyCode::Tab | KeyCode::Right | KeyCode::Char('l') => { state.settings.section = SettingsSection::Theme; state.settings.list.selected = current_theme_index(&state.theme_name); } @@ -252,6 +280,14 @@ impl AppState { None } } + SettingsSection::PaneLabels => { + let list_y = area.y + 3; + if row >= list_y && row < list_y + 2 { + Some((row - list_y) as usize) + } else { + None + } + } } } @@ -264,6 +300,9 @@ impl AppState { SettingsSection::Theme => current_theme_index(&self.theme_name), SettingsSection::Sound => usize::from(!self.sound_enabled()), SettingsSection::Toast => toast_delivery_index(self.toast_delivery()), + SettingsSection::PaneLabels => { + usize::from(!self.agent_border_labels_enabled()) + } }); return None; } @@ -282,6 +321,10 @@ impl AppState { let delivery = toast_delivery_for_index(idx); Some(SettingsAction::SaveToastDelivery(delivery)) } + SettingsSection::PaneLabels => { + let enabled = idx == 0; + Some(SettingsAction::SaveAgentBorderLabels(enabled)) + } }; } |
