aboutsummaryrefslogtreecommitdiff
path: root/test/functional/ui
Commit message (Collapse)AuthorAge
* fix(ui2): use global value of 'fillchars' #42397Evgeni Chasnovski3 days
| | | | | | | | Problem: Custom ui2 window tracks 'fillchars' option to adjust to the change of `msgsep` flag. However, 'fillchars' is `:h global-local` window option. If it is set locally to the window, ui2 reacts to its `msgsep` value and keeps using it afterwards even in other windows. Solution: Use and react to only global value of 'fillchars'.
* fix(options): extend dry-run validationLewis Russell4 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: nvim_set_option_value() dry runs skip checks in did_set_* callbacks. This logic also prepares values needed to apply the option, such as tab widths or a compiled regexp. Moving the checks into validation callbacks needs a way to save that work for did_set_*. Solution: Store prepared values in optset_T so did_set_* can consume them after the option is stored. Dry runs perform the same validation, then free the prepared values without changing live state. This extends dry-run validation for: - 'cedit': reject invalid command-line window keys. - 'completeitemalign': require each completion column exactly once. - 'cursorlineopt': reject empty values and conflicting line modes. - 'encoding': accept only UTF-8 and its aliases. - 'fileencoding': reject lists and local changes with 'nomodifiable'. - 'messagesopt': require mandatory fields and enforce numeric limits. - 'spellcapcheck': return regexp errors, including under :silent!. - 'spellsuggest': reject conflicting suggestion modes. - 'varsofttabstop' and 'vartabstop': reject invalid tab widths. - 'wildmode': reject more than four completion stages. 'makeencoding' also uses the shared encoding preparation. Separating value preparation exposed a bug in 'vartabstop' and 'varsofttabstop': failed assignments could discard local tab widths, and global assignments could overwrite them. Fix this by preparing new widths separately and applying them only after a valid local assignment. AI-assisted
* fix(ui): ext_messages/ui2: stale 'rulerformat' "[+]" after :write #42315Justin M. Keyes7 days
| | | | | | | | | | | | | | Problem: With 'ruler' in the cmdline ('laststatus=0') and ext_messages (ui2), a 'rulerformat' "%m" does not update the "[+]" indicator after ":write", until a cursor-move. Analysis: `redraw_buf_status_later()` only marks windows with a statusline or winbar. The symptom is hidden by the legacy message grid because the write message overwrites the cmdline, which redraws the ruler. Solution: Also mark the cmdline 'ruler', like `status_redraw_buf()`.
* feat(startup): --embed --listen waits for UI if stdin is not a pipeJustin M. Keyes10 days
| | | | | | | | | | | | | | | | | | | | | | Problem: `nvim --embed --listen addr` always treats stdin as an RPC channel. If stdin is /dev/null (e.g. backgrounded over ssh), the channel closes before a UI can attach, so Nvim exits (detach=false behavior). If stdin is a tty, keystrokes are read as RPC. Solution: With `--embed --listen`, open the stdio RPC channel only if stdin is a pipe or socket. Else wait for a UI at the `--listen` address. $ nvim --embed --listen ./nvim.sock Nvim server (pid: 71984) waiting for UI, listening on: "./nvim.sock" Note: - No change when stdin is a pipe. So the test harness, TUI, and :restart all behave exactly as before. - The #29634 use-case of configuring a UI that attaches *after* startup (a second UI, or reattach) still requires #25377 (reliable UIEnter). Not affected by this change.
* Merge #42130 from epithet/tabline-base-hlJustin M. Keyes2026-10-05
|\ | | | | fix(tabline): make TabLineFill base highlight group of default 'tabline'
| * fix(tabline): make TabLineFill base highlight group of default 'tabline'Sébastien Hoffmann2026-10-03
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Follow-up to #41196 Problem: since #29976, the custom 'tabline' has a base highlight group TabLineFill that all %# highlights are automatically combined with. But the default C implementation still uses the TabLine and TabLineSel highlight groups uncombined, or rather effectively combined with Normal. Therefore, themes cannot depend on the base highlighting if they want to support both the default and custom tab lines. Solution: automatically combine TabLine and TabLineSel with TabLineFill in the default C implementation. fix https://github.com/neovim/neovim/issues/41173 ref https://github.com/neovim/neovim/pull/41196 ref https://github.com/neovim/neovim/pull/29976
* | test: simplify functional test expectationsLewis Russell2026-10-05
| | | | | | | | | | | | | | | | | | | | | | | | Problem: Repeated default fields and field-by-field assertions obscure the values that each functional test is meant to check. Solution: Add eq_partial() to check selected record fields while preserving list length and order. Use local helpers to fill fixed expected defaults where tests need full equality. Keep explicit absence checks and test-specific values at the call sites. AI-assisted
* | vim-patch:9.2.1163: tests: not enough tests for virtual text before ↵zeertzjq2026-10-04
|/ | | | | | | | | | | 'linebreak' (#42225) Problem: tests: not enough tests for virtual text before 'linebreak'. Solution: Add a new case that behaved incorrectly before patch 9.2.1162 (zeertzjq). closes: vim/vim#21426 https://github.com/vim/vim/commit/fbd316b43f1a58f19dc2bb9343d56d46ff1d468a
* fix(display): pad virtual text after listchars eol #41292Langning Zhang2026-10-03
| | | | | | | | | Problem: End-of-line virtual text is drawn directly after a displayed listchars eol character. Solution: Preserve the normal one-cell separator after the eol character. AI-assisted
* vim-patch:9.1.1568: need a few more default highlight groupszeertzjq2026-10-03
| | | | | | | | | | | | | Problem: need a few more default highlight groups Solution: Add Bold, Italic and BoldItalic default highlight groups (Maxim Kim). related: https://github.com/vim/vim/pull/17598#issuecomment-3007320523 closes: vim/vim#17804 https://github.com/vim/vim/commit/16f7098e68951ce421512c34d03810bdd1efbaed Co-authored-by: Maxim Kim <habamax@gmail.com>
* fix(search): correct patlen calculation for semicolon search (#42150)Qiming zhao2026-09-30
| | | | | | | | | | | | | | | | | Problem: When repeating search using a semicolon (e.g. `/pat1/;/pat2`), `pat` advances past both the semicolon and the delimiter ('/' or '?'), consuming 2 characters, but `patlen` was only decremented by 1. Consequently, `patlen` in the subsequent search is 1 byte too long and includes the trailing NUL byte, corrupting `msgbuf` and causing ui2's search_count handler to fail with 'attempt to concatenate a nil value'. Solution: Decrement `patlen` by 2 when skipping ';' and delimiter. Also ensure ui2 safely guards search_count messages when extracting the search stat. Fixes #41929 AI-assisted
* Merge #41944 from epithet/stl-hl-scopesJustin M. Keyes2026-09-30
|\
| * feat(statusline): highlight scopesSébastien Hoffmann2026-09-26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem 1: many status line sections are automatically hidden when they currently aren't relevant. When such a section contains highlights, the exact pre-section highlighting needs to be reset at the end, otherwise the highlighting of unrelated sections to the right depend on whether the section is hidden or not. And in case of auto-hiding item groups, it might even refuse to hide. Problem 2: when only a part in the middle of a section should deviate from the surrounding highlighting, the section needs knowledge of the highlighting outside in order to reset it, which makes it hard to create self-contained, reusable modules. Problem 3: with nested sections of progressively stacked highlighting changes, the last %$-modifications effectively have to be subtracted when ending a subsection. This can only be done by replaying all the pre-subsection changes from the last %#. Solution: Introduce highlight scopes %#(...%#) that automatically reset pre-scope highlighting at the end. ref #26037 ref #29976 ref #29980 ref #35806 ref #36685
* | vim-patch:9.2.1114: Visual selection is not highlighted at the cursor ↵Takumi Katase2026-09-27
|/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | position #42105 vim-patch:9.2.1114: Visual selection is not highlighted at the cursor position Problem: In a terminal the character under the cursor is normally not shown as part of the visual selection. Solution: Don't set "noinvcur" in win_line() (Shane Harper). The problem did not occur in the GUI, only in a terminal. The name "noinvcur" ("don't invert the cursor") was misleading: the variable did not affect the cursor, but whether the character under the cursor could be displayed as part of the visual selection. The "noinvcur" handling may have been meant to help during a visual selection when Visual is shown in reverse video and the terminal draws the cursor by inverting the character under it, as otherwise the character under the cursor would not look highlighted like the rest of the selection. But Vim cannot know in general how a terminal draws the cursor, and when either the cursor is not drawn by inverting the character under it or Visual is not shown in reverse video, the handling just left a character of the visual selection unhighlighted. closes: vim/vim#21317 https://github.com/vim/vim/commit/d10aab4ba6602f8f2f2576d2d62ceb63869db6fb Co-authored-by: Shane Harper <shane@shaneharper.net> AI-assisted
* fix(ui2): dialog messages offset by the pager line count #41839Justin M. Keyes2026-09-11
| | | | | | | | | | | | | | | | Problem: expand_msg() derives its start row from the pager buffer even when the target is the cmd or dialog buffer, so the copied lines are appended instead of replacing, and the copied extmarks are placed at pager rows in a smaller buffer: "Invalid 'end_col': out of range", thrown inside a UI event handler. Solution: Offset only when appending to a visible pager, and read the line count after msg_clear(), whose autocmds may write to the pager. Copy marks with `strict = false`, since the rows and columns are recomputed for a different buffer and should clamp rather than raise. AI-assisted
* revert(scrollbind): revert #41519 due to regressionsYanuo Ma2026-09-10
| | | | | | | | | | | | | | | | | Problem: Resetting w_scbind_pos to the displayed position discards pending scroll distance. This breaks scrollbind with asymmetric folds and leaves persistent offsets after tall virtual-line blocks. Wrapped lines with smoothscroll also show increased follower lag. Solution: Revert the original change and its test. This restores the previous behavior, including the original tall-virt_lines oscillation, while a replacement is reviewed separately. This reverts commit b781e95a24bd2d201f4afbe4729635114893cdf5. AI-assisted
* fix(ui2): :quit on unsaved buffer shows hit-enter prompt #41575Tomasz N2026-09-09
| | | | | | | | | Problem: "Press any key" modal prompt is shown when `:quit` from unsaved buffer, even if ui2 is enabled (which should never show hit-enter prompt). Solution: Skip `wait_return` for `ext_messages` UIs.
* vim-patch:9.2.1038: CursorLineFold/Sign highlighting depends on ↵zeertzjq2026-09-08
| | | | | | | | | | | | | | | | 'cursorlineopt' (#41785) Problem: CursorLineFold and CursorLineSign are only applied when 'cursorlineopt' contains "number" or is "both" (Evgeni Chasnovski). Solution: Apply those groups whenever 'cursorline' is set, independent of 'cursorlineopt' (Vrushali Zampalkar). fixes: vim/vim#20480 closes: vim/vim#21112 https://github.com/vim/vim/commit/1f8d3c44c5bd5a3d5032b3fc53e9d3aa1052583c Co-authored-by: Vrushali-Z <zampalkarvasu@gmail.com>
* Merge pull request #41751 from bfredl/stringly_nilsbfredl2026-09-08
|\ | | | | test(ci): non fatal errors for [NULL] safety in vim_snprintf
| * fix(strings): non fatal errors for [NULL] safety in vim_snprintfbfredl2026-09-08
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | context: vim_snprintf provides a "portable" replacement for a system vsnprintf(). However we rely on system vsnprintf() in places. This is quite arbitrary. I want to use system vsnprintf() only, and reduce the machinery in string.c for typval printf only, which will delet a lot of duplicated code. The biggest hurdle here is not "portably" (we only support sane c runtimes) but the following discrepancy: standard libc printf() considers NULL args to %s to be undefined behavior strictly while vim_snprintf() _defacto_ allows this by replacement to "[NULL]" IMO, this should be seen as "graceful" error handling (nicer than crashing on the user), not a valid means to have the string "[NULL]" intentionally be shoved in the users face. more robust code should explicitly check for NULL and replace it with a _appropriate_ fallback for the situation, depending on what a NULL string actually means in the context (unnamed buffer? anonymous namespace? global augroup?) soo, this PR provides the most _gently_ incremental nudge towards considering this case again as an error one could possible imagine. If sanitizers are complied in, this minor incursion gets printed into the sanitizers' log as a "report-and-continue" error with a traceback. This doesn't annoy the end user or "stop the world" in the test suite, but the CI will see the reported error and fail the build, just like other non-fatal CI errors.
* | fix(scrollbind): window jumps back and forth with tall virt_lines blockYanuo Ma2026-09-08
| | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Scrolling a 'scrollbind' window whose peer has a virt_lines block taller than the window makes the peer jump back and forth. Solution: After scrollup()/scrolldown(), sync w_scbind_pos to the actual get_vtopline() when the target was not clamped to buffer bounds. Ref: esmuellert/codediff.nvim#519 AI-assisted
* | fix(ui2): mouse movement dismisses expanded messages #41732Volodymyr Chernetskyi2026-09-06
| | | | | | | | | | | | | | | | | | | | | | | | | | 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
* | feat(ui2): highlight the [+x] spill indicator with MoreMsg #41679Volodymyr Chernetskyi2026-09-04
| | | | | | | | | | | | | | | | | | | | | | | | | | 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
* | fix(api): leaked window set in nvim__ns_set() #41689Volodymyr Chernetskyi2026-09-04
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: The early return for an invalid window handle bypasses the `set_destroy()` at the end of the block, so the set's backing allocation leaks whenever an earlier iteration already called `set_put()`. Triggered by `{ wins = { valid_win, 9999 } }`. Solution: Destroy the set before returning. The new test passes either way, since the leak is only visible to a sanitizer; it is there so the ASAN job covers the path. AI-assisted
* | feat(ui2): scroll the dialog window with the mouse wheel #41682Volodymyr Chernetskyi2026-09-04
| | | | | | | | | | | | | | | | | | | | | | | | 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
* | fix(move): zz does not center the cursor with wrapped lines #41656Volodymyr Chernetskyi2026-09-04
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: `scroll_cursor_halfway()` resets its `above` and `below` row counters on every iteration of the `topline` scan, because they are declared inside the loop. Each iteration then takes one line from each side regardless of how many screen rows those lines occupy, so tall wrapped lines below the cursor leave it near the top of the window instead of centered. Affects the default `nosmoothscroll` path, reached from "zz" and from `update_topline()`. Regression from 9b9ccac6256 (vim-patch:9.0.1121), which moved the declarations to their first use while porting; the upstream patch did not touch them. Solution: Declare the counters at function scope, as Vim does, so they accumulate across iterations.
* | fix(statusline): default 'statusline' improvements #41597Sébastien Hoffmann2026-09-03
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* | fix(statuscolumn): heap buffer overflow with sign/number column (#41640)zeertzjq2026-09-03
|/ | | | | Problem: Drawing 'statuscolumn' leads to a heap-buffer-overflow if a sign/number column comes after many items. Solution: Avoid curitem >= stl_items_len when writing to stl_items.
* fix(mcursor): drop q= "follow motion" messageJustin M. Keyes2026-09-02
|
* fix(highlight): cterm default for Cursor hlgroupJustin M. Keyes2026-09-02
| | | | | | | | Problem: The `Cursor` highlight is invisible if 'termguicolors' is disabled. Solution: Change its default.
* vim-patch:9.2.1031: 'wildmode' list:full does not show 'wildmenu'zeertzjq2026-09-02
| | | | | | | | | | | | | | | | | 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 https://github.com/vim/vim/commit/fa1ddffcce24f22d61608c0086e55adadd1d2c11 Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
* feat(multicursor): MC HAMMER #41587Justin M. Keyes2026-09-01
| | | | | | | | | | | | | | | | | | | | | 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().
* fix(ui2): don't draw MsgSeparator if cmdheight=0 #41531not_compiled2026-08-29
| | | | | | | | | Problem: When 'cmdheight' is 0, the MsgSeparator can obscure the statusline when a message is displayed, making its contents disappear until the next redraw. Solution: Skip the separator when 'cmdheight=0' available.
* feat(editor): undo restores cursor position #41520Justin M. Keyes2026-08-27
| | | | | | | | | | | | | | | | | | Problem: Undo places the cursor wherever the cursor happened to sit at "save time" (`uh_cursor` is sampled lazily on the first change). Examples: - `i` preserves, but `a` does not - `diw`, `atest<Esc>`, `d^` abandon the original position - `D`, `o` restore it (by accident). Solution: `composite` tracks the pending atom (and its `origin`) across frames. A `stuffed` continuation frame inherits the `origin` + prepped redo. Store `origin` info in the undo header, so undo can restore it. - Not for a mid-command undo break (i_CTRL-G_u). - Undoing a mapping restores where the mapping started (which technically may be different than where the "edit" started).
* fix(ui2): cmdwin is not special #41508Justin M. Keyes2026-08-26
| | | | | | | | | | | | | | | | | | | | Problem: Unreliable ui2 test: FAILED …/ui/messages2_spec.lua @ 277: messages2 multiline messages and pager …/ui/messages2_spec.lua:277: Row 1 did not match. Expected: ... |*{1::}echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | |*{1::}messages | |*{1::}^ | ... Actual: ... |*{9:vim.schedule callback: ...ork/neovim/neovim/runt [+7]}| Solution: ui2 is doing contortions to handle the old cmdwin behavior; stop doing that, it's no longer necessary since b2bf7bcfb151.
* test: fix wrong order of args to eq(), neq() #41499zeertzjq2026-08-26
|
* test(shell): unreliable "throttles shell-command output…"Justin M. Keyes2026-08-25
|
* feat(ui2): lift ui2 options into 'messagesopt' (part 1) #41474Justin M. Keyes2026-08-25
| | | | | | | | | | | | | | | | | | | Problem: In order for ui2 to graduate to the main "messages ui" its configuration needs to graduate into actual options. Solution: Migrate some of its config to 'messagesopt': - "maxheight" (note: currently this is an integer treated as a "percentage"; if we want to support a row count we could allow values with units, like `"42%"`) - "pager" - "timeout" Also improves error messages: messagesopt=hit-enter,history:500,bogus E474: Unknown item 'bogus' messagesopt=hit-enter,history:500,progress:x E474: 'progress' must be one of: , c messagesopt=hit-enter,history:abc E474: 'history' requires a number
*