Patch 8.2.4479
Problem: No fuzzy completieon for maps and abbreviations.
Solution: Fuzzy complete maps and abbreviations. (Yegappan Lakshmanan,
closes #9856)
Files: src/cmdexpand.c, src/map.c, src/proto/map.pro, src/search.c,
src/testdir/test_cmdline.vim
*** ../vim-8.2.4478/src/cmdexpand.c 2022-02-26 16:05:05.030403209 +0000
--- src/cmdexpand.c 2022-02-27 12:01:28.427935734 +0000
***************
*** 56,62 ****
&& xp->xp_context != EXPAND_FILES_IN_PATH
&& xp->xp_context != EXPAND_FILETYPE
&& xp->xp_context != EXPAND_HELP
- && xp->xp_context != EXPAND_MAPPINGS
&& xp->xp_context != EXPAND_OLD_SETTING
&& xp->xp_context != EXPAND_OWNSYNTAX
&& xp->xp_context != EXPAND_PACKADD
--- 56,61 ----
***************
*** 1216,1225 ****
// Isolate the command and search for it in the command table.
// Exceptions:
! // - the 'k' command can directly be followed by any character, but
! // do accept "keepmarks", "keepalt" and "keepjumps".
// - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
! if (*cmd == 'k' && cmd[1] != 'e')
{
eap->cmdidx = CMD_k;
p = cmd + 1;
--- 1215,1226 ----
// Isolate the command and search for it in the command table.
// Exceptions:
! // - the 'k' command can directly be followed by any character, but do
! // accept "keepmarks", "keepalt" and "keepjumps". As fuzzy matching can
! // find matches anywhere in the command name, do this only for command
! // expansion based on regular expression and not for fuzzy matching.
// - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
! if (!fuzzy && (*cmd == 'k' && cmd[1] != 'e'))
{
eap->cmdidx = CMD_k;
p = cmd + 1;
***************
*** 2596,2602 ****
|| xp->xp_context == EXPAND_BOOL_SETTINGS)
ret = ExpandSettings(xp, ®match, pat, numMatches, matches);
else if (xp->xp_context == EXPAND_MAPPINGS)
! ret = ExpandMappings(®match, numMatches, matches);
# if defined(FEAT_EVAL)
else if (xp->xp_context == EXPAND_USER_DEFINED)
ret = ExpandUserDefined(xp, ®match, matches, numMatches);
--- 2597,2603 ----
|| xp->xp_context == EXPAND_BOOL_SETTINGS)
ret = ExpandSettings(xp, ®match, pat, numMatches, matches);
else if (xp->xp_context == EXPAND_MAPPINGS)
! ret = ExpandMappings(pat, ®match, numMatches, matches);
# if defined(FEAT_EVAL)
else if (xp->xp_context == EXPAND_USER_DEFINED)
ret = ExpandUserDefined(xp, ®match, matches, numMatches);
***************
*** 2712,2718 ****
fuzmatch = ALLOC_MULT(fuzmatch_str_T, count);
else
*matches = ALLOC_MULT(char_u *, count);
! if ((fuzzy && (fuzmatch == NULL)) || (*matches == NULL))
{
*numMatches = 0;
*matches = NULL;
--- 2713,2720 ----
fuzmatch = ALLOC_MULT(fuzmatch_str_T, count);
else
*matches = ALLOC_MULT(char_u *, count);
! if ((!fuzzy && (*matches == NULL))
! || (fuzzy && (fuzmatch == NULL)))
{
*numMatches = 0;
*matches = NULL;
*** ../vim-8.2.4478/src/map.c 2022-02-16 18:27:32.583437344 +0000
--- src/map.c 2022-02-27 12:01:28.427935734 +0000
***************
*** 1257,1265 ****
*/
int
ExpandMappings(
regmatch_T *regmatch,
! int *num_file,
! char_u ***file)
{
mapblock_T *mp;
int hash;
--- 1257,1266 ----
*/
int
ExpandMappings(
+ char_u *pat,
regmatch_T *regmatch,
! int *numMatches,
! char_u ***matches)
{
mapblock_T *mp;
int hash;
***************
*** 1267,1277 ****
int round;
char_u *p;
int i;
validate_maphash();
! *num_file = 0; // return values in case of FAIL
! *file = NULL;
// round == 1: Count the matches.
// round == 2: Build the array to keep the matches.
--- 1268,1284 ----
int round;
char_u *p;
int i;
+ int fuzzy;
+ int match;
+ int score;
+ fuzmatch_str_T *fuzmatch = NULL;
+
+ fuzzy = cmdline_fuzzy_complete(pat);
validate_maphash();
! *numMatches = 0; // return values in case of FAIL
! *matches = NULL;
// round == 1: Count the matches.
// round == 2: Build the array to keep the matches.
***************
*** 1279,1284 ****
--- 1286,1292 ----
{
count = 0;
+ // First search in map modifier arguments
for (i = 0; i < 7; ++i)
{
if (i == 0)
***************
*** 1300,1312 ****
else
continue;
! if (vim_regexec(regmatch, p, (colnr_T)0))
{
! if (round == 1)
! ++count;
else
! (*file)[count++] = vim_strsave(p);
}
}
for (hash = 0; hash < 256; ++hash)
--- 1308,1336 ----
else
continue;
! if (!fuzzy)
! match = vim_regexec(regmatch, p, (colnr_T)0);
! else
! {
! score = fuzzy_match_str(p, pat);
! match = (score != 0);
! }
!
! if (!match)
! continue;
!
! if (round == 2)
{
! if (fuzzy)
! {
! fuzmatch[count].idx = count;
! fuzmatch[count].str = vim_strsave(p);
! fuzmatch[count].score = score;
! }
else
! (*matches)[count] = vim_strsave(p);
}
+ ++count;
}
for (hash = 0; hash < 256; ++hash)
***************
*** 1326,1339 ****
if (mp->m_mode & expand_mapmodes)
{
p = translate_mapping(mp->m_keys);
! if (p != NULL && vim_regexec(regmatch, p, (colnr_T)0))
{
! if (round == 1)
! ++count;
else
{
! (*file)[count++] = p;
! p = NULL;
}
}
vim_free(p);
--- 1350,1380 ----
if (mp->m_mode & expand_mapmodes)
{
p = translate_mapping(mp->m_keys);
! if (p != NULL)
{
! if (!fuzzy)
! match = vim_regexec(regmatch, p, (colnr_T)0);
else
{
! score = fuzzy_match_str(p, pat);
! match = (score != 0);
! }
!
! if (match)
! {
! if (round == 2)
! {
! if (fuzzy)
! {
! fuzmatch[count].idx = count;
! fuzmatch[count].str = p;
! fuzmatch[count].score = score;
! }
! else
! (*matches)[count] = p;
! p = NULL;
! }
! ++count;
}
}
vim_free(p);
***************
*** 1346,1357 ****
if (round == 1)
{
! *file = ALLOC_MULT(char_u *, count);
! if (*file == NULL)
! return FAIL;
}
} // for (round)
if (count > 1)
{
char_u **ptr1;
--- 1387,1411 ----
if (round == 1)
{
! if (fuzzy)
! {
! fuzmatch = ALLOC_MULT(fuzmatch_str_T, count);
! if (fuzmatch == NULL)
! return FAIL;
! }
! else
! {
! *matches = ALLOC_MULT(char_u *, count);
! if (*matches == NULL)
! return FAIL;
! }
}
} // for (round)
+ if (fuzzy && fuzzymatches_to_strmatches(fuzmatch, matches, count,
+ FALSE) == FAIL)
+ return FAIL;
+
if (count > 1)
{
char_u **ptr1;
***************
*** 1359,1368 ****
char_u **ptr3;
// Sort the matches
! sort_strings(*file, count);
// Remove multiple entries
! ptr1 = *file;
ptr2 = ptr1 + 1;
ptr3 = ptr1 + count;
--- 1413,1424 ----
char_u **ptr3;
// Sort the matches
! // Fuzzy matching already sorts the matches
! if (!fuzzy)
! sort_strings(*matches, count);
// Remove multiple entries
! ptr1 = *matches;
ptr2 = ptr1 + 1;
ptr3 = ptr1 + count;
***************
*** 1378,1384 ****
}
}
! *num_file = count;
return (count == 0 ? FAIL : OK);
}
--- 1434,1440 ----
}
}
! *numMatches = count;
return (count == 0 ? FAIL : OK);
}
*** ../vim-8.2.4478/src/proto/map.pro 2022-01-11 11:58:14.920745981 +0000
--- src/proto/map.pro 2022-02-27 12:01:28.431935722 +0000
***************
*** 8,14 ****
int map_to_exists(char_u *str, char_u *modechars, int abbr);
int map_to_exists_mode(char_u *rhs, int mode, int abbr);
char_u *set_context_in_map_cmd(expand_T *xp, char_u *cmd, char_u *arg, int
forceit, int isabbrev, int isunmap, cmdidx_T cmdidx);
! int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file);
int check_abbr(int c, char_u *ptr, int col, int mincol);
char_u *eval_map_expr(mapblock_T *mp, int c);
char_u *vim_strsave_escape_csi(char_u *p);
--- 8,14 ----
int map_to_exists(char_u *str, char_u *modechars, int abbr);
int map_to_exists_mode(char_u *rhs, int mode, int abbr);
char_u *set_context_in_map_cmd(expand_T *xp, char_u *cmd, char_u *arg, int
forceit, int isabbrev, int isunmap, cmdidx_T cmdidx);
! int ExpandMappings(char_u *pat, regmatch_T *regmatch, int *num_file, char_u
***file);
int check_abbr(int c, char_u *ptr, int col, int mincol);
char_u *eval_map_expr(mapblock_T *mp, int c);
char_u *vim_strsave_escape_csi(char_u *p);
*** ../vim-8.2.4478/src/search.c 2022-02-25 15:24:21.049157319 +0000
--- src/search.c 2022-02-27 12:01:28.431935722 +0000
***************
*** 5006,5012 ****
if (str == NULL || pat == NULL)
return 0;
! fuzzy_match(str, pat, FALSE, &score, matchpos,
sizeof(matchpos) / sizeof(matchpos[0]));
return score;
--- 5006,5012 ----
if (str == NULL || pat == NULL)
return 0;
! fuzzy_match(str, pat, TRUE, &score, matchpos,
sizeof(matchpos) / sizeof(matchpos[0]));
return score;
*** ../vim-8.2.4478/src/testdir/test_cmdline.vim 2022-02-26
16:05:05.030403209 +0000
--- src/testdir/test_cmdline.vim 2022-02-27 12:01:28.431935722 +0000
***************
*** 2658,2668 ****
call feedkeys(":mapclear buf\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"mapclear <buffer>', @:)
! " map name fuzzy completion - NOT supported
" test regex completion works
set wildoptions=fuzzy
call feedkeys(":cnoremap <ex\<Tab> <esc> \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"cnoremap <expr> <esc> \<Tab>", @:)
" menu name fuzzy completion
if has('gui_running')
--- 2658,2709 ----
call feedkeys(":mapclear buf\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"mapclear <buffer>', @:)
! " map name fuzzy completion
" test regex completion works
set wildoptions=fuzzy
call feedkeys(":cnoremap <ex\<Tab> <esc> \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"cnoremap <expr> <esc> \<Tab>", @:)
+ nmap <plug>MyLongMap :p<CR>
+ call feedkeys(":nmap MLM\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <Plug>MyLongMap", @:)
+ call feedkeys(":nmap MLM \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap MLM \t", @:)
+ call feedkeys(":nmap <F2> one two \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <F2> one two \t", @:)
+ " duplicate entries should be removed
+ vmap <plug>MyLongMap :<C-U>#<CR>
+ call feedkeys(":nmap MLM\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <Plug>MyLongMap", @:)
+ nunmap <plug>MyLongMap
+ vunmap <plug>MyLongMap
+ call feedkeys(":nmap ABC\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap ABC\t", @:)
+ " results should be sorted by best match
+ nmap <Plug>format :
+ nmap <Plug>goformat :
+ nmap <Plug>TestFOrmat :
+ nmap <Plug>fendoff :
+ nmap <Plug>state :
+ nmap <Plug>FendingOff :
+ call feedkeys(":nmap <Plug>fo\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <Plug>format <Plug>TestFOrmat <Plug>FendingOff
<Plug>goformat <Plug>fendoff", @:)
+ nunmap <Plug>format
+ nunmap <Plug>goformat
+ nunmap <Plug>TestFOrmat
+ nunmap <Plug>fendoff
+ nunmap <Plug>state
+ nunmap <Plug>FendingOff
+
+ " abbreviation fuzzy completion
+ set wildoptions=fuzzy
+ call feedkeys(":iabbr wait\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"iabbr <nowait>", @:)
+ iabbr WaitForCompletion WFC
+ call feedkeys(":iabbr fcl\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"iabbr WaitForCompletion", @:)
+ call feedkeys(":iabbr a1z\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"iabbr a1z\t", @:)
+ iunabbrev WaitForCompletion
" menu name fuzzy completion
if has('gui_running')
***************
*** 2792,2797 ****
--- 2833,2848 ----
call assert_equal('"Foo2Bar', @:)
delcommand Foo2Bar
+ " Test for command completion for a command starting with 'k'
+ command KillKillKill :
+ set wildoptions&
+ call feedkeys(":killkill\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"killkill\<Tab>", @:)
+ set wildoptions=fuzzy
+ call feedkeys(":killkill\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"KillKillKill', @:)
+ delcom KillKillKill
+
set wildoptions&
%bw!
endfunc
*** ../vim-8.2.4478/src/version.c 2022-02-26 16:05:05.034403199 +0000
--- src/version.c 2022-02-27 12:04:06.599471869 +0000
***************
*** 756,757 ****
--- 756,759 ----
{ /* Add new patch number below this line */
+ /**/
+ 4479,
/**/
--
hundred-and-one symptoms of being an internet addict:
114. You are counting items, you go "0,1,2,3,4,5,6,7,8,9,A,B,C,D...".
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/20220227120810.C80481C14BE%40moolenaar.net.