Skip to content

Commit

Permalink
feat: use cousin navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
justinpombrio committed May 5, 2024
1 parent d1643ee commit a8a4b8e
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 29 deletions.
20 changes: 9 additions & 11 deletions scripts/init.rhai
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,16 @@ tree_keymap.bind_key("o", "Open", || {
open_file_menu(s::current_dir());
});

tree_keymap.bind_key("left", "InorderPrev", || s::tree_nav_inorder_prev());
tree_keymap.bind_key("right", "InorderNext", || s::tree_nav_inorder_next());
tree_keymap.bind_key("down", "RightSibling", || s::tree_nav_next());
tree_keymap.bind_key("up", "LeftSibling", || s::tree_nav_prev());

tree_keymap.bind_key("j", "LeftSibling", || s::tree_nav_prev());
tree_keymap.bind_key("k", "RightSibling", || s::tree_nav_next());
tree_keymap.bind_key("h", "InorderNext", || s::tree_nav_inorder_prev());
tree_keymap.bind_key("l", "InorderPrev", || s::tree_nav_inorder_next());
tree_keymap.bind_key("k", "Prev", || s::tree_nav_prev());
tree_keymap.bind_key("K", "First", || s::tree_nav_first());
tree_keymap.bind_key("j", "Next", || s::tree_nav_next());
tree_keymap.bind_key("J", "Last", || s::tree_nav_last());
tree_keymap.bind_key("h", "ChildLeft", || s::tree_nav_last_child());
tree_keymap.bind_key("H", "BeforeParent", || s::tree_nav_before_parent());
tree_keymap.bind_key("l", "ChildRight", || s::tree_nav_first_child());
tree_keymap.bind_key("L", "AfterParent", || s::tree_nav_after_parent());

tree_keymap.bind_key(";", "Parent", || s::tree_nav_parent());
tree_keymap.bind_key("J", "First", || s::tree_nav_first());
tree_keymap.bind_key("K", "Last", || s::tree_nav_last());
tree_keymap.bind_key("^", "First", || s::tree_nav_first());
tree_keymap.bind_key("$", "Last", || s::tree_nav_last());

