Problem:
The zh_TW catalog was stale, omitted 743 messages from the current source, and contained empty, fuzzy, and format-unsafe translations.
Solution:
Regenerate the catalog with the official translation build, preserve the focused translation repairs, and translate the reported E5200 diagnostic.
Problem:
As it turns out, when you have 17 different ways to "exit", you need to
plug 17 different holes.
Leak still reported by ASAN CI, even after 1eae512285f238788601.
ERROR: LeakSanitizer: detected memory leaks
strbuf_init src/cjson/strbuf.c:62:22
json_create_config src/cjson/lua_cjson.c:635:5
lua_cjson_new src/cjson/lua_cjson.c:2060:5
nlua_state_add_stdlib src/nvim/lua/stdlib.c:840:3
nlua_state_init src/nvim/lua/executor.c:973:3
Analysis:
`os_breakcheck()` may process a `exit_event` placed by
`exit_on_closed_chan()` during shutdown. This would re-enter
`preserve_exit()`, which then skips everything because it sees
`really_exiting=true`.
Solution:
Set `exiting` in `preserve_exit()`, not only in `getout()`.
Problem:
SIGTERM received during `os_exit()` can cause it to "nest":
os_exit src/nvim/main.c:720
preserve_exit src/nvim/main.c:910
deadly_signal src/nvim/os/signal.c:205
on_signal src/nvim/os/signal.c:240
signal_event src/nvim/event/signal.c:45
multiqueue_process_events src/nvim/event/multiqueue.c:159
event_teardown src/nvim/main.c:178
os_exit src/nvim/main.c:720
Solution:
Call `signal_reject_deadly()` at the start of `os_exit()` like
`preserve_exit()` already does.
Problem:
TSan CI, always at exit:
WARNING: ThreadSanitizer: use of an invalid mutex (e.g. uninitialized or destroyed)
#1 uv_mutex_lock
#2 tui_flush src/nvim/tui/tui.c:1708
#3 ui_client_event_flush
#4 parse_msgpack src/nvim/msgpack_rpc/channel.c:259
...
#10 event_teardown src/nvim/main.c:187
#11 os_exit src/nvim/main.c:720
...
#19 tinput_done_event src/nvim/tui/input.c:184
Analysis (guess):
`rpc_close_event()` may run during `event_teardown()` and reattach to
a restarted server, then `ui_client_attached=true` gets set and redraws
resume in an already-stopped TUI.
Solution:
Check `!exiting` in `rpc_close_event`, like we already do in
`channel_proc_exit_cb()`.
Problem:
Unreliable test on slow CI (ASAN/TSAN):
FAILED .../tui_spec.lua @ 3054: TUI exits immediately when stdin is closed
retry() attempts: 1
Expected: vim.NIL
Actual: { name = "nvim", pid = 33201, ppid = -1 }
The test asserts "immediate" exit of the Nvim process, but this may be
subject to OS delays outside of our control.
Solution:
Make the "timed out waiting for DA1" log conditional on the actual
timeout, and assert the logs in the test.
Problem:
Leak reported by ASAN CI, always at Lua state init.
ERROR: LeakSanitizer: detected memory leaks
strbuf_init src/cjson/strbuf.c:62:22
json_create_config src/cjson/lua_cjson.c:635:5
lua_cjson_new src/cjson/lua_cjson.c:2060:5
nlua_state_add_stdlib src/nvim/lua/stdlib.c:840:3
nlua_state_init src/nvim/lua/executor.c:973:3
...
SUMMARY: AddressSanitizer: 1055 byte(s) leaked in 2 allocation(s).
Analysis:
`getout()` may run during `free_all_mem()` (that's why it checks
`!entered_free_all_mem`). If that happens, the second `os_exit()`
returns early from `free_all_mem()` then `exit()` is called and Lua
state is never closed.
Solution:
Always call `nlua_free_all_mem()` in the early-return case.
Problem:
- Dot-repeat of a Visual selection prepared by a `<Cmd>` mapping,
results in E1255 and leaves Visual mode active.
- Visual-mode capture is implemented as a second, parallel "capture
engine": it re-composes a CmdSpec from cmdarg_T per key and decides
replayability from its own table of "void" key classes.
Solution:
- Model nested `normal_execute()` as a `CmdFrame` stack,
instead of a single module-scoped `stage`.
- Capture `<Cmd>` ":norm …" commands as subatoms from its nested frames.
- Produce every command exactly once; atom_push_raw() routes the atom to
the Visual composite while a selection is open, like it already does
for mapping composites.
- `v/pat<CR>d` is now repeatable and cascades.
vim-patch:8.2.0514: several global functions are used in only one file
vim-patch:8.2.1814: missing change to remove "static"
vim-patch:8.2.2860: adding a text property causes the whole window to be redawn
vim-patch:8.2.3276: Vim9: exists() can only be evaluated at runtime
vim-patch:8.2.3753: Vim9: function unreferenced while called is never deleted
vim-patch:8.2.4669: in compiled code len('string') is not inlined
vim-patch:9.0.1821: Vim9 constructors are always static
vim-patch:9.0.1953: Misplaced comment in errors.h
vim-patch:9.1.0349: Vim9: need static type for typealias
vim-patch:9.1.0584: Warning about redeclaring f_id() non-static
vim-patch:ae3a8664b runtime(doc): Add explanation for Vim's IME
vim-patch:9.1.2033: tests: Test_terminal_cwd flaky when using ConPTY
vim-patch:9.2.0026: The ss_pending_cmds variable is visible globally
vim-patch:9.2.0643: Missing Image ifdefs
vim-patch:381da9f85 CI: Bump github/codeql-action
vim-patch:9.2.0965: GTK4: blurry text rendering
vim-patch:9.2.0966: GTK4: window opens two lines too small
vim-patch:0b7700e1a runtime(doc): add PREVENT LOADING section for pi_getscript.txt
vim-patch:068657ffc runtime(vimlogo): remove coincident lines and reshade vimlogo.svg
vim-patch:8.2.0149: maintaining a Vim9 branch separately is more work
vim-patch:8.2.0173: build fails with old compiler
vim-patch:8.2.0191: cannot put a terminal in a popup window
vim-patch:8.2.0194: some commands can cause problems in terminal popup
vim-patch:8.2.0196: blocking commands for a finished job in a popup window
vim-patch:8.2.0202: when 'lazyredraw' is set the window title may not be updated
vim-patch:8.2.0204: crash when using winnr('j') in a popup window
vim-patch:8.2.0320: no Haiku support
vim-patch:8.2.0328: no redraw when leaving term-normal mode in popup terminal
vim-patch:8.2.0364: printf test failing on Haiku
vim-patch:8.2.0367: can use :pedit in a popup window
vim-patch:8.2.0399: various memory leaks
vim-patch:8.2.0516: client-server code is spread out
vim-patch:8.2.0557: no IPv6 support for channels
vim-patch:8.2.0574: ipv6 feature not shown in :version output
vim-patch:8.2.0588: Putty does not use "sgr" 'ttymouse' by default
vim-patch:8.2.0596: crash in test49
vim-patch:8.2.0611: Vim9: no check for space before #comment
vim-patch:8.2.0613: Vim9: no check for space before #comment
vim-patch:8.2.0624: Vim9: no check for space before #comment
vim-patch:8.2.0641: Vim9: not expanded in :hardcopy and syn-include
vim-patch:8.2.0650: Vim9: script function can be deleted
vim-patch:8.2.0653: using uninitialized pointer
vim-patch:8.2.0656: MS-Windows: redrawing right screen edge may not be needed
vim-patch:8.2.0694: Haiku: channel and terminal do not work
vim-patch:8.2.0718: gcc warning for returning pointer to local variable
vim-patch:8.2.0747: cannot forcefully close all popups
vim-patch:8.2.0748: cannot get a list of all popups
vim-patch:8.2.1601: Vim9: cannot use 'true" with garbagecollect()
vim-patch:8.2.1602: Vim9: cannot use 'true" with getbufinfo()
vim-patch:8.2.1603: Vim9: cannot use "true" with getchar()
vim-patch:8.2.1604: Vim9: cannot use "true" with getcompletion()
vim-patch:8.2.1606: Vim9: cannot use "true" with has()
vim-patch:8.2.1610: Vim9: cannot pass "true" to list2str() and str2list()
vim-patch:8.2.1611: Vim9: cannot pass "true" to nr2char()
vim-patch:8.2.1614: Vim9: cannot pass "true" to searchcount()
vim-patch:8.2.1615: Vim9: cannot pass "true" to searchdecl()
vim-patch:8.2.1616: Vim9: cannot pass "true" to synID()
vim-patch:8.2.1617: Vim9: cannot pass "true" to win_splitmove()
vim-patch:8.2.1619: Vim9: cannot pass "true" to spellsuggest()
vim-patch:8.2.4597: LuaV_debug() not covered by tests
vim-patch:8.2.4648: handling LSP messages is a bit slow
vim-patch:8.2.4650: "import autoload" only works with using 'runtimepath'
vim-patch:8.2.4653: "import autoload" does not check the file name
vim-patch:8.2.0528: Vim9: function arguments insufficiently tested
vim-patch:9.0.0375: the footer feature is unused
vim-patch:9.1.0202: leaking memory in add_user() on failure
Problem: The hit-enter prompt fires whenever a message scrolls the screen.
When this happens while a mapping is being processed, it consumes
the mapping's next key, causing unexpected behavior for users.
Solution: Similar to what 9.1.1969 did for stuffed characters, skip the
hit-enter prompt when there are still keys pending from a mapping
in the typeahead buffer.
related: neovim/neovim#38298
related: neovim/neovim#20635
related: neovim/neovim#30890
closes: vim/vim#20753
AI assisted.
6025ea9e02
Co-authored-by: XiaowenHu96 <me@xiaowenhu.com>
Problem: A SAL rule longer than MAXWLEN is silently truncated to an
empty lead. set_sal_first() then reorders the sl_sal entries
by their index byte and can move the terminating sentinel out
of the last slot, so spell_soundfold_wsal() reads past the end
of the array, e.g. when soundfold() or spellsuggest() is used
(Erick Alex).
Solution: Bound the sound-folding loops against sl_sal.ga_len.
closes: vim/vim#210766ac008db96
Co-authored-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: string_reduce() copies *rettv into argv[0] before calling
eval_expr_typval(). When the evaluator fails early, rettv is
never reset and still aliases argv[0] v_string.
clear_tv(&argv[0]) frees it, leaving rettv dangling and when
in vim9script get_func_tv() frees it again (Ave Dva).
Solution: Set rettv->v_type = VAR_UNKNOWN like what is done in
list_reduce() and tuple_reduce(), use tv_get_string_strict()
in f_reduce()
closes: vim/vim#21048
Supported by AI.
cd59994c45
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: Informational message has an error message number.
Solution: Use a message without an error number. (closesvim/vim#11530)
b53a190e9f
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Problem:
`buffheader_T` is a linked list (Vim's favorite data structure) with
complex bookkeeping, optimized for ancient hardware:
1. Memory topology: On old platforms (Amiga 512KB without MMU, MS-DOS
64KB segments), large contiguous allocations were hazardous (no VM).
2. Never-move appends: `add_buff()` fills spare space or links a new
block.
3. OOM "recovery": a failed block allocation only loses one append.
To avoid OOM, it prefers to allocate small, linked chunks, instead of
resizing one continguous slice. Each stuff/drain cycle costs
a malloc+free.
Solution:
Replace Vim's favorite data structure with Nvim's favorite data structure.
Nvim doesn't have granular handling of OOM (`xmalloc`), and hardware has
changed: caches favor contiguous memory, allocators handle
fragmentation. And these buffers are ~kb scale, so OOM is irrelevant on
any system that can run Nvim.
- Use a flat `StringBuilder` + `read`/`insert` offsets.
- Keeps capacity (does not shrink) until `free_buff`.
- "Steady state" allocates nothing: 1 fewer malloc+free per dot-repeat.
Problem:
`RedoBuf` is mostly indirection. It has a mild benefit as an "ownership"
signal but it counteracts the general goal of unifying how "redo state"
is passed throughout the system, tends to sprout redundant interfaces,
and reduces clarity.
Solution:
Add `CmdSpec.body` to hold the "prefixless" key sequence.
Reuse `CmdSpec` to represent a "redo" buf.
Problem: Cannot show extra info for completion in a popup window.
Solution: Add the "popup" entry in 'completeopt'.
576a4a6ff1
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Problem:
Redo prep is scattered/duplicated.
- `do_pending_operator()` has 3 prep blocks whose conditions must be in
sync with `atom_capture_op()`.
- insert.c, spell_suggest() hand-roll `redo_new()` + `redo_append_xx()`
sequences.
- prep_redo() has 2 roles, decided by `keys != NULL`.
Solution:
- `atom_capture_op()` is the "operator" entry point: capture, then
prep.
- Extract `prep_redo_visual()`, `atom_capturable()`.
Problem:
When `z=` delegates to `vim.ui.select()`, the picker may change the
current window before returning. `spell_suggest()` then continues to the
cursor restoration branch with the new window and assigns `prev_cursor`,
which belongs to the original window. This can leave Normal mode with an
invalid cursor position and produce E315.
Solution:
Clean up the spell suggestion state and return immediately after handing
control to `vim.ui.select()`.
Problem:
`<cmd>` mappings do not emit `CmdAtom.text`.
`<cmd>` and Lua-callback mappings that edit the buffer apply only at the
primary cursor, not cascaded (multicursor).
Solution:
Capture the `<cmd>` command in getcmdkeycmd().
Add kKeyOpaque ("no capturable keys"); narrow kKeySynthetic ("not
a keystroke") to K_EVENT/K_IGNORE, so an opaque mapping's edit still
sets `map_edit` and cascades via LHS-replay.
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.
Problem:
Undo of a change spanning many paired marks is quadratic. A node's
"intersect" array holds every pair crossing that node, and both
intersect_node() and unintersect_node() walked it linearly. Undoing an
edit over 1M paired marks spends 68% of its time in unintersect_node()'s
scan alone.
Solution:
The array is sorted, so binary search it.
marks undo before after
200k 831ms 385ms
1M 14006ms 3820ms
Redo is unaffected: it is dominated by marktree_move() actually
repositioning the marks.
Problem:
A named mark updated after a change is moved back (treated as the
original mark) by undo:
:1mark d
:$
dw
:2mark d " 'd is on line 2
:undo " 'd is back on line 1
The undo header snapshots `b_namedm` when the change is recorded, and
`u_undoredo()` restores that snapshot indiscriminately.
Solution:
Update the pending header's snapshot when a mark is set explicitly.
Marks that the change itself moved go through mark_adjust(), not
setmark_pos(), so those are still reverted.
Similar to 2546741d1b (for extmarks): an explicit set inside an undo
block is confused with an edit-driven adjustment. But the extmarks case
is dealing with mid-edit moves, whereas named/regular marks only need
the stale snapshot dropped.
Problem:
Setting a :bcd buffer into another window, modifies the caller's CWD.
local b = vim.api.nvim_create_buf(true, true)
vim.api.nvim_buf_call(b, function() vim.cmd.bcd('..') end)
vim.cmd('vsplit')
vim.api.nvim_win_set_buf(vim.fn.win_getid(2), b)
:echo haslocaldir(0) haslocaldir(-1,0) haslocaldir(-1,-1,0)
0 0 0
:echo getcwd() ==# getcwd(-1,-1)
0
Analysis:
`ctx_dirs_save` only saves CWD if it predicts the switch can change it.
But win_set_buf() replaces the target window's buffer *after* the
switch, which cannot be "predicted" from `ctx_dirs_save`.
Solution:
Always snapshot whenever the switch enters another window.
Skipping `os_dirname` was a micro-optimization.
Problem:
nvim_win_set_buf() on a non-current win, while the current win has
a win-local dir, changes the global CWD:
:vsplit | lcd ..
:call nvim_win_set_buf(other_win, buf)
:wincmd l
:verbose pwd
[global] /parent " expected: the initial cwd
Analysis:
`globaldir` is where to return when no local dir applies; NULL means the
process CWD is already there. Switching to a window with no local dir
makes update_cwd() chdir back to `globaldir` and clear it. kCtxKeepCwd
restores the process CWD but not that bookkeeping, so the restored
window-local dir is mistaken for the global one.
Solution:
Save/restore `globaldir` with the CWD.
Problem:
A mark created by `nvim_buf_set_extmark()` while an undo block is open
never comes back on redo.
Analysis:
Undo deletes the text it covers and collapses the range; redo replays
the splices, which re-insert the text but cannot re-expand the mark.
`extmark_set()` records a position only for a mark it moves, not for one
it creates.
Solution:
Record the created position for redo; undo leaves the mark to the splice
replay, since it did not exist before the edit. Each side of a paired
mark gets its own entry. Redo also revives a mark that undo invalidated,
else its position returns but its highlight does not.
Problem:
There is no unified notion of a "user action".
Vim processes input by one-char-at-a-time, and mostly throws away any
hints it might gather about the user's action, with one exception: it
stores the last _edit_ action (the "redo buffer", encoded as
unstructured `["x][v][count]body` bytes).
Plugins can only observe individual keys (vim.on_key) and high-level
effects (TextChanged, CursorMoved).
Solution:
- Users can subscribe to `CmdAtom` events to handle any user action.
- Event is deferred; handlers cannot cancel or interfere with user
actions.
- Capture `CmdSpec` from the normal/insert/visual subsystems.
- typeahead/readahead stay unstructured (`buffheader_T`): they are key
streams, not commands.
- the redo/record buffers become `StringBuilder`: fewer
allocations/copies.
- Repurpose the input/redo engine to accept `CmdSpec` objects.
"atom": one repeatable unit of user input, as a resolved (post-mapping)
keysequence plus structured fields. Only user actions, not `:normal`,
API calls, or non-"t" `feedkeys`.
BREAKING: dot-repeat of an Insert session, replays the entire session
including cursor-moves (:help ins-repeat).
BREAKING: dot-repeat of a Visual operation, replays the selection
instead of operating on a fixed-size region.
vim-patch:9.2.0946: GTK2/3: mouse move starts Visual selection after a dialog
vim-patch:9.2.0947: GTK4: screen is cleared when moving the mouse after startup
vim-patch:9.2.0948: GTK4: mouse move starts Visual selection after a dialog
vim-patch:9.2.0949: GDK_KEY_VoidSymbol might be undefined
vim-patch:9.2.0951: GTK3: cursor does no longer blink
vim-patch:9.2.0955: tests: terminal tests are flaky
vim-patch:9.2.0956: GTK4: crash when the window is resized while redrawing
vim-patch:8.1.0768: updating completions may cause the popup menu to flicker
vim-patch:8.1.0863: cannot see what signal caused a job to end
vim-patch:8.1.0876: completion match not displayed when popup menu is not shown
vim-patch:8.1.0894: MS-Windows: resolve() does not return a reparse point
vim-patch:8.1.1218: cannot set a directory for a tab page
vim-patch:8.1.1224: MS-Windows: cannot specify font weight
vim-patch:8.1.1417: MS-Windows: resolve() does not resolve all components of path
vim-patch:8.1.1473: new resolve() implementation causes problem for plugins
vim-patch:8.1.1525: cannot move a popup window with the mouse
vim-patch:8.1.1558: popup_menu() and popup_filter_menu() are not implemented yet
vim-patch:8.1.1561: popup_setoptions() is not implemented yet
vim-patch:8.1.1577: command line redrawn for +arabic without Arabic characters
vim-patch:8.1.1580: cannot make part of a popup transparent
vim-patch:8.1.1589: popup window does not indicate scroll position
vim-patch:8.1.1597: cannot scroll a popup window with the mouse
vim-patch:8.1.1609: the user cannot easily close a popup window
vim-patch:8.1.1612: cannot show an existing buffer in a popup window
vim-patch:8.1.1626: no test for closing a popup window with a modified buffer
vim-patch:8.1.1628: popup window functions not in list of functions
vim-patch:8.1.1713: highlighting cursor line only works with popup_menu()
vim-patch:8.1.1714: cannot preview a file in a popup window
vim-patch:8.1.1718: popup menu highlighting does not look good
vim-patch:8.1.1770: cannot get the window ID of the popup preview window
vim-patch:8.1.1784: MS-Windows: resolve() does not work if serial nr duplicated
vim-patch:8.1.1787: cannot resize a popup window
vim-patch:8.1.1799: cannot avoid mapping for a popup window
vim-patch:8.1.1813: ATTENTION prompt for a preview popup window
vim-patch:8.1.1819: :pedit does not work with a popup preview window
vim-patch:8.1.1880: cannot show extra info for completion in a popup window
vim-patch:8.1.1882: cannot specify properties of the info popup window
vim-patch:8.1.1884: cannot use mouse scroll wheel in popup in Insert mode
vim-patch:8.1.1892: missing index entry and option menu for 'completepopup'
vim-patch:8.1.1904: cannot have an info popup align with the popup menu
vim-patch:8.1.1905: cannot set all properties of the info popup
vim-patch:8.1.1906: info popup size is sometimes incorrect
vim-patch:8.1.1908: every popup window consumes a buffer number
vim-patch:8.1.1928: popup windows don't move with the text when making changes
vim-patch:8.1.1969: popup window filter is used in all modes
vim-patch:8.1.2039: character from 'showbreak' does not use 'wincolor'
vim-patch:8.1.2092: MS-Windows: redirect in system() does not work
vim-patch:8.1.2093: MS-Windows: system() test fails
vim-patch:8.1.2139: the modifyOtherKeys codes are not tested
vim-patch:8.1.2142: some key mappings do not work with modifyOtherKeys
vim-patch:8.1.2153: combining text property and syntax highlight is wrong
vim-patch:8.1.2155: in a terminal window 'cursorlineopt' does not work properly
vim-patch:8.1.2158: terminal attributes missing in Terminal-normal mode
vim-patch:8.1.2192: cannot easily fill the info popup asynchronously
vim-patch:8.1.2208: Unix: Tabs in output might be expanded to spaces
vim-patch:8.1.2273: wrong default when "pos" is changed with popup_atcursor()
vim-patch:8.1.2279: computation of highlight attributes is too complicated
vim-patch:8.1.2324: with of scrollbar in popup menu not taken into account
vim-patch:8.1.2351: 'wincolor' not used for > for not fitting double width char
vim-patch:8.1.2362: cannot place signs in a popup window
vim-patch:8.1.2386: 'wincolor' is not used for 'listchars'
vim-patch:8.1.2399: info popup on top of cursor if it doesn't fit
vim-patch:8.1.2415: popup menu flickers if an info popup is used
vim-patch:8.1.2418: bufnr('$') is wrong after recycling popup buffer
Problem:
`inputlist()` advertises "click with the mouse" purely because it
implements click selection, so under the default `'mouse'` of "nvi" it
offers a click that command-line mode never receives.
Solution:
Only offer the mouse when `'mouse'` covers command-line mode, the same
condition `:help inputlist()` already documents.
Problem: u_read_undo() has comments that do not add anything to what
the code says (afte rv9.2.0935).
Solution: Drop the redundant comments (Hirohito Higashi).
related: vim/vim#20942
closes: vim/vim#21028ecfea491aa
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Problem: The duplicate-check hashtab in insexpand.c has comments that
do not add anything to what the code says (after v9.2.0909).
Solution: Drop the redundant comments.
related: vim/vim#20926
closes: vim/vim#210274dde4afa1d
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Problem: transstr() has comments that do not add anything to what the
code says, and it casts a length to int only to cast it back to
size_t.
Solution: Drop the comments and keep the length in a size_t
(Hirohito Higashi).
related: vim/vim#20925
closes: vim/vim#21026fe65307d49
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Problem: The comments on the precomputed sort keys explain the code by
contrasting it with the previous implementation, and one of
them exceeds 80 columns (after v9.2.0937).
Solution: Drop the redundant comments and shorten the union member ones
(Hirohito Higashi).
related: vim/vim#21003
closes: vim/vim#21030722f4292e5
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
vim-patch:8.1.1523: cannot show range of buffer lines in popup window
vim-patch:8.1.1537: using "tab" for popup window can be confusing
vim-patch:8.1.1538: cannot specify highlighting for notifications
vim-patch:8.1.1548: popup_dialog() is not implemented
vim-patch:8.1.1553: not easy to change the text in a popup window
vim-patch:8.1.1559: popup window title property not implemented yet
vim-patch:8.1.1574: tabpage option not yet implemented for popup window
vim-patch:8.1.1659: popup window "mousemoved" values not correct
vim-patch:8.1.1673: cannot easily find the popup window at a certain position
vim-patch:8.1.1690: default padding for popup window menu is too much
vim-patch:8.1.1944: leaking memory when using sound callback
vim-patch:8.1.1999: calling both PlaySoundW() and PlaySoundA()
vim-patch:8.1.2193: popup_setoptions(popup_getoptions()) does not work
vim-patch:8.1.2250: CTRL-U and CTRL-D don't work in popup window
vim-patch:8.1.2292: v:mouse_winid not set on click in popup window
vim-patch:8.2.0238: MS-Windows: job_stop() results in exit value zero
vim-patch:8.2.0286: cannot use popup_close() for a terminal popup
vim-patch:8.2.2105: sound test is a bit flaky
vim-patch:8.2.2296: cannot use CTRL-N and CTRL-P in a popup menu
vim-patch:8.2.2950: sound code not fully tested
vim-patch:8.2.2959: sound_playfile() is not tested on MS-Windows
vim-patch:9.0.0800: compiler complains about repeated typedef
vim-patch:9.0.0999: memory may leak
vim-patch:9.0.2089: sound_playfile() fails when using powershell
vim-patch:9.1.0271: CI sound test aborts with undefined variable
vim-patch:9.1.0949: popups inconsistently shifted to the left
vim-patch:1f045f324 runtime(doc): clarify buffer deletion on popup_close()
vim-patch:9.1.1985: tests: test_sound.vim fails on Windows
vim-patch:3d863d6aa runtime(doc): Update popup width rule
vim-patch:9.2.0928: MinGW: tests hang when Vim is built with coverage enabled
vim-patch:9.2.0940: GTK4: columns are lost when a scrollbar appears
vim-patch:9.2.0943: test: test_hardcopy fails on GTK4 UI
vim-patch:c6b041c63 CI: Keep the GTK4 job from affecting the other jobs
Problem: sort() with "n", "N" or "f" converts an item to its number on
every comparison. For "n" that is a tv2string() plus strtod()
per comparison, so sorting a list of numbers turns each number
into a string and back O(n log n) times, dwarfing the sort.
Solution: Compute the numeric key of each item once, before the sort,
and compare the stored key (Samuel Schlesinger). Only the
builtin numeric compare modes are affected; uniq(), which
passes a bare list item to the compare function, and the
string and user-function paths are unchanged.
Sorting a list of 100000 numbers (min of 3, macOS arm64):
- sort(l, 'n'): 0.205s -> 0.017s
- sort(l, 'N'): 0.017s -> 0.010s
- sort(l, 'f'): 0.014s -> 0.010s
The result is identical, including that a string is still treated as 0
in "n" mode and that "N" keeps full 64-bit precision.
Add Test_sort_numeric_precomputed(): a large shuffled list sorted with
"n", mixed integers and floats, int64 values beyond the exact range of
a double for "N", and uniq() over the non-precomputed path.
closes: vim/vim#21003c8c59db9df
Co-authored-by: Samuel Schlesinger <sgschlesinger@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Problem: Reading an undo file resolves every stored sequence number
with a linear scan over all headers, making loading
quadratic in the number of undo states.
Solution: Sort uhp_table on uh_seq once and resolve each reference
with a binary search; the duplicate uh_seq check becomes a
single pass over the sorted table (Samuel Schlesinger).
At the default 'undolevels' of 1000 the quadratic cost is not
measurable; it takes 'undolevels' in the tens of thousands to matter.
Loading an undo file with 20000 states and 50 alternate branches with
:rundo goes from 1.49s to 0.11s (min of 3, macOS arm64), with the
same undotree().
Also make old_idx/new_idx/cur_idx and the loop index "i" long instead
of short/int: they index uhp_table, whose length num_head is a long
read from the file. A short index truncated above 32767 headers,
making the restored b_u_oldhead/b_u_newhead/b_u_curhead pointers
wrong in exactly the many-headers case this change is about.
Add tests: a round-trip test with alternate branches that compares
the entries of the tree and the text at every sequence number, a
corruption test with a duplicated uh_seq, and a test for reading an
undo file with zero headers, which is written when only the line for
the "U" command is saved.
closes: vim/vim#20942fccf613c8f
Co-authored-by: Samuel Schlesinger <sgschlesinger@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Problem: In diff mode with 'cursorbind' the cursor in the other window is
not updated after an undo that changes which lines correspond.
Solution: Also check whether the text changed before skipping the update
(Hirohito Higashi).
fixes: vim/vim#20982
related: vim/vim#13219
related: vim/vim#13210
closes: vim/vim#210042045a20d4b
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Problem: When the owner of an undo file differs from the owner of
the text file and the current user, u_read_undo() returns
without freeing the file name it allocated with
u_get_undo_file_name().
Solution: Free the file name before returning (Samuel Schlesinger).
Every other exit of the function frees it under the "theend" label;
this early return sits before the file pointer is initialized, so it
cannot use that label.
closes: vim/vim#20987d03735e8d2
Co-authored-by: Samuel Schlesinger <sgschlesinger@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Problem: When the automatic regexp engine falls back to the
backtracking engine in vim_regexec_string(), the compiled
program is freed before the replacement is compiled; when
saving the pattern fails from being out of memory the
caller's "regprog" is left pointing to freed memory and
is freed again.
Solution: Free the previous program only after compiling the
replacement succeeded, like vim_regexec_multi() already
does (Samuel Schlesinger).
closes: vim/vim#20986cab0901f12
Co-authored-by: Samuel Schlesinger <sgschlesinger@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Now this was a cargo cult anti-pattern to write home about.
Doing painful save-and-restore bookkeeping around a separate
`magic_overruled` decoy global is just as messy as doing painful
save-and-restore logic around `p_magic` itself. only that now you need
to wrap every access to the effective value in a function call.
This replaces this with a marvellous new Clean Code technique™:
passing in the intended behavior as a function parameter to functions
where either the option or an explicit value might be used.