Commit Graph

36171 Commits

Author SHA1 Message Date
Nathan Zeng
a0dcdcd8a0 feat(treesitter): provide select()
Problem: No public method for treesitter incremental selection.

Solution: Add `vim.treesitter.select()`.
2026-05-07 12:03:02 +02:00
glepnir
cac643f0f5 refactor(excmd): remove duplicate get_cmd_argt (#39643)
Problem:
`excmd_get_argt` and `get_cmd_argt` do the same thing.

Solution:
Drop `get_cmd_argt` and update its callers to use `excmd_get_argt`.

(cherry picked from commit 1fd82615b1)
2026-05-07 09:30:17 +00:00
Justin M. Keyes
ad27075c8d feat(pos): pos:to_offset(), pos.offset() (#39639)
Problem:
For a given position, it is not easy to compare which of several other positions is closest to it.

Solution:
Add support for converting `vim.Pos` to a buffer byte offset.

This allows for sorting, e.g:
```lua
table.sort(positions, function(pos1, pos2)
  return pos1:to_offset() < pos2:to_offset()
end
```

Or a binary search, e.g:
```lua
vim.list.bisect(positions, pos, { key = function(pos) return pos:to_offset() end })
```

Co-authored-by: Yi Ming <ofseed@foxmail.com>
2026-05-07 05:16:53 -04:00
Justin M. Keyes
0197461265 backport fix(diagnostic): status() respects config.signs (#39601)
Problem:
`diagnostic.status` only follows the `config.status.format` setting to determine how to display diagnostic signs. However, `signs` can actually also be configured via `config.signs.text`.

Solution:
If the user has set symbols via `config.status.format`, let that determine the content of `signs`; otherwise, use `config.signs.text` for display.

TODO: drop support `type(config.status.format) == 'table'`; users should just configure `config.signs.text` directly.

Co-authored-by: Yi Ming <ofseed@foxmail.com>
2026-05-06 16:42:02 +00:00
Tomasz N
70f22713a1 fix(ui2): entering the pager fails if <ESC> is remapped to :fclose (#39462)
Problem:  Entering the pager fails if <ESC> is remapped to :fclose by user.
Solution: Avoid executing mappings with nvim_feedkeys() that closes expanded cmdline.
(cherry picked from commit 2b7a00746d)
2026-05-06 13:58:25 +00:00
STG
13041a067e fix(ui2): error E518 when typing "vim:" in cmdline #39599
Problem: `vim:`, etc. in cmdline are interpreted as modeline, causing error E518.

Solution: Set 'nomodeline' when creating the buffers.
(cherry picked from commit 0ea720f281)
2026-05-06 13:31:37 +00:00
zeertzjq
0aa77cb78c vim-patch:9.2.0443: GUI: cancelling save dialog overwrites or discards unnamed buffer (#39617)
Problem:  When closing gvim with an unsaved unnamed buffer, choosing
          "Yes" in the "Save changes?" dialog and then "Cancel" in the
          file selection dialog either silently writes the buffer to a
          file named "Untitled" (overwriting any existing file with
          that name) or discards the buffer altogether
          (vibs29, after v9.1.0265).
Solution: In dialog_changed(), if browse_save_fname() leaves the buffer
          without a file name, treat it as a cancel and return without
          saving.  Also stop clearing the modified flag in the restore
          path on write failure, so the unsaved changes are kept and
          the caller (e.g. gui_shell_closed()) can also cancel the
          close.  Pre-fill the file dialog with "Untitled" to match
          the preceding "Save changes to ..." prompt.  Add a test for
          the write-failure path (Hirohito Higashi).

fixes:  vim/vim#20132
closes: vim/vim#20143

cf947e7ef0

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
(cherry picked from commit 2bb426ce4a)
2026-05-06 01:47:06 +00:00
zeertzjq
15a58bb02a vim-patch:9.2.0444: Cannot set 'path' option via modeline
Problem:  Cannot set 'path' option via modeline (zeertzjq, after v9.2.0435)
Solution: Revert the part that disallows setting 'path' via modeline.

closes: vim/vim#20137

88fb739918

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit d1c3d6fbaa)
2026-05-06 00:54:27 +00:00
zeertzjq
b013940391 vim-patch:9.2.0435: [security]: backticks in 'path' may cause shell execution on completion
Problem:  [security]: Backticks enclosed shell commands in the 'path'
          option value are executed during completion (q1uf3ng).
Solution: Skip path entries containing backticks, add P_SECURE to 'path'
          option, so that it cannot be set from a modeline (for symmetry with
          the 'cdpath' option)

Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-hwg5-3cxw-wvvg

Supported by AI.

190cb3c2b9

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit b06f8b174f)
2026-05-06 00:54:27 +00:00
David Balatero
a5482eeb9f test: flaky terminal channel exitcode check #39580
Problem:
The `nvim_get_chan_info()` terminal channel test used `shell-test INTERACT` to verify that `jobstop()` reports an unhandled `SIGHUP` as exit code `129`.

`INTERACT` reads from stdin with `fgets()`, so closing the PTY could race with `SIGHUP` delivery. If `fgets()` observed EOF first, `shell-test` exited normally with code `0`, causing intermittent failures on slower sanitizer builds.

Solution:
Add a `shell-test HOLD` mode that prints a readiness prompt and then waits without reading stdin. Use it for the `SIGHUP` assertion so PTY EOF cannot make the helper exit normally before the signal path is observed.

(cherry picked from commit 78111e5371)
2026-05-05 23:21:25 +00:00
Yi Ming
e67f9c5853 fix(lua): avoid __index when deciding if a table is a list #39556
Problem:
When a table has `__index`, `vim.islist` is unreliable.

Solution:
Index using `rawget`.

(cherry picked from commit 264fbc0ace)
2026-05-05 20:54:41 +00:00
David Balatero
c9cb49358b test: unreliable pack_spec.after_each: "EBUSY: resource busy or locked" #39606
Problem:
`EBUSY` during cleanup:
Windows CI can intermittently fail `pack_spec.lua` with `EBUSY` while removing
`site/pack/core/opt/plugindirs`.

This can happen because:
- the test Nvim session may still be alive when `after_each()` removes the pack
  directory
- Windows does not allow removing a directory while another process still has an
  open handle below it
- startup-time `vim.pack.add()` performs a real `git clone`, so process and file
  handle release timing can vary on slower runners

Startup timeout:
The startup tests can also fail before cleanup because they wait for `_G.done`
with a fixed timeout. That timeout includes the time needed for startup to run
`vim.pack.add()` and finish the local clone.

Solution:
Close before cleanup:
Capture the pack, lockfile, and log paths while the test Nvim session is still
available, then call `n.check_close()` before removing the pack directory.

Extend Windows startup wait:
Increase the `_G.done` retry budget only on Windows so startup-time
`vim.pack.add()` has more time to finish on slower CI runners.

(cherry picked from commit 19a2ef5afa)
2026-05-05 18:33:31 +00:00
David Balatero
d9baaf7da1 fix(ci): generate more data to stress output throttling test #39577
Problem:
This test would sometimes fail to match lines starting with `.` (indicating throttling) due to a race condition, likely because throttling completed before the test could properly assert.

Solution:
I 6x'd the amount of test data we were pushing into `nvim` in an attempt to trigger throttling consistently.

I don't _love_ this solution as it is still non-deterministic and might not hold up over time.

A good solution would be: create a deterministic way to pause neovim in a functional test, assert on the temporarily throttle state, then unpause neovim. However, it's likely this is not possible today and will take too much effort.

Before test time (30000 lines): ~0.40sec/run
After test time (150000 lines): ~1.7sec/run

This increases test runtime, but if it removes flakes I think it's worth it.

(cherry picked from commit cbedd537ac)
2026-05-04 16:53:44 +00:00
zeertzjq
65a0553b95 refactor(cmdexpand.c): deduplicate code (#39582)
(cherry picked from commit cdccd452ff)
2026-05-04 02:02:00 +00:00
zeertzjq
f9f2596288 vim-patch:9.2.0436: Buffer overflow when parsing overlong errorformat lines (#39578)
Problem:  When an error line in a file passed to :cfile / :cgetfile is
          longer than IOSIZE, qf_parse_file_pfx() copies the tail
          into the fixed-size IObuff with STRMOVE(), overflowing the heap buffer.
          The same code path can also loop indefinitely because
          qf_parse_file_pfx() always returns QF_MULTISCAN when a
          tail is present, and qf_init_ext() unconditionally goes
          to "restofline" without bounding the tail length (Nabih).
Solution: Remove the STRMOVE() into IObuff.  In the QF_MULTISCAN
          branch, alias linebuf into the tail directly and update
          linelen, requiring strict progress (new length less than
          the previous length) before retrying; otherwise ignore
          the line.

closes: vim/vim#20126

Supported by AI

77677c33de

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit 0e69a38026)
2026-05-03 23:34:55 +00:00
David Balatero
4f22640b86 fix(treesitter): get_node_text() inconsistent trailing newline #39409
Problem:
`get_node_text()` returned inconsistent results between buffer and
string sources when a node's range ends at `end_col == 0` (i.e. the node
ends with a newline). The buffer path dropped the trailing newline; the
string path included it correctly.

Solution:
Append `'\n'` in `buf_range_get_text()` when `end_col == 0` and
`start_row ~= end_row`. The `start_row ~= end_row` guard excludes
zero-width nodes at column 0, which should return `""`.

Remove the workaround in the `#trim!` directive that manually
compensated for the missing newline.

Strip whitespace in `resolve_lang()` so injection language nodes ending
at `end_col == 0` (e.g. `">lua\n"`) still resolve correctly.

(cherry picked from commit 7ed5609439)
2026-05-03 13:53:04 +00:00
Christian Clason
44baa8d94b ci(external): no need for neovim-ppa/stable
Problem: The with-external-deps workflow keeps failing because adding the neovim-ppa/stable times out.

Solution: Don't add the PPA; it doesn't seem to be necessary for installing current dependencies.
2026-05-02 17:22:27 +02:00
Barrett Ruth
0c9dd4e471 ci(optional): avoid reruns from unrelated labels #39547
Problem: Optional CI reevaluates on unrelated label events and shares
one workflow-wide concurrency group. One optional label change can
cancel in-flight jobs for the other optional suite.

Solution: Only reevaluate each optional job when its own label changes,
and move concurrency to the job level. This keeps `s390x` and
`windows-asan` from restarting each other.

(cherry picked from commit 085bb518c8)
2026-05-02 10:55:05 +08:00
Tristan Knight
8919b02eba fix(lsp): dynamic registration for off-spec method #39544
Problem:
LSP clients previously did not handle dynamic registration for off-spec methods

Solution:
Update the client logic to assume support for dynamic registration when
the method is unknown. Adjust the registration provider fallback and
enhance tests to verify correct behaviour for unknown methods and their
registration options. This improves compatibility with servers using
custom dynamic registrations.

AI-assisted: OpenCode
(cherry picked from commit 344d984ed2)
2026-05-02 10:54:42 +08:00
altermo
e230ff0439 fix: vim._with may silence all cmdline-errors #34301
Problem:
vim._with may silence all cmdline-errors if emsg_silent=true, silent=false.

Steps to reproduce:
`nvim --clean -u repro.lua`, then `:echoerr 123`, nothing is shown.

    local api, fn = vim.api, vim.fn
    -- api.nvim_create_autocmd("CursorMovedC", {
    api.nvim_create_autocmd("CmdlineChanged", {
      callback = function(args)
        if args.match ~= ":" then
          return
        end
        -- vim.cmd([[silent! ]])
        vim._with({ emsg_silent = true }, function()
          -- return api.nvim_parse_cmd(fn.getcmdline(), {})
        end)
      end,
    })

Solution:
Force CMOD_SILENT if CMOD_ERRSILENT.

(cherry picked from commit a6ea3a1055)
2026-05-02 10:54:14 +08:00
Yochem van Rosmalen
e069022215 fix(help): fix CTRL character issue for :help {subject} #39537
Problem:
The argument to `:help` is normalized to fit the general tag format.
I.e. i^U-default, iCTRL-U-default and i_CTRL_U-default should all point
to the i_CTRL_U-default tag. Our normalization adds an underscore around
the CTRL keycode, e.g. iCTRL-GCTRL-J becomes i_CTRL-G_CTRL-J. That's not
necessary if the following part starts with a dash, like the case of
iCTRL-U-default.

Solution:
Do not insert an underscore if the following character is a dash/minus
(-).

(cherry picked from commit 84ae70c172)
2026-05-01 10:50:35 +00:00
Matthew Hughes
20a2398877 docs: Update instructions for debugging LSP (#39527)
docs: update instructions for debugging LSP

Previously, it was suggested to set:

    vim.lsp.log.set_format_func(vim.inspect)

This made sense before f72c13341a, when
`format_func` was called once per argument being logged, but since that
commit it's called with the log level followed by the other args, so the
suggested setting would call `vim.inspect(log_level, ....)` which would
just print the human readable name of the current log level and no other
details, for example with this set I saw in my logs:

    "DEBUG""DEBUG""DEBUG""DEBUG"

Instead just rely on the default formatter, which will:

> ... log the level, date, source and line number of the
caller, followed by the arguments.

(cherry picked from commit 578727c25e)
2026-04-30 22:05:37 +00:00
Justin M. Keyes
4b424a06c5 backport fix(lsp): send didClose, didOpen when languageId changes (#39519)
fix(lsp): send didClose, didOpen when languageId changes

Problem:
If a buffer's filetype changes after the LSP client has already
attached (e.g. from json to jsonc via a modeline), but the client
supports both filetypes, it stays attached. It does not notify the
server of the new languageId, causing the server to incorrectly process
the file using the old languageId.

Solution:
Save the languageId used during textDocument/didOpen, and send
textDocument/didClose + textDocument/didOpen when buffer's languageId
changed.

Lsp spec:
0003fb53f1/_specifications/lsp/3.18/textDocument/didOpen.md (L5)
> If the language id of a document changes, the client
> needs to send a textDocument/didClose to the server followed by a
> textDocument/didOpen with the new language id if the server handles
> the new language id as well.

AI-assisted: Gemini 3.1 Pro

Co-authored-by: phanium <91544758+phanen@users.noreply.github.com>
2026-04-30 13:09:55 +00:00
Justin M. Keyes
d147d0434d Merge pull request #39512 from justinmk/release
backports
2026-04-29 20:30:32 -04:00
Justin M. Keyes
4ee47a56ec docs: misc 2026-04-30 02:08:19 +02:00
Till Bungert
822778f7e5 fix(excmd): use realtime for v:starttime, :uptime #39425
Problem:
`v:starttime`, `:uptime` use a monotonic high-resolution timer. This
only works as long as the timer keeps running (if the computer is
suspended the timer is paused). This is somewhat unintuitive, and
doesn't match the behavior of the `uptime` shell command.

Solution:
Implement `os_realtime` to get the real time since the
epoch in nanoseconds.
2026-04-29 23:41:41 +02:00
Olivia Kinnear
c9ca59ad28 backport: fix(lsp): util.lua attempt to concatenate userdata #39510
Problem:
Error when querying document symbols using python-lsp-server:

    lsp/util.lua:1955: attempt to concatenate field 'containerName' (a userdata value)

Solution:
Check for `vim.NIL`.

(cherry picked from commit 1799aaebda)
2026-04-29 16:13:47 -04:00
neovim-backports[bot]
378f5f49b3 backport: fix(lsp): show meaningful error on invalid completion response (#39476)
Problem: vim.NIL is truthy in Lua, so `#(result.items or result)`
crashes on `#vim.NIL` when servers return null.

Solution: skip spec-allowed result=null silently, raise an error
on items=null with the server name.

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion
(cherry picked from commit b9431b340f)

Co-authored-by: glepnir <glephunter@gmail.com>
2026-04-28 11:27:50 -04:00
neovim-backports[bot]
24a4bf20c0 backport: fix(termdebug): fix evaluate display with gdb pretty print (#39475)
Calling `set print pretty on` in GDB will:

> Cause GDB to print structures in an indented format with one member
per line

However, `termdebug` just renders the newlines as raw `\n` characters.
This is a regression of[1]. Glancing through the history it looks to
have been caused by cd1b14f027 which
removed the output splitting when displaying the eval results, so this
changes adds that behaviour back.

As a quick reproduction/test, compile the following C program:

```c

struct Foo {
    char *name;
};

int main(void) {
    struct Foo f = {"hello"};
    printf("%s\n", f.name);

    return 0;
}
```

Then launch `nvim` and run:

    :Termdebug main
    :Gdb
    (gdb) set print pretty on
    (gdb) break main
    (gdb) run
    :Source

Place the cursor on the `f` variable and call `:Evaluate`. Before this change:

![](https://github.com/user-attachments/assets/51318e1e-9cdd-43ab-aa35-4aaad1d9f65f)

With this change:

![](https://github.com/user-attachments/assets/33874679-21b4-4d07-98ef-c2c9e9d19dd6)

Link: https://github.com/neovim/neovim/issues/10020 [1]
(cherry picked from commit c06e3d6f81)

Co-authored-by: Matthew Hughes <matthewhughes934@gmail.com>
2026-04-28 11:25:53 -04:00
zeertzjq
34bf0472ab fix(marks): don't use spell decorations from other lines (#39441)
Spell decorations from other lines aren't relevant to the current line.
Also, decor_redraw_col() can only go forward, while spell navigation
needs to go both forward and backward.

(cherry picked from commit 46c83ce321)
2026-04-27 23:36:36 +00:00
Yi Ming
96d5dd4107 perf(vim.pos): use numeric index internally #39447
(cherry picked from commit d40875a2f8)
2026-04-27 18:26:02 +00:00
Justin M. Keyes
0f6f5cd0a7 Merge pull request #39428 from justinmk/release
backport
2026-04-26 16:30:12 -04:00
Justin M. Keyes
d735ce36ec docs: sort quasi-keysets 2026-04-26 22:02:34 +02:00
Justin M. Keyes
b1b489b316 build(docs): sort/lint class fields and keysets
Problem:
Fields (key names) in classes, keysets, and quasi-keysets are ordered
randomly, which adds friction when reading docs.

Solution:
- Sort class fields and keysets when generating docs.
- Add a lint check for quasi-keysets (keysets defined as unstructured
  markdown lists within a docstring).
2026-04-26 22:00:11 +02:00
Justin M. Keyes
534b1a8e7e docs: vim.ui.select, misc
(cherry picked from commit d960ae6760)
2026-04-26 19:45:57 +00:00
Justin M. Keyes
e77e260d36 docs: lsp.CodeActionContext, nested @inlinedoc
- fix https://github.com/neovim/neovim/issues/39208
- fix generation of neste `@inlinedoc` classes

(cherry picked from commit 825bfba789)
2026-04-26 19:45:57 +00:00
Justin M. Keyes
fb56d50032 fix(eval): writestring() handling of null #39328
Problem:
- write_blob, write_string dereference args which may be NULL.
- `writefile(v:_null_blob, …)` fails.

Solution:
- Fix the annotation.
- Handle null blob.

Co-authored-by: zeertzjq <zeertzjq@outlook.com>
(cherry picked from commit 6d0cdcd605)
2026-04-26 14:27:11 +00:00
Justin M. Keyes
35a5ac9aa6 Merge pull request #39419 from justinmk/release
backports
2026-04-26 07:40:27 -04:00
Luis Calle
2ec758f403 fix(vim.range): validate arguments on all cases #39415 2026-04-26 12:41:06 +02:00
Luis Calle
49efe692f3 feat(vim.pos): accept buf=0 for current buf #39414 2026-04-26 12:41:06 +02:00
Yi Ming
828a35b14f feat(docs): render class dot members as module functions
AI-assisted: Codex
2026-04-26 12:39:45 +02:00
Yi Ming
b6ccf44aef revert: "docs: vim.range, vim.pos #38869"
This reverts commit c530fd8e75.
2026-04-26 12:39:45 +02:00
Barrett Ruth
53d34ba719 ci(news): only rerun on ci:skip-news label changes #39399
Problem: The news workflow reruns on unrelated label events.

Solution: Only reevaluate the job when the changed label is
`ci:skip-news`.

(cherry picked from commit 1aeaa61bcf)
2026-04-25 22:15:48 +00:00
Justin M. Keyes
26678ebbd8 backport: docs: misc (#39395) 2026-04-25 13:51:22 -04:00
neovim-backports[bot]
cf17575b7b backport: docs(vim.ui): document an interface for vim.ui.select preview (#39401)
Problem: Plugins may want to have a way to show more details about items
  when using `vim.ui.select`. This is a fairly common problem that
  prompts plugin authors to implement dedicated sources/pickers for
  fuzzy picker plugins that are popular at the moment.

Solution: Document a way for `vim.ui.select` to provide preview:
  - `vim.ui.select` users can provide `opts.preview_item` function that
    creates/uses a buffer and its contents at certain position to show
    more details about an item.
  - `vim.ui.select` implementations may use `opts.preview_item` in the
    way they see fit (like show the buffer in a separate/same window
    interactively/on-demand or do nothing) if they have a way to show
    more information about an item.
(cherry picked from commit c44df255aa)

Co-authored-by: Evgeni Chasnovski <evgeni.chasnovski@gmail.com>
2026-04-25 13:48:07 -04:00
Yi Ming
5e6c8d4edf fix(lsp): check window is still valid after async request #39396
Problem:
Since `foldclose` is async, it must wait for the request to return before actually executing, at which point the original window may no longer be valid.

Solution:
Check whether the window is valid before actually performing `foldclose`.

(cherry picked from commit 775c7d1b53)
2026-04-25 16:55:31 +00:00
zeertzjq
f0baa18043 fix(channel): stack-buffer-overflow with exit during connection (#39387)
Problem:  When Nvim exits while connecting to a socket it leads to
          stack-buffer-overflow.
Solution: Associate the handle with the Stream and use the Stream's
          internal_close_cb to update the "closed" status.
(cherry picked from commit 4ed2e66d2e)
2026-04-25 12:38:20 +00:00
zeertzjq
e5114d03b5 test: add finally() to meta file (#39388)
(cherry picked from commit df8cf0ed25)
2026-04-25 10:10:25 +00:00
Tristan Knight
aedbae4ab6 fix(lsp): handle self-mapped methods in supports_method #39383
Problem:
The LSP client incorrectly checks for server capabilities when determining
support for self-mapped methods (e.g., 'shutdown'), which do not have
corresponding capabilities in the server's response. This leads to false
negatives when checking if such methods are supported.
This was handled correctly for dynamic registrations, but not for static.

Methods such as 'shutdown', do not have a related server capability and should
be assumed to be supported.

Solution:
Update the `supports_method` logic to always return true for self-mapped
methods.

(cherry picked from commit f83d0b9653)
2026-04-24 23:19:16 +00:00
neovim-backports[bot]
e5d6d2e769 backport: fix(api): leak preview callback LuaRef in nvim_create_user_command (#39377)
Problem:
Invalid `nvim_create_user_command` calls can leak the
`preview` callback reference after Neovim has taken ownership of it.

1. build with {a,l}san
2. run:
    ```sh
    <path/to/nvim> --headless -u NONE --clean +'lua
    for i = 1, 100 do
      pcall(vim.api.nvim_create_user_command,
        "some very epic stuff" .. i,
        {}, -- NOTE: this is INVALID (not a function or string)
        { preview = function() end })
    end
    vim.cmd("qa!")
    ' +qa
    ```
3. see:
    ```
    100 lua references were leaked!
    ```

Solution:
Clear `preview_luaref` in `err:`.

(cherry picked from commit 393f687503)

Co-authored-by: Barrett Ruth <62671086+barrettruth@users.noreply.github.com>
2026-04-24 17:27:46 -04:00