Commit Graph

2147 Commits

Author SHA1 Message Date
zeertzjq
7ee1bf91ad vim-patch:9.2.0855: 'showcmd' not redrawn with empty mapping triggered on timeout
Problem:  'showcmd' not redrawn with empty mapping triggered on timeout.
Solution: Don't postpone redraw when inside vgetorpeek(). Also move test
          for tabline 'showcmd' to test_tabline.vim.

fixes:  vim/vim#20839
closes: vim/vim#20840

2e9687647a
2026-07-26 07:07:38 +08:00
Justin M. Keyes
bf3d4210c3 refactor: 'previewpopup' #40945
- drop w_maxwidth/w_maxheight, calculate them on-demand from
  'previewpopup' (this is cheap bc of `opt_keyset`)
2026-07-24 13:49:47 -04:00
Justin M. Keyes
e8195baaef refactor(options): 'previewpopup' validation
Use a schema instead of manual parsing.
2026-07-24 13:05:20 +02:00
glepnir
f95bd73935 feat(float): 'previewpopup' option #26799
Problem:
The preview-window (:pedit, etc.) always uses a split, but it would be
useful as a floatwin (or "popup").

Solution:
Support Vim's 'previewpopup' option.
2026-07-23 17:27:14 -04:00
Ondrej Balaz
8b6bdb79e6 fix(ui): invalid ruler items in other windows #40891
Problem:
When buffer is open in multiple windows and its line count changes, any
'statusline' or 'rulerformat' items depending on it (e.g. %P) will
become invalid in non-current windows because w_redr_status is only set
on first change.

Solution:
Set w_redr_status on all windows with the buffer when the line count
changes.

Signed-off-by: Ondrej Balaz <blami@blami.net>
2026-07-22 12:05:37 -04:00
XiaowenHu
bd73d8c011 fix(inccommand): enforce timeout during matching, not just after a line #40892
Problem: do_sub() only checks the timeout limit after finishing a line.
         A pathological regex will run on a single line input unbounded
         until the compute is completed.

Solution: Pass the timeout limit to `vim_regexec_multi()` so the
          computation on the regex engine is bounded per-line.

Signed-off-by: XiaowenHu96 <me@xiaowenhu.com>
2026-07-22 08:27:54 -04:00
Justin M. Keyes
008ea4dd65 Merge #40873 fix(ui): handle combining chunked float titles 2026-07-21 11:45:44 -04:00
Justin M. Keyes
6d8c8b18d5 test(harness): migrate away from magic globals
Problem:
The magic globals `it`, `describe`, etc., are more trouble than they are
worth.

- Hooking into `after_each` requires `getfenv()` hacks.
- They confuse luals/emmylua, because the top-level `.luarc.json` isn't
  merged with `test/.luarc.json` (apparently a luals limitation?)
- They totally defeat discoverability because the user just has to
  "know" about the various magic symbols.

So they harm DX, which means they serve no purpose at all.

Solution:
- Expose the test API from `testutil`, so tests can call `t.it()`,
  `t.describe()`, etc., in the conventional way.
- Drop `getfenv()` hacks.
- Drop the `setfenv()` injection in `load_chunk`.
- Drop `test/_meta.lua`.
2026-07-21 13:22:39 +02:00
Barrett Ruth
16c145d240 fix(ui2): preserve Visual mode messages #40828
Problem:
The existing `showmode` overlay can immediately cover messages emitted while
Visual mode is active, including the `g CTRL-G` word count.

Solution:
Protect Visual mode messages with the existing message delay and temporarily
hide the previous last-line overlay until it is restored.
2026-07-20 15:44:37 -04:00
Artem Krinitsyn
18d6b2309f fix(ui): handle combining chunked float titles
Problem:
The title is combined with window's attributes only if the title is a
string (which implies the FloatTitle / FloatFooter highlight groups),
but not when the title is text-hl chunks.

Solution:
Combine specified highlight group with window-local Normal highlight as
well.
2026-07-20 19:35:08 +00:00
Artem Krinitsyn
746f5682a7 fix(ui): combine float border with window background #40796
Problem:
Float border highlight groups (FloatBorder, FloatTitle and FloatFooter)
fall back to Normal background highlight if no background color set.

Solution:
Combine border colors with window-local Normal highlight.

