patch 9.1.1178: not possible to generate completion candidates using fuzzy matching
Problem: not possible to generate completion candidates using fuzzy
matching
Solution: add the 'completefuzzycollect' option for (some) ins-completion
modes (glepnir)
fixes #15296
fixes #15295
fixes #15294
closes: #16032
Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 1bef953..345e365 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2731,7 +2731,7 @@
bwipe!
endfunc
-func Test_complete_fuzzy_match()
+func Test_complete_opt_fuzzy()
func OnPumChange()
let g:item = get(v:event, 'completed_item', {})
let g:word = get(g:item, 'word', v:null)
@@ -2787,8 +2787,65 @@
call feedkeys("S\<C-x>\<C-o>fb\<C-n>", 'tx')
call assert_equal('fooBaz', g:word)
- " avoid breaking default completion behavior
- set completeopt=fuzzy,menu
+ " 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)
+
+ " "nosort" shouldn't enable fuzzy filtering when "fuzzy" isn't present.
+ set cot=menuone,noinsert,nosort
+ call feedkeys("S\<C-x>\<C-o>fooB\<C-Y>", 'tx')
+ call assert_equal('fooBaz', getline('.'))
+
+ set cot=menuone,fuzzy,nosort
+ func CompAnother()
+ call complete(col('.'), [#{word: "do" }, #{word: "echo"}, #{word: "for (${1:expr1}, ${2:expr2}, ${3:expr3}) {\n\t$0\n}", abbr: "for" }, #{word: "foo"}])
+ return ''
+ endfunc
+ call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-N>\<C-N>", 'tx')
+ call assert_equal("for", g:abbr)
+ call assert_equal(2, g:selected)
+
+ set cot+=noinsert
+ call feedkeys("i\<C-R>=CompAnother()\<CR>f", 'tx')
+ call assert_equal("for", g:abbr)
+ call assert_equal(2, g:selected)
+
+ set cot=menu,menuone,noselect,fuzzy
+ call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-N>\<C-N>\<C-N>\<C-N>", 'tx')
+ call assert_equal("foo", g:word)
+ call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-P>", 'tx')
+ call assert_equal("foo", g:word)
+ call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-P>\<C-P>", 'tx')
+ call assert_equal("for", g:abbr)
+
+ " clean up
+ set omnifunc=
+ bw!
+ set complete& completeopt&
+ autocmd! AAAAA_Group
+ augroup! AAAAA_Group
+ delfunc OnPumChange
+ delfunc Omni_test
+ delfunc Comp
+ unlet g:item
+ unlet g:word
+ unlet g:abbr
+endfunc
+
+func Test_complete_fuzzy_collect()
+ new
+ set completefuzzycollect=keyword,files,whole_line
call setline(1, ['hello help hero h'])
" Use "!" flag of feedkeys() so that ex_normal_busy is not set and
" ins_compl_check_keys() is not skipped.
@@ -2820,16 +2877,6 @@
call feedkeys("A\<C-X>\<C-N>\<C-N>\<Esc>0", 'tx!')
call assert_equal('你的 我的 我的', getline('.'))
- " respect wrapscan
- set nowrapscan
- call setline(1, ["xyz", "yxz", ""])
- call cursor(3, 1)
- call feedkeys("Sy\<C-X>\<C-N>\<Esc>0", 'tx!')
- call assert_equal('y', getline('.'))
- set wrapscan
- call feedkeys("Sy\<C-X>\<C-N>\<Esc>0", 'tx!')
- call assert_equal('xyz', getline('.'))
-
" fuzzy on file
call writefile([''], 'fobar', 'D')
call writefile([''], 'foobar', 'D')
@@ -2845,7 +2892,6 @@
call assert_match('../testdir', getline('.'))
" can get completion from other buffer
- set completeopt=fuzzy,menu,menuone
vnew
call setline(1, ["completeness,", "compatibility", "Composite", "Omnipotent"])
wincmd p
@@ -2897,79 +2943,109 @@
call assert_equal('你好 他好', getline('.'))
" issue #15526
- set completeopt=fuzzy,menuone,menu,noselect
+ set completeopt=menuone,menu,noselect
call setline(1, ['Text', 'ToText', ''])
call cursor(3, 1)
call feedkeys("STe\<C-X>\<C-N>x\<CR>\<Esc>0", 'tx!')
call assert_equal('Tex', getline(line('.') - 1))
- " 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)
-
- " "nosort" shouldn't enable fuzzy filtering when "fuzzy" isn't present.
- set cot=menuone,noinsert,nosort
- call feedkeys("S\<C-x>\<C-o>fooB\<C-Y>", 'tx')
- call assert_equal('fooBaz', getline('.'))
-
- set cot=menuone,fuzzy,nosort
- func CompAnother()
- call complete(col('.'), [#{word: "do" }, #{word: "echo"}, #{word: "for (${1:expr1}, ${2:expr2}, ${3:expr3}) {\n\t$0\n}", abbr: "for" }, #{word: "foo"}])
- return ''
- endfunc
- call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-N>\<C-N>", 'tx')
- call assert_equal("for", g:abbr)
- call assert_equal(2, g:selected)
-
- set cot+=noinsert
- call feedkeys("i\<C-R>=CompAnother()\<CR>f", 'tx')
- call assert_equal("for", g:abbr)
- call assert_equal(2, g:selected)
-
- set cot=menu,menuone,noselect,fuzzy
- call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-N>\<C-N>\<C-N>\<C-N>", 'tx')
- call assert_equal("foo", g:word)
- call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-P>", 'tx')
- call assert_equal("foo", g:word)
- call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-P>\<C-P>", 'tx')
- call assert_equal("for", g:abbr)
-
- " clean up
- set omnifunc=
bw!
bw!
- set complete& completeopt&
- autocmd! AAAAA_Group
- augroup! AAAAA_Group
- delfunc OnPumChange
- delfunc Omni_test
- delfunc Comp
- delfunc CompAnother
- unlet g:item
- unlet g:word
- unlet g:selected
- unlet g:abbr
+ set completeopt& cfc& cpt&
endfunc
-func Test_complete_fuzzy_with_completeslash()
+func Test_cfc_with_longest()
+ new
+ set completefuzzycollect=keyword,files,whole_line
+ set completeopt=menu,menuone,longest,fuzzy
+
+ " keyword
+ exe "normal ggdGShello helio think h\<C-X>\<C-N>\<ESC>"
+ call assert_equal("hello helio think hel", getline('.'))
+ exe "normal hello helio think h\<C-X>\<C-P>\<ESC>"
+ call assert_equal("hello helio think hel", getline('.'))
+
+ " skip non-consecutive prefixes
+ exe "normal ggdGShello helio heo\<C-X>\<C-N>\<ESC>"
+ call assert_equal("hello helio heo", getline('.'))
+
+ " kdcit
+ call writefile(['help'], 'test_keyword.txt', 'D')
+ set complete=ktest_keyword.txt
+ exe "normal ggdGSh\<C-N>\<ESC>"
+ " auto insert help when only have one match
+ call assert_equal("help", getline('.'))
+ call writefile(['hello', 'help', 'think'], 'xtest_keyword.txt', 'D')
+ set complete=kxtest_keyword.txt
+ " auto insert hel
+ exe "normal ggdGSh\<C-N>\<ESC>"
+ call assert_equal("hel", getline('.'))
+
+ " line start with a space
+ call writefile([' hello'], 'test_case1.txt', 'D')
+ set complete=ktest_case1.txt
+ exe "normal ggdGSh\<C-N>\<ESC>"
+ call assert_equal("hello", getline('.'))
+
+ " multiple matches
+ set complete=ktest_case2.txt
+ call writefile([' hello help what'], 'test_case2.txt', 'D')
+ exe "normal ggdGSh\<C-N>\<C-N>\<C-N>\<C-N>\<ESC>"
+ call assert_equal("what", getline('.'))
+
+ " multiple lines of matches
+ set complete=ktest_case3.txt
+ call writefile([' hello help what', 'hola', ' hey'], 'test_case3.txt', 'D')
+ exe "normal ggdGSh\<C-N>\<C-N>\<ESC>"
+ call assert_equal("hey", getline('.'))
+ exe "normal ggdGSh\<C-N>\<C-N>\<C-N>\<C-N>\<ESC>"
+ call assert_equal("hola", getline('.'))
+
+ set complete=ktest_case4.txt
+ call writefile([' auto int enum register', 'why'], 'test_case4.txt', 'D')
+ exe "normal ggdGSe\<C-N>\<C-N>\<ESC>"
+ call assert_equal("enum", getline('.'))
+ set complete&
+
+ " file
+ call writefile([''], 'hello', 'D')
+ call writefile([''], 'helio', 'D')
+ exe "normal ggdGS./h\<C-X>\<C-f>\<ESC>"
+ call assert_equal('./hel', getline('.'))
+
+ " word
+ call setline(1, ['what do you think', 'why i have that', ''])
+ call cursor(3,1)
+ call feedkeys("Sw\<C-X>\<C-l>\<C-N>\<Esc>0", 'tx!')
+ call assert_equal('wh', getline('.'))
+
+ exe "normal ggdG"
+ " auto complete when only one match
+ exe "normal Shello\<CR>h\<C-X>\<C-N>\<esc>"
+ call assert_equal('hello', getline('.'))
+ exe "normal Sh\<C-N>\<C-P>\<esc>"
+ call assert_equal('hello', getline('.'))
+
+ exe "normal Shello\<CR>h\<C-X>\<C-N>\<Esc>cch\<C-X>\<C-N>\<Esc>"
+ call assert_equal('hello', getline('.'))
+
+ " continue search for new leader after insert common prefix
+ exe "normal ohellokate\<CR>h\<C-X>\<C-N>k\<C-y>\<esc>"
+ call assert_equal('hellokate', getline('.'))
+
+ bw!
+ set completeopt&
+ set completefuzzycollect&
+endfunc
+
+func Test_completefuzzycollect_with_completeslash()
CheckMSWindows
call writefile([''], 'fobar', 'D')
let orig_shellslash = &shellslash
set cpt&
new
- set completeopt+=fuzzy
+ set completefuzzycollect=files
set noshellslash
" Test with completeslash unset
@@ -2991,6 +3067,7 @@
" Reset and clean up
let &shellslash = orig_shellslash
set completeslash=
+ set completefuzzycollect&
%bw!
endfunc