Problem: With a non-zero 'autocompletedelay', Insert-mode autocommands
(TextChangedI, TextChangedP, CursorMovedI) are delayed, and
while typing faster than the delay they are dropped entirely,
because the delay blocks the main loop.
Solution: Make 'autocompletedelay' non-blocking: instead of busy-waiting
before showing the popup menu, defer it with an input-wait
timeout (K_COMPLETE_DELAY) modeled on CursorHoldI, so typing
stays responsive and the Insert-mode autocommands fire normally.
The delay timer coexists with 'updatetime': the main loop waits for the
sooner of the two and triggers the event whose deadline was reached, so
'autocompletedelay' no longer shadows CursorHold timing. Changing the
completion leader, for example with Backspace, updates the visible popup
immediately like a zero delay; only the first popup is deferred.
Update the 'autocompletedelay' screendumps for the non-blocking display.
One test opened the menu with CTRL-N right after the delay expired and
could race with the deferred popup, so it now waits a little longer than
the delay before sending the key.
fixes: vim/vim#20591closes: vim/vim#205988ce43ea4e3
Also include some insexpand.c and ui.c changes from patch 9.2.0750.
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem:
Redundant code.
Solution:
Add path_skip_sep() and use it.
Dropping MB_PTR_ADV is safe: the loops only advance while `*p` is
a one-byte separator (`/`, `\`, `:`). MB_PTR_ADV was needed in legacy
Vim because it supported non-UTF-8 (DBCS) *internal* encodings.
Problem:
On Windows, `fnamemodify('//foo/C$', ':h')` incorrectly removes `C$`
as a regular file name and returns `//foo`. However, this is a valid
UNC path, `foo` is a server name and `C$` is a share name.
The correct result should be `//foo/C$`.
Solution:
Extend `os_fileinfo2` and `FileInfo` with `prefix_off`, `rest_off` to
identify path types and logical root boundaries. ':h' can use this info
to prevent traversing past the logical root.
Examples:
/foo => /
//foo => // (POSIX)
//foo/bar => //foo (POSIX)
//server/share/foo => //server/share/ (Windows)
C:/foo => C:/
//?/C:/foo => //?/C:/
Co-authored-by: Barrett Ruth <br@barrettruth.com>
Problem: completion: menu state wrong on interruption
(Maxim Kim)
Solution: Call show_pum() if completion was interrupted
(Girish Palya).
Popup menu was not built after fuzzy sorting, so internal state wasn't
reflected on screen.
No test. Couldn't get the terminal test to trigger both interruption and
refresh together.
fixes: vim/vim#17725closes: vim/vim#17736f6a308c65b
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: Session with multiple tabpages sets 'winminheight' to 0.
Solution: Only save 'winminheight' and 'winminwidth' once (zeertzjq).
related: vim/vim#8119
related: neovim/neovim#40493closes: vim/vim#20673294dec827d
vim-patch:9.2.0516: socketserver: spurious error when servername is taken
vim-patch:9.2.0615: sixel encoder drops pixels on the right edge of shapes
vim-patch:9.2.0637: sixel: anti-aliased RGBA images render with visible outline
vim-patch:9.2.0692: GTK2: build failure, popup images not drawn correctly
vim-patch:9.2.0727: popup images not rendered correctly when unfocused
vim-patch:9.2.0730: GTK4 GUI tabline is not updated
vim-patch:9.2.0731: GTK4 GUI scrollbar size not updated when restoring a session
vim-patch:9.2.0733: GTK3: GUI slow on X11 since dropping the alpha channel
vim-patch:9.2.0737: tests: comment test can be improved
vim-patch:e876e256f CI: Bump actions/checkout in the github-actions group across 1 directory
vim-patch:9.2.0740: GTK4: scrollbar wrongly displayed
vim-patch:c0fc51184 CI: MS-Windows: Run gvim/vim tests in parallel
vim-patch:9.2.0744: popup_atcursor() closes immediately on white space
vim-patch:9.2.0746: NULL pointer dereference in gui_photon
vim-patch:9.2.0747: cscope: connection leak when growing the array fails
vim-patch:9.2.0751: GTK3 GUI is slow under Wayland
The system version of ConPTY in kernel32.dll is old and will
mangle some VT sequences sent by shells. Newer versions of ConPTY
available as part of the Windows Terminal project fix this by
passing through VT sequences unmodified when the terminal has set
ENABLE_VIRTUAL_TERMINAL_INPUT. This change allows users to fix
buggy behaviour of Neovim's terminal on Windows by copying
conpty.dll to Neovim's bin directory.
Co-authored-by: Scott Young <s@sjy.au>
Problem: changed_lines got a hardcoded 0, so the changelist entry
and '. mark always recorded column 0 instead of where the edit
actually happened.
Solution: pass start_col instead. changelist now tracks the real
column.
Problem:
`:restart` does not preserve window layout, etc.
Solution:
- Change `:restart` to save/restore a session automatically.
- Introduce "bang" variant `:restart!` to restart *without* session
save/restore.
- Introduce `v:startreason`.
- `ZR` maps to `:restart!`.
Problem:
On Windows, channel jobs inherit Nvim's stdio, so a background job
writing to CON (e.g. gutentags) draws onto the TUI and stays until
redraw.
Solution:
Give Windows job stdin/stderr libuv-created pipes (UV_CREATE_PIPE)
instead of inherited fds, so libuv spawns the child with
CREATE_NO_WINDOW and CON writes no longer leak onto the TUI.
Problem:
- Lua<=>API roundtrips
- Although we prefer Lua for most business-logic code, doing this
conversion in C makes sense in this case because:
1. setting options is a hot path
2. most of the options logic lives in C
3. the current arrangement is MORE verbose and requires MORE code
Solution:
Move conversion to a C util.
- nvim_set_option_value passes the raw Object (scalar, Array, or Dict)
to `object_as_optval_for()` which flattens it to the canonical `:set`
string and validates the type.
- drop `convert_value_to_vim`, eliminate its roundtrip.
The added test shows the context, one expected a JSON field
to be a Object but it was a null value
pros: shows `vim.NIL` instead of `a userdata`
cons: the context `field 'foo'` is lost. I think this is generated
with internal magic which is hard to replicate.
Problem: Crash when reading truncated spellfile (MarkLee131)
Solution: Set sl_sofo to TRUE in set_sofo() once sl_sal has been
converted to the soundfold layout.
Supported by AI.
closes: vim/vim#20660488a3eed12
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: Several string and memory wrapper macros cast their size
argument to size_t although the wrapped function's prototype
already declares that parameter size_t; such casts silence the
warning a compiler would otherwise give when a value of the
wrong type, such as a pointer, is passed as the size.
Solution: Where the wrapped function's prototype already declares the
parameter size_t, remove the cast so that a size argument of
the wrong type can be reported at compile time (K.Takata,
Shane Harper).
From gcc 14 on, -Wint-conversion is an error by default.
With gcc, passing a signed value where size_t is expected triggers
-Wsign-conversion, but the check is off by default and the build already
emits many such warnings.
related: vim/vim#20642
closes: vim/vim#206567f122f9eff
Co-authored-by: Shane Harper <shane@shaneharper.net>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Problem: Mapped typed keys didn't interrupt completion in
complete_check() (Yikai Zhao)
Solution: Also interrupt when in_compl_func and not replaying a register.
(glepnir)
closes: vim/vim#5547closes: vim/vim#2064337d85f5f1a
Problem:
No lint for strtol().
Solution:
Add lint, and update existing usages.
Callers that previously got a (garbage) large positive value:
- `indent.c`: use getdigits() (intmax, no int truncation) with def=1 so
overflow/too-large values stay positive and fall through to the
existing "too big" check (E475).
- `file_search.c`: use getdigits() with def=255 so overflow/too-large
values keep the "max expand" (else) branch.
The other conversions (api/command.c, eval/window.c, highlight_group.c,
tui/tui.c) only diverge on pathological overflow inputs where strtol's
result was already garbage and the observable outcome is unchanged.
Problem:
`nvim_set_option_value` cannot "update" options similar to `:set opt=`,
`:set opt+=`, etc. The Lua impls of "vim.opt" / "vim.o" have incomplete,
bespoke reimplementations of those operations.
ref #38420
Solution:
- Add `operation` param to `nvim_set_option_value`, which may be "set",
"append", "prepend", or "remove".
- Use this feature to implement `vim.opt` / `vim.o`.
Problem:
`os.exit()` in `nvim -l` exits through normal teardown. But, as #39783 shows,
when it is called from a libuv callback, teardown polling the main loop
when inside `uv_run()` can trip the recursive poll guard and cause a crash.
Fast callbacks are not safe to teardown, so it's better to schedule an exit out
of a callback rather than convolutedly handle this as I tried before.
Solution:
Reject `os.exit()` from fast callbacks with `E5560` error.
* refactor(autocmd): safely parse buflocal buffer numbers
Replace unsafe atoi with a robust integer conversion when extracting
the buffer number out of a "<buffer=123>" pattern in
aupat\_get\_buflocal\_nr.
This prevents potential silent integer overflows and ensures variables
fit safely within INT\_MAX boundaries before truncation.
* fix(autocmd): use getdigits_int to safely parse buffer numbers
* fix(autocmd): raise error for invalid buffer-local pattern values
When defining an autocommand, an invalid buffer-local pattern format
(such as `<buffer=foo>` or `<buffer=0>`) would previously fall through
silently and default to a generic `<buffer>` tag behavior.
Fix this regression by trapping invalid buffer numbers
early from `aupat_get_buflocal_nr()` and throwing a proper E680 error
to match Vim's runtime validation behavior.
Problem: Separation markers (%=) are ignored within item groups. This
lead to a regression when the C implementation of the statusline was
replaced with a default expression. When the user configured a custom
ruler expression with a %= and used the overloaded item group syntax to
set the ruler width, the separation marker worked in the ruler, but not
when the ruler was incorporated into the statusline where the item group
syntax was interpreted in the usual way.
Solution: Analogously to top-level behaviour, expand separation markers
evenly within item groups until `minwid` is reached (if set).
ref https://github.com/neovim/neovim/pull/33036
fix https://github.com/neovim/neovim/issues/39984
ref https://github.com/neovim/neovim/issues/40247
Problem: The recursion offset into the static `stl_items` was not taken
into account when adjusting the item count after truncation.
Steps to reproduce: first prepare `stl_items`:
set stl=%{%repeat('%#Error#',10)%}
then watch how the Error highlight leaks into the recursive call:
set stl=%l%l%l%{%nvim_eval_statusline('test%l%<',{'maxwidth':3,'highlights':1}).highlights%}
ref https://github.com/neovim/neovim/issues/32259
* fix(statusline): consistent truncation at multicell character
Problem 1: truncation of item groups at multicell character didn't take
into account that minwid can be specified as a negative number.
Problem 2: after truncation at top-level from the right at multicell
character, the returned width was always `maxwidth`, even though the
actual width was reduced. In vim, this can be observed as a statusline
that is not fully drawn until the edge of the screen:
vim --clean +"set ls=2 stl=%{%repeat('x',&columns-2)%}🙂x%<"
Problem 3: after truncation at top-level from the left at multicell
character, the resulting gap to reach `maxwidth` again was filled with
fillchars, but then the final NUL was not set correctly.
This can be seen in the following example, where the statuscolumn spills
into the editing area starting from line 10:
nvim --clean +"set number stc=%<x🙂%{repeat('x',43)}%l" +"norm yy10p"
Solution: fix the small errors and, at top-level, consistently reduce
the size instead of compensating with fillchars. In the case of the
statusline and the winbar, the remaining place is filled with the
configured fillchars in `win_redr_custom`, after `build_stl_str_hl` has
returned. In all other cases (title, icon, statuscol, tabline, ruler),
there seems to be no point in adding additional spaces at the end.
* feat(statusline)!: scope %< to item groups
Problem:
Previously, item groups were only truncated at the beginning, which is
often not desired. In the example
%.15(path: %f%)
the group's title/label is truncated away:
<th/to/file.txt
Truncation markers (%<) in item groups were processed at the top-level
in the end, which can be confusing. Only the first %< is used for the
whole string, and it is used even if the containing item group is
hidden. Additionally, in the case of hidden item groups, the marker's
position was not adapted. For example,
%(hidden%<%)%f
had the effect of truncating the path somewhere in the middle:
/path/<file.txt
Solution:
Make truncation consistent with top-level behaviour, which has a better
default of truncating at the first `Normal` item, i.e.
path: <file.txt
and allows for fine-grained control with truncation markers (%<). E.g.
%.15(path: %f%<%)
now yields
path: /path/to>
The original behaviour can be restored like so:
%.15(%<path: %f%)
BREAKING CHANGE: %< is no longer processed at top-level
- the default truncation behaviour has changed: now at first item
- truncation markers inside item groups don't affect truncation outside
of the item group anymore
- several truncation markers can now have an effect when separated with
item groups, whereas previously only the first one globally had
ref https://github.com/neovim/neovim/issues/39984
Problem: A crafted swap file can cause an out-of-bounds write during
recovery when the same block is referenced twice with
different pe_page_count values (cipher-creator)
Solution: Check hp->bh_page_count against page_count after mf_get() and
clamp page_count to the actual block size.
closes: vim/vim#2064543939cf9eb
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: The "%" command and bracket/text-object motions can skip the
matching paren or bracket on a line with quotes and a trailing
backslash.
Solution: Use the quote state at the search start when an odd-quote line
is continued with a backslash, instead of always treating the
search as starting in quotes (Barrett Ruth).
closes: vim/vim#20631c44a6561cc
Co-authored-by: Barrett Ruth <br@barrettruth.com>
Problem: ":filetype detect" is a valid command but not offered by
command-line completion.
Solution: Add "detect" to the completion candidates (glepnir)
closes: vim/vim#20625984f29860e
Co-authored-by: glepnir <glephunter@gmail.com>
Problem:
After ctrl-f from the cmdline, the last 2 lines of cmdwin are redundant.
Solution:
In `open_cmdwin`, clear the live cmdline so that unwinding it (via
Ctrl_C) does not add it to history.
vim-patch:ccdc81701 CI: Restore daily Coverity Scan
vim-patch:9.2.0710: GTK4 GUI resize handling can be improved
vim-patch:9.2.0712: GTK4: dialogs not handling mnemonics correctly
vim-patch:9.2.0720: GTK4: no support for browsefilter
vim-patch:9.2.0722: GTK4: find/replace dialog can be improved
vim-patch:9.2.0724: Use-after-free when freeing exit_cb job on exit
vim-patch:9.2.0709: GTK4: a few minor issues
vim-patch:9.2.0711: leak in ins_compl_infercase_gettext() in error case
vim-patch:9.0.0996: if 'keyprotocol' is empty "xterm" still uses modifyOtherKeys
vim-patch:9.0.1504: no error when calling remote_startserver("")
vim-patch:9.2.0042: crypt: cannot decrypt empty file
vim-patch:9.2.0113: winhighlight pointer may be used uninitialized
vim-patch:9.2.0118: memory leak in w_hl when reusing a popup window
vim-patch:9.2.0119: incorrect highlight initialization in win_init()
vim-patch:9.2.0292: E340 internal error when using method call on void value
ArrayOf metadata existed before the LuaCATS type documentation refactor and is
useful to typed clients consuming api_info().
Keep Tuple metadata normalized to Array, since tuple element types can be mixed,
but preserve ArrayOf(...) for exported API metadata.
Fixes#38734
AI-assisted: Codex
Problem:
cmdwin (the `:q` cmdline buffer) has various limitations which require
special-casing all over the codebase.
Besides complicating the code, it also breaks async plugins if they try
to create buffers/windows after some work is done, if the user happens
to open cmdwin at the wrong the moment:
Lua callback: …/guh.nvim/lua/guh/util.lua:531:
E11: Invalid in command-line window; <CR> executes, CTRL-C quits
stack traceback:
[C]: in function 'nvim_buf_delete'
…/guh.nvim/lua/guh/util.lua:531: in function <…/guh.nvim/lua/guh/util.lua:526>
Solution:
Just say no to "inception". Reimplement cmdwin as a normal buffer+window.
All of the cmdwin contortions (in both core, and innocent plugins) exist
literally only to support "inception": recursive
cmdwin-in-cmdline-things, like `<c-r>=`, `/`, search-during-substitute,
`:input()`, etc. So we just won't support that (though I have
a potential plan for that later, which I call "modal parking lot").
The benefit is that plugins, and core, no longer have to care about
cmdwin.
BONUS:
- mouse-drag on vertical separators works (it only worked for
horizontal/statusline before)
- inccommand-in-cmdwin now works correctly, for free (thus don't need
#40077).
POTENTIAL FOLLOWUPS
- Drop `CHECK_CMDWIN` ("E11: Invalid in command-line window"), allow chaos.
- Unify `BUFLOCK_OK` / `LOCK_OK` ?
DESIGN:
- Eliminate lots of C globals, `EX_CMDWIN`, etc.
- `text_locked()` no longer reports true for cmdwin.
- cmdwin = a normal window with 'winfixbuf', 'bufhidden=wipe',
'buftype=nofile'. Invariants come from those options rather than
special cases throughout the codebase.
- `nv_record` for q:/q//q? calls Lua
`nlua_call_vimfn("vim._core.cmdwin", …)`. No `K_CMDWIN`
/ cmdline-reader detour.
- `cedit_key` (`c_CTRL-F`) schedules a deferred event that calls
`vim._core.cmdwin.open(type, content, pos)` and returns `Ctrl_C` so
the in-flight cmdline cancels. Reader state is not serialized; instead
the captured `(type, line, col)` is replayed via
`nvim_feedkeys(type..line.."<CR>", "nt", …)` after user confirms.
- On confirm/cancel: `<CR>` / `<C-C>` calls into Lua which closes the
window and re-feeds the cmdline.
BREAKING CHANGES:
- Expression-register cmdline (`<C-R>=` from insert-mode) no longer
supports cmdwin. Same applies to `input()` / `inputlist()` (already
covered by `text_locked`).
- Usage of cmdwin in macros/mappings will probably break (assuming they
ever worked).
Problem: :syn sync without an argument also lists every defined cluster
Solution: Fix control flow in syn_cmd_list() so that only the syncing
items are printed when this function gets called by :syn sync.
(dmitmel)
closes: vim/vim#20614f2954c821e
`redraw_custom_statusline` and `win_redr_custom` are misleading bc the
builtin statusline is always "custom". And that terminology will be even
more irrelevant once 'tabline' and 'ruler' are similarly migrated.
Problem: Unecessary/unexpected cleanup happens when restoring the
current window for redraw purposes (since 28ffb334).
Solution: Don't call autocmd_restbuf() to restore the current window,
just do so directly.
Problem: Leak in do_autocmd in error case (Cheng)
Solution: goto err_exit in the error case and clean up, make the double
++once an actual error
closes: vim/vim#2060698f5171ef6
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: An autocommand that redraws may do so while curwin is
temporarily set for the autocommand scope. This can result in
flickering or unexpected state with UI components (statusline,
winbar, decor providers...) that depend on the current window.
Current workaround for statusline and winbar specifically
delays the redraw, which can itself be unexpected for the
autocommand.
Solution: If redrawing happens with a temporary autocmd current window,
temporarily restore the current window while redrawing.
Problem: Attach-time terminal probes cannot distinguish responses from
different attached UIs.
Solution: Identify the UI by RPC channel id in `TermResponse` and make
`vim.tty.request()` filter responses by channel.
Problem: `nvim_exec_autocmds({buf=...})` may temporarily switch curwin/curbuf
through `aucmd_prepbuf()`. Requested statuslines/winbars before
`aucmd_restbuf()` may erroneously see the target window as current.
Solution: Track `aucmd_prepbuf()` window-switch depth and leave statusline/winbar
redraws marked dirty until the original window is restored.
vim-patch:9.2.0700: configure: -lrt requirement for timer_create not detected
vim-patch:9.2.0701: tests: test_terminal.vim does not wait for job to finish
vim-patch:9.2.0704: GTK4: not handling mouse events
vim-patch:9.2.0706: tests: test_terminal3 may fail when $SHELL is zsh
vim-patch:9.0.0547: looping over empty out_loop[] entries
vim-patch:9.0.0718: extra empty line between two virtual text "below"
vim-patch:9.0.0723: extra empty line below virtual text when 'list' is set
vim-patch:9.0.0962: virtual text below cannot be placed below empty lines
vim-patch:9.0.0975: virtual text below empty line misplaced when 'number' set