aboutsummaryrefslogtreecommitdiff
path: root/src/app/input
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-19 20:44:43 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-19 20:44:44 +0300
commita26a654351ee03b1a51d7b398f3bdff2c1ca920d (patch)
tree05382168990e4a6f50f6dbb5220c52fad062923d /src/app/input
parent01d371bf7a10330c6a5c139c7df766ae8f6f1cda (diff)
feat: connected tree glyphs, workspace grouping, and search auto-select in navigator
refs #1611
Diffstat (limited to 'src/app/input')
-rw-r--r--src/app/input/modal.rs16
-rw-r--r--src/app/input/overlays.rs16
2 files changed, 18 insertions, 14 deletions
diff --git a/src/app/input/modal.rs b/src/app/input/modal.rs
index 23134ddc..dc126b40 100644
--- a/src/app/input/modal.rs
+++ b/src/app/input/modal.rs
@@ -173,7 +173,7 @@ pub(crate) fn handle_navigator_key(
KeyCode::Backspace => {
state.navigator.state_filter = None;
state.navigator.query.pop();
- state.clamp_navigator_selection_from(terminal_runtimes);
+ state.select_first_navigator_match_from(terminal_runtimes);
}
KeyCode::Up => state.move_navigator_selection_from(terminal_runtimes, -1),
KeyCode::Down => state.move_navigator_selection_from(terminal_runtimes, 1),
@@ -222,22 +222,22 @@ pub(crate) fn handle_navigator_key(
KeyCode::Char('b') if key.modifiers.is_empty() => {
state.navigator.query.clear();
state.navigator.state_filter = Some(NavigatorStateFilter::Blocked);
- state.clamp_navigator_selection_from(terminal_runtimes);
+ state.select_first_navigator_match_from(terminal_runtimes);
}
KeyCode::Char('w') if key.modifiers.is_empty() => {
state.navigator.query.clear();
state.navigator.state_filter = Some(NavigatorStateFilter::Working);
- state.clamp_navigator_selection_from(terminal_runtimes);
+ state.select_first_navigator_match_from(terminal_runtimes);
}
KeyCode::Char('i') if key.modifiers.is_empty() => {
state.navigator.query.clear();
state.navigator.state_filter = Some(NavigatorStateFilter::Idle);
- state.clamp_navigator_selection_from(terminal_runtimes);
+ state.select_first_navigator_match_from(terminal_runtimes);
}
KeyCode::Char('d') if key.modifiers.is_empty() => {
state.navigator.query.clear();
state.navigator.state_filter = Some(NavigatorStateFilter::Done);
- state.clamp_navigator_selection_from(terminal_runtimes);
+ state.select_first_navigator_match_from(terminal_runtimes);
}
KeyCode::Char('j') | KeyCode::Down => {
state.move_navigator_selection_from(terminal_runtimes, 1)
@@ -246,12 +246,12 @@ pub(crate) fn handle_navigator_key(
state.move_navigator_selection_from(terminal_runtimes, -1)
}
KeyCode::Char('d') if key.modifiers == KeyModifiers::CONTROL => state
- .move_navigator_selection_from(
+ .move_navigator_selection_by_lines_from(
terminal_runtimes,
(state.navigator_body_rect().height / 2).max(1) as isize,
),
KeyCode::Char('u') if key.modifiers == KeyModifiers::CONTROL => state
- .move_navigator_selection_from(
+ .move_navigator_selection_by_lines_from(
terminal_runtimes,
-((state.navigator_body_rect().height / 2).max(1) as isize),
),
@@ -281,7 +281,7 @@ pub(crate) fn insert_navigator_search_text(
}
state.navigator.state_filter = None;
state.navigator.query.push_str(text);
- state.clamp_navigator_selection_from(terminal_runtimes);
+ state.select_first_navigator_match_from(terminal_runtimes);
}
pub(crate) fn handle_keybind_help_key(state: &mut AppState, key: KeyEvent) {
diff --git a/src/app/input/overlays.rs b/src/app/input/overlays.rs
index 20944080..e9cf3139 100644
--- a/src/app/input/overlays.rs
+++ b/src/app/input/overlays.rs
@@ -172,9 +172,8 @@ impl App {
}
MouseEventKind::ScrollUp => {
self.state.navigator.scroll = self.state.navigator.scroll.saturating_sub(3);
- self.state.navigator.selected = self.state.navigator.scroll;
self.state
- .clamp_navigator_selection_from(&self.terminal_runtimes);
+ .align_navigator_selection_to_scroll_from(&self.terminal_runtimes);
}
MouseEventKind::ScrollDown => {
let viewport = self.state.navigator_body_rect().height as usize;
@@ -183,9 +182,8 @@ impl App {
.navigator_max_scroll_from(&self.terminal_runtimes, viewport);
self.state.navigator.scroll =
self.state.navigator.scroll.saturating_add(3).min(max);
- self.state.navigator.selected = self.state.navigator.scroll;
self.state
- .clamp_navigator_selection_from(&self.terminal_runtimes);
+ .align_navigator_selection_to_scroll_from(&self.terminal_runtimes);
}
_ => {}
}
@@ -337,11 +335,17 @@ impl AppState {
if !rect_contains(body, col, row) {
return None;
}
- let idx = self
+ let line_idx = self
.navigator
.scroll
.saturating_add(row.saturating_sub(body.y) as usize);
- (idx < self.navigator_rows_from(terminal_runtimes).len()).then_some(idx)
+ let lines = crate::app::state::navigator_display_lines(
+ &self.navigator_rows_from(terminal_runtimes),
+ );
+ match lines.get(line_idx) {
+ Some(crate::app::state::NavigatorDisplayLine::Row(idx)) => Some(*idx),
+ _ => None,
+ }
}
pub(crate) fn navigator_row_caret_at(&self, col: u16) -> bool {