Problem: not possible to anchor specific lines in diff mode
Solution: Add support for the anchoring lines in diff mode using the
'diffanchor' option (Yee Cheng Chin).
Adds support for anchoring specific lines to each other while viewing a
diff. While lines are anchored, they are guaranteed to be aligned to
each other in a diff view, allowing the user to control and inform the
diff algorithm what the desired alignment is. Internally, this is done
by splitting up the buffer at each anchor and run the diff algorithm on
each split section separately, and then merge the results back for a
logically consistent diff result.
To do this, add a new "diffanchors" option that takes a list of
`{address}`, and a new "diffopt" option value "anchor". Each address
specified will be an anchor, and the user can choose to use any type of
address, including marks, line numbers, or pattern search. Anchors are
sorted by line number in each file, and it's possible to have multiple
anchors on the same line (this is useful when doing multi-buffer diff).
Update documentation to provide examples.
This is similar to Git diff's `--anchored` flag. Other diff tools like
Meld/Araxis Merge also have similar features (called "synchronization
points" or "synchronization links"). We are not using Git/Xdiff's
`--anchored` implementation here because it has a very limited API
(it requires usage of the Patience algorithm, and can only anchor
unique lines that are the same across both files).
Because the user could anchor anywhere, diff anchors could result in
adjacent diff blocks (one block is directly touching another without a
gap), if there is a change right above the anchor point. We don't want
to merge these diff blocks because we want to line up the change at the
anchor. Adjacent diff blocks were first allowed when linematch was
added, but the existing code had a lot of branched paths where
line-matched diff blocks were handled differently. As a part of this
change, refactor them to have a more unified code path that is
generalized enough to handle adjacent diff blocks correctly and without
needing to carve in exceptions all over the place.
closes: vim/vim#176150d9160e11c
Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
Problem: The ruler disappears after typing the second character during
insert mode completion, even when completion messages are
suppressed ('shortmess' includes "c"). This makes the UI
appear inconsistent.
Solution: Ensure the ruler is restored during screen redraw when popup
completion is active (Girish Palya).
Notes:
No new tests were added, as existing screen dump tests were updated to
reflect the corrected behavior.
closes: vim/vim#17770824286c9a7
Nvim already behaves correctly as the popup menu is a separate grid in
the compositor.
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: Vim crashes during omnifunc completion inside the command-line
window ("q:") if the completion item attempts to open an "info"
preview window. This leads to a failed assert during execution.
Solution: Avoid opening preview windows while inside the command-line
window to prevent the crash (Girish Palya).
closes: vim/vim#17764e4fdb1e4e7
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: string handling in cmdexpand.c can be improved
Solution: Improve string manipulation in cmdexpand.c (John Marriott).
This PR does the following:
In cmdline_fuzzy_completion_supported():
- replace the series of if tests with a switch
In expand_shellcmd_onedir():
- move the code to concatenate path and pattern to expand_shellcmd().
This allows us to slightly simplify the argument list to pass the fully
pathed pattern and the length of the path in the pattern (0 if no path)
- factor out calls to STRMOVE()
In expand_shellcmd():
- factor out calls to STRMOVE() in the first for loop.
- reorganise the second for loop by:
a) only calling vim_strchr() if s is not at the end of the string
b) making sure that when the path and pattern are concatenated they fit
inside buf
c) concatenating path and pattern and pass to expand_shellcmd_onedir()
In globpath():
- slightly improve logic that determines if the complete path will fit
inside the buffer
In f_getcompletion():
- replace the series of if tests with a switch
- factor out calls to STRLEN()
In copy_substring_from_pos():
- factor out the call to STRLEN()
closes: vim/vim#17742393d398247
Co-authored-by: John Marriott <basilisk@internode.on.net>
Problem: completion: repeated insertion and deletion of complete
functions
Solution: Remove unnecessary insertion and deletion of leader text
('compl_orig_text') during expansion of function present in
'complete' option (Girish Palya).
closes: vim/vim#1773878b10eab6c
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem:
Cannot use `nvim_open_term()` to pipe terminal scrollback > 100000
Solution:
Increase scrollback limit to 1000000
If there's no technical consequences of doing this, can be set even
higher in the future.
Problem: completion: messages don't respect 'shm' setting
Solution: Turn off completion messages when 'shortmess' includes "c"
(Girish Palya).
`:set shortmess+=c` is intended to reduce noise during completion by
suppressing messages.
Previously, some completion messages still appeared regardless of this setting.
This change ensures that **all** completion-related messages are suppressed
when `'c'` is present in `'shortmess'`.
Not entirely sure if the original behavior was intentional. If there's a
reason certain messages were always shown, feel free to close this without
merging.
closes: vim/vim#17737fe1d3c8af7
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem:
Nvim depends on netrw to download/request URL contents.
Solution:
- Add `vim.net.request()` as a thin curl wrapper:
- Basic GET with --silent, --show-error, --fail, --location, --retry
- Optional `opts.outpath` to save to a file
- Operates asynchronously. Pass an `on_response` handler to get the result.
- Add integ tests (requires NVIM_TEST_INTEG to be set) to test success
and 404 failure.
- Health check for missing `curl`.
- Handle `:edit https://…` using `vim.net.request()`.
API Usage:
1. Asynchronous request:
vim.net.request('https://httpbingo.org/get', { retry = 2 }, function(err, response)
if err then
print('Fetch failed:', err)
else
print('Got body of length:', #response.body)
end
end)
2. Download to file:
vim.net.request('https://httpbingo.org/get', { outpath = 'out_async.txt' }, function(err)
if err then print('Error:', err) end
end)
3. Remote :edit integration (in runtime/plugin/net.lua) fetches into buffer:
:edit https://httpbingo.org/get
Problem:
The "gitsigns" plugin runs `vim.diff` in a thread (`uv.new_work`), but
`vim.diff` is nil in that context:
Lua callback:
…/gitsigns.nvim/lua/gitsigns/diff_int.lua:30: bad argument #1 to 'decode' (string expected, got nil)
stack traceback:
[C]: in function 'decode'
…/gitsigns.nvim/lua/gitsigns/diff_int.lua:30: in function <…/gitsigns.nvim/lua/gitsigns/diff_int.lua:29>
Luv thread:
…/gitsigns.nvim/lua/gitsigns/diff_int.lua:63: attempt to call field 'diff' (a nil value)
Solution:
Revert the `stdlib.c` change (set `vim.diff` instead of `vim._diff`).
Problem: tests: string options in gen_opt_test.vim aren't fully sorted.
Solution: Sort the string options alphabetically. Also make description
of 'maxsearchcount' start with lower-case for consistency with
other options, update documentation for searchcount().
closes: vim/vim#177207306e8fcdb
Problem: When 'winminheight' is zero and the window height is set to
zero, the actual height is clamped whereas the stored config
value is not. Reciprocal window configuration through
nvim_win_get_config() then results in an error.
Solution: Also clamp the stored dimensions in the window config.
Problem: The maximum search count uses a hard-coded value of 99
(Andres Monge, Joschua Kesper)
Solution: Make it configurable using the 'maxsearchcount' option.
related: vim/vim#8855fixes: vim/vim#17527closes: vim/vim#17695b7b7fa04bf
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: When winblend=100 is set on floating windows with transparent
background, the desktop background is not visible through the window.
Solution: Add special case to preserve transparency (-1) when blend
ratio is 100% and background was originally transparent.
Problem: winborder option only supported predefined styles and lacked support for custom border characters.
Solution: implement parsing for comma-separated list format that allows specifying 8 individual border characters (topleft, top, topright, right, botright, bottom, botleft, left).
Many terminals now include support for OSC 52 in their Primary Device
Attributes (DA1) response. This is preferable to using XTGETTCAP because
DA1 is _much_ more broadly supported.
Problem: Shada jumplist entries still include entries from e.g. 'nobuflisted' buffers.
Solution: Check `ignore_buf()` before adding jumplist entries, followup to b98eefd8.
Co-authored-by: Luuk van Baal <luukvbaal@gmail.com>
Problem: Hardcoded highlight IDs for ext_messages/cmdline output need
to be adjusted everytime a builtin highlight group is added.
Solution: Store a global map of default highlights through nvim_get_hl()
and fetch missing (custom) highlight groups through synIDattr().
Use more compact formatting for screen:expect().
Problem: completion: crash with getcompletion()
(zeertzjq)
Solution: Don't set may_expand_pattern in f_getcompletion(),
unset may_expand_pattern() once it is not longer needed
(Girish Palya).
fixes: vim/vim#17680closes: vim/vim#17686f2ec8d4afc
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: completion: search completion match may differ in case
(techntools)
Solution: add "exacttext" to 'wildoptions' value (Girish Palya)
This flag does the following:
exacttext
When this flag is present, search pattern completion
(e.g., in |/|, |?|, |:s|, |:g|, |:v|, and |:vim|)
shows exact buffer text as menu items, without
preserving regex artifacts like position
anchors (e.g., |/\<|). This provides more intuitive
menu items that match the actual buffer text. However,
searches may be less accurate since the pattern is not
preserved exactly.
By default, Vim preserves the typed pattern (with
anchors) and appends the matched word. This preserves
search correctness, especially when using regular
expressions or with 'smartcase' enabled. However, the
case of the appended matched word may not exactly
match the case of the word in the buffer.
fixes: vim/vim#17654closes: vim/vim#1766793c2d5bf7f
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: Unable to tell whether msg_history_show event is emitted for a
:messages or g< command.
Solution: Add "prev_cmd" argument that is set to true for g<.
Problem: When using `/` or `?` in command-line mode with 'ignorecase' and
'smartcase' enabled, the completion menu could show items that
don't actually match any text in the buffer due to case mismatches
Solution: Instead of validating menu items only against the user-typed
pattern, the new logic also checks whether the completed item
matches actual buffer content. If needed, it retries the match
using a lowercased version of the candidate, respecting
smartcase semantics.
closes: vim/vim#17665af22007784
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem:
The `nvim_get_keymap()` function is missing the `lhsrawalt` field in its response for mappings with an alternate key representation. This makes its return value inconsistent with its documented `maparg()`-like structure and its formal type definition.
Solution:
Corrects the `keymap_array` function to pass the alternate mapping keys (`current_maphash->m_alt->m_keys`) to `mapblock_fill_dict`. The argument responsible for this was previously hardcoded to `NULL`.
For example, for a mapping of `<C-x>`, the API will now correctly return both `lhsraw` (`<80><fc>^DX`) and `lhsrawalt` (the alternate form, e.g., `^X`).
Problem: When 'wildmode' is set to include "noselect", the popup menu (pum)
incorrectly retained its scroll position when reopened. This
meant that after scrolling down through the menu with `<C-n>`,
reopening the menu (e.g., by retyping the command and
triggering completion again) would show the menu starting from
the previously scrolled position, rather than from the top.
This could confuse users, as the first visible item would not
be the first actual match in the list.
Solution: Ensure that the popup menu resets its scroll position to the
top when reopened (Girish Palya).
closes: vim/vim#176730cd7f3536b
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: getcompletiontype() crashes when no completion is available
(after v9.1.1509).
Solution: Don't call set_expand_context() (zeertzjq)
fixes: vim/vim#17681closes: vim/vim#17684e2c0f81dd0
Problem:
Coverity reports string null termination issue:
*** CID 569464: Memory - string handling (STRING_NULL)
/src/nvim/runtime.c: 1374 in ExpandRTDir_int()
1372 if (flags & DIP_START) {
1373 memcpy(tail - 15, "pack/*/start/*/", 15); // NOLINT
>>> CID 569464: Memory - string handling (STRING_NULL)
>>> Passing unterminated string "tail - 15" to "globpath", which expects a null-terminated string.
1374 globpath(p_pp, tail - 15, gap, glob_flags, expand_dirs);
Similar issues occur at lines 1376, 1381, and 1383 where memcpy()
constructs strings passed to globpath() without null termination.
Solution:
Replace dangerous pointer arithmetic and memcpy() with direct snprintf()
construction of complete search paths. This eliminates the need for
buffer reuse through pointer offsets and ensures all strings passed to
globpath() are properly null-terminated.
vim-patch:9.1.1515: Coverity complains about potential unterminated strings
Problem: tests: no test that 'incsearch' is updated after accepting
search completion.
Solution: Add a test case (zeertzjq).
closes: vim/vim#1768208e5b128b8
Problem: Patch 9.1.1505 was not good
Solution: Revert "patch 9.1.1505: not possible to return completion type
for :ex command" and instead add the getcompletiontype()
function (Hirohito Higashi).
related: vim/vim#17606closes: vim/vim#1766296b3ef2389
Cherry-pick Test_multibyte_expression() from Vim, as it passes.
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Shougo Matsushita <Shougo.Matsu@gmail.com>
Problem: not possible to return command-line completion type for :ex
command
Solution: make getcmdcompltype() accept an optional and return the
command-line completion for that arg (Shougo Matsushita).
closes: vim/vim#176065d2354fc07
Co-authored-by: Shougo Matsushita <Shougo.Matsu@gmail.com>
Problem: completion: can only complete from keyword characters
Solution: remove this restriction, allow completion functions when
called from i_CTRL-N/i_CTRL-P to be triggered from non-keyword
characters (Girish Palya)
Previously, functions specified in the `'complete'` option were
restricted to starting completion only from keyword characters (as
introduced in PR 17065). This change removes that restriction.
With this change, user-defined functions (e.g., `omnifunc`, `userfunc`)
used in `'complete'` can now initiate completion even when triggered
from non-keyword characters. This makes it easier to reuse existing
functions alongside other sources without having to consider whether the
cursor is on a keyword or non-keyword character, or worry about where
the replacement should begin (i.e., the `findstart=1` return value).
The logic for both the “collection” and “filtering” phases now fully
respects each source’s specified start column. This also extends to
fuzzy matching, making completions more predictable.
Internally, this builds on previously merged infrastructure that tracks
per-source metadata. This PR focuses on applying that metadata to
compute the leader string and insertion text appropriately for each
match.
Also, a memory corruption has been fixed in prepare_cpt_compl_funcs().
closes: vim/vim#17651ba11e78f1d
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: Search completion may use invalid memory (after 9.1.1490).
Solution: Don't get two line pointers at the same time (zeertzjq).
closes: vim/vim#176615e34eec6f8
Problem: manually comparing positions on buffer
(after v9.1.1490)
Solution: use the LTOREQ_POS() macro, fix a few other minor style issues
(glepnir)
closes: vim/vim#176297cf35bc1be
Co-authored-by: glepnir <glephunter@gmail.com>
Problem: 'wildchar' does not work in search contexts
Solution: implement search completion when 'wildchar' is typed
(Girish Palya).
This change enhances Vim's command-line completion by extending
'wildmode' behavior to search pattern contexts, including:
- '/' and '?' search commands
- ':s', ':g', ':v', and ':vim' commands
Completions preserve the exact regex pattern typed by the user,
appending the completed word directly to the original input. This
ensures that all regex elements — such as '<', '^', grouping brackets
'()', wildcards '\*', '.', and other special characters — remain intact
and in their original positions.
---
**Use Case**
While searching (using `/` or `?`) for lines containing a pattern like
`"foobar"`, you can now type a partial pattern (e.g., `/f`) followed by
a trigger key (`wildchar`) to open a **popup completion menu** showing
all matching words.
This offers two key benefits:
1. **Precision**: Select the exact word you're looking for without
typing it fully.
2. **Memory aid**: When you can’t recall a full function or variable
name, typing a few letters helps you visually identify and complete the
correct symbol.
---
**What’s New**
Completion is now supported in the following contexts:
- `/` and `?` search commands
- `:s`, `:g`, `:v`, and `:vimgrep` ex-commands
---
**Design Notes**
- While `'wildchar'` (usually `<Tab>`) triggers completion, you'll have
to use `<CTRL-V><Tab>` or "\t" to search for a literal tab.
- **Responsiveness**: Search remains responsive because it checks for
user input frequently.
---
**Try It Out**
Basic setup using the default `<Tab>` as the completion trigger:
```vim
set wim=noselect,full wop=pum wmnu
```
Now type:
```
/foo<Tab>
```
This opens a completion popup for matches containing "foo".
For matches beginning with "foo" type `/\<foo<Tab>`.
---
**Optional: Autocompletion**
For automatic popup menu completion as you type in search or `:`
commands, include this in your `.vimrc`:
```vim
vim9script
set wim=noselect:lastused,full wop=pum wcm=<C-@> wmnu
autocmd CmdlineChanged [:/?] CmdComplete()
def CmdComplete()
var [cmdline, curpos, cmdmode] = [getcmdline(), getcmdpos(),
expand('<afile>') == ':']
var trigger_char = '\%(\w\|[*/:.-]\)$'
var not_trigger_char = '^\%(\d\|,\|+\|-\)\+$' # Exclude numeric range
if getchar(1, {number: true}) == 0 # Typehead is empty, no more
pasted input
&& !wildmenumode() && curpos == cmdline->len() + 1
&& (!cmdmode || (cmdline =~ trigger_char && cmdline !~
not_trigger_char))
SkipCmdlineChanged()
feedkeys("\<C-@>", "t")
timer_start(0, (_) => getcmdline()->substitute('\%x00', '',
'ge')->setcmdline()) # Remove <C-@>
endif
enddef
def SkipCmdlineChanged(key = ''): string
set ei+=CmdlineChanged
timer_start(0, (_) => execute('set ei-=CmdlineChanged'))
return key == '' ? '' : ((wildmenumode() ? "\<C-E>" : '') .. key)
enddef
**Optional: Preserve history recall behavior**
cnoremap <expr> <Up> SkipCmdlineChanged("\<Up>")
cnoremap <expr> <Down> SkipCmdlineChanged("\<Down>")
**Optional: Customize popup height**
autocmd CmdlineEnter : set bo+=error | exec $'set ph={max([10,
winheight(0) - 4])}'
autocmd CmdlineEnter [/?] set bo+=error | set ph=8
autocmd CmdlineLeave [:/?] set bo-=error ph&
```
closes: vim/vim#175706b49fba8c8
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: Unused assignment in ex_uniq() (after v9.1.1476)
Solution: Remove the assignment and the wrong comments above
(zeertzjq).
closes: vim/vim#17596fc378a88d8
Problem: no easy way to deduplicate text
Solution: add the :uniq ex command
(Hirohito Higashi)
closes: vim/vim#1753874f0a77bb9
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>