]> granicus.if.org Git - vim/commitdiff
patch 8.2.4479: no fuzzy completieon for maps and abbreviations v8.2.4479
authorYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 27 Feb 2022 12:07:30 +0000 (12:07 +0000)
committerBram Moolenaar <Bram@vim.org>
Sun, 27 Feb 2022 12:07:30 +0000 (12:07 +0000)
Problem:    No fuzzy completieon for maps and abbreviations.
Solution:   Fuzzy complete maps and abbreviations. (Yegappan Lakshmanan,
            closes #9856)

src/cmdexpand.c
src/map.c
src/proto/map.pro
src/search.c
src/testdir/test_cmdline.vim
src/version.c

index 003f6daf1e70dd3b1c410940fa08dd78bb748ce2..84dc64342430c5b727608ce5a596922dab2255c8 100644 (file)
@@ -56,7 +56,6 @@ cmdline_fuzzy_completion_supported(expand_T *xp)
            && 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
@@ -1216,10 +1215,12 @@ set_cmd_index(char_u *cmd, exarg_T *eap, expand_T *xp, int *complp)
 
     // 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 '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 (*cmd == 'k' && cmd[1] != 'e')
+    if (!fuzzy && (*cmd == 'k' && cmd[1] != 'e'))
     {
        eap->cmdidx = CMD_k;
        p = cmd + 1;
@@ -2596,7 +2597,7 @@ ExpandFromContext(
            || xp->xp_context == EXPAND_BOOL_SETTINGS)
        ret = ExpandSettings(xp, &regmatch, pat, numMatches, matches);
     else if (xp->xp_context == EXPAND_MAPPINGS)
-       ret = ExpandMappings(&regmatch, numMatches, matches);
+       ret = ExpandMappings(pat, &regmatch, numMatches, matches);
 # if defined(FEAT_EVAL)
     else if (xp->xp_context == EXPAND_USER_DEFINED)
        ret = ExpandUserDefined(xp, &regmatch, matches, numMatches);
@@ -2712,7 +2713,8 @@ ExpandGeneric(
                fuzmatch = ALLOC_MULT(fuzmatch_str_T, count);
            else
                *matches = ALLOC_MULT(char_u *, count);
-           if ((fuzzy && (fuzmatch == NULL)) || (*matches == NULL))
+           if ((!fuzzy && (*matches == NULL))
+                                       || (fuzzy && (fuzmatch == NULL)))
            {
                *numMatches = 0;
                *matches = NULL;
index b681d2ff2b32996979e02f9e46918dc034979d67..594c934d23e1f78597a039d0f93aadb3904e912f 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -1257,9 +1257,10 @@ set_context_in_map_cmd(
  */
     int
 ExpandMappings(
+    char_u     *pat,
     regmatch_T *regmatch,
-    int                *num_file,
-    char_u     ***file)
+    int                *numMatches,
+    char_u     ***matches)
 {
     mapblock_T *mp;
     int                hash;
@@ -1267,11 +1268,17 @@ ExpandMappings(
     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();
 
-    *num_file = 0;                 // return values in case of FAIL
-    *file = NULL;
+    *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,6 +1286,7 @@ ExpandMappings(
     {
        count = 0;
 
+       // First search in map modifier arguments
        for (i = 0; i < 7; ++i)
        {
            if (i == 0)
@@ -1300,13 +1308,29 @@ ExpandMappings(
            else
                continue;
 
-           if (vim_regexec(regmatch, p, (colnr_T)0))
+           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 (round == 1)
-                   ++count;
+               if (fuzzy)
+               {
+                   fuzmatch[count].idx = count;
+                   fuzmatch[count].str = vim_strsave(p);
+                   fuzmatch[count].score = score;
+               }
                else
-                   (*file)[count++] = vim_strsave(p);
+                   (*matches)[count] = vim_strsave(p);
            }
+           ++count;
        }
 
        for (hash = 0; hash < 256; ++hash)
@@ -1326,14 +1350,31 @@ ExpandMappings(
                if (mp->m_mode & expand_mapmodes)
                {
                    p = translate_mapping(mp->m_keys);
-                   if (p != NULL && vim_regexec(regmatch, p, (colnr_T)0))
+                   if (p != NULL)
                    {
-                       if (round == 1)
-                           ++count;
+                       if (!fuzzy)
+                           match = vim_regexec(regmatch, p, (colnr_T)0);
                        else
                        {
-                           (*file)[count++] = p;
-                           p = NULL;
+                           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,12 +1387,25 @@ ExpandMappings(
 
        if (round == 1)
        {
-           *file = ALLOC_MULT(char_u *, count);
-           if (*file == NULL)
-               return FAIL;
+           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,10 +1413,12 @@ ExpandMappings(
        char_u  **ptr3;
 
        // Sort the matches
-       sort_strings(*file, count);
+       // Fuzzy matching already sorts the matches
+       if (!fuzzy)
+           sort_strings(*matches, count);
 
        // Remove multiple entries
-       ptr1 = *file;
+       ptr1 = *matches;
        ptr2 = ptr1 + 1;
        ptr3 = ptr1 + count;
 
@@ -1378,7 +1434,7 @@ ExpandMappings(
        }
     }
 
-    *num_file = count;
+    *numMatches = count;
     return (count == 0 ? FAIL : OK);
 }
 
index 42ebd4b61331d738bcadcc0528a0f0a315c7179c..8b8bc062461d2f3afbe67303570f2020b5dfcb4d 100644 (file)
@@ -8,7 +8,7 @@ int mode_str2flags(char_u *modechars);
 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 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);
index 063058d326f09729ec7c8dfc99bcfa5c9574915c..98241a471c7f807f78ba3d44ca8063cbd368f0b6 100644 (file)
@@ -5006,7 +5006,7 @@ fuzzy_match_str(char_u *str, char_u *pat)
     if (str == NULL || pat == NULL)
        return 0;
 
-    fuzzy_match(str, pat, FALSE, &score, matchpos,
+    fuzzy_match(str, pat, TRUE, &score, matchpos,
                                sizeof(matchpos) / sizeof(matchpos[0]));
 
     return score;
index 2fc19c6fb42d4e62368022d2968e1934ed62262a..d7e46d989811c2410c18570ece44e4c01e69923e 100644 (file)
@@ -2658,11 +2658,52 @@ func Test_wildoptions_fuzzy()
   call feedkeys(":mapclear buf\<Tab>\<C-B>\"\<CR>", 'tx')
   call assert_equal('"mapclear <buffer>', @:)
 
-  " map name fuzzy completion - NOT supported
+  " 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,6 +2833,16 @@ func Test_wildoptions_fuzzy()
   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
index c77f76134cc828d42b0d6862e254d6660ab490d0..a8c0bdc553228c1a6b6d94ff4b2bd370ef0601b8 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4479,
 /**/
     4478,
 /**/