Expand Down
6 changes: 5 additions & 1 deletion src/engine/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ pub enum TreeNavCommand {
/// Move the cursor to the previous location in-order.
InorderPrev,
/// Move the cursor after its parent.
Parent,
AfterParent,
/// Move the cursor before its parent.
BeforeParent,
/// Move the cursor to before the first child of the node after the cursor.
FirstChild,
/// Move the cursor to after the last child of the node before the cursor.
LastChild,
/// If the node before the cursor is texty, enter text mode, placing the cursor at the
Expand Down
17 changes: 11 additions & 6 deletions src/engine/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,10 @@ fn execute_tree_ed(
match cmd {
Insert(node) => match cursor.insert(s, node) {
Ok(None) => Ok(vec![(*cursor, Backspace.into())]),
Ok(Some(detached_node)) => {
Ok(vec![(cursor.prev(s).bug(), Insert(detached_node).into())])
}
Ok(Some(detached_node)) => Ok(vec![(
cursor.prev_sibling(s).bug(),
Insert(detached_node).into(),
)]),
Err(()) => Err(EditError::CannotPlaceNode),
},
Replace(new_node) => {
Expand Down Expand Up @@ -378,14 +379,18 @@ fn execute_tree_nav(
}

let new_loc = match cmd {
Prev => cursor.prev(s),
Next => cursor.next(s),
Prev => cursor.prev_cousin(s),
Next => cursor.next_cousin(s),
First => cursor.first(s),
Last => cursor.last(s),
Parent => cursor.after_parent(s),
BeforeParent => cursor.before_parent(s),
AfterParent => cursor.after_parent(s),
LastChild => cursor
.left_node(s)
.and_then(|node| Location::after_children(s, node)),
FirstChild => cursor
.right_node(s)
.and_then(|node| Location::before_children(s, node)),
InorderNext => cursor.inorder_next(s),
InorderPrev => cursor.inorder_prev(s),
EnterText => cursor
Expand Down
16 changes: 15 additions & 1 deletion src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,22 @@ impl<F: Frontend<Style = Style> + 'static> Runtime<F> {
rt,
TreeNavCommand::InorderPrev as tree_nav_inorder_prev
);
register!(
module,
rt,
TreeNavCommand::FirstChild as tree_nav_first_child
);
register!(module, rt, TreeNavCommand::LastChild as tree_nav_last_child);
register!(module, rt, TreeNavCommand::Parent as tree_nav_parent);
register!(
module,
rt,
TreeNavCommand::BeforeParent as tree_nav_before_parent
);
register!(
module,
rt,
TreeNavCommand::AfterParent as tree_nav_after_parent
);
register!(module, rt, TreeNavCommand::EnterText as tree_nav_enter_text);

// Editing: Tree Ed
Expand Down
4 changes: 2 additions & 2 deletions src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,9 @@ impl ColorTheme {
/// The "default dark" Base16 colorscheme, by Chris Kempson (http://chriskempson.com)
pub fn default_dark() -> ColorTheme {
ColorTheme {
base00: Rgb::from_hex("#312121").bug(),
base00: Rgb::from_hex("#103030").bug(),
base01: Rgb::from_hex("#111111").bug(),
base02: Rgb::from_hex("#103030").bug(),
base02: Rgb::from_hex("#312121").bug(),
base03: Rgb::from_hex("#585858").bug(),
base04: Rgb::from_hex("#b8b8b8").bug(),
base05: Rgb::from_hex("#d8d8d8").bug(),
Expand Down
4 changes: 2 additions & 2 deletions src/tree/forest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl<D> Forest<D> {
}

/// Get the `node`'s previous sibling, if any.
pub fn prev(&self, node: NodeIndex) -> Option<NodeIndex> {
pub fn prev_sibling(&self, node: NodeIndex) -> Option<NodeIndex> {
if self.is_first(node) {
None
} else {
Expand All @@ -117,7 +117,7 @@ impl<D> Forest<D> {
}

/// Get the `node`'s next sibling, if any.
pub fn next(&self, node: NodeIndex) -> Option<NodeIndex> {
pub fn next_sibling(&self, node: NodeIndex) -> Option<NodeIndex> {
if self.is_last(node) {
None
} else {
Expand Down
33 changes: 31 additions & 2 deletions src/tree/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,36 @@ impl Location {
* Navigation *
**************/

pub fn prev(self, s: &Storage) -> Option<Location> {
pub fn prev_cousin(self, s: &Storage) -> Option<Location> {
use LocationInner::{AfterNode, BeforeNode, BelowNode, InText};

match self.0 {
InText(_, _) => return None,
AfterNode(node) => return Some(Location::before(s, node)),
BeforeNode(_) | BelowNode(_) => (),
}

Location::after_children(s, self.parent_node(s)?.prev_cousin(s)?)
}

pub fn next_cousin(self, s: &Storage) -> Option<Location> {
use LocationInner::{AfterNode, BeforeNode, BelowNode, InText};

match self.0 {
InText(_, _) => return None,
BeforeNode(node) => return Some(Location::after(s, node)),
AfterNode(node) => {
if let Some(sibling) = node.next_sibling(s) {
return Some(Location::after(s, sibling));
}
}
BelowNode(_) => (),
}

Location::before_children(s, self.parent_node(s)?.next_cousin(s)?)
}

pub fn prev_sibling(self, s: &Storage) -> Option<Location> {
use LocationInner::{AfterNode, BeforeNode, BelowNode, InText};

match self.0 {
Expand All @@ -154,7 +183,7 @@ impl Location {
}
}

pub fn next(self, s: &Storage) -> Option<Location> {
pub fn next_sibling(self, s: &Storage) -> Option<Location> {
use LocationInner::{AfterNode, BeforeNode, BelowNode, InText};

match self.0 {
Expand Down
42 changes: 38 additions & 4 deletions src/tree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,12 @@ impl Node {
s.forest().nth_child(self.0, n).map(Node)
}

pub fn next_sibling(self, s: &Storage) -> Option<Node> {
s.forest().next(self.0).map(Node)
pub fn prev_sibling(self, s: &Storage) -> Option<Node> {
s.forest().prev_sibling(self.0).map(Node)
}

pub fn prev_sibling(self, s: &Storage) -> Option<Node> {
s.forest().prev(self.0).map(Node)
pub fn next_sibling(self, s: &Storage) -> Option<Node> {
s.forest().next_sibling(self.0).map(Node)
}

pub fn first_sibling(self, s: &Storage) -> Node {
Expand All @@ -275,6 +275,40 @@ impl Node {
Node(s.forest().last_sibling(self.0))
}

pub fn prev_cousin(self, s: &Storage) -> Option<Node> {
let mut level = 0;
let mut grandparent = self;
loop {
if let Some(great_aunt) = grandparent.prev_sibling(s) {
let mut cousin = great_aunt;
for _ in 0..level {
cousin = cousin.last_child(s)?;
}
return Some(cousin);
} else {
grandparent = grandparent.parent(s)?;
level += 1;
}
}
}

pub fn next_cousin(self, s: &Storage) -> Option<Node> {
let mut level = 0;
let mut grandparent = self;
loop {
if let Some(great_aunt) = grandparent.next_sibling(s) {
let mut cousin = great_aunt;
for _ in 0..level {
cousin = cousin.first_child(s)?;
}
return Some(cousin);
} else {
grandparent = grandparent.parent(s)?;
level += 1;
}
}
}

pub fn root(self, s: &Storage) -> Node {
Node(s.forest().root(self.0))
}
Expand Down

0 comments on commit a8a4b8e

Please sign in to comment.