1079 Commits

Author SHA1 Message Date
Justin M. Keyes
f50f421694 test(pack): unreliable "vim.pack" tests on Windows #40717
FAILED   …/plugin/pack_spec.lua:92: …/plugin/pack_spec.lua @ 70: vim.pack update() can use lockfile revision as a target
    …/plugin/pack_spec.lua:92: …/plugin/pack_spec.lua:70: process still exists
    stack traceback:
    D:/a/neovim/neovim/test/functional/testnvim/exec_lua.lua:124: in function 'system_sync'
    …/plugin/pack_spec.lua:92: in function 'git_cmd'
    …/plugin/pack_spec.lua:113: in function 'git_add_commit'
    …/plugin/pack_spec.lua:1209: in function <…/plugin/pack_spec.lua:1173>

fix #40167
2026-07-13 10:49:48 -04:00
tao
4a08596314 fix(path): normalize separators (slashes) #39155
Problem:
Continue separators normalization, and try to keep it at the
nvim <-> external boundary, e.g., `fn.xxx`, `api.xxx`, `:xxx`

Solution:
some key changes
- normalize `$HOME-windows`
- normalize entry points of changing directory
  - `nvim_set_current_dir()`, `chdir()`
- normalize the named pipe
  - `--listen` arg, `--server` arg, `:restart`
  - `serverstart()`, `sockconnect()`, `serverstop()`
- make `expand()` respect 'shellslash' again
- clean up `did_set_shellslash`
- replace `forward_slash` with `TO_SLASH`
- remove obsolete `TMP_PATHSEPSTR`
- remove `slash_adjust` in `do_autocmd_dirchanged`?
- make `fnamemodify()` always return `/` (except when substituting
  separators via `:s`, `:gs` ?)

Note:
- these funcs still apply `slash_adjust` on return, as before:
  `:pwd`, `chdir()`, `exepath()`, `getcwd()`
- these funcs alwarys return `/`, unlike before the normalization PRs
  - `getcompletion()`, `finddir()`, `findfile()`

Also
- clean up code, comments, formatting and tests
- move `TO_SLASH` from `f_chdir` to `changedir_func`
- move `TO_SLASH` from `f_bufadd` to `buflist_new`

Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2026-07-12 13:23:44 -04:00
Kim A. Brandt
543a96e491 fix(lsp): unclear error on malformed server responses #40422
Problem:
Malformed server responses with `null` (vim.NIL) values, do not show
clear error messages.


Solution:
Assert two known, specific cases, to avoid user confusion.
2026-07-12 12:52:10 -04:00
Barrett Ruth
67af4141c8 fix(filetype): false positive when matching directory buffer #40695
Problem:
URI buffer names can end with a slash, but slash-ended directory
matching should not preempt URI filetype patterns.

Solution:
Do not use the slash shortcut for names with URI schemes, so those
continue through normal filetype matching.

Co-authored-by: Adam Karafyllidis <akisarou90@gmail.com>
2026-07-11 18:19:44 -04:00
Justin M. Keyes
0f1e0a7900 refactor(ctx): drop aucmd_prepbuf/aucmd_restbuf #40692 2026-07-11 12:04:31 -04:00
Justin M. Keyes
f2927bd919 test: unreliable "vim.system (async) supports timeout"
FAILED   2 tests, listed below:
    FAILED   …/lua/system_spec.lua:124: …/lua/system_spec.lua @ 44: vim.system (async) supports timeout
    …/lua/system_spec.lua:124: …/lua/system_spec.lua:44: process still exists
    stack traceback:
    D:/a/neovim/neovim/test/functional/testnvim/exec_lua.lua:124: in function 'system'
    …/lua/system_spec.lua:124: in function <…/lua/system_spec.lua:118>
    FAILED   …/lua/system_spec.lua:111: …/lua/system_spec.lua @ 22: vim.system (sync) can set environment with clear_env = true and env = nil
    …/lua/system_spec.lua:111: …/lua/system_spec.lua:22: process still exists
    stack traceback:
    D:/a/neovim/neovim/test/functional/testnvim/exec_lua.lua:124: in function 'system'
    …/lua/system_spec.lua:111: in function <…/lua/system_spec.lua:97>
2026-07-11 14:46:48 +02:00
Barrett Ruth
3b88a8a65d fix(filetype): ensure directory bufname ends w/ slash sep #40552
Problem:
`vim.filetype.match()` needs a cheap way to recognize directory buffers
without doing filesystem stat work.

Solution:
Ensure full buffer names for directories end in a trailing slash. Now
directory buffers can proceed through the normal 'filetype' path.

Note side-effects: session and ShaDa buffer-list restore behavior must
be compatible, so those + corresponding tests must be updated.
2026-07-10 12:40:13 -04:00
Evgeni Chasnovski
fce6d9a549 feat(lua): add cwd context to vim._with() #40653
Problem: No concise way to execute a callback with temporarily set
  working directory. This might be useful when sourcing nested files to
  allow them to assume that current working directory is their root
  directory.