Fix #38330
2026-07-19 11:03:46 -04:00
Barrett Ruth
b2bb60d70a fix(ui2): avoid ModeChanged in message window #40788 2026-07-18 07:33:38 -04:00
Sean Dewar
1741da8412 fix(window): yeet grid later when closing float in other tabpage #40758
Problem: #40731 may still crash if close_buffer autocmds reinsert the float's
grid. Plus removing the grid (and posting win_close) is unneeded if
win_close_othertab refuses to close the window later, which is possible.

Solution: do the stuff before freeing the window, like win_close.
2026-07-15 19:09:54 -04:00
Justin M. Keyes
31ad7d4527 Merge #40621 fix(ui2)!: legacy 'ruler' inconsistencies 2026-07-15 08:13:37 -04:00
phanium
6f370f34f2 fix(window): remove float grid from compositor layers before free #40731
Problem: Closing a floating window from a non-current tab frees its grid
without removing it from the compositor's `layers` table, so the next
`ui_comp_put_grid()` walks a dangling pointer (UAF).

Solution: Call `ui_comp_remove_grid()` (and `ui_call_win_close()` for
multigrid UIs) before `win_free_mem()`, matching `win_close()` since
PR #21551.
2026-07-15 07:48:34 -04:00
Barrett Ruth
b2570e6852 fix(showcmd): avoid stale %S contents #40747
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
2026-07-15 06:10:09 -04:00
Sébastien Hoffmann
0ffd74ae85 fix(ui2): fix ruler on repeated messages
Problem: a long message is cropped to keep the ruler visible. But when
the message is repeated, it can be written over the ruler, while the
repetition indicator "(1)" is still placed just before the ruler, which
ends up somewhere inside the message.

Solution: currently, long messages are only cropped when setting the
'last' virttext. Make sure this happens after a repeated long message.
2026-07-11 18:44:42 +02:00
Sébastien Hoffmann
2473cb62b7 fix(ui2): correctly crop message at multibyte/multicell character 2026-07-11 18:31:54 +02:00
Sébastien Hoffmann
fcc391d89a fix(ui2): clear showcmd virt_text together with search count
Problem: when the search count is displayed, the showcmd virt_text is
set to 11 empty spaces to ensure a consistent distance between search
count and ruler, or screen edge in case of noruler. But when the search
count is removed to make place for a message, the empty dummy showcmd
remains and unnecessarily erases part of the message.

Solution: properly remove showcmd together with search count.
2026-07-11 18:31:54 +02:00
Sébastien Hoffmann
60687ccb6a fix(ui2)!: consistent ruler width inside/outside statusline
Problem: before ui2, the ruler in the last line had a one cell safety
margin on the right because writing in the last column of the last line
"scrolls the screen up on some terminals," according to code comments.
When the ruler is included in the statusline, it aligns on the left with
the normal ruler, but goes all the way to the screen edge on the right,
and is therefore one cell longer.

Since ui2 doesn't have that padding cell, they don't align anymore.

Also, in the future, when the C implementation of the ruler will be
replaced with a default expression that will be included in the default
statusline (currently `%-14.(%l,%c%V%) %P`), the width will naturally be
the same in both places, and the unit tests will need adapting anyway.

Solution: when ui2 is active, increase the ruler width by 1.

BREAKING CHANGE: the default ruler in ui2 is now 1 cell wider.

ref https://github.com/neovim/neovim/issues/40247
2026-07-11 18:31:54 +02:00
Barrett Ruth
784765cb73 fix(winbar): update hidden tabpages on global 'winbar' change #40608
Problem:
Changing global 'winbar' only updates window layout state in the current
tabpage. This means existing hidden tabs can keep stale winbar height.

Solution:
Recompute winbar state for all tabpages on global `'winbar'` changes.
2026-07-10 12:49:52 -04:00
Justin M. Keyes
982d2f2531 fix(test): screen:expect({none=…}) with no any/grid
Problem:
`screen:expect({none=…})` with no any/grid crashed (concat on nil)
because actual_rows was only rendered when any or grid was present.

