Commit Graph

1059 Commits

Author SHA1 Message Date
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
Ellison
b1ebf45a6d fix(vim.net): unreliable integration tests #39594 2026-05-05 16:26:59 -04:00
Ellison
9734f33bc7 feat(vim.net): request() accepts more http methods #39406 2026-05-01 06:54:44 -04:00
Justin M. Keyes
7c4845ff46 fix(ui): z=, tselect with async vim.ui.select
Problem:
After 55ceb31,  z= and tselect don't work if `vim.ui.select` is an async
provider (especially terminal buffers).

Solution:
Drop the `vim.wait()` approach, use an async approach.

fix #39506
2026-04-30 19:19:42 +02:00
Justin M. Keyes
18d7dd485b feat(ui): use vim.ui.select for :oldfiles, :recover
Problem:
followup to 55ceb314ca #39478
`:oldfiles` and swapfile `:recover` do not delegate to `vim.ui.select`.

Solution:
- Delegate to `vim.ui.select`.
- Fix a long-standing `recover_names` bug where `concat_fnames(dir_name,
  files[i], true)` produced malformed `<dir>//<dir>/<file>` paths (also
  fixes `swapfilelist()`).
2026-04-30 17:44:31 +02:00
bfredl
77a27076e8 Merge pull request #39469 from bfredl/systempipa
fix(vim.system): use REAL PIPES for vim.system, similar to jobs
2026-04-30 13:31:45 +02:00
bfredl
46fa9354b6 fix(vim.system): use REAL PIPES for vim.system, similar to jobs
This is essentially the #35991 fix for the #35984 issue,
but applied to vim.system().
2026-04-30 12:22:57 +02:00
Justin M. Keyes
55ceb314ca feat(ui): use vim.ui.select for :tselect, z= #39478
Problem:
`:tselect` and `z=` (spell suggest) have their own bespoke select menus.

Solution:
- Delegate to `vim.ui.select` instead.
- Bonus:
  - `:tselect` gains mouse support. `print_tag_list` didn't suport mouseclick.

This causes some minor regressions, which are not blockers:

- `z=` no longer draws the list right-left if 'rightleft' is set.
  - TODO: can/should `vim.ui.select` / `vim.fn.inputlist()` handle that?
- `:tselect`
  - No "column" headings (`# pri kind tag file`).
  - No highlighting: (HLF_T: tag name, HLF_D: file, HLF_CM: extra fields).
  - TODO: can `vim.ui.select()` support highlighted chunks (`[[text, hl_id], ...]`) ?

fix https://github.com/neovim/neovim/issues/25814
fix https://github.com/neovim/neovim/issues/31987
2026-04-28 18:29:17 -04:00
Lewis Russell
c822a2657c refactor(lua): move vim.wait into runtime Lua
Move vim.wait into runtime/lua/vim/_core/editor.lua and replace
the C entrypoint with narrow vim._core helpers for polling, UI
flushing, and interrupt checks.

Keep the existing interval semantics by retaining the dummy timer that
wakes the loop while it is otherwise idle.

Update the docs to describe the success return values correctly, and
adjust the test expectation for the new vim.validate() callback error.

AI-assisted: Codex
2026-04-27 11:33:47 +01:00
Luis Calle
0b7a291238 feat(vim.pos): accept buf=0 for current buf #39414 2026-04-26 06:34:18 -04:00
Justin M. Keyes
5c88492a13 fix(trust): always use "/" slashes in filepaths #39355
Problem:
We should not use "\" (backslashes) except where absolutely required.
See references in https://github.com/neovim/neovim/pull/37729

Solution:
There is no reason to use "\" slashes in the trust db, so don't.
2026-04-24 07:37:21 -04:00
Olivia Kinnear
645a588aa6 feat(excmd): add :uptime command #39331
Problem
Nvim marks its v:starttime, but there is no user-friendly way to get Nvim's uptime.

Solution
Add :uptime (based loosely on uptime(1)).
2026-04-23 17:11:59 -04:00
Justin M. Keyes
c42aea3d37 refactor(test): deduplicate trust tests #39354 2026-04-23 16:44:21 -04:00
Barrett Ruth
0a8218a2b4 fix(trust): hash unchanged empty buffers as empty files #39027
Problem:
`vim.secure.trust()` hashes an unchanged empty buffer as
a newline, so trusting an empty file by buffer never works.

Solution:
Hash unchanged empty-buffers `''` so buffer-based
trust matches the on-disk empty file.
2026-04-23 15:01:37 -04:00
Justin M. Keyes
4ceca862fc refactor(test): drop deprecated exc_exec #39242 2026-04-20 14:16:41 -04:00
Evgeni Chasnovski
3a4cc5db0b fix(lua): make vim._with() work with buf=0 and win=0 context #39151
Problem: Using `buf=0`/`win=0` context in `vim._with` should be
  equivalent to using explicit buffer/window identifier respectively.

Solution: Explicitly adjust context in case of `buf=0` or `win=0`.
2026-04-18 12:04:28 -04:00
Evgeni Chasnovski
6b9b4a1377 fix(vim.filetype): match() fails if g:ft_ignore_pat is not defined #39158
Problem: Calling `vim.filetype.match({ filename = '...', buf = ... })`
  during startup results in an error due to not yet defined
  `g:ft_ignore_pat`.

Solution: Add a guard to check `g:ft_ignore_pat` related properties only
  if the variable is defined. This also allows to simplify other tests
  which did not depend on `g:ft_ignore_pat` but required it explicitly
  set to work.
2026-04-18 06:50:28 -04:00
Justin M. Keyes
0d4d285bd2 perf(vim.fn): call Lua-implemented vim.fn.xx() directly #39166
Problem:
- Builtin "Vimscript" functions (f_xx) are mostly implemented in C.
  Partly that's because there is some boilerplate required to call out
  to Lua.
- Calls to `vim.fn.foo()` always marshall over the Lua <=> Vimscript
  ("typval") bridge, even if `fn.foo()` is implemented entirely in Lua:
  ```
  Lua => typval => Object => Lua => Object => typval => Lua.
  ```

Solution:
Functions declared in eval.lua with `func_lua` are implemented in
entirely in Lua (`_core/vimfn.lua`).

- `gen_eval.lua` wires `func_lua` entries to `lua_wrapper`, which handles
  the typval conversion for Vimscript callers (slow path).
- `nlua_call()` detects `func_lua` functions and calls the Lua
  implementation directly. This eliminates all conversion overhead for
  Lua callers (fast path).
- Validate at build-time that `func`, `func_float`, and `func_lua` are
  mutually exclusive.
- Migrate `hostname()` as a toy example, to show the idea.
2026-04-17 19:10:20 -04:00
Justin M. Keyes
646ce85aa5 refactor: update usages of deprecated "buffer" param #39089 2026-04-15 18:45:26 +00:00
Justin M. Keyes
71ac4db335 refactor(api): rename "window" to "win" (positional parameters) #39083
continues d0af4cd909.

This commit renames positional parameters. This is only "cosmetic", but
is intended to make it extra clear which name is preferred, since people
often copy existing code despite the guidelines in `:help dev-naming`.
2026-04-15 13:31:17 -04:00
Lewis Russell
1f53abf54b refactor(diagnostic): split diagnostic module
Extract the diagnostic implementation from
runtime/lua/vim/diagnostic.lua into focused internal modules covering
config, display, float rendering, jump/list helpers, namespace and
storage management, severity/shared utilities, and statusline support.

Move the builtin handlers into runtime/lua/vim/diagnostic/handlers/ and
keep runtime/lua/vim/diagnostic.lua as the public facade that lazily
dispatches to the split modules. This preserves the external
vim.diagnostic API while making the implementation easier to navigate
and reason about.

AI-assisted: Codex
2026-04-15 14:44:13 +01:00