Solution: Add `cwd` context to `vim._with().`
2026-07-09 07:07:14 -04:00
Justin M. Keyes
d55252a3ec refactor(logging)!: rename current_level #40642 2026-07-08 20:15:42 +00:00
bfredl
349f810eed refactor(test): unify XDG path handling (cmake vs zig)
fixes #40381
2026-07-06 10:55:20 +02:00
Manoj Panda
9456cec7f9 vim-patch:9.2.0769 conversion to utf-16be using iconv is inconsistent #40567
fix(iconv): conversion to utf-16be using iconv is inconsistent

vim-patch:9.2.0769

Problem:  enc_canonize function changes utf-16be to utf-16 but in linux
          type utf-16 defaults to utf-16le.

Solution: Creating a separate entry for utf-16be in enc_canon_table.
          Note: the effect is only visible on iconv implementations that
          treat "utf-16" and "utf-16be" differently, so the test does
          not necessarily fail on an unpatched Vim. But the bug is
          visible in vim.iconv. (Manoj Panda)

from: vim/vim@2a63f74
closes: neovim#40262

Signed-off-by: Manoj Panda <manojpandawork@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2026-07-04 11:50:38 +00:00
Justin M. Keyes
971a0a0fe0 feat(vim.fs): dir() ergonomics 2026-07-01 13:00:06 +02:00
Justin M. Keyes
f141916e3d fix(vim.fs): dir(), find() error-reporting 2026-07-01 12:05:41 +02:00
Rudrajeet Pal
4e04dff228 feat(vim.fs): dir(), find() error-reporting
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.
2026-07-01 12:05:41 +02:00
bfredl
b22a8e2f00 Merge pull request #40475 from bfredl/vim.NIL
fix(lua): give nicer error message when trying to index vim.NIL
2026-06-29 19:28:52 +02:00
Justin M. Keyes
559730af0a perf(options): avoid Lua<=>API roundtrips #40477
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.
2026-06-29 10:00:36 -04:00
bfredl
71b28da0f4 fix(lua): give nicer error message when trying to index vim.NIL
The added test shows the context, one expected a JSON field
to be a Object but it was a null value

