pi-vim 0.1.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/README.md +62 -60
  2. package/index.ts +545 -129
  3. package/motions.ts +55 -13
  4. package/package.json +1 -1
  5. package/types.ts +1 -1
package/README.md CHANGED
@@ -1,16 +1,12 @@
1
- # pi-vim — Vim Mode for Pi REPL
1
+ # pi-vim
2
2
 
3
- Modal vim-like editing for Pi's REPL prompt.
4
- Focus: the high-frequency 90% command surface, not full Vim.
3
+ Modal vim-like editing for Pi's input prompt. Covers the high-frequency 90% command surface.
5
4
 
6
- ## TL;DR
5
+ ## why
7
6
 
8
- - Problem: REPL editing is slow with only linear cursor movement.
9
- - Solution: modal editing (`INSERT`/`NORMAL`) with Vim-style motions,
10
- operators, counts, and repeatable workflows.
11
- - Install: `pi install npm:pi-vim`
7
+ You love Pi, you love Vim, you'll love pi-vim.
12
8
 
13
- ## Install
9
+ ## install
14
10
 
15
11
  ```bash
16
12
  pi install npm:pi-vim
@@ -18,19 +14,11 @@ pi install npm:pi-vim
18
14
 
19
15
  Restart Pi after install.
20
16
 
21
- ### Local loading (dev)
17
+ ## stats
22
18
 
23
- ```bash
24
- pi --extension /path/to/pi-vim/index.ts
25
- ```
26
-
27
- Or add to `.pi/settings.json`:
28
-
29
- ```json
30
- {
31
- "extensions": ["./pi-extensions/pi-vim/index.ts"]
32
- }
33
- ```
19
+ - **112 commands**: motions, operators, counts, text objects, undo/redo
20
+ - **sub-µs word motions** via precomputed boundary cache (~4ms startup, ~150KB memory)
21
+ - **0 dependencies**
34
22
 
35
23
  ## 30-second quickstart
36
24
 
@@ -41,27 +29,28 @@ Esc # NORMAL mode
41
29
  3gg # jump to absolute line 3
42
30
  2dw # delete two words
43
31
  u # undo
32
+ <C-r> # redo last undone edit (safe no-op when empty)
44
33
  2} # jump two paragraphs forward
45
34
  ```
46
35
 
47
36
  Mode indicator (`INSERT` / `NORMAL`) appears at bottom-right.
48
37
 
49
- ## Why pi-vim
38
+ ## why pi-vim
50
39
 
51
40
  - Fast modal editing without leaving Pi.
52
41
  - Count-aware motions/operators (`2dw`, `3G`, `d2j`, `2}`).
53
42
  - Strong REPL-focused defaults; safe out-of-scope boundaries documented.
54
43
  - Clipboard/register behavior is explicit and tested.
55
44
 
56
- ## For you / not for you
45
+ ## for you / not for you
57
46
 
58
47
  Use pi-vim if you want fast Vim muscle-memory in Pi prompts.
59
48
  Skip it if you need full Vim feature parity (visual mode, macros, search,
60
49
  ex-commands, etc.).
61
50
 
62
- ## Common recipes
51
+ ## common recipes
63
52
 
64
- | Goal | Keys |
53
+ | goal | keys |
65
54
  |------|------|
66
55
  | Jump to exact line 25 | `25gg` (or `25G`) |
67
56
  | Delete two words | `2dw` |
@@ -71,14 +60,15 @@ ex-commands, etc.).
71
60
  | Join 3 lines with spacing | `3J` |
72
61
  | Jump 2 paragraphs forward | `2}` |
73
62
  | Undo last edit | `u` |
63
+ | Redo last undone edit | `<C-r>` |
74
64
 
75
65
  ---
76
66
 
77
- ## Full reference
67
+ ## full reference
78
68
 
79
- ### Mode switching
69
+ ### mode switching
80
70
 
81
- | Key | Action |
71
+ | key | action |
82
72
  |----------|----------------------------------------|
83
73
  | `Esc` / `Ctrl+[` | Insert → Normal mode |
84
74
  | `Esc` / `Ctrl+[` | Normal mode → pass to Pi (abort agent) |
@@ -91,7 +81,7 @@ ex-commands, etc.).
91
81
 
