Problem:
Flickering may occur when paging up/down in big files, as ranges for semantic
tokens are requested. This happens with LSP servers like gopls which return
"/full" semantic tokens if the file is too big, where we fall back to
viewport-range token retrievals.
Solution:
Broaden the requested ranges to one viewport of "overscan" on each side plus
some padding if possible:
(viewport_topline - viewport_height)..(viewport_botline + viewport_height)
(cherry picked from commit 3ed78daf83)
Problem:
`foldcolumn` is empty for virtual lines above the start of a nested
fold.
Solution:
For virtual lines, compute the outer fold level and display it by
reusing the logic from `fill_foldcolumn`.
(cherry picked from commit fe154f4d45)
Problem:
`nvim -u NONE -d <(xxd one) <(xxd two)` has weird behavior.
Process substitution `<(...)` is a pipe and not a seekable file.
Test case:
cat /dev/random | head -c 10240 > one
cp one two
cat /dev/random | head -c 10240 >> two
nvim -u NONE -d <(xxd one) <(xxd two)
Solution:
Workaround the issue by skipping `nvim.difftool` if the 2 args are not
directories; fall-through to the builtin diff handling.
Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
(cherry picked from commit 2fd2361a9d)
Following is a list of commits (fixes/features only) in this release.
See `:help news` in Nvim for release notes.
BREAKING
--------------------------------------------------------------------------------
- f54f566bf8 diagnostic: deprecate `format` as a table
FEATURES
--------------------------------------------------------------------------------
- fd1b193d51 :restart: v:starttime, v:exitreason #39319
- c407e3e67b eval: treat Lua string as "blob" in writefile() #39098
- a0dcdcd8a0 treesitter: provide select()
- 49efe692f3 vim.pos: accept buf=0 for current buf #39414
- ad27075c8d vim.pos: pos:to_offset(), pos.offset() (#39639)
- b05675bccc `opts.scope` in `vim.ui.input` (#39906)
PERFORMANCE
--------------------------------------------------------------------------------
- 96d5dd4107 vim.pos: use numeric index internally #39447
FIXES
--------------------------------------------------------------------------------
- e230ff0439 vim._with may silence all cmdline-errors #34301
- 781c43ea05 api: adjust Visual position after nvim_buf_set_text #30690
- 5b8268356a api: don't update 'title' when renaming non-curbuf #39743
- 4df16ecdb9 api: `LuaRef` leak in `nvim_set_keymap` on LHS too long (>=66 bytes) (#39376)
- e5d6d2e769 api: leak `preview` callback `LuaRef` in `nvim_create_user_command` (#39377)
- f0baa18043 channel: stack-buffer-overflow with exit during connection (#39387)
- d9baaf7da1 ci: generate more data to stress output throttling test #39577
- f62ce1a42f difftool: handle filenames containing spaces #39740
- fb56d50032 eval: writestring() handling of null #39328
- 822778f7e5 excmd: use realtime for v:starttime, :uptime #39425
- 8fccb26cd3 fold: virtual lines duplicate foldopen (#39891)
- 10695f44af health: set 'tags' for help filetype #39742
- e069022215 help: fix CTRL character issue for :help {subject} #39537
- 445fe8a6b7 lsp: calc correct screen_width when opts.relative == 'editor' (#39977)
- 93dc301781 lsp: callHierarchy/outgoingCalls ranges are relative to caller, not callee #39336
- 5e6c8d4edf lsp: check window is still valid after async request #39396
- 8919b02eba lsp: dynamic registration for off-spec method #39544
- c4d3a3d363 lsp: filter code_action diagnostics to the cursor #38988
- 27d01f2dbb lsp: handle null id in JSON-RPC responses
- aedbae4ab6 lsp: handle self-mapped methods in supports_method #39383
- 0bd6e62509 lsp: malformed edit if apply_text_edits() is called twice (#39347)
- 378f5f49b3 lsp: show meaningful error on invalid completion response (#39476)
- c9ca59ad28 lsp: util.lua attempt to concatenate userdata #39510
- e67f9c5853 lua: avoid `__index` when deciding if a table is a list #39556
- 731f9743e2 lua: don't strip debuginfo in precompile module #39191
- b0bfce290f lua: fields of `nvim.spellfile.Opts` are optional #39902
- 34bf0472ab marks: don't use spell decorations from other lines (#39441)
- d1cf3ab4c3 marks: read from the correct variable in conceal_lines mark collection (#39991)
- 33b6b0bfe5 messages: avoid recursive rtp build due to msg_show #39888
- d725ead5ec messages: reset redirection message column after :echon #39472
- b490fba786 mouse: mouse=n should not adjust visual selection
- 17ddfde131 net: `:edit <uri>` should set buftype=nofile #39915
- dd95e434e3 pack: only use tags that strictly comply with semver spec #39342
- 585c93204f path: `nvim_get_runtime_file` fails on DOS 8.3 filename #40144
- 42f6c1c443 prompt: handle multi-element lists in prompt_appendbuf #39550
- 915880d252 shada: bdelete'd buffers not stored in oldfiles #39070
- e4a9bd55b2 shada: set correct buffer number for local marks on read #39712
- 2389cf2e39 shell: preserve CR when `:!` outputs to binary-mode buffer #39558
- 98098d8466 startup: emitting useless OptionSet
- ae9f7accdd statusline: no cmdline ruler for autocommand window
- 39e8c584d5 terminal: memory leak in pending TermRequest StringBuilder #39333
- fa69cac7e3 terminal: memory leak when pasting '=' register (#39738)
- 3a3405d964 test: only test for unibilium if a valid compilation string exists
- dcf9e8a98e treesitter: crash in ts_parser_delete after gc #39497
- 4f22640b86 treesitter: get_node_text() inconsistent trailing newline #39409
- 654c964d1a trust: hash unchanged empty buffers as empty files #39027
- 70f22713a1 ui2: entering the pager fails if `<ESC>` is remapped to `:fclose` (#39462)
- 13041a067e ui2: error E518 when typing "vim:" in cmdline #39599
- a0ee5811b1 unittest: preprocess failure when __typeof declarations present #40145
- b9d39f5bb2 vim.fs: fs.dir() may return nil "type" on some filesystems #39749
- be4e7cfd6a vim.hl: range(0,…) highlight not cleared after buffer-switch #40130
- 79fd0b6655 vim.range: empty ranges semantics vs regular ranges #39474
- 2ec758f403 vim.range: validate arguments on all cases #39415
- f83e0dcaf8 vim.secure: read() command injection vulnerability #39918
BUILD
--------------------------------------------------------------------------------
- a612ada984 version bump
- b1b489b316 docs: sort/lint class fields and keysets
- 4f6c711fc0 test: declaration specifier expected near '_Static_assert' #39788
VIM PATCHES
--------------------------------------------------------------------------------
- 964e797fdf 9.2.0395: tests: Test_backupskip() may read from $HOME (#39417)
- b013940391 9.2.0435: [security]: backticks in 'path' may cause shell execution on completion
- f9f2596288 9.2.0436: Buffer overflow when parsing overlong errorformat lines (#39578)
- 0aa77cb78c 9.2.0443: GUI: cancelling save dialog overwrites or discards unnamed buffer (#39617)
- 15a58bb02a 9.2.0444: Cannot set 'path' option via modeline
- 03af1ec931 9.2.0450: [security]: heap buffer overflow in spellfile.c read_compound() (#39660)
- 2902ec0541 9.2.0458: Crash with invalid shellredir/shellpipe value (#39691)
- 647b6be489 9.2.0461: Corrupted undofile causes use-after-free (#39707)
- c8e0af85e0 9.2.0500: filetype: some html files wrongly recognized as htmlangular (#39880)
- d9b8bac435 9.2.0508: completion: cannot complete user cmd :K with 'ignorecase' (#39944)
- 15a3318e13 9.2.0513: [security]: memory safety issues in spellfile.c (#39960)
- cc1982bd06 9.2.0517: quickfix: can set quickfixtextfunc in restricted/sandbox mode (#39970)
- dfd6cd477f bfebd12: runtime(javacc): Check for existence of javaFuncDef syn group before clearing it (#39731)
- a76bcbe3b8 partial:9.2.0315: missing bound-checks (#39334)
Problem:
stdpath() may return a DOS 8.3 "shortened" filename, because Windows
truncates some long usernames into `6ch~N` names. Then features such
as `nvim_get_runtime_file` fail to find the file.
Analysis:
When expanding an 8.3 filename path like `C:/Users/ADMINI~1/AppData/*`,
we treat `~` as a special character and first check whether a directory
named `ADMINI~1` exists under `Users`. Since no such directory actually
exists, the expansion fails.
Solution:
Treat `~` as a literal character in `do_path_expand`. Since the `~/`
case is already handled in `gen_expand_wildcards`, any remaining `~` is
just a literal character and will later be escaped to `\~` by
`file_pat_to_reg_pat` if needed.
(cherry picked from commit 7bf2ab4b87)
Problem:
When `vim.hl.range(0, …, { timeout = N })` is called, the deferred
`range_hl_clear` captures `buf=0`, which resolves to an arbitrary
"current buffer" at timeout. This may cause a stale highlight that never
gets cleared.
Solution:
Resolve `buf=0` explicitly, before `range_hl_clear` captures it.
(cherry picked from commit ec7dab077b)
Builds with -DNDEBUG do not contain the compilation string, so the test
will fail even if nvim is built with unibilium.
Similarly, zig builds only report "Compilation: TODO", so they also fail
the test even when build with unibilium
Detect both scenarios and skip the test, rather than failing it.
(cherry picked from commit b7fd8cbd2b)
Problem: tests: Test_backupskip() may read from $HOME
Solution: Set $HOME to an empty value, use --clean
(D Ben Knoble)
Even though we unset HOME, we can see via scriptnames that user files
are still sourced! One of my installed plugins warns when not compiled
with +python3, so this test has a "press Enter" prompt.
Use `--clean` like most other GetVimProg()'s do to fix it. Some tests
use `system()` instead, but that turns this test into a failure rather
than passing; I'm not sure why other tests don't suffer from this.
To prove to ourselves, we can use code like this:
diff --git i/src/testdir/test_options.vim w/src/testdir/test_options.vim
index a408e20e1..044364a54 100644
--- i/src/testdir/test_options.vim
+++ w/src/testdir/test_options.vim
@@ -1179,6 +1179,7 @@ func Test_backupskip()
" P_NODUP). Run this in a separate instance and write v:errors in a file,
" so that we see what happens on startup.
let after =<< trim [CODE]
+ call writefile([execute('scriptnames')], 'foo')
let bsklist = split(&backupskip, ',')
call assert_equal(uniq(copy(bsklist)), bsklist)
call writefile(['errors:'] + v:errors, 'Xtestout')
@@ -1196,7 +1197,7 @@ func Test_backupskip()
" unset $HOME, so that it won't try to read init files
let saveenv['HOME'] = getenv("HOME")
call setenv('HOME', v:null)
- exe 'silent !' . cmd
+ exe 'silent !' . cmd .. ' --cmd "echo &rtp"'
call assert_equal(['errors:'], readfile('Xtestout'))
" restore environment variables
Here, that causes "foo" to include a bunch of files under ~/.vim. I'm
not sure why this happens, but lets paper over it for the test.
We can also tell that (orthogonal to --clean) setting HOME='' works too.
Let's do that in addition since unsetting HOME isn't quite enough.
closes: vim/vim#200518d9c383aaf
Co-authored-by: D. Ben Knoble <ben.knoble+github@gmail.com>
(cherry picked from commit 0039a13fe4)
Problem:
Currently, only some filesystems (Btrfs, ext2, ext3, ext4) have full
support of accessing the `dirent` entry-type. On other filesystems,
`uv.fs_scandir_next` may return `nil` for an existing but unsupported
entry-type.
This means consumers (such as `fs.dir()`), cannot know if `nil` means
"non-existent" or "unsupported".
Solution:
Fall back to `uv.fs_lstat` when `etype` is `nil`; return "unknown" if it
fails.
(cherry picked from commit 4b5f026ac9)
Problem: Not using current mark for namespace check during iteration for conceal_line marks.
Solution: Use the appropriate mark variable for namespace check.
(cherry picked from commit 70792aa6e4)
Problem: quickfix: can set quickfixtextfunc in restricted/sandbox mode
(tacdm)
Solution: Disallow setting the quickfixtextfunc option from a sandbox
and restricted mode (Yegappan Lakshmanan).
closes: vim/vim#20305cb8510d470
Co-Authored-by: tacdm
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
(cherry picked from commit 1a064abb0a)
Problem: Cmdline ruler may be drawn for autocommand window.
Solution: Check that the current window is not an autocommand window
when deciding whether to draw the ruler.
(cherry picked from commit b58ce1ab79)
Problem: completion: cannot complete user cmd :K with 'ignorecase'
(rendcrx)
Solution: Skip the short-circuit when 'ignorecase' is set
(Yasuhiro Matsumoto)
The set_cmd_index() short-circuit for the :k command treats ":k<X>" as
":k {X}" (mark argument), which makes ":kz<Tab>" never reach the
command-name expansion path. With 'ignorecase' the same prefix on other
letters (":gz<Tab>") completes a user command like :Gz, so the result is
inconsistent. Skip the short-circuit when 'ignorecase' is set; default
behaviour is preserved so the existing :k tests still pass.
fixes: vim/vim#20241closes: vim/vim#20275b54e57ee54
Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
(cherry picked from commit dee602e659)
Problem: If there are pending messages when starting to build the
runtime search path, a msg_show callback may invoke
runtime_search_path_validate() recursively.
Solution: Avoid msg_show callback by ensuring messages are flushed.
(cherry picked from commit 53da0c5060)
Problem:
Virtual lines above a line where a fold starts show `foldopen` in
`foldcolumn`.
Solution:
Check if the line below the virtual one is inside a fold that starts
higher up or if it's the start of a fold. In the latter case, don't show
anything in `foldcolumn` for the virtual line.
refactor: lint
(cherry picked from commit 526ae1cc1b)
Problem:
When mouse=n is set
- Dragging the mouse enters visual mode, and then stops listening for
mouse events.
- Double/Triple/Quad clicking performs selections.
- Clicking in visual mode moves the cursor (though not through the TUI).
Solution:
Explicitly gate mouse actions that affect visual mode with a check for
MOUSE_VISUAL. This matches the behavior described in :help mouse.
> If enabled for "v" (Visual mode) then double-click selects word-wise,
> triple-click makes it line-wise, and quadruple-click makes it
> rectangular block-wise.
(cherry picked from commit 24f7182390)
feat(ui): vim.ui.input(opts.scope) #39570
Problem: There is no way for a `vim.ui.input` caller to indicate for
which scope the input is. As in "This input is for something at cursor
scope". This information can be useful for `vim.ui.input`
implementation to tweak its behavior and presentation:
- Show different floating window depending on the scope. For example:
- Near cursor for "cursor" scope.
- At line start for "line" scope.
- In window corner for "buffer" and "window" scopes.
- In whole editor corner for "tabpage", "editor", "project" scopes.
- Navigate through history only for inputs with the same scope.
Solution: Document new `opts.scope` for `vim.ui.input`. Use it in the
codebase.
Problem: filetype: some html files are wrongly recognized as htmlangular
Solution: Use the \< atom to anchor ng-template and ng-content to start
of word (truffle)
Prevent false-positive htmlangular detection on words containing
'ng-template' or 'ng-content' as a substring (e.g. 'song-template',
'sing-content'). Anchor both branches with \< to require a word start,
matching the \<DTD\s\+XHTML\s idiom used five lines below.
related: neovim/neovim#39778.
closes: vim/vim#20246354ab1a69e
Co-authored-by: truffle <truffleagent@gmail.com>
(cherry picked from commit f3bb21e71d)
Problem:
Visual selection could end up in the wrong place after
nvim_buf_set_text or nvim_buf_set_lines. In some delete cases,
Visual.lnum was already clamped before the line shift happened, so the
adjustment got skipped.
Solution:
Split fix_cursor_cols into reusable fix_pos_col logic and reuse it
for Visual updates. Also adjust Visual.lnum before changed_lines so
the shift uses the original position before final clamping.
(cherry picked from commit 450ba41436)
Problem:
During startup, we manually trigger a useless and misleading `OptionSet`
event, which doesn't set `v:option_*` values (this is a limitation of
`nvim_exec_autocmds`).
ad4bc2d90c/runtime/lua/vim/_core/defaults.lua (L939).
Solution:
The `nvim_exec_autocmds('OptionSet',…)` call does not serve any purpose
since 5cbb9d613b, so just drop it.
Problem:
After closing and reopening Neovim, ]' and [' fail with E92: Buffer 0
not found for marks restored from ShaDa. Direct jumps like 'a work
because mark_get_local() rewrites fnum before returning, but ]' uses
getnextmark() which does not, leaving fnum = 0.
Solution:
Set .fnum = buf->b_fnum when restoring local marks from ShaDa.
(cherry picked from commit 0b96b3cd52)
Problem:
On "arm clang unittest" CI job, `make unittest` sometimes fails with
lots of these messages:
FAILED test/unit/testutil.lua @ 773: ...
test/unit/testutil.lua:773:
test/unit/testutil.lua:297: declaration specifier expected near '_Static_assert' at line 429
exit code: 256
stack traceback:
test/unit/testutil.lua:773: in function 'itp_parent'
test/unit/testutil.lua:811: in function <test/unit/testutil.lua:801>
Solution:
Update filter_complex_blocks.
(cherry picked from commit adb5d8a646)
Problem:
Using the `DiffTool` plugin (e.g. through `nvim -d ...` or `:DiffTool
<file1> <file2>` fails if a space is in one of the paths. This occurs
because the `diff` wraps the paths with quotes (`'`) if space
characters are present, which the line diff regex fails to parse.
Solution:
Update regex to handle quoted paths by matching the string within the
quotes, if it exists.
(cherry picked from commit 1e09b020e5)
Problem:
When using prompt_appendbuf with multi-element list,
the first item is concated and rest replace the prompt instead of
inserting the lines before the prompt.
Solution:
Concat first element with replace_buf and insert the rest of the list
with set_buffer_lines.
Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
(cherry picked from commit a977e1077b)
Problem:
When using the default `lua_ls` config from nvim-lspconfig, the following info message gets printed:
```
LSP[lua_ls] Too large file: src/nvim/eval.lua skipped. The currently set size limit is: 500 KB, and the file size is: 511.133 KB.
```
Solution:
Set `workspace.preloadFileSize` to 1000 KB instead of the default 500 KB.
(cherry picked from commit 5d1910e1e0)
Co-authored-by: Olivia Kinnear <git@superatomic.dev>
Problem: 'title' is updated when changing the name of a non-current
buffer with nvim_buf_set_name().
Solution: Set RedrawingDisabled when renaming the buffer.
(cherry picked from commit 96fc7c150f)
Problem: Message redirection column for captured output is not reset
after :echon since (4260f73, e63346df).
Solution: Ensure msg_ext_append is set before the kind with :echon.
(cherry picked from commit ce9f4f0369)
Problem:
The `:checkhealth` buffer uses the help syntax, so help tag links (e.g.
`|clipboard|`) are highlighted like they are in help buffers. However,
unlike in help buffers, `CTRL-]` doesn't jump to the relevant help file.
I expect that if the `:checkhealth` buffer looks like a help buffer,
then it should behave like one where it makes sense. This comment from
/r/neovim suggests that this was the intention:
https://www.reddit.com/r/neovim/comments/5ghv3r/see_clipboard_how/dascnry/.
Solution:
Set `'tags'` in `checkhealth` buffers so that `:tag` and friends look
for tags in the help tags files.
(cherry picked from commit c4285acb92)
Problem: The four pointer-resolution loops in u_read_undo() lack
an i != j guard, so a header whose uh_next.seq equals
its own uh_seq resolves uh_next.ptr to itself. On
buffer close, u_freeheader() sees uhp->uh_next.ptr !=
NULL and skips updating b_u_oldhead, so u_blockfree()
dereferences the freed header on the next iteration.
The same pattern applies to uh_prev, uh_alt_next and
uh_alt_prev. A crafted .un~ file in the same directory
as a text file can trigger the use-after-free and
subsequent double-free when the buffer is closed.
(Daniel Cervera)
Solution: Add an i != j guard to each of the four resolution
loops, matching the guard already present in the
duplicate-detection loop above.
closes: vim/vim#20168
Supported by AI
4f610f07b7
Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit 2d5f56c0aa)
Problem: Crash with invalid shellredir/shellpipe value
(bfredl)
Solution: Validate the option and allow only a single "%s".
fixes: vim/vim#20157closes: vim/vim#2015984ae09dd79
Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit ffe87d91f7)
Problem:
- Empty ranges have different `<`, `<=`, `has` and `intersect` semantics compared to regular ranges.
- `to_inclusive_pos` assumes that the end position of a range is exclusive, which is not true for empty ranges
Solution:
Special case empty ranges in these operations.
(cherry picked from commit 416f3482e7)
Problem:
When `:!` writes shell output to a buffer, write_output() splits on `\r`, `\n`,
and `\r\n`, replacing the terminator byte with NUL. For a binary-mode buffer
this is wrong: `\r` should be preserved verbatim, not treated as a line
terminator. This wrong behavior causes a file like `\r\n` round-trips through
`:%!cat` to `\n`.
This was masked when 'shelltemp' was enabled, because output went through a temp
file and the regular file I/O path handled binary-mode correctly. Switching the
default to 'noshelltemp' exposed the bug, since output is now piped directly
into write_output().
Solution:
In `write_output()`, skip the `\r` and `\r\n` splits for a binary-mode buffer;
only split on `\n`.
(cherry picked from commit 832a68835b)
Problem: select_spec tests a public function, but uses private enums.
Solution: Replace private enums with public enums.
(cherry picked from commit a61c8f3580)
feat(tui): restore 'ttyfast' to control tty requests
Problem:
When running nvim on a remote machine over SSH, if there is high ping,
then bg detection may not complete in time. This results in a warning
every time nvim is started. #38648
Solution:
Restore 'ttyfast' option and allow it to control whether or not bg
detection is performed. Because this is during startup and before any
user config or commands, we use the environment variable
`NVIM_NOTTYFAST` to allow disabling `ttyfast` during initialization.
Co-authored-by: Kyle <50718101+kylesower@users.noreply.github.com>
Problem: read_compound() in spellfile.c computes the size of the regex
pattern buffer using signed-int arithmetic on the attacker
controlled SN_COMPOUND sectionlen. With sectionlen=0x40000008
and UTF-8 encoding active the multiplication wraps to 27 while
the per-byte loop writes up to ~1B bytes, overflowing the heap.
Reachable when loading a crafted .spl file (e.g. via 'set spell'
after a modeline sets 'spelllang'). The cp/ap/crp allocations
have the same int + 1 overflow class (Daniel Cervera)
Solution: Use type size_t as buffer size and reject values larger than
COMPOUND_MAX_LEN (100000). Apply the same size_t treatment to
the cp/ap/crp allocations.
Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-q4jv-r9gj-6cwv9299332917
Co-authored-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
(cherry picked from commit 0976ce255b)
Problem:
`builtin_types.lua` seems to be about vimfn (aka "eval", aka
"vimscript", …) specifically, whereas `builtin.lua` is about the Lua
stdlib.
Solution:
Rename it to `vimfn_types.lua`, to align with `vimfn.gen.lua`.
(cherry picked from commit aea9aeee78)