pros: shows `vim.NIL` instead of `a userdata`
cons: the context `field 'foo'` is lost. I think this is generated
with internal magic which is hard to replicate.
2026-06-29 14:20:09 +02:00
Kyle
f34ee3da80 feat(api): nvim_set_option_value(operation=...) #39849
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`.
2026-06-28 13:20:56 -04:00
bfredl
90157d3790 fix(tests): use builtin default attributes in more places 2026-06-19 19:42:28 +02:00
Oleh Volynets
b55a868309 feat(diagnostic): debounce current-line render #39542
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.
2026-06-15 11:11:57 -04:00
Justin M. Keyes
6f3446c970 Merge #40087 from ofseed/pos-util-follow-up
feat(pos): create a cursor position by using the current of a window
2026-06-14 12:42:52 -04:00
Evgeni Chasnovski
e9b9426d7d fix(filetype): vim.filetype.match fails if CWD goes missing #40190
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.
2026-06-13 13:20:45 -04:00
John Reid
d52ebe317d feat(diagnostic): add virt_lines_overflow option for virtual_lines #40178
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".
2026-06-13 04:20:20 -04:00
Justin M. Keyes
baabb7ab6f test: mark non-actionable tests as N/A #40207
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.
2026-06-12 09:50:27 -04:00
Yi Ming
2bd13177b8 feat(pos): create a cursor position by using the current of a window
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.
2026-06-08 19:52:51 +08:00
Justin M. Keyes
ec7dab077b fix(vim.hl): range(0,…) highlight not cleared after buffer-switch #40130
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.
2026-06-06 10:26:12 +00:00
Artem Krinitsyn
738cd366f9 fix(diagnostic): stack _tags hl-groups in a single extmark #38654
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.
2026-06-02 18:36:03 -04:00
Olivia Kinnear
e728c100b5 feat(lua): support table lhs in vim.keymap.set()/del() #39948
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.
2026-05-29 14:45:33 -04:00
abdulahmoda
4b5f026ac9 fix(vim.fs): fs.dir() may return nil "type" on some filesystems #39749
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.
2026-05-29 14:24:22 -04:00
luukvbaal
cad5a4cf5c fix(lsp): unwanted redraw for buffer not in window #40002
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.
2026-05-27 09:27:25 -04:00
bfredl
2d192f3e6d Merge pull request #39920 from bfredl/luastring
fix(lua): use even safer and even better error() message conversion
2026-05-25 16:35:40 +02:00
bfredl
24e23de721 fix(lua): use even safer and even better error() message conversion
problem:
this crashes neovim:

ondska = setmetatable({}, {__tostring = error})
error(ondska)

solution:

make it not crash neovim
2026-05-25 11:06:02 +02:00
Justin M. Keyes
799cbfff85 fix(vim.secure): read() command injection vulnerability #39918
Problem:
Malicious filename can execute code because of ":" cmdline expansion.

Solution:
Use `fnameescape()`.

fix https://github.com/neovim/neovim/issues/39914
2026-05-20 15:27:43 -04:00
Yi Ming
b1c1f32089 refactor(pos,range): extract vim.pos._util
Problem:
- To share logic, creating a `vim.Range` currently creates two `vim.Pos` values
  as intermediates, which causes unnecessary table allocations.
- `pos.lua` and `range.lua` contain some overlapping logic.

Solution:
Add `vim.pos._util`, a module for handling
positions represented directly by `row` and `col`.
2026-05-20 16:23:03 +08:00
Yi Ming
856bc6d284 fix(range): handle inclusive/exclusive positions on multibyte characters 2026-05-18 22:19:07 +08:00
Justin M. Keyes
846b8b2420 refactor: group nvim_buf_call, nvim_win_call tests #39828 2026-05-17 11:20:54 -04:00
Ayose C.
3ace049c6a feat(vim.hl): vim.hl.hl_op() #39777
Problem:
vim.hl.on_yank() only works for TextYankPost, not TextPutPost.

Solution:
Introduce hl_op().
Deprecate on_yank().
2026-05-17 09:56:37 -04:00
Justin M. Keyes
6bb3e1b239 test(vim.fs): basename(), dirname() trim trailing slashes #39790
close #37698
2026-05-14 16:02:31 -04:00
Justin M. Keyes
11084f5db3 Merge #39730 from ofseed/lsp-remove-deprecated 2026-05-11 11:34:09 -04:00
Yi Ming
fd51fb3fa0 refactor!: remove deprecated APIs 2026-05-11 16:51:58 +08:00
Justin M. Keyes
5370eb0146 fix(lua): vim.wait(0) does not call loop_poll #39679
Problem:
Regression from c822a2657c: `vim.wait(0)` does not call `loop_poll`,
so `vim.wait(1)` is needed to "yield" from Lua.

Solution:
- Ensure that `vim._core.loop_poll()` is always called, even when `time=0`.
- Document how to interrupt Lua code (ctrl-c).

ref https://github.com/neovim/neovim/issues/6800
2026-05-10 14:22:31 -04:00
Yi Ming
eb79cf5aee feat(logging): vim.log #38906 2026-05-10 11:03:15 -04:00
glepnir
2dc0efccb0 fix(snippet): cancel session on <Esc> in Select mode #39238
Problem: <Esc> in a Select-mode tabstop leaves the session and highlight active.
CursorMoved isn’t triggered since the cursor doesn’t move.

Solution: use ModeChanged (s:n) instead. Defer with vim.schedule() to avoid transient
s:n from jump().
2026-05-10 09:19:12 -04:00
Maria Solano
2acf27e5ff fix(diagnostic): handle signs = false in status() (#39703) 2026-05-09 17:59:21 -07:00
Luis Calle
416f3482e7 fix(vim.range): empty ranges semantics vs regular ranges #39474
Problem:
- Empty ranges have different `<`, `<=`, `has` and `intersect` semantics compared to regular ranges.
- `to_inclusive_pos` assumes that the end position of a range is exclusive, which is not true for empty ranges

Solution:
Special case empty ranges in these operations.
2026-05-08 05:17:00 -04:00
Yi Ming
9174157f74 feat(pos): pos:to_offset(), pos.offset() #39564
Problem:
For a given position, it is not easy to compare which of several other positions is closest to it.

Solution:
Add support for converting `vim.Pos` to a buffer byte offset.

This allows for sorting, e.g:
```lua
table.sort(positions, function(pos1, pos2)
  return pos1:to_offset() < pos2:to_offset()
end
```

Or a binary search, e.g:
```lua
vim.list.bisect(positions, pos, { key = function(pos) return pos:to_offset() end })
```
2026-05-06 16:37:16 -04:00
Olivia Kinnear
fcd1d97265 feat(lua)!: vim.isnil, vim.nonnil, deprecate vim.F #39495 2026-05-06 08:15:00 -04:00
Yi Ming
f562204a5c feat(diagnostic)!: deprecate format as a table #39603 2026-05-06 07:01:21 -04:00
Yi Ming
97de5f145a perf(lua): memoize key_fn results #39568
Problem:
When using `vim.list.unique` or `vim.list.bisect`, if the `key` function is
complex, it can degrade performance, because it is invoked on every comparison

Solution:
The `key` interface convention is designed specifically to address this issue;
performance can be improved by memoizing its results.

Also added the shorthand use of the field name string as the key.
2026-05-05 17:04:11 -04:00
Yi Ming
264fbc0ace fix(lua): avoid __index when deciding if a table is a list #39556
Problem:
When a table has `__index`, `vim.islist` is unreliable.

Solution:
Index using `rawget`.
2026-05-05 16:32:20 -04:00