Problem: runtime(netrw): command injection possible via crafted
directory names in NetrwMaps() (Christopher Lusk)
Solution: Temporarily remove B flag in NetrwMaps() to prevent command
injection
Signed-off-by: Christian Brabandt <cb@256bit.org>
includes a new zig_cc file to catch warnings
closes: #20198
Signed-off-by: yilisharcs <yilisharcs@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: the bookmarks list can have duplicate entries, more often
in win32 (due to mixed slashes and capitalization) and when
g:netrw_keepdir=0 (which could introduce relative paths).
Duplicate entries could be: C:\foo\BAR\baz.file
c:\foo\bar\baz.file
c:/foo\BAR/baz.file
BAR/baz.file
Solution: Normalize the paths and make sure they are always absolute
(J. Paulo Seibt).
closes: #20194
Signed-off-by: J. Paulo Seibt <jpseibt@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: No way to hook into put commands
(yochem)
Solution: Introduce TextPutPre and TextPutPost autocommands
(Foxe Chen).
fixes: #18701closes: #20144
Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
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>
Problem: modeline: foldmarker cannot be set with modelinestrict
(Lyderic Landry, after v9.2.0350)
Solution: Add foldmarker option to the whitelist
fixes: #20028closes: #20174
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: runtime(netrw): bookmarking directory uses current dir
Solution: Correctly handle netrw actual directory (J. Paulo Seibt)
fixes: #10481closes: #20169
Signed-off-by: J. Paulo Seibt <jpseibt@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: Crash with invalid shellredir/shellpipe value
(bfredl)
Solution: Validate the option and allow only a single "%s".
fixes: #20157closes: #20159
Signed-off-by: Christian Brabandt <cb@256bit.org>
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: #20163closes: #20164
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
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>
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: #20155closes: #20158
Signed-off-by: zeertzjq <zeertzjq@outlook.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).
fixes: #4
fixes: #648
fixes: #19578closes: #19581closes: #20111
Signed-off-by: magnus-rattlehead <guranjakustivi@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
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>
Problem: Cannot set 'path' option via modeline (zeertzjq, after v9.2.0435)
Solution: Revert the part that disallows setting 'path' via modeline.
closes: #20137
Signed-off-by: Christian Brabandt <cb@256bit.org>
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)
Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-hwg5-3cxw-wvvg
Supported by AI.
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>
Problem: popup: no opacity support for completepopup/previewpopup
Solution: Add support opacity: suboption for the 'completeopt'.
Accepts opacity:0-100 with the same semantics as popup_create()'s
opacity option, allowing the info / preview popup to blend with
the background.
closes: #20099
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
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>
- 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>
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>
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>
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: #16551closes: #20080
Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
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: #18411closes: #20090
Signed-off-by: Maxim Kim <habamax@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
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: #20041closes: #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>
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>
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>
Problem: when jumping to tags, will open URLs
(Srinivas Piskala Ganesh Babu)
Solution: Disallow trying to open remote files.
closes: #20068
Supported by AI
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: redraw_listener_add() does not check secure flag
Solution: Check for check_secure() in f_redraw_listener_add()
closes: #20070
Signed-off-by: Christian Brabandt <cb@256bit.org>
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>