hjkl_engine/keymap_motion.rs
1/// Cursor motion identity for the hjkl keymap layer.
2///
3/// Moved from `hjkl-vim` into `hjkl-engine` (Phase 6.6 cycle-break) so that
4/// `hjkl-vim` can depend on `hjkl-engine` without a circular dependency.
5///
6/// The host converts a `MotionKind` to the appropriate `Editor::apply_motion`
7/// call. Designed for extensibility: future phases may add variants without
8/// breaking existing match arms — callers must use `..` or add the new arms
9/// when they bump the hjkl-engine minor version.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11#[non_exhaustive]
12pub enum MotionKind {
13 /// `h` / `<Backspace>` — move the cursor one character to the left.
14 /// Clamps at column 0 (no line-wrap), matching vim's normal-mode `h`.
15 CharLeft,
16 /// `l` / `<Space>` — move the cursor one character to the right.
17 /// Clamps at the last character of the line (no line-wrap), matching
18 /// vim's normal-mode `l`.
19 CharRight,
20 /// `j` — move the cursor one line down, restoring the sticky column.
21 LineDown,
22 /// `k` — move the cursor one line up, restoring the sticky column.
23 LineUp,
24 /// `+` / `<CR>` (not yet bound) — move down one line and land on the
25 /// first non-blank character. Sets the sticky column.
26 FirstNonBlankDown,
27 /// `-` — move up one line and land on the first non-blank character.
28 /// Sets the sticky column.
29 FirstNonBlankUp,
30 /// `w` — move the cursor forward to the start of the next small word.
31 /// Counts repeat the motion; wraps across lines matching vim's `w`.
32 WordForward,
33 /// `W` — move the cursor forward to the start of the next BIG word
34 /// (whitespace-delimited). Counts repeat; wraps across lines.
35 BigWordForward,
36 /// `b` — move the cursor backward to the start of the current or previous
37 /// small word. Counts repeat; wraps across lines matching vim's `b`.
38 WordBackward,
39 /// `B` — move the cursor backward to the start of the current or previous
40 /// BIG word (whitespace-delimited). Counts repeat; wraps across lines.
41 BigWordBackward,
42 /// `e` — move the cursor forward to the end of the current or next small
43 /// word. Counts repeat; wraps across lines matching vim's `e`.
44 WordEnd,
45 /// `E` — move the cursor forward to the end of the current or next BIG
46 /// word (whitespace-delimited). Counts repeat; wraps across lines.
47 BigWordEnd,
48 /// `0` — move the cursor to the first column of the current line
49 /// (column 0). Count is ignored (vim `0` is always a plain motion).
50 LineStart,
51 /// `<Home>` — as `LineStart`, but a closed fold under the cursor stays
52 /// closed (vim's `<Home>` is not a `'foldopen'` `hor` motion).
53 Home,
54 /// `^` — move the cursor to the first non-blank character on the current
55 /// line. On a blank/all-whitespace line, lands at column 0.
56 FirstNonBlank,
57 /// `$` / `<End>` — move the cursor to the last character on the current
58 /// line. On an empty line, stays at column 0. Count-aware: `count$`
59 /// moves down `count-1` lines, then lands at the end of that line.
60 LineEnd,
61 /// `G` — go to line. Count semantics match vim:
62 /// - count 0 or 1 (bare `G`) → last line of buffer.
63 /// - count > 1 → jump to that line number (1-based).
64 ///
65 /// Note: `gg` (first line) is dispatched via the G-chord path
66 /// (`Editor::after_g`), not via this variant.
67 GotoLine,
68 /// `;` — repeat last `f`/`F`/`t`/`T` in the same direction.
69 /// No-op if no prior find exists.
70 FindRepeat,
71 /// `,` — repeat last `f`/`F`/`t`/`T` in the reverse direction.
72 /// No-op if no prior find exists.
73 FindRepeatReverse,
74 /// `%` — jump to matching bracket. With a count `N%`, vim normally
75 /// jumps to the `N%` line of the file (percentage). The engine
76 /// currently implements only the matching-bracket semantic; count is
77 /// passed through and handled engine-side. Bracket types: `()`, `[]`,
78 /// `{}`, plus C-style block comments `/* */` (engine detail).
79 BracketMatch,
80 /// `H` — jump to the top of the visible viewport. With a count, moves
81 /// to the viewport top and then `count - 1` rows further down (matching
82 /// vim's `H` count semantics). Lands on the first non-blank character.
83 ViewportTop,
84 /// `M` — jump to the middle row of the visible viewport. Count is
85 /// ignored (vim's `M` is always a plain motion). Lands on the first
86 /// non-blank character.
87 ViewportMiddle,
88 /// `L` — jump to the bottom of the visible viewport. With a count,
89 /// moves to the viewport bottom and then `count - 1` rows further up
90 /// (matching vim's `L` count semantics). Lands on the first non-blank
91 /// character.
92 ViewportBottom,
93 /// `<C-d>` — move the cursor half a page down. Count multiplies the
94 /// half-page distance (e.g. `2<C-d>` = one full page). Lands on the
95 /// first non-blank of the target row.
96 HalfPageDown,
97 /// `<C-u>` — move the cursor half a page up. Count multiplies the
98 /// half-page distance. Lands on the first non-blank of the target row.
99 HalfPageUp,
100 /// `<C-f>` — move the cursor a full page down (with 2-line overlap).
101 /// Count multiplies the full-page distance. Lands on the first non-blank
102 /// of the target row.
103 FullPageDown,
104 /// `<C-b>` — move the cursor a full page up (with 2-line overlap).
105 /// Count multiplies the full-page distance. Lands on the first non-blank
106 /// of the target row.
107 FullPageUp,
108 /// `_` — first non-blank of `count-1` lines below the cursor (count=1 = current line).
109 /// Linewise. Vim's `_` motion.
110 FirstNonBlankLine,
111 /// `[[` — backward to the previous `{` at column 0 (C section header).
112 /// Charwise exclusive; count-aware.
113 SectionBackward,
114 /// `]]` — forward to the next `{` at column 0. Charwise exclusive; count-aware.
115 SectionForward,
116 /// `[]` — backward to the previous `}` at column 0 (C section end).
117 /// Charwise exclusive; count-aware.
118 SectionEndBackward,
119 /// `][` — forward to the next `}` at column 0. Charwise exclusive; count-aware.
120 SectionEndForward,
121}