Make p paste as children and P as siblings below

After trying part 8c, the user found p and P doing the same thing on the
canvas: both pasted a sibling below the node (P only differed in the
outline's order). Their pick: p pastes under the node, as its last
children, the way a adds a child; P pastes the next siblings, below it,
where o adds one. ]p went away, since p does what it did.

Inside a title p and P still paste after and before the text cursor, as
in vim: they're their own commands (paste-after, paste-before), and the
node ones are paste-as-child and paste-as-sibling.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
skkeyeandClaude Opus 5.5 committed 2026-10-02 05:05:00 -04:00
1 parent 7bec5bf3fc
commit bd819409f4
10 files changed
+59 -53

No files matched your search

+6 -4
View File
@@ -157,9 +157,11 @@ lines.
- A register holds text or nodes, and either pastes anywhere: nodes pasted - A register holds text or nodes, and either pastes anywhere: nodes pasted
into a text give their titles, text pasted on nodes becomes nodes. `yy`, into a text give their titles, text pasted on nodes becomes nodes. `yy`,
`yab`, `yib` yank nodes; every delete (`dd`, `x`, `dib`, `d` on a `yab`, `yib` yank nodes; every delete (`dd`, `x`, `dib`, `d` on a
selection) keeps what it took, so `dd` then `p` moves a branch. `p` `P` selection) keeps what it took, so `dd` then `p` moves a branch. `p`
`]p` paste after, before, or as the last children, keeping the yanked pastes as the node's last children and `P` as its next siblings (the
layout, where a new node would go; a count pastes copies. Links between user's pick after trying part 8c: `p` goes under the node as `a` adds,
`P` below it as `o` adds), keeping the yanked layout, where a new node
would go; a count pastes copies. Links between
the pasted nodes come along, and so do links to nodes still there when the pasted nodes come along, and so do links to nodes still there when
they go back into the document they came from. they go back into the document they came from.
- `"+` is the system clipboard. Nodes go there as Markdown, the user's - `"+` is the system clipboard. Nodes go there as Markdown, the user's
@@ -421,7 +423,7 @@ text).
| **Move** (every view) | `hjkl` or arrows · `gh gj gk gl` tree moves · `w` `b` next / previous in reading order · `gg` root · `G` last · `/` `n` `N` search · `Ctrl-o` `Ctrl-i` (Tab) jump back / forward · `m{a-z}` `'{a-z}` marks (`A–Z` across documents) · Enter or `gf` through a portal · `gd` follow a cross-link | | **Move** (every view) | `hjkl` or arrows · `gh gj gk gl` tree moves · `w` `b` next / previous in reading order · `gg` root · `G` last · `/` `n` `N` search · `Ctrl-o` `Ctrl-i` (Tab) jump back / forward · `m{a-z}` `'{a-z}` marks (`A–Z` across documents) · Enter or `gf` through a portal · `gd` follow a cross-link |
| **View** | `zz` center · `Ctrl-e` `Ctrl-y` `zh` `zl` pan · `Ctrl-d` `Ctrl-u` half a screen · `+` `-` zoom · `za zo zc zR zM` folds · `zf` Auto · `zi` focus · `K` body card | | **View** | `zz` center · `Ctrl-e` `Ctrl-y` `zh` `zl` pan · `Ctrl-d` `Ctrl-u` half a screen · `+` `-` zoom · `za zo zc zR zM` folds · `zf` Auto · `zi` focus · `K` body card |
| **Create and edit** | `o` `O` sibling below / above · `a` child · `i` `A` Enter edit the title · `I` edit from its start · `cc` `S` retype | | **Create and edit** | `o` `O` sibling below / above · `a` child · `i` `A` Enter edit the title · `I` edit from its start · `cc` `S` retype |
| **Operators** | `dd` or `dab` delete branch · `dib` delete children · `x` delete just the node · `yy` `yab` `yib` yank · `p` `P` paste after / before · `]p` paste as child · `>>` `<<` indent / outdent · `"a`–`"z` and `"+` registers · `.` repeat · `u` `Ctrl-r` undo / redo | | **Operators** | `dd` or `dab` delete branch · `dib` delete children · `x` delete just the node · `yy` `yab` `yib` yank · `p` paste as children · `P` paste as siblings below · `>>` `<<` indent / outdent · `"a`–`"z` and `"+` registers · `.` repeat · `u` `Ctrl-r` undo / redo |
| **Modes** | `v` `V` visual · `M` move · `C` connect · `:` command · Esc back to normal | | **Modes** | `v` `V` visual · `M` move · `C` connect · `:` command · Esc back to normal |
| **Leader** `<Space>` | `c` color · `s` style · `B` border · `t` tags · `p` new portal · `i` inbox · `b` documents · `v` then `c`/`o`/`n` for canvas / outline / note · `w` which-key on/off · `?` help | | **Leader** `<Space>` | `c` color · `s` style · `B` border · `t` tags · `p` new portal · `i` inbox · `b` documents · `v` then `c`/`o`/`n` for canvas / outline / note · `w` which-key on/off · `?` help |
| **Panes, documents** | `Ctrl-w v` `Ctrl-w s` split · `Ctrl-w hjkl` focus · `Ctrl-w w` the next pane · `Ctrl-w c` close · `Ctrl-w o` only · `Ctrl-w =` even sizes · `gt` `gT` `]b` `[b` next / previous document · `ZZ` close pane (the last one quits) | | **Panes, documents** | `Ctrl-w v` `Ctrl-w s` split · `Ctrl-w hjkl` focus · `Ctrl-w w` the next pane · `Ctrl-w c` close · `Ctrl-w o` only · `Ctrl-w =` even sizes · `gt` `gT` `]b` `[b` next / previous document · `ZZ` close pane (the last one quits) |
+1 -1
View File
@@ -72,7 +72,7 @@ The plan for the everyday keys (all of them are in DESIGN.md):
| `o` `O` `a` | new sibling below / above, new child: type its title, Enter for the next one | | `o` `O` `a` | new sibling below / above, new child: type its title, Enter for the next one |
| `i` or Enter | edit the title (Esc: vim keys inside it, Esc again: done) | | `i` or Enter | edit the title (Esc: vim keys inside it, Esc again: done) |
| `dd` `x` | delete the branch / just the node (kept in a register, as in vim) | | `dd` `x` | delete the branch / just the node (kept in a register, as in vim) |
| `yy` `p` `P` `]p` | yank the branch / paste after, before, as a child (`dd` then `p` moves a branch) | | `yy` `p` `P` | yank the branch / paste as children, or as siblings below (`dd` then `p` moves a branch) |
| `"a` `"+` | before `y`, `d` or `p`: register `a`; `"+` is the system clipboard (nodes go there as Markdown) | | `"a` `"+` | before `y`, `d` or `p`: register `a`; `"+` is the system clipboard (nodes go there as Markdown) |
| `.` | the last change again | | `.` | the last change again |
| `>>` `<<` | under the node above / out a level | | `>>` `<<` | under the node above / out a level |
+6 -7
View File
@@ -145,7 +145,7 @@ pub enum AppAction {
nodes: Vec<NodeId>, nodes: Vec<NodeId>,
branches: bool, branches: bool,
}, },
/// Paste what a register holds (`p`, `P`, `]p`): its nodes, or its text /// Paste what a register holds (`p`, `P`): its nodes, or its text
/// made into nodes, `times` copies. /// made into nodes, `times` copies.
Paste { Paste {
register: Option<Register>, register: Option<Register>,
@@ -256,15 +256,14 @@ pub enum AppAction {
Say(Message), Say(Message),
} }
/// Where `p` and its kin paste, from the cursor's node. /// Where `p` and `P` paste, from the cursor's node (the user's pick after
/// trying part 8c: `p` pastes under the node, as `a` adds).
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PasteAt { pub enum PasteAt {
/// Its next siblings (`p`). /// Its last children (`p`).
After,
/// Its siblings before it (`P`).
Before,
/// Its last children (`]p`).
Child, Child,
/// Its next siblings, below it, where `o` adds one (`P`).
Sibling,
} }
/// What `:w` and its kin save. /// What `:w` and its kin save.
+7 -9
View File
@@ -64,13 +64,12 @@ pub fn shared(typed: &Typed, ctx: &ViewContext<'_>) -> Option<Vec<Action>> {
app(AppAction::Yank { register: typed.register, nodes: children.to_vec(), branches: true }) app(AppAction::Yank { register: typed.register, nodes: children.to_vec(), branches: true })
} }
}, },
Command::PasteAfter => app(AppAction::Paste { register: typed.register, at: PasteAt::After, times }),
Command::PasteBefore => {
app(AppAction::Paste { register: typed.register, at: PasteAt::Before, times })
}
Command::PasteAsChild => { Command::PasteAsChild => {
app(AppAction::Paste { register: typed.register, at: PasteAt::Child, times }) app(AppAction::Paste { register: typed.register, at: PasteAt::Child, times })
} }
Command::PasteAsSibling => {
app(AppAction::Paste { register: typed.register, at: PasteAt::Sibling, times })
}
Command::Operate(Operator::Indent, Target::Current) => indent(ctx, &siblings(ctx, times), None), Command::Operate(Operator::Indent, Target::Current) => indent(ctx, &siblings(ctx, times), None),
Command::Operate(Operator::Outdent, Target::Current) => outdent(ctx, &siblings(ctx, times), None), Command::Operate(Operator::Outdent, Target::Current) => outdent(ctx, &siblings(ctx, times), None),
Command::ToggleFold => toggle_fold(ctx), Command::ToggleFold => toggle_fold(ctx),
@@ -415,17 +414,16 @@ fn delete_children(ctx: &ViewContext<'_>, register: Option<Register>) -> Vec<Act
] ]
} }
/// `p`, `P` and `]p`: copies of a clip around the cursor's node, placed /// `p` and `P`: copies of a clip under the cursor's node or after it,
/// where a new sibling or child would go, one below the other, each keeping /// placed where a new child or sibling would go, one below the other, each
/// the clip's own layout. /// keeping the clip's own layout.
pub fn paste(ctx: &ViewContext<'_>, clip: Clip, at: PasteAt, times: u32) -> Option<EditOp> { pub fn paste(ctx: &ViewContext<'_>, clip: Clip, at: PasteAt, times: u32) -> Option<EditOp> {
let (doc, cursor) = (ctx.doc, ctx.cursor); let (doc, cursor) = (ctx.doc, ctx.cursor);
let bounds = clip.bounds(|node| ctx.box_size(node))?; let bounds = clip.bounds(|node| ctx.box_size(node))?;
let rects = ctx.box_rects(); let rects = ctx.box_rects();
let (spot, start) = match at { let (spot, start) = match at {
PasteAt::After => (Spot::After(cursor), below_spot(cursor, bounds.size, &rects)),
PasteAt::Before => (Spot::Before(cursor), below_spot(cursor, bounds.size, &rects)),
PasteAt::Child => (Spot::LastChildOf(cursor), child_spot(doc, cursor, bounds.size, &rects)), PasteAt::Child => (Spot::LastChildOf(cursor), child_spot(doc, cursor, bounds.size, &rects)),
PasteAt::Sibling => (Spot::After(cursor), below_spot(cursor, bounds.size, &rects)),
}; };
let mut offsets = Vec::new(); let mut offsets = Vec::new();
let mut pos = start; let mut pos = start;
+3 -3
View File
@@ -494,8 +494,8 @@ impl Popup {
Popup::Menu(Runs { list, runs }) Popup::Menu(Runs { list, runs })
} }
/// `:registers`: what each register holds. Enter pastes it after the /// `:registers`: what each register holds. Enter pastes it under the
/// cursor's node. /// cursor's node, as `p` does.
pub fn registers(registers: &[(char, String)], theme: &Theme) -> Popup { pub fn registers(registers: &[(char, String)], theme: &Theme) -> Popup {
let key = Style::new().fg(theme.accent).add_modifier(Modifier::BOLD); let key = Style::new().fg(theme.accent).add_modifier(Modifier::BOLD);
let muted = Style::new().fg(theme.muted); let muted = Style::new().fg(theme.muted);
@@ -507,7 +507,7 @@ impl Popup {
rows.push(ListRow::new(spans, what)); rows.push(ListRow::new(spans, what));
runs.push(Run::Keys(vec![Key::char('"'), Key::char(name), Key::char('p')])); runs.push(Run::Keys(vec![Key::char('"'), Key::char(name), Key::char('p')]));
} }
let footer = "Enter: paste it after the cursor's node · Esc: close"; let footer = "Enter: paste it under the cursor's node · Esc: close";
let list = ListPopup::new("registers", footer, rows, Place::Center { width: CONFLICT_WIDTH }); let list = ListPopup::new("registers", footer, rows, Place::Center { width: CONFLICT_WIDTH });
Popup::Menu(Runs { list, runs }) Popup::Menu(Runs { list, runs })
} }
+24 -22
View File
@@ -17,18 +17,18 @@ fn yank_and_paste_nodes() {
// yy on Raised beds: the node and its branch. // yy on Raised beds: the node and its branch.
h.type_keys("glgjyy"); h.type_keys("glgjyy");
assert_eq!(h.message(), "yanked 3 nodes"); assert_eq!(h.message(), "yanked 3 nodes");
// p on Watering: the copy goes after it, with its children. // P on Watering: the copy goes after it, with its children.
h.type_keys("gjp"); h.type_keys("gjP");
assert_eq!(top(&h), ["Soil", "Raised beds", "Watering", "Raised beds", "Kitchen"]); assert_eq!(top(&h), ["Soil", "Raised beds", "Watering", "Raised beds", "Kitchen"]);
let copy = h.doc().children(h.node("Garden plans"))[3]; let copy = h.doc().children(h.node("Garden plans"))[3];
assert_eq!(h.app.current().cursor(), copy, "the cursor goes to what was pasted"); assert_eq!(h.app.current().cursor(), copy, "the cursor goes to what was pasted");
let titles: Vec<String> = h.doc().children(copy).iter().map(|&id| h.title(id)).collect(); let titles: Vec<String> = h.doc().children(copy).iter().map(|&id| h.title(id)).collect();
assert_eq!(titles, ["Cedar, untreated", "40 cm high"]); assert_eq!(titles, ["Cedar, untreated", "40 cm high"]);
assert_eq!(h.doc().node(copy).unwrap().look.color.as_ref().map(|c| c.as_str()), Some("orange")); assert_eq!(h.doc().node(copy).unwrap().look.color.as_ref().map(|c| c.as_str()), Some("orange"));
// ]p: as the last children; 2p: two copies. // p: as the last children; 2P: two copies.
h.type_keys("gg]p"); h.type_keys("ggp");
assert_eq!(top(&h).len(), 6); assert_eq!(top(&h).len(), 6);
h.type_keys("u2p"); h.type_keys("u2P");
assert_eq!(h.message(), "pasted 6 nodes"); assert_eq!(h.message(), "pasted 6 nodes");
assert_eq!(top(&h), ["Soil", "Raised beds", "Watering", "Raised beds", "Kitchen"]); assert_eq!(top(&h), ["Soil", "Raised beds", "Watering", "Raised beds", "Kitchen"]);
assert_eq!(h.doc().loose().len(), 4, "after the root: loose nodes, before the two there were"); assert_eq!(h.doc().loose().len(), 4, "after the root: loose nodes, before the two there were");
@@ -39,32 +39,34 @@ fn yank_and_paste_nodes() {
#[test] #[test]
fn deletes_keep_what_they_take() { fn deletes_keep_what_they_take() {
let mut h = Harness::new(); let mut h = Harness::new();
// dd then p: the branch moves. // dd then P: the branch moves, after Watering.
h.type_keys("glgjdd"); h.type_keys("glgjdd");
assert_eq!(h.cursor(), "Watering"); assert_eq!(h.cursor(), "Watering");
h.type_keys("p"); h.type_keys("P");
assert_eq!(top(&h), ["Soil", "Watering", "Raised beds", "Kitchen"]); assert_eq!(top(&h), ["Soil", "Watering", "Raised beds", "Kitchen"]);
assert_eq!(h.children("Raised beds"), ["Cedar, untreated", "40 cm high"]); assert_eq!(h.children("Raised beds"), ["Cedar, untreated", "40 cm high"]);
// x keeps just the node: its children stay behind. // x keeps just the node: its children stay behind.
h.type_keys("x"); h.type_keys("x");
assert_eq!(top(&h), ["Soil", "Watering", "Cedar, untreated", "40 cm high", "Kitchen"]); assert_eq!(top(&h), ["Soil", "Watering", "Cedar, untreated", "40 cm high", "Kitchen"]);
h.type_keys("ggP"); // p: under the node, as its last child.
assert_eq!(h.message(), "nothing goes before the root"); h.type_keys("ggglp");
h.type_keys("glP"); assert_eq!(h.children("Soil"), ["Raised beds"]);
assert_eq!(top(&h)[0], "Raised beds", "P: before Soil");
assert!(h.children("Raised beds").is_empty()); assert!(h.children("Raised beds").is_empty());
// P on the root: a loose node, where o adds one.
h.type_keys("ggP");
assert_eq!((h.cursor().as_str(), h.doc().loose().len()), ("Raised beds", 3));
// Named registers, and the black hole. // Named registers, and the black hole.
h.type_keys("gl\"ayy"); h.type_keys("\"ayy");
assert_eq!(h.message(), "yanked 1 node into \"a"); assert_eq!(h.message(), "yanked 1 node into \"a");
h.type_keys("gj\"_dd"); h.type_keys("gggl\"_x");
assert_eq!(h.message(), "deleted 1 node · u to undo"); assert_eq!(h.message(), "deleted 1 node · u to undo");
h.type_keys("gg]p"); h.type_keys("ggp");
assert_eq!( assert_eq!(
h.children("Garden plans").last().map(String::as_str), h.children("Garden plans").last().map(String::as_str),
Some("Raised beds"), Some("Raised beds"),
"\"_ kept nothing" "\"_ kept nothing"
); );
h.type_keys("gg\"a]p"); h.type_keys("gg\"ap");
assert_eq!(h.children("Garden plans").iter().filter(|title| *title == "Raised beds").count(), 3); assert_eq!(h.children("Garden plans").iter().filter(|title| *title == "Raised beds").count(), 3);
} }
@@ -81,7 +83,7 @@ fn the_clipboard_holds_markdown() {
assert_eq!(h.doc().node(pasted).unwrap().look.color.as_ref().map(|c| c.as_str()), Some("orange")); assert_eq!(h.doc().node(pasted).unwrap().look.color.as_ref().map(|c| c.as_str()), Some("orange"));
// Text another app put there: a node per section, tags and body too. // Text another app put there: a node per section, tags and body too.
h.app.registers.clipboard().write("## Mulch\n---\n- todo\n---\nStraw or leaves.\n\n### Straw\n").unwrap(); h.app.registers.clipboard().write("## Mulch\n---\n- todo\n---\nStraw or leaves.\n\n### Straw\n").unwrap();
h.type_keys("gg\"+]p"); h.type_keys("gg\"+p");
assert_eq!(h.cursor(), "Mulch"); assert_eq!(h.cursor(), "Mulch");
assert_eq!((h.tags("Mulch").as_str(), h.body("Mulch").as_str()), ("#todo", "Straw or leaves.")); assert_eq!((h.tags("Mulch").as_str(), h.body("Mulch").as_str()), ("#todo", "Straw or leaves."));
assert_eq!(h.children("Mulch"), ["Straw"]); assert_eq!(h.children("Mulch"), ["Straw"]);
@@ -97,9 +99,9 @@ fn text_and_nodes_paste_into_each_other() {
// A word yanked in a title, pasted on nodes: a node. // A word yanked in a title, pasted on nodes: a node.
h.type_keys("gli<Esc>yiw<Esc>ggp"); h.type_keys("gli<Esc>yiw<Esc>ggp");
assert_eq!(h.cursor(), "Soil"); assert_eq!(h.cursor(), "Soil");
assert_eq!(h.doc().loose().len(), 3, "after the root: a loose node"); assert_eq!(top(&h).last().map(String::as_str), Some("Soil"), "under the root, at the end");
// Nodes pasted into a title: their titles. // Nodes pasted into a title: their titles.
h.type_keys("gg]pu"); h.type_keys("ggpu");
h.type_keys("glgjyyggi <Esc>p"); h.type_keys("glgjyyggi <Esc>p");
assert_eq!(h.draft(), "Garden plans Raised beds Cedar, untreated 40 cm high"); assert_eq!(h.draft(), "Garden plans Raised beds Cedar, untreated 40 cm high");
} }
@@ -141,10 +143,10 @@ fn visual_mode_takes_in_a_rectangle() {
h.type_keys("d"); h.type_keys("d");
assert_eq!(top(&h), ["Kitchen"]); assert_eq!(top(&h), ["Kitchen"]);
assert_eq!(h.message(), "deleted 8 nodes · u to undo"); assert_eq!(h.message(), "deleted 8 nodes · u to undo");
// What went is in the register: ]p puts it back under the root, where // What went is in the register: p puts it back under the root, where
// the cursor went. // the cursor went.
assert_eq!(h.cursor(), "Garden plans"); assert_eq!(h.cursor(), "Garden plans");
h.type_keys("]p"); h.type_keys("p");
assert_eq!(top(&h), ["Kitchen", "Soil", "Raised beds", "Watering"]); assert_eq!(top(&h), ["Kitchen", "Soil", "Raised beds", "Watering"]);
} }
@@ -393,9 +395,9 @@ fn registers_list_and_paste() {
let screen = h.screen(); let screen = h.screen();
assert!(screen.contains("\"a 1 node") && screen.contains("\"b 3 nodes"), "{screen}"); assert!(screen.contains("\"a 1 node") && screen.contains("\"b 3 nodes"), "{screen}");
assert!(screen.contains("\"+ the system clipboard")); assert!(screen.contains("\"+ the system clipboard"));
// Enter on "a: pasted after the cursor's node. // Enter on "a: pasted under the cursor's node.
h.type_keys("j<CR>"); h.type_keys("j<CR>");
assert_eq!(top(&h), ["Soil", "Raised beds", "Soil", "Watering", "Kitchen"]); assert_eq!(h.children("Raised beds"), ["Cedar, untreated", "40 cm high", "Soil"]);
} }
#[test] #[test]
+1 -1
View File
@@ -1,5 +1,5 @@
//! Nodes into registers and back: `yy` and the deletes keep nodes in a //! Nodes into registers and back: `yy` and the deletes keep nodes in a
//! register, `p` `P` `]p` paste them (or a register's text, made into //! register, `p` and `P` paste them (or a register's text, made into
//! nodes). See [`registers`](super::registers). //! nodes). See [`registers`](super::registers).
use std::collections::BTreeSet; use std::collections::BTreeSet;
+2 -3
View File
@@ -208,9 +208,8 @@ const NORMAL: &[DefaultBinding] = &[
operator("y", Op::Yank), operator("y", Op::Yank),
operator(">", Op::Indent), operator(">", Op::Indent),
operator("<lt>", Op::Outdent), operator("<lt>", Op::Outdent),
bind("p", C::PasteAfter), bind("p", C::PasteAsChild),
bind("P", C::PasteBefore), bind("P", C::PasteAsSibling),
bind("]p", C::PasteAsChild),
bind("u", C::Undo), bind("u", C::Undo),
bind("<C-r>", C::Redo), bind("<C-r>", C::Redo),
bind(".", C::Repeat), bind(".", C::Repeat),
+7 -1
View File
@@ -254,9 +254,14 @@ pub enum Command {
EditBodyAtStart, EditBodyAtStart,
/// `x`: delete just this node; its children move up. /// `x`: delete just this node; its children move up.
DeleteNode, DeleteNode,
/// Inside text: paste after the text cursor.
PasteAfter, PasteAfter,
/// Inside text: paste before the text cursor.
PasteBefore, PasteBefore,
/// `p` on nodes: paste as the node's last children.
PasteAsChild, PasteAsChild,
/// `P` on nodes: paste as the node's next siblings.
PasteAsSibling,
Undo, Undo,
Redo, Redo,
Repeat, Repeat,
@@ -468,7 +473,8 @@ pub const COMMANDS: &[CommandInfo] = &[
info("outdent-selection", C::Operate(Op::Outdent, Target::Selection), "outdent the selection"), info("outdent-selection", C::Operate(Op::Outdent, Target::Selection), "outdent the selection"),
info("paste-after", C::PasteAfter, "paste after"), info("paste-after", C::PasteAfter, "paste after"),
info("paste-before", C::PasteBefore, "paste before"), info("paste-before", C::PasteBefore, "paste before"),
info("paste-as-child", C::PasteAsChild, "paste as a child"), info("paste-as-child", C::PasteAsChild, "paste as children"),
info("paste-as-sibling", C::PasteAsSibling, "paste as siblings below"),
info("undo", C::Undo, "undo"), info("undo", C::Undo, "undo"),
info("redo", C::Redo, "redo"), info("redo", C::Redo, "redo"),
info("repeat", C::Repeat, "repeat the last change"), info("repeat", C::Repeat, "repeat the last change"),
+2 -2
View File
@@ -389,11 +389,11 @@ mod tests {
assert_eq!(type_keys(&mut engine, &keymap, "12j"), run(Command::Move(Motion::Down), Some(12), None)); assert_eq!(type_keys(&mut engine, &keymap, "12j"), run(Command::Move(Motion::Down), Some(12), None));
assert_eq!( assert_eq!(
type_keys(&mut engine, &keymap, "\"+p"), type_keys(&mut engine, &keymap, "\"+p"),
run(Command::PasteAfter, None, Some(Register::Clipboard)) run(Command::PasteAsChild, None, Some(Register::Clipboard))
); );
assert_eq!( assert_eq!(
type_keys(&mut engine, &keymap, "3\"ap"), type_keys(&mut engine, &keymap, "3\"ap"),
run(Command::PasteAfter, Some(3), Some(Register::Named('a'))) run(Command::PasteAsChild, Some(3), Some(Register::Named('a')))
); );
assert_eq!(type_keys(&mut engine, &keymap, "gq"), Outcome::Unknown("gq".into())); assert_eq!(type_keys(&mut engine, &keymap, "gq"), Outcome::Unknown("gq".into()));
assert_eq!(type_keys(&mut engine, &keymap, "z<Esc>"), Outcome::Cancelled); assert_eq!(type_keys(&mut engine, &keymap, "z<Esc>"), Outcome::Cancelled);