mirror of
https://github.com/neovim/neovim.git
synced 2025-09-07 11:58:17 +00:00
vim-patch:9.1.1049: insert-completed items are always sorted
Problem: insert-completed items are always sorted, although the LSP
spec[1] standard defines sortText in the returned
completionitem list. This means that the server has sorted the
results. When fuzzy is enabled, this will break the server's
sorting results.
Solution: disable sorting of candidates when "nosort" is set in
'completeopt'
[1]
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItem
closes: vim/vim#16501
f400a0cc41
Co-authored-by: glepnir <glephunter@gmail.com>
This commit is contained in:
@@ -1571,6 +1571,10 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
list of alternatives, but not how the candidates are
|
list of alternatives, but not how the candidates are
|
||||||
collected (using different completion types).
|
collected (using different completion types).
|
||||||
|
|
||||||
|
nosort Disable sorting of completion candidates based on fuzzy
|
||||||
|
scores when "fuzzy" is enabled. Candidates will appear
|
||||||
|
in their original order.
|
||||||
|
|
||||||
*'completeslash'* *'csl'*
|
*'completeslash'* *'csl'*
|
||||||
'completeslash' 'csl' string (default "")
|
'completeslash' 'csl' string (default "")
|
||||||
local to buffer
|
local to buffer
|
||||||
|
4
runtime/lua/vim/_meta/options.lua
generated
4
runtime/lua/vim/_meta/options.lua
generated
@@ -1098,6 +1098,10 @@ vim.go.cia = vim.go.completeitemalign
|
|||||||
--- list of alternatives, but not how the candidates are
|
--- list of alternatives, but not how the candidates are
|
||||||
--- collected (using different completion types).
|
--- collected (using different completion types).
|
||||||
---
|
---
|
||||||
|
--- nosort Disable sorting of completion candidates based on fuzzy
|
||||||
|
--- scores when "fuzzy" is enabled. Candidates will appear
|
||||||
|
--- in their original order.
|
||||||
|
---
|
||||||
--- @type string
|
--- @type string
|
||||||
vim.o.completeopt = "menu,preview"
|
vim.o.completeopt = "menu,preview"
|
||||||
vim.o.cot = vim.o.completeopt
|
vim.o.cot = vim.o.completeopt
|
||||||
|
@@ -1212,7 +1212,8 @@ static int ins_compl_build_pum(void)
|
|||||||
int max_fuzzy_score = 0;
|
int max_fuzzy_score = 0;
|
||||||
unsigned cur_cot_flags = get_cot_flags();
|
unsigned cur_cot_flags = get_cot_flags();
|
||||||
bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0;
|
bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0;
|
||||||
bool compl_fuzzy_match = (cur_cot_flags & kOptCotFlagFuzzy) != 0;
|
bool fuzzy_nosort = (cur_cot_flags & kOptCotFlagNosort) != 0;
|
||||||
|
bool fuzzy_filter = fuzzy_nosort || (cur_cot_flags & kOptCotFlagFuzzy) != 0;
|
||||||
compl_T *match_head = NULL, *match_tail = NULL;
|
compl_T *match_head = NULL, *match_tail = NULL;
|
||||||
|
|
||||||
// If the current match is the original text don't find the first
|
// If the current match is the original text don't find the first
|
||||||
@@ -1232,14 +1233,14 @@ static int ins_compl_build_pum(void)
|
|||||||
comp->cp_in_match_array = false;
|
comp->cp_in_match_array = false;
|
||||||
// When 'completeopt' contains "fuzzy" and leader is not NULL or empty,
|
// When 'completeopt' contains "fuzzy" and leader is not NULL or empty,
|
||||||
// set the cp_score for later comparisons.
|
// set the cp_score for later comparisons.
|
||||||
if (compl_fuzzy_match && compl_leader.data != NULL && compl_leader.size > 0) {
|
if (fuzzy_filter && compl_leader.data != NULL && compl_leader.size > 0) {
|
||||||
comp->cp_score = fuzzy_match_str(comp->cp_str.data, compl_leader.data);
|
comp->cp_score = fuzzy_match_str(comp->cp_str.data, compl_leader.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!match_at_original_text(comp)
|
if (!match_at_original_text(comp)
|
||||||
&& (compl_leader.data == NULL
|
&& (compl_leader.data == NULL
|
||||||
|| ins_compl_equal(comp, compl_leader.data, compl_leader.size)
|
|| ins_compl_equal(comp, compl_leader.data, compl_leader.size)
|
||||||
|| (compl_fuzzy_match && comp->cp_score > 0))) {
|
|| (fuzzy_filter && comp->cp_score > 0))) {
|
||||||
compl_match_arraysize++;
|
compl_match_arraysize++;
|
||||||
comp->cp_in_match_array = true;
|
comp->cp_in_match_array = true;
|
||||||
if (match_head == NULL) {
|
if (match_head == NULL) {
|
||||||
@@ -1248,7 +1249,7 @@ static int ins_compl_build_pum(void)
|
|||||||
match_tail->cp_match_next = comp;
|
match_tail->cp_match_next = comp;
|
||||||
}
|
}
|
||||||
match_tail = comp;
|
match_tail = comp;
|
||||||
if (!shown_match_ok && !compl_fuzzy_match) {
|
if (!shown_match_ok && !fuzzy_filter) {
|
||||||
if (comp == compl_shown_match || did_find_shown_match) {
|
if (comp == compl_shown_match || did_find_shown_match) {
|
||||||
// This item is the shown match or this is the
|
// This item is the shown match or this is the
|
||||||
// first displayed item after the shown match.
|
// first displayed item after the shown match.
|
||||||
@@ -1261,18 +1262,20 @@ static int ins_compl_build_pum(void)
|
|||||||
shown_compl = comp;
|
shown_compl = comp;
|
||||||
}
|
}
|
||||||
cur = i;
|
cur = i;
|
||||||
} else if (compl_fuzzy_match) {
|
} else if (fuzzy_filter) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
shown_compl = comp;
|
shown_compl = comp;
|
||||||
}
|
}
|
||||||
// Update the maximum fuzzy score and the shown match
|
// Update the maximum fuzzy score and the shown match
|
||||||
// if the current item's score is higher
|
// if the current item's score is higher
|
||||||
if (comp->cp_score > max_fuzzy_score) {
|
if (!fuzzy_nosort && comp->cp_score > max_fuzzy_score) {
|
||||||
did_find_shown_match = true;
|
did_find_shown_match = true;
|
||||||
max_fuzzy_score = comp->cp_score;
|
max_fuzzy_score = comp->cp_score;
|
||||||
if (!compl_no_select) {
|
if (!compl_no_select) {
|
||||||
compl_shown_match = comp;
|
compl_shown_match = comp;
|
||||||
}
|
}
|
||||||
|
} else if (fuzzy_nosort && i == 0 && !compl_no_select) {
|
||||||
|
compl_shown_match = shown_compl;
|
||||||
}
|
}
|
||||||
if (!shown_match_ok && comp == compl_shown_match && !compl_no_select) {
|
if (!shown_match_ok && comp == compl_shown_match && !compl_no_select) {
|
||||||
cur = i;
|
cur = i;
|
||||||
@@ -1282,7 +1285,7 @@ static int ins_compl_build_pum(void)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp == compl_shown_match && !compl_fuzzy_match) {
|
if (comp == compl_shown_match && !fuzzy_filter) {
|
||||||
did_find_shown_match = true;
|
did_find_shown_match = true;
|
||||||
// When the original text is the shown match don't set
|
// When the original text is the shown match don't set
|
||||||
// compl_shown_match.
|
// compl_shown_match.
|
||||||
@@ -1323,7 +1326,7 @@ static int ins_compl_build_pum(void)
|
|||||||
comp = match_next;
|
comp = match_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compl_fuzzy_match && compl_leader.data != NULL && compl_leader.size > 0) {
|
if (fuzzy_filter && !fuzzy_nosort && compl_leader.data != NULL && compl_leader.size > 0) {
|
||||||
for (i = 0; i < compl_match_arraysize; i++) {
|
for (i = 0; i < compl_match_arraysize; i++) {
|
||||||
compl_match_array[i].pum_idx = i;
|
compl_match_array[i].pum_idx = i;
|
||||||
}
|
}
|
||||||
|
@@ -1493,6 +1493,7 @@ local options = {
|
|||||||
'noinsert',
|
'noinsert',
|
||||||
'noselect',
|
'noselect',
|
||||||
'fuzzy',
|
'fuzzy',
|
||||||
|
'nosort',
|
||||||
},
|
},
|
||||||
flags = true,
|
flags = true,
|
||||||
deny_duplicates = true,
|
deny_duplicates = true,
|
||||||
@@ -1537,6 +1538,10 @@ local options = {
|
|||||||
difference how completion candidates are reduced from the
|
difference how completion candidates are reduced from the
|
||||||
list of alternatives, but not how the candidates are
|
list of alternatives, but not how the candidates are
|
||||||
collected (using different completion types).
|
collected (using different completion types).
|
||||||
|
|
||||||
|
nosort Disable sorting of completion candidates based on fuzzy
|
||||||
|
scores when "fuzzy" is enabled. Candidates will appear
|
||||||
|
in their original order.
|
||||||
]=],
|
]=],
|
||||||
full_name = 'completeopt',
|
full_name = 'completeopt',
|
||||||
list = 'onecomma',
|
list = 'onecomma',
|
||||||
|
@@ -2778,7 +2778,7 @@ func Test_complete_fuzzy_match()
|
|||||||
if a:findstart
|
if a:findstart
|
||||||
return col(".")
|
return col(".")
|
||||||
endif
|
endif
|
||||||
return [#{word: "foo"}, #{word: "foobar"}, #{word: "fooBaz"}, #{word: "foobala"}]
|
return [#{word: "foo"}, #{word: "foobar"}, #{word: "fooBaz"}, #{word: "foobala"}, #{word: "你好吗"}, #{word: "我好"}]
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
new
|
new
|
||||||
@@ -2837,6 +2837,21 @@ func Test_complete_fuzzy_match()
|
|||||||
call feedkeys("STe\<C-X>\<C-N>x\<CR>\<Esc>0", 'tx!')
|
call feedkeys("STe\<C-X>\<C-N>x\<CR>\<Esc>0", 'tx!')
|
||||||
call assert_equal('Tex', getline('.'))
|
call assert_equal('Tex', getline('.'))
|
||||||
|
|
||||||
|
" test case for nosort option
|
||||||
|
set cot=menuone,menu,noinsert,fuzzy,nosort
|
||||||
|
" fooBaz" should have a higher score when the leader is "fb".
|
||||||
|
" With `nosort`, "foobar" should still be shown first in the popup menu.
|
||||||
|
call feedkeys("S\<C-x>\<C-o>fb", 'tx')
|
||||||
|
call assert_equal('foobar', g:word)
|
||||||
|
call feedkeys("S\<C-x>\<C-o>好", 'tx')
|
||||||
|
call assert_equal("你好吗", g:word)
|
||||||
|
|
||||||
|
set cot+=noselect
|
||||||
|
call feedkeys("S\<C-x>\<C-o>好", 'tx')
|
||||||
|
call assert_equal(v:null, g:word)
|
||||||
|
call feedkeys("S\<C-x>\<C-o>好\<C-N>", 'tx')
|
||||||
|
call assert_equal('你好吗', g:word)
|
||||||
|
|
||||||
" clean up
|
" clean up
|
||||||
set omnifunc=
|
set omnifunc=
|
||||||
bw!
|
bw!
|
||||||
|
Reference in New Issue
Block a user