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.
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
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.
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.
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>
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`.
* Match command names introduced in v.5.0.0 (August 2024):
"auth", "multiinput", "status", "truecolor".
* Match command names introduced in v.4.5.0 (January 2017):
"defdynamictitle" and "dynamictitle".
* Deprecate command names that have been retired thus far:
"debug", "maxwin", "nethack", "password", "time".
* Remove a spurious "defzombie" command name (this name is
just lamented over in the documentation entry for the
"zombie" command as being more fitting than "zombie"
because its effects are not local to a window; no such
name is entered in "comm.c").
* Separately group the Braille navigation commands, "bd_*",
that may belong to another, superset program Dotscreen:
(see doc/README.DOTSCREEN and commit 848af83f5 elsewhere).
* Revise string escape characters:
- Recognise more characters, "%[`<>=eEfFHOPSxX]".
- Recognise undocumented characters, "%[gNpT]", and list
relevant Screen commits in the comments.
- Match optional qualifiers, "%\%([-+L]\|\d\+\).".
* Match more items in double-quoted command arguments.
* Match unquoted environment variable references.
* Match octal numbers, e.g. "defmode 0622".
* Match escaped octal numbers, e.g. "bind \077 help".
Unless a Dotscreen program (c. 1995) or an older than
v.4.3.1 (c. 2015) Screen program, that was compiled with
"HAVE_BRAILLE" defined, is installed and needs configuring,
add to ".vim/after/syntax/screen.vim":
-----------------------------------------------------------
if hlexists('dotscreenCommands')
syn clear dotscreenCommands
endif
-----------------------------------------------------------
To BACKPORT the updated syntax file to version 4 of Screen,
add to ".vim/after/syntax/screen.vim":
-----------------------------------------------------------
if hlexists('screenDeprecatedCommands')
syn clear screenDeprecatedCommands
endif
if hlexists('screenVersion5Commands')
syn clear screenVersion5Commands
endif
-----------------------------------------------------------
References:
https://lists.gnu.org/archive/html/info-gnu/2024-08/msg00004.htmlhttps://lists.gnu.org/archive/html/info-gnu/2017-01/msg00007.htmlhttps://git.savannah.gnu.org/git/screen.gitcloses: vim/vim#20550a65741c8b3
Co-authored-by: Aliaksei Budavei <0x000c70@gmail.com>
Co-authored-by: Dmitri Vereshchagin <dmitri.vereshchagin@gmail.com>
- Move whitespace formatting settings from the indent to the filetype
plugin behind a "typst_recommended_style" config option.
- Set browsefilter
- Improve syntax file
Thanks to Maxim Kim for taking on maintainership of the typst runtime
files.
related: vim/vim#20036
closes: vim/vim#20077dd8975428b
Co-authored-by: Doug Kearns <dougkearns@gmail.com>
Co-authored-by: Maxim Kim <habamax@gmail.com>
Problem:
Redundant code.
Solution:
Add path_skip_sep() and use it.
Dropping MB_PTR_ADV is safe: the loops only advance while `*p` is
a one-byte separator (`/`, `\`, `:`). MB_PTR_ADV was needed in legacy
Vim because it supported non-UTF-8 (DBCS) *internal* encodings.
Problem:
On Windows, `fnamemodify('//foo/C$', ':h')` incorrectly removes `C$`
as a regular file name and returns `//foo`. However, this is a valid
UNC path, `foo` is a server name and `C$` is a share name.
The correct result should be `//foo/C$`.
Solution:
Extend `os_fileinfo2` and `FileInfo` with `prefix_off`, `rest_off` to
identify path types and logical root boundaries. ':h' can use this info
to prevent traversing past the logical root.
Examples:
/foo => /
//foo => // (POSIX)
//foo/bar => //foo (POSIX)
//server/share/foo => //server/share/ (Windows)
C:/foo => C:/
//?/C:/foo => //?/C:/
Co-authored-by: Barrett Ruth <br@barrettruth.com>
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.
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.
- 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.
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.
The system version of ConPTY in kernel32.dll is old and will
mangle some VT sequences sent by shells. Newer versions of ConPTY
available as part of the Windows Terminal project fix this by
passing through VT sequences unmodified when the terminal has set
ENABLE_VIRTUAL_TERMINAL_INPUT. This change allows users to fix
buggy behaviour of Neovim's terminal on Windows by copying
conpty.dll to Neovim's bin directory.
Co-authored-by: Scott Young <s@sjy.au>
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!`.
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.
Normalize the 15 existing guards to the documented two-level form
get(g:, 'X_recommended_style', get(g:, 'filetype_recommended_style', 1)):
fix the two non-standard "!exists() || != 0" guards (python, arduino) and
tolk's wrong fallback variable, and convert the simple one-level guards.
Add the guard to filetype plugins that set stylistic indentation/format
options without one: aap, abap, ada, cabal, cobol, elixir, falcon,
graphql, heex, idris2, mermaid, occam, racket, scala, swift, tera.
Settings that are required rather than stylistic are left untouched, e.g.
make/gomod/scdoc (mandatory tabs), chatito and vroom (indent mandated by
the format), and the textwidth/formatoptions cases in gitcommit/help/
jjdescription.
Supported by AI.
fixes: vim/vim#20036closes: vim/vim#206501f33732613
Co-authored-by: Christian Brabandt <cb@256bit.org>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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#206356e66ebc0fd
Co-authored-by: Fionn Fitzmaurice <git@fionn.computer>
The following let-heredoc can cause legacy scripts to be misidentified
as Vim9 script if it appears early in the file. Only match :vim9script
at the start of a line where it sensibly belongs.
let x =<< trim LINES
vim9script
...
LINES
fixes: vim/vim#20647 (reported by Maxim Kim).
closes: vim/vim#206549a899af7e8
Co-authored-by: Doug Kearns <dougkearns@gmail.com>
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`.
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.
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
Problem: plugin/shada.lua does not respect the `+` flag of 'cpoptions'
when writing a *.shada buffer into a different file.
Solution: Check the presence of `+` in 'cpoptions' and whether the
buffer is written to a different file in BufWriteCmd for
*.shada before resetting the 'modified' option of the buffer.
This little defect appeared after plugin/shada.vim was rewritten into
Lua in #34725.
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
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
Problem: [security]: With C omni-completion, a crafted tags file can execute
arbitrary Ex commands when completing a struct/union member
(cipher-creator)
Solution: Escape the type field before inserting it into the :vimgrep
pattern so it cannot close the pattern and start a new command
(Hirohito Higashi).
Github Security Advisory:
https://github.com/vim/vim/security/advisories/GHSA-mf92-v4xw-j45x6b611b0d15
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>