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.
Problem:
On Windows and macOS, entries in `oldfiles` may differ only in case,
but actually refer to the same file.
Solution:
Previously, deduplication used `Set_cstr_t`. We can add a similar `Set_path_t`
that performs path-aware comparisons, ignoring case differences. On Windows, it
could also ignore path separator differences, and treat `C:\foo` and `\foo` as
the same path when the current drive is `C:`.
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
Problem:
On some non-US keyboards, like Estonian/Swedish/etc, widely used []
characters in vim are hard to type. One way to overcome this is to use langmap
option to map accented characters, that are in the same place as [] on US
keyboards to []. Unfortunately this does not work currently in neovim, it
cannot map multibyte characters via langmap.
Solution:
The fix iterates over characters in typeahead and key buffers, instead of bytes,
in getchar.c handle_mapping(). It does not handle macros though, these tests are
still failing when turned on.
Closes#2420Closes#27776
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
Problem:
Any random ftplugin or other autocmd, can throw an error when
`:checktime` reloads a buffer. This causes a trace which makes it look
like an issue with `autoread.lua`.
vim.schedule callback: …/runtime/lua/nvim/autoread.lua:146:
FileType Autocommands for "*"..function <SNR>1_LoadFTPlugin[20] ..script
…/runtime/ftplugin/help.lua: Vim(runtime):E5113: Lua chunk:
…/runtime/lua/vim/treesitter.lua:216: Index out of bounds
stack traceback:
[C]: in function 'nvim_buf_get_text'
…/runtime/lua/vim/treesitter.lua:216: in function 'get_node_text'
…/runtime/lua/vim/treesitter/query.lua:558: in function 'handler'
…/runtime/lua/vim/treesitter/query.lua:843: in function '_match_predicates'
…/runtime/lua/vim/treesitter/query.lua:1082: in function '(for generator)'
…/runtime/ftplugin/help.lua:91: in function 'runnables'
…/runtime/ftplugin/help.lua:124: in main chunk
[C]: in function 'checktime'
…/runtime/lua/nvim/autoread.lua:146: in function <…/runtime/lua/nvim/autoread.lua:138>
Solution:
Use pcall() and surface the error via nvim_echo.
Problem:
Old 'autoread' only did `:checktime` on focus-change and shell (":!")
commands, and only for non-hidden buffers. Since 'autoread' is now
driven by OS filewatcher events, buffers are updated much more eagerly.
This should be surfaced to the user somehow, either via a carefully
placed notification, or a minimal UI indicator.
A "notification" would be noisy, unless it is conditional on specific
circumstances (e.g. when "many" buffers are updated).
Solution:
Use the existing 'busy' buffer-local option as a subtle hint about
activity.
Problem: The semantic token module is using its own debounce timer for
the buffer on_lines event. If its internal debounce is shorter than the
changetracking module's debounce, it's possible for semantic token
requests to fire for changed buffers before the textDocument/didChange
notification is sent to the server.
Solution: Trigger semantic token requests from the LspNotify autocmd
when the method is the didChange or didOpen notifications, which
enforces a strict happens-before relationship for the sync change
notification followed by a semantic token request.
Note: There is still an internal debounce mechanism in the semantic
token module to handle other debouncing needs specific to its
functionality, such as debouncing server refresh notifications and
handling WinScrolled events when using range requests.
Problem: Running `vim.filetype.match()` when current working directory
was removed from disk throws a `vim.fs.abspath` assertion error.
However, the matching might still be possible without trying to match
against full path (like if it is a known extension).
Solution: Safely compute absolute path and ignore it if it errors.
Problem: Clicking on a "below" virtual line interacts with the line
it is attached to for decor/drawing purposes, rather than
the line the extmark is placed at.
Solution: Account for "below" virtual lines when computing mouse line number.
Problem:
After 400f247397 the undotree test became flaky.
It seems to be caused by some kind of race condition where an entry in the undotree is not added when a change in the buffer happens (adding a bunch of sleep around buffer-change operations seems to fix the issue).
Solution:
Disable autoread plugin in undotree test.
Problem: Diagnostic virtual lines are hardcoded with "scroll" for
virt_lines_overflow option.
Solution: Add a `overflow` option to `virtual_lines` config
to support "wrap", "scroll", "trunc", and "auto".
Problem:
The 'autoread' option only checks for file changes reactively — on
FocusGained, :checktime, CmdlineEnter, etc. — by polling timestamps.
External changes are not detected until the user interacts with Neovim.
Solution:
Add a core module (runtime/lua/nvim/autoread.lua) enabled from
runtime/plugin/autoread.lua that watches each buffer's file using
vim._watch.watch() (libuv fs_event). On change detection it calls
:checktime, which invokes the existing buf_check_timestamp() logic
for reload/prompt handling. Watchers are managed via autocmds tied
to buffer lifecycle events and respect the 'autoread' option (global
and buffer-local).
Problem:
stdpath() may return a DOS 8.3 "shortened" filename, because Windows
truncates long usernames into `6ch~N` names in `TEMP/TMP` env vars.
We don't want to "leak" them into Nvim.
Solution:
For "run", pass `true` to `vim_FullName` to expand 8.3 filenames.
For "cache", call `os_realpath` to expand 8.3 filenames.
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
Problem:
Listing individual "skipped" notices for each non-actionable or
NVIM_TEST_INTEG test is noisy and makes the "skipped" list overwhelming
and less meaningful.
Solution:
- Mark non-actionable tests with "N/A".
- Report NVIM_TEST_INTEG tests as a separate 1-line summary.
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`.
Problem:
A text edit positioned entirely past the last buffer line, with
newText ending in a newline, leaves a stray blank line: the
past-the-end path appends the trailing empty fragment produced by
vim.split() and does not set has_eol_text_edit, so the end-of-buffer
cleanup is skipped. Formatting servers emit such edits whenever
formatting moves text to the end of a document.
Regression from ec94014cd1 (#20137), which split the past-the-end
fast path off the clamp path that sets the flag.
Solution:
Set has_eol_text_edit in the past-the-end path, like the adjacent
path that clamps end_row.
Problem:
When a server sends workspace/codeLens/refresh while an automatic codelens
request is already scheduled, Nvim ignores the server refresh. This can leave
rendered codelens text stale until another buffer edit triggers a new request.
Solution:
Cancel the pending automatic request and send the server-requested refresh
immediately. This preserves request coalescing while giving explicit server
refreshes priority.
Problem:
Since 5181984d, `nvim_exec_autocmds({buf=…})` temporarily sets the
`buf`-window as current-window, and its statusline renders as
a "current-window statusline", regardless of the user's actual
current-window.
Solution:
Mark the statusline for redraw in `aucmd_restbuf()`, so it is redrawn
correctly after the event.
Co-authored-by: Luuk van Baal <luukvbaal@gmail.com>
Problem:
* 'shellcmdflag' states that its default value is set according to the
value of 'shell', but this behavior is not yet implemented on Windows.
The same applies to 'shellpipe', 'shellredir', and 'shellxquote'.
* On Windows, Git is often installed in paths containing spaces, and we
still do not correctly resolve the sh executable name as described in
'shell'.
* On Windows, the default value of 'shellslash' is always `false`,
which causes Unix-like shells to interpret `\` in paths returned by
some functions as escape charaters.
Solution:
Use a simple rule table to detect common shells (e.g. `cmd`,
`powershell`, shells whose names contain `csh` or `sh`) and apply
best-effort defaults, while leaving more complex scenarios to user
configuration.
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.
Problem: Extmark has support for horizontal scrolling and truncating, but not wrapping.
Solution: Extend virt_lines_overflow flags to support "wrap" and "auto" based on proposed changes in #18282.
Problem: In command-line completion with a popup menu ('wildoptions'
contains "pum"), the info popup shown next to the menu could
not be scrolled, unlike the Insert mode completion info popup
which scrolls with the mouse wheel.
Solution: When the mouse pointer is on top of the info popup, scroll it
with the mouse wheel in command-line mode as well, without
closing the completion popup menu.
closes: vim/vim#20146closes: vim/vim#2041896dbab257a
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
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.
Problem:
The comma form of 'winborder' is split with copy_option_part(),
whose skip_to_option_part() eats spaces after a comma, and empty
fields are rejected.
Solution:
Split the comma form literally on ',', keeping empty fields and
single-space fields.
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.
Problem: Redundant newlines and "Press any key" prompt with ext_messages
for Visual filter command.
Solution: Remove newlines and prompt with ext_messages.
Problem:
Edit a file with a drive-letter path, then re-edit it without the drive letter
and colon. This cause `path_fnamencmp` to loop infinitely as `len` never
reaches 0, while `c1` and `c2` are already NUL.
Commit e18a578 accidentally used || before `(p_fic`, commit 4bcee96 fixed that,
but also moved the NUL check into a grouped condition. The bug remained hidden
because there weren't any cases where strings had different lengths and c1 and
c2 could both reach NUL. `c:/foo` vs `/foo` happens to be such a case, which is
why the infinite loop finally showed up.
Solution:
Break the loop when either `c1` or `c2` is NUL.
Problem:
Diagnostic highlight groups were applied by iterating and calling
`vim.hl.range` for each group individually. That resulted in multiple
extmarks with the same priority being created separately, which does not
allow `DiagnosticUnnecessary` and `DiagnosticDeprecated` with matching
options override `Diagnostic*` styling.
Solution:
Pass the list of hl-groups to `vim.hl.range` so they are applied
together in the correct order.
Problem:
PR #38340 prevented messages we receive with id:null from being
incorrectly classified as notifications, but caused us to ignore all
messages with id:null, including requests.
Solution:
Handle requests with id:null. When we receive a request, we only need to
respond based on the `method` and `param`.
(The original so-called `notification_received` in the test was actually
semantically `request_or_notification_received`.)
Problem: when the TUI output buffer is filled during a redraw, flushing
it to the terminal also causes `CSI ? 2026 l` to be emitted, which ends
synchronized output. This causes visible flickering with large redraws.
Solution: track whether a synchronized output is currently active, and
only emit the end sequence on the final flush.
The new lua based runner replaces Makefile, runnvim.sh and runnvim.vim
As it happens, we run a `--headless` nvim inside a `:terminal` layer,
this is pointless.
Also there is still a lot remnants for oldesttests, but we don't
have any except for test1.in which just checks the environment
for following, nonexistant oldesttests. so just skip that.
For now, the actual vimscript code which runs in vim-under-test is
completely unchanged.
On macos, luajit is finally working with the latest ziglua master.
Also fix some minor bugs regarding locales, such as incorrect
HAVE_WORKING_LIBINTL checks
Problem: nvim_win_set_config() does not error on flags not allowed for
non-floating windows.
`hide` should not be allowed for non-floating windows.
Solution: Check that a window is a split when reconfiguring.
Error when trying to hide a split window.
Problem:
Literal tab (or other control char) in a float title/footer is
not made printable, so it renders incorrectly instead of as "^I".
Solution:
Normalize title/footer text for display like 'statusline'
tab to "^I", parameterize parse_virt_text() with untab
and recompute the width.
Problem: Redrawing in an autocommand that uses an autocommand window
(more common since 5181984d) can result in flickering.
Solution: Hide autocommand windows.
Problem:
It is repetitive to map multiple keymaps to do the same thing. Here are some
cases where being able to do this would be useful:
-- Visual movement for both j/k and down/up:
vim.keymap.set({ 'n', 'x' }, { 'j', '<Down>' }, 'v:count == 0 ? "gj" : "j"', { expr = true })
vim.keymap.set({ 'n', 'x' }, { 'k', '<Up>' }, 'v:count == 0 ? "gk" : "k"', { expr = true })
-- Map multiple keys to `<Nop>` concisely:
vim.keymap.set({ 'n', 'x' }, { '<Leader>', '<Localleader>', '<CR>' }, '<Nop>')
-- Remove multiple keymaps at once:
vim.keymap.del('n', { 'gri', 'grn', 'grr' })
Solution:
Support the `lhs` of `vim.keymap.set()` and `vim.keymap.del()` being a table, in
the same way that `modes` can be.
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.
Problem: Redrawing when a loaded buffer is not shown in any window on
the current tabpage.
Solution: Check that buffer is shown in a (normal) window before redrawing.