# v0.2 — Vim navigation

> Part of the [Typoena macro plan](macroplan.md). Requirements and targets:
> [qfd.md](qfd.md). Load-bearing decisions: [adr.md](adr.md).

**Status:** COMPLETE 2026-07-11. Navigation done in core; the **UTF-8-correct
buffer** and **`Ctrl-d/u` half-page scroll** landed and are hardware-verified,
and the **absolute line-number gutter** is built, host-tested, and **confirmed
on the panel (Spike 13) 2026-07-11** — a single-line edit repaints only the rows
at/below the change and forces no extra full refresh. Shipped early beyond scope:
a read-only **View** mode and the full `d`/`c` operator + text-object grammar
(see [v0.3](v0.3-editing.md) / [v0.4](v0.4-visual-and-ex.md)).

- [x] Mode state machine (Normal / Insert / View), mode indicator in the status strip
- [x] Movement: `h j k l`, `w b e`, `0 $`, `gg G`, `Ctrl-d Ctrl-u`. `Ctrl-d/u`
      step **display** (soft-wrapped) rows, not logical lines — half a page is
      half the visible window however prose wraps; decoded as `HalfPageDown/Up`
      intents in the keymap, caret moves and the viewport follows.
- [x] `i a o O A` to enter Insert
- [x] `Esc` returns to Normal
- [x] Line numbers in the left gutter: **absolute**, built + host-tested
      2026-07-11, **confirmed on the panel (Spike 13) 2026-07-11** — numbered on a
      logical line's first display row, blank on wrapped continuation rows; the
      gutter width tracks the buffer's line count (2 digits + separator, widening
      past 99 lines) and steals its columns from the soft-wrap. **Always on** in
      v0.2; the on/off toggle rides the [v0.5](v0.5-palette-and-multi-file.md)
      `.typoena.toml` prefs.
      Relative numbering was dropped (2026-07-11): renumbering the whole gutter on
      every `j`/`k` burns the e-ink ghosting budget for no proportionate gain,
      whereas absolute renumbers only the rows below an edit — the on-panel check
      confirmed a single-line edit repaints only rows at/below it with no extra
      full refresh.
- [x] Groundwork — UTF-8-correct buffer: caret motions and edits step by
      character, not byte (dropped the ASCII == byte-offset assumption), so every
      motion stays correct with accented input. **Done 2026-07-11** alongside
      extracting the editor into a host-testable crate — char-step
      motions/deletes, byte-vs-char split in `layout`/`caret_rc`, `word_end`/`de`
      fixed; 15 host tests. Render font is ISO-8859-15 (Latin-9), so accented
      glyphs display.
