Commit Graph

11430 Commits

Author SHA1 Message Date
Volodymyr Chernetskyi
a31f9affde fix(msgpack): strptime() fails east of UTC+12 #41743
Problem:
msgpack#strptime() finds a timestamp by bisecting strftime() output, and
brackets the search with the extreme UTC offsets. The lower bound
subtracts 12 hours, but -12:00 is the westernmost offset, which produces
the *largest* timestamp for a given local time. The easternmost offset
is +14:00, so in any zone east of UTC+12 the search can start above the
target and the function throws:

    internal-start-string:Internal error: start > string

With TZ=GMT-14, four of the five timestamps in msgpack_spec.lua fail,
as do three tests in shada_spec.lua, which reaches the same function
through shada#strings_to_sd().

Solution:
Subtract 14 hours instead. The upper bound is already generous enough at
+14, and widening a bisection bracket downwards cannot change the result
in zones that worked before.

The test disables the python3 provider, because msgpack#strptime() only
uses the Vimscript implementation changed here when no provider answers,
and otherwise hands the work to datetime.strptime().

AI-assisted
2026-09-07 08:24:16 -04:00
Justin M. Keyes
1c8d5581d9 Merge #41118 from altermo/optwin-tab-scope
optwin.lua improvements
2026-09-07 08:20:24 -04:00
zeertzjq
4d1793a106 Merge pull request #41717 from janlazo/vim-0ed11ba
vim-patch:9.1.1429,{0ed11ba,57d6d00}
2026-09-07 20:08:06 +08:00
Lewis Russell
80c2181ce9 refactor(pack): use vim.async
Problem: vim.pack uses a private async implementation even though
vim.async is now available.

Solution: Remove the private implementation and run plugin operations in
structured task scopes. Bound parallel work with semaphores and use
protected awaits so cancellation still propagates.

AI-assisted
2026-09-07 10:53:56 +01:00
altermo
ec957ffd8c refactor(optwin): use current window as fallback 2026-09-07 11:05:19 +02:00
altermo
9975b73dfb fix(optwin): handle tabpage local options 2026-09-07 11:05:19 +02:00
Jan Edmund Lazo
b222398553 vim-patch:57d6d00: runtime(doc): Add documentation style
closes: vim/vim#17627

57d6d00433

Co-authored-by: Damien Lejay <damien@lejay.be>
Co-authored-by: Phạm Bình An <111893501+brianhuster@users.noreply.github.com>
2026-09-06 23:57:11 -04:00
Jan Edmund Lazo
594381d758 vim-patch:0ed11ba: runtime(doc): Tweak documentation style a bit
0ed11ba223

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
2026-09-06 23:56:32 -04:00
zeertzjq
31626aed41 vim-patch:a96c3bc: runtime(robot): Include ftplugin and set comment options
Set 'comments' and 'commentstring' for Robot Framework files.

closes: vim/vim#21220

a96c3bc1f7

Co-authored-by: Dawid Dziurla <dawidd0811@gmail.com>
2026-09-07 08:05:11 +08:00
zeertzjq
87ef6ad92b vim-patch:d53f436: runtime(gdb): Update syntax for GDB 17
closes: vim/vim#21219

d53f436eaa

Co-authored-by: Doug Kearns <dougkearns@gmail.com>
2026-09-07 08:05:11 +08:00
zeertzjq
1e92632c1f vim-patch:22b72dc: runtime(spup): fix E92 in syntax script
Problem:  Spup syntax fails for an out-of-range comment mode.
Solution: Add the missing let to the fallback assignment (Qiming zhao).

Setting oneline_comments above 3 raises E492 while loading the syntax
script. Use a valid legacy Vim script assignment to restore the default
value of 2.

Validated with oneline_comments set to 1, 2, 3, 4 and 99, and with the
variable unset. The original script fails with E492 for a value of 4.
The corrected script loads and applies the expected comment mode.

closes: vim/vim#21227

Supported by AI.

22b72dca7e

Co-authored-by: Qiming zhao <chemzqm@gmail.com>
2026-09-07 08:05:11 +08:00
zeertzjq
797171f45f vim-patch:ca2e65a: runtime(doc): Update quickfix help text with missing information
closes: vim/vim#21229