Solution:
Update the condition.
2026-07-10 00:06:59 +02:00
zeertzjq
7c9222f45e fix(mouse): reset click count on next click if mouse moved (#40637)
Also, drop drag event if the mouse hasn't moved, like in gVim.
2026-07-09 08:40:00 +08:00
Justin M. Keyes
b5f500263b fix(lua): bufwrite message overridden by :redrawstatus
Problem:
bufwrite message overridden by :redrawstatus command within Progress callback.

Solution:
- don't use globally-shared IObuf.
- use vim_snprintf to deduplicate `nlua_call_luaeval`, `nlua_call_vlua`.

fix https://github.com/neovim/neovim/issues/40616
2026-07-06 22:17:25 +02:00
Justin M. Keyes
e494c4777b fix(test): screen:expect() render crash masks the real failure #40593
Problem:
When screen:expect() fails, it renders a snapshot for the error
message. If the grid references a highlight id that was never defined
via "hl_attr_define", the renderer crashes:

    screen.lua:1910: attempt to index local 'entry' (a nil value)

This hides the actual failure, and appears "flaky": it only fires on the
failure path, and only when the shared screen is missing an id the grid
still references. A screen created in setup() attaches mid-session, so
highlight ids allocated before it attached (still referenced by stale
grid cells) are never sent to it.

Solution:
- Don't crash while rendering a diagnostic: show undefined highlight ids
  as "UNKNOWN_HL_ID(n)", so the real failure and the desync are legible.
- put_spec: fix `visualbell` typo. If it fails again then we can find
  the actual root cause.

ref https://github.com/neovim/neovim/issues/36250
2026-07-05 12:08:41 -04:00
Justin M. Keyes
3b8c19ea46 fix(bufwrite): cursor flicker on :write
PROBLEM:
Cursor briefly flickers in cmdline when the "written" message is printed
(very noticeable in Neovide with cursor animation).

SOLUTION:
- Mark UI "busy" (cursor hidden) while emitting the message, as done for
  the search message (cb2ca54331).
- Note: ff68fd6b8a moved the message from `filemess()` into
  `buf_write..msg_progress`.
- Fix a bug in `tui.c:flush_buf` which manifested after this change. See
  ANALYSIS below. https://github.com/libuv/libuv/issues/5182

ANALYSIS:
After this change...

    ui_busy_start();
    set_keep_msg(msg_progress(IObuff, msg_id, "success", 0, true, true), 0);
    ui_busy_stop();

...ASAN analyzer fails on tui_spec.lua test "with non-tty (pipe) stdout/stderr":

    2026-07-04T14:09:28.9521023Z = ==32405==ERROR: AddressSanitizer: ABRT on unknown address 0x03e900007e95
    ...
    4 0x7f5506a288fe in abort stdlib/abort.c:79:7
    5 0x559afd7113a2 in uv__epoll_ctl_flush
    build/src/libuv/src/unix/linux.c:1335:7
    6 0x559afd710a81 in uv__io_poll
    build/src/libuv/src/unix/linux.c:1448:9
    7 0x559afd6f67a7 in uv_run
    build/src/libuv/src/unix/core.c:460:5
    8 0x559afd2a72cc in flush_buf
    nvim/tui/tui.c:2642:5
    9 0x559afd2bce9f in tui_flush
    nvim/tui/tui.c:1747:3
    10 0x559afd2f39a0 in ui_client_event_flush
    nvim/auto/ui_events_client.generated.h:64:3
    11 0x559afcb8e014 in parse_msgpack
    nvim/msgpack_rpc/channel.c:255:11
    12 0x559afcb840e7 in receive_msgpack
    nvim/msgpack_rpc/channel.c:217:5
    13 0x559afc53b2af in read_event
    nvim/event/rstream.c:180:23
    14 0x559afc53ad52 in invoke_read_cb
    nvim/event/rstream.c:233:3
    15 0x559afc5382d6 in read_cb
    nvim/event/rstream.c:135:3
    16 0x559afd707b25 in uv__read
    build/src/libuv/src/unix/stream.c:1145:7
    17 0x559afd70744a in uv__stream_io
    build/src/libuv/src/unix/stream.c:1208:5
    18 0x559afd6f727e in uv__io_cb
    build/src/libuv/src/unix/core.c:930:5
    19 0x559afd710d7a in uv__io_poll
    build/src/libuv/src/unix/linux.c:1546:11
    20 0x559afd6f67a7 in uv_run
    build/src/libuv/src/unix/core.c:460:5
    21 0x559afc526e2d in loop_uv_run
    nvim/event/loop.c:59:3
    22 0x559afc526aa4 in loop_poll_events
    nvim/event/loop.c:80:26
    23 0x559afd2fdbb7 in ui_client_run
    nvim/ui_client.c:172:5
    24 0x559afc920d7b in main /home/runner/work/neovim/neovim/src/nvim/main.c:355:5
    25 0x7f5506a2a1c9 in __libc_start_call_main
    main.h:58:16
    26 0x7f5506a2a28a in __libc_start_main csu/../csu/libc-start.c:360:3
    27 0x559afbd6d254 in _start

The abort requires two rare conditions:
1. a `uv_write` whose buffer array *ends* in a zero-length buffer, which only
   happens by "flush while cursor-hidden".
2. an output fd that *epoll cannot watch*. The only CI test with such an fd is
   tui_spec.lua "with non-tty (pipe) stdout/stderr", which runs a TUI with
   `stdout > /dev/null`, then runs `:w testF`, which triggers the "written"
   message.

Our change guarantees trailing-empty flushes (`:w` fires busy + `ui_flush()`
while busy) in the only test that runs a TUI on `/dev/null`.

0. In a normal (non-busy) no-sync flush, post always contains `cursor_normal`.
1. Our change emits:
   ```
   busy_start → msg_progress("…written") → ui_flush → busy_stop
   ```
2. TUI flushes *while busy*, so `should_invisible() = true` and `flush_buf`
   skips the cursor-restore string (`bufs[2]` is zero-length).
3. libuv *cannot complete* a write whose tail is a zero-length buffer: EVERY
   trailing-empty write goes through epoll, even when every byte was already
   written. https://github.com/libuv/libuv/issues/5182
4. In `tui_spec.lua:3298`, the output fd is `/dev/null`, whose kernel
   `file_operations` has no `.poll` method (`drivers/char/mem.c`), so
   `EPOLL_CTL_ADD` fails with `EPERM`.

Trailing empty buffers are semantically pointless, and libuv punishes
them: forced async, one epoll round-trip *per trailing empty*, plus
a 0-byte `write()` syscall.

Helped-by: Shougo Matsushita <Shougo.Matsu@gmail.com>
Helped-by: Fred Sundvik <fsundvik@gmail.com>
2026-07-04 23:17:27 +02:00
Sébastien Hoffmann
444d0b8b6c feat(statusline)!: allow %= in item groups, scope %< to item groups #40369
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
2026-06-27 11:10:05 -04:00
Justin M. Keyes
5675c11910 fix(cmdwin): space in cmdwin-char 'statuscolumn'
To match the old behavior, the cmdwin-char should not be followed by
a space char.
2026-06-26 21:04:10 +02:00
Justin M. Keyes
ac623bd417 fix(cmdwin): duplicate line in history
Problem:
After ctrl-f from the cmdline, the last 2 lines of cmdwin are redundant.

Solution:
In `open_cmdwin`, clear the live cmdline so that unwinding it (via
Ctrl_C) does not add it to history.
2026-06-26 21:04:10 +02:00
Justin M. Keyes
b2bf7bcfb1 feat(cmdwin): implement cmdwin as a normal buf+win
Problem:

cmdwin (the `:q` cmdline buffer) has various limitations which require
special-casing all over the codebase.

Besides complicating the code, it also breaks async plugins if they try
to create buffers/windows after some work is done, if the user happens
to open cmdwin at the wrong the moment:

    Lua callback: …/guh.nvim/lua/guh/util.lua:531:
    E11: Invalid in command-line window; <CR> executes, CTRL-C quits
    stack traceback:
        [C]: in function 'nvim_buf_delete'
        …/guh.nvim/lua/guh/util.lua:531: in function <…/guh.nvim/lua/guh/util.lua:526>

Solution:

Just say no to "inception". Reimplement cmdwin as a normal buffer+window.

All of the cmdwin contortions (in both core, and innocent plugins) exist
literally only to support "inception": recursive
cmdwin-in-cmdline-things, like `<c-r>=`, `/`, search-during-substitute,
`:input()`, etc. So we just won't support that (though I have
a potential plan for that later, which I call "modal parking lot").

