-
-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Feature: Add proximity-based sorting of completion matches #17076
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
During insert-mode completion, the most relevant match is often the one closest to the cursor—frequently just above the current line. However, both `<C-N>` and `<C-P>` tend to place candidates from above the cursor near the bottom of the completion menu, rather than the top. This ordering can feel unintuitive, especially when `noselect` is active, as it doesn't prioritize the most contextually relevant suggestions. This change introduces a new option value `nearest` for the `'completeopt'` (`'cot'`) setting. When enabled, matches from the current buffer are prioritized based on their proximity to the cursor position, improving the relevance of suggestions during completion. Key Details: - Option: "nearest" added to 'completeopt' - Applies to: Matches from the current buffer only - Effect: Sorts completion candidates by their distance from the cursor - Interaction with other options: - Has no effect if the `fuzzy` option is also present This feature allows users to fine-tune the ordering of completion candidates, especially when working within large buffers where multiple similar matches may exist at different locations. M runtime/doc/options.txt M src/insexpand.c M src/option.h M src/optionstr.c M src/testdir/test_ins_complete.vim
|
Hm, not being a completion user myself much, but I'd think this sorting method could cause quite a bit of confusion about the ordering in the popup menu, no? I don't think I ever had a use case for such sorting. |
M src/insexpand.c
glepnir
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be done in a script. Don't make it too bloated here.
What does LSP got anything to do with this PR? Open |
|
? lsp provides sort so why do we need something extra like this? And can't you implement it in your completion plugin even if you don't use lsp? This is not in the planned todo and there is no issue. I don't think this PR brings any obvious benefits. time complexity of reposition_match is O(n) growth factor of n is the file size and the options that cpt needs to handle. Doesn't it get slower when n is larger? Currently, the efficiency of keyword itself needs to be improved on large files. I don't think it will be more complicated before refactoring. |
chrisbra
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay fair. I have a few minor comments.
…ursor
Problem: During insert-mode completion, the most relevant match is often
the one closest to the cursor—frequently just above the current line.
However, both `<C-N>` and `<C-P>` tend to rank candidates from the
current buffer that appear above the cursor near the bottom of the
completion menu, rather than near the top. This ordering can feel
unintuitive, especially when `noselect` is active, as it doesn't
prioritize the most contextually relevant suggestions.
Solution: This change introduces a new sub-option value "nearest" for the
'completeopt' setting. When enabled, matches from the current buffer
are prioritized based on their proximity to the cursor position,
improving the relevance of suggestions during completion
(Girish Palya).
Key Details:
- Option: "nearest" added to 'completeopt'
- Applies to: Matches from the current buffer only
- Effect: Sorts completion candidates by their distance from the cursor
- Interaction with other options:
- Has no effect if the `fuzzy` option is also present
This feature is helpful especially when working within large buffers where
multiple similar matches may exist at different locations.
You can test this feature with auto-completion using the snippet below. Try it
in a large file like `vim/src/insexpand.c`, where you'll encounter many
potential matches. You'll notice that the popup menu now typically surfaces the
most relevant matches—those closest to the cursor—at the top. Sorting by
spatial proximity (i.e., contextual relevance) often produces more useful
matches than sorting purely by lexical distance ("fuzzy").
Another way to sort matches is by recency, using an LRU (Least Recently Used)
cache—essentially ranking candidates based on how recently they were used.
However, this is often overkill in practice, as spatial proximity (as provided
by the "nearest" option) is usually sufficient to surface the most relevant
matches.
```vim
set cot=menuone,popup,noselect,nearest inf
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
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>
inoremap <silent><expr> <tab> pumvisible() ? "\<c-n>" : "\<tab>"
inoremap <silent><expr> <s-tab> pumvisible() ? "\<c-p>" : "\<s-tab>"
```
closes: vim/vim#17076
vim/vim@b156588
Co-authored-by: Girish Palya <girishji@gmail.com>
…ursor (#33491) Problem: During insert-mode completion, the most relevant match is often the one closest to the cursor—frequently just above the current line. However, both `<C-N>` and `<C-P>` tend to rank candidates from the current buffer that appear above the cursor near the bottom of the completion menu, rather than near the top. This ordering can feel unintuitive, especially when `noselect` is active, as it doesn't prioritize the most contextually relevant suggestions. Solution: This change introduces a new sub-option value "nearest" for the 'completeopt' setting. When enabled, matches from the current buffer are prioritized based on their proximity to the cursor position, improving the relevance of suggestions during completion (Girish Palya). Key Details: - Option: "nearest" added to 'completeopt' - Applies to: Matches from the current buffer only - Effect: Sorts completion candidates by their distance from the cursor - Interaction with other options: - Has no effect if the `fuzzy` option is also present This feature is helpful especially when working within large buffers where multiple similar matches may exist at different locations. You can test this feature with auto-completion using the snippet below. Try it in a large file like `vim/src/insexpand.c`, where you'll encounter many potential matches. You'll notice that the popup menu now typically surfaces the most relevant matches—those closest to the cursor—at the top. Sorting by spatial proximity (i.e., contextual relevance) often produces more useful matches than sorting purely by lexical distance ("fuzzy"). Another way to sort matches is by recency, using an LRU (Least Recently Used) cache—essentially ranking candidates based on how recently they were used. However, this is often overkill in practice, as spatial proximity (as provided by the "nearest" option) is usually sufficient to surface the most relevant matches. ```vim set cot=menuone,popup,noselect,nearest inf 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 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> inoremap <silent><expr> <tab> pumvisible() ? "\<c-n>" : "\<tab>" inoremap <silent><expr> <s-tab> pumvisible() ? "\<c-p>" : "\<s-tab>" ``` closes: vim/vim#17076 vim/vim@b156588 Co-authored-by: Girish Palya <girishji@gmail.com>
|
Why can't we add a fractional factor for the visible area? Would this also affect the sorting when fuzzy? merger was too hasty. |





Problem: During insert-mode completion, the most relevant match is often the one closest to the cursor—frequently just above the current line. However, both
<C-N>and<C-P>tend to rank candidates from the current buffer that appear above the cursor near the bottom of the completion menu, rather than near the top. This ordering can feel unintuitive, especially whennoselectis active, as it doesn't prioritize the most contextually relevant suggestions.Solution: This change introduces a new option value
nearestfor the'completeopt'('cot') setting. When enabled, matches from the current buffer are prioritized based on their proximity to the cursor position, improving the relevance of suggestions during completion.Key Details:
fuzzyoption is also presentThis feature is helpful especially when working within large buffers where multiple similar matches may exist at different locations.
Edit:
You can test this feature with auto-completion using the snippet below. Try it in a large file like
vim/src/insexpand.c, where you'll encounter many potential matches. You'll notice that the popup menu now typically surfaces the most relevant matches—those closest to the cursor—at the top. Sorting by spatial proximity (i.e., contextual relevance) often produces more useful matches than sorting purely by lexical distance ("fuzzy").Another way to sort matches is by recency, using an LRU (Least Recently Used) cache—essentially ranking candidates based on how recently they were used. However, this is often overkill in practice, as spatial proximity (as provided by the "nearest" option) is usually sufficient to surface the most relevant matches.