aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim
Commit message (Collapse)AuthorAge
...
* fix(trust): hash unchanged empty buffers as empty files #39027Barrett Ruth2026-04-23
| | | | | | | | | Problem: `vim.secure.trust()` hashes an unchanged empty buffer as a newline, so trusting an empty file by buffer never works. Solution: Hash unchanged empty-buffers `''` so buffer-based trust matches the on-disk empty file.
* fix(lsp): malformed edit if apply_text_edits() is called twice #34954geril072026-04-23
| | | | | | | | | | | | | | Problem: Use vim.lsp.util.apply_text_edits to re-apply the same textedit causes an incorrect edit, because apply_text_edits silently modifies the parameter. Solution: - Avoid changing `text_edit._index`. - Document this fun feature. Helped-by: Riley Bruins <ribru17@hotmail.com> Helped-by: Yi Ming <ofseed@foxmail.com> Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* fix(pack): only use tags that strictly comply with semver spec #39342Evgeni Chasnovski2026-04-23
| | | | | | | | | | | | | | | | | | Problem: Using `version=vim.version.range(...)` in plugin specification is meant to use semver-like tags. Whether a tag is semver-like was decided by a plain `vim.version.parse` which is not strict by default. This allowed treating tags like `nvim-0.6` (which is usually reserved for the latest revision compatible with Nvim<=0.6 version) like semver tags and resulted in confusing behavior (preferring `nvim-0.6` tag over `v0.2.2`, for example). Solution: Use `vim.version.range(x, { strict = true })` to decide if the tag name is semver-like or not. This allows tags like both `v1.2.3` and `1.2.3` while being consistent in what Nvim thinks is a semver string. This is technically not a breaking change since it was documented that only tags like `v<major>.<minor>.<patch>` will be recognized as semver.
* fix(lsp): callHierarchy/outgoingCalls ranges are relative to caller, not ↵Ashley Hauck2026-04-23
| | | | | | | | | | | | | callee #39336 Problem: The fromRanges field of the result of callHierarchy/outgoingCalls is documented as being relative to the caller. Using vim.lsp.buf.outgoing_calls() opened the qflist with an entry with the callee's filename, but the caller's line number. Solution: Open the qflist with the callers file (the bufnr from the request), rather than the callees (the uri from the resulting CallHierarchyItem)
* fix(lsp): filter code_action diagnostics to the cursor #38988Barrett Ruth2026-04-23
| | | | | | | Problem: Cursor-position `vim.lsp.buf.code_action()` requests include all diagnostics on the current line, so unrelated same-line diagnostics affect the returned actions. Solution: Filter same-line diagnostics to the cursor position for cursor-position requests.
* feat(treesitter): expand selection to sibling node #38938altermo2026-04-22
| | | | | | | | | Problem: Can't expand treesitter-incremental-selection to the next and previous sibling nodes. Solution: Pressing `]N` in visual mode will expand the selection to the next sibling node, and `[N` will do the same with the previous node.
* feat(:restart): v:starttime, v:exitreason #39282Justin M. Keyes2026-04-22
| | | | | | | | | | | | Problem: - The `ZR` feature makes it more obvious that we need some sort of flag so that an `ExitPre` / `QuitPre` / `VimLeave` handler can handle restarts differently than a normal exit. For example, it's common that users want `:mksession` on restart, but perhaps not on a normal exit. - Nvim has no way to report its "uptime". Solution: - Introduce `v:starttime` - Introduce `v:exitreason`
* perf(lsp): clear table by table.clear() #39222Yi Ming2026-04-22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | benchmark: https://gist.github.com/ofseed/6224529d77c016c36f7ab2f977059848 local rounds = tonumber(arg[1]) or 1000 local count = tonumber(arg[2]) or 1000 -- Load the table.clear function. local clear = require("table.clear") local function fill(t, n) for i = 1, n do t[i] = i end end local function bench_reassign(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do t = {} collectgarbage("collect") fill(t, n_items) end return os.clock() - start end local function bench_reassign_no_gc(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do t = {} fill(t, n_items) end return os.clock() - start end local function bench_clear(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do clear(t) fill(t, n_items) end return os.clock() - start end -- Warm up LuaJIT before the real benchmark. do local t = {} for _ = 1, 2000 do clear(t) fill(t, count) end end collectgarbage("collect") local reassign_time = bench_reassign(rounds, count) collectgarbage("collect") local reassign_no_gc_time = bench_reassign_no_gc(rounds, count) collectgarbage("collect") local clear_time = bench_clear(rounds, count) print(string.format("rounds=%d count=%d", rounds, count)) print(string.format("t = {} + GC : %.6f s", reassign_time)) print(string.format("t = {} : %.6f s", reassign_no_gc_time)) print(string.format("table.clear : %.6f s", clear_time)) print(string.format("vs + GC : %.2fx", reassign_time / clear_time)) print(string.format("vs no GC : %.2fx", reassign_no_gc_time / clear_time)) benchmark result: rounds=1000 count=1000 t = {} + GC : 0.022469 s t = {} : 0.002570 s table.clear : 0.000387 s vs + GC : 58.06x vs no GC : 6.64x `count` is how many items the table has, and `round` is how many rounds we fill the table, clear, and then refill it. `table = {}` is clear the table by resigning a new empty one, because this script does not run persistently like nvim so GC is not triggered, so I added another extreme control group that manually triggers GC.
* fix(options): default 'titlestring' shows CWD #39233Nick Krichevsky2026-04-22
| | | | | | | Problem: In the default 'titlestring', if the containing directory is the CWD, it renders as "." Solution: Add `:p` to the titlestring.
* fix(pack): GIT_DIR/GIT_WORK_TREE env vars may interfere #39279fleesk2026-04-22
| | | | | | | | Problem: With GIT_DIR/GIT_WORK_TREE set, the LSP on the vim.pack.update() confirmation buffer does not show the correct git log on hover. Solution: Temporarily remove the git vars from the environment.
* vim-patch:9.2.0356: Cannot apply 'scrolloff' context lines at end of filezeertzjq2026-04-22
| | | | | | | | | | | | Problem: Cannot apply 'scrolloff' context lines at end of file Solution: Add the 'scrolloffpad' option to keep 'scrolloff' context even when at the end of the file (McAuley Penney). closes: vim/vim#19040 https://github.com/vim/vim/commit/a414630393f81c9a5b8fa4d0fcc1287155f67751 Co-authored-by: McAuley Penney <jacobmpenney@gmail.com>
* fix(:restart): avoid ERR/WRN logging on Windows with --listen (#39287)zeertzjq2026-04-22
| | | | | Problem: :restart leads to ERR/WRN logging on Windows with --listen. Solution: Add a log_level flag to vim._with() and use it to suppress logging from serverstart()/serverstop() during restart.
* fix(:restart): reuse --listen addr on Windows #38539Sanzhar Kuandyk2026-04-21
| | | | | | | | | | Problem: On Windows, :restart cannot immediately reuse the canonical --listen address because named pipe release is asynchronous. Solution: Start the new Nvim server on a temporary address; in the new Nvim, retry serverstart() with the original ("canonical") address until it succeeds.
* feat(normal): normal-mode ZR does :restartJustin M. Keyes2026-04-21
| | | | Make it a normal-mode command instead of a default mapping.
* feat(defaults): map ZR to restartMike J. McGuirk2026-04-21
| | | | | | | | Problem: No default mapping for :restart. Solution: Map to ZR in defaults. Closes: https://github.com/neovim/neovim/issues/38942
* vim-patch:9.2.0371: filetype: ghostty config files are not recognized (#39267)zeertzjq2026-04-21
| | | | | | | | | | | | Problem: filetype: ghostty config files are not recognized Solution: Detect ghostty configuration files as ghostty filetype, include a simple ghostty filetype plugin (Bez Hermoso) closes: vim/vim#20002 https://github.com/vim/vim/commit/b30803b231beea13e2efa42fefc04be71a4e9bb5 Co-authored-by: Bez Hermoso <bezalelhermoso@gmail.com> Co-authored-by: Christian Brabandt <cb@256bit.org>
* fix(ui2): don't dismiss expanded messages for non-typed key #39247luukvbaal2026-04-20
| | | | | | | | | Problem: Invalid check for non-typed key to dismiss expanded cmdline. Unable to delay the timer that removes a message from the msg window. Solution: Check for empty string instead of nil to determine whether a key is typed. Restart the timer if it expires while the user is in the msg window. Allow entering the msg window with a mouse click.
* fix(ui2): ensure msg window is visible after closing tabLuuk van Baal2026-04-20
| | | | | | | | | | Problem: After closing a tabpage while the msg window is showing a message, it is hidden while the msg window still contains a message. Solution: Unhide the msg window after entering a tabpage and it still contains a message. Co-authored-by: Linykq <yukunlin590@gmail.com>
* docs: misc #39207Justin M. Keyes2026-04-20
|
* fix(api): expose fg_indexed/bg_indexed in nvim_get_hl #39210glepnir2026-04-20
| | | | | | | | | Problem: fg_indexed/bg_indexed were dropped from nvim_get_hl output due to a wrong short_keys guard. HL_FG_INDEXED also wasn't cleared in hl_blend_attrs, and HLATTRS_DICT_SIZE was too small. Solution: Remove the short_keys guard, clear HL_FG_INDEXED in hl_blend_attrs, bump HLATTRS_DICT_SIZE to 24, and clarify docs that these flags mean rgb is an approximation of the cterm palette index.
* Merge #39194 from justinmk/luavimfnJustin M. Keyes2026-04-20
|\
| * fix(health): workaround nil vim.system():wait() resultJustin M. Keyes2026-04-20
| | | | | | | | Workaround until https://github.com/neovim/neovim/issues/37922 is fixed.
| * refactor(excmd): migrate ex_terminal to LuaJustin M. Keyes2026-04-20
| |
| * refactor(excmd): migrate ex_checkhealth to LuaJustin M. Keyes2026-04-20
| |
* | feat(options): add 'winpinned' to pin a window #39157luukvbaal2026-04-19
|/ | | | | | | | | | | | | | Problem: - Unable to "pin" a window to prevent closing without specifically being targeted. - :fclose closes hidden windows (even before visible windows). Solution: - Add 'winpinned' window-local option. When set, window is skipped by :fclose and :only. Pin the ui2 cmdline window (which should always be visible), so that it is not closed by :only/fclose. - Skip over hidden (and pinned) windows with :fclose. Co-authored-by: glepnir <glephunter@gmail.com>
* fix(lsp): notify when maximum created `hl` groups is reached #39231Maria Solano2026-04-19
|
* docs(lsp): description for `on_list` example #39230Maria Solano2026-04-19
|
* feat(excmd): add EXX error codes for :lsp, :log #39135Olivia Kinnear2026-04-19
| | | | Also remove the `--add-comments` flag from `xgettext` because it dumped a bunch of comments from Lua files into the `.pot` files.
* fix(lsp): stale codelens after external file change (#39203)Jaehwang Jung2026-04-18
| | | | | | | | | Problem: Codelens virtual lines remain on stale rows after an external file change and buffer reload. Solution: Clear codelens extmarks and cached row/version state in `on_reload` before requesting fresh code lenses.
* fix(lsp): show CompletionItem.detail in info popup #38904glepnir2026-04-18
| | | | | | | Problem: completionItem/resolve response's `detail` field is silently dropped. Only `documentation` is shown in the popup. Solution: Prepend `detail` as a fenced code block before `documentation` in the info popup, skipping if documentation already contains it.
* docs: misc #39045Justin M. Keyes2026-04-18
|
* fix(lsp): skip codelens refresh redraw for deleted buffer #39193Jaehwang Jung2026-04-18
| | | | | | | | | | | | Problem: After on_refresh() sends a textDocument/codeLens request, the buffer may be deleted before the response arrives. The response callback then tries to redraw that deleted buffer and raises Invalid buffer id error. Solution: Check buffer validity before redrawing. AI-assisted: Codex Co-authored-by: Yi Ming <ofseed@foxmail.com>
* docs(events): Lua types for autocmd event-data #38518Aditya Malik2026-04-18
| | | | | | | | | | Problem: No LuaLS types for event-data fields (ev.data). Types are only documented ad hoc in scattered locations. Solution: Add runtime/lua/vim/_meta/events.lua defining vim.event.<name>.data classes for events that provide ev.data. Reference the types from each event's help in autocmd.txt, lsp.txt, and pack.txt.
* fix(lua): make `vim._with()` work with `buf=0` and `win=0` context #39151Evgeni Chasnovski2026-04-18
| | | | | | Problem: Using `buf=0`/`win=0` context in `vim._with` should be equivalent to using explicit buffer/window identifier respectively. Solution: Explicitly adjust context in case of `buf=0` or `win=0`.
* refactor(vimfn): full-Lua impl of vim.fn.environ()Justin M. Keyes2026-04-18
|
* feat(vimfn): use Lua for more excmds/vimfnsJustin M. Keyes2026-04-18
| | | | | | | | | | | Problem: Too much boilerplate needed to use Lua to impl an excmd or f_xx function. Solution: - Add `nlua_call_vimfn` which takes the args typval, executes Lua, and returns a typval. - refactor(excmd): lua impl for :log, :lsp
* fix(vim.filetype): match() fails if g:ft_ignore_pat is not defined #39158Evgeni Chasnovski2026-04-18
| | | | | | | | | | Problem: Calling `vim.filetype.match({ filename = '...', buf = ... })` during startup results in an error due to not yet defined `g:ft_ignore_pat`. Solution: Add a guard to check `g:ft_ignore_pat` related properties only if the variable is defined. This also allows to simplify other tests which did not depend on `g:ft_ignore_pat` but required it explicitly set to work.
* fix(lsp): limit number of created highlight groups (#39133)Evgeni Chasnovski2026-04-17
| | | | | | | | | | | | | | | | | | | | | | | | * fix(api): allow silencing "Too many highlight groups" error Problem: Using Lua's `vim.api.nvim_set_hl(0, 'New', {...})` can fail if there are too many existing highlight groups. However, this error can not be silenced with `pcall`. Solution: Make it possible to silence in `nvim_set_hl` and `nvim_get_hl_id_by_name`. * fix(lsp): limit number of groups created by `document_color()` Problem: A file can contain many string colors that would be highlighted by an LSP server. If this number crosses 19999 (maximum number of allowed highlight groups), there are general issues with creating other highlight groups, which can break functionality outside of `vim.lsp.document_color`. Solution: Limit number of highlight groups that are created by `vim.lsp.document_color` to 10000 (half of allowed maximum). This is not a 100% solution (since there can exist more than 10000 other highlight groups), but explicitly checking number of groups is slow and 10000 should (hopefully) be enough for most use cases.
* perf(vim.fn): call Lua-implemented vim.fn.xx() directly #39166Justin M. Keyes2026-04-17
| | | | | | | | | | | | | | | | | | | | | | | | Problem: - Builtin "Vimscript" functions (f_xx) are mostly implemented in C. Partly that's because there is some boilerplate required to call out to Lua. - Calls to `vim.fn.foo()` always marshall over the Lua <=> Vimscript ("typval") bridge, even if `fn.foo()` is implemented entirely in Lua: ``` Lua => typval => Object => Lua => Object => typval => Lua. ``` Solution: Functions declared in eval.lua with `func_lua` are implemented in entirely in Lua (`_core/vimfn.lua`). - `gen_eval.lua` wires `func_lua` entries to `lua_wrapper`, which handles the typval conversion for Vimscript callers (slow path). - `nlua_call()` detects `func_lua` functions and calls the Lua implementation directly. This eliminates all conversion overhead for Lua callers (fast path). - Validate at build-time that `func`, `func_float`, and `func_lua` are mutually exclusive. - Migrate `hostname()` as a toy example, to show the idea.
* vim-patch:8.2.2440: documentation based on patches is outdated (#39144)zeertzjq2026-04-17
| | | | | | | | | | | Problem: Documentation based on patches is outdated. Solution: Add changes to documentation in a patch. https://github.com/vim/vim/commit/853886722c051ecaef6d818ce32a822e4f43dc2b Trailing space was removed in later patches. Also fix a few more misplaced error numbers from #8155. Co-authored-by: Bram Moolenaar <Bram@vim.org>
* fix(ui2): dialog paging is inconsistent #39128luukvbaal2026-04-16
| | | | | | | | | | | | | | Problem: - Paging keys in the dialog window consume input when the user may not expect it. The dismissable title hint intended to mitigate that results in having to press Escape twice to abandon the prompt. - Mimicked "msgsep" float border is taking up unnecessary space when window takes up the entire screen. Solution: - Use (conventional, albeit less convenient) keys intended for scrolling to page the dialog window: <(Mousewheel/Page)Up/Down>, <Home/End>. - Only set the float top border when separation is actually necessary, i.e. window does not reach the first row.
* refactor(lsp): provide a default list handler example #39005Yi Ming2026-04-16
| | | | | | | | | | | | | | Problem: Difficult for us to provide default handlers for functions like `vim.lsp.buf.definition`. When users wanted to fine-tune the default behavior, they don't know how. Solution: - Document an example providing `on_list` boilerplate to make it easier for users to modify and override. - Also, considering that the parameters of the previous `on_list`(`vim.lsp.ListOpts.OnList`) are compatible with the parameters of `setqflist`, remove that custom type in favor of passing `vim.fn.setqflist.what`.
* fix(treesitter): TSNode:id() with NUL byte causes unreliable select() #39134altermo2026-04-16
| | | | | | | | | | | Problem: `TSNode:id()` returns the underlying c pointer as a string, which may include NUL bytes. In PUC Lua, `('%s'):format('\0a\0')` returns `''` and not `'\0a\0'` (i.e. treats the string as a c-string (which terminates at the NUL byte)). This resulted in two different nodes being able to have the same id. Solution: Use concatenation `..` instead of `string.format()`.
* docs(pack): improve "Synchronize across machines" steps #39122Evgeni Chasnovski2026-04-16
| | | | | | | | | | Problem: Sometimes automatic lockfile synchronization after `:restart` might fail, like due to bad/absent Internet connection. This would remove failed to install entries from the lockfile (since they are not on disk and lockfile is meant to lock the latest plugin version on disk). Solution: Document that this should be treated as an unwanted update and use steps similar to "Revert plugin after an update" use case.
* test: lint naming conventions #39117Justin M. Keyes2026-04-16
| | | | | | | | | | | | Problem: Naming conventions are not automatically checked. Solution: Add a check to the doc generator. Eventually we should extract this somehow, but that will require refactoring the doc generator... Note: this also checks non-public functions, basically anything that passes through `gen_eval_files.lua` and `gen_vimdoc.lua`. And that's a good thing.
* Merge #39078 render class dot members as module functionsJustin M. Keyes2026-04-16
|\
| * feat(docs): render class dot members as module functionsYi Ming2026-04-16
| | | | | | | | AI-assisted: Codex
| * revert: "docs: vim.range, vim.pos #38869"Yi Ming2026-04-15
| | | | | | | | This reverts commit c530fd8e752607f57b83854b74b029eabe8d57c6.
* | refactor(lsp): fix typing for LSP methods #39099Luis Calle2026-04-16
| | | | | | | | | | | | | | | | Problem Some variables use the wrong type (ClientToServer instead of ServerToClient) and some use vaguer types that could be more strict. Solution Use the correct types.
* | vim-patch:9.2.0354: filetype: not all Bitbake include files are recognizedzeertzjq2026-04-16
| | | | | | | | | | | | | | | | | | | | | | | | Problem: filetype: not all Bitbake include files are recognized Solution: Enhance the file detection logic and consider varflags (Martin Schwan) closes: vim/vim#19983 https://github.com/vim/vim/commit/0e02be191909df88a8d6ef0a1b091c67c49b1888 Co-authored-by: Martin Schwan <m.schwan@phytec.de>