92
82
  Insert-mode shortcuts (stay in Insert mode):
93
83
 
94
- | Key | Action |
84
+ | key | action |
95
85
  |-----------------|------------------------|
96
86
  | `Shift+Alt+A` | Go to end of line |
97
87
  | `Shift+Alt+I` | Go to start of line |
@@ -100,11 +90,11 @@ Insert-mode shortcuts (stay in Insert mode):
100
90
 
101
91
  ---
102
92
 
103
- ### Navigation (Normal mode)
93
+ ### navigation (normal mode)
104
94
 
105
95
  A `{count}` prefix can be prepended to any navigation key (max: `9999`).
106
96
 
107
- | Key | Action |
97
+ | key | action |
108
98
  |---------------|-------------------------------|
109
99
  | `h` | Left |
110
100
  | `l` | Right |
@@ -114,6 +104,7 @@ A `{count}` prefix can be prepended to any navigation key (max: `9999`).
114
104
  | `{count}j/k` | Move down/up `{count}` lines (clamped to buffer size) |
115
105
  | `0` | Line start |
116
106
  | `^` | First non-whitespace char of line |
107
+ | `_` | First non-whitespace char; with `{count}`, move down `count - 1` lines first |
117
108
  | `$` | Line end |
118
109
  | `gg` | Buffer start (line 1) |
119
110
  | `{count}gg` | Go to line `{count}` (1-indexed, clamped) |
@@ -146,11 +137,11 @@ Operator forms with braces (`d{`, `d}`, `c{`, `c}`, `y{`, `y}`) are out of scope
146
137
 
147
138
  ---
148
139
 
149
- ### Character-find motions (Normal mode)
140
+ ### character-find motions (normal mode)
150
141
 
151
142
  A `{count}` prefix finds the Nth occurrence of `{char}` on the line.
152
143
 
153
- | Key | Action |
144
+ | key | action |
154
145
  |------------------|------------------------------------------------|
155
146
  | `f{char}` | Jump forward to `char` (inclusive) |
156
147
  | `F{char}` | Jump backward to `char` (inclusive) |
