Vim mode plugin (#538) #566

Closed
kayg wants to merge 0 commits from issue/538-vim into dev
Owner

Vim mode as an editor plugin (#538, VM1–VM5), and the fix for Esc's block selection looking like selected words. Not merged; it's for a train.

What

  • VM1: a plugin, off by default, with a "Vim mode" switch in Settings → Editor (pref ui.vim). Its code (@replit/codemirror-vim 6.4.0, MIT, 37.7 KB brotli) loads with import() only when it's on.

  • VM2:

    • A note opens in insert mode. Esc gives normal mode, and Esc in normal mode does nothing more.
    • v selects characters. Ctrl-v selects a column.
    • V uses the app's block selection (its bar and its look). In it:
      • j/k (with counts) take in more blocks;
      • d/x delete them, y yanks them, and >/< nest them;
      • Esc or V puts them down.
    • Text objects: iw, i", is, and it/at. Markdown has no tag tree, so it finds the tag pair in the text.
  • VM3: motions, counts, operators, ., registers, undo, and search: see the coverage list below.

  • VM4: the caret shows the mode:

    • normal: an accent block on the letter;
    • insert: the app's bar;
    • visual: an outline.

    It doesn't blink with reduced motion.

  • VM5: off with a coarse pointer until a key a screen keyboard doesn't have (Esc, an arrow, Tab, or a key held with a modifier) shows a hardware keyboard.

  • Command line: :, / and ? morph the bottom bar into a field with the prefix at its start.

    • Enter runs the line. Esc morphs back.
    • Search highlights matches as you type, and n/N cycle through them.
    • Commands: :w says "Saved", :q/:wq/:x leave the note, :<n>, :s, :%s, :noh.
    • Line numbers count from the first line you can see, and % never reaches the hidden properties.
  • Fit to Calternal (packages/editor/src/vim/):

    • u and Ctrl-r use this person's own shared history (ADR 0022).
    • Each Vim change is one undo step, however slowly it's typed.
    • Vim never lands in the hidden properties.
    • Another device's edits never join ..
    • Vim's own edits never count as typing, so they don't open the [[ picker.
    • Esc with the picker open closes the picker and stays in insert mode.
  • Bug fix (blocks/selected.ts): a block selection (Esc, the handle, V) now wears a rounded 16% accent tint per block, 8 px past its text: the #397 look without the phone's circles. The words' selection paint and the caret step aside. A phone with #523's own pick look keeps that one (.cm-picking hides this tint).

  • Bundle budget: bundle-size.mjs counts opt-in plugin chunks as web.bundle.plugins_* (budget ≤ 45 KB) instead of in all, which stays at 249 KB. Without this, the Vim chunk would push all_js_brotli to 287 KB, over the 260 KB budget, although nobody downloads it unless they turn Vim on.

Tests: e2e/vim.spec.ts (14 tests) and packages/editor/test/vim.test.ts (10 tests). Gate output, latency numbers and open questions are on #538.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WCcFhwwgMK66k9LMVqogNJ

Vim mode as an editor plugin (#538, VM1–VM5), and the fix for Esc's block selection looking like selected words. Not merged; it's for a train. **What** - **VM1:** a plugin, off by default, with a "Vim mode" switch in Settings → Editor (pref `ui.vim`). Its code (`@replit/codemirror-vim` 6.4.0, MIT, 37.7 KB brotli) loads with `import()` only when it's on. - **VM2:** - A note opens in insert mode. Esc gives normal mode, and Esc in normal mode does nothing more. - `v` selects characters. Ctrl-v selects a column. - `V` uses the app's block selection (its bar and its look). In it: - j/k (with counts) take in more blocks; - d/x delete them, y yanks them, and `>`/`<` nest them; - Esc or V puts them down. - Text objects: iw, i", is, and `it`/`at`. Markdown has no tag tree, so `it` finds the tag pair in the text. - **VM3:** motions, counts, operators, `.`, registers, undo, and search: see the coverage list below. - **VM4:** the caret shows the mode: - normal: an accent block on the letter; - insert: the app's bar; - visual: an outline. It doesn't blink with reduced motion. - **VM5:** off with a coarse pointer until a key a screen keyboard doesn't have (Esc, an arrow, Tab, or a key held with a modifier) shows a hardware keyboard. - **Command line:** `:`, `/` and `?` morph the bottom bar into a field with the prefix at its start. - Enter runs the line. Esc morphs back. - Search highlights matches as you type, and n/N cycle through them. - Commands: `:w` says "Saved", `:q`/`:wq`/`:x` leave the note, `:<n>`, `:s`, `:%s`, `:noh`. - Line numbers count from the first line you can see, and `%` never reaches the hidden properties. - **Fit to Calternal (`packages/editor/src/vim/`):** - `u` and Ctrl-r use this person's own shared history (ADR 0022). - Each Vim change is one undo step, however slowly it's typed. - Vim never lands in the hidden properties. - Another device's edits never join `.`. - Vim's own edits never count as typing, so they don't open the `[[` picker. - Esc with the picker open closes the picker and stays in insert mode. - **Bug fix (`blocks/selected.ts`):** a block selection (Esc, the handle, `V`) now wears a rounded 16% accent tint per block, 8 px past its text: the #397 look without the phone's circles. The words' selection paint and the caret step aside. A phone with #523's own pick look keeps that one (`.cm-picking` hides this tint). - **Bundle budget:** `bundle-size.mjs` counts opt-in plugin chunks as `web.bundle.plugins_*` (budget ≤ 45 KB) instead of in `all`, which stays at 249 KB. Without this, the Vim chunk would push `all_js_brotli` to 287 KB, over the 260 KB budget, although nobody downloads it unless they turn Vim on. Tests: `e2e/vim.spec.ts` (14 tests) and `packages/editor/test/vim.test.ts` (10 tests). Gate output, latency numbers and open questions are on #538. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01WCcFhwwgMK66k9LMVqogNJ
Vim's keys in the editor, as a plugin: off by default, turned on in
Settings → Editor, and loaded only once it's on. It stays off on a touch
screen until a hardware key shows a keyboard is there.

- @replit/codemirror-vim 6.4.0 (MIT) for motions, operators, counts,
  registers, `.`, text objects, visual modes and `:` commands, fitted to
  the editor in packages/editor/src/vim/:
  - u and Ctrl-r undo this person's own changes;
  - V selects whole blocks the app's way;
  - `:` and `/` are typed in the bottom bar;
  - each Vim change is one undo step;
  - the hidden properties are out of reach;
  - another device's edits never join `.`;
  - `it` works on inline HTML.
- The caret shows the mode: a block in normal mode, the bar in insert
  mode, an outline in visual mode. It doesn't blink with reduced motion.
- A note opens in insert mode. Esc gives normal mode and does nothing
  more there.
- The command line morphs the bar into a field with its prefix. Search
  highlights matches as you type. :w, :q, :n, :s and :%s work.
- Fix: a block selection (Esc, the handle, V) now looks like a block,
  a rounded accent tint, never like selected words.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WCcFhwwgMK66k9LMVqogNJ
Vim mode: accent caret over Vim's own, opt-in plugin chunks counted apart
Some checks failed
CI / server (pull_request) Successful in 34s
CI / rust (pull_request) Successful in 2m23s
CI / web (pull_request) Failing after 36s
3a71b7a8ac
- The caret and search matches are drawn in the accent. Vim's own pink,
  yellow and cyan styles no longer win.
- bundle-size.mjs counts chunks that only load once their plugin is
  turned on (the Vim chunk, 37.7 KB brotli) as web.bundle.plugins_*,
  with their own budget (≤ 45 KB), and leaves them out of "all".
- A reload never leaves the bar on an empty command line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WCcFhwwgMK66k9LMVqogNJ
Author
Owner

Landed in train z, #567.

Landed in train z, #567.
kayg closed this pull request 2026-10-18 02:42:28 +00:00
Some checks failed
CI / server (pull_request) Successful in 34s
CI / rust (pull_request) Successful in 2m23s
CI / web (pull_request) Failing after 36s

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal!566
No description provided.