]> granicus.if.org Git - vim/commitdiff
patch 8.2.1587: loop for handling keys for the command line is too long v8.2.1587
authorBram Moolenaar <Bram@vim.org>
Fri, 4 Sep 2020 13:37:31 +0000 (15:37 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 4 Sep 2020 13:37:31 +0000 (15:37 +0200)
Problem:    Loop for handling keys for the command line is too long.
Solution:   Move wild menu handling to separate functions. (Yegappan
            Lakshmanan, closes #6856)

src/cmdexpand.c
src/ex_getln.c
src/proto/cmdexpand.pro
src/version.c

index fe82ab7d4ae8520adfca367860af6f30cfbb3a46..79fb006b24e6f250d19f6e762c635f1823ba7e6e 100644 (file)
@@ -2614,6 +2614,255 @@ globpath(
     vim_free(buf);
 }
 
+#ifdef FEAT_WILDMENU
+
+/*
+ * Translate some keys pressed when 'wildmenu' is used.
+ */
+    int
+wildmenu_translate_key(
+       cmdline_info_T  *cclp,
+       int             key,
+       expand_T        *xp,
+       int             did_wild_list)
+{
+    int c = key;
+
+    if (did_wild_list && p_wmnu)
+    {
+       if (c == K_LEFT)
+           c = Ctrl_P;
+       else if (c == K_RIGHT)
+           c = Ctrl_N;
+    }
+    // Hitting CR after "emenu Name.": complete submenu
+    if (xp->xp_context == EXPAND_MENUNAMES && p_wmnu
+           && cclp->cmdpos > 1
+           && cclp->cmdbuff[cclp->cmdpos - 1] == '.'
+           && cclp->cmdbuff[cclp->cmdpos - 2] != '\\'
+           && (c == '\n' || c == '\r' || c == K_KENTER))
+       c = K_DOWN;
+
+    return c;
+}
+
+/*
+ * Delete characters on the command line, from "from" to the current
+ * position.
+ */
+    static void
+cmdline_del(cmdline_info_T *cclp, int from)
+{
+    mch_memmove(cclp->cmdbuff + from, cclp->cmdbuff + cclp->cmdpos,
+           (size_t)(cclp->cmdlen - cclp->cmdpos + 1));
+    cclp->cmdlen -= cclp->cmdpos - from;
+    cclp->cmdpos = from;
+}
+
+/*
+ * Handle a key pressed when wild menu is displayed
+ */
+    int
+wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp)
+{
+    int                c = key;
+    int                i;
+    int                j;
+
+    if (!p_wmnu)
+       return c;
+
+    // Special translations for 'wildmenu'
+    if (xp->xp_context == EXPAND_MENUNAMES)
+    {
+       // Hitting <Down> after "emenu Name.": complete submenu
+       if (c == K_DOWN && cclp->cmdpos > 0
+               && cclp->cmdbuff[cclp->cmdpos - 1] == '.')
+           c = p_wc;
+       else if (c == K_UP)
+       {
+           // Hitting <Up>: Remove one submenu name in front of the
+           // cursor
+           int found = FALSE;
+
+           j = (int)(xp->xp_pattern - cclp->cmdbuff);
+           i = 0;
+           while (--j > 0)
+           {
+               // check for start of menu name
+               if (cclp->cmdbuff[j] == ' '
+                       && cclp->cmdbuff[j - 1] != '\\')
+               {
+                   i = j + 1;
+                   break;
+               }
+               // check for start of submenu name
+               if (cclp->cmdbuff[j] == '.'
+                       && cclp->cmdbuff[j - 1] != '\\')
+               {
+                   if (found)
+                   {
+                       i = j + 1;
+                       break;
+                   }
+                   else
+                       found = TRUE;
+               }
+           }
+           if (i > 0)
+               cmdline_del(cclp, i);
+           c = p_wc;
+           xp->xp_context = EXPAND_NOTHING;
+       }
+    }
+    if ((xp->xp_context == EXPAND_FILES
+               || xp->xp_context == EXPAND_DIRECTORIES
+               || xp->xp_context == EXPAND_SHELLCMD))
+    {
+       char_u upseg[5];
+
+       upseg[0] = PATHSEP;
+       upseg[1] = '.';
+       upseg[2] = '.';
+       upseg[3] = PATHSEP;
+       upseg[4] = NUL;
+
+       if (c == K_DOWN
+               && cclp->cmdpos > 0
+               && cclp->cmdbuff[cclp->cmdpos - 1] == PATHSEP
+               && (cclp->cmdpos < 3
+                   || cclp->cmdbuff[cclp->cmdpos - 2] != '.'
+                   || cclp->cmdbuff[cclp->cmdpos - 3] != '.'))
+       {
+           // go down a directory
+           c = p_wc;
+       }
+       else if (STRNCMP(xp->xp_pattern, upseg + 1, 3) == 0 && c == K_DOWN)
+       {
+           // If in a direct ancestor, strip off one ../ to go down
+           int found = FALSE;
+
+           j = cclp->cmdpos;
+           i = (int)(xp->xp_pattern - cclp->cmdbuff);
+           while (--j > i)
+           {
+               if (has_mbyte)
+                   j -= (*mb_head_off)(cclp->cmdbuff, cclp->cmdbuff + j);
+               if (vim_ispathsep(cclp->cmdbuff[j]))
+               {
+                   found = TRUE;
+                   break;
+               }
+           }
+           if (found
+                   && cclp->cmdbuff[j - 1] == '.'
+                   && cclp->cmdbuff[j - 2] == '.'
+                   && (vim_ispathsep(cclp->cmdbuff[j - 3]) || j == i + 2))
+           {
+               cmdline_del(cclp, j - 2);
+               c = p_wc;
+           }
+       }
+       else if (c == K_UP)
+       {
+           // go up a directory
+           int found = FALSE;
+
+           j = cclp->cmdpos - 1;
+           i = (int)(xp->xp_pattern - cclp->cmdbuff);
+           while (--j > i)
+           {
+               if (has_mbyte)
+                   j -= (*mb_head_off)(cclp->cmdbuff, cclp->cmdbuff + j);
+               if (vim_ispathsep(cclp->cmdbuff[j])
+# ifdef BACKSLASH_IN_FILENAME
+                       && vim_strchr((char_u *)" *?[{`$%#",
+                           cclp->cmdbuff[j + 1]) == NULL
+# endif
+                  )
+               {
+                   if (found)
+                   {
+                       i = j + 1;
+                       break;
+                   }
+                   else
+                       found = TRUE;
+               }
+           }
+
+           if (!found)
+               j = i;
+           else if (STRNCMP(cclp->cmdbuff + j, upseg, 4) == 0)
+               j += 4;
+           else if (STRNCMP(cclp->cmdbuff + j, upseg + 1, 3) == 0
+                   && j == i)
+               j += 3;
+           else
+               j = 0;
+           if (j > 0)
+           {
+               // TODO this is only for DOS/UNIX systems - need to put in
+               // machine-specific stuff here and in upseg init
+               cmdline_del(cclp, j);
+               put_on_cmdline(upseg + 1, 3, FALSE);
+           }
+           else if (cclp->cmdpos > i)
+               cmdline_del(cclp, i);
+
+           // Now complete in the new directory. Set KeyTyped in case the
+           // Up key came from a mapping.
+           c = p_wc;
+           KeyTyped = TRUE;
+       }
+    }
+
+    return c;
+}
+
+/*
+ * Free expanded names when finished walking through the matches
+ */
+    void
+wildmenu_cleanup(cmdline_info_T *cclp)
+{
+    int skt = KeyTyped;
+    int old_RedrawingDisabled = RedrawingDisabled;
+
+    if (!p_wmnu || wild_menu_showing == 0)
+       return;
+
+    if (cclp->input_fn)
+       RedrawingDisabled = 0;
+
+    if (wild_menu_showing == WM_SCROLLED)
+    {
+       // Entered command line, move it up
+       cmdline_row--;
+       redrawcmd();
+    }
+    else if (save_p_ls != -1)
+    {
+       // restore 'laststatus' and 'winminheight'
+       p_ls = save_p_ls;
+       p_wmh = save_p_wmh;
+       last_status(FALSE);
+       update_screen(VALID);   // redraw the screen NOW
+       redrawcmd();
+       save_p_ls = -1;
+    }
+    else
+    {
+       win_redraw_last_status(topframe);
+       redraw_statuslines();
+    }
+    KeyTyped = skt;
+    wild_menu_showing = 0;
+    if (cclp->input_fn)
+       RedrawingDisabled = old_RedrawingDisabled;
+}
+#endif
+
 #if defined(FEAT_EVAL) || defined(PROTO)
 /*
  * "getcompletion()" function
index bc193a209af4fba0ce09bf75d3044debe7f99773..eb922a1c4dc35298eb7a31cc5002a18de6b948c8 100644 (file)
@@ -44,9 +44,6 @@ static void   draw_cmdline(int start, int len);
 static void    save_cmdline(cmdline_info_T *ccp);
 static void    restore_cmdline(cmdline_info_T *ccp);
 static int     cmdline_paste(int regname, int literally, int remcr);
-#ifdef FEAT_WILDMENU
-static void    cmdline_del(int from);
-#endif
 static void    redrawcmdprompt(void);
 static int     ccheck_abbr(int);
 
@@ -1064,21 +1061,7 @@ getcmdline_int(
            c = Ctrl_P;
 
 #ifdef FEAT_WILDMENU
-       // Special translations for 'wildmenu'
-       if (did_wild_list && p_wmnu)
-       {
-           if (c == K_LEFT)
-               c = Ctrl_P;
-           else if (c == K_RIGHT)
-               c = Ctrl_N;
-       }
-       // Hitting CR after "emenu Name.": complete submenu
-       if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu
-               && ccline.cmdpos > 1
-               && ccline.cmdbuff[ccline.cmdpos - 1] == '.'
-               && ccline.cmdbuff[ccline.cmdpos - 2] != '\\'
-               && (c == '\n' || c == '\r' || c == K_KENTER))
-           c = K_DOWN;
+       c = wildmenu_translate_key(&ccline, c, &xpc, did_wild_list);
 #endif
 
        // free expanded names when finished walking through matches
@@ -1095,190 +1078,13 @@ getcmdline_int(
                xpc.xp_context = EXPAND_NOTHING;
            wim_index = 0;
 #ifdef FEAT_WILDMENU
-           if (p_wmnu && wild_menu_showing != 0)
-           {
-               int skt = KeyTyped;
-               int old_RedrawingDisabled = RedrawingDisabled;
-
-               if (ccline.input_fn)
-                   RedrawingDisabled = 0;
-
-               if (wild_menu_showing == WM_SCROLLED)
-               {
-                   // Entered command line, move it up
-                   cmdline_row--;
-                   redrawcmd();
-               }
-               else if (save_p_ls != -1)
-               {
-                   // restore 'laststatus' and 'winminheight'
-                   p_ls = save_p_ls;
-                   p_wmh = save_p_wmh;
-                   last_status(FALSE);
-                   update_screen(VALID);       // redraw the screen NOW
-                   redrawcmd();
-                   save_p_ls = -1;
-               }
-               else
-               {
-                   win_redraw_last_status(topframe);
-                   redraw_statuslines();
-               }
-               KeyTyped = skt;
-               wild_menu_showing = 0;
-               if (ccline.input_fn)
-                   RedrawingDisabled = old_RedrawingDisabled;
-           }
+           wildmenu_cleanup(&ccline);
 #endif
        }
 
 #ifdef FEAT_WILDMENU
-       // Special translations for 'wildmenu'
-       if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu)
-       {
-           // Hitting <Down> after "emenu Name.": complete submenu
-           if (c == K_DOWN && ccline.cmdpos > 0
-                                 && ccline.cmdbuff[ccline.cmdpos - 1] == '.')
-               c = p_wc;
-           else if (c == K_UP)
-           {
-               // Hitting <Up>: Remove one submenu name in front of the
-               // cursor
-               int found = FALSE;
-
-               j = (int)(xpc.xp_pattern - ccline.cmdbuff);
-               i = 0;
-               while (--j > 0)
-               {
-                   // check for start of menu name
-                   if (ccline.cmdbuff[j] == ' '
-                           && ccline.cmdbuff[j - 1] != '\\')
-                   {
-                       i = j + 1;
-                       break;
-                   }
-                   // check for start of submenu name
-                   if (ccline.cmdbuff[j] == '.'
-                           && ccline.cmdbuff[j - 1] != '\\')
-                   {
-                       if (found)
-                       {
-                           i = j + 1;
-                           break;
-                       }
-                       else
-                           found = TRUE;
-                   }
-               }
-               if (i > 0)
-                   cmdline_del(i);
-               c = p_wc;
-               xpc.xp_context = EXPAND_NOTHING;
-           }
-       }
-       if ((xpc.xp_context == EXPAND_FILES
-                             || xpc.xp_context == EXPAND_DIRECTORIES
-                             || xpc.xp_context == EXPAND_SHELLCMD) && p_wmnu)
-       {
-           char_u upseg[5];
-
-           upseg[0] = PATHSEP;
-           upseg[1] = '.';
-           upseg[2] = '.';
-           upseg[3] = PATHSEP;
-           upseg[4] = NUL;
-
-           if (c == K_DOWN
-                   && ccline.cmdpos > 0
-                   && ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP
-                   && (ccline.cmdpos < 3
-                       || ccline.cmdbuff[ccline.cmdpos - 2] != '.'
-                       || ccline.cmdbuff[ccline.cmdpos - 3] != '.'))
-           {
-               // go down a directory
-               c = p_wc;
-           }
-           else if (STRNCMP(xpc.xp_pattern, upseg + 1, 3) == 0 && c == K_DOWN)
-           {
-               // If in a direct ancestor, strip off one ../ to go down
-               int found = FALSE;
-
-               j = ccline.cmdpos;
-               i = (int)(xpc.xp_pattern - ccline.cmdbuff);
-               while (--j > i)
-               {
-                   if (has_mbyte)
-                       j -= (*mb_head_off)(ccline.cmdbuff, ccline.cmdbuff + j);
-                   if (vim_ispathsep(ccline.cmdbuff[j]))
-                   {
-                       found = TRUE;
-                       break;
-                   }
-               }
-               if (found
-                       && ccline.cmdbuff[j - 1] == '.'
-                       && ccline.cmdbuff[j - 2] == '.'
-                       && (vim_ispathsep(ccline.cmdbuff[j - 3]) || j == i + 2))
-               {
-                   cmdline_del(j - 2);
-                   c = p_wc;
-               }
-           }
-           else if (c == K_UP)
-           {
-               // go up a directory
-               int found = FALSE;
-
-               j = ccline.cmdpos - 1;
-               i = (int)(xpc.xp_pattern - ccline.cmdbuff);
-               while (--j > i)
-               {
-                   if (has_mbyte)
-                       j -= (*mb_head_off)(ccline.cmdbuff, ccline.cmdbuff + j);
-                   if (vim_ispathsep(ccline.cmdbuff[j])
-# ifdef BACKSLASH_IN_FILENAME
-                           && vim_strchr((char_u *)" *?[{`$%#",
-                               ccline.cmdbuff[j + 1]) == NULL
-# endif
-                      )
-                   {
-                       if (found)
-                       {
-                           i = j + 1;
-                           break;
-                       }
-                       else
-                           found = TRUE;
-                   }
-               }
-
-               if (!found)
-                   j = i;
-               else if (STRNCMP(ccline.cmdbuff + j, upseg, 4) == 0)
-                   j += 4;
-               else if (STRNCMP(ccline.cmdbuff + j, upseg + 1, 3) == 0
-                            && j == i)
-                   j += 3;
-               else
-                   j = 0;
-               if (j > 0)
-               {
-                   // TODO this is only for DOS/UNIX systems - need to put in
-                   // machine-specific stuff here and in upseg init
-                   cmdline_del(j);
-                   put_on_cmdline(upseg + 1, 3, FALSE);
-               }
-               else if (ccline.cmdpos > i)
-                   cmdline_del(i);
-
-               // Now complete in the new directory. Set KeyTyped in case the
-               // Up key came from a mapping.
-               c = p_wc;
-               KeyTyped = TRUE;
-           }
-       }
-
-#endif // FEAT_WILDMENU
+       c = wildmenu_process_key(&ccline, c, &xpc);
+#endif
 
        // CTRL-\ CTRL-N goes to Normal mode, CTRL-\ CTRL-G goes to Insert
        // mode when 'insertmode' is set, CTRL-\ e prompts for an expression.
@@ -3660,21 +3466,6 @@ cmdline_paste_str(char_u *s, int literally)
        }
 }
 
-#ifdef FEAT_WILDMENU
-/*
- * Delete characters on the command line, from "from" to the current
- * position.
- */
-    static void
-cmdline_del(int from)
-{
-    mch_memmove(ccline.cmdbuff + from, ccline.cmdbuff + ccline.cmdpos,
-           (size_t)(ccline.cmdlen - ccline.cmdpos + 1));
-    ccline.cmdlen -= ccline.cmdpos - from;
-    ccline.cmdpos = from;
-}
-#endif
-
 /*
  * This function is called when the screen size changes and with incremental
  * search and in other situations where the command line may have been
index 523565942dae6e50e532c2c156f48c1d3582f5f6..1c4f95439484f2c7f828e5a6abfec1f4c4307dc6 100644 (file)
@@ -9,5 +9,8 @@ char_u *addstar(char_u *fname, int len, int context);
 void set_cmd_context(expand_T *xp, char_u *str, int len, int col, int use_ccline);
 int expand_cmdline(expand_T *xp, char_u *str, int col, int *matchcount, char_u ***matches);
 void globpath(char_u *path, char_u *file, garray_T *ga, int expand_options);
+int wildmenu_translate_key(cmdline_info_T *cclp, int key, expand_T *xp, int did_wild_list);
+int wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp);
+void wildmenu_cleanup(cmdline_info_T *cclp);
 void f_getcompletion(typval_T *argvars, typval_T *rettv);
 /* vim: set ft=c : */
index 86c2cfe50f45c78e2c3d6d2a6b30f45bca96316a..92ff1e9bb5f7dccd8ed172fc8a419367e1c5f7a3 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1587,
 /**/
     1586,
 /**/