Commit Graph

16 Commits

Author SHA1 Message Date
Justin M. Keyes
7e2e3f8c25 feat(editor): undo restores cursor position #41520
Problem:
Undo places the cursor wherever the cursor happened to sit at "save
time" (`uh_cursor` is sampled lazily on the first change).
Examples:
- `i` preserves, but `a` does not
- `diw`, `atest<Esc>`, `d^` abandon the original position
- `D`, `o` restore it (by accident).

Solution:
`composite` tracks the pending atom (and its `origin`) across frames.
A `stuffed` continuation frame inherits the `origin` + prepped redo.
Store `origin` info in the undo header, so undo can restore it.

- Not for a mid-command undo break (i_CTRL-G_u).
- Undoing a mapping restores where the mapping started (which
  technically may be different than where the "edit" started).
2026-08-27 16:12:11 -04:00
Justin M. Keyes
214bcf24cc fix(undo): crash on corrupted undo file #41339
Problem:
`:rundo` on a corrupted undo file crashes or hangs, instead of failing
with E825. Patching one 4-byte field is enough:

    ue_size = 0xFFFFFFFF  " walks a NULL ue_array
    ue_size = 0x7FFFFFF0  " 17 GB xmalloc + memset, then preserve_exit()
    ue_top  = 0xFFFFFFFB  " negative lnum reaches ml_delete()

Analysis:
Every count in the file is read with `undo_read_4c()` and then checked,
differently at each site. None bounds the value by what the file can
hold, so a 2 GB count reaches `xmalloc()`.

Note:
- Vim doesn't have `bi_fsize` because it checks `U_ALLOC_LINE` result
  everywhere (thus doesn't crash, but may thrash...); those checks were
  dropped when Nvim moved to `xmalloc()`, and the `ue_size` loop counter
  became unsigned.
- Vim *does* have the negative line numbers bug: `u_undoredo()` checks
  `top > ml_line_count || top >= bot || bot > ml_line_count + 1`, which
  rejects none of them.

Solution:
- Introduce `undo_read_len()` and use it to fail early instead of
  continuing with nonsense.
- Validate `ue_top`/`ue_bot`/ `ue_lcount`.
- Use `xcalloc()`, so no site can proceed with a NULL array.
- Report a truncated "U" line, distinguish EOF from a 0xFFFFFFFF field,
  and free the header on the extmark error path.
2026-08-16 10:24:24 -04:00
Justin M. Keyes
6d8c8b18d5 test(harness): migrate away from magic globals
Problem:
The magic globals `it`, `describe`, etc., are more trouble than they are
worth.

- Hooking into `after_each` requires `getfenv()` hacks.
- They confuse luals/emmylua, because the top-level `.luarc.json` isn't
  merged with `test/.luarc.json` (apparently a luals limitation?)
- They totally defeat discoverability because the user just has to
  "know" about the various magic symbols.

So they harm DX, which means they serve no purpose at all.

Solution:
- Expose the test API from `testutil`, so tests can call `t.it()`,
  `t.describe()`, etc., in the conventional way.
- Drop `getfenv()` hacks.
- Drop the `setfenv()` injection in `load_chunk`.
- Drop `test/_meta.lua`.
2026-07-21 13:22:39 +02:00
zeertzjq
2df2e72e0a fix(undo): undefined behavior with empty entry in 'undodir' (#38849)
Problem:  Undefined behavior when 'undodir' contains empty entry.
Solution: Don't try to remove trailing slashes from empty path. Also
          don't remove a colon on Windows while at it.
2026-04-07 14:49:05 +08:00
Sean Dewar
a5eb023a53 fix(prompt): clear undo when changing/appending prompt
Problem: undoing after the prompt is changed breaks it (and causes init_prompt
to abort it and append a new one), as the undo history contains the old prompt.

Solution: like submitting, clear the undo buffer. Don't do it in init_prompt if
the line was empty; that may not result in a new prompt, and causes commands
like "S" to lose the history.

As u_save, etc. wasn't being called by prompt_setprompt, undoing after it fixes
the prompt usually gave undesirable results anyway.

Remove the added undo_spec.lua test, as its approach no longer works as a repro,
and finding a new one seems fiddly.
2026-02-17 23:43:37 +00:00
Sean Dewar
ce9dbd398b fix(undo): u_savecommon uses wrong buffer
Problem: u_savecommon with reload = true wrongly uses curbuf.

Solution: use buf. Fix comments.
2026-02-17 01:03:58 +00:00
glepnir
86a4588d4a test: remove feed_command in undo_spec #36953
Problem: feed_command is marked as deprecated.

Solution: replace it with command and pcall_err.
2025-12-15 02:11:23 -05:00
dundargoc
052498ed42 test: improve test conventions
Specifically, functions that are run in the context of the test runner
are put in module `test/testutil.lua` while the functions that are run
in the context of the test session are put in
`test/functional/testnvim.lua`.

Closes https://github.com/neovim/neovim/issues/27004.
2024-04-23 18:17:04 +02:00
Lewis Russell
81fc27124b refactor(test): inject after_each differently 2024-04-10 15:53:50 +01:00
dundargoc
7035125b2b test: improve test conventions
Work on https://github.com/neovim/neovim/issues/27004.
2024-04-08 22:51:00 +02:00
Lewis Russell
795f896a57 test: rename (meths, funcs) -> (api, fn) 2024-01-12 18:59:14 +00:00
Justin M. Keyes
04f2f864e2 refactor: format test/* 2024-01-03 02:09:29 +01:00
zeertzjq
95044991e6 test(undo_spec): add more tests for writing in Insert mode 2022-12-09 07:00:27 +08:00
zeertzjq
70d6c335b1 vim-patch:9.0.1036: undo misbehaves when writing from an insert mode mapping
Problem:    Undo misbehaves when writing from an insert mode mapping.
Solution:   Sync undo when writing. (closes vim/vim#11674)

3f8f827723

Co-authored-by: Bram Moolenaar <Bram@vim.org>
2022-12-09 06:55:15 +08:00
Famiu Haque
1e3d9c7dbc feat: add undo!
Allows using `undo!` to undo changes and remove them from the undo-tree. Can only be used for moving backwards in the same undo branch.
2022-04-20 00:10:02 +06:00
Justin M. Keyes
d8de4eb685 test: reorg #15698
Problem:
Subdirectories like "visual", "insert", "normal" encourage people to
separate *related* tests for no good reason.  Typically the _mode_ is
not the relevant topic of a test (and when it is, _then_ create
an appropriate describe() or it()).

Solution:
- Delete the various `test/functional/<mode>/` subdirectories, move
  their tests to more meaningful topics.
- Rename `…/normal/` to `…/editor/`.
  - Move or merge `…/visual/*` and `…/insert/*` tests into here where
    appropriate.
- Rename `…/eval/` to `…/vimscript/`.
  - Move `…/viml/*` into here also.

* test(reorg): insert/* => editor/mode_insert_spec.lua
* test(reorg): cmdline/* => editor/mode_cmdline_spec.lua
* test(reorg): eval core tests => eval_spec.lua
2021-09-17 09:16:40 -07:00