diff src/cmdexpand.c @ 27597:4eb2bf8b2f27 v8.2.4325

patch 8.2.4325: 'wildmenu' only shows few matches Commit: https://github.com/vim/vim/commit/3908ef5017a6b4425727013588f72cc7343199b9 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Tue Feb 8 12:08:07 2022 +0000 patch 8.2.4325: 'wildmenu' only shows few matches Problem: 'wildmenu' only shows few matches. Solution: Add the "pum" option: use a popup menu to show the matches. (Yegappan Lakshmanan et al., closes #9707)
author Bram Moolenaar <Bram@vim.org>
date Tue, 08 Feb 2022 13:15:05 +0100
parents 4c7bb6fd383f
children a74901e95937
line wrap: on
line diff
--- a/src/cmdexpand.c
+++ b/src/cmdexpand.c
@@ -27,6 +27,16 @@ static int	ExpandUserDefined(expand_T *x
 static int	ExpandUserList(expand_T *xp, int *num_file, char_u ***file);
 #endif
 
+#ifdef FEAT_WILDMENU
+// "compl_match_array" points the currently displayed list of entries in the
+// popup menu.  It is NULL when there is no popup menu.
+static pumitem_T *compl_match_array = NULL;
+static int compl_match_arraysize;
+// First column in cmdline of the matched item for completion.
+static int compl_startcol;
+static int compl_selected;
+#endif
+
     static int
 sort_func_compare(const void *s1, const void *s2)
 {
@@ -245,6 +255,42 @@ nextwild(
     return OK;
 }
 
+#if defined(FEAT_WILDMENU) || defined(PROTO)
+/*
+ * Display the cmdline completion matches in a popup menu
+ */
+void cmdline_pum_display(void)
+{
+    pum_display(compl_match_array, compl_match_arraysize, compl_selected);
+}
+
+int cmdline_pum_active(void)
+{
+    return p_wmnu && pum_visible() && compl_match_array != NULL;
+}
+
+/*
+ * Remove the cmdline completion popup menu
+ */
+void cmdline_pum_remove(void)
+{
+    pum_undisplay();
+    VIM_CLEAR(compl_match_array);
+    update_screen(0);
+}
+
+void cmdline_pum_cleanup(cmdline_info_T *cclp)
+{
+    cmdline_pum_remove();
+    wildmenu_cleanup(cclp);
+}
+
+int cmdline_compl_startcol(void)
+{
+    return compl_startcol;
+}
+#endif
+
 /*
  * Do wildcard expansion on the string 'str'.
  * Chars that should not be expanded must be preceded with a backslash.
@@ -327,7 +373,12 @@ ExpandOne(
 		    findex = -1;
 	    }
 #ifdef FEAT_WILDMENU
-	    if (p_wmnu)
+	    if (compl_match_array)
+	    {
+		compl_selected = findex;
+		cmdline_pum_display();
+	    }
+	    else if (p_wmnu)
 		win_redr_status_matches(xp, xp->xp_numfiles, xp->xp_files,
 							findex, cmd_showtail);
 #endif
@@ -339,6 +390,12 @@ ExpandOne(
 	    return NULL;
     }
 
+    if (mode == WILD_CANCEL)
+	ss = vim_strsave(orig_save ? orig_save : (char_u *)"");
+    else if (mode == WILD_APPLY)
+	ss = vim_strsave(findex == -1 ? (orig_save ?
+		    orig_save : (char_u *)"") : xp->xp_files[findex]);
+
     // free old names
     if (xp->xp_numfiles != -1 && mode != WILD_ALL && mode != WILD_LONGEST)
     {
@@ -351,7 +408,7 @@ ExpandOne(
     if (mode == WILD_FREE)	// only release file name
 	return NULL;
 
-    if (xp->xp_numfiles == -1)
+    if (xp->xp_numfiles == -1 && mode != WILD_APPLY && mode != WILD_CANCEL)
     {
 	vim_free(orig_save);
 	orig_save = orig;
@@ -554,6 +611,35 @@ showmatches(expand_T *xp, int wildmenu U
     }
 
 #ifdef FEAT_WILDMENU
+    if (wildmenu && vim_strchr(p_wop, WOP_PUM) != NULL)
+    {
+	compl_match_arraysize = num_files;
+	compl_match_array = ALLOC_MULT(pumitem_T, compl_match_arraysize);
+	for (i = 0; i < num_files; i++)
+	{
+	    compl_match_array[i].pum_text = L_SHOWFILE(i);
+	    compl_match_array[i].pum_info = NULL;
+	    compl_match_array[i].pum_extra = NULL;
+	    compl_match_array[i].pum_kind = NULL;
+	}
+	compl_startcol = ccline->cmdpos + 1;
+	columns = vim_strsize(xp->xp_pattern);
+	if (showtail)
+	{
+	    columns += vim_strsize(sm_gettail(files_found[0]));
+	    columns -= vim_strsize(files_found[0]);
+	}
+	if (columns >= compl_startcol)
+	    compl_startcol = 0;
+	else
+	    compl_startcol -= columns;
+	compl_selected = -1;
+	cmdline_pum_display();
+	return EXPAND_OK;
+    }
+#endif
+
+#ifdef FEAT_WILDMENU
     if (!wildmenu)
     {
 #endif
@@ -1500,7 +1586,7 @@ set_one_cmd_context(
 	case CMD_tjump:
 	case CMD_stjump:
 	case CMD_ptjump:
-	    if (*p_wop != NUL)
+	    if (vim_strchr(p_wop, WOP_TAGFILE) != NULL)
 		xp->xp_context = EXPAND_TAGS_LISTFILES;
 	    else
 		xp->xp_context = EXPAND_TAGS;
@@ -2639,6 +2725,22 @@ wildmenu_translate_key(
 {
     int c = key;
 
+#ifdef FEAT_WILDMENU
+    if (p_wmnu && cmdline_pum_active())
+    {
+	// When the popup menu is used, Up/Down keys go to the previous and
+	// next items in the menu and Left/Right keys go up/down a directory.
+	if (c == K_UP)
+	    c = K_LEFT;
+	else if (c == K_DOWN)
+	    c = K_RIGHT;
+	else if (c == K_LEFT)
+	    c = K_UP;
+	else if (c == K_RIGHT)
+	    c = K_DOWN;
+    }
+#endif
+
     if (did_wild_list && p_wmnu)
     {
 	if (c == K_LEFT)
@@ -2646,6 +2748,7 @@ wildmenu_translate_key(
 	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