Supported by AI.

ca2e65a842

Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
2026-09-07 08:05:09 +08:00
Volodymyr Chernetskyi
5f1f5a8c2a fix(treesitter): conceal_lines is not applied to injected trees
Problem:
TSHighlighter._on_conceal_line() parses with the range { row, row }. A
Range2 has an exclusive end, so that is the empty range, and no injected
region ever intercepts it.

The root tree is parsed regardless, because its region is empty, so only
injections are affected: conceal_lines metadata coming from an injected
language's highlights query is dropped. on_range_impl() then records the
row in _conceal_checked, so the miss persists until the buffer changes.

For a markdown code block nested in a markdown code block, the inner
fence delimiters stay visible and nvim_win_text_height() reports 5 rows
where 3 are displayed.

Solution:
Pass the one-row range, as the on_range_impl() call below already does.

AI-assisted
2026-09-06 19:36:32 +02:00
Volodymyr Chernetskyi
d951908e12 fix(ui2): mouse movement dismisses expanded messages #41732
Problem:
cmd_on_key() tests the key it was handed against the literal string
'<MouseMove>', but at that point "typed" still holds raw key bytes. Thus
the comparison never holds and the branch its own comment describes
is dead. Moving the mouse over an expanded cmdline collapses it.

Solution:
Translate the key once, up front, so every comparison in the function
sees the same form.

AI-assisted
2026-09-06 12:37:28 -04:00
Volodymyr Chernetskyi
2f5df7add7 fix(treesitter): #has-parent? errors on a node with no parent
Problem:
The #has-parent? predicate indexes the result of node:parent() without
checking it, so a capture that matches a tree's root node raises

    query.lua:600: attempt to index a nil value

instead of simply not matching. In a highlights query that breaks
highlighting for the whole buffer. The sibling #has-ancestor? predicate
handles the same situation.

Solution:
Treat a missing parent as "does not match".

AI-assisted
2026-09-06 18:27:02 +02:00
Justin M. Keyes
bd43394d4e fix(multicursor): skip insert live-mirror on conflicting edits #41730
Problem:
Cursors placed same-line before the primary, or producing multiline
edits on lines above the primary, shift the text in a way that breaks
the insert-mode live-mirroring.

Solution:
Skip live-mirroring under those conditions.

TODO (future): we could support live-mirroring if ins-completion's
internal bookkeeping tracked its regions more precisely.
2026-09-06 10:04:47 -04:00
Volodymyr Chernetskyi
06bff27929 feat(ui2): highlight the [+x] spill indicator with MoreMsg #41679
Problem:
The "spill" indicator that ui2 appends when messages overflow the
available height is drawn with whatever highlight the message tail
happens to have, so it is indistinguishable from the message text.

Solution:
Give the [+x] chunks an explicit `MoreMsg` highlight, and only fall back
to the message tail highlight for chunks that don't carry one of their
own.

AI-assisted
2026-09-04 14:28:22 -04:00
Volodymyr Chernetskyi
b21f2094ba feat(ui2): scroll the dialog window with the mouse wheel #41682
Problem:
The ui2 dialog implements paging for the arrow keys, Home/End and the
page keys, but not for the mouse wheel. When `mouse` contains `"c"`,
turning the wheel does nothing at all.

Solution:
Handle <ScrollWheelUp>/<ScrollWheelDown>, scrolling by the `mousescroll`
`"ver"` amount.

AI-assisted
2026-09-04 11:33:53 -04:00
Justin M. Keyes
2124f968a6 feat(multicursor): "]C"/"[C" leave a cursor at old position #41681
Problem:
`]C` jumps the primary onto another cursor, which dedupes at the next
edit. Every `]C` consumes a cursor.

Solution:
`]C` adds a cursor at the current position before jumping. This
effectively "rotates" the primary cursor.
2026-09-04 06:28:42 -04:00
Lewis Russell
ce8a897f98 feat(lua): add vim.async
Problem: Nvim has many Lua APIs that start callback-driven work: timers,
jobs, libuv handles, and other event-loop tasks. Callers that need to
sequence or cancel that work have to build their own coroutine wrappers,
task bookkeeping, and cleanup rules. This makes async control flow hard
to share, test, and document.