The benefit is that plugins, and core, no longer have to care about
cmdwin.

BONUS:
- mouse-drag on vertical separators works (it only worked for
  horizontal/statusline before)
- inccommand-in-cmdwin now works correctly, for free (thus don't need
  #40077).

POTENTIAL FOLLOWUPS
- Drop `CHECK_CMDWIN` ("E11: Invalid in command-line window"), allow chaos.
- Unify `BUFLOCK_OK` / `LOCK_OK` ?

DESIGN:
- Eliminate lots of C globals, `EX_CMDWIN`, etc.
- `text_locked()` no longer reports true for cmdwin.
- cmdwin = a normal window with 'winfixbuf', 'bufhidden=wipe',
  'buftype=nofile'. Invariants come from those options rather than
  special cases throughout the codebase.
- `nv_record` for q:/q//q? calls Lua
  `nlua_call_vimfn("vim._core.cmdwin", …)`. No `K_CMDWIN`
  / cmdline-reader detour.
- `cedit_key` (`c_CTRL-F`) schedules a deferred event that calls
  `vim._core.cmdwin.open(type, content, pos)` and returns `Ctrl_C` so
  the in-flight cmdline cancels. Reader state is not serialized; instead
  the captured `(type, line, col)` is replayed via
  `nvim_feedkeys(type..line.."<CR>", "nt", …)` after user confirms.
- On confirm/cancel: `<CR>` / `<C-C>` calls into Lua which closes the
  window and re-feeds the cmdline.

BREAKING CHANGES:
- Expression-register cmdline (`<C-R>=` from insert-mode) no longer
  supports cmdwin. Same applies to `input()` / `inputlist()` (already
  covered by `text_locked`).
- Usage of cmdwin in macros/mappings will probably break (assuming they
  ever worked).
2026-06-25 18:36:24 +02:00
luukvbaal
28ffb334cf fix(autocmd): never draw aucmd_prepbuf temp win #40379
Problem:  An autocommand that redraws may do so while curwin is
          temporarily set for the autocommand scope. This can result in
          flickering or unexpected state with UI components (statusline,
          winbar, decor providers...) that depend on the current window.
          Current workaround for statusline and winbar specifically
          delays the redraw, which can itself be unexpected for the
          autocommand.

Solution: If redrawing happens with a temporary autocmd current window,
          temporarily restore the current window while redrawing.
2026-06-23 16:05:26 -04:00
Barrett Ruth
e4fbe162c1 fix(statusline): defer redraw in aucmd context #40309
Problem: `nvim_exec_autocmds({buf=...})` may temporarily switch curwin/curbuf
through `aucmd_prepbuf()`. Requested statuslines/winbars before
`aucmd_restbuf()` may erroneously see the target window as current.

Solution: Track `aucmd_prepbuf()` window-switch depth and leave statusline/winbar
redraws marked dirty until the original window is restored.
2026-06-23 06:05:11 -04:00
zeertzjq
eb0bd381e5 vim-patch:9.2.0707: completion: popup misplaced when text before it is concealed (#40374)
Problem:  When the cursor line has concealed text before the start of the
          completion, the insert-mode completion popup is drawn at the wrong
          screen column and the cursor no longer lines up with the completed
          text.
Solution: Record the concealed width before the cursor on its screen line in
          a new `win_T` field while `win_line()` draws it, subtract it in
          `pum_display()` to place the menu over the visible text, and redraw
          the cursor line so `win_line()` corrects the cursor too.

closes: vim/vim#20539

d167c50de4

Co-authored-by: Barrett Ruth <br@barrettruth.com>
2026-06-23 08:51:03 +00:00
Luuk van Baal
e542b42903 fix(ui2): message before empty prompt not shown
Problem:  Message before empty input() is not visible.
Solution: Route to dialog window with active prompt (hl_id >= 0).
2026-06-22 15:56:26 +02:00
Luuk van Baal
d16bd456a8 fix(cmdline): encode no prompt in cmdline_show.hl_id
Problem:  Unable to distinguish an empty prompt from no prompt in
          cmdline_show event.
Solution: Set cmdline_show.hl_id to -1 when no prompt is active.
2026-06-22 15:56:26 +02:00
Luuk van Baal
60a46036c0 fix(ui2): clear search_count after clearing the screen
Problem:  Clearing the screen doesn't clear the "last" virtual text.
          Dupe counter virtual text is not increased beyond 1.
Solution: Clear "last" virtual text when clearing the screen.
          Restore assignment lost in a previous commit.
2026-06-22 15:14:53 +02:00
zeertzjq
9607e53cea vim-patch:9.2.0682: Wrong dot-repeat when calling complete() while filtering completion (#40350)
Problem:  Wrong dot-repeat when calling complete() while filtering
          Ctrl-N completion.
Solution: Also check compl_started for whether completion is active.
          (zeertzjq)

related: neovim/neovim#40346
closes:  vim/vim#20595

37a7e4944f
2026-06-21 14:09:43 +00:00
luukvbaal
69160854c5 feat(column): per row click handlers for 'statuscolumn' (#40265)
Problem:
- Current 'statuscolumn' click label caveat is restrictive.
- v:virtnum is not unique to a line if it has both above and
  below virtual lines.
- 'statuscolumn' click handler may expect v:virt/lnum to be set.

Solution:
- Store per-row click definitions for the statuscolumn in a
  (nested line/virt number) map.
- Implement strategy that gives each 'statuscolumn' row a unique
  v:virtnum.
- Set v:virt/lnum when determining which line is clicked.
2026-06-20 15:59:08 +02:00
Sam Reynoso
6be9459d35 fix(cmdline): avoid redraw loop after wrapped line #40240
Problem:  A wrapped command line and screen width may be redrawn
          repeatedly after calls to `redrawstatus` from lua.

Solution: redrawcmd() redraws the command line, but msg_clr_eos() may
          invalidate cmdline_was_last_drawn during the redraw process.
          Restore cmdline_was_last_drawn when redrawcmd() completes.

Co-authored-by: Sam Reynoso <sam@codeoutpost.com>
Co-authored-by: Luuk van Baal <luukvbaal@gmail.com>
2026-06-19 16:24:53 -04:00
bfredl
90157d3790 fix(tests): use builtin default attributes in more places 2026-06-19 19:42:28 +02:00
glepnir
823517ad1d fix(highlight): keep guisp underline color in float with 'winblend' #40283
Problem:
A colored (guisp) underline showing through a 'winblend' float
lost its special color and followed the foreground instead.

Solution:
In the blend-through case, blend the underline's special color
only when the cell below sets sp explicitly; otherwise clear it.
2026-06-16 07:39:32 -04:00
Vahur Sinijärv
db0fca2443 fix(mappings): 'langmap' with multibyte chars #40148
Problem:
On some non-US keyboards, like Estonian/Swedish/etc, widely used []
characters in vim are hard to type. One way to overcome this is to use langmap
option to map accented characters, that are in the same place as [] on US
keyboards to []. Unfortunately this does not work currently in neovim, it
cannot map multibyte characters via langmap.

Solution:
The fix iterates over characters in typeahead and key buffers, instead of bytes,
in getchar.c handle_mapping(). It does not handle macros though, these tests are
still failing when turned on.

Closes #2420
Closes #27776

Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2026-06-15 06:49:41 -04:00
luukvbaal
736f914c7b fix(mouse): click on "below" virtual lines #40217
Problem:  Clicking on a "below" virtual line interacts with the line
          it is attached to for decor/drawing purposes, rather than
          the line the extmark is placed at.
Solution: Account for "below" virtual lines when computing mouse line number.
2026-06-13 12:56:42 -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
Matei Stroia
fe154f4d45 fix(folds): foldcolumn is interrupted for virtual line above nested fold (#39999)
Problem:
`foldcolumn` is empty for virtual lines above the start of a nested
fold.

Solution:
For virtual lines, compute the outer fold level and display it by
reusing the logic from `fill_foldcolumn`.
2026-06-11 13:42:18 +00:00
Barrett Ruth
7c53de949b fix(autocmd): redraw statusline after nvim_exec_autocmds() #40172
Problem:
Since 5181984d, `nvim_exec_autocmds({buf=…})` temporarily sets the
`buf`-window as current-window, and its statusline renders as
a "current-window statusline", regardless of the user's actual
current-window.

Solution:
Mark the statusline for redraw in `aucmd_restbuf()`, so it is redrawn
correctly after the event.

Co-authored-by: Luuk van Baal <luukvbaal@gmail.com>
2026-06-10 18:02:03 -04:00
zeertzjq
fcd2adf8ae test: virt_lines_overflow=wrap with virt_lines_leftcol (#40147) 2026-06-09 02:30:38 +00:00
zeertzjq
5e8fbfd043 perf(extmark): fix performance regression for non-wrapped virt lines 2026-06-08 22:37:43 +08:00
jreidx
d9aa06eed8 feat(extmark): virt_lines_overflow "wrap" and "auto"
Problem: Extmark has support for horizontal scrolling and truncating, but not wrapping.

Solution: Extend virt_lines_overflow flags to support "wrap" and "auto" based on proposed changes in #18282.
2026-06-08 22:19:25 +08:00
zeertzjq
4ab670399b vim-patch:9.2.0596: cmdline completion popup cannot be scrolled with the mouse (#40142)
Problem:  In command-line completion with a popup menu ('wildoptions'
          contains "pum"), the info popup shown next to the menu could
          not be scrolled, unlike the Insert mode completion info popup
          which scrolls with the mouse wheel.
Solution: When the mouse pointer is on top of the info popup, scroll it
          with the mouse wheel in command-line mode as well, without
          closing the completion popup menu.

closes: vim/vim#20146
closes: vim/vim#20418

96dbab257a

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 20:53:10 +08:00