diff options
author | glepnir <glephunter@gmail.com> | 2024-06-19 20:20:48 +0200 |
---|---|---|
committer | Christian Brabandt <cb@256bit.org> | 2024-06-19 20:25:01 +0200 |
commit | 43eef882ff42e673af1e753892801ba20c5d002a (patch) | |
tree | 9af6e3ac6997ee065d8863553bc57a1f49c1fd73 | |
parent | 94c5d8a5e20e1dd8c9e8434ee14e368276644f61 (diff) |
patch 9.1.0503: cannot use fuzzy keyword completionv9.1.0503
Problem: cannot use fuzzy keyword completion
(Maxim Kim)
Solution: add the "fuzzycollect" value for the 'completeopt'
setting, to gather matches using fuzzy logic (glepnir)
fixes: #14912
closes: #14976
Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
-rw-r--r-- | runtime/doc/options.txt | 7 | ||||
-rw-r--r-- | runtime/doc/version9.txt | 9 | ||||
-rw-r--r-- | src/insexpand.c | 40 | ||||
-rw-r--r-- | src/option.h | 15 | ||||
-rw-r--r-- | src/optionstr.c | 2 | ||||
-rw-r--r-- | src/testdir/test_ins_complete.vim | 31 | ||||
-rw-r--r-- | src/version.c | 2 |
7 files changed, 92 insertions, 14 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 6ec4031175..62d6ded111 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 9.1. Last change: 2024 Jun 17 +*options.txt* For Vim version 9.1. Last change: 2024 Jun 19 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2151,6 +2151,11 @@ A jump table for the options with a short description can be found at |Q_op|. difference how completion candidates are reduced from the list of alternatives, but not how the candidates are collected (using different completion types). + fuzzycollect + Enable fuzzy collection for default keyword completion. + This allows the collection of matches using fuzzy matching + criteria, providing more comprehensive and flexible + results. Works in combination with other fuzzy options. *'completepopup'* *'cpp'* 'completepopup' 'cpp' string (default empty) diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index 86dfe6da4d..e33b8fa70f 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2024 Jun 18 +*version9.txt* For Vim version 9.1. Last change: 2024 Jun 19 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41554,7 +41554,7 @@ Enum support for Vim9 script |:enum| *new-other-9.2* Other new features ~ ------------------ -The comment plugin |comment-install| is included. +The new plugins |comment-install| and |nohlsearch-install| are included. Support for Wayland UI. @@ -41634,7 +41634,8 @@ Improved visual highlighting. Python3 support in OpenVMS. -Support |fuzzy-matching| during |ins-completion| with "fuzzy" item for 'completeopt' +Support for |fuzzy-matching| during |ins-completion| with the "fuzzy" and +"fuzzycollect" values of the 'completeopt' setting ============================================================================== COMPILE TIME CHANGES *compile-changes-9.2* @@ -41643,6 +41644,8 @@ Support for building with Ruby 3.3. Support for building Vim 9 in z/OS (MVS). +Clean-up old MS-Windows code. + ============================================================================== PATCHES *patches-9.2* *bug-fixes-9.2* *patches-after-9.1* diff --git a/src/insexpand.c b/src/insexpand.c index c673df927c..78fea51272 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -4100,8 +4100,7 @@ find_comp_when_fuzzy(void) int is_backward = compl_shows_dir_backward(); compl_T *comp = NULL; - if (compl_match_array == NULL || - (is_forward && compl_selected_item == compl_match_arraysize - 1) + if ((is_forward && compl_selected_item == compl_match_arraysize - 1) || (is_backward && compl_selected_item == 0)) return compl_first_match; @@ -4508,6 +4507,11 @@ ins_compl_use_match(int c) static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col) { + int i; + int char_len; + size_t fuzzy_len; + char_u *fuzzy_pattern; + if ((compl_cont_status & CONT_SOL) || ctrl_x_mode_path_defines()) { if (!compl_status_adding()) @@ -4622,6 +4626,38 @@ get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col) compl_patternlen = STRLEN(compl_pattern); + if ((get_cot_flags() & COT_FUZZYCOLLECT) != 0) + { + // Adjust size to avoid buffer overflow + fuzzy_len = (size_t)compl_length * 5 + 10; + // Allocate enough space + fuzzy_pattern = alloc(fuzzy_len); + if (fuzzy_pattern == NULL) + { + compl_patternlen = 0; + return FAIL; + } + // Use 'very magic' mode for simpler syntax + STRCPY(fuzzy_pattern, "\\v"); + i = 2; // Start from 2 to skip "\\v" + while (i < compl_length + 2) + { + // Append "\\k*" before each character + STRNCAT(fuzzy_pattern, "\\k*", fuzzy_len - STRLEN(fuzzy_pattern) - 1); + // Get length of current multi-byte character + char_len = mb_ptr2len(compl_pattern + i); + // Concatenate the character safely + STRNCAT(fuzzy_pattern, compl_pattern + i, char_len); + // Move to the next character + i += char_len; + } + // Append "\\k*" at the end to match any characters after the pattern + STRNCAT(fuzzy_pattern, "\\k*", fuzzy_len - STRLEN(fuzzy_pattern) - 1); + vim_free(compl_pattern); + compl_pattern = fuzzy_pattern; + compl_patternlen = STRLEN(compl_pattern); + } + return OK; } diff --git a/src/option.h b/src/option.h index 91d8d95c5b..67d0b04620 100644 --- a/src/option.h +++ b/src/option.h @@ -520,13 +520,14 @@ EXTERN unsigned cot_flags; // flags from 'completeopt' #define COT_ANY_MENU 0x003 // combination of menu flags #define COT_LONGEST 0x004 // FALSE: insert full match, // TRUE: insert longest prefix -#define COT_PREVIEW 0x008 -#define COT_POPUP 0x010 -#define COT_POPUPHIDDEN 0x020 -#define COT_ANY_PREVIEW 0x038 // combination of preview flags -#define COT_NOINSERT 0x040 // FALSE: select & insert, TRUE: noinsert -#define COT_NOSELECT 0x080 // FALSE: select & insert, TRUE: noselect -#define COT_FUZZY 0x100 // TRUE: fuzzy match enabled +#define COT_PREVIEW 0x008 +#define COT_POPUP 0x010 +#define COT_POPUPHIDDEN 0x020 +#define COT_ANY_PREVIEW 0x038 // combination of preview flags +#define COT_NOINSERT 0x040 // FALSE: select & insert, TRUE: noinsert +#define COT_NOSELECT 0x080 // FALSE: select & insert, TRUE: noselect +#define COT_FUZZY 0x100 // TRUE: fuzzy match enabled +#define COT_FUZZYCOLLECT 0x200 // TRUE: fuzzy collect enabled #ifdef BACKSLASH_IN_FILENAME EXTERN char_u *p_csl; // 'completeslash' #endif diff --git a/src/optionstr.c b/src/optionstr.c index d72298194a..170d48e9a2 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -118,7 +118,7 @@ static char *(p_fdm_values[]) = {"manual", "expr", "marker", "indent", "syntax", NULL}; static char *(p_fcl_values[]) = {"all", NULL}; #endif -static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview", "popup", "popuphidden", "noinsert", "noselect", "fuzzy", NULL}; +static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview", "popup", "popuphidden", "noinsert", "noselect", "fuzzy", "fuzzycollect", NULL}; #ifdef BACKSLASH_IN_FILENAME static char *(p_csl_values[]) = {"slash", "backslash", NULL}; #endif diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index 48589ce188..61c8ac7643 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -2586,6 +2586,37 @@ func Test_complete_fuzzy_match() call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') call assert_equal('hello help hero h', getline('.')) + set completeopt=fuzzycollect + call setline(1, ['xyz yxz x']) + call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') + call assert_equal('xyz yxz xyz', getline('.')) + " can fuzzy get yxz when use Ctrl-N twice + call setline(1, ['xyz yxz x']) + call feedkeys("A\<C-X>\<C-N>\<C-N>\<Esc>0", 'tx!') + call assert_equal('xyz yxz yxz', getline('.')) + + call setline(1, ['one two o']) + call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') + call assert_equal('one two one', getline('.')) + + call setline(1, ['你好 你']) + call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') + call assert_equal('你好 你好', getline('.')) + call setline(1, ['你的 我的 的']) + call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') + call assert_equal('你的 我的 你的', getline('.')) + " can fuzzy get multiple-byte word when use Ctrl-N twice + call setline(1, ['你的 我的 的']) + call feedkeys("A\<C-X>\<C-N>\<C-N>\<Esc>0", 'tx!') + call assert_equal('你的 我的 我的', getline('.')) + + "respect noinsert + set completeopt=fuzzycollect,menu,menuone,noinsert + call setline(1, ['one two o']) + call feedkeys("A\<C-X>\<C-N>", 'tx') + call assert_equal('one', g:word) + call assert_equal('one two o', getline('.')) + " clean up set omnifunc= bw! diff --git a/src/version.c b/src/version.c index 3afaefa480..a366f35af8 100644 --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 503, +/**/ 502, /**/ 501, |