Problem: PMenu selection broken with multi-line selection and limits
(Maxim Kim)
Solution: update completion match index when limiting the completion
sources (Girish Palya)
fixes: vim/vim#17394closes: vim/vim#174016c40df09e0
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: scheduling of complete function can be improved
Solution: call user completion functions earlier when just determining
the insertion column (Girish Palya)
This change improves the scheduling behavior of async user-defined
completion functions (such as `F{func}`, `F`, or `'o'` values in the
`'complete'` option), particularly benefiting LSP clients.
Currently, these user functions are invoked twice:
1. First with `findstart = 1` to determine the completion start
position.
2. Then with `findstart = 0` to retrieve the actual matches.
Previously, both calls were executed back-to-back. With this change, the
first call (`findstart = 1`) is performed earlier—before any matches are
gathered from other sources.
This adjustment gives event-driven completion sources (e.g., LSP
clients) more time to send their requests while Vim concurrently
collects matches from other sources like the current buffer.
Not sure about the real-world performance gains, but this approach
should, in theory, improve responsiveness and reduce latency for
asynchronous completions.
To test, try using yegappan LSP client:
```vim
set cpt+=o^10
autocmd VimEnter * g:LspOptionsSet({ autoComplete: false, omniComplete: true })
```
If you prefer to use 'native' auto-completion (without plugins), try the
following configuration:
```vim
set cot=menuone,popup,noselect,nearest
autocmd TextChangedI * InsComplete()
def InsComplete()
if getcharstr(1) == '' && getline('.')->strpart(0, col('.') - 1) =~ '\k$'
SkipTextChangedI()
feedkeys("\<c-n>", "n")
endif
enddef
inoremap <silent> <c-e> <c-r>=<SID>SkipTextChangedI()<cr><c-e>
inoremap <silent> <c-y> <c-r>=<SID>SkipTextChangedI()<cr><c-y>
def SkipTextChangedI(): string
set eventignore+=TextChangedI
timer_start(1, (_) => {
set eventignore-=TextChangedI
})
return ''
enddef
inoremap <silent><expr> <tab> pumvisible() ? "\<c-n>" : "\<tab>"
inoremap <silent><expr> <s-tab> pumvisible() ? "\<c-p>" : "\<s-tab>"
```
closes: vim/vim#1739698c29dbfd1
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: using f-flag in 'complete' conflicts with Neovims filename
completion (glepnir, after v9.1.1301).
Solution: use upper-case "F" flag for completion functions
(Girish Palya).
fixes: vim/vim#17347closes: vim/vim#1737814f6da5ba8
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: compile warning about uninitialized value
(Tony Mechelynck, after v9.1.1311)
Solution: initialize variable on declaration
b53d4fb63e
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: completion: not possible to limit number of matches
Solution: allow to limit the matches for 'complete' sources by using the
"{flag}^{limit}" notation (Girish Palya)
This change extends the 'complete' option to support limiting the
number of matches returned from individual completion sources.
**Rationale:** In large files, certain sources (such as the current
buffer) can generate an overwhelming number of matches, which may cause
more relevant results from other sources (e.g., LSP or tags) to be
pushed out of view. By specifying per-source match limits, the
completion menu remains balanced and diverse, improving visibility and
relevance of suggestions.
A caret (`^`) followed by a number can be appended to a source flag to
specify the maximum number of matches for that source. For example:
```
:set complete=.^9,w,u,t^5
```
In this configuration:
- The current buffer (`.`) will return up to 9 matches.
- The tag completion (`t`) will return up to 5 matches.
- Other sources (`w`, `u`) are not limited.
This feature is fully backward-compatible and does not affect behavior
when the `^count` suffix is not used.
The caret (`^`) was chosen as the delimiter because it is least likely
to appear in file names.
closes: vim/vim#170870ac1eb3555
Cherry-pick test_options.vim change from patch 9.1.1325.
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: Coverity warns about using uninitialized value
(Coverity, Tony Mechelynck, after v9.1.1301)
Solution: initialize callback pointer to NULL
d2079cff48
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: completion: cannot configure completion functions with
'complete'
Solution: add support for setting completion functions using the f and o
flag for 'complete' (Girish Palya)
This change adds two new values to the `'complete'` (`'cpt'`) option:
- `f` – invokes the function specified by the `'completefunc'` option
- `f{func}` – invokes a specific function `{func}` (can be a string or `Funcref`)
These new flags extend keyword completion behavior (e.g., via `<C-N>` /
`<C-P>`) by allowing function-based sources to participate in standard keyword
completion.
**Key behaviors:**
- Multiple `f{func}` values can be specified, and all will be called in order.
- Functions should follow the interface defined in `:help complete-functions`.
- When using `f{func}`, escaping is required for spaces (with `\`) and commas
(with `\\`) in `Funcref` names.
- If a function sets `'refresh'` to `'always'`, it will be re-invoked on every
change to the input text. Otherwise, Vim will attempt to reuse and filter
existing matches as the input changes, which matches the default behavior of
other completion sources.
- Matches are inserted at the keyword boundary for consistency with other completion methods.
- If finding matches is time-consuming, `complete_check()` can be used to
maintain responsiveness.
- Completion matches are gathered in the sequence defined by the `'cpt'`
option, preserving source priority.
This feature increases flexibility of standard completion mechanism and may
reduce the need for external completion plugins for many users.
**Examples:**
Complete matches from [LSP](https://github.com/yegappan/lsp) client. Notice the use of `refresh: always` and `function()`.
```vim
set cpt+=ffunction("g:LspCompletor"\\,\ [5]). # maxitems = 5
def! g:LspCompletor(maxitems: number, findstart: number, base: string): any
if findstart == 1
return g:LspOmniFunc(findstart, base)
endif
return {words: g:LspOmniFunc(findstart, base)->slice(0, maxitems), refresh: 'always'}
enddef
autocmd VimEnter * g:LspOptionsSet({ autoComplete: false, omniComplete: true })
```
Complete matches from `:iabbrev`.
```vim
set cpt+=fAbbrevCompletor
def! g:AbbrevCompletor(findstart: number, base: string): any
if findstart > 0
var prefix = getline('.')->strpart(0, col('.') - 1)->matchstr('\S\+$')
if prefix->empty()
return -2
endif
return col('.') - prefix->len() - 1
endif
var lines = execute('ia', 'silent!')
if lines =~? gettext('No abbreviation found')
return v:none # Suppresses warning message
endif
var items = []
for line in lines->split("\n")
var m = line->matchlist('\v^i\s+\zs(\S+)\s+(.*)$')
if m->len() > 2 && m[1]->stridx(base) == 0
items->add({ word: m[1], info: m[2], dup: 1 })
endif
endfor
return items->empty() ? v:none :
items->sort((v1, v2) => v1.word < v2.word ? -1 : v1.word ==# v2.word ? 0 : 1)
enddef
```
**Auto-completion:**
Vim's standard completion frequently checks for user input while searching for
new matches. It is responsive irrespective of file size. This makes it
well-suited for smooth auto-completion. You can try with above examples:
```vim
set cot=menuone,popup,noselect inf
autocmd TextChangedI * InsComplete()
def InsComplete()
if getcharstr(1) == '' && getline('.')->strpart(0, col('.') - 1) =~ '\k$'
SkipTextChangedIEvent()
feedkeys("\<c-n>", "n")
endif
enddef
inoremap <silent> <c-e> <c-r>=<SID>SkipTextChangedIEvent()<cr><c-e>
def SkipTextChangedIEvent(): string
# Suppress next event caused by <c-e> (or <c-n> when no matches found)
set eventignore+=TextChangedI
timer_start(1, (_) => {
set eventignore-=TextChangedI
})
return ''
enddef
```
closes: vim/vim#17065cbe53191d0
Temporarily remove bufname completion with #if 0 to make merging easier.
Co-authored-by: Girish Palya <girishji@gmail.com>
Co-authored-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: glepnir <glephunter@gmail.com>
Problem: preview-window does not scroll correctly
Solution: init firstline = 0 for a preview window
(Girish Palya)
The 'info' window, which appears during insert-mode completion to display
additional information, was not scrolling properly when using commands like:
win_execute(popup_findinfo(), "normal! \<PageDown>")
This issue made it impossible to navigate through info window contents using
keyboard-based scrolling.
The fix correctly updates the w_firstline value of the popup window, ensuring
proper scrolling behavior. Mouse scrolling was already working as expected and
remains unaffected.
closes: vim/vim#1670312b1eb58ab
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: Buffer setup after moving the message buffer to the "more"
window after ff95d7ff is incomplete.
Solution: Adjust and invoke tab_check_wins() to do the setup instead.
Problem: Closing the "more" window for an entered cmdwin in ff95d7ff9
still requires special casing to properly handle "more" visibility.
Solution: Reposition the "more" window instead; anchoring it to the
cmdwin.
Problem: Unable to change the "relative" of a flag after its target
"win" no longer exists.
Solution: Unset target window if it is not present in config and
reconfigured "relative" no longer expects a target window.
Problem:
Developing/troubleshooting plugins has friction because "restarting"
Nvim requires quitting and manually starting again. #32484
Solution:
- Implement a `:restart` command which emits `restart` UI event.
- Handle the `restart` UI event in the builtin TUI client: stop the
`nvim --embed` server, start a new one, and attach to it.
Complement the documented support for the recognition of all
public types of the "java.lang" package (":help java.vim").
(The original syntax item generator may have, inadvertently,
contributed via suppressing "NullPointerException"s to not
having annotation and interface types qualify in general.)
Also, re-link usage instructions for the alternative syntax
item generator to a rolling "master"'s version.
closes: vim/vim#17419b577ad50d0
Co-authored-by: Aliaksei Budavei <0x000c70@gmail.com>
Problem: When using conhost and pressing the 'x' button
to close it while nvim is open, nvim hangs up
while trying to reset the window icon, causing a big
delay before the terminal actually closes. #34171
Solution: Set the window handle to NULL after receiving SIGHUP
so that nvim will not try resetting the icon.
Problem: Non-visible/focusable windows are assigned a window number,
whereas commands that use this window number skip over them.
Solution: Skip over non-visible/focusable windows when computing
the window number, unless it is made the current window
through the API in which case an identifiable window number
is still useful. This also ensures it matches the window
number of the window entered by `<winnr>wincmd w` since
403fcacf.
Problem: nvim_create_user_command() Lua callbacks were missing the documented nargs field in the options table passed to the callback function.
Solution: Add nargs field derivation from command argument type flags in nlua_do_ucmd(), using the same logic as nvim_parse_cmd().
Problem: Message lines from multiple message events that end up
spilling 'cmdheight' end up spread out over the cmdline
and "more" window.
Messages emitted as feedback to a typed :command (rather than
its sole purpose like :echo/:=) are routed to the more window.
The more window isn't closed when entering the cmdwin, and
doesn't allow `vim.hl.on_yank()`.
Solution: When first opening the "more" window for spilled messages,
move the message buffer to the more window.
Restrict routing of typed commands to echo kinds.
Ignore all events but WinLeave and TextYankPost.
- Match full :mark and :k commands.
- Match 2 and 3 letter :s repeat commands.
- Match :s [count] argument.
closes: vim/vim#17408086b3b5b79
Co-authored-by: Doug Kearns <dougkearns@gmail.com>
- Match "autoload" as a keyword in :import commands.
- Match an expression argument for the filename.
closes: vim/vim#153757b5550fac7
Co-authored-by: Doug Kearns <dougkearns@gmail.com>
Problem: tests: could need some more tests for shebang lines
Solution: add more shebang patterns to test_filetype.vim
(Eisuke Kawashima)
closes: vim/vim#1740954a09e7e86
Co-authored-by: Eisuke Kawashima <e-kwsm@users.noreply.github.com>
Problem: Shebang filetype detection can be improved
Solution: Improve detection logic (Eisuke Kawashima)
Vim does not correctly detect filetype from
- `#!/usr/bin/env --split-string=awk -f`
- `#!/usr/bin/env -S -i awk -f`
- `#!/usr/bin/env -S VAR= awk -f`
So update the current detection logic to detect those cases.
closes: vim/vim#17199f102f4c2e8
Co-authored-by: Eisuke Kawashima <e-kwsm@users.noreply.github.com>
Problem: It is difficult to ignore all but some events.
Solution: Add support for a "-" prefix syntax in '(win)eventignore' that
subtracts an event from the ignored set if present
(Luuk van Baal).
8cc6d8b187
Problem: Blockwise Visual selection not redrawn correctly when moving
cursor for more than 1 cells with 'virtualedit'.
Solution: Restore the curswant update removed in 6679687bb3.
- Match comments and trailing bar after :set without args.
- Match the <...> form for key code options.
- Remove orphaned vim_ex_python[3x]* dump files (Aliaksei Budavei).
closes: vim/vim#17397570e71a277
Co-authored-by: Doug Kearns <dougkearns@gmail.com>
Problem:
Despite the name, `builtin.txt` only includes Vimscript functions, which
is confusing, especially to people who only use Lua to configure Nvim
Solution: From justinmk's suggestion
- Rename `builtin.txt` to `vimfn.txt`
- Rename `eval.txt` to `vimeval.txt`
- The tags `*builtin.txt*` and `*eval.txt*` should be kept for Vim-patches
Closes#33743
Problem:
Currently undefined behavior can occur when `string_fragment()` is
called with `OSC_COMMAND`. This is because when the state changes to
`OSC_COMMAND`, `string_initial` is set to true. Then in some cases,
directly after this `string_initial` will be set back to false before
the on_osc callback is called, this leads to `term_settermprop()` never
initializing the title.
Solution:
In all of the no-op cases in `string_fragment()` currently, we continue
to the end of the function where `vt->parser.string_initial` is set to
false. This change returns in the no-op cases instead since in these
cases the string has not yet been terminated and sent to the callback.
Note:
This change also adds a test with a byte sequence from the file
in #34028 that caused nvim to crash. This byte sequences is the shortest
sequence I could trim down from that file that still would trigger the
crash. There are also two other tests I added which validate that
setting the title with OSC-0 and OSC-2 still works.
Fixes: #34028
Problem: `TSLangInfo` annotation does not reflect the structure returned
by `vim.treesitter.language.inspect()`.
Solution: Move version information under new (optional since ABI 15 only)
`TSLangMetadata` field.
Problem:
vim.uv.spawn will emit ENOENT for either when the cmd or cwd do not
exist and does not tell you which.
Solution:
If an error occurs, check if cwd was supplied and included in the error
message if it does not exist.