diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-15 20:31:01 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-15 20:31:01 +0300 |
| commit | 4cbe72ec2d8a174e3c4f9bde2101aa189c7f38e7 (patch) | |
| tree | 2de696538e494d3c14a920c20877bcd6d4ac39dc /src/app/input | |
| parent | 43d60fc6629d222ae63813ebcf4531067ba5bc9d (diff) | |
feat: add indexed keybind families
Diffstat (limited to 'src/app/input')
| -rw-r--r-- | src/app/input/navigate.rs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/app/input/navigate.rs b/src/app/input/navigate.rs index 6dfaf475..7675835b 100644 --- a/src/app/input/navigate.rs +++ b/src/app/input/navigate.rs @@ -17,6 +17,10 @@ pub(crate) fn terminal_direct_navigation_action( state: &AppState, key: &KeyEvent, ) -> Option<NavigateAction> { + if let Some(action) = indexed_navigation_action(state, key) { + return Some(action); + } + let kb = &state.keybinds; if kb .previous_workspace @@ -373,6 +377,9 @@ pub(crate) enum NavigateAction { NewWorkspace, RenameWorkspace, CloseWorkspace, + SwitchWorkspace(usize), + SwitchTab(usize), + FocusAgent(usize), PreviousWorkspace, NextWorkspace, PreviousAgent, @@ -398,7 +405,40 @@ pub(crate) enum NavigateAction { Detach, } +fn indexed_navigation_action(state: &AppState, key: &KeyEvent) -> Option<NavigateAction> { + let KeyCode::Char(c @ '1'..='9') = key.code else { + return None; + }; + let idx = (c as usize) - ('1' as usize); + let kb = &state.keybinds; + + if kb + .indexed_tabs + .is_some_and(|mods| key_matches(key, KeyCode::Char(c), mods)) + { + return Some(NavigateAction::SwitchTab(idx)); + } + if kb + .indexed_workspaces + .is_some_and(|mods| key_matches(key, KeyCode::Char(c), mods)) + { + return Some(NavigateAction::SwitchWorkspace(idx)); + } + if kb + .indexed_agents + .is_some_and(|mods| key_matches(key, KeyCode::Char(c), mods)) + { + return Some(NavigateAction::FocusAgent(idx)); + } + + None +} + fn navigate_action_for_key(state: &AppState, key: &KeyEvent) -> Option<NavigateAction> { + if let Some(action) = indexed_navigation_action(state, key) { + return Some(action); + } + let kb = &state.keybinds; if key_matches(key, kb.new_workspace.0, kb.new_workspace.1) { return Some(NavigateAction::NewWorkspace); @@ -526,6 +566,27 @@ pub(super) fn execute_navigate_action(state: &mut AppState, action: NavigateActi } } } + NavigateAction::SwitchWorkspace(idx) => { + if idx < state.workspaces.len() { + state.switch_workspace(idx); + leave_navigate_mode(state); + } + } + NavigateAction::SwitchTab(idx) => { + let tab_exists = state + .active + .and_then(|ws_idx| state.workspaces.get(ws_idx)) + .is_some_and(|ws| idx < ws.tabs.len()); + if tab_exists { + state.switch_tab(idx); + leave_navigate_mode(state); + } + } + NavigateAction::FocusAgent(idx) => { + if state.focus_agent_entry(idx) { + leave_navigate_mode(state); + } + } NavigateAction::PreviousWorkspace => { state.previous_workspace(); leave_navigate_mode(state); @@ -791,6 +852,20 @@ mod tests { assert_eq!(action, Some(NavigateAction::FocusPaneLeft)); } + #[test] + fn terminal_direct_indexed_tab_shortcut_maps_to_navigation_action() { + let mut state = state_with_workspaces(&["test"]); + state.keybinds.indexed_tabs = Some(KeyModifiers::CONTROL); + state.keybinds.indexed_tabs_label = Some("ctrl+1..9".into()); + + let action = terminal_direct_navigation_action( + &state, + &KeyEvent::new(KeyCode::Char('3'), KeyModifiers::CONTROL), + ); + + assert_eq!(action, Some(NavigateAction::SwitchTab(2))); + } + #[tokio::test] async fn custom_command_runs_from_prefix_key_in_navigate_mode() { let (_api_tx, api_rx) = tokio::sync::mpsc::unbounded_channel(); |
