Move cursor to prev/next sibling
This commit is contained in:
parent
d65183e0ae
commit
a4b79d4e81
3 changed files with 52 additions and 62 deletions
|
|
@ -17,6 +17,7 @@ Procedure when bumping the version number:
|
||||||
### Added
|
### Added
|
||||||
- New messages are now marked as unseen
|
- New messages are now marked as unseen
|
||||||
- Sub-trees can now be folded
|
- Sub-trees can now be folded
|
||||||
|
- Key bindings to move to prev/next sibling
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Improved editor key bindings
|
- Improved editor key bindings
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ impl<M: Msg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
|
|
||||||
pub fn list_movement_key_bindings(&self, bindings: &mut KeyBindingsList) {
|
pub fn list_movement_key_bindings(&self, bindings: &mut KeyBindingsList) {
|
||||||
bindings.binding("j/k, ↓/↑", "move cursor up/down");
|
bindings.binding("j/k, ↓/↑", "move cursor up/down");
|
||||||
|
bindings.binding("J/K, ctrl+↓/↑", "move cursor to prev/next sibling");
|
||||||
bindings.binding("h/l, ←/→", "move cursor chronologically");
|
bindings.binding("h/l, ←/→", "move cursor chronologically");
|
||||||
bindings.binding("H/L, ctrl+←/→", "move cursor to prev/next unseen message");
|
bindings.binding("H/L, ctrl+←/→", "move cursor to prev/next unseen message");
|
||||||
bindings.binding("g, home", "move cursor to top");
|
bindings.binding("g, home", "move cursor to top");
|
||||||
|
|
@ -82,6 +83,8 @@ impl<M: Msg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
match event {
|
match event {
|
||||||
key!('k') | key!(Up) => self.move_cursor_up().await,
|
key!('k') | key!(Up) => self.move_cursor_up().await,
|
||||||
key!('j') | key!(Down) => self.move_cursor_down().await,
|
key!('j') | key!(Down) => self.move_cursor_down().await,
|
||||||
|
key!('K') | key!(Ctrl + Up) => self.move_cursor_up_sibling().await,
|
||||||
|
key!('J') | key!(Ctrl + Down) => self.move_cursor_down_sibling().await,
|
||||||
key!('h') | key!(Left) => self.move_cursor_older().await,
|
key!('h') | key!(Left) => self.move_cursor_older().await,
|
||||||
key!('l') | key!(Right) => self.move_cursor_newer().await,
|
key!('l') | key!(Right) => self.move_cursor_newer().await,
|
||||||
key!('H') | key!(Ctrl + Left) => self.move_cursor_older_unseen().await,
|
key!('H') | key!(Ctrl + Left) => self.move_cursor_older_unseen().await,
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,54 @@ impl<M: Msg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
self.correction = Some(Correction::MakeCursorVisible);
|
self.correction = Some(Correction::MakeCursorVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn move_cursor_up_sibling(&mut self) {
|
||||||
|
match &mut self.cursor {
|
||||||
|
Cursor::Bottom | Cursor::Pseudo { parent: None, .. } => {
|
||||||
|
if let Some(last_tree_id) = self.store.last_tree_id().await {
|
||||||
|
self.cursor = Cursor::Msg(last_tree_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Cursor::Msg(ref mut msg) => {
|
||||||
|
let path = self.store.path(msg).await;
|
||||||
|
let mut tree = self.store.tree(path.first()).await;
|
||||||
|
Self::find_prev_sibling(&self.store, &mut tree, msg).await;
|
||||||
|
}
|
||||||
|
Cursor::Editor { .. } => {}
|
||||||
|
Cursor::Pseudo {
|
||||||
|
parent: Some(parent),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let path = self.store.path(parent).await;
|
||||||
|
let tree = self.store.tree(path.first()).await;
|
||||||
|
if let Some(children) = tree.children(parent) {
|
||||||
|
if let Some(last_child) = children.last() {
|
||||||
|
self.cursor = Cursor::Msg(last_child.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.correction = Some(Correction::MakeCursorVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn move_cursor_down_sibling(&mut self) {
|
||||||
|
match &mut self.cursor {
|
||||||
|
Cursor::Msg(ref mut msg) => {
|
||||||
|
let path = self.store.path(msg).await;
|
||||||
|
let mut tree = self.store.tree(path.first()).await;
|
||||||
|
if !Self::find_next_sibling(&self.store, &mut tree, msg).await
|
||||||
|
&& tree.parent(msg).is_none()
|
||||||
|
{
|
||||||
|
self.cursor = Cursor::Bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Cursor::Pseudo { parent: None, .. } => {
|
||||||
|
self.cursor = Cursor::Bottom;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
self.correction = Some(Correction::MakeCursorVisible);
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn move_cursor_older(&mut self) {
|
pub async fn move_cursor_older(&mut self) {
|
||||||
match &mut self.cursor {
|
match &mut self.cursor {
|
||||||
Cursor::Msg(id) => {
|
Cursor::Msg(id) => {
|
||||||
|
|
@ -385,68 +433,6 @@ impl<M: Msg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub async fn move_up_sibling<S: MsgStore<M>>(
|
|
||||||
&mut self,
|
|
||||||
store: &S,
|
|
||||||
cursor: &mut Option<Cursor<M::Id>>,
|
|
||||||
frame: &mut Frame,
|
|
||||||
size: Size,
|
|
||||||
) {
|
|
||||||
let old_blocks = self
|
|
||||||
.layout_blocks(store, cursor.as_ref(), frame, size)
|
|
||||||
.await;
|
|
||||||
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
|
||||||
let path = store.path(&cursor.id).await;
|
|
||||||
let mut tree = store.tree(path.first()).await;
|
|
||||||
self.find_prev_sibling(store, &mut tree, &mut cursor.id)
|
|
||||||
.await;
|
|
||||||
} else if let Some(last_tree) = store.last_tree().await {
|
|
||||||
// I think moving to the root of the last tree makes the most sense
|
|
||||||
// here. Alternatively, we could just not move the cursor, but that
|
|
||||||
// wouldn't be very useful.
|
|
||||||
*cursor = Some(Cursor::new(last_tree));
|
|
||||||
}
|
|
||||||
// If neither condition holds, we can't set a cursor because there's no
|
|
||||||
// message to move to.
|
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
|
||||||
self.correct_cursor_offset(store, frame, size, &old_blocks, &old_cursor_id, cursor)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn move_down_sibling<S: MsgStore<M>>(
|
|
||||||
&mut self,
|
|
||||||
store: &S,
|
|
||||||
cursor: &mut Option<Cursor<M::Id>>,
|
|
||||||
frame: &mut Frame,
|
|
||||||
size: Size,
|
|
||||||
) {
|
|
||||||
let old_blocks = self
|
|
||||||
.layout_blocks(store, cursor.as_ref(), frame, size)
|
|
||||||
.await;
|
|
||||||
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
|
||||||
let path = store.path(&cursor.id).await;
|
|
||||||
let mut tree = store.tree(path.first()).await;
|
|
||||||
self.find_next_sibling(store, &mut tree, &mut cursor.id)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
// If that condition doesn't hold, we're already at the bottom in
|
|
||||||
// cursor-less mode and can't move further down anyways.
|
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
|
||||||
self.correct_cursor_offset(store, frame, size, &old_blocks, &old_cursor_id, cursor)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO move_older[_unseen]
|
|
||||||
// TODO move_newer[_unseen]
|
|
||||||
|
|
||||||
pub async fn center_cursor<S: MsgStore<M>>(
|
pub async fn center_cursor<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
store: &S,
|
store: &S,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue