Skip to content

Commit f0bf6d7

Browse files
authored
Merge pull request neovim#35673 from zeertzjq/vim-9.1.1676
vim-patch: cmdline completion fixes
2 parents ad22d0a + bea87b4 commit f0bf6d7

File tree

8 files changed

+437
-113
lines changed

8 files changed

+437
-113
lines changed

src/nvim/cmdexpand.c

Lines changed: 62 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
254254
CmdlineInfo *const ccline = get_cmdline_info();
255255
char *p;
256256
bool from_wildtrigger_func = options & WILD_FUNC_TRIGGER;
257+
bool wild_navigate = (type == WILD_NEXT || type == WILD_PREV
258+
|| type == WILD_PAGEUP || type == WILD_PAGEDOWN
259+
|| type == WILD_PUM_WANT);
257260

258261
if (xp->xp_numfiles == -1) {
259262
pre_incsearch_pos = xp->xp_pre_incsearch_pos;
@@ -292,15 +295,13 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
292295

293296
// If cmd_silent is set then don't show the dots, because redrawcmd() below
294297
// won't remove them.
295-
if (!cmd_silent && !from_wildtrigger_func
298+
if (!cmd_silent && !from_wildtrigger_func && !wild_navigate
296299
&& !(ui_has(kUICmdline) || ui_has(kUIWildmenu))) {
297300
msg_puts("..."); // show that we are busy
298301
ui_flush();
299302
}
300303

301-
if (type == WILD_NEXT || type == WILD_PREV
302-
|| type == WILD_PAGEUP || type == WILD_PAGEDOWN
303-
|| type == WILD_PUM_WANT) {
304+
if (wild_navigate) {
304305
// Get next/previous match for a previous expanded pattern.
305306
p = ExpandOne(xp, NULL, NULL, 0, type);
306307
} else {
@@ -313,7 +314,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
313314
tmp = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
314315
}
315316
// Translate string into pattern and expand it.
316-
const int use_options = ((options & ~WILD_KEEP_SOLE_ITEM)
317+
const int use_options = (options
317318
| WILD_HOME_REPLACE
318319
| WILD_ADD_SLASH
319320
| WILD_SILENT
@@ -337,7 +338,13 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
337338
}
338339
}
339340

340-
if (p != NULL && !got_int) {
341+
// Save cmdline before inserting selected item
342+
if (!wild_navigate && ccline->cmdbuff != NULL) {
343+
xfree(cmdline_orig);
344+
cmdline_orig = xstrnsave(ccline->cmdbuff, (size_t)ccline->cmdlen);
345+
}
346+
347+
if (p != NULL && !got_int && !(options & WILD_NOSELECT)) {
341348
size_t plen = strlen(p);
342349
int difflen = (int)plen - (int)(xp->xp_pattern_len);
343350
if (ccline->cmdlen + difflen + 4 > ccline->cmdbufflen) {
@@ -364,7 +371,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
364371

365372
if (xp->xp_numfiles <= 0 && p == NULL) {
366373
beep_flush();
367-
} else if (xp->xp_numfiles == 1 && !(options & WILD_KEEP_SOLE_ITEM)) {
374+
} else if (xp->xp_numfiles == 1 && !(options & WILD_NOSELECT) && !wild_navigate) {
368375
// free expanded pattern
369376
ExpandOne(xp, NULL, NULL, 0, WILD_FREE);
370377
}
@@ -374,10 +381,9 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
374381
return OK;
375382
}
376383

377-
/// Create and display a cmdline completion popup menu with items from
378-
/// "matches".
384+
/// Create completion popup menu with items from "matches".
379385
static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches, int numMatches,
380-
bool showtail)
386+
bool showtail, bool noselect)
381387
{
382388
assert(numMatches >= 0);
383389
// Add all the completion matches
@@ -395,19 +401,13 @@ static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches,
395401
}
396402

397403
// Compute the popup menu starting column
398-
char *endpos = showtail ? showmatches_gettail(xp->xp_pattern, true) : xp->xp_pattern;
404+
char *endpos = showtail ? showmatches_gettail(xp->xp_pattern, noselect) : xp->xp_pattern;
399405
if (ui_has(kUICmdline) && cmdline_win == NULL) {
400406
compl_startcol = (int)(endpos - ccline->cmdbuff);
401407
} else {
402408
compl_startcol = cmd_screencol((int)(endpos - ccline->cmdbuff));
403409
}
404410

405-
// no default selection
406-
compl_selected = -1;
407-
408-
pum_clear();
409-
cmdline_pum_display(true);
410-
411411
return EXPAND_OK;
412412
}
413413

@@ -420,8 +420,7 @@ void cmdline_pum_display(bool changed_array)
420420
/// Returns true if the cmdline completion popup menu is being displayed.
421421
bool cmdline_pum_active(void)
422422
{
423-
// compl_match_array != NULL should already imply pum_visible() in Nvim.
424-
return compl_match_array != NULL;
423+
return pum_visible() && compl_match_array != NULL;
425424
}
426425

427426
/// Remove the cmdline completion popup menu (if present), free the list of items.
@@ -745,11 +744,20 @@ static char *get_next_or_prev_match(int mode, expand_T *xp)
745744
}
746745

747746
// Display matches on screen
748-
if (compl_match_array) {
749-
compl_selected = findex;
750-
cmdline_pum_display(false);
751-
} else if (p_wmnu) {
752-
redraw_wildmenu(xp, xp->xp_numfiles, xp->xp_files, findex, cmd_showtail);
747+
if (p_wmnu) {
748+
if (compl_match_array) {
749+
compl_selected = findex;
750+
cmdline_pum_display(false);
751+
} else if (wop_flags & kOptWopFlagPum) {
752+
if (cmdline_pum_create(get_cmdline_info(), xp, xp->xp_files,
753+
xp->xp_numfiles, cmd_showtail, false) == EXPAND_OK) {
754+
compl_selected = findex;
755+
pum_clear();
756+
cmdline_pum_display(true);
757+
}
758+
} else {
759+
redraw_wildmenu(xp, xp->xp_numfiles, xp->xp_files, findex, cmd_showtail);
760+
}
753761
}
754762

755763
xp->xp_selected = findex;
@@ -925,7 +933,7 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
925933
cmdline_pum_remove();
926934
}
927935
}
928-
xp->xp_selected = 0;
936+
xp->xp_selected = (options & WILD_NOSELECT) ? -1 : 0;
929937

