mirror of
https://github.com/neovim/neovim.git
synced 2025-10-14 13:56:05 +00:00
vim-patch:9.1.1676: completion: long line shown twice
Problem: completion: long line shown twice
(Maxim Kim)
Solution: Fix the issue, disable an incorrect test.
(Girish Palya)
fixes: vim/vim#18035
closes: vim/vim#18088
57379302aa
Omit removal of blank line in Test_noselect_expand_env_var() as it's
added again in patch 9.1.1682.
Cherry-pick two blank lines in Test_long_line_noselect() from patch
9.1.1682.
Co-authored-by: Girish Palya <girishji@gmail.com>
This commit is contained in:
@@ -254,6 +254,9 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
|
|||||||
CmdlineInfo *const ccline = get_cmdline_info();
|
CmdlineInfo *const ccline = get_cmdline_info();
|
||||||
char *p;
|
char *p;
|
||||||
bool from_wildtrigger_func = options & WILD_FUNC_TRIGGER;
|
bool from_wildtrigger_func = options & WILD_FUNC_TRIGGER;
|
||||||
|
bool wild_navigate = (type == WILD_NEXT || type == WILD_PREV
|
||||||
|
|| type == WILD_PAGEUP || type == WILD_PAGEDOWN
|
||||||
|
|| type == WILD_PUM_WANT);
|
||||||
|
|
||||||
if (xp->xp_numfiles == -1) {
|
if (xp->xp_numfiles == -1) {
|
||||||
pre_incsearch_pos = xp->xp_pre_incsearch_pos;
|
pre_incsearch_pos = xp->xp_pre_incsearch_pos;
|
||||||
@@ -292,15 +295,13 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
|
|||||||
|
|
||||||
// If cmd_silent is set then don't show the dots, because redrawcmd() below
|
// If cmd_silent is set then don't show the dots, because redrawcmd() below
|
||||||
// won't remove them.
|
// won't remove them.
|
||||||
if (!cmd_silent && !from_wildtrigger_func
|
if (!cmd_silent && !from_wildtrigger_func && !wild_navigate
|
||||||
&& !(ui_has(kUICmdline) || ui_has(kUIWildmenu))) {
|
&& !(ui_has(kUICmdline) || ui_has(kUIWildmenu))) {
|
||||||
msg_puts("..."); // show that we are busy
|
msg_puts("..."); // show that we are busy
|
||||||
ui_flush();
|
ui_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == WILD_NEXT || type == WILD_PREV
|
if (wild_navigate) {
|
||||||
|| type == WILD_PAGEUP || type == WILD_PAGEDOWN
|
|
||||||
|| type == WILD_PUM_WANT) {
|
|
||||||
// Get next/previous match for a previous expanded pattern.
|
// Get next/previous match for a previous expanded pattern.
|
||||||
p = ExpandOne(xp, NULL, NULL, 0, type);
|
p = ExpandOne(xp, NULL, NULL, 0, type);
|
||||||
} else {
|
} else {
|
||||||
@@ -313,7 +314,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
|
|||||||
tmp = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
|
tmp = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
|
||||||
}
|
}
|
||||||
// Translate string into pattern and expand it.
|
// Translate string into pattern and expand it.
|
||||||
const int use_options = ((options & ~WILD_KEEP_SOLE_ITEM)
|
const int use_options = (options
|
||||||
| WILD_HOME_REPLACE
|
| WILD_HOME_REPLACE
|
||||||
| WILD_ADD_SLASH
|
| WILD_ADD_SLASH
|
||||||
| WILD_SILENT
|
| WILD_SILENT
|
||||||
@@ -337,7 +338,13 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p != NULL && !got_int) {
|
// Save cmdline before inserting selected item
|
||||||
|
if (!wild_navigate && ccline->cmdbuff != NULL) {
|
||||||
|
xfree(cmdline_orig);
|
||||||
|
cmdline_orig = xstrnsave(ccline->cmdbuff, (size_t)ccline->cmdlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p != NULL && !got_int && !(options & WILD_NOSELECT)) {
|
||||||
size_t plen = strlen(p);
|
size_t plen = strlen(p);
|
||||||
int difflen = (int)plen - (int)(xp->xp_pattern_len);
|
int difflen = (int)plen - (int)(xp->xp_pattern_len);
|
||||||
if (ccline->cmdlen + difflen + 4 > ccline->cmdbufflen) {
|
if (ccline->cmdlen + difflen + 4 > ccline->cmdbufflen) {
|
||||||
@@ -364,7 +371,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
|
|||||||
|
|
||||||
if (xp->xp_numfiles <= 0 && p == NULL) {
|
if (xp->xp_numfiles <= 0 && p == NULL) {
|
||||||
beep_flush();
|
beep_flush();
|
||||||
} else if (xp->xp_numfiles == 1 && !(options & WILD_KEEP_SOLE_ITEM)) {
|
} else if (xp->xp_numfiles == 1 && !(options & WILD_NOSELECT) && !wild_navigate) {
|
||||||
// free expanded pattern
|
// free expanded pattern
|
||||||
ExpandOne(xp, NULL, NULL, 0, WILD_FREE);
|
ExpandOne(xp, NULL, NULL, 0, WILD_FREE);
|
||||||
}
|
}
|
||||||
@@ -377,7 +384,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
|
|||||||
/// Create and display a cmdline completion popup menu with items from
|
/// Create and display a cmdline completion popup menu with items from
|
||||||
/// "matches".
|
/// "matches".
|
||||||
static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches, int numMatches,
|
static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches, int numMatches,
|
||||||
bool showtail)
|
bool showtail, bool noselect)
|
||||||
{
|
{
|
||||||
assert(numMatches >= 0);
|
assert(numMatches >= 0);
|
||||||
// Add all the completion matches
|
// Add all the completion matches
|
||||||
@@ -403,7 +410,7 @@ static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no default selection
|
// no default selection
|
||||||
compl_selected = -1;
|
compl_selected = noselect ? -1 : 0;
|
||||||
|
|
||||||
pum_clear();
|
pum_clear();
|
||||||
cmdline_pum_display(true);
|
cmdline_pum_display(true);
|
||||||
@@ -925,7 +932,7 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
|
|||||||
cmdline_pum_remove();
|
cmdline_pum_remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xp->xp_selected = 0;
|
xp->xp_selected = (options & WILD_NOSELECT) ? -1 : 0;
|
||||||
|
|
||||||
if (mode == WILD_FREE) { // only release file name
|
if (mode == WILD_FREE) { // only release file name
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1097,12 +1104,6 @@ int showmatches(expand_T *xp, bool wildmenu, bool noselect)
|
|||||||
int columns;
|
int columns;
|
||||||
bool showtail;
|
bool showtail;
|
||||||
|
|
||||||
// Save cmdline before expansion
|
|
||||||
if (ccline->cmdbuff != NULL) {
|
|
||||||
xfree(cmdline_orig);
|
|
||||||
cmdline_orig = xstrnsave(ccline->cmdbuff, (size_t)ccline->cmdlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xp->xp_numfiles == -1) {
|
if (xp->xp_numfiles == -1) {
|
||||||
set_expand_context(xp);
|
set_expand_context(xp);
|
||||||
if (xp->xp_context == EXPAND_LUA) {
|
if (xp->xp_context == EXPAND_LUA) {
|
||||||
@@ -1122,7 +1123,7 @@ int showmatches(expand_T *xp, bool wildmenu, bool noselect)
|
|||||||
|
|
||||||
if (((!ui_has(kUICmdline) || cmdline_win != NULL) && wildmenu && (wop_flags & kOptWopFlagPum))
|
if (((!ui_has(kUICmdline) || cmdline_win != NULL) && wildmenu && (wop_flags & kOptWopFlagPum))
|
||||||
|| ui_has(kUIWildmenu) || (ui_has(kUICmdline) && ui_has(kUIPopupmenu))) {
|
|| ui_has(kUIWildmenu) || (ui_has(kUICmdline) && ui_has(kUIPopupmenu))) {
|
||||||
return cmdline_pum_create(ccline, xp, matches, numMatches, showtail);
|
return cmdline_pum_create(ccline, xp, matches, numMatches, showtail, noselect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wildmenu) {
|
if (!wildmenu) {
|
||||||
@@ -1139,7 +1140,7 @@ int showmatches(expand_T *xp, bool wildmenu, bool noselect)
|
|||||||
if (got_int) {
|
if (got_int) {
|
||||||
got_int = false; // only int. the completion, not the cmd line
|
got_int = false; // only int. the completion, not the cmd line
|
||||||
} else if (wildmenu) {
|
} else if (wildmenu) {
|
||||||
redraw_wildmenu(xp, numMatches, matches, -1, showtail);
|
redraw_wildmenu(xp, numMatches, matches, noselect ? -1 : 0, showtail);
|
||||||
} else {
|
} else {
|
||||||
// find the length of the longest file name
|
// find the length of the longest file name
|
||||||
maxlen = 0;
|
maxlen = 0;
|
||||||
|
@@ -40,7 +40,7 @@ enum {
|
|||||||
WILD_NOERROR = 0x800, ///< sets EW_NOERROR
|
WILD_NOERROR = 0x800, ///< sets EW_NOERROR
|
||||||
WILD_BUFLASTUSED = 0x1000,
|
WILD_BUFLASTUSED = 0x1000,
|
||||||
BUF_DIFF_FILTER = 0x2000,
|
BUF_DIFF_FILTER = 0x2000,
|
||||||
WILD_KEEP_SOLE_ITEM = 0x4000,
|
WILD_NOSELECT = 0x4000,
|
||||||
WILD_MAY_EXPAND_PATTERN = 0x8000,
|
WILD_MAY_EXPAND_PATTERN = 0x8000,
|
||||||
WILD_FUNC_TRIGGER = 0x10000, ///< called from wildtrigger()
|
WILD_FUNC_TRIGGER = 0x10000, ///< called from wildtrigger()
|
||||||
};
|
};
|
||||||
|
@@ -1120,14 +1120,11 @@ static int command_line_wildchar_complete(CommandLineState *s)
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
int options = WILD_NO_BEEP;
|
int options = WILD_NO_BEEP;
|
||||||
bool noselect = (wim_flags[0] & kOptWimFlagNoselect) != 0;
|
bool noselect = p_wmnu && (wim_flags[0] & kOptWimFlagNoselect) != 0;
|
||||||
|
|
||||||
if (wim_flags[s->wim_index] & kOptWimFlagLastused) {
|
if (wim_flags[s->wim_index] & kOptWimFlagLastused) {
|
||||||
options |= WILD_BUFLASTUSED;
|
options |= WILD_BUFLASTUSED;
|
||||||
}
|
}
|
||||||
if (noselect) {
|
|
||||||
options |= WILD_KEEP_SOLE_ITEM;
|
|
||||||
}
|
|
||||||
if (s->xpc.xp_numfiles > 0) { // typed p_wc at least twice
|
if (s->xpc.xp_numfiles > 0) { // typed p_wc at least twice
|
||||||
// if 'wildmode' contains "list" may still need to list
|
// if 'wildmode' contains "list" may still need to list
|
||||||
if (s->xpc.xp_numfiles > 1
|
if (s->xpc.xp_numfiles > 1
|
||||||
@@ -1164,6 +1161,9 @@ static int command_line_wildchar_complete(CommandLineState *s)
|
|||||||
if (wim_flags[0] & kOptWimFlagLongest) {
|
if (wim_flags[0] & kOptWimFlagLongest) {
|
||||||
res = nextwild(&s->xpc, WILD_LONGEST, options, s->firstc != '@');
|
res = nextwild(&s->xpc, WILD_LONGEST, options, s->firstc != '@');
|
||||||
} else {
|
} else {
|
||||||
|
if (noselect || (wim_flags[s->wim_index] & kOptWimFlagList)) {
|
||||||
|
options |= WILD_NOSELECT;
|
||||||
|
}
|
||||||
res = nextwild(&s->xpc, WILD_EXPAND_KEEP, options, s->firstc != '@');
|
res = nextwild(&s->xpc, WILD_EXPAND_KEEP, options, s->firstc != '@');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1188,14 +1188,6 @@ static int command_line_wildchar_complete(CommandLineState *s)
|
|||||||
}
|
}
|
||||||
if ((wim_flags[s->wim_index] & kOptWimFlagList)
|
if ((wim_flags[s->wim_index] & kOptWimFlagList)
|
||||||
|| (p_wmnu && (wim_flags[s->wim_index] & (kOptWimFlagFull|kOptWimFlagNoselect)))) {
|
|| (p_wmnu && (wim_flags[s->wim_index] & (kOptWimFlagFull|kOptWimFlagNoselect)))) {
|
||||||
if (!(wim_flags[0] & kOptWimFlagLongest)) {
|
|
||||||
int p_wmnu_save = p_wmnu;
|
|
||||||
p_wmnu = 0;
|
|
||||||
// remove match
|
|
||||||
nextwild(&s->xpc, WILD_PREV, options, s->firstc != '@');
|
|
||||||
p_wmnu = p_wmnu_save;
|
|
||||||
}
|
|
||||||
|
|
||||||
showmatches(&s->xpc,
|
showmatches(&s->xpc,
|
||||||
p_wmnu && ((wim_flags[s->wim_index] & kOptWimFlagList) == 0),
|
p_wmnu && ((wim_flags[s->wim_index] & kOptWimFlagList) == 0),
|
||||||
noselect);
|
noselect);
|
||||||
@@ -1204,9 +1196,6 @@ static int command_line_wildchar_complete(CommandLineState *s)
|
|||||||
|
|
||||||
if (wim_flags[s->wim_index] & kOptWimFlagLongest) {
|
if (wim_flags[s->wim_index] & kOptWimFlagLongest) {
|
||||||
nextwild(&s->xpc, WILD_LONGEST, options, s->firstc != '@');
|
nextwild(&s->xpc, WILD_LONGEST, options, s->firstc != '@');
|
||||||
} else if ((wim_flags[s->wim_index] & kOptWimFlagFull)
|
|
||||||
&& !(wim_flags[s->wim_index] & kOptWimFlagNoselect)) {
|
|
||||||
nextwild(&s->xpc, WILD_NEXT, options, s->firstc != '@');
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vim_beep(kOptBoFlagWildmode);
|
vim_beep(kOptBoFlagWildmode);
|
||||||
|
@@ -530,6 +530,47 @@ describe('cmdline', function()
|
|||||||
/global^ |
|
/global^ |
|
||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- oldtest: Test_long_line_noselect()
|
||||||
|
it("long line is shown properly with noselect in 'wildmode'", function()
|
||||||
|
local screen = Screen.new(60, 8)
|
||||||
|
exec([[
|
||||||
|
set wildmenu wildoptions=pum wildmode=noselect,full
|
||||||
|
command -nargs=1 -complete=custom,Entries DoubleEntry echo
|
||||||
|
func Entries(a, b, c)
|
||||||
|
return 'loooooooooooooooong quite loooooooooooong, really loooooooooooong, probably too looooooooooooooooooooooooooong entry'
|
||||||
|
endfunc
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed(':DoubleEntry <Tab>')
|
||||||
|
screen:expect([[
|
||||||
|
|
|
||||||
|
{1:~ }|*5
|
||||||
|
{1:~ }{4: loooooooooooooooong quite loooooooooooong, real}|
|
||||||
|
:DoubleEntry ^ |
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed('<C-N>')
|
||||||
|
screen:expect([[
|
||||||
|
|
|
||||||
|
{1:~ }|*3
|
||||||
|
{3: }|
|
||||||
|
:DoubleEntry loooooooooooooooong quite loooooooooooong, real|
|
||||||
|
ly loooooooo{12: loooooooooooooooong quite loooooooooooong, real}|
|
||||||
|
ong entry^ |
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed('<C-N>')
|
||||||
|
screen:expect([[
|
||||||
|
|
|
||||||
|
{1:~ }|*3
|
||||||
|
{3: }{4: loooooooooooooooong quite loooooooooooong, real}|
|
||||||
|
:DoubleEntry ^ |
|
||||||
|
|*2
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed('<Esc>')
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('cmdwin', function()
|
describe('cmdwin', function()
|
||||||
|
@@ -2286,8 +2286,11 @@ func Wildmode_tests()
|
|||||||
" when using longest completion match, matches shorter than the argument
|
" when using longest completion match, matches shorter than the argument
|
||||||
" should be ignored (happens with :help)
|
" should be ignored (happens with :help)
|
||||||
set wildmode=longest,full
|
set wildmode=longest,full
|
||||||
call feedkeys(":help a*\t\<C-B>\"\<CR>", 'xt')
|
" XXX: This test is incorrect. ':help a*' will never yield 'help a'
|
||||||
call assert_equal('"help a', @:)
|
" because '`a' exists as a menu item. The intent was to test a case
|
||||||
|
" handled by nextwild().
|
||||||
|
" call feedkeys(":help a*\t\<C-B>\"\<CR>", 'xt')
|
||||||
|
" call assert_equal('"help a', @:)
|
||||||
" non existing file
|
" non existing file
|
||||||
call feedkeys(":e a1b2y3z4\t\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":e a1b2y3z4\t\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal('"e a1b2y3z4', @:)
|
call assert_equal('"e a1b2y3z4', @:)
|
||||||
@@ -4406,7 +4409,7 @@ func Test_cmdcomplete_info()
|
|||||||
call feedkeys(":h echom\<cr>", "tx") " No expansion
|
call feedkeys(":h echom\<cr>", "tx") " No expansion
|
||||||
call assert_equal('{}', g:cmdcomplete_info)
|
call assert_equal('{}', g:cmdcomplete_info)
|
||||||
call feedkeys($":h echoms{trig}\<cr>", "tx")
|
call feedkeys($":h echoms{trig}\<cr>", "tx")
|
||||||
call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info)
|
call assert_equal('{''cmdline_orig'': ''h echoms'', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info)
|
||||||
call feedkeys($":h echom{trig}\<cr>", "tx")
|
call feedkeys($":h echom{trig}\<cr>", "tx")
|
||||||
call assert_equal(
|
call assert_equal(
|
||||||
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 0, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}',
|
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 0, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}',
|
||||||
@@ -4422,7 +4425,7 @@ func Test_cmdcomplete_info()
|
|||||||
|
|
||||||
set wildoptions=pum
|
set wildoptions=pum
|
||||||
call feedkeys($":h echoms{trig}\<cr>", "tx")
|
call feedkeys($":h echoms{trig}\<cr>", "tx")
|
||||||
call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info)
|
call assert_equal('{''cmdline_orig'': ''h echoms'', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info)
|
||||||
call feedkeys($":h echom{trig}\<cr>", "tx")
|
call feedkeys($":h echom{trig}\<cr>", "tx")
|
||||||
call assert_equal(
|
call assert_equal(
|
||||||
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}',
|
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}',
|
||||||
@@ -4874,4 +4877,33 @@ func Test_cmdline_changed()
|
|||||||
call Ntest_override("char_avail", 0)
|
call Ntest_override("char_avail", 0)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Issue #18035: long lines should not get listed twice in the menu when
|
||||||
|
" 'wildmode' contains 'noselect'
|
||||||
|
func Test_long_line_noselect()
|
||||||
|
CheckScreendump
|
||||||
|
|
||||||
|
let lines =<< trim [SCRIPT]
|
||||||
|
set wildmenu wildoptions=pum wildmode=noselect,full
|
||||||
|
command -nargs=1 -complete=custom,Entries DoubleEntry echo
|
||||||
|
func Entries(a, b, c)
|
||||||
|
return 'loooooooooooooooong quite loooooooooooong, really loooooooooooong, probably too looooooooooooooooooooooooooong entry'
|
||||||
|
endfunc
|
||||||
|
[SCRIPT]
|
||||||
|
call writefile(lines, 'XTest_wildmenu', 'D')
|
||||||
|
let buf = RunVimInTerminal('-S XTest_wildmenu', {'rows': 8, 'cols': 60})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, ":DoubleEntry \<Tab>")
|
||||||
|
call VerifyScreenDump(buf, 'Test_long_line_noselect_1', {})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, "\<Esc>:DoubleEntry \<Tab>\<C-N>")
|
||||||
|
call VerifyScreenDump(buf, 'Test_long_line_noselect_2', {})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, "\<Esc>:DoubleEntry \<Tab>\<C-N>\<C-N>")
|
||||||
|
call VerifyScreenDump(buf, 'Test_long_line_noselect_3', {})
|
||||||
|
|
||||||
|
" clean up
|
||||||
|
call term_sendkeys(buf, "\<Esc>")
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Reference in New Issue
Block a user