A multi-line paste near the bottom of the screen left its later lines below
the viewport — adjust_scroll only kept the caret's (first) pasted line
visible. Add reveal(), which scrolls the end of the pasted block into view
while the caret stays on its first line (vim semantics unchanged).
Yank/paste via one unnamed register: `y` operator (yy/yw/yiw/y$), `p`/`P`,
with `x`/`d`/`c` also filling it so `dd`…`p` moves a line. Undo/redo (`u`,
`Ctrl-r`) as bounded full-buffer snapshots — one Insert session is one undo
group. `.` replays the last change from its recorded keystrokes, so it
repeats insert sessions like `ciwfoo<Esc>`.
Run :fmt in-core before :w/:sync emit their effect, so :sync is
fmt -> save -> commit -> push and :w saves formatted. Gated on the
format_on_save field (default on); the v0.5 .typoena.toml key will drive it.
Add Effect::Pull and the `:gl` command (fetch + fast-forward only, refuse on
divergence). The editor side is host-tested; the firmware arm is a stub posting
"pull: not wired yet (v0.7)" — the on-device fetch/fast-forward in git_sync is
v0.7 work (only push is wired today).
Handle DeleteWord (Ctrl-W) and DeleteLine (Cmd-Backspace) in Command mode:
Ctrl-W drops the previous word, Cmd-Backspace clears the line. Neither exits to
Normal on empty (unlike Backspace), so command editing stays on the line.
Reserve a left gutter for absolute line numbers, drawn on each logical line's
first display row and blank on wrapped continuation rows. Gutter width tracks
the buffer's line count (2 digits + separator, widening past 99 lines) and
steals its columns from the soft-wrap. Widen the writing region 60->63 cols so
the gutter doesn't narrow the text: a file up to 99 lines keeps a full 60-col
text column, at the cost of the side panel shrinking 30->25 cols.
Decode Ctrl+D/Ctrl+U as HalfPageDown/HalfPageUp intents (matching the existing
DeleteWord/DeleteLine chord pattern, so the editor stays ignorant of Ctrl).
They step display (soft-wrapped) rows, not logical lines, so half a page is
half the visible window regardless of how prose wraps: Normal moves the caret
and the viewport follows, View scrolls the viewport, Insert/Command are no-ops.
Two boot/panel UX changes that share the editor's constructor, so they
land in one commit:
- Power-on mode is now Normal (was Insert). with_text() opens a loaded
note in Normal with the caret on the last char (the resume point);
draw(false) now suppresses the caret in every mode, so the boot-error
screen renders as pure text rather than sprouting a block caret.
- notice/set_notice(): a transient side-panel message ("snackbar")
drawn under the word count and cleared on the next keystroke — no
timed repaint, which on e-ink would cost a ~630 ms flash to erase.
The host had no way to read the buffer out or seed it from a loaded
file. with_text lands the caret at the end so boot-load resumes writing
where the user left off; text() exposes the buffer for :w/:sync.
Match the workspace convention (firmware, keymap already ignore their
lockfiles); these two library crates just never got a .gitignore when
they were extracted.
The pure, no-IO editor core can't persist or push, so `handle()` now
returns an `Effect` (None/Save/Publish) that the firmware actions. `:w`
signals Save, `:sync` signals Publish (save then git push); `:wq`/`:x`
alias Save with vim's "quit" half dropped, and the `:q` family stays
absent — an always-on appliance has nothing to quit to. `:fmt` remains
in-core and yields no effect.
The main loop keeps the batch's last effect and matches on it. Actual
SD-write and git-push are the v0.1 gate and still stubbed as log lines.
Step whole characters everywhere instead of assuming 1 byte = 1 char, so
the dead-key composer's accented Latin-9 output (é, ç, …) no longer traps
the caret mid-character and panics on the next edit. Covers h/l/a and the
Escape step-back, j/k column math, backspace and x, word-end (e) with
de/ce, and layout/caret_rc (byte offsets vs display columns). Adds 7
accented-input tests (15 total).
Move the editor core out of the firmware crate (pinned to the xtensa
target, so it can't run `cargo test`) into a standalone `editor` crate,
with the panel framebuffer + geometry split into a `display` crate. Both
depend only on embedded-graphics + keymap, so the editor is now
host-buildable and unit-tested (8 characterization tests). Firmware links
them and re-exports the geometry from epd.rs; behaviour is unchanged.
The xtensa firmware build was not verified in this environment.