930938
if (mode == WILD_FREE) { // only release file name
931939
return NULL;
@@ -1084,49 +1092,49 @@ static void showmatches_oneline(expand_T *xp, char **matches, int numMatches, in
10841092
}
10851093
}
10861094

1087-
/// Show all matches for completion on the command line.
1088-
/// Returns EXPAND_NOTHING when the character that triggered expansion should
1089-
/// be inserted like a normal character.
1090-
int showmatches(expand_T *xp, bool wildmenu)
1095+
/// Display completion matches.
1096+
/// Returns EXPAND_NOTHING when the character that triggered expansion should be
1097+
/// inserted as a normal character.
1098+
int showmatches(expand_T *xp, bool display_wildmenu, bool display_list, bool noselect)
10911099
{
10921100
CmdlineInfo *const ccline = get_cmdline_info();
10931101
int numMatches;
10941102
char **matches;
1095-
int j;
10961103
int maxlen;
10971104
int lines;
10981105
int columns;
10991106
bool showtail;
11001107

1101-
// Save cmdline before expansion
1102-
if (ccline->cmdbuff != NULL) {
1103-
xfree(cmdline_orig);
1104-
cmdline_orig = xstrnsave(ccline->cmdbuff, (size_t)ccline->cmdlen);
1105-
}
1106-
11071108
if (xp->xp_numfiles == -1) {
11081109
set_expand_context(xp);
11091110
if (xp->xp_context == EXPAND_LUA) {
11101111
nlua_expand_pat(xp);
11111112
}
1112-
int i = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos,
1113-
&numMatches, &matches);
1114-
showtail = expand_showtail(xp);
1115-
if (i != EXPAND_OK) {
1116-
return i;
1113+
int retval = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos,
1114+
&numMatches, &matches);
1115+
if (retval != EXPAND_OK) {
1116+
return retval;
11171117
}
1118+
showtail = expand_showtail(xp);
11181119
} else {
11191120
numMatches = xp->xp_numfiles;
11201121
matches = xp->xp_files;
11211122
showtail = cmd_showtail;
11221123
}
11231124

