Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add key bindings to jump to the next item of the same kind #45

Merged
merged 3 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 88 additions & 34 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,10 @@ pub enum Event {
PageUp,
PageDown,
FocusPrev,
FocusPrevSameKind, // focus on the previous item of the same kind (i.e. file, section, line)
FocusPrevPage,
FocusNext,
FocusNextSameKind, // focus on the next item of the same kind
FocusNextPage,
FocusInner,
FocusOuter,
Expand Down Expand Up @@ -165,7 +167,7 @@ impl From<crossterm::event::Event> for Event {
}) => Self::QuitAccept,

Event::Key(KeyEvent {
code: KeyCode::Char('y'),
code: KeyCode::Up | KeyCode::Char('y'),
modifiers: KeyModifiers::CONTROL,
kind: KeyEventKind::Press,
state: _,
Expand All @@ -177,7 +179,7 @@ impl From<crossterm::event::Event> for Event {
modifiers: _,
}) => Self::ScrollUp,
Event::Key(KeyEvent {
code: KeyCode::Char('e'),
code: KeyCode::Down | KeyCode::Char('e'),
modifiers: KeyModifiers::CONTROL,
kind: KeyEventKind::Press,
state: _,
Expand All @@ -189,34 +191,18 @@ impl From<crossterm::event::Event> for Event {
modifiers: _,
}) => Self::ScrollDown,

Event::Key(
KeyEvent {
code: KeyCode::PageUp,
modifiers: KeyModifiers::NONE,
kind: KeyEventKind::Press,
state: _,
}
| KeyEvent {
code: KeyCode::Char('b'),
modifiers: KeyModifiers::CONTROL,
kind: KeyEventKind::Press,
state: _,
},
) => Self::PageUp,
Event::Key(
KeyEvent {
code: KeyCode::PageDown,
modifiers: KeyModifiers::NONE,
kind: KeyEventKind::Press,
state: _,
}
| KeyEvent {
code: KeyCode::Char('f'),
modifiers: KeyModifiers::CONTROL,
kind: KeyEventKind::Press,
state: _,
},
) => Self::PageDown,
Event::Key(KeyEvent {
code: KeyCode::PageUp | KeyCode::Char('b'),
modifiers: KeyModifiers::CONTROL,
kind: KeyEventKind::Press,
state: _,
}) => Self::PageUp,
Event::Key(KeyEvent {
code: KeyCode::PageDown | KeyCode::Char('f'),
modifiers: KeyModifiers::CONTROL,
emesterhazy marked this conversation as resolved.
Show resolved Hide resolved
kind: KeyEventKind::Press,
state: _,
}) => Self::PageDown,

Event::Key(KeyEvent {
code: KeyCode::Up | KeyCode::Char('k'),
Expand All @@ -231,6 +217,19 @@ impl From<crossterm::event::Event> for Event {
state: _,
}) => Self::FocusNext,

Event::Key(KeyEvent {
code: KeyCode::PageUp,
modifiers: KeyModifiers::NONE,
kind: KeyEventKind::Press,
state: _,
}) => Self::FocusPrevSameKind,
Event::Key(KeyEvent {
code: KeyCode::PageDown,
modifiers: KeyModifiers::NONE,
kind: KeyEventKind::Press,
state: _,
}) => Self::FocusNextSameKind,

Event::Key(KeyEvent {
code: KeyCode::Left | KeyCode::Char('h'),
modifiers: KeyModifiers::NONE,
Expand Down Expand Up @@ -738,6 +737,14 @@ impl<'state, 'input> Recorder<'state, 'input> {
label: Cow::Borrowed("Next item (down, j)"),
event: Event::FocusNext,
},
MenuItem {
label: Cow::Borrowed("Previous item of the same kind (page-up)"),
event: Event::FocusPrevSameKind,
},
MenuItem {
label: Cow::Borrowed("Next item of the same kind (page-down)"),
event: Event::FocusNextSameKind,
},
MenuItem {
label: Cow::Borrowed("Outer item (left, h)"),
event: Event::FocusOuter,
Expand Down Expand Up @@ -768,19 +775,19 @@ impl<'state, 'input> Recorder<'state, 'input> {
event: Event::ExpandAll,
},
MenuItem {
label: Cow::Borrowed("Scroll up (ctrl-y)"),
label: Cow::Borrowed("Scroll up (ctrl-up, ctrl-y)"),
event: Event::ScrollUp,
},
MenuItem {
label: Cow::Borrowed("Scroll down (ctrl-e)"),
label: Cow::Borrowed("Scroll down (ctrl-down, ctrl-e)"),
event: Event::ScrollDown,
},
MenuItem {
label: Cow::Borrowed("Page up (page-up, ctrl-b)"),
label: Cow::Borrowed("Previous page (ctrl-page-up, ctrl-b)"),
event: Event::PageUp,
},
MenuItem {
label: Cow::Borrowed("Page down (page-down, ctrl-f)"),
label: Cow::Borrowed("Next page (ctrl-page-down, ctrl-f)"),
event: Event::PageDown,
},
],
Expand Down Expand Up @@ -1056,6 +1063,8 @@ impl<'state, 'input> Recorder<'state, 'input> {
| Event::PageDown
| Event::FocusPrev
| Event::FocusNext
| Event::FocusPrevSameKind
| Event::FocusNextSameKind
| Event::FocusPrevPage
| Event::FocusNextPage
| Event::ToggleAll
Expand Down Expand Up @@ -1098,6 +1107,22 @@ impl<'state, 'input> Recorder<'state, 'input> {
ensure_in_viewport: true,
}
}
(None, Event::FocusPrevSameKind) => {
let selection_key =
self.select_prev_or_next_of_same_kind(/*select_previous=*/ true);
StateUpdate::SelectItem {
selection_key,
ensure_in_viewport: true,
}
}
(None, Event::FocusNextSameKind) => {
let selection_key =
self.select_prev_or_next_of_same_kind(/*select_previous=*/ false);
StateUpdate::SelectItem {
selection_key,
ensure_in_viewport: true,
}
}
(None, Event::FocusPrevPage) => {
let selection_key = self.select_prev_page(term_height, drawn_rects);
StateUpdate::SelectItem {
Expand Down Expand Up @@ -1309,6 +1334,35 @@ impl<'state, 'input> Recorder<'state, 'input> {
}
}

// Returns the previous or next SelectionKey of the same kind as the current
// selection key. If there are no other keys of the same kind, the current
// key is returned instead. If `select_previous` is true, the previous key
// is returned. Otherwise, the next key is returned.
fn select_prev_or_next_of_same_kind(&self, select_previous: bool) -> SelectionKey {
let (keys, index) = self.find_selection();
let iterate_keys_with_wrap_around = |i| -> Box<dyn DoubleEndedIterator<Item = _>> {
let forward_iter = keys[i + 1..] // Skip the current key
.iter()
.chain(keys[..i].iter());
if select_previous {
Box::new(forward_iter.rev())
} else {
Box::new(forward_iter)
}
};
match index {
None => self.first_selection_key(),
Some(index) => {
match iterate_keys_with_wrap_around(index)
.find(|k| std::mem::discriminant(*k) == std::mem::discriminant(&keys[index]))
{
None => keys[index],
Some(key) => *key,
}
}
}
}

fn select_prev_page(
&self,
term_height: usize,
Expand Down
Loading
Loading