Problem:
The "restart" event has some problems:
- all UI clients must implement a somewhat complex set of setups
- UI must be on the same machine as the server
- only works for the "current" UI
- race/edge case: If the user config has errors / waiting for input, are
all UIs able to attach while Nvim is waiting for input?
Solution:
- Perform the restart on the server, not the client.
- Pass listen address (instead of CLI args) in the UI event.
- Simplifies UI logic: they only need to attach to new address.
- Opens the door for more enhancements in the future, such as allowing
all UIs to reattach instead of only the "current" UI.
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
Problem:
- Progress-events are filtered by "source". But "source" is not required by nvim_echo.
- Without "++nested" (force=false), nvim_echo in an event-handler does not trigger Progress events.
- vim.health does not declare a "source".
Solution:
- Make source mandatory for progress-messages
- Enable ++nested (force=true) by default when firing Progress event.
- Set "source" in vim.health module.
Problem: unnecessary restrictions for defining dictionary function
names
Solution: Allow defining dict function with bracket key that is not a
valid identifier (thinca)
In Vim script, "function obj.func()" and "function obj['func']()" both
define a dictionary function. However, the bracket form required the
key to match function naming rules (eval_isnamec), so
"function obj['foo-bar']()" failed with E475.
Assigning and calling already work: "let obj['foo-bar'] = obj.func"
and "call obj['foo-bar']()" are valid. Only the definition was
incorrectly restricted.
Skip the identifier check when the name comes from fd_newkey (i.e. the
key was given in bracket notation). Dictionary keys may be any string.
Supported by AI
closes: vim/vim#19833f89662722d
Co-authored-by: thinca <thinca@gmail.com>
Problem: setting one underline style to false clears bits belonging
to another style. `{underdouble = true, underdashed = false}` results
in undercurl because CHECK_FLAG_WITH_KEY does `m &= ~flag` which
doesn't work for multi-bit encoded values sharing HL_UNDERLINE_MASK.
Solution: use a local variable to derive the correct clear mask from
the flag. Clear the whole HL_UNDERLINE_MASK field instead of individual
bits, and only clear on false when the current style actually matches.
Changing REUSE_MAX from 4 to 0 produces the following ASAN error:
=================================================================
==924403==ERROR: AddressSanitizer: heap-use-after-free on address 0x7d33333ed128 at pc 0x55f165a47a86 bp 0x7fff40e71690 sp 0x7fff40e71688
READ of size 1 at 0x7d33333ed128 thread T0
#0 0x55f165a47a85 in socket_address_tcp_host_end **/src/nvim/event/socket.c:37:30
#1 0x55f1667d6349 in channel_connect_event **/src/nvim/ui_client.c:296:17
#2 0x55f165a35af6 in multiqueue_process_events **/src/nvim/event/multiqueue.c:159:7
#3 0x55f165a308f6 in loop_poll_events **/src/nvim/event/loop.c:81:3
#4 0x55f1667d3fbc in ui_client_run **/src/nvim/ui_client.c:172:5
#5 0x55f165e1f2e1 in main **/src/nvim/main.c:367:5
#6 0x7f23340bc6c0 in __libc_start_call_main /usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:59:16
#7 0x7f23340bc7f8 in __libc_start_main /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:360:3
#8 0x55f16521d044 in _start (**/build/bin/nvim+0xcb9044) (BuildId: 6c8517919bbcd317c6bb5675d1eb3f2c7c319e2c)
0x7d33333ed128 is located 40 bytes inside of 4096-byte region [0x7d33333ed100,0x7d33333ee100)
freed by thread T0 here:
#0 0x55f16532547d in free.part.0 asan_malloc_linux.cpp.o
#1 0x55f165fc2380 in xfree **/src/nvim/memory.c:159:3
#2 0x55f165fc5b6d in free_block **/src/nvim/memory.c:786:5
#3 0x55f165fc5c38 in arena_mem_free **/src/nvim/memory.c:798:5
#4 0x55f166082dd2 in parse_msgpack **/src/nvim/msgpack_rpc/channel.c:258:7
#5 0x55f166078ade in receive_msgpack **/src/nvim/msgpack_rpc/channel.c:217:5
#6 0x55f165a4683b in read_event **/src/nvim/event/rstream.c:234:23
#7 0x55f165a462d8 in invoke_read_cb **/src/nvim/event/rstream.c:287:3
#8 0x55f165a42e11 in read_cb **/src/nvim/event/rstream.c:149:3
#9 0x55f166bdc28b in uv__read **/.deps/build/src/libuv/src/unix/stream.c:1145:7
#10 0x55f166bdba97 in uv__stream_io **/.deps/build/src/libuv/src/unix/stream.c:1208:5
#11 0x55f166bca7fe in uv__io_cb **/.deps/build/src/libuv/src/unix/core.c:930:5
#12 0x55f166be6251 in uv__io_poll **/.deps/build/src/libuv/src/unix/linux.c:1546:11
#13 0x55f166bc9c57 in uv_run **/.deps/build/src/libuv/src/unix/core.c:460:5
#14 0x55f165a30be7 in loop_uv_run **/src/nvim/event/loop.c:59:3
#15 0x55f165a30864 in loop_poll_events **/src/nvim/event/loop.c:80:26
#16 0x55f1667d3fbc in ui_client_run **/src/nvim/ui_client.c:172:5
#17 0x55f165e1f2e1 in main **/src/nvim/main.c:367:5
#18 0x7f23340bc6c0 in __libc_start_call_main /usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:59:16
#19 0x7f23340bc7f8 in __libc_start_main /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:360:3
#20 0x55f16521d044 in _start (**/build/bin/nvim+0xcb9044) (BuildId: 6c8517919bbcd317c6bb5675d1eb3f2c7c319e2c)
previously allocated by thread T0 here:
#0 0x55f1653263e5 in malloc (**/build/bin/nvim+0xdc23e5) (BuildId: 6c8517919bbcd317c6bb5675d1eb3f2c7c319e2c)
#1 0x55f165fc2054 in try_malloc **/src/nvim/memory.c:113:15
#2 0x55f165fc22b4 in xmalloc **/src/nvim/memory.c:147:15
#3 0x55f165fc4d5d in alloc_block **/src/nvim/memory.c:717:12
#4 0x55f165fc4e09 in arena_alloc_block **/src/nvim/memory.c:724:20
#5 0x55f165fc5113 in arena_alloc **/src/nvim/memory.c:746:5
#6 0x55f166096d98 in api_parse_enter **/src/nvim/msgpack_rpc/unpacker.c:161:5
#7 0x55f166aa290e in mpack_parse_tok **/src/mpack/object.c:56:29
#8 0x55f166aa4fa9 in mpack_parse **/src/mpack/object.c:82:16
#9 0x55f166099de9 in unpacker_advance **/src/nvim/msgpack_rpc/unpacker.c:343:12
#10 0x55f1660825c9 in parse_msgpack **/src/nvim/msgpack_rpc/channel.c:248:10
#11 0x55f166078ade in receive_msgpack **/src/nvim/msgpack_rpc/channel.c:217:5
#12 0x55f165a4683b in read_event **/src/nvim/event/rstream.c:234:23
#13 0x55f165a462d8 in invoke_read_cb **/src/nvim/event/rstream.c:287:3
#14 0x55f165a42e11 in read_cb **/src/nvim/event/rstream.c:149:3
#15 0x55f166bdc28b in uv__read **/.deps/build/src/libuv/src/unix/stream.c:1145:7
#16 0x55f166bdba97 in uv__stream_io **/.deps/build/src/libuv/src/unix/stream.c:1208:5
#17 0x55f166bca7fe in uv__io_cb **/.deps/build/src/libuv/src/unix/core.c:930:5
#18 0x55f166be6251 in uv__io_poll **/.deps/build/src/libuv/src/unix/linux.c:1546:11
#19 0x55f166bc9c57 in uv_run **/.deps/build/src/libuv/src/unix/core.c:460:5
#20 0x55f165a30be7 in loop_uv_run **/src/nvim/event/loop.c:59:3
#21 0x55f165a30864 in loop_poll_events **/src/nvim/event/loop.c:80:26
#22 0x55f1667d3fbc in ui_client_run **/src/nvim/ui_client.c:172:5
#23 0x55f165e1f2e1 in main **/src/nvim/main.c:367:5
#24 0x7f23340bc6c0 in __libc_start_call_main /usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:59:16
#25 0x7f23340bc7f8 in __libc_start_main /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:360:3
#26 0x55f16521d044 in _start (**/build/bin/nvim+0xcb9044) (BuildId: 6c8517919bbcd317c6bb5675d1eb3f2c7c319e2c)
SUMMARY: AddressSanitizer: heap-use-after-free **/src/nvim/event/socket.c:37:30 in socket_address_tcp_host_end
Shadow bytes around the buggy address:
0x7d33333ece80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7d33333ecf00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7d33333ecf80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7d33333ed000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7d33333ed080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x7d33333ed100: fd fd fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd
0x7d33333ed180: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x7d33333ed200: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x7d33333ed280: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x7d33333ed300: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x7d33333ed380: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==924403==ABORTING
Problem:
Currently, we recommend always inserting text above prompt-line in
prompt-buffer. This can be done using the `:` mark. However, although
we recommend it this way it can sometimes get confusing how to do it
best.
Solution:
Provide an api to append text to prompt buffer. This is a common
use-case for things using prompt-buffer.
Problem:
When running nvim in headless mode with `cmdheight=0`, an extra newline
is prepended to output (eg. `nvim --clean --cmd 'set cmdheight=0'
--headless -c 'echo 1 | q' ` prints `\n1` instead of `1`), because
`!ui_has(kUIMessages)` is always true in headless mode, causing `p_ch ==
0` in `msg_start()` to unconditionally trigger `msg_putchar('\n')` which
writes a newline to stdout.
Solution:
When in headless printf mode with `p_ch == 0` and no prior output on the
current line, call `msg_puts_display("\n", ...)` directly instead of
`msg_putchar('\n')`, so the grid is still updated for correct screen
positioning but no newline is written to stdout.
Problem:
Currently, there's no way to distinguish progress messages coming from
different sources. Nor can Progress event be easily filtered based on
source.
Solution:
- Add "source" field to nvim_echo-opts.
- The Progress event pattern is now defined by the "source" field.
- Include the "title" as ev.data.
- Unrelated change: set force=false to disable nesting.
vim-patch:9.2.0234: test: Test_close_handle() is flaky
vim-patch:a603175c6 runtime(manpager): use \x07 instead of \a for BEL in OSC 8 regex
vim-patch:9.2.0245: xxd: color output detection is broken
vim-patch:9.2.0247: popup: popups may not wrap as expected
vim-patch:e09000a78 runtime(doc): Update examples in xxd.1 manpage
vim-patch:be7ef8a19 translation(it): Update Italian xxd man page
vim-patch:9.2.0242: memory leak in check_for_cryptkey()
vim-patch:9.2.0243: memory leak in change_indent()
vim-patch:9.2.0244: memory leak in eval8()
vim-patch:9.2.0246: memory leak in globpath()
Problem:
The temp_dict in `do_autocmd_progress()` is sized 7, but the max is 6 (id, text, percent, status, title, data). The extra capacity is rather misleading.
Solution:
make the size of the dict 6.
Problem:
- Small error in port of v9.1.0678, causing :ball to check w_locked for the
wrong window.
- After #27439, free_all_mem() may not wipe out buffers that were open in more
than one window before windows were freed.
Solution:
- Check win_locked() for wp in ex_buffer_all(), not curwin.
- Set b_nwindows to 0 in free_all_mem() before calling close_buffer().
Ref: https://github.com/neovim/neovim/pull/38473#issuecomment-4125117681
No need to block these fixes on that.
free_all_mem() change also looks like it fixed the existing "N lua references were
leaked!" warnings on the CI.
Problem: nvim_set_hl always replaces all attributes.
Solution: Add update field. When true, merge with existing
attributes instead of replacing. Unspecified attributes are preserved.
If highlight group doesn't exist, falls back to reset mode.
Problem:
Currently same progress stat get's displayed on statusline of all
windows. This is repeatitive and noisy.
Solultion:
Only display progress-status on the focused window
Problem:
Currently, when multiple progress are on going we show it as Progress:
{N} items {percent}% format. It can be simplified sinnce items doesn't
really add enough value for the valuable space it takes in statusline
Solution:
Change format to Progress: {percent}%({N})
Problem: Compiler warning in strings.c
(Timothy Rice, after v9.2.0031)
Solution: Return early when str_m is zero
(Hirohito Higashi)
fixes: vim/vim#19795closes: vim/vim#19800347e8c1e7d
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Problem:
`vim.keymap.*.Opts.buf` allows `boolean` aliases for more widely
used `integer?` values, `true` -> `0` and `false` -> `nil`. This
conversion is unnecessary and can be handled at call sites.
Solution:
As a follow-up to deprecating the `buffer` option, drop support for
boolean values for the new `buf` option. The deprecated `buffer`
continues to support booleans for backward compatibility.
vim-patch:9.2.0166: Coverity warning for potential NULL dereference
vim-patch:9.2.0170: channel: some issues in ch_listen()
vim-patch:9.2.0173: tests: Test_balloon_eval_term_visual is flaky
vim-patch:9.2.0177: Vim9: Can set environment variables in restricted mode
vim-patch:9.2.0183: channel: using deprecated networking APIs
vim-patch:9.2.0187: MS-Windows: rendering artifacts with DirectX renderer
vim-patch:2b70de167 CI: bump actions/upload-artifact to v7
vim-patch:a907a7f73 runtime(doc): disable color codes when generating ascii man pages in Makefile
vim-patch:c9e5aeff3 runtime(doc): Update Italian xxd manpage
vim-patch:9.2.0210: tests: Test_xxd tests are failing
vim-patch:9774651ec runtime(manpager): Strip OSC 8 hyperlink sequences in manpager plugin
vim-patch:9.2.0220: MS-Windows: some defined cannot be set on Cygwin/Mingw
vim-patch:9.2.0224: channel: 2 issues with out/err callbacks
vim-patch:243dcd1bc translation(it): Update Italian xxd man page
vim-patch:9.2.0230: popup: opacity not working accross vert splits
vim-patch:9.2.0231: Amiga: Link error for missing HAVE_LOCALE_H
vim-patch:9.2.0176: external diff is allowed in restricted mode
vim-patch:9.2.0188: Can set environment variables in restricted mode
vim-patch:9.2.0191: feat(has): add support for 'android' and 'termux' feature flags
Problem: Option handling for key:value suboptions is limited
Solution: Improve :set+=, :set-= and :set^= for options that use
"key:value" pairs (Hirohito Higashi)
For comma-separated options with P_COLON (e.g., diffopt, listchars,
fillchars), :set += -= ^= now processes each comma-separated item
individually instead of treating the whole value as a single string.
For :set += and :set ^=:
- A "key:value" item where the key already exists with a different value:
the old item is replaced.
- An exact duplicate item is left unchanged.
- A new item is appended (+=) or prepended (^=).
For :set -=:
- A "key:value" or "key:" item removes by key match regardless of value.
- A non-colon item removes by exact match.
This also handles multiple non-colon items (e.g., :set
diffopt-=filler,internal) by processing each item individually, making
the behavior order-independent.
Previously, :set += simply appended the value, causing duplicate keys to
accumulate.
fixes: vim/vim#18495closes: vim/vim#19783e2f4e18437
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Problem: No 'incsearch' highlighting support for :uniq
Solution: Add :uniq support (Hirohito Higashi)
closes: vim/vim#1978048137e4e48
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Problem: "zb" scrolls incorrectly with cursor on fold.
Solution: Set w_botline to the line below the fold (zeertzjq).
related: neovim/neovim#38413
closes: vim/vim#197855a3b75d67b
The `buffer` option remains functional but is now undocumented.
Providing both will raise an error. Since providing `buf` was disallowed
before, there is no code that will break due to using `buffer` alongside
`buf`.
Problem: call stack can be corrupted, because calculated remaining
capacity for call stack string can underflow (after v9.1.1983)
Solution: Calculate capacity against maximum capacity
(Sergey Vlasov).
closes: vim/vim#197598e0483c2f4
Co-authored-by: Sergey Vlasov <sergey@vlasov.me>
Problem:
Default statusline doesn't show progress status.
Solution:
- Provide `vim.ui.progress_status()`.
- Include it in the default 'statusline'.
How it works:
Status text summarizes "running" progress messages.
- If none: returns empty string
- If one running item: "title: percent%"
- If multiple running items: "Progress: N items avg-percent%"
Problem:
Terminal refresh may be missed if buffer update callbacks poll for uv
events. Example test failure on FreeBSD:
FAILED test/functional/terminal/buffer_spec.lua @ 1049: :terminal buffer scrollback is correct if buffer update callbacks poll for uv events
test/functional/terminal/buffer_spec.lua:1004: Row 1 did not match.
Expected:
|*19995: TEST{MATCH: +}|
|*19996: TEST{MATCH: +}|
|*19997: TEST{MATCH: +}|
|*19998: TEST{MATCH: +}|
|*19999: TEST{MATCH: +}|
|^[Process exited 0] |
|{5:-- TERMINAL --} |
Actual:
|*19696: TEST |
|*19697: TEST |
|*19698: TEST |
|*19699: TEST |
|*19700: TEST |
|^[Process exited 0] |
|{5:-- TERMINAL --} |
Solution:
Call changed_lines() after resetting invalid region in refresh_screen().
Handle terminal being invalidated in the middle of refresh_timer_cb().
Problem: Vim may freeze if setcmdline() is called while the wildmenu or
cmdline popup menu is active (rendcrx)
Solution: Cleanup completion state if cmdbuff_replaced flag has been set
(Yasuhiro Matsumoto)
fixes: vim/vim#19742closes: vim/vim#19744332dd22ed4
Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Problem: The glob() function on Unix-like systems does not escape
newline characters when expanding wildcards. A maliciously
crafted string containing '\n' can be used as a command
separator to execute arbitrary shell commands via
mch_expand_wildcards(). This depends on the user's 'shell'
setting.
Solution: Add the newline character ('\n') to the SHELL_SPECIAL
definition to ensure it is properly escaped before being
passed to the shell (pyllyukko).
closes: vim/vim#19746
Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-w5jw-f54h-x46c645ed6597d
Co-authored-by: pyllyukko <pyllyukko@maimed.org>
Problem:
Mouse popup menus (right-click context menus) do not respect the
'pumborder' option and could overflow screen boundaries when borders
were enabled near the edge.
Solution:
- Remove the mouse menu exclusion from border rendering.
- Add boundary check to shift menu left when border would exceed screen
width, ensuring complete visibility of menu content and borders.
Problem: using copy_option_part() can be improved
Solution: Refactor and use the return value of copy_option_part() to
avoid strlen() calls (John Marriott).
In addition, this commit includes the following changes:
memline.c:
- In recover_names():
- Replace calls to vim_strsave() with vim_strnsave() for the literal
strings
- Use a string_T to store local variable dir_name.
bufwrite.c:
- In buf_write()
- move variable wp to where it is used.
help.c:
- In fix_help_buffer():
- replace call to add_pathsep() with after_pathsep()
optionstr.c:
- In export_myvimdir():
- use a string_T to store local variable buf
- replace call to add_pathsep() with after_pathsep()
scriptfile.c:
- In do_in_path():
- use a string_T to store local variable buf
- measure the lengths of prefix and name once before the while loop
- replace call to add_pathsep() with after_pathsep()
- move some variables closer to where they are used
spellfile.c:
- In init_spellfile():
- use a string_T to store local variable buf
closes: vim/vim#19725a74e5fc5b9
Co-authored-by: John Marriott <basilisk@internode.on.net>
Problem:
If buffer update callbacks poll for uv events during terminal scrollback
refresh, new output from PTY process may lead to incorrect scrollback.
Solution:
Don't poll for output to the same terminal as the one being refreshed.