@@ -164,17 +155,17 @@ Char-find motions compose with operators: `df{char}`, `ct{char}`, `d{count}t{cha
164
155
 
165
156
  ---
166
157
 
167
- ### Edit operators (Normal mode)
158
+ ### edit operators (normal mode)
168
159
 
169
160
  All operators write to the unnamed register and mirror to the system clipboard
170
161
  (best-effort; clipboard failure never breaks editing).
171
162
 
172
- #### Delete `d{motion}` / `dd`
163
+ #### delete `d{motion}` / `dd`
173
164
 
174
165
  A `{count}` or dual-count prefix (`{pfx}d{op}{motion}`) is supported for
175
166
  word, char-find, and linewise motions. Maximum total count: `9999`.
176
167
 
177
- | Command | Deletes |
168
+ | command | deletes |
178
169
  |-------------------|-----------------------------------------------------------|
179
170
  | `dw` | Forward to next `word` start (exclusive, can cross lines) |
180
171
  | `de` | Forward to `word` end (inclusive, can cross lines) |
@@ -187,6 +178,8 @@ word, char-find, and linewise motions. Maximum total count: `9999`.
187
178
  | `d$` | To end of line |
188
179
  | `d0` | To start of line |
189
180
  | `d^` | To first non-whitespace char of line |
181
+ | `d_` | Current line (linewise, same as `dd`) |
182
+ | `d{count}_` | `{count}` lines (linewise, same as `{count}dd`) |
190
183
  | `dd` | Current line (linewise) |
191
184
  | `{count}dd` | `{count}` lines (linewise) |
192
185
  | `d{count}j` | Current line + `{count}` lines below (linewise) |
@@ -201,11 +194,11 @@ word, char-find, and linewise motions. Maximum total count: `9999`.
201
194
  | `daw` | Around word (includes surrounding spaces) |
202
195
  | `d{count}aw` | Around `{count}` words |
203
196
 
204
- #### Change `c{motion}` / `cc`
197
+ #### change `c{motion}` / `cc`
205
198
 
206
199
  Same motion and count set as `d`. Deletes text then enters Insert mode.
207
200
 
208
- | Command | Action |
201
+ | command | action |
209
202
  |-----------------|------------------------------------|
210
203
  | `cw` | Change `word` + Insert |
211
204
  | `ce` / `cb` | Change to `word` end / previous `word` start |
@@ -216,14 +209,16 @@ Same motion and count set as `d`. Deletes text then enters Insert mode.
216
209
  | `ciw` | Change inner word |
217
210
  | `caw` | Change around word |
218
211
  | `cc` | Delete line content + Insert |
212
+ | `c_` | Change line (linewise, same as `cc`) |
213
+ | `c{count}_` | Change `{count}` lines (linewise) |
219
214
  | `c$` / `c0` / `c^` | Delete to EOL / BOL / first non-whitespace + Insert |
220
215
  | … | All `d` motions apply |
221
216
 
222
- #### Single-key edits
217
+ #### single-key edits
223
218
 
224
219
  A `{count}` prefix is supported for `x`, `p`, `P`. Maximum: `9999`.
225
220
 
226
- | Key | Action |
221
+ | key | action |
227
222
  |--------------|---------------------------------------------------------------|
228
223
  | `x` | Delete char under cursor (no-op at/past EOL) |
229
224
  | `{count}x` | Delete `{count}` chars |
@@ -231,14 +226,16 @@ A `{count}` prefix is supported for `x`, `p`, `P`. Maximum: `9999`.
231
226
  | `S` | Delete line content + Insert mode |
232
227
  | `D` | Delete cursor to EOL (captures `\n` if at EOL with next line) |
233
228
  | `C` | Delete cursor to EOL + Insert mode |
229
+ | `r{char}` | Replace char under cursor with `{char}` (stays in Normal) |
230
+ | `{count}r{char}` | Replace next `{count}` chars with `{char}` |
234
231
 
235
232
  ---
236
233
 
237
- ### Yank `y{motion}` / `yy`
234
+ ### yank `y{motion}` / `yy`
238
235
 
239
236
  Same motion set as `d`. Writes to register, **no text mutation**.
240
237
 
241
- | Command | Yanks |
238
+ | command | yanks |
242
239
  |---------|---------------------------------|
243
240
  | `yy` | Whole line + trailing `\n` |
244
241
  | `{count}yy` | `{count}` whole lines + trailing `\n` |
@@ -254,6 +251,8 @@ Same motion set as `d`. Writes to register, **no text mutation**.
254
251
  | `y$` | To end of line |
255
252
  | `y0` | To start of line |
256
253
  | `y^` | To first non-whitespace char of line |
254
+ | `y_` | Whole line (linewise, same as `yy`) |
255
+ | `y{count}_` | `{count}` whole lines (linewise) |
257
256
  | `yf{c}` | To and including `char` |
258
257
  | `yiw` | Inner word |
259
258
  | `yaw` | Around word (includes spaces) |
@@ -264,9 +263,9 @@ Linewise counted yank (`{count}yy`, `y{count}j/k`) remains supported.
264
263
 
265
264
  ---
266
265
 
267
- ### Put / Paste
266
+ ### put / paste
268
267
 
269
- | Key | Action |
268
+ | key | action |
270
269
  |--------------|-------------------------------------------------------------|
271
270
  | `p` | Put after cursor (char-wise) / new line below (line-wise) |
272
271
  | `P` | Put before cursor (char-wise) / new line above (line-wise) |
@@ -278,21 +277,22 @@ Line-wise detection: register content ending in `\n` is treated as line-wise.
278
277
 
279
278
  ---
280
279
 
281
- ### Undo
282
-
283
- | Key | Action |
284
- |-----|-------------------------------------------------|
285
- | `u` | Undo — sends `ctrl+_` (`\x1f`) to the underlying readline editor |
280
+ ### undo / redo
286
281
 
287
- Redo (`<C-r>`) is **not implemented** — see [Out of scope](#out-of-scope).
282
+ | key | action |
283
+ |-----|--------|
284
+ | `u` | Undo in normal mode |
285
+ | `Ctrl+_` | Undo in normal mode (alias for `u`) |
286
+ | `<C-r>` | Redo one undone change in normal mode; safe no-op when redo history is empty |
287
+ | `{count}<C-r>` | Redo up to `{count}` undone changes in order; clamps at available history and consumes count state (no leak to the next command) |
288
288
 
289
289
  ---
290
290
 
291
- ## Register and clipboard policy
291
+ ## register and clipboard policy
292
292
 
293
293
  - One unnamed register (like Vim's `""` register).
294
294
  - Every `d`, `c`, `x`, `s`, `S`, `D`, `C`, `y` operator form
295
- (including `dd`, `{count}dd`, `d{count}j/k`, `dG`, `yy`, `{count}yy`,
295
+ (including `dd`/`d_`, `{count}dd`, `d{count}j/k`, `dG`, `yy`/`y_`, `{count}yy`,
296
296
  `y{count}j/k`, `yG`) writes to the register and mirrors to the OS clipboard
297
297
  (via `copyToClipboard`, best-effort).
298
298
  - `p` / `P` read from the unnamed register only (not the OS clipboard).
@@ -300,18 +300,18 @@ Redo (`<C-r>`) is **not implemented** — see [Out of scope](#out-of-scope).
300
300
 
301
301
  ---
302
302
 
303
- ## Known differences from full Vim
303
+ ## known differences from full Vim
304
304
 
305
- | Area | This extension | Full Vim |
305
+ | area | this extension | full Vim |
306
306
  |-----------------------|----------------------------------------|-------------------------------|
307
307
  | `$` motion | Moves past last char (readline CTRL+E) | Moves to last char |
308
308
  | `w` / `e` / `b` + `W` / `E` / `B` | Cross-line for `word` + `WORD` motions | Cross-line |
309
309
  | `0` / `$` operators | Exclusive of anchor col | `0` inclusive of col 0 |
310
310
  | Undo depth | Delegates to underlying readline undo | Full per-change undo tree |
311
- | Redo | Not implemented | `<C-r>` |
311
+ | Redo | Normal-mode `<C-r>` supported (safe no-op when empty; counted redo is stepwise, clamps to available history, and preserves single-step undo granularity) | `<C-r>` |
312
312
  | Visual mode | Not implemented | `v`, `V`, `<C-v>` |
313
313
  | Text objects | Supports `iw`/`aw` only | Full text-object set |
314
- | Count prefix | Supported for operators, word/char motions, navigation, and edits (`x`, `p`/`P`); capped at `MAX_COUNT=9999` to prevent abuse | Full support |
314
+ | Count prefix | Supported for operators, word/char motions, navigation, and edits (`x`, `r`, `p`/`P`); capped at `MAX_COUNT=9999` to prevent abuse | Full support |
315
315
  | Named registers | Not implemented (`"a`, etc.) | Supported |
