diff --git a/CHANGELOG.md b/CHANGELOG.md index e194222..7cd53ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Procedure when bumping the version number: ### Added - New messages are now marked as unseen - Sub-trees can now be folded +- Key bindings to move to prev/next sibling ### Changed - Improved editor key bindings diff --git a/src/ui/chat/tree.rs b/src/ui/chat/tree.rs index 8ab9f2a..e14a7c7 100644 --- a/src/ui/chat/tree.rs +++ b/src/ui/chat/tree.rs @@ -67,6 +67,7 @@ impl> InnerTreeViewState { pub fn list_movement_key_bindings(&self, bindings: &mut KeyBindingsList) { 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, ctrl+←/→", "move cursor to prev/next unseen message"); bindings.binding("g, home", "move cursor to top"); @@ -82,6 +83,8 @@ impl> InnerTreeViewState { match event { key!('k') | key!(Up) => self.move_cursor_up().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!('l') | key!(Right) => self.move_cursor_newer().await, key!('H') | key!(Ctrl + Left) => self.move_cursor_older_unseen().await, diff --git a/src/ui/chat/tree/cursor.rs b/src/ui/chat/tree/cursor.rs index bc98357..fafa74c 100644 --- a/src/ui/chat/tree/cursor.rs +++ b/src/ui/chat/tree/cursor.rs @@ -240,6 +240,54 @@ impl> InnerTreeViewState { 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) { match &mut self.cursor { Cursor::Msg(id) => { @@ -385,68 +433,6 @@ impl> InnerTreeViewState { } /* - pub async fn move_up_sibling>( - &mut self, - store: &S, - cursor: &mut Option>, - 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>( - &mut self, - store: &S, - cursor: &mut Option>, - 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>( &mut self, store: &S,