Skip to content

Restore undo grouping by honoring explicit save_before callbacks - #2140

Open
AryanRG wants to merge 1 commit into
prompt-toolkit:mainfrom
AryanRG:fix-named-command-undo-snapshots
Open

AryanRG wants to merge 1 commit into
prompt-toolkit:mainfrom
AryanRG:fix-named-command-undo-snapshots

Conversation

@AryanRG

@AryanRG AryanRG commented Oct 14, 2026 •

Copy link
Copy Markdown

Fixes #1467.

In Vi mode, typing asdf, Escape, then u currently leaves asd; this restores the pre-3.0.4 result of an empty buffer. An earlier insert is preserved (x followed by a new asdf insert undoes back to x ). Emacs ControlUnderscore and repeated backspace grouping are covered as well.

Named commands became Binding objects in 3.0.4. Re-registering them through KeyBindings.add silently drops the explicit save_before callbacks already supplied by the built-in self-insert, delete and Emacs undo bindings. This change makes an explicit callable take effect, while omitted callbacks continue to inherit the source binding's callback.

This deliberately changes public API precedence: KeyBindings.add(..., save_before=f)(existing_binding) now uses f. Existing-Binding precedence was not documented; explicit-caller precedence is inferred from the parameter description, the built-in callers and historical behavior. Omitting save_before or passing None inherits the source callback. Plain-handler registration with an omitted or callable value keeps its existing behavior; explicit None now means omitted instead of failing when called. The public signature default changes to None. Falsy callable objects remain valid overrides. The Binding constructor and generic key_binding() decorator keep their existing defaults, and other binding metadata handling is unchanged.

If preserving explicit-callback precedence for custom Binding objects is preferred, an alternative is an unspecified-callback marker limited to named commands. This patch chooses the consistent public add behavior and documents it. It leaves the buffer undo/redo implementation unchanged; #2083 addresses separate redo invalidation behavior.

Validation:

  • New regressions on the unmodified source: 9 failed, 42 passed across the focused files; with the fix: 51 passed.
  • Full suite: 167 passed on Python 3.12.15 and 3.14.4.
  • ruff check ., ruff format --check ., and typos . passed.
  • mypy --strict src/ passed for win32, linux, and darwin (145 source files each).
  • Historical 3.0.3 and current pipe-input probes confirm the Vi and Emacs grouping expectations.

AI assistance: AI agents implemented the change and performed separate automated plan and final reviews, including executable checks. Submitted as a draft for maintainer feedback on the API tradeoff; the issue has no maintainer statement endorsing this approach. Review may take time given the existing PR queue.

@AryanRG
AryanRG marked this pull request as ready for review October 14, 2026 13:34
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.

Commit 148833e9 (released in 3.0.4) changed undo's behavior in vi mode

1 participant