Solution: Add `vim.async`, a structured-concurrency module vendored from
async.nvim. It provides task handles, await/pawait helpers,
sleep/timeout helpers, completion-order iteration, and semaphores on top
of Nvim's event loop.

The API follows the same broad model as Trio: async work has an owner,
tasks are awaited explicitly, and cancellation is cooperative. Include
generated vimdoc with an introductory overview and examples, a news
entry, and functional tests for the new module.

AI-assisted
2026-09-03 19:17:25 +01:00
Sébastien Hoffmann
3808c00fc8 fix(statusline): default 'statusline' improvements #41597
Problem: there should be exactly one cell of padding between sections,
and exactly one cell of minimum padding between the left and the right.
- Spaces between sections waste space when a section is empty.
  According to a comment in #33036, this was the reason to avoid `%k`
  and implement the keymap section with a vim expression, but other
  sections still have this problem.
- The diagnostics section wastes space because it is not entirely empty
  when there are diagnostics in another buffer.
- The terminal exit code section can touch the right side, e.g. the
  ruler, even though it belongs to the left side.
Solution:
- Use auto-hiding item groups (`%(` without width fields) to get rid of
  unneeded spaces when a section shows no information.
  This simplifies the 'showcmd' and 'keymap' sections in particular.
- As a slight simplification, `term_exitcode` is moved into the flags
  section since it is formatted with square brackets like a flag.
- Count the diagnostics for the current buffer specifically.
- Ensure at least one cell of padding between the left and the right
  side by adding a space next to the separator `%=`.

Problem: some sections are implemented with `%{%`, even though
reevaluation of the expression result is not needed.
This leads to otherwise needless %-escaping in `progress_status`.
Solution: use `%{` instead.

Problem: `%{` and `%{%` (without items) replace spaces with fillchars.
This looks out-of-place inside the terminal exit code section, and in
contrast to all other sections, the 'busy' section is surrounded by
fillchars, which looks inconsistent, and with some terminal-font
combinations, ◐ overlaps the fillchar, e.g. Alacritty & JetBrains Mono.
Solution: use non-breaking spaces U+202F to avoid fillchar substitution.

Problem: sections that appear/disappear frequently can make otherwise
more stable sections jump around a lot.
Solution: sort the sections on the right roughly by volatility:
'showcmd' in first place, 'keymap' next to the ruler.
2026-09-03 12:44:30 -04:00
Volodymyr Chernetskyi
73923b0dd8 fix(ssh): compare table length in the SSH config #41637
Problem:
`parse_ssh_config()` compares tables against a freshly allocated empty
table.
- In `parse_multiple_values()`, the guard which avoids flushing an empty
  accumulator never applies. Runs of separators and trailing whitespace
  push empty strings into the results, and `is_valid()` does not filter
  them. `Host  alpha   beta ` parses as `{ 'alpha', '', 'beta' }`.
- In `parse_value()`, the condition reduces to `chr == '"' and quoted`.
  `quoted` starts false and only that branch sets it, so it can never
  become true: quotes are never recognised and are inserted literally,
  and the unterminated-quote check is unreachable.

Solution:
Compare `#val` instead. Add a test for repeated and trailing separators.

AI-assisted
2026-09-03 06:40:58 -04:00
Volodymyr Chernetskyi
9222ed3a4a fix(filetype): report documented parameter name #41649
Problem:
Invalid `args` parameter for `vim.filetype.match()` reports wrong
parameter name `"arg"`.

Solution:
Report correct parameter name `"args"` instead.
2026-09-03 04:10:05 -04:00
Volodymyr Chernetskyi
9a8966879a fix(iter): keep take() predicate within bounds #41635
Problem:
`IterArray:take()` iterates up to `self._tail`, but `_tail` is
exclusive. When no element fails the predicate, the loop reads one index
past the last element and calls the predicate with `nil`.

Solution:
Stop at `self._tail - inc`, which is the last in-range index for both
iteration directions. Add tests using a predicate which dereferences its
argument and matches every element, forward and reversed.

