aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua
Commit message (Collapse)AuthorAge
...
* feat(lsp): convert inlay_hint to capability framework #40569jdrouhard2026-07-05
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Inlay hints used separate global and per-buffer bufstates tables and bespoke global autocmds for managing the inlay hint state across buffers and clients, duplicating the lifecycle logic already provided by the Capability framework. This caused inconsistencies in how client state was handled and inlay hint state lifecycle was managed compared to other LSP features. Solution: Replace the ad-hoc bufstate tracking and global autocmds in vim.lsp.inlay_hint with a proper InlayHint subclass of Capability. This also refactors the way inlay hint state is managed and fixes bugs I found while doing this: 1. For each line with inlay hints, the list of the hints along with whether they have been applied is stored in a current result on the client state. This allows the on_win decorator to clear all inlay hints for an old document version once, and then re-add the new version's hints line-by-line as they are drawn to the screen, modeling the semantic tokens module. 2. It fixes problems with mixing results from multiple clients attached to the buffer by fully moving each client's state to its own table. Previously, only the most recent document version used to populate a line's inlay hints was stored, but there was no distinction for which client the hints may have come from. (Fixes #36318) 3. It fixes the workspace/inlayHint/refresh server->client notification behavior. Previously it would only re-request inlay hints for buffers currently displayed in a window but would not invalidate them in non-displayed buffers (or provide any mechanism for those buffers to re-request at a later time). Model semantic token module here again by invalidating all buffers, and adding a BufWinEnter autocmd to refresh hints. 4. Add a mechanism to cancel in-flight requests if a new request for a newer document version is made before the last one returned 5. Handle stale results by simply dropping them.
* Merge #40520 nvim_win_resizeJustin M. Keyes2026-07-05
|\
| * feat(api): add nvim_win_resize()XiaowenHu962026-07-05
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Ref #6645 Problem: When a window is resized it takes space from the window right/below first, and only falls back to the window left/above when there is no more room. Sometimes a user wants the space to come from a specific direction. Solution: Add nvim_win_resize(win, width, height, {anchor}) which resizes a window with a choosable anchor edge, letting a window grow leftwards or upwards by taking space from the window to the left or above first. The default anchor reproduces nvim_win_set_width()/nvim_win_set_height().
* | fix(lsp): support -1 column in format range #40570Barrett Ruth2026-07-05
| | | | | | | | | | | | | | | | | | | | Problem: `vim.lsp.buf.format()` accepts ranges using nvim indexing, where an end column of -1 means end of line. LSP ranges cannot use that, which is confusing for things like range formatting. Solution: Resolve -1 end columns to the line length before converting the range to LSP positions.
* | fix(health): always set 'modifiable' #40584dqnne2026-07-05
| | | | | | | | | | | | | | | | Problem: When buffers are by default `nomodifiable`, such as when Nvim starts with `-M`, the health buffer cannot be updated. Solution: Always set `modifiable` before modifying the buffer.
* | fix(health): don't check node package via yarn #40572Barrett Ruth2026-07-04
| |
* | feat(channel): add ChanClose event #40568Barrett Ruth2026-07-04
| | | | | | | | | | | | | | | | | | Problem: Plugins using RPC sockets cannot detect when the peer closes a `sockconnect()` channel, so reconnect logic has no reliable trigger. Solution: Add a `ChanClose` event with channel info before the channel is removed, matching the existing `ChanOpen`/`ChanInfo` event model.
* | fix(lsp): semantic tokens reset_timer() usage #40554jdrouhard2026-07-04
| | | | | | | | | | | | | | | | | | | | | | | | | | Problem: reset_timer() was being called without checking for whether the client state for the client_id still existed. debounce_request() starts a timer that defers a call to send_request() which then calls reset_timer(). If the timer fires after the client_state is erased, then the deferred function attempts to dereference the timer on a nil client state. Solution: Change reset_timer to take a state directly so it can't be nil and move the reset_timer() call inside a guard that ensures state exists. Additionally, reset a client's timer when the client detaches so it doesn't become dangling.
* | fix(lsp): use LspNotify for document_color #40571jdrouhard2026-07-04
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: The document_color lsp module was already using the capability framework but was still using raw buffer events to handle requests and reloading. This means that every keystroke was sending a document_color request to the server since there was no debounce in the raw handlers. Solution: Switch to using LspNotify autocmd events. LspNotify fires just after new document versions are synced with the server and provides a built in debounce mechanism for changes. It also provides the signal for when the current state should be cleared (didClose). The detach part is already handled by the capability framework. Fixes #39785
* | docs(lsp): document rpc Client request/notify as fields #40573Barrett Ruth2026-07-04
| | | | | | | | | | | | | | | | | | | | Problem: `request()` and `notify()` are methods of the object returned by `vim.lsp.rpc.start()`/`connect()`, but were rendered with module-level helptags (`vim.lsp.rpc.request()`, `vim.lsp.rpc.notify()`) (erroneously implying module functions that do not exist). Solution: Mark the wrappers `@private` and describe them on `vim.lsp.rpc.Client` instead.
* | fix(cmdwin): set 'noscrollbind' #40556STG2026-07-04
| | | | | | | | | | | | | | | | Problem: Opening cmdwin from a 'scrollbind' window makes cmdwin scrollbinded. Legacy cmdwin set 'noscrollbind'. Solution: Set 'noscrollbind'.
* | fix(dir): define "-" (up/parent) mapping earlier #40531Barrett Ruth2026-07-02
| | | | | | | | | | | | | | | | | | | | Problem: The dir.lua "-" mapping cannot be easily overridden (because of autocmd ordering). Solution: - Move it to defaults.lua. - Also to be extra polite: fall back to builtin `-` motion if the user disabled the `dir.lua` plugin.
* | docs: pos argument in vim.lsp.ListOpts should be optional #40550nikolightsaber2026-07-02
| | | | | | | | | | | | | | | | Problem: the pos argument in ListOps for lsp is an optional parameter, but the lua_ls typing system doesn't reflect that Solution: let pos be optional Co-authored-by: nikolightsaber <nikolightsaber@gmail.com>
* | fix(pack): do not assert non-nil `stderr` #40544Evgeni Chasnovski2026-07-02
| | | | | | | | | | | | | | | | | | | | | | | | Problem: On some systems `stderr` can be disabled. This results in not usable `vim.pack` since it asserted `stderr` to be non-nil. Solution: Stop asserting non-nil `stderr`. The downside is that potential errors are not shown, but this is intentional since `stderr` is disabled on system level. Still assert non-nil `stdout` as its output is important for `vim.pack` to actually do its job. Disabled `stdout` is not something that can work with `vim.pack`.
* | fix(health): handle failed dir listingJustin M. Keyes2026-07-01
| |
* | feat(health): report ulimit infoJustin M. Keyes2026-07-01
| | | | | | | | | | | | | | | | | | Problem: Nvim shows `(libuv) kqueue(): Too many open files` on macos. ref https://github.com/neovim/neovim/issues/40238 Solution: Add a healthcheck for this situation.
* | refactor(dir): use vim.fs.dir()Justin M. Keyes2026-07-01
| |
* | feat(vim.fs): dir() ergonomicsJustin M. Keyes2026-07-01
| |
* | fix(vim.fs): dir(), find() error-reportingJustin M. Keyes2026-07-01
| |
* | feat(vim.fs): dir(), find() error-reportingRudrajeet Pal2026-07-01
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: vim.fs.dir() and vim.fs.find() drop errors returned by uv.fs_scandir(). Solution: - vim.fs.dir(): - Return root scan failures as a secondary return value. - Propagate recursive scan failures through the iterator. This allows callers to distinguish unreadable directories from empty ones. - vim.fs.find(): Collect errors during search, and return the list as a second retval.
* | fix(lsp): request semantic tokens in BufWinEnter (#40510)jdrouhard2026-06-30
| | | | | | | | | | | | | | | | | | Problem: A previous refactor removed the BufWinEnter autocmd that initiated a token request. When an LSP server sends a refresh notification, then buffers that aren't shown in any window lost their only trigger to request new tokens. Solution: Add the BufWinEnter autocmd back which simply requests tokens for all clients attached to the buffer.
* | fix(dir): reload listing on :edit #40496Barrett Ruth2026-06-30
| |
* | fix(cmdwin): handle control characters properly #40488zeertzjq2026-06-30
| | | | | | | | | | - Replace newlines in the current cmdline with NULs when opening cmdwin, and do the reverse when putting a cmdwin line back into the cmdline. - Escape control characters with Ctrl-V when feeding cmdline.
* | fix(dir): remove loaded plugin guard #40489Barrett Ruth2026-06-30
| |
* | fix(cmdwin): handle split/tabpageJustin M. Keyes2026-06-29
| | | | | | | | | | | | | | | | | | | | | | | | Problem: - If cmdwin window is split, ENTER in one does not close the others. - If cmdwin is put into a different tabpage via <c-w>T, it stops working (ENTER does not execute the cmd). Solution: - Close the buffer instead of the window. - In the WinClosed handler, skip `M._cleanup()` unless this is the last cmdwin window.
* | refactor: cleanup, docs #40480Justin M. Keyes2026-06-29
| |
* | feat(:restart)!: ":restart" (no bang) saves/restores session #40321Nathan Zeng2026-06-29
| | | | | | | | | | | | | | | | | | | | | | 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!`.
* | perf(options): avoid Lua<=>API roundtrips #40477Justin M. Keyes2026-06-29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* | vim-patch:9.2.0742: filetype: SSH keys and related filetypes not recognized ↵zeertzjq2026-06-28
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (#40469) Problem: filetype: SSH keys and related filetypes not recognized Solution: Detect sshpublickey, sshknownhosts sshauthorizedkeys and sshallowedsigners filetypes, add syntax scripts for those filetypes (Fionn Fitzmaurice) This adds syntax highlighting for SSH public keys, as well as related filetypes derived from this (SSH authorized keys, SSH known hosts and SSH allowed signers). Also add filetype detection based on the path and name. closes: vim/vim#20635 https://github.com/vim/vim/commit/6e66ebc0fdd7804db4baa076e62c78d208adaeaf Co-authored-by: Fionn Fitzmaurice <git@fionn.computer>
* | feat(api): nvim_set_option_value(operation=...) #39849Kyle2026-06-28
| | | | | | | | | | | | | | | | | | | | | | | | | | 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`.
* | feat(pack): ensure order of `PackChanged{Pre,}` events #40455Evgeni Chasnovski2026-06-27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: due to totally async install/update/checkout there is no guaranteed order of `PackChanged{Pre,}` events across different plugins. This might lead to conflicts when callback for some "main" plugin relies on features from "dependency" plugin: i.e. callback for "main" plugin can trigger before installing/updating "dependency" plugin. The installation order can be enforced by separate vim.pack.add() calls, but update/checkout can not. Solution: Trigger events in bulk independently of async execution: - `PackChangedPre` before any action for all input plugins in order they are supplied. It will also trigger even if an action will fail. - `PackChanged` after all actions finished for all sucessfully affected plugins in order they are supplied. This also comes with a couple of side effect changes: - `PackChangedPre kind=delete` is now also triggered even if the delete won't be done. This makes it more aligned with `kind=install` and `kind=update`. - Force update (`:packupdate!`) and "udpate LSP action" now do two async steps: download/compute updates and apply them. This also results in two progress reports. This is mostly a by-product of the implementation (there has to be a pre-computation of target revision for all plugins before doing `PackChangedPre` in bulk before possibly applying an update), but I kind of like it more this way as it is more explicit of what's going on. If absolutely not acceptable, there might be some hacks to mitigate it at least in code action, but I'd keep it like this.
* | fix(dir): respect directory buffer lifetime #40453Barrett Ruth2026-06-27
| | | | | | | | | | | | | | | | | | | | Problem: dir.lua leaves previously-navigated directory buffers around. This is fine by default, but users need a simple way to opt out. Solution: 1. Respect `set hidden` (via `'bufhidden'`) as one way to make previously-navigated dir buffers from showing up. 2. Document a one-liner to hide these buffers
* | feat(statusline)!: allow %= in item groups, scope %< to item groups #40369Sébastien Hoffmann2026-06-27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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
* | fix(lsp): process semantic tokens LspNotify callback only when attached #40450jdrouhard2026-06-27
| | | | | | | | | | | | | | | | | | | | | | Problem: LspNotify will fire for any attached client. If there's at least two clients where one has semantic tokens enabled and one that doesn't, the disabled one will get the LspNotify requests but won't have a client state. Solution: Only process LspNotify autocmds if there's a client state to act on. Fixes #40448
* | fix(cmdwin): do not block WinEnter events on close #40449Evgeni Chasnovski2026-06-27
| | | | | | | | | | Problem: manual closing cmdwin blocks some events. Solution: use `nested=true` in buffer-local `WinClosed` event.
* | vim-patch:9.2.0728: filetype: supertux info pattern is relative to current dirzeertzjq2026-06-27
| | | | | | | | | | | | | | | | | | | | Problem: filetype: supertux info pattern is relative to current directory (after 9.2.0716). Solution: Add `*/` to the start of the pattern (zeertzjq) closes: vim/vim#20629 https://github.com/vim/vim/commit/c30ee2efa905473e54b095b8467af986b033296b
* | vim-patch:9.2.0716: filetype: not all supertux files are recognizedzeertzjq2026-06-27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: filetype: not all supertux files are recognized Solution: Detect more supertux related files as scheme filetype (Wu Zhenyu) levels: *.stwm: supertux world map https://github.com/SuperTux/supertux/wiki/Worldmap-Format *.stl: supertux level https://github.com/S