From 3908ef5017a6b4425727013588f72cc7343199b9 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Tue, 8 Feb 2022 12:08:07 +0000 Subject: 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) --- src/cmdexpand.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 3 deletions(-) (limited to 'src/cmdexpand.c') diff --git a/src/cmdexpand.c b/src/cmdexpand.c index b75903df98..b37c4f9acb 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -25,6 +25,16 @@ static int expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, int f #if defined(FEAT_EVAL) static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file); 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 @@ -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; @@ -553,6 +610,35 @@ showmatches(expand_T *xp, int wildmenu UNUSED) showtail = cmd_showtail; } +#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) { @@ -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 -- cgit v1.2.3