AI-assisted
2026-09-03 03:23:45 -04:00
zeertzjq
7645d7e232 vim-patch:9.2.1035: filetype: Github citation files are not recognized (#41643)
Problem:  filetype: Github citation files are not recognized
Solution: Detect *.cff files as yaml filetype (Wu Zhenyu).

Reference:
https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files

closes: vim/vim#21163

05de894401

Co-authored-by: Wu, Zhenyu <wuzhenyu@ustc.edu>
2026-09-03 11:07:12 +08:00
Volodymyr Chernetskyi
0ecca23ee2 fix(treesitter): accept a string title in inspect_tree() #41639
Problem:
`inspect_tree()` documents `title` as
`string|fun(bufnr:integer):string|nil`, but the implementation handles
only `nil` and function values. A string title leaves `title` unset and
fails the assertion below.

Solution:
Use the string as the title.
2026-09-02 17:01:54 -04:00
Volodymyr Chernetskyi
a58cee4512 fix(lsp): respect range in linewise visual mode #41636
Problem:
An explicitly passed `range` to `vim.lsp.buf.format()` in linewise
visual mode is silently replaced by the selection.

Solution:
Parenthesise the mode check.
2026-09-02 17:01:32 -04:00
Volodymyr Chernetskyi
10fa98bb6e fix(pack): read document links from the request buffer #41638
Problem:
The `textDocument/documentLink` handler resolves the confirmation buffer
from the request URI and checks it for `nil`, then reads lines from
buffer `0`. When the confirmation buffer is not current, links are
computed from unrelated text and returned against the confirmation
buffer's line numbers, producing missing or misplaced links.

Solution:
Read lines from the resolved `bufnr`.

AI-assisted
2026-09-02 16:58:26 -04:00
Volodymyr Chernetskyi
45b645718c fix(keymap): report the documented parameter name #41633
Problem:
Invalid `modes` parameter for `vim.keymap.del()` reports wrong parameter
name `"mode"`.

Solution:
Report correct parameter name `"mode"` instead.
2026-09-02 16:27:20 -04:00
Volodymyr Chernetskyi
40258d5d05 fix(health): correct reporting messages #41632
Problems:
- Slow shell check measures time in nanoseconds, but reports seconds.
- `kdch1` check incorrectly tests `kbs_entry` instead.
- curl version is passed as an advice, so it is never reported.

Solutions:
- Scale the elapsed time to seconds before reporting.
- Test `kdch1_entry` for `kdch1` check.
- Format curl warning with `string.format()`.

AI-assisted
2026-09-02 16:04:32 -04:00
Justin M. Keyes
80e9708afa fix(multicursor): atom may cascade in another buffer #41624
Problem:
An atom queued in buffer A cascades on B's cursors if the mapping ends
in B ("nnoremap X x:bnext<CR>").

Solution:
Check the atom's origin buffer (`CmdAtom.origin.buf`).

Note: This does not preclude mappings etc from doing work in temporary
throwaway buffers, as long as they return to the origin buffer.
2026-09-02 10:38:27 -04:00
Volodymyr Chernetskyi
8321941ff2 fix(vim.version): fix metatable for intersections #41615
Problem:
`vim.version.intersect()` returns tables with `VersionRange` (method
table) as their metatable. Although the calculated bounds are correct,
the results do not expose `VersionRange` methods.

Solution:
Construct intersection tables with `range_mt`, matching
`vim.version.range()`. Add assertions covering method access and
repeated intersection.
2026-09-02 10:10:18 -04:00
Volodymyr Chernetskyi
a41d008666 fix(trust): hash fileformat=mac buffers correctly #41616
Problem:
`compute_hash()` reconstructs buffer contents with `fileformat` set to
`mac` using CRLF (`dos`) line endings. The resulting hash does not match
the file's bytes.

Solution:
Define the line ending for every supported file format. Use that mapping
when reconstructing buffer contents for hashing.
2026-09-02 10:09:20 -04:00
Volodymyr Chernetskyi
5bc7dbb13e fix(loader): remove all cached loaders on disable #41613
Problem:
When disabling, the loader list is traversed forwards while entries are
removed. As a result, some entries are skipped and remain active. Thus,
disabling `vim.loader` restores `_G.loadfile`, but does not fully
restore the original package loader chain.

Solution:
Traverse `package.loaders` in reverse when removing cached loaders.
Capture the original `package.loaders` list in the test, and assert that
the list is restored properly.
2026-09-02 10:08:37 -04:00
Justin M. Keyes
350fa5ad7c fix(multicursor): act on fold contents, not the fold itself #41622
Problem:
If an edit cascades to cursor(s) that happen to be within a closed fold,
the edit acts on the fold itself (`:h fold-behavior`). E.g. "dd" deletes
the entire fold, not the cursor's line within the fold.

Solution:
Check `mc_replaying()` in `hasAnyFolding()`, so folds are ignored during
a multicursor cascade. This means multicursor always replays relative to
text *within* the fold.
2026-09-02 09:42:40 -04:00
Volodymyr Chernetskyi
3ea7bc3f60 fix(health): restore pynvim version lookup #41619
Problem:
Fallback pynvim version lookup is broken since Vimscript-to-Lua rewrite.
- `vim.fs.basename()` returns the module filename instead of the
  directory needed to discover adjacent metadata. This produces an
  empty metadata list, hiding the remaining issues.
- `table.sort()` requires a Boolean comparator, while
  `vim.version.cmp()` returns a number.
- `table.sort()` sorts in place and returns no value, so assigning its
  result discards the metadata list.

Solution:
- Use `vim.fs.dirname()` to discover adjacent package metadata.
- Use `vim.version.gt()` as the descending Boolean comparator.
- Sort the metadata list in place.
This restores fallback version detection when `neovim.VERSION` is
unavailable.
2026-09-02 08:12:07 -04:00
Justin M. Keyes
d290ef58b2 Merge #41599 from justinmk/mchammer 2026-09-02 07:46:37 -04:00
Volodymyr Chernetskyi
1c31526a90 fix(vim.hl): convert finish column independently #41618
Problem:
Coordinates-to-position conversion for the finish column in
`vim.hl.range()` checks the start column. This results in an incorrect
finish column when only one of the column coordinates is `vim.v.maxcol`.

Solution:
Check the finish column when converting the finish position. Update the
existing screen test so that a `vim.v.maxcol` finish highlights the
end-of-line marker, matching the existing `-1` behavior.
2026-09-02 07:45:52 -04:00
Justin M. Keyes
7168e0d12f fix(mcursor): drop q= "follow motion" message 2026-09-02 13:09:30 +02:00
zeertzjq
90fc8946e8 vim-patch:fac9e33: runtime(doc): fix example output of cosh (#41609)
closes: vim/vim#21197

fac9e333a8

Co-authored-by: Eisuke Kawashima <e-kwsm@users.noreply.github.com>
2026-09-02 13:52:12 +08:00
zeertzjq
8e34903b6a vim-patch:e9c5e56: runtime(python): improve performance of number and ellipsis matching (#41608)
Problem:  The floating-point `.d` number match and the two ellipsis
          matches are slow: each begins with a look-behind, which cannot
          be reduced to a fixed first character, so the automatic regexp
          engine selects the slower NFA backend for them.
Solution: Force the backtracking engine with \%#=1 on those three
          patterns; it evaluates the look-behind far more efficiently.
          Highlighting is unchanged.

Measured with :syntime over a 40000 line corpus: the three affected
rules drop from ~0.13s to ~0.008s (about -93%), which cuts the total
syntax parse cost by ~10% (1.85s to 1.65s).

closes: vim/vim#21194

e9c5e56081

Co-authored-by: Julien Voisin <julien.voisin@dustri.org>
2026-09-02 13:51:57 +08:00
zeertzjq
749e0a06c2 vim-patch:9.2.1031: 'wildmode' list:full does not show 'wildmenu'
Problem:  With 'wildmode' set to list:full the matches are listed but the
          wildmenu is not shown, although it is "full" that starts
          wildmenu mode (zeertzjq).
Solution: List the matches and show the menu, as the two behaviors in
          the same phase ask for.  The menu is left to the phases that
          ask for it, so that "list" on its own still only lists
          (Hirohito Higashi).

fixes:  vim/vim#21196
closes: vim/vim#21205

fa1ddffcce

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
2026-09-02 09:51:47 +08:00
Justin M. Keyes
9a29622b54 feat(multicursor): MC HAMMER #41587
Other (squashed) commits:

fix(tui): emit ui_send output atomically with the frame

Problem:
tui_ui_send() writes directly to the TTY, bypassing the output buffer.
Sequences sent via nvim_ui_send() (e.g. kitty multiple-cursors, or
visual-dot-repeat) always arrive in a separate TTY write from the frame
they were computed for. This manifests as "tearing", or e.g. in the case
of multicursor the terminal renders text with stale cursor overlays.

Solution:
- tui_ui_send(): while a frame is being assembled (pending invalid
  regions or buffered output), buffer instead of writing directly.
  - Out-of-frame sends (tty queries, clear-on-disable) still write
    immediately.
- mcursor.lua: emit the terminal-cursor update at the end of the redraw
  cycle (`on_end`, when screen positions are final) instead of
  vim.schedule().
2026-09-01 15:17:22 +00:00
Evgeni Chasnovski
9ebf9b1017 fix(ui2): respect options set during startup after enabling ui2 #41591
Problem: options related to ui2 (like `fillchars` with `msgsep`) do not
  take effect if set during startup after enabling ui2.

Solution: explicitly check just after startup if relevant options were
  changed during startup.
2026-09-01 13:23:23 +00:00
wrvsrx
c275b5de5a fix(lsp): separate adjacent nested folding ranges #41428
Problem:
Folding range markers are overwritten while ranges are evaluated. A range ending on a row can hide another range starting there, and multiple nested ranges ending together emit only the innermost ending level.

Solution:
Track starts and the number of ends per row before emitting markers. Prefer starts on shared boundary rows and use the outermost level when nested ranges end together.

AI-assisted
2026-08-31 08:41:19 -04:00
Aryan Pandey
ad42ee1c41 fix(cmdwin): handle UTF-8 characters containing 0x80 #41566
Problem:
Confirming cmdwin with a UTF-8 character containing 0x80 does not complete the
command.

Solution:
Escape K_SPECIAL bytes while feeding the cmdwin input after confirmation.
2026-08-31 06:52:20 -04:00
zeertzjq
8edcb401cf vim-patch:5c9c5a4: runtime(c): syntax depends on the 'iskeyword' option
Problem:  C keywords are matched using the characters from 'iskeyword',
          so changing that option highlights part of an identifier as a
          keyword and leaves keywords containing an underscore
          unhighlighted.
Solution: Set the keyword characters with ":syn iskeyword".

fixes:  vim/vim#21173
closes: vim/vim#21176

5c9c5a43c1

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-Authored-By: Maxim Kim <habamax@gmail.com>
2026-08-31 10:46:52 +08:00
zeertzjq
a61bd270d6 vim-patch:41cab67: runtime(gitignore): take care when undo_ftplugin is already set
closes: vim/vim#21180

41cab67eef

Co-authored-by: D. Ben Knoble <ben.knoble+github@gmail.com>
2026-08-31 10:46:15 +08:00
zeertzjq
7f7115f752 vim-patch:560dfad: runtime(yaml): syntax highlighting of numbers is slow
Problem:  YAML syntax highlighting is slow; the yamlInteger and yamlFloat
          rules alone account for over half of the parsing time.
Solution: The number, null and timestamp scalar patterns begin with a
          lookbehind, which stops the regexp engine from using a
          first-character search, so the automatic engine selects the
          much slower NFA engine.  Force the backtracking engine with
          \%#=1 on these patterns for a large speedup with identical
          matches (Jordan).

On a 40000-line YAML file the total :syntime drops by about 30%: the
yamlFloat rule goes from 0.61s to 0.17s and yamlInteger from 0.42s to 0.31s.
The engine override is applied only to the lookbehind-anchored number rules;
forcing it on the structural plain-scalar and mapping-key patterns regresses
them badly, so those are left on the automatic engine.

closes: vim/vim#21182

560dfadac8

Co-authored-by: Julien Voisin <julien.voisin@dustri.org>
2026-08-31 10:45:59 +08:00
Justin M. Keyes
b542f3a8f8 fix(cmdatom): edit-repeat mapping #41564
Problem:
The "." example mapping at `:h edit-repeat` doesn't work well with
`nvim_feedkeys(…, 'mt', false)`.

Solution:
Use `vim.b[ev.buf].maxseq` instead of `undotree()`.
2026-08-30 23:38:34 +00:00