aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim
Commit message (Collapse)AuthorAge
...
| * | fix(cmdwin): implement Enter/Ctrl-C as builtinsJustin M. Keyes2026-06-26
| | | | | | | | | | | | What echasnovski wants, echasnovski gets.
| * | fix(cmdwin): space in cmdwin-char 'statuscolumn'Justin M. Keyes2026-06-26
| | | | | | | | | | | | | | | To match the old behavior, the cmdwin-char should not be followed by a space char.
| * | fix(cmdwin): duplicate line in historyJustin M. Keyes2026-06-26
| | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: After ctrl-f from the cmdline, the last 2 lines of cmdwin are redundant. Solution: In `open_cmdwin`, clear the live cmdline so that unwinding it (via Ctrl_C) does not add it to history.
* | | fix(lsp): define autocmds for capabilities once per buffer #40435jdrouhard2026-06-26
|/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | fix(lsp): define autocmds for capabilities in new(), not on_attach() Problem: Defining autocmds in on_attach() caused issues when multiple clients provide the same capability for a buffer. Each attaching client would "replace" the previously defined one since they are all identical. Then the first one to detach clears them out and any remaining attached clients would no longer trigger the autocmd for the capability. Further, the semantic tokens module itself didn't quite work with multiple clients since any LspNotify (from any client) would send a token request to all attached clients with no differentiation and the debounce timer was shared across all clients. Solution: Always define the buffer-local autocmds in the capability's `new()` function, and don't mess with the autocmds in on_attach or on_detach. The capability framework itself will clear the autocmds when the last client detaches. Also, refactor a bit of the semantic tokens module so that the various methods take a specific client_id to perform the work on, and split out timers so each client has its own.
* | refactor(lsp): convert diagnostics to capability framework #40433jdrouhard2026-06-26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Diagnostic tracking used a separate bufstates table and manual LspDetach/LspNotify autocmd management via _enable()/_refresh(), duplicating the lifecycle logic already provided by the Capability framework. This caused inconsistencies in how client attach/detach and buffer teardown were handled compared to other LSP features. Solution: Replace the ad-hoc bufstate tracking and _enable/_refresh pattern in vim.lsp.diagnostic with a proper Diagnostics subclass of Capability. This cleans up a few random places in the main lsp module and client module that were poking the diagnostics. It also fixes some pre-existing bugs and inconsistencies that were discovered: - Refresh diagnostics immediately on attach instead of lazily by the first didOpen/didChange notification - Fix Capability.active lookup in M.enable() to key by it_bufnr instead of the filter bufnr - Set lsp defaults before calling the _text_document_did_open_handler in Client:on_attach() so defaults are there before any lsp notification occurs - Log (and return early) on any error from a diagnostic request result instead of only returning early for server cancelled errors
* | fix(lsp): use root_dir as cmd CWD #40331Barrett Ruth2026-06-26
| | | | | | | | | | | | | | | | | | | | | | | | Problem: cmd given as string[] always starts using Nvim's CWD, which is arbitrary. Solution: If cmd_cwd is not given, use root_dir as CWD. BREAKING CHANGE: LSP commands given as string arrays now use `root_dir` as the process working directory when `cmd_cwd` is unset. Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* | Merge #40325 from justinmk/cmdwinJustin M. Keyes2026-06-25
|\ \
| * | fix(ui2): "msg_history_show" error while in cmdwinJustin M. Keyes2026-06-25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Executing :messages while in cmdwin fails: Error in "msg_history_show" UI event handler (ns=nvim.ui2): Lua: …/_core/ui2/messages.lua:699: Invalid 'height': expected positive Integer stack traceback: [C]: in function 'nvim_win_set_config' …/_core/ui2/messages.lua:699: in function 'set_pos' …/_core/ui2/messages.lua:329: in function 'set_target_pos' …/_core/ui2/messages.lua:389: in function 'show_msg' …/_core/ui2/messages.lua:553: in function 'handler' …/_core/ui2.lua:161: in function 'ui_callback' …/_core/ui2.lua:210: in function <…/_core/ui2.lua:202> The bug: when `texth.all` is small (e.g. 0 from a hidden pager whose new content isn't laid out yet), or when the available height after subtracting the cmdwin is small, `math.min(min, …)` can yield 0, and `nvim_win_set_config` rejects `height=0`. Solution: Floor at 1.
| * | feat(cmdwin): implement cmdwin as a normal buf+winJustin M. Keyes2026-06-25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: cmdwin (the `:q` cmdline buffer) has various limitations which require special-casing all over the codebase. Besides complicating the code, it also breaks async plugins if they try to create buffers/windows after some work is done, if the user happens to open cmdwin at the wrong the moment: Lua callback: …/guh.nvim/lua/guh/util.lua:531: E11: Invalid in command-line window; <CR> executes, CTRL-C quits stack traceback: [C]: in function 'nvim_buf_delete' …/guh.nvim/lua/guh/util.lua:531: in function <…/guh.nvim/lua/guh/util.lua:526> Solution: Just say no to "inception". Reimplement cmdwin as a normal buffer+window. All of the cmdwin contortions (in both core, and innocent plugins) exist literally only to support "inception": recursive cmdwin-in-cmdline-things, like `<c-r>=`, `/`, search-during-substitute, `:input()`, etc. So we just won't support that (though I have a potential plan for that later, which I call "modal parking lot"). The benefit is that plugins, and core, no longer have to care about cmdwin. BONUS: - mouse-drag on vertical separators works (it only worked for horizontal/statusline before) - inccommand-in-cmdwin now works correctly, for free (thus don't need #40077). POTENTIAL FOLLOWUPS - Drop `CHECK_CMDWIN` ("E11: Invalid in command-line window"), allow chaos. - Unify `BUFLOCK_OK` / `LOCK_OK` ? DESIGN: - Eliminate lots of C globals, `EX_CMDWIN`, etc. - `text_locked()` no longer reports true for cmdwin. - cmdwin = a normal window with 'winfixbuf', 'bufhidden=wipe', 'buftype=nofile'. Invariants come from those options rather than special cases throughout the codebase. - `nv_record` for q:/q//q? calls Lua `nlua_call_vimfn("vim._core.cmdwin", …)`. No `K_CMDWIN` / cmdline-reader detour. - `cedit_key` (`c_CTRL-F`) schedules a deferred event that calls `vim._core.cmdwin.open(type, content, pos)` and returns `Ctrl_C` so the in-flight cmdline cancels. Reader state is not serialized; instead the captured `(type, line, col)` is replayed via `nvim_feedkeys(type..line.."<CR>", "nt", …)` after user confirms. - On confirm/cancel: `<CR>` / `<C-C>` calls into Lua which closes the window and re-feeds the cmdline. BREAKING CHANGES: - Expression-register cmdline (`<C-R>=` from insert-mode) no longer supports cmdwin. Same applies to `input()` / `inputlist()` (already covered by `text_locked`). - Usage of cmdwin in macros/mappings will probably break (assuming they ever worked).
* | | perf(treesitter): reduce memory usage of _select.lua #40409Dmytro Meleshko2026-06-25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: The table `history` in treesitter/_select.lua stores references to previously selected TSNodes, but a TSNode needs to keep its whole TSTree alive in memory, which may be kept alive even after closing the buffer to which this history corresponds. Solution: Store just the bits of information from the TSNode we need to go back in selection history (the range and ID), without referencing the TSNode itself.
* | | fix(treesitter): incremental selection causes beeps when the bell is enabled ↵Dmytro Meleshko2026-06-25
|/ / | | | | | | | | | | | | | | | | | | | | #40414 Problem: The function visual_select() in treesitter/_select.lua is executing `:normal! v<Esc>` to ensure that `gv` later goes back to character Visual mode, but doing so when mode() is already `v` first switches back to the Normal mode, then executes <Esc>, which causes a beep. Solution: Check if the mode() is already `v` and avoid any switching in that case.
* | fix(lsp): skip invalid file watcher globs #40376 #40396Barrett Ruth2026-06-25
| | | | | | | | | | Some servers register `workspace/didChangeWatchedFiles` watchers for URI schemes that cannot be watched locally. Skipping the unsupported glob and keep the rest of the registration batch active.
* | fix(lsp): fire LspNotify didChange autocmds after undo/redo #40404jdrouhard2026-06-25
| | | | | | | | | | | | | | | | | | | | | | Problem: LspNotify autocmds were not being triggered for didChange requests when being used during undo/redo (and possibly other) actions. autocmds are blocked when calling on_lines() callbacks while doing the undo/redo action. Solution: Defer firing the autocmd until after the action is complete. This is closer to what existed before, but now there's a check in the deferred function to only fire the autocmd if the client is still active and the buffer is still attached, if applicable.
* | fix(tty): filter terminal probes by channel #40356Barrett Ruth2026-06-24
|/ | | | | | | | | | | | | | | | | | | | Problem: Terminal probes sent with `nvim_ui_send()` can reach more than one stdout TTY UI. Probes with a known TTY UI owner should not accept `TermResponse`s from unrelated UI channels. Solution: Thread the existing `chan` filter through owned terminal probes. This covers startup/attach background detection, fallback truecolor detection, and `vim.tty.query()` forwarding opts to `vim.tty.request()`. Note: Not every terminal escape path is updated here. I only passed `chan` when the caller already knows which TTY UI owns the probe. For example, this does not include: - (Followup) OSC 52 (system clipboard) detection. It needs to capture the `UIEnter` channel. Adding `{ chan = ... }` only to the nested query would be half a fix. - OSC 52 _paste_ is left global because the provider callback does not have a UI channel (paste is invoked without a ui channel/tty ui object).
* docs: bufadd(), fnameescape() guidance #40378Justin M. Keyes2026-06-23
|
* fix(tui): attribute `TermResponse` to source channel #40330Barrett Ruth2026-06-23
| | | | | | | Problem: Attach-time terminal probes cannot distinguish responses from different attached UIs. Solution: Identify the UI by RPC channel id in `TermResponse` and make `vim.tty.request()` filter responses by channel.
* fix(ui2): message before empty prompt not shownLuuk van Baal2026-06-22
| | | | | Problem: Message before empty input() is not visible. Solution: Route to dialog window with active prompt (hl_id >= 0).
* fix(ui2): clear search_count after clearing the screenLuuk van Baal2026-06-22
| | | | | | | Problem: Clearing the screen doesn't clear the "last" virtual text. Dupe counter virtual text is not increased beyond 1. Solution: Clear "last" virtual text when clearing the screen. Restore assignment lost in a previous commit.
* fix(defaults): detect `'background'`/`'termguicolors'` on UI attach #40175Barrett Ruth2026-06-20
| | | | | | | | Problem: Terminal background and truecolor detection runs only at startup, gated on a UI being attached. A headless server has no UI then, so `'background'` and `'termguicolors'` are never detected and remote UIs ignore the terminal's theme. Solution: Also (re)detect on UIEnter. The most recently attached terminal wins; an explicit user value is preserved.
* fix(health): check more "old" filesJustin M. Keyes2026-06-20
|
* perf(ui2): accumulate message lines #40338luukvbaal2026-06-20
| | | | | | Problem: Writing a message with a large number of newlines (:echo "foo\n"->repeat(1000000)) takes longer than it has to (since c973c7ae). Solution: Accumulate newlines in a single API call when possible.
* fix(lsp): make LspNotify more robust #40332jdrouhard2026-06-20
| | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: LspNotify never passed a buffer when executing the autocmds, so buffer-local LspNotify autocmd subscriptions didn't have the correct buf in the event metadata. It was also wrapped in a schedule() so the actual autocmd was delayed until after the event loop. This could result in the wrong buffer receiving the notification if multiple LspNotify autocmds with buffer filters were added. Only the "latest" one would actually receive non-buffer-filtered autocmds, not the matching one. It also caused listeners to receive the notification "out of sync" with when the notification is actually sent. If a buffer is being deleted (which fires a textDocument/didClose notification), the notification is scheduled and fired after the buffer is already gone. Solution: For LSP notifications that pertain to a particular buffer, set it when executing the LspNotify autocmds so the callback functions that are filtered on that buffer will get the correct notifications and the metadata buf field will be correct. Additionally, there is no need to wrap the LspNotify callback in vim.schedule when it can be called inline when the notification to the rpc server is fired. This is tested by removing now-unnecessary autocmds from semantic tokens (InsertEnter and BufWinEnter should no longer be necessary now that requests are fired by LspNotify). Without this fix, simply modifying a buffer doesn't actually trigger LspNotify correctly, and the test for that fails.
* fix(lsp): multiline semantic token processing #40339jdrouhard2026-06-20
| | | | | | | | | | | | | Problem: When multiline semantic token support was introduced, the loop that finds the end line for a particular token didn't sanitize the token length sent back by the LSP server. If the server returned an overflowed length (near uint32 max), neovim would burn cpu and loop for an extremely long time while trying to find the "end line" represented by the massively large token, causing neovim to seemingly hang. Solution: Stop looping once the calculated end_line reaches the actual last line of the buffer. Fixes #36257
* feat(column): per row click handlers for 'statuscolumn' (#40265)luukvbaal2026-06-20
| | | | | | | | | | | | | | Problem: - Current 'statuscolumn' click label caveat is restrictive. - v:virtnum is not unique to a line if it has both above and below virtual lines. - 'statuscolumn' click handler may expect v:virt/lnum to be set. Solution: - Store per-row click definitions for the statuscolumn in a (nested line/virt number) map. - Implement strategy that gives each 'statuscolumn' row a unique v:virtnum. - Set v:virt/lnum when determining which line is clicked.
* refactor(lsp): refactor linked_editing_range to use vim.lsp._capability (#40327)jdrouhard2026-06-19
| | | | | | | Problem: linked_editing_range was still doing most of the capability boilerplate itself. Solution: refactor it to make use of the common Capability framework for handling enabling, disabling, etc.
* fix(:checkhealth): open after current tabpage (#40319)zeertzjq2026-06-19
|
* feat(:restart): v:startreason #40186Nathan Zeng2026-06-18
| | | | | | | | Problem: It's clumsy for scripts to handle a "restart", without custom mappings or global vars. Solution: Introduce `v:startreason`
* fix(lsp): allow specifying bufnr + client_id filter when enabling ↵Gregory Anders2026-06-17
| | | | | | | | capabilities #37690 Today there is a constraint that these arguments to the enable filter be mutually exclusive, but I do not know why such a constraint exists (it is perfectly reasonable to want to enable a capabilility for just one buffer and just one client).
* fix(lsp): catch another nil buffer state #40285Steve Huff2026-06-16
|
* fix(lsp): requery empty isIncomplete completion lists #40100glepnir2026-06-15
| | | | | | | | | Problem: an empty `{ isIncomplete = true, items = {} }` ends completion instead of requerying. Solution: keep isIncomplete on empty lists and retrigger on keypress while incomplete. Reset on <C-e> so it doesn't immediately re-query.
* fix(api): keep highlight font through set/get and redraws #40200glepnir2026-06-15
| | | | | | | | | | | | Problem: a font set via nvim_set_hl is lost or corrupted with font-only groups, attribute combining, and update=true, and is dropped on any attr-table rebuild. nvim__inspect_cell also frees the font name while a returned dict still borrows it. Solution: register font-only groups, carry font through hl_combine_attr, inherit it on update, and persist sg_font so a rebuild can restore it. Keep interned font names across a rebuild instead of clearing them. Add the missing font field to get_hl_info. Co-authored-by: Ryan Patterson <cgamesplay@cgamesplay.com>
* feat(diagnostic): debounce current-line render #39542Oleh Volynets2026-06-15
| | | | | | | | | | | Problem: vim.diagnostic.Opts.VirtualLines.current_line and vim.diagnostic.Opts.VirtualText.current_line cause redraw on every CursorMoved event that makes the text jump uncomfortably with rapid cursor movement. Solution: `current_line` state is applied only on CursorHold, while still being cleared on CursorMoved making it so that until the cursor has stopped on a line, its diagnostic looks like cursor is not on the line preventing flicker.
* fix(tui): late-arriving OSC11 response triggers OptionSet #40270Justin M. Keyes2026-06-15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: This test is flaky since fff9897ce3f2 : FAILED ...Xtest_xdg_terminal/test/functional/terminal/tui_spec.lua @ 4359: TUI bg color does not trigger OptionSet from automatic background processing Expected values to be equal. Expected: { true, 0 } Actual: { true, 1 } stack traceback: ...Xtest_xdg_terminal/test/functional/terminal/tui_spec.lua:4380: in function <...Xtest_xdg_terminal/test/functional/terminal/tui_spec.lua:4359> `apply_optionset_autocmd_now` does not emit `OptionSet` during startup: void apply_optionset_autocmd_now(...) { // Don't do this while starting up, failure or recursively. if (starting || errmsg != NULL || *get_vim_var_str(VV_OPTION_TYPE) != NUL) { return; } ... } but if OSC 11 response arrives AFTER VimEnter, then `nvim_set_option_value('background',…)` call triggers `OptionSet`. Solution: Use `:noautocmd` when setting 'background'. Per fff9897ce3f2, OSC11 is not intended to trigger OptionSet. fix https://github.com/neovim/neovim/issues/40235
* feat(lsp): clean up semantic token initialization and debounce #40254jdrouhard2026-06-15
| | | | | | | | | | | | | | | | Problem: The refactor to use Capability left around some cruft and semi-broken configuration for debounce. Solution: Clean up now-unnecessary helper methods and simplify deprecated ones to pass through to the non-deprecated ones. `debounce` now defaults to 200 for all buffers but is overridable via the deprecated start() method, which continues to take the max value specified for any client attached to the buffer. If we wish to expose changing the debounce in a non-deprecated way, we will need to consider a "configuration" function, or even a bespoke method to set the debounce time on the main metaclass (or provide options to override for a particular buffer). General configuration of specific LSP features is an as-of-yet unsolved problem.
* vim-patch:9.2.0649: filetype: tf files sometimes incorrectly recognized (#40258)zeertzjq2026-06-15
| | | | | | | | | | | | | | Problem: filetype: tf files sometimes incorrectly recognized (Christian Robinson) Solution: Add support for g;filetype_tf variable to override detection, re-write the filetype detection loop closes: vim/vim#20510 Supported by AI https://github.com/vim/vim/commit/522a39a48962f43dabcd5e568c1ee78799599e94 Co-authored-by: Christian Brabandt <cb@256bit.org>
* feat(events): :mksession SessionWritePre event #39688Igor Lacerda2026-06-14
| | | | | | | Problem: No event triggered just before writing a session file. Solution: Add `SessionWritePre`.
* Merge #40087 from ofseed/pos-util-follow-upJustin M. Keyes2026-06-14
|\ | | | | feat(pos): create a cursor position by using the current of a window
| * feat(pos)!: match return value of `to_cursor()` with parameters of `cursor()`Yi Ming2026-06-08
| | | | | | | | | | | | | | | | | | | | | | Problem: - `pos.cursor()` receives a table contains `row` and `col` as arguments, but `pos:to_cursor` returns `row` and `col` directly without wrapping them in a table. - `pos.mark()`/`pos:to_mark` can already handle unpacked `row` `col`. Solution: Make `pos:to_cursor()` return a `row` and `col` in a table.
| * feat(pos): create a cursor position by using the current of a windowYi Ming2026-06-08
| | | | | | | | | | | | | | | | | | | | Problem: `vim.pos.cursor(vim.api.nvim_get_current_buf(win), vim.api.nvim_win_get_cursor(win))` is too verbose to create a cursor position of a window, but it is a common use case. Solution: Overload `vim.pos.cursor()`, so that it accepts `win` as an argument when `pos` is omitted.
* | feat(lsp): use LspNotify for semantic tokens #40224jdrouhard2026-06-14
| | | | | | | |