Skip to content

feat: C-x z repeat-last-command (FM-REPEAT, done right) - #118

Merged
danielxvu merged 4 commits into
neomgfrom
fm-repeat
Jul 6, 2026
Merged

feat: C-x z repeat-last-command (FM-REPEAT, done right)#118
danielxvu merged 4 commits into
neomgfrom
fm-repeat

Conversation

@danielxvu

Copy link
Copy Markdown
Owner

feat: C-x z repeats the last command (done right)

The C-x z repeat that was dropped from #117 for silent data corruption — reworked correctly.

Approach

mgwrap (the single dispatch point) now captures the full context for each real command: last_command (replacing the old static ofp), last_f/last_n (numeric prefix), and last_key (a snapshot of the invoking key sequence). repeat restores key and re-runs the command through mgwrap in a loop, stopping on non-TRUE, and repeating while you press z.

This fixes all four bugs the earlier review caught:

  • selfinsert reads its char from key.k_chars → restoring key gives the original char (xxxx, not xz);
  • undo keys off rptcount → routing through mgwrap increments it, so C-x z after C-x u continues undoing instead of reversing it;
  • ABORT (e.g. a cancelled goto-line) stops the loop (!= TRUE);
  • the numeric prefix is preserved (C-u 3 C-n then C-x z moves 3+3).

This branch's own review caught one more

C-x z recorded into a keyboard macro stack-overflowed on replay (executemacro re-runs repeat, whose last_command is now executemacro → infinite recursion). Fixed by refusing repeat during macro replay (inmacro), like query-replace's macro guard — with a regression test that records a macro containing C-x z, replays it, and asserts the editor survives and stays responsive.

Tests / verification

pty: self-insert repeats the right char; undo continuation; numeric prefix preserved; macro replay no-crash; no-prior-command beeps. macOS 331/331 · TSan zero races · Alpine/musl 331/331 · legacy plain-C clean.

Based on neomg.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Pj1ZHaD7aNhVWJ69SFKJcp

Daniel Vu and others added 4 commits July 5, 2026 20:04
Capture full dispatch context in mgwrap (last_command + last_f/last_n +
last_key snapshot) and re-run repeat THROUGH mgwrap, restoring key first. Fixes
the 4 review findings from the dropped first attempt: selfinsert char, undo
rptcount continuation, ABORT handling, numeric prefix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pj1ZHaD7aNhVWJ69SFKJcp
One task: mgwrap captures last_command + last_f/last_n + last_key snapshot;
repeat restores key + re-runs through mgwrap; bind C-x z (cXmap 6->7). pty tests:
self-insert repeats right char (xxx not xz), no-prior-command beeps, movement
repeat lands correctly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pj1ZHaD7aNhVWJ69SFKJcp
Redo of the dropped first attempt, correctly this time. mgwrap captures the
full dispatch context for each real command: last_command (replaces the static
ofp), last_f/last_n (numeric prefix), and last_key (a snapshot of the invoking
key sequence). repeat restores key and re-runs THROUGH mgwrap, so:
- selfinsert reads the original char (x -> xxx, not xz),
- undo sees rptcount++ and continues the chain (not a redo),
- ABORT/FALSE stop the loop (!= TRUE),
- the numeric prefix is preserved (C-u 5 C-n then C-x z moves 5).
Bind C-x z (cXmap 6->7). repeat is excluded from last_command so it can't recurse.

macOS 329/329.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pj1ZHaD7aNhVWJ69SFKJcp
…rash)

Whole-branch review: a C-x z recorded into a keyboard macro crashed on replay --
executemacro() calls recorded steps directly (bypassing mgwrap), so last_command
stays executemacro; the recorded repeat then re-ran the whole macro and recursed
to a stack overflow. Guard repeat with inmacro (like query-replace's macro
guard). Add regression tests: macro-with-C-x-z replays without crashing and the
editor stays responsive; and C-x z preserves the repeated command's numeric
prefix (C-u 3 C-n then C-x z lands on line 7, proving n=3 wasn't dropped).
Moved the def.h prototype into the kbd.c section.

macOS 331/331.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pj1ZHaD7aNhVWJ69SFKJcp
danielxvu pushed a commit that referenced this pull request Jul 6, 2026
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pj1ZHaD7aNhVWJ69SFKJcp
@danielxvu
danielxvu merged commit 10199c9 into neomg Jul 6, 2026
14 of 16 checks passed
@danielxvu
danielxvu deleted the fm-repeat branch July 6, 2026 01:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant