Commit Graph

929 Commits

Author SHA1 Message Date
skewb1k
448f15ca39 feat(json): pretty-format (indent) with vim.json.encode() #35424
Problem:
There is no straightforward way to pretty-print objects as JSON.
The existing `vim.inspect` outputs LON.

Solution:
Introduce an `indent` option for `vim.json.encode()` which enables
human-readable output with configurable indentation.

Adapts PR to upstream: openresty/lua-cjson#114
2025-09-07 14:38:27 -07:00
Justin M. Keyes
9c3099f0cf docs: lsp, misc
- Problem: It's not clear for new plugin developers that `:help` uses
  a help-tags file for searching the docs, generated by `:helptags`.
  - Solution: Hint to the |:helptags| docs for regenerating the tags
    file for their freshly written documentation.

Co-authored-by: Yochem van Rosmalen <git@yochem.nl>
2025-09-03 23:03:51 -04:00
luukvbaal
de950f8272 fix(window): avoid referencing cmdline_win after it is closed #35617
Solution:  A window marked for ext_cmdline usage is still referenced
           after it is already closed and freed.
Solution:  Unset cmdline_win when the window is closed.
2025-09-03 16:28:23 -07:00
Justin M. Keyes
d8a8825679 feat(lua): vim.wait() returns callback results #35588
Problem:
The callback passed to `vim.wait` cannot return results directly, it
must set upvalues or globals.

    local rv1, rv2, rv3
    local ok = vim.wait(200, function()
      rv1, rv2, rv3 = 'a', 42, { ok = { 'yes' } }
      return true
    end)

Solution:
Let the callback return values after the first "status" result.

    local ok, rv1, rv2, rv3 = vim.wait(200, function()
      return true, 'a', 42, { ok = { 'yes' } }
    end)
2025-09-01 13:26:46 -07:00
zeertzjq
6a330f893b fix(lua): report error in Lua Funcref callback properly (#35555) 2025-08-31 06:44:23 +08:00
Justin M. Keyes
bccec33f5a docs: misc #35459 2025-08-24 23:43:48 +00:00
TheBlob42
701258921e feat(snippet): highlight active tabstop (#35378) 2025-08-19 06:21:32 -07:00
Siddhant Agarwal
1d40f67776 feat(ssh): SSH configuration parser #35027 2025-08-17 20:40:28 -07:00
Sean Dewar
2211953266 fix(api): on_detach consistently before buf_freeall autocmds
Problem: on_detach may be called after buf_freeall and other important things,
plus its textlock restrictions are insufficient. This can cause issues such as
leaks, internal errors and crashes.

Solution: disable buffer updates in buf_freeall, before autocommands (like the
order after #35355 and when do_ecmd reloads a buffer). Don't do so in
free_buffer_stuff; it's not safe to run user code there, and buf_freeall already
runs before then; just free them to avoid leaks if buf_freeall autocommands
registered more for some reason.

Fixes #28084
Fixes #33967
Fixes #35116
2025-08-17 22:32:53 +01:00
Justin M. Keyes
d8ed43c6a7 Merge #35109 vim.pos, vim.range 2025-08-17 16:37:56 -04:00
Jaehwang Jung
285c04e2d0 fix(api,lsp): call on_detach before wiping out the buffer #35355
Problem:
Buffer-updates on_detach callback is invoked before buf_freeall(), which
deletes autocmds of the buffer (via apply_autocmds(EVENT_BUFWIPEOUT,
...)). Due to this, buffer-local autocmds executed in on_detach (e.g.,
LspDetach) are not actually invoked.

Solution:
Call buf_updates_unload() before buf_freeall().
2025-08-17 11:37:24 -07:00
Yi Ming
9f5b309d82 feat(lua): conversion between vim and lsp position/range 2025-08-17 12:13:24 +08:00
Yi Ming
98f8224c19 feat(lua): vim.pos/vim.range 2025-08-17 11:54:53 +08:00
TheBlob42
6f904cfef1 fix(snippet): adjacent tabstops without placeholders (#35167)
* fix(snippet): adjacent tabstops without placeholders

* test(snippet): add tests for directly adjacent tabstops
2025-08-13 14:51:43 -04:00
TheBlob42
ecded994c1 fix(snippet): early return for final tabstop #35115
The cursor movement autocommand can not detect when the final tabstop $0
is directly adjacent to another tabstop, which prevents ending the
snippet session. The fix is an early return when jumping.
2025-08-03 19:52:09 +00:00
Yi Ming
7ed8cbd095 feat(lua): vim.list.bisect() #35108 2025-08-03 07:45:49 -07:00
Anton Kastritskii
b79ff967ac feat(statusline): vim.diagnostic.status() #33723
Problem:
Not easy to get a status string for diagnostics.

Solution:
- Add vim.diagnostic.status().
- Add it to the default 'statusline'.
2025-07-29 18:53:57 -07:00
glepnir
15d57ab0ba fix(api): single-line visual block insert triggers extra on_lines #35098
Problem: Visual block insert on a single line incorrectly triggers two
on_lines callbacks - one for the correct line (0-indexed) and another
for a non-existent additional line.

Solution: Only call changed_lines() in block_insert() when additional
lines beyond the first were actually modified (start.lnum < end.lnum).
2025-07-29 06:24:44 -07:00
Justin M. Keyes
dc3a30cfbb fix(messages): 'exrc' / secure messages 2025-07-28 22:00:25 -04:00
nyngwang
dc67ba948e feat(exrc): user must view and explicitly run ":trust" #35069
Problem:
It's relatively easy to mispress key `a` to (a)llow arbitrary execution
of 'exrc' files. #35050

Solution:
- For exrc files (not directories), remove "allow" menu item.
  Require the user to "view" and then explicitly `:trust` the file.
2025-07-28 13:11:58 -07:00
Lewis Russell
cf9b36f3d9 feat(lua): add vim.list.unique()
Problem:
No way to deduplicate values in a list in-place

Solution:
Add `vim.list.unique()`
2025-07-28 09:34:06 +01:00
Sergei Slipchenko
7a051a4c38 fix(diagnostics): avoid jumping to diagnostics in deleted ranges #35088
Problem:
diagnostic extmark used for positioning continues to exist after
deleting a range containing it, so it's possible to jump to a
next/previous diagnositc, which isn't visible in any way, including not
being shown via `open_float`.

Solution:
enable `invalidate` flag when setting an extmark to be able to filter
out diagnostics based on `invalid` flag when looking for next/previous
diagnostic to jump to.
2025-07-28 05:24:10 +00:00
TheBlob42
628d569a59 fix(snippet): jumping backwards to choice node (#35062)
Avoid duplicate text when jumping back to a choice node. Set cursor to
end of tabstop range and prioritize current choice in completion items.
2025-07-27 16:10:00 -04:00
TheBlob42
dff78f580d fix(snippet): setting end_right_gravity (#35061)
When right_gravity is set to true for deactivating tabstop expansion we
have to set end_right_gravity to false to avoid expanding the tabstop
region on the right side. Vice versa for activating tabstop expansion
again.
2025-07-27 12:19:01 -07:00
Sergei Slipchenko
0a113013fb fix(diagnostics): position diagnostics using extmarks #34014
Problem:
Diagnostic positions are not being updated after text changes, which
means `vim.diagnostic.open_float` and `vim.diagnostic.jump` will work
with outdated positions when text is changed until diagnostics are
updated again (if ever).

Solution:
Create extmarks in `vim.diagnostic.set` and use their positions for
`vim.diagnostic.open_float` and `next_diagnostic` (used by
`vim.diagnostic.jump`, `vim.diagnostic.get_next` and
`vim.diagnostic.get_prev`).
2025-07-25 07:56:50 -07:00
glepnir
4fe51dfdae fix(iter): ArrayIter:last returns nil when filtered to empty #34697
Problem: After filtering out all elements, ArrayIter:last still returns a stale element.
Solution: Add check for self._head == self._tail and return nil early.

Fix #34696
2025-07-22 17:40:24 -07:00
Tom Ampuero
7cd5356a6f feat(net): vim.net.request(), :edit [url] #34140
Problem:
Nvim depends on netrw to download/request URL contents.

Solution:
- Add `vim.net.request()` as a thin curl wrapper:
  - Basic GET with --silent, --show-error, --fail, --location, --retry
  - Optional `opts.outpath` to save to a file
  - Operates asynchronously. Pass an `on_response` handler to get the result.
- Add integ tests (requires NVIM_TEST_INTEG to be set) to test success
  and 404 failure.
- Health check for missing `curl`.
- Handle `:edit https://…` using `vim.net.request()`.

API Usage:
1. Asynchronous request:

    vim.net.request('https://httpbingo.org/get', { retry = 2 }, function(err, response)
      if err then
        print('Fetch failed:', err)
      else
        print('Got body of length:', #response.body)
      end
    end)

2. Download to file:

    vim.net.request('https://httpbingo.org/get', { outpath = 'out_async.txt' }, function(err)
      if err then print('Error:', err) end
    end)

3. Remote :edit integration (in runtime/plugin/net.lua) fetches into buffer:

    :edit https://httpbingo.org/get
2025-07-13 13:43:11 -07:00
Justin M. Keyes
89b946aa87 fix(lua): vim.diff is nil in uv.new_work() thread #34909
Problem:
The "gitsigns" plugin runs `vim.diff` in a thread (`uv.new_work`), but
`vim.diff` is nil in that context:

    Lua callback:
    …/gitsigns.nvim/lua/gitsigns/diff_int.lua:30: bad argument #1 to 'decode' (string expected, got nil)
    stack traceback:
      [C]: in function 'decode'
      …/gitsigns.nvim/lua/gitsigns/diff_int.lua:30: in function <…/gitsigns.nvim/lua/gitsigns/diff_int.lua:29>
    Luv thread:
    …/gitsigns.nvim/lua/gitsigns/diff_int.lua:63: attempt to call field 'diff' (a nil value)

Solution:
Revert the `stdlib.c` change (set `vim.diff` instead of `vim._diff`).
2025-07-12 20:54:22 -07:00
Justin M. Keyes
815916b450 test: zig build thread_spec.lua failure after vim.text.diff rename
Problem:
Since renaming `vim.diff` to `vim.text.diff`, `thread_spec.lua` fails in
the zig build. Is `vim.text.diff` not available in the thread context?
Why does it only fail in the zig build?

    FAILED   ./test/functional/lua/thread_spec.lua @ 217: thread vim.* diff
    ./test/functional/lua/thread_spec.lua:229: Expected objects to be the same.
    Passed in:
    (nil)
    Expected:
    (table: 0x7f221d392218) {
      [1] = 'notification'
    E5113: Lua chunk:
      [2] = 'result'
      [3] = {
        [1] = '@@ -1 +1 @@
    -Hello
    +Helli
    ' } }

    stack traceback:
            ./test/functional/lua/thread_spec.lua:229: in function <./test/functional/lua/thread_spec.lua:217>

    FAILED   ./test/functional/lua/thread_spec.lua @ 372: threadpool vim.* work
    ./test/functional/lua/thread_spec.lua:384: Expected objects to be the same.
    Passed in:
    (table: 0x7f2225be2c30) {
      [1] = 'notification'
      [2] = 'result'
     *[3] = {
       *[1] = vim.NIL } }
    Expected:
    (table: 0x7f2225be25c0) {
      [1] = 'notification'
      [2] = 'result'
     *[3] = {
       *[1] = '@@ -1 +1 @@
    -Hello
    +Helli
    ' } }

    stack traceback:
            ./test/functional/lua/thread_spec.lua:384: in function <./test/functional/lua/thread_spec.lua:372>

Solution:
Use `vim._diff` in the test, until a root cause is found.
2025-07-12 18:58:17 -04:00
Justin M. Keyes
f3a54e7ccf refactor(lua): rename vim.diff => vim.text.diff #34864
Problem:
`vim.diff()` was introduced before we had the `vim.text` module, where
it obviously belongs.

Solution:
Move it.
2025-07-12 22:36:07 +00:00
Justin M. Keyes
4f3aa7bafb Merge #34558 docs 2025-07-10 22:36:16 -04:00
jade
7a69fefdb9 fix(vim.json): loss of precision on integers >14 digits #34876
Problem: multiple DAP servers keep assuming they can have internal IDs
         up to 2**52, which get corrupted by the Neovim JSON encoder.
Solution: change (1) constant and add a test so nobody breaks it while
          updating the library.

Fixes: https://github.com/neovim/neovim/issues/24532
Fixes: https://github.com/mfussenegger/nvim-dap/issues/1534
Fixes: https://github.com/facebook/buck2/issues/1032
2025-07-10 19:07:56 -07:00
Justin M. Keyes
58df501913 docs: api, pack, events, develop 2025-07-10 21:50:46 -04:00
Riley Bruins
68e316e3f9 feat(diagnostic): jump to related info location from open_float #34837
This commit allows users to jump to the location specified in a
diagnostic's `relatedInformation`, using `gf` from within the
`open_float` window. The cursor need only be on line that displays the
related info.
2025-07-10 11:24:17 -07:00
luukvbaal
3a3484be29 test(messages/cmdline_spec): convert highlight IDs to name and format (#34845)
Problem:  Hardcoded highlight IDs for ext_messages/cmdline output need
          to be adjusted everytime a builtin highlight group is added.
Solution: Store a global map of default highlights through nvim_get_hl()
          and fetch missing (custom) highlight groups through synIDattr().
          Use more compact formatting for screen:expect().
2025-07-09 09:33:19 +00:00
luukvbaal
f68a5c40f0 feat(messages): add "prev_cmd" argument to msg_history_show (#34779)
Problem:  Unable to tell whether msg_history_show event is emitted for a
          :messages or g< command.
Solution: Add "prev_cmd" argument that is set to true for g<.
2025-07-08 11:19:02 +02:00
Mart-Mihkel Aun
f01419f3d5 feat(runtime): accept predicates in take and skip (#34657)
Make `vim.iter():take()` and `vim.iter():skip()`
optionally accept predicates to enable takewhile
and skipwhile patterns used in functional
programming.
2025-07-03 08:12:24 -05:00
Lewis Russell
ac75de0d2a test: add more structure to vim.bo/wo tests 2025-07-03 11:05:08 +01:00
Lewis Russell
a5e582dab6 test: move lua option/variable tests to a separate file 2025-07-03 11:05:08 +01:00
Lewis Russell
0a6a73fd25 refactor: option tests 2025-07-03 11:05:08 +01:00
Lewis Russell
4eebc46930 fix(vim.system): env=nil passes env=nil to uv.spawn
731e616a79 made it so passing `{env = nil, clear_env = true }` would
pass `{env = {}}` to `vim.uv.spawn`.

However this is not what `clear_env` is (arguably) supposed to do.
If `env=nil` then that implies the uses wants `vim.uv.spawn()` to use
the default environment. Adding `clear_env = true` simply prevents
`NVIM` (the base environment) from being added.

Fixes #34730
2025-07-02 17:01:29 +01:00
Evgeni Chasnovski
773075b2bc feat(vim.version): add vim.version.intersect()
Problem: No way to compute intersection of two version ranges, which is
useful when computing version range that fits inside several reference
ranges.

Solution: Add `vim.version.intersect()`.
2025-06-30 20:59:44 +03:00
Evgeni Chasnovski
649ff924d9 fix(vim.version): improve construction of '<=a.b.c' and '>a.b.c' ranges
Problem: `vim.version.range('<=a.b.c')` is not precise when it comes to
its right hand side. This is due to version ranges using exclusive right
hand side. While `vim.version.range('>a.b.c')` is not precise when it
comes to its left hand side because left hand sides are inclusive.

Solution: For '>=a.b.c' increase `to` from 'a.b.c' to the smallest
reasonable version that is bigger than 'a.b.c'. For '<a.b.c' do the same
for `from`.
More proper solution is an explicit control over inclusivity of version
range sides, but it has more side effects and requires design decisions.
2025-06-30 20:59:12 +03:00
Evgeni Chasnovski
aeb8bca12d feat(vim.version): make tostring() return human-readable version range
Problem: `tostring()` applied to version range doesn't return
human-readable text with information about the range.

Solution: Add `__tostring()` method.
2025-06-30 16:08:56 +03:00
luukvbaal
2b4c1127ad feat(ui): emit "msg_clear" event after clearing the screen (#34035)
Problem:  ext_messages cannot tell when the screen was cleared, which is
          needed to clear visible messages. An empty message is also
          never emitted, but clears messages from the message grid.
Solution: Repurpose the "msg_clear" event to be emitted when the screen
          was cleared. Emit an empty message with the `empty` kind to
          hint to a UI to clear the cmdline area.
2025-06-26 22:27:21 +00:00
Birdee
731e616a79 fix(vim.system): clear_env=true gives an invalid env to uv.spawn #33955
Problem:
In setup_env, some needed logic is bypassed when clear_env=true.

Solution:
Drop the early return in setup_env().

Co-authored-by: BirdeeHub <birdee@localhost>
2025-06-25 15:15:19 -07:00
luukvbaal
4369d7d9a7 fix(ui)!: decouple ext_messages from message grid #27963
Problem:  ext_messages is implemented to mimic the message grid
          implementation w.r.t. scrolling messages, clearing scrolled
          messages, hit-enter-prompts and replacing a previous message.
          Meanwhile, an ext_messages UI may not be implemented in a way
          where these events are wanted. Moreover, correctness of these
          events even assuming a "scrolled message" implementation
          depends on fragile "currently visible messages" global state,
          which already isn't correct after a previous message was
          supposed to have been overwritten (because that should not only
          happen when `msg_scroll == false`).

Solution: - No longer attempt to keep track of the currently visible
            messages: remove the `msg_ext(_history)_visible` variables.
            UIs may remove messages pre-emptively (timer based), or never
            show messages that don't fit a certain area in the first place.
          - No longer emit the `msg(_history)_clear` events to clear
            "scrolled" messages. This opens up the `msg_clear` event to
            be emitted when messages should actually be cleared (e.g.
            when the screen is cleared). May also be useful to emit before
            the first message in an event loop cycle as a hint to the UI
            that it is a new batch of messages (vim._extui currently
            schedules an event to determine that).
          - Set `replace_last` explicitly at the few callsites that want
            this to be set to true to replace an incomplete status message.
          - Don't store a "keep" message to be re-emitted.
2025-06-25 08:25:40 -07:00
glepnir
69c379dc44 fix(quickfix): use correct lnume when appending (#34611)
Problem: ml_get error when updating quickfix buffer with nvim_buf_attach
Solution: use correct lnume parameter in changed_lines for append mode

Fix #34610
2025-06-23 23:48:55 +00:00
glepnir
006361fc6b fix(api): buffer updates in quickfix buffer #31105
Problem: Buffer events (specifically on_bytes callbacks) weren't triggered when the
quickfix list was modified, preventing buffer change notifications.

Solution: Add code to send both bytes and lines change notifications after
quickfix buffer updates to properly trigger all attached callbacks.
2025-06-17 06:31:14 -07:00
luukvbaal
29f2cb89f0 fix(messages): add append parameter to history entries (#34467)
Problem:  The "append" parameter added in abb40ece is missing from
          history entries, resulting in different message formatting
          for "g<".
Solution: Add "append" field to message history entries.

Co-authored-by: phanium <91544758+phanen@users.noreply.github.com>
2025-06-15 23:36:41 +02:00