patch 9.1.1639: completion: popup may be misplaced
Problem: During commandline completiom, popup window placement can be
incorrect when 'noselect' is present in 'wildmode'
(Shane-XB-Qian)
Solution: Disable "showtail" feature when 'noselect' is present.
fixes: #17969
closes: #18001
Signed-off-by: Girish Palya <girishji@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
a09b1604d4
commit
1e38198a41
@ -342,7 +342,7 @@ nextwild(
|
|||||||
{
|
{
|
||||||
size_t plen = STRLEN(p);
|
size_t plen = STRLEN(p);
|
||||||
int difflen;
|
int difflen;
|
||||||
int v;
|
int v = OK;
|
||||||
|
|
||||||
difflen = (int)plen - xp->xp_pattern_len;
|
difflen = (int)plen - xp->xp_pattern_len;
|
||||||
if (ccline->cmdlen + difflen + 4 > ccline->cmdbufflen)
|
if (ccline->cmdlen + difflen + 4 > ccline->cmdbufflen)
|
||||||
@ -350,8 +350,7 @@ nextwild(
|
|||||||
v = realloc_cmdbuff(ccline->cmdlen + difflen + 4);
|
v = realloc_cmdbuff(ccline->cmdlen + difflen + 4);
|
||||||
xp->xp_pattern = ccline->cmdbuff + i;
|
xp->xp_pattern = ccline->cmdbuff + i;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
v = OK;
|
|
||||||
if (v == OK)
|
if (v == OK)
|
||||||
{
|
{
|
||||||
mch_memmove(&ccline->cmdbuff[ccline->cmdpos + difflen],
|
mch_memmove(&ccline->cmdbuff[ccline->cmdpos + difflen],
|
||||||
@ -395,7 +394,7 @@ cmdline_pum_create(
|
|||||||
int showtail)
|
int showtail)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int columns;
|
int prefix_len;
|
||||||
|
|
||||||
// Add all the completion matches
|
// Add all the completion matches
|
||||||
compl_match_array = ALLOC_MULT(pumitem_T, numMatches);
|
compl_match_array = ALLOC_MULT(pumitem_T, numMatches);
|
||||||
@ -415,13 +414,11 @@ cmdline_pum_create(
|
|||||||
|
|
||||||
// Compute the popup menu starting column
|
// Compute the popup menu starting column
|
||||||
compl_startcol = ccline == NULL ? 0 : vim_strsize(ccline->cmdbuff) + 1;
|
compl_startcol = ccline == NULL ? 0 : vim_strsize(ccline->cmdbuff) + 1;
|
||||||
columns = vim_strsize(xp->xp_pattern);
|
prefix_len = vim_strsize(xp->xp_pattern);
|
||||||
if (showtail)
|
if (showtail)
|
||||||
{
|
prefix_len += vim_strsize(showmatches_gettail(matches[0]))
|
||||||
columns += vim_strsize(showmatches_gettail(matches[0]));
|
- vim_strsize(matches[0]);
|
||||||
columns -= vim_strsize(matches[0]);
|
compl_startcol = MAX(0, compl_startcol - prefix_len);
|
||||||
}
|
|
||||||
compl_startcol = MAX(0, compl_startcol - columns);
|
|
||||||
|
|
||||||
// no default selection
|
// no default selection
|
||||||
compl_selected = -1;
|
compl_selected = -1;
|
||||||
@ -1279,12 +1276,12 @@ showmatches_oneline(
|
|||||||
* be inserted like a normal character.
|
* be inserted like a normal character.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
showmatches(expand_T *xp, int wildmenu UNUSED)
|
showmatches(expand_T *xp, int wildmenu, int noselect)
|
||||||
{
|
{
|
||||||
cmdline_info_T *ccline = get_cmdline_info();
|
cmdline_info_T *ccline = get_cmdline_info();
|
||||||
int numMatches;
|
int numMatches;
|
||||||
char_u **matches;
|
char_u **matches;
|
||||||
int i, j;
|
int i;
|
||||||
int maxlen;
|
int maxlen;
|
||||||
int lines;
|
int lines;
|
||||||
int columns;
|
int columns;
|
||||||
@ -1300,12 +1297,13 @@ showmatches(expand_T *xp, int wildmenu UNUSED)
|
|||||||
|
|
||||||
if (xp->xp_numfiles == -1)
|
if (xp->xp_numfiles == -1)
|
||||||
{
|
{
|
||||||
|
int retval;
|
||||||
set_expand_context(xp);
|
set_expand_context(xp);
|
||||||
i = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos,
|
retval = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos,
|
||||||
&numMatches, &matches);
|
&numMatches, &matches);
|
||||||
|
if (retval != EXPAND_OK)
|
||||||
|
return retval;
|
||||||
showtail = expand_showtail(xp);
|
showtail = expand_showtail(xp);
|
||||||
if (i != EXPAND_OK)
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1316,7 +1314,8 @@ showmatches(expand_T *xp, int wildmenu UNUSED)
|
|||||||
|
|
||||||
if (wildmenu && vim_strchr(p_wop, WOP_PUM) != NULL)
|
if (wildmenu && vim_strchr(p_wop, WOP_PUM) != NULL)
|
||||||
// cmdline completion popup menu (with wildoptions=pum)
|
// cmdline completion popup menu (with wildoptions=pum)
|
||||||
return cmdline_pum_create(ccline, xp, matches, numMatches, showtail);
|
return cmdline_pum_create(ccline, xp, matches, numMatches,
|
||||||
|
showtail && !noselect);
|
||||||
|
|
||||||
if (!wildmenu)
|
if (!wildmenu)
|
||||||
{
|
{
|
||||||
@ -1339,17 +1338,18 @@ showmatches(expand_T *xp, int wildmenu UNUSED)
|
|||||||
maxlen = 0;
|
maxlen = 0;
|
||||||
for (i = 0; i < numMatches; ++i)
|
for (i = 0; i < numMatches; ++i)
|
||||||
{
|
{
|
||||||
|
int len;
|
||||||
if (!showtail && (xp->xp_context == EXPAND_FILES
|
if (!showtail && (xp->xp_context == EXPAND_FILES
|
||||||
|| xp->xp_context == EXPAND_SHELLCMD
|
|| xp->xp_context == EXPAND_SHELLCMD
|
||||||
|| xp->xp_context == EXPAND_BUFFERS))
|
|| xp->xp_context == EXPAND_BUFFERS))
|
||||||
{
|
{
|
||||||
home_replace(NULL, matches[i], NameBuff, MAXPATHL, TRUE);
|
home_replace(NULL, matches[i], NameBuff, MAXPATHL, TRUE);
|
||||||
j = vim_strsize(NameBuff);
|
len = vim_strsize(NameBuff);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
j = vim_strsize(SHOW_MATCH(i));
|
len = vim_strsize(SHOW_MATCH(i));
|
||||||
if (j > maxlen)
|
if (len > maxlen)
|
||||||
maxlen = j;
|
maxlen = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xp->xp_context == EXPAND_TAGS_LISTFILES)
|
if (xp->xp_context == EXPAND_TAGS_LISTFILES)
|
||||||
|
|||||||
@ -946,10 +946,11 @@ cmdline_wildchar_complete(
|
|||||||
int res;
|
int res;
|
||||||
int j;
|
int j;
|
||||||
int options = WILD_NO_BEEP;
|
int options = WILD_NO_BEEP;
|
||||||
|
int noselect = (wim_flags[0] & WIM_NOSELECT) != 0;
|
||||||
|
|
||||||
if (wim_flags[wim_index] & WIM_BUFLASTUSED)
|
if (wim_flags[wim_index] & WIM_BUFLASTUSED)
|
||||||
options |= WILD_BUFLASTUSED;
|
options |= WILD_BUFLASTUSED;
|
||||||
if (wim_flags[0] & WIM_NOSELECT)
|
if (noselect)
|
||||||
options |= WILD_KEEP_SOLE_ITEM;
|
options |= WILD_KEEP_SOLE_ITEM;
|
||||||
if (xp->xp_numfiles > 0) // typed p_wc at least twice
|
if (xp->xp_numfiles > 0) // typed p_wc at least twice
|
||||||
{
|
{
|
||||||
@ -960,7 +961,8 @@ cmdline_wildchar_complete(
|
|||||||
|| (p_wmnu && (wim_flags[wim_index] & WIM_FULL) != 0)))
|
|| (p_wmnu && (wim_flags[wim_index] & WIM_FULL) != 0)))
|
||||||
{
|
{
|
||||||
(void)showmatches(xp,
|
(void)showmatches(xp,
|
||||||
p_wmnu && ((wim_flags[wim_index] & WIM_LIST) == 0));
|
p_wmnu && ((wim_flags[wim_index] & WIM_LIST) == 0),
|
||||||
|
noselect);
|
||||||
redrawcmd();
|
redrawcmd();
|
||||||
*did_wild_list = TRUE;
|
*did_wild_list = TRUE;
|
||||||
}
|
}
|
||||||
@ -1011,7 +1013,7 @@ cmdline_wildchar_complete(
|
|||||||
// "list", or no change and 'wildmode' contains "longest,list",
|
// "list", or no change and 'wildmode' contains "longest,list",
|
||||||
// list all matches
|
// list all matches
|
||||||
if (res == OK
|
if (res == OK
|
||||||
&& xp->xp_numfiles > ((wim_flags[wim_index] & WIM_NOSELECT) ? 0 : 1))
|
&& xp->xp_numfiles > (noselect ? 0 : 1))
|
||||||
{
|
{
|
||||||
// a "longest" that didn't do anything is skipped (but not
|
// a "longest" that didn't do anything is skipped (but not
|
||||||
// "list:longest")
|
// "list:longest")
|
||||||
@ -1031,7 +1033,7 @@ cmdline_wildchar_complete(
|
|||||||
p_wmnu = p_wmnu_save;
|
p_wmnu = p_wmnu_save;
|
||||||
}
|
}
|
||||||
(void)showmatches(xp, p_wmnu
|
(void)showmatches(xp, p_wmnu
|
||||||
&& ((wim_flags[wim_index] & WIM_LIST) == 0));
|
&& ((wim_flags[wim_index] & WIM_LIST) == 0), noselect);
|
||||||
redrawcmd();
|
redrawcmd();
|
||||||
*did_wild_list = TRUE;
|
*did_wild_list = TRUE;
|
||||||
if (wim_flags[wim_index] & WIM_LONGEST)
|
if (wim_flags[wim_index] & WIM_LONGEST)
|
||||||
@ -2013,7 +2015,8 @@ getcmdline_int(
|
|||||||
{
|
{
|
||||||
if (cmdline_pum_active())
|
if (cmdline_pum_active())
|
||||||
{
|
{
|
||||||
skip_pum_redraw = skip_pum_redraw && (vim_isprintc(c)
|
skip_pum_redraw = skip_pum_redraw && !key_is_wc
|
||||||
|
&& (vim_isprintc(c)
|
||||||
|| c == K_BS || c == Ctrl_H || c == K_DEL
|
|| c == K_BS || c == Ctrl_H || c == K_DEL
|
||||||
|| c == K_KDEL || c == Ctrl_W || c == Ctrl_U);
|
|| c == K_KDEL || c == Ctrl_W || c == Ctrl_U);
|
||||||
cmdline_pum_remove(&ccline, skip_pum_redraw);
|
cmdline_pum_remove(&ccline, skip_pum_redraw);
|
||||||
@ -2124,7 +2127,8 @@ getcmdline_int(
|
|||||||
{
|
{
|
||||||
// Trigger the popup menu when wildoptions=pum
|
// Trigger the popup menu when wildoptions=pum
|
||||||
showmatches(&xpc, p_wmnu
|
showmatches(&xpc, p_wmnu
|
||||||
&& ((wim_flags[wim_index] & WIM_LIST) == 0));
|
&& ((wim_flags[wim_index] & WIM_LIST) == 0),
|
||||||
|
wim_flags[0] & WIM_NOSELECT);
|
||||||
}
|
}
|
||||||
if (nextwild(&xpc, WILD_PREV, 0, firstc != '@') == OK
|
if (nextwild(&xpc, WILD_PREV, 0, firstc != '@') == OK
|
||||||
&& nextwild(&xpc, WILD_PREV, 0, firstc != '@') == OK)
|
&& nextwild(&xpc, WILD_PREV, 0, firstc != '@') == OK)
|
||||||
@ -2239,7 +2243,8 @@ getcmdline_int(
|
|||||||
goto cmdline_not_changed;
|
goto cmdline_not_changed;
|
||||||
|
|
||||||
case Ctrl_D:
|
case Ctrl_D:
|
||||||
if (showmatches(&xpc, FALSE) == EXPAND_NOTHING)
|
if (showmatches(&xpc, FALSE, wim_flags[0] & WIM_NOSELECT)
|
||||||
|
== EXPAND_NOTHING)
|
||||||
break; // Use ^D as normal char instead
|
break; // Use ^D as normal char instead
|
||||||
|
|
||||||
redrawcmd();
|
redrawcmd();
|
||||||
|
|||||||
@ -12,7 +12,7 @@ char_u *ExpandOne(expand_T *xp, char_u *str, char_u *orig, int options, int mode
|
|||||||
void ExpandInit(expand_T *xp);
|
void ExpandInit(expand_T *xp);
|
||||||
void ExpandCleanup(expand_T *xp);
|
void ExpandCleanup(expand_T *xp);
|
||||||
void clear_cmdline_orig(void);
|
void clear_cmdline_orig(void);
|
||||||
int showmatches(expand_T *xp, int wildmenu);
|
int showmatches(expand_T *xp, int wildmenu, int noselect);
|
||||||
char_u *addstar(char_u *fname, int len, int context);
|
char_u *addstar(char_u *fname, int len, int context);
|
||||||
void set_expand_context(expand_T *xp);
|
void set_expand_context(expand_T *xp);
|
||||||
void set_cmd_context(expand_T *xp, char_u *str, int len, int col, int use_ccline);
|
void set_cmd_context(expand_T *xp, char_u *str, int len, int col, int use_ccline);
|
||||||
|
|||||||
8
src/testdir/dumps/Test_expand_env_var_1.dump
Normal file
8
src/testdir/dumps/Test_expand_env_var_1.dump
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
| +0&#ffffff0@74
|
||||||
|
|~+0#4040ff13&| @73
|
||||||
|
|~| @73
|
||||||
|
|~| @73
|
||||||
|
|~| | +0#0000001#ffd7ff255|a|/|b|/|c|/| @8| +0#4040ff13#ffffff0@56
|
||||||
|
|~| | +0#0000001#ffd7ff255|a|/|b|/|f|i|l|e|X|n|a|m|e|1| | +0#4040ff13#ffffff0@56
|
||||||
|
|~| | +0#0000001#ffd7ff255|a|/|b|/|f|i|l|e|X|n|a|m|e|2| | +0#4040ff13#ffffff0@56
|
||||||
|
|:+0#0000000&|e| |$|T|E|S|T|D|I|R|/> @62
|
||||||
8
src/testdir/dumps/Test_expand_env_var_2.dump
Normal file
8
src/testdir/dumps/Test_expand_env_var_2.dump
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
| +0&#ffffff0@74
|
||||||
|
|~+0#4040ff13&| @73
|
||||||
|
|~| @73
|
||||||
|
|~| @73
|
||||||
|
|~| | +0#0000001#e0e0e08|a|/|b|/|c|/| @8| +0#4040ff13#ffffff0@56
|
||||||
|
|~| | +0#0000001#ffd7ff255|a|/|b|/|f|i|l|e|X|n|a|m|e|1| | +0#4040ff13#ffffff0@56
|
||||||
|
|~| | +0#0000001#ffd7ff255|a|/|b|/|f|i|l|e|X|n|a|m|e|2| | +0#4040ff13#ffffff0@56
|
||||||
|
|:+0#0000000&|e| |a|/|b|/|c|/> @65
|
||||||
@ -4859,4 +4859,34 @@ func Test_wildtrigger_update_screen()
|
|||||||
cnoremap <buffer> <F8> <C-R>=wildtrigger()[-1]<CR>
|
cnoremap <buffer> <F8> <C-R>=wildtrigger()[-1]<CR>
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Issue #17969: With 'noselect', the popup menu should appear next to the
|
||||||
|
" environment variable being expanded. Disable 'showtail' when completing
|
||||||
|
" file paths when 'noselect' is present.
|
||||||
|
func Test_noselect_expand_env_var()
|
||||||
|
CheckScreendump
|
||||||
|
|
||||||
|
let lines =<< trim [SCRIPT]
|
||||||
|
set wildmenu wildoptions=pum wildmode=noselect,full
|
||||||
|
let $TESTDIR = 'a/b'
|
||||||
|
[SCRIPT]
|
||||||
|
call writefile(lines, 'XTest_wildmenu', 'D')
|
||||||
|
let buf = RunVimInTerminal('-S XTest_wildmenu', {'rows': 8})
|
||||||
|
|
||||||
|
call mkdir('a/b/c', 'pR')
|
||||||
|
call writefile(['asdf'], 'a/b/fileXname1')
|
||||||
|
call writefile(['foo'], 'a/b/fileXname2')
|
||||||
|
|
||||||
|
call term_sendkeys(buf, ":e $TESTDIR/\<Tab>")
|
||||||
|
call VerifyScreenDump(buf, 'Test_expand_env_var_1', {})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, "\<C-N>")
|
||||||
|
call VerifyScreenDump(buf, 'Test_expand_env_var_2', {})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, "\<C-P>")
|
||||||
|
call VerifyScreenDump(buf, 'Test_expand_env_var_1', {})
|
||||||
|
" clean up
|
||||||
|
call term_sendkeys(buf, "\<Esc>")
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
|||||||
@ -719,6 +719,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1639,
|
||||||
/**/
|
/**/
|
||||||
1638,
|
1638,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
Reference in New Issue
Block a user