summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYee Cheng Chin <ychin.git@gmail.com>2023-10-17 10:56:25 +0200
committerChristian Brabandt <cb@256bit.org>2023-10-17 10:56:25 +0200
commit209ec90b9b9bd948d76511c9cd2b17f47a97afe6 (patch)
tree5a74b51ad3571a32852a7348b77c3637cf8fb8ce
parent396058acd0cc66e5071d052e03d2067b134952af (diff)
patch 9.0.2037: A few remaining cmdline completion issues with C-E/Yv9.0.2037
Problem: A few remaining cmdline completion issues with C-E/Y Solution: Fix cmdline completion fuzzy/Ctrl-E/Ctrl-Y/options when not used at the end Fix cmdline completion fuzzy/Ctrl-E/Ctrl-Y/options when not used at the end A few places in the cmdline completion code only works properly when the user hits Tab (or 'wildchar') at the end of the cmdline, even though it's supposed to work even in the middle of the line. For fuzzy search, `:e ++ff`, and `:set hl=`, fix completion code to make sure to use `xp_pattern_len` instead of assuming the entire `xp_pattern` is the search pattern (since it contains texts after the cursor). Fix Ctrl-E / Ctrl-Y to not jump to the end when canceling/accepting a wildmenu completion. Also, make them work even when not using `set wildoptions+=pum` as there is no drawback to doing so. (Related issue where this was brought up: #13331) closes: #13362 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
-rw-r--r--runtime/doc/index.txt4
-rw-r--r--runtime/doc/options.txt8
-rw-r--r--src/cmdexpand.c2
-rw-r--r--src/ex_docmd.c3
-rw-r--r--src/ex_getln.c13
-rw-r--r--src/optionstr.c5
-rw-r--r--src/testdir/dumps/Test_wildmenu_pum_51.dump10
-rw-r--r--src/testdir/dumps/Test_wildmenu_pum_52.dump10
-rw-r--r--src/testdir/dumps/Test_wildmenu_pum_53.dump10
-rw-r--r--src/testdir/test_cmdline.vim31
-rw-r--r--src/testdir/test_options.vim3
-rw-r--r--src/version.c2
12 files changed, 88 insertions, 13 deletions
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
index a9a8eec257..6f4b5d74db 100644
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1119,12 +1119,12 @@ commands in wildmenu mode (see 'wildmenu')
<Left> select the previous match / move up to parent
<Right> select the next match / move down to submenu
<CR> move into submenu when doing menu completion
+ CTRL-E stop completion and go back to original text
+ CTRL-Y accept selected match and stop completion
other stop completion and insert the typed character
commands in wildmenu mode with 'wildoptions' set to "pum"
- CTRL-E stop completion and go back to original text
- CTRL-Y accept selected match and stop completion
<PageUp> select a match several entries back
<PageDown> select a match several entries forward
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 86a734f6e6..cdb4992a74 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -9323,6 +9323,10 @@ A jump table for the options with a short description can be found at |Q_op|.
CTRL-N - go to the next entry
<CR> - in menu completion, when the cursor is just after a
dot: move into a submenu.
+ CTRL-E - end completion, go back to what was there before
+ selecting a match.
+ CTRL-Y - accept the currently selected match and stop
+ completion.
When not using the popup menu for command line completion, the
following keys have special meanings:
@@ -9341,10 +9345,6 @@ A jump table for the options with a short description can be found at |Q_op|.
parent directory or parent menu.
<Right> - in filename/menu name completion: move into a
subdirectory or submenu.
- CTRL-E - end completion, go back to what was there before
- selecting a match.
- CTRL-Y - accept the currently selected match and stop
- completion.
This makes the menus accessible from the console |console-menus|.
diff --git a/src/cmdexpand.c b/src/cmdexpand.c
index d27e039443..8bccaa3bb0 100644
--- a/src/cmdexpand.c
+++ b/src/cmdexpand.c
@@ -260,7 +260,7 @@ nextwild(
{
if (cmdline_fuzzy_completion_supported(xp))
// If fuzzy matching, don't modify the search string
- p1 = vim_strsave(xp->xp_pattern);
+ p1 = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len);
else
p1 = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index f0c7aad7df..06837ac92c 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -5590,7 +5590,8 @@ expand_argopt(
// Special handling of "ff" which acts as a short form of
// "fileformat", as "ff" is not a substring of it.
- if (STRCMP(xp->xp_pattern, "ff") == 0)
+ if (xp->xp_pattern_len == 2
+ && STRNCMP(xp->xp_pattern, "ff", xp->xp_pattern_len) == 0)
{
*matches = ALLOC_MULT(char_u *, 1);
if (*matches == NULL)
diff --git a/src/ex_getln.c b/src/ex_getln.c
index 711e08e886..9683e2ebd5 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -1599,7 +1599,7 @@ getcmdline_int(
cmdline_info_T save_ccline;
int did_save_ccline = FALSE;
int cmdline_type;
- int wild_type;
+ int wild_type = 0;
// one recursion level deeper
++depth;
@@ -1878,7 +1878,7 @@ getcmdline_int(
c = wildmenu_translate_key(&ccline, c, &xpc, did_wild_list);
int key_is_wc = (c == p_wc && KeyTyped) || c == p_wcm;
- if (cmdline_pum_active() && !key_is_wc)
+ if ((cmdline_pum_active() || did_wild_list) && !key_is_wc)
{
// Ctrl-Y: Accept the current selection and close the popup menu.
// Ctrl-E: cancel the cmdline popup menu and return the original
@@ -1889,7 +1889,6 @@ getcmdline_int(
if (nextwild(&xpc, wild_type, WILD_NO_BEEP,
firstc != '@') == FAIL)
break;
- c = Ctrl_E;
}
}
@@ -2016,6 +2015,14 @@ getcmdline_int(
do_abbr = TRUE; // default: check for abbreviation
+ // If already used to cancel/accept wildmenu, don't process the key
+ // further.
+ if (wild_type == WILD_CANCEL || wild_type == WILD_APPLY)
+ {
+ wild_type = 0;
+ goto cmdline_not_changed;
+ }
+
/*
* Big switch for a typed command line character.
*/
diff --git a/src/optionstr.c b/src/optionstr.c
index 8458f2a4a4..b7cdcc4511 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -2582,12 +2582,13 @@ expand_set_highlight(optexpand_T *args, int *numMatches, char_u ***matches)
if (*matches == NULL)
return FAIL;
- size_t pattern_len = STRLEN(xp->xp_pattern);
+ int pattern_len = xp->xp_pattern_len;
for (i = 0; i < num_hl_modes; i++)
{
// Don't allow duplicates as these are unique flags
- if (vim_strchr(xp->xp_pattern + 1, p_hl_mode_values[i]) != NULL)
+ char_u *dup = vim_strchr(xp->xp_pattern + 1, p_hl_mode_values[i]);
+ if (dup != NULL && (int)(dup - xp->xp_pattern) < pattern_len)
continue;
// ':' only works by itself, not with other flags.
diff --git a/src/testdir/dumps/Test_wildmenu_pum_51.dump b/src/testdir/dumps/Test_wildmenu_pum_51.dump
new file mode 100644
index 0000000000..d5ad45c14e
--- /dev/null
+++ b/src/testdir/dumps/Test_wildmenu_pum_51.dump
@@ -0,0 +1,10 @@
+| +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @2| +0#0000001#e0e0e08|w|i|l|d|c|h|a|r| @6| +0#4040ff13#ffffff0@54
+|~| @2| +0#0000001#ffd7ff255|w|i|l|d|c|h|a|r|m| @5| +0#4040ff13#ffffff0@54
+|:+0#0000000&|s|e|t| |w|i|l|d|c|h|a|r>z@1| @59
diff --git a/src/testdir/dumps/Test_wildmenu_pum_52.dump b/src/testdir/dumps/Test_wildmenu_pum_52.dump
new file mode 100644
index 0000000000..81e59b6e88
--- /dev/null
+++ b/src/testdir/dumps/Test_wildmenu_pum_52.dump
@@ -0,0 +1,10 @@
+| +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|:+0#0000000&|s|e|t| |w|i|l|d|c|h|a>z@1| @60
diff --git a/src/testdir/dumps/Test_wildmenu_pum_53.dump b/src/testdir/dumps/Test_wildmenu_pum_53.dump
new file mode 100644
index 0000000000..5f61cdd3ce
--- /dev/null
+++ b/src/testdir/dumps/Test_wildmenu_pum_53.dump
@@ -0,0 +1,10 @@
+| +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|:+0#0000000&|s|e|t| |w|i|l|d|c|h|a|r>z@1| @59
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index c285b087a4..33ff606424 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -158,6 +158,13 @@ func Test_complete_wildmenu()
call feedkeys(":sign \<Tab>\<PageUp>\<Left>\<Right>\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"TestWildMenu', @:)
+ " Test for Ctrl-E/Ctrl-Y being able to cancel / accept a match
+ call feedkeys(":sign un zz\<Left>\<Left>\<Left>\<Tab>\<C-E> yy\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sign un yy zz', @:)
+
+ call feedkeys(":sign un zz\<Left>\<Left>\<Left>\<Tab>\<Tab>\<C-Y> yy\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sign unplace yy zz', @:)
+
" cleanup
%bwipe
set nowildmenu
@@ -1105,6 +1112,9 @@ func Test_cmdline_complete_argopt()
call assert_equal('edit', getcompletion('read ++bin ++edi', 'cmdline')[0])
call assert_equal(['fileformat='], getcompletion('edit ++ff', 'cmdline'))
+ " Test ++ff in the middle of the cmdline
+ call feedkeys(":edit ++ff zz\<Left>\<Left>\<Left>\<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal("\"edit ++fileformat= zz", @:)
call assert_equal('dos', getcompletion('write ++ff=d', 'cmdline')[0])
call assert_equal('mac', getcompletion('args ++fileformat=m', 'cmdline')[0])
@@ -2585,6 +2595,16 @@ func Test_wildmenu_pum()
call term_sendkeys(buf, "\<PageUp>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_50', {})
+ " pressing <C-E> to end completion should work in middle of the line too
+ call term_sendkeys(buf, "\<Esc>:set wildchazz\<Left>\<Left>\<Tab>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_51', {})
+ call term_sendkeys(buf, "\<C-E>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_52', {})
+
+ " pressing <C-Y> should select the current match and end completion
+ call term_sendkeys(buf, "\<Esc>:set wildchazz\<Left>\<Left>\<Tab>\<C-Y>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_53', {})
+
call term_sendkeys(buf, "\<C-U>\<CR>")
call StopVimInTerminal(buf)
endfunc
@@ -3293,6 +3313,17 @@ func Test_fuzzy_completion_custom_func()
set wildoptions&
endfunc
+" Test for fuzzy completion in the middle of a cmdline instead of at the end
+func Test_fuzzy_completion_in_middle()
+ set wildoptions=fuzzy
+ call feedkeys(":set ildar wrap\<Left>\<Left>\<Left>\<Left>\<Left>\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"set wildchar wildcharm wrap", @:)
+
+ call feedkeys(":args ++odng zz\<Left>\<Left>\<Left>\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"args ++encoding= zz", @:)
+ set wildoptions&
+endfunc
+
" Test for :breakadd argument completion
func Test_cmdline_complete_breakadd()
call feedkeys(":breakadd \<C-A>\<C-B>\"\<CR>", 'tx')
diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim
index 6b2b7482a7..ef2d3bd4da 100644
--- a/src/testdir/test_options.vim
+++ b/src/testdir/test_options.vim
@@ -616,6 +616,9 @@ func Test_set_completion_string_values()
\ {idx, val -> val != ':'}),
\ '')
call assert_equal([], getcompletion('set hl+=8'..hl_display_modes, 'cmdline'))
+ " Test completion in middle of the line
+ call feedkeys(":set hl=8b i\<Left>\<Left>\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal("\"set hl=8bi i", @:)
"
" Test flag lists
diff --git a/src/version.c b/src/version.c
index 02441bceb2..438e9a0454 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2037,
+/**/
2036,
/**/
2035,