patch 9.2.0469: popup: textprop-anchored popups bleed past host window edges
Problem: A popup anchored to a text property in a split window is
positioned relative to the screen and may extend into
adjacent splits or off-screen regions. There is no way to
confine the popup to the window that contains the textprop.
Solution: Add the "clipwindow" popup option to allow clipping the text
property popup to the host window (Yasuhiro Matsumoto).
Adds a "clipwindow" boolean option to popup_create()/popup_setoptions().
When set on a textprop-anchored popup, the popup's drawn extent is
confined to its host (textprop) window's content rectangle so the popup
no longer bleeds across a horizontal split's statusline (top/bottom) or
a vsplit's separator (right) into another window.
The popup keeps its full logical size and position; only the rows or
columns that fall outside the host window's content area are skipped
during drawing, so a popup that scrolls toward the host's edge looks
visually "cut off" without its borders being relocated. popup_getoptions
and popup_getpos continue to report the unclipped geometry.
Implementation:
- w_popup_topoff / w_popup_bottomoff record how many rows of the
popup fall outside the host on each side. popup_adjust_position()
computes them from the host rectangle after the logical layout is
finalised, and update_popups() and the popup-mask builder subtract
them when emitting cells/borders/scrollbar and when marking
popup-owned cells. win_update() is bracketed by transient
w_height/w_topline/w_winrow adjustments so the buffer's drawn
content matches the visible row range.
- w_popup_rightclip is the horizontal counterpart for the host's
right edge: the right border, padding and content columns past
the host are not drawn. win_update() is bracketed by a transient
w_width reduction so the buffer text is not written past the
host's right edge either.
- When the textprop scrolls just above the host window's top, the
popup is kept visible by extending the prop search above topline
(new helper find_prop_in_lines) and synthesising a negative
screen_row so the top-clip path can roll the popup off the top.
When the textprop has scrolled far enough that even the bottom
border would overlap the host edge -- or when the popup would
overflow the host's left edge at all -- the popup is hidden, and
unhidden again once it comes back within range.
- The "reduce-height" / "clamp winrow to 0" fallbacks in
popup_adjust_position are bypassed for host-clipped popups so the
popup keeps its natural anchored position instead of being
snapped to the screen edge.
Left-edge partial clipping is intentionally not supported: it
would require shrinking the buffer width during win_update, which
reflows wrapped lines and corrupts the displayed content; the
popup is hidden instead.
closes: #20166
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0468: popups: not correctly updated from a CmdlineChanged autocommand
Problem: popup_show() from a CmdlineChanged autocommand doesn't update
the screen (Mao-Yining)
Solution: Refresh the screen when popups need redraw
(Yasuhiro Matsumoto).
popup_settext()/popup_show() called from a CmdlineChanged autocommand
did not refresh the screen because cmdline mode normally skips
update_screen(), so async info-popup updates only became visible after
a manual :redraw. Refresh the screen when popups need redrawing right
after the autocommand.
fixes: #20175
closes: #20179
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: In a multi-line statusline (and 'tabpanel'), %#XX# / %N*
set on one row do not persist on subsequent rows.
build_stl_str_hl_local() rebuilds stl_items[] from scratch
on every line break ("%@" or "\n"), so the highlight is
reset at each row boundary even though within a row it
stays until %* (or another %# / %*).
Solution: Carry the last Highlight item's stl_minwid across line
breaks via a new in/out int* parameter "carry_hl". At the
start of each row, pre-insert a Highlight item from the
carried value so the row begins under the same highlight;
before returning, update the carried value with the row's
final Highlight item. Apply the same carry to the
tabpanel rendering loop (Hirohito Higashi).
related: #19123
closes: #20180
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Hirohito Higashi <h.east.727@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0466: popup: redraw can use stale blended cells
Problem: popup: redraw can use stale blended cells
Solution: Save the old popup area and redraw the newly exposed region so
opacity popups don't show stale blended cells when another
popup moves or closes. Consolidate redraw helpers so the
saved-area and exposed-area logic is shared across
move/hide/close/settext/setoptions. Refactor popup redrawing
code, add a regressions tests (Yasuhiro Matsumoto).
closes: #20172
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0463: Not able to use legacy expression evaluation in a vim9script maps
Problem: Not able to use legacy expression evaluation in a vim9script
maps
Solution: Explicitly set script version to 1 when the :legacy modifier has been
used (Yegappan Lakshmanan).
fixe: #20176
closes: #20177
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
K.Takata [Sun, 10 May 2026 16:34:01 +0000 (16:34 +0000)]
patch 9.2.0462: MS-Windows: workaround for assert error on GUI
Problem: When Vim is built with debug mode, gvim causes an assertion
error and stops working when running on Visual Studio
Debugger.
Solution: Stop calling _set_fmode() if not needed (Ken Takata).
closes: #20181
Signed-off-by: K.Takata <kentkt@csc.jp> Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: The four pointer-resolution loops in u_read_undo() lack
an i != j guard, so a header whose uh_next.seq equals
its own uh_seq resolves uh_next.ptr to itself. On
buffer close, u_freeheader() sees uhp->uh_next.ptr !=
NULL and skips updating b_u_oldhead, so u_blockfree()
dereferences the freed header on the next iteration.
The same pattern applies to uh_prev, uh_alt_next and
uh_alt_prev. A crafted .un~ file in the same directory
as a text file can trigger the use-after-free and
subsequent double-free when the buffer is closed.
(Daniel Cervera)
Solution: Add an i != j guard to each of the four resolution
loops, matching the guard already present in the
duplicate-detection loop above.
zeertzjq [Sat, 9 May 2026 14:18:53 +0000 (14:18 +0000)]
patch 9.2.0460: did_set_shellpipe_redir() in wrong file
Problem: did_set_shellpipe_redir() is a callback for a string option,
but is not in optionstr.c (after 9.2.0458).
Solution: Move it to optionstr.c. Also add missing change from patch
9.2.0455 (zeertzjq).
related: #20159
related: #20164
closes: #20170
Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: tests: test_termcodes fails, because it disabled DECRQM, but
did not adjust the expected values in the test (after v9.2.0456)
Solution: Update the test
dependabot[bot] [Sat, 9 May 2026 13:49:43 +0000 (13:49 +0000)]
CI: Bump the github-actions group across 1 directory with 2 updates
Bumps the github-actions group with 2 updates in the / directory: [github/codeql-action](https://github.com/github/codeql-action) and [actions/labeler](https://github.com/actions/labeler).
Updates `github/codeql-action` from 4.35.2 to 4.35.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v4.35.2...v4.35.3)
Updates `actions/labeler` from 6 to 6.0.1
- [Release notes](https://github.com/actions/labeler/releases)
- [Commits](https://github.com/actions/labeler/compare/v6...v6.0.1)
zeertzjq [Fri, 8 May 2026 21:09:48 +0000 (21:09 +0000)]
patch 9.2.0455: 'findfunc' only allows extra info for cmdline completion
Problem: 'findfunc' only allows extra info for cmdline completion, not
for actually finding files (Maxim Kim, after 9.2.0451).
Solution: Handle returning a list of dicts when actually finding files.
Also fix crash on NULL string (zeertzjq).
fixes: #20163
closes: #20164
Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0453: vertical separator of statusline blend into active statusline
Problem: Since v9.2.0349, the vertical separator cell at status line
rows is drawn as a space with StatusLine highlight, hiding the
user's 'fillchars' "vert" or "stl"/"stlnc" character at that
cell (after v9.2.0349)
Solution: Drop the status line blend. At status line rows the separator
cell goes back to using the status fillchar when adjacent
status lines are connected, or the vsep character otherwise.
(Same as before v9.2.0348)
Keep the VertSplitNC highlight group introduced in v9.2.0349. The
highlight (VertSplit vs VertSplitNC) is selected based on whether the
current window is adjacent to the separator at the row.
Vertical separators are redrawn on current-window changes and on
:redrawstatus[!] so the VertSplit/VertSplitNC highlight is updated
immediately.
fixes: #20089
related: #19951
closes: #20167
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Hirohito Higashi <h.east.727@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0452: screen.c popup opacity blend logic is duplicated
Problem: screen_line() has four near-identical blocks computing
the popup_attr, the combined attr, the blend value and
the underlying base attr in sequence when handling popups
with opacity. The duplication makes the function long
and hard to follow, and changes have to be applied to all
four sites.
Solution: Extract the shared computation into popup_blend_with_base()
and popup_base_attr_or() helpers, and cache per-popup
attrs once via popup_opacity_T. No behavior change
(Yasuhiro Matsumoto).
closes: #20154
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
zeertzjq [Thu, 7 May 2026 19:29:06 +0000 (19:29 +0000)]
patch 9.2.0451: 'findfunc' can't return extra info for cmdline completion
Problem: 'findfunc' can't return extra info for cmdline completion
(Maxim Kim).
Solution: Handle 'findfunc' return value in cmdline completion like that
of "customlist" functions (zeertzjq).
fixes: #20155
closes: #20158
Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0450: [security]: heap buffer overflow in spellfile.c read_compound()
Problem: read_compound() in spellfile.c computes the size of the regex
pattern buffer using signed-int arithmetic on the attacker
controlled SN_COMPOUND sectionlen. With sectionlen=0x40000008
and UTF-8 encoding active the multiplication wraps to 27 while
the per-byte loop writes up to ~1B bytes, overflowing the heap.
Reachable when loading a crafted .spl file (e.g. via 'set spell'
after a modeline sets 'spelllang'). The cp/ap/crp allocations
have the same int + 1 overflow class (Daniel Cervera)
Solution: Use type size_t as buffer size and reject values larger than
COMPOUND_MAX_LEN (100000). Apply the same size_t treatment to
the cp/ap/crp allocations.
patch 9.2.0448: Vim9: dangling cmdline pointer after skip_expr_cctx()
Problem: Vim9: dangling cmdline pointer after skip_expr_cctx()
(Foxe Chen)
Solution: Extract the cmdline restoration logic from compile_lambda into
a helper restore_cmdline_arg() and call it from
skip_expr_cctx() too, so a skipped lambda inside an "else"
branch does not leave "*arg" pointing into freed evalarg
memory (Yasuhiro Matsumoto).
fixes: #20147
closes: #20148
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: When find_start_brace() scans backwards for the enclosing
block, '{' and '}' inside // and /* */ comments are counted,
producing wrong indent for code following such comments
(rendcrx).
Solution: Implement FM_SKIPCOMM in findmatchlimit() to track block-
comment state and skip matches inside comments. Pass
FM_SKIPCOMM from cindent's call sites
(find_start_brace, find_match_char, cin_iswhileofdo,
get_c_indent).
J. Paulo Seibt [Tue, 5 May 2026 20:06:15 +0000 (20:06 +0000)]
patch 9.2.0446: runtime(netrw): off-by-one bug in s:NetrwUnMarkFile()
Problem: off-by-one bug in s:NetrwUnMarkFile()
Solution: Correctly loop through all buffers to unlet all variables
(J. Paulo Seibt)
When the function loops through buffers to clear s:netrwmarkfilelist_#
and s:netrwmarkfilemtch_#, it skips the last one at bufnr('$'), messing
up mark highlights and causing other functions that operate on those
arrays (like delete or rename) to target stale marked files.
The bufnr() help page says that bufnr("$") returns the highest buffer
number of existing buffers, so while ibuf < bufnr("$") does not clear
the last buffer-local arrays.
To reproduce:
Just opening a fresh Vim and running :Ex opens a netrw buffer at the
highest number. Then, typing mu after marking some files triggers the
mark highlight bug, and finally typing D would act like calling the
delete function against the previous marked files, as the buffer-local
arrays where not touched by s:NetrwUnMarkFile.
closes: #20129
Signed-off-by: J. Paulo Seibt <jpseibt@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0445: win_fix_scroll() called before win_comp_pos() in command_height()
Problem: win_fix_scroll(true) is called before win_comp_pos() in
command_height().
Solution: Move win_fix_scroll(true) after win_comp_pos(), matching the
ordering used in win_drag_status_line() (Jesse Rosenstock).
Patch 9.2.0413 added win_fix_scroll(true) to command_height() to handle
splitkeep when cmdheight changes, but placed the call before win_comp_pos().
win_fix_scroll() reads w_winrow to detect window movement
(https://github.com/vim/vim/blob/620557bd48865fa3d927901764d2747bf68597b5/src/window.c#L7266),
but w_winrow is not recomputed until win_comp_pos() runs
(https://github.com/vim/vim/blob/620557bd48865fa3d927901764d2747bf68597b5/src/window.c#L6516).
This causes incorrect scroll adjustments and was breaking
Test_smoothscroll_incsearch on macOS CI.
closes: #20138
Co-authored-by: Gemini Signed-off-by: Jesse Rosenstock <jmr@google.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0443: GUI: cancelling save dialog overwrites or discards unnamed buffer
Problem: When closing gvim with an unsaved unnamed buffer, choosing
"Yes" in the "Save changes?" dialog and then "Cancel" in the
file selection dialog either silently writes the buffer to a
file named "Untitled" (overwriting any existing file with
that name) or discards the buffer altogether
(vibs29, after v9.1.0265).
Solution: In dialog_changed(), if browse_save_fname() leaves the buffer
without a file name, treat it as a cancel and return without
saving. Also stop clearing the modified flag in the restore
path on write failure, so the unsaved changes are kept and
the caller (e.g. gui_shell_closed()) can also cancel the
close. Pre-fill the file dialog with "Untitled" to match
the preceding "Save changes to ..." prompt. Add a test for
the write-failure path (Hirohito Higashi).
fixes: #20132
closes: #20143
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
zeertzjq [Tue, 5 May 2026 18:56:56 +0000 (18:56 +0000)]
patch 9.2.0442: completion: i_CTRL-X_CTRL-V doesn't use dict from customlist
Problem: Completion with i_CTRL-X_CTRL-V doesn't use dict from cmdline
"customlist" completion.
Solution: Include abbr/kind/menu/info in the completion items
(zeertzjq).
closes: #20139
Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
mityu [Mon, 4 May 2026 20:24:07 +0000 (20:24 +0000)]
Fix wrong comment in getchar.c
The comment for `do_key_input_pre()` function says that it handles the
InsertCharPre autocommand, but what the function actually handles is the
KeyInputPre autocommand.
closes: #20142
Signed-off-by: mityu <mityu.mail@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0441: statusline: click handler not called on multi-line statusline
Problem: With a multi-line statusline clicking on a "%[FuncName]...%[]"
or "%@FuncName@..." region defined on a row other than the
last drawn row does not invoke the handler (Christian
Robinson, after v9.2.0338)
Solution: In win_redr_custom() the click region table reflects only the
last iteration of the per-row draw loop, so click regions are
recorded only for the last row. Move the click-region
resolution inside the loop and append regions for each row
using vim_realloc(). This also fixes a leak of
clicktab[].funcname for non-last rows (Hirohito Higashi).
fixes: #20116
closes: #20120
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Hirohito Higashi <h.east.727@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0440: MS-Windows: cursor flicker during update_screen()
Problem: MS-Windows: cursor flicker during update_screen()
Solution: Hide the cursor during update_screen() to avoid Windows ConPTY
flicker (Yasuhiro Matsumoto).
On terminals that do not honor synchronized output mode (e.g. Windows
ConPTY), update_screen() emits cell positioning and content as multiple
Win32 console writes through mch_write(), which the terminal renders as
separate frames. This shows up as the cursor briefly jumping to column
1 of rows being redrawn, especially during async redraws around the
popup completion menu.
Disable the cursor with cursor_off() at the start of update_screen()
and restore it with cursor_on() at the end, but only when synchronized
output mode is not active. When it is, the redraw is already atomic
from the terminal's view and hiding the cursor would only add visible
blink with no benefit.
closes: #20121
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
zeertzjq [Mon, 4 May 2026 19:53:10 +0000 (19:53 +0000)]
patch 9.2.0439: completion: info popup not removed in cmdline mode
Problem: Info popup isn't removed when selecting an item that doesn't
have "info" in cmdline completion, which is inconsistent with
Insert mode behavior.
Solution: Set pum_call_update_screen in cmdline mode (zeertzjq).
closes: #20128
Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0438: tests: test_plugin_termdebug is flaky
Problem: Test_termdebug_tbreak(), Test_termdebug_basic(), and
Test_termdebug_toggle_break() use synchronous assert_equal()
to check breakpoint signs immediately after sending commands
to gdb. On slow CI (ASAN, ARM64, macOS) gdb may not have
processed the response yet, causing the sign to be missing.
Solution: Wrap the three assertions in WaitForAssert() to poll until
the signs are placed, matching the pattern already used by
the other assertions in the same tests (Jesse Rosenstock).
closes: #20133
Co-authored-by: Gemini Signed-off-by: Jesse Rosenstock <jmr@google.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0437: MS-Windows: cursor flicker in vtp mode
Problem: MS-Windows: cursor flicker in vtp mode
Solution: Skip mch_update_cursor() in cursor_visible() when vtp is
active (Yasuhiro Matsumoto).
In vtp (ConPTY) mode the cursor visibility is controlled by DECTCEM
(\033[?25h / \033[?25l). The follow-up call to mch_update_cursor() then
re-emits DECSCUSR (\033[0 q etc.) on every visibility toggle even though
the cursor shape did not change. Some terminals briefly redisplay the
cursor when DECSCUSR arrives, so this can cause a visible flash at the
position the cursor will be moved to next (e.g. column 0 ahead of a line
redraw).
In non-vtp mode the call is still required because SetConsoleCursorInfo()
inside mch_set_cursor_shape() reads s_cursor_visible to apply the
visibility change, so keep that path unchanged.
closes: #20122
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0436: Buffer overflow when parsing overlong errorformat lines
Problem: When an error line in a file passed to :cfile / :cgetfile is
longer than IOSIZE, qf_parse_file_pfx() copies the tail
into the fixed-size IObuff with STRMOVE(), overflowing the heap buffer.
The same code path can also loop indefinitely because
qf_parse_file_pfx() always returns QF_MULTISCAN when a
tail is present, and qf_init_ext() unconditionally goes
to "restofline" without bounding the tail length (Nabih).
Solution: Remove the STRMOVE() into IObuff. In the QF_MULTISCAN
branch, alias linebuf into the tail directly and update
linelen, requiring strict progress (new length less than
the previous length) before retrying; otherwise ignore
the line.
patch 9.2.0435: [security]: backticks in 'path' may cause shell execution on completion
Problem: [security]: Backticks enclosed shell commands in the 'path'
option value are executed during completion (q1uf3ng).
Solution: Skip path entries containing backticks, add P_SECURE to 'path'
option, so that it cannot be set from a modeline (for symmetry with
the 'cdpath' option)
patch 9.2.0434: cscope: filename interpreted by /bin/sh
Problem: cs_create_connection() builds the cscope command by
interpolating csinfo[i].fname (and ppath, flags) into a
string and lets the shell parse it. Shell metacharacters
in a database filename are therefore evaluated by /bin/sh
before cscope is exec'd, rather than being passed through as a
literal path (q1uf3ng)
Solution: Build argv directly and execvp() the cscope binary
without an intervening shell.
closes: #20119
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: customlist completion cannot supply pum metadata
Solution: Allow each item returned by a customlist function to be
either a string or a Dict with keys "word", "abbr", "kind",
"menu" and "info" (Yasuhiro Matsumoto).
closes: #20100
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0432: blob to string conversion can be improved
Problem: blob to string conversion can be improved
Solution: Compute the output size up front and use a single alloc plus
mch_memmove() (Yasuhiro Matsumoto).
Replace per-byte ga_append/snprintf loops with bulk allocation and
mch_memmove in three hot paths: blob2string() (used by string()),
string_from_blob(), and the UTF-16/UCS path of f_blob2str(). For a
16 MiB blob, string(blob) is ~28x faster and blob2str() is ~2x faster.
Benchmark (16 MiB blob, 5 iterations, total seconds):
Problem: blob encoding can be improved
Solution: Speed up blob encoding by avoiding per-byte ga_append()
(Yasuhiro Matsumoto)
Replace the per-byte ga_append loop in the VAR_BLOB branch of
json_encode_item() with a single ga_grow for the worst case
(2 + 4 * blen) and direct writes through a local pointer. Also
read blob bytes through a local char_u* instead of going through
blob_get() for each byte.
Benchmark (1 MiB blob, 5 iterations, total seconds, median of 3 runs):
patch 9.2.0430: tests: Test_shortmess_F3() is flaky on MS-Windows
Problem: tests: Test_shortmess_F3() is flaky on MS-Windows
Solution: Increase the sleep to 3s (Yasuhiro Matsumoto)
On MS-Windows time_differs() treats mtime as unchanged unless st_mtime
differs by more than 1 second, so a 2-second sleep can fall short when
the two writes straddle a second boundary. Bump the non-nanotime sleep
to 3 seconds.
closes: #20117
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: tests: flaky screendump Test_smoothscroll_incsearch()
Solution: Replace screendump test by WaitForAssert()
(Yasuhiro Matsumoto)
VerifyScreenDump fails consistently on the macos-15-intel CI runner.
Replace the dump comparisons with assertions that verify the actual
invariant under test: that the visible buffer view stays unchanged
across the four incremental-search keystrokes (i.e. skipcol is not
reset). Drop the now-unused dump files.
closes: #20118
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0427: popup: opacity blend may leaks white bg color
Problem: popup: opacity blend may leaks white bg color
Solution: Add cterm color blending for 256 color terminals, use
COLOR_INVALID() macro to check for invalid color
(Yasuhiro Matsumoto)
When a textprop highlight only set gui=undercurl/guisp (no fg/bg), the
CTERMCOLOR sentinel was treated by hl_blend_attr() as a real near-white
color, leaking white bg onto textprop-covered cells under an opacity
popup or pum. Add a cterm color blending path that approximates blends
in the xterm 256-color palette using the gui RGB when available, so
opacity now has a visible effect even without 'termguicolors' (in
256-color terminals). Below 256 colors the blend is skipped.
Also document the requirement (GUI, 'termguicolors', or 256-color
terminal) and update existing pumopt/popupwin opacity screendumps to
reflect the new blended output.
closes: #20095
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0426: tests: still some flaky screendump tests
Problem: tests: still some flaky screendump tests
(James McCoy)
Solution: Replace flaky VerifyScreenDump checks with assert_* assertions
for Test_visual_block_scroll and Test_scrolloffpad_with_folds,
and remove the now-unused dump files, mark those tests as
flaky (which happened previously for screendump tests
automatically) (Yasuhiro Matsumoto).
fixes: #20096
related: #20095
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0424: popup: flicker when wildtrigger() refreshes the popup menu
Problem: popup: flicker when wildtrigger() refreshes the popup menu
Solution: Wrap the pum teardown and cmdline redraw in synchronized
terminal output (Yasuhiro Matsumoto).
Reduces flicker when wildtrigger() refreshes the popup on every
keystroke and the cmdline is wrapped: the un-scroll inside
update_screen() and the re-scroll inside redrawcmd() are emitted as
one atomic terminal update.
closes: #20081
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0423: popup: wrapped cmdline truncated with wildoptions=pum
Problem: popup: wrapped cmdline truncated with wildoptions=pum
Solution: Call msg_starthere() in redrawcmd() to reset lines_left
before each redraw (Yasuhiro Matsumoto).
redrawcmd() leaves lines_left at its previous value, which decrements
across successive redraws (e.g. when wildtrigger() refreshes the popup
on every keystroke) until 0, after which msg_no_more aborts drawing
the wrapped cmdline. Call msg_starthere() to reset it.
related: #20081
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0422: popup: leave stray char when scrollbar changes
Problem: popup: leave stray char when scrollbar changes
(Maxim Kim, after v9.2.0112)
Solution: refresh popup mask when scrollbar visibility changes
(Yasuhiro Matsumoto)
popup_adjust_position() set popup_mask_refresh only on geometry
changes, missing the case where w_has_scrollbar flips. After
popup_settext() shrinks the buffer enough that the scrollbar
disappears, the cell that held the old border / scrollbar was
never repainted, leaving stray characters.
fixes: #20092
closes: #20098
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime(doc): clarify separator cell on status line rows
- Expand hl-VertSplit / hl-VertSplitNC in syntax.txt to spell out which
character (space vs 'fillchars' "vert") and which highlight group
(StatusLine / StatusLineNC / VertSplit / VertSplitNC) are used at the
separator cell on each kind of screen row.
- Add cross references from hl-StatusLine and hl-StatusLineNC to
hl-VertSplit / hl-VertSplitNC.
The behavior itself is unchanged — see v9.2.0349 (c72196529) — but the
asymmetry reported in #20089 surprised users, so this aims to make the
spec discoverable from the highlight group docs.
closes: #20101
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0420: channel: cannot handle binary data via channel callbacks
Problem: channel: cannot handle binary data via channel callbacks
Solution: Add a blob channel mode that passes callback data as a Blob
(Yasuhiro Matsumoto).
closes: #20084
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0418: wildcards in expanded env vars reinterpreted by glob
Problem: With $d='[dir]', `:e $d/file.txt` opens the wrong file,
`:e $d/<Tab>` fails to complete, and `glob('$d/*')` returns
nothing. Wildcard characters inside expanded environment
variables get picked up by globbing again.
Solution: Turn the 4th parameter of expand_env_esc() from a bool into a
string of characters to escape in each expanded value. Callers
that pass the result to wildcard expansion should include
PATH_ESC_WILDCARDS in addition to " \t" (glepnir).
closes: #20053
Signed-off-by: glepnir <glephunter@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0417: completion: no support for "noinsert" with 'wildmode'
Problem: completion: no support for "noinsert" with 'wildmode' and
commandline completion
Solution: Add "noinsert" value to the 'wildmode' option, mirroring
'completeopt' "noinsert" behaviour (glepnir).
fixes: #16551
closes: #20080
Signed-off-by: glepnir <glephunter@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Maxim Kim [Wed, 29 Apr 2026 17:14:11 +0000 (17:14 +0000)]
patch 9.2.0416: Unix: filename completion splits at space for single-file Ex commands
Problem: SPACE_IN_FILENAME is defined on most platforms but not on Unix.
As a result, set_context_for_wildcard_arg() on Unix always resets the
completion pattern at white space for Ex commands that take a
single file argument.
Solution: Drop the SPACE_IN_FILENAME ifdef (Maxim Kim)
fixes: #18411
closes: #20090
Signed-off-by: Maxim Kim <habamax@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0415: Wrong behavior when executing register that ends in Insert mode
Problem: Wrong behavior when executing register that ends in Insert
mode from Ctrl-O (Emilien Breton)
Solution: Use :startinsert etc. to restore Insert mode after executing
the register contents (zeertzjq).
fixes: #20085
closes: #20091
Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0414: Flicker when drawing window separator and pum is shown
Problem: In a vertical split where the pum overlaps the windows vsep column,
background draws (vsep at cursor row, status line,
redraw_vseps, idle ins_redraw) can write into cells that are
covered by the pum, because skip_for_popup() only protects
those cells while pum_will_redraw is set.
Solution: In skip_for_popup(), also skip cells under a visible pum when
the current draw is not the pum itself (screen_zindex
POPUPMENU_ZINDEX). Exclude the wildmenu pum (MODE_CMDLINE):
while the cmdline grows, pum_row is briefly stale and
protecting those cells would blank a cell of the wrapped
cmdline row (Yasuhiro Matsumoto).
closes: #20093
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0413: Scrolling wrong with 'splitkeep' when changing 'cmdheight'
Problem: Cursor is not adjusted when 'cmdheight' is changed to cover
the cursor with 'splitkeep' ~= "cursor".
Solution: Handle window resize for 'splitkeep' after changing 'cmdheight'.
Ensure previous window height is set when changing 'splitkeep'
(Luuk van Baal).
closes: #20043
Signed-off-by: Luuk van Baal <luukvbaal@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0412: channel: term_start() out_cb/err_cb no longer deliver raw chunks
Problem: channel: term_start() out_cb/err_cb no longer deliver raw
chunks (regression from patch 9.2.0224, breaks callers like
vim-fugitive that parse multi-line output)
(D. Ben Knoble, after v9.2.0224)
Solution: Remove the PTY-specific per-line splitting in
may_invoke_callback() so RAW callbacks again receive the
raw chunk as returned by read(), preserving embedded NL.
If per-line handling is desired, the callback must split
"msg" on NL and strip the trailing CR itself; document
this behavior in term_start(). Replace
Test_term_start_cb_per_line() with
Test_term_start_cb_raw_chunk() to verify the raw-chunk
contract.
fixes: #20041
closes: #20045
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-Authored-By: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0411: tabpanel: no Vim script functions for the tabpanel
Problem: tabpanel: no Vim script functions for the tabpanel
Solution: Add tabpanel_getinfo() and tabpanel_scroll()
(Yasuhiro Matsumoto).
tabpanel_getinfo() returns a dict describing the tabpanel (align,
columns, scrollbar, offset, total, max_offset).
tabpanel_scroll(n) scrolls the tabpanel by n rows (positive for
down, negative for up). With {absolute: 1} the argument is used as
the new absolute offset instead of a delta. The offset is clamped to
the valid range; returns true when it actually changes.
closes: #20056
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0410: test suite races when run with parallel make
Problem: Running "make test" with -jN causes spurious failures because
the old-style tests share filenames (test.ok, test.out, X*,
viminfo) in the working directory.
Solution: Add .NOTPARALLEL to the testdir Makefile to prevent parallel
execution of tests (Jesse Rosenstock).
closes: #20082
Co-authored-by: Gemini Signed-off-by: Jesse Rosenstock <jmr@google.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0408: Insert-mode <Cmd> edits can corrupt undo
Problem: A <Cmd> command in Insert mode can edit the current buffer,
e.g., with setline(). That edit appends to the current undo
block, but Insert mode does not know that the cursor line may
need to be saved again before the next typed edit. If the next
typed edit is a <BS> at the start of a line, it can join away
the line that was changed by the <Cmd> command before Insert
mode saves that updated line. The newest undo entry can then
still refer to the joined-away line, so undo sees a range past
the end of the buffer and fails with E438.
Solution: If a <Cmd> command in Insert mode changes the buffer, set
ins_need_undo so stop_arrow() refreshes Insstart. This lets
the next edit properly decide whether a new undo entry is
needed (Jaehwang Jung)
closes: #20087
AI-assisted: Codex
Signed-off-by: Jaehwang Jung <tomtomjhj@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0407: tabpanel: A few issues with the tabpanel
Problem: Several issues around the tabpanel scrollbar:
1. :set tabpanelopt= completion did not offer "scroll" and
"scrollbar".
2. gt/gT and other tab switches did not update the scrollbar
thumb; the current tab could move outside the visible
panel range without the view following.
3. When tpl_scroll_offset was at its maximum, the thumb's
bottom did not reach the last screen row due to integer
truncation in thumb_top (e.g. 31 tabs on 24 rows + :tablast
left a one-row gap).
4. For align:right the scrollbar was drawn on the panel's
left edge (adjacent to the buffer area), which breaks the
common convention that a vertical scrollbar sits on the
right.
Solution: - Add "scroll" and "scrollbar" to the 'tabpanelopt' expansion
list. Cover the completion in test_options.vim and extend
util/gen_opt_test.vim with the new valid/invalid values;
drop the now-redundant acceptance test from
test_tabpanel.vim.
- In draw_tabpanel(), remember the last-drawn curtab and,
when it changes, adjust tpl_scroll_offset so curtab_row
falls inside [offset, offset + Rows). Mouse wheel and
drag leave curtab unchanged, so the user's chosen offset
is preserved.
- In draw_tabpanel_scrollbar(), compute thumb_top as
(Rows - thumb_height) * tpl_scroll_offset
/ (tpl_total_rows - Rows), mirroring the mapping already
used by tabpanel_drag_scrollbar(). This guarantees the
thumb's bottom reaches the last row at the maximum offset.
- In draw_tabpanel(), place the scrollbar at the tabpanel's
right edge for both align:left and align:right (previously
align:right put it on the panel's left edge next to the
vertical separator). For align:right this means the
scrollbar now sits at the screen's right edge.
- Update :h tabpanel-scroll to describe the new, align-
independent placement.
- Add Test_tabpanel_scrollbar_follows_curtab() and
Test_tabpanel_scrollbar_reaches_bottom() to exercise the
regressions fixed by items 2 and 3.
closes: #20052
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Hirohito Higashi <h.east.727@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0406: VisualNOS not used when Wayland selection ownership lost
Problem: VisualNOS not used when Wayland selection ownership lost
(lilydjwg)
Solution: Don't require X_DISPLAY != NULL to use VisualNOS
(Shane Harper).
Problem: Vim9: def function sandbox bypass
(Srinivas Piskala Ganesh Babu)
Solution: Check for sandbox flag in call_user_func() and call_dfunc()
when executing Vim9 script functions
patch 9.2.0402: pum: opacity not applied to wildmenu pum
Problem: pum: opacity not applied to wildmenu pum
Solution: Call pum_call_update_screen() in cmdline_pum_display() when
opacity is set, fix flicker by checking against expected row
(Yasuhiro Matsumoto).
closes: #20072
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: tests: still a few flaky tests
Solution: Add WaitForAssert to test_messages.vim, use a smaller terminal
window for test_tabpanel, add TermWait() in test_messages
to handle DECQRM messages.
patch 9.2.0400: sandbox callbacks selected through 'complete'
Problem: Modeline-tainted 'complete' values can invoke completion
callbacks outside the sandbox.
Solution: Enter the sandbox for both 'complete' callback phases and add
a regression test (Barrett Ruth)
closes: #20078
Signed-off-by: Barrett Ruth <br.barrettruth@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0398: MS-Windows: missing strptime() support
Problem: MS-Windows: missing strptime() support
Solution: Port NetBSD's strptime fallback to Vim
(Yasuhiro Matsumoto).
The MSVC and MinGW C runtimes do not provide strptime(), so the
strptime() builtin was unavailable on Windows. Port NetBSD's
lib/libc/time/strptime.c (rev 1.67) and compile it into the Windows
builds. The BSD 2-clause notice from the original is preserved in the
file. Windows-specific adjustments: English-only locale tables, the
fromzone()/tzalloc() path is stubbed out (no IANA tzfile loader on
Windows), and tm_gmtoff / tm_zone stores are elided.
Also call tzset() before mktime() in f_strptime() so changes to \$TZ
are honored.
Skip the POSIX DST TZ assertion in Test_strptime() on MS-Windows since
the CRT tzset() does not parse POSIX TZ strings with DST rules.
closes: #20054
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
patch 9.2.0397: tabpanel: double-click opens a new tab
Problem: tabpanel: double-click opens a new tab page
Solution: Do not create a new tab page when using a double click
(Yasuhiro Matsumoto).
The tabpanel click handler inherited the tabline behavior where a
double-click opens a new, empty tab page. Unlike the tabline, the
tabpanel has no "empty area": every row maps to some tab, so this
fires on any double-click in the tabpanel and can generate stray
empty tabs. The behavior is also not documented for the tabpanel.
Skip the new-tab branch when the click originated in the tabpanel
and fall through to the regular tab-switch path instead. The
tabline behavior is unchanged.
runtime(javascript): Fix regex highlighting after `(`
- Fix regex highlighting after opening parens, javascriptParens was
matching later. Fixes issue #20069.
- Add missing regex flags.
- Mark the file as unmaintained. Thanks Claudio for all your work.
closes: #20076
Signed-off-by: Doug Kearns <dougkearns@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime(help): fix wrong check for existing HelpComplete function
To check for an existing HelpComplete function, exists('*HelpComplete')
should be used, as exists('HelpComplete') still returns 0 after sourcing
the ftplugin.
closes: #20073
Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime(algol68): Add new syntax file, ftplugin and filetype detection
- Add a syntax file update to Neville Dempsey's long-serving version
- Add a new rudimentary ftplugin
- Add filetype detection
Changes to the syntax file include:
- improved prelude, number and symbol highlighting
- prelude highlighting tests
- updated boiler plate
Note that these runtime files currently target Algol 68 Genie employing
the default UPPER stropping regime. Support for GNU Algol 68 should
also be usable with the UPPER stropping regime, although somewhat less
complete. Full support for the SUPPER stropping regime in GNU Algol 68
is also planned.
patch 9.2.0396: tests: Test_error_callback_terminal is flaky on macOS
Problem: tests: Test_error_callback_terminal is flaky on macOS
Solution: Use WaitForAssert() to make it more reliable
(Yasuhiro Matsumoto).
term_wait() only waits for terminal screen updates and does not
guarantee that the err_io 'pipe' callback has fired, so on macOS
the assert_match() against g:error frequently runs before sh has
written "sh: XXXX: not found", causing the test to flake.
Replace term_wait() + assert_match() with WaitForAssert() so each
assertion polls until the callback delivers the expected output.
Also defer sending "exit" until the stderr message has been seen,
to avoid losing the stderr write to the exit race.
closes: #20075
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
D. Ben Knoble [Sun, 26 Apr 2026 08:33:59 +0000 (08:33 +0000)]
patch 9.2.0395: tests: Test_backupskip() may read from $HOME
Problem: tests: Test_backupskip() may read from $HOME
Solution: Set $HOME to an empty value, use --clean
(D Ben Knoble)
Even though we unset HOME, we can see via scriptnames that user files
are still sourced! One of my installed plugins warns when not compiled
with +python3, so this test has a "press Enter" prompt.
Use `--clean` like most other GetVimProg()'s do to fix it. Some tests
use `system()` instead, but that turns this test into a failure rather
than passing; I'm not sure why other tests don't suffer from this.
To prove to ourselves, we can use code like this:
diff --git i/src/testdir/test_options.vim w/src/testdir/test_options.vim
index a408e20e1..044364a54 100644
--- i/src/testdir/test_options.vim
+++ w/src/testdir/test_options.vim
@@ -1179,6 +1179,7 @@ func Test_backupskip()
" P_NODUP). Run this in a separate instance and write v:errors in a file,
" so that we see what happens on startup.
let after =<< trim [CODE]
+ call writefile([execute('scriptnames')], 'foo')
let bsklist = split(&backupskip, ',')
call assert_equal(uniq(copy(bsklist)), bsklist)
call writefile(['errors:'] + v:errors, 'Xtestout')
@@ -1196,7 +1197,7 @@ func Test_backupskip()
" unset $HOME, so that it won't try to read init files
let saveenv['HOME'] = getenv("HOME")
call setenv('HOME', v:null)
- exe 'silent !' . cmd
+ exe 'silent !' . cmd .. ' --cmd "echo &rtp"'
call assert_equal(['errors:'], readfile('Xtestout'))
" restore environment variables
Here, that causes "foo" to include a bunch of files under ~/.vim. I'm
not sure why this happens, but lets paper over it for the test.
We can also tell that (orthogonal to --clean) setting HOME='' works too.
Let's do that in addition since unsetting HOME isn't quite enough.
closes: #20051
Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>