1124-
if (((!ui_has(kUICmdline) || cmdline_win != NULL) && wildmenu && (wop_flags & kOptWopFlagPum))
1125+
if (((!ui_has(kUICmdline) || cmdline_win != NULL) && display_wildmenu && !display_list
1126+
&& (wop_flags & kOptWopFlagPum))
11251127
|| ui_has(kUIWildmenu) || (ui_has(kUICmdline) && ui_has(kUIPopupmenu))) {
1126-
return cmdline_pum_create(ccline, xp, matches, numMatches, showtail);
1128+
int retval = cmdline_pum_create(ccline, xp, matches, numMatches, showtail, noselect);
1129+
if (retval == EXPAND_OK) {
1130+
compl_selected = noselect ? -1 : 0;
1131+
pum_clear();
1132+
cmdline_pum_display(true);
1133+
}
1134+
return retval;
11271135
}
11281136

1129-
if (!wildmenu) {
1137+
if (display_list) {
11301138
msg_didany = false; // lines_left will be set
11311139
msg_start(); // prepare for paging
11321140
msg_putchar('\n');
@@ -1138,22 +1146,24 @@ int showmatches(expand_T *xp, bool wildmenu)
11381146
}
11391147

11401148
if (got_int) {
1141-
got_int = false; // only int. the completion, not the cmd line
1142-
} else if (wildmenu) {
1143-
redraw_wildmenu(xp, numMatches, matches, -1, showtail);
1144-
} else {
1149+
got_int = false; // only interrupt the completion, not the cmd line
1150+
} else if (display_wildmenu && !display_list) {
1151+
redraw_wildmenu(xp, numMatches, matches, noselect ? -1 : 0,
1152+
showtail); // display statusbar menu
1153+
} else if (display_list) {
11451154
// find the length of the longest file name
11461155
maxlen = 0;
11471156
for (int i = 0; i < numMatches; i++) {
1157+
int len;
11481158
if (!showtail && (xp->xp_context == EXPAND_FILES
11491159
|| xp->xp_context == EXPAND_SHELLCMD
11501160
|| xp->xp_context == EXPAND_BUFFERS)) {
11511161
home_replace(NULL, matches[i], NameBuff, MAXPATHL, true);
1152-
j = vim_strsize(NameBuff);
1162+
len = vim_strsize(NameBuff);
11531163
} else {
1154-
j = vim_strsize(SHOW_MATCH(i));
1164+
len = vim_strsize(SHOW_MATCH(i));
11551165
}
1156-
maxlen = MAX(maxlen, j);
1166+
maxlen = MAX(maxlen, len);
11571167
}
11581168

11591169
if (xp->xp_context == EXPAND_TAGS_LISTFILES) {
@@ -3569,7 +3579,7 @@ int wildmenu_translate_key(CmdlineInfo *cclp, int key, expand_T *xp, bool did_wi
35693579
{
35703580
int c = key;
35713581

3572-
if (did_wild_list) {
3582+
if (cmdline_pum_active() || did_wild_list || wild_menu_showing) {
35733583
if (c == K_LEFT) {
35743584
c = Ctrl_P;
35753585
} else if (c == K_RIGHT) {

src/nvim/cmdexpand.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ enum {
4040
WILD_NOERROR = 0x800, ///< sets EW_NOERROR
4141
WILD_BUFLASTUSED = 0x1000,
4242
BUF_DIFF_FILTER = 0x2000,
43-
WILD_KEEP_SOLE_ITEM = 0x4000,
43+
WILD_NOSELECT = 0x4000,
4444
WILD_MAY_EXPAND_PATTERN = 0x8000,
4545
WILD_FUNC_TRIGGER = 0x10000, ///< called from wildtrigger()
4646
};

0 commit comments

Comments
 (0)