316
316
  | Macros | Not implemented (`q`, `@`) | Supported |
317
317
  | Search | Not implemented (`/`, `?`, `n`, `N`) | Supported |
@@ -320,7 +320,7 @@ Redo (`<C-r>`) is **not implemented** — see [Out of scope](#out-of-scope).
320
320
 
321
321
  ---
322
322
 
323
- ## Out of scope
323
+ ## out of scope
324
324
 
325
325
  These are **explicitly deferred** and not planned for this feature:
326
326
 
@@ -331,15 +331,17 @@ These are **explicitly deferred** and not planned for this feature:
331
331
  - Ex command surface (`:s`, `:g`, `:r`, …)
332
332
  - Search mode (`/`, `?`, `n`, `N`)
333
333
  - Repeat (`.`)
334
+ - Replace mode (`R`) — only single-char `r{char}` is supported
334
335
  - Extended count prefix beyond currently supported motions (e.g. `:`, global operator counts)
335
- - Redo (`<C-r>`) no native redo primitive in the underlying readline editor;
336
- deferred until a suitable hook is available.
336
+ - No insert-mode `<C-r>` feature expansion beyond current underlying-editor behavior.
337
+ - No cross-session redo persistence.
338
+ - No upstream `pi-tui` redo prerequisite in this wave.
337
339
  - Window / tab / buffer management
338
340
  - Plugin / runtime ecosystem compatibility
339
341
 
340
342
  ---
341
343
 
342
- ## Architecture notes
344
+ ## architecture notes
343
345
 
344
346
  - `index.ts` — `ModalEditor` subclass of `CustomEditor`; all key handling.
345
347
  - `motions.ts` — pure motion calculation helpers (`findWordMotionTarget`,