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