aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/options.txt2
-rw-r--r--runtime/lua/vim/_meta/options.lua2
-rw-r--r--src/nvim/option.c13
-rw-r--r--src/nvim/options.lua4
-rw-r--r--test/functional/options/cursorbind_spec.lua1
-rw-r--r--test/functional/ui/popupmenu_spec.lua99
-rw-r--r--test/functional/ui/wildmode_spec.lua79
-rw-r--r--test/old/testdir/test_cmdline.vim59
-rw-r--r--test/old/testdir/test_options.vim5
9 files changed, 251 insertions, 13 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index e734b62020..c8ea5ce67f 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -6920,6 +6920,8 @@ A jump table for the options with a short description can be found at |Q_op|.
The character is not recognized when used inside a macro. See
'wildcharm' for that.
Some keys will not work, such as CTRL-C, <CR> and Enter.
+ <Esc> can be used, but hitting it twice in a row will still exit
+ command-line as a failsafe measure.
Although 'wc' is a number option, you can set it to a special key: >
:set wc=<Tab>
<
diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua
index 50146bac50..cc013112b3 100644
--- a/runtime/lua/vim/_meta/options.lua
+++ b/runtime/lua/vim/_meta/options.lua
@@ -7466,6 +7466,8 @@ vim.go.ww = vim.go.whichwrap
--- The character is not recognized when used inside a macro. See
--- 'wildcharm' for that.
--- Some keys will not work, such as CTRL-C, <CR> and Enter.
+--- <Esc> can be used, but hitting it twice in a row will still exit
+--- command-line as a failsafe measure.
--- Although 'wc' is a number option, you can set it to a special key:
--- ```
--- :set wc=<Tab>
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 0c8230d7c9..389d5ee218 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2677,6 +2677,19 @@ static const char *did_set_updatecount(optset_T *args)
return NULL;
}
+/// Process the new 'wildchar' / 'wildcharm' option value.
+static const char *did_set_wildchar(optset_T *args)
+{
+ OptInt c = *(OptInt *)args->os_varp;
+
+ // Don't allow key values that wouldn't work as wildchar.
+ if (c == Ctrl_C || c == '\n' || c == '\r' || c == K_KENTER) {
+ return e_invarg;
+ }
+
+ return NULL;
+}
+
/// Process the new 'winblend' option value.
static const char *did_set_winblend(optset_T *args)
{
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 8d12d860d8..d416b0070f 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -9473,6 +9473,7 @@ return {
},
{
abbreviation = 'wc',
+ cb = 'did_set_wildchar',
defaults = {
if_true = imacros('TAB'),
doc = '<Tab>',
@@ -9484,6 +9485,8 @@ return {
The character is not recognized when used inside a macro. See
'wildcharm' for that.
Some keys will not work, such as CTRL-C, <CR> and Enter.
+ <Esc> can be used, but hitting it twice in a row will still exit
+ command-line as a failsafe measure.
Although 'wc' is a number option, you can set it to a special key: >
:set wc=<Tab>
<
@@ -9496,6 +9499,7 @@ return {
},
{
abbreviation = 'wcm',
+ cb = 'did_set_wildchar',
defaults = { if_true = 0 },
desc = [=[
'wildcharm' works exactly like 'wildchar', except that it is
diff --git a/test/functional/options/cursorbind_spec.lua b/test/functional/options/cursorbind_spec.lua
index 1a03ed099a..498206936a 100644
--- a/test/functional/options/cursorbind_spec.lua
+++ b/test/functional/options/cursorbind_spec.lua
@@ -8,6 +8,7 @@ local feed = helpers.feed
before_each(clear)
describe("'cursorbind'", function()
+ -- oldtest: Test_cursorline_cursorbind_horizontal_scroll()
it("behaves consistently whether 'cursorline' is set or not vim-patch:8.2.4795", function()
local screen = Screen.new(60, 8)
screen:set_default_attr_ids({
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index bfa4b7f14e..6d5546e0aa 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -3768,13 +3768,16 @@ describe('builtin popupmenu', function()
]])
end)
- -- oldtest: Test_wildmenu_pum_clear_entries()
- it('wildoptions=pum when using odd wildchar', function()
+ -- oldtest: Test_wildmenu_pum_odd_wildchar()
+ it('wildoptions=pum with odd wildchar', function()
screen:try_resize(30, 10)
+ -- Test odd wildchar interactions with pum. Make sure they behave properly
+ -- and don't lead to memory corruption due to improperly cleaned up memory.
exec([[
set wildoptions=pum
set wildchar=<C-E>
]])
+
feed(':sign <C-E>')
screen:expect([[
|
@@ -3788,7 +3791,97 @@ describe('builtin popupmenu', function()
{1:~ }{n: unplace }{1: }|
:sign define^ |
]])
- assert_alive()
+
+ -- <C-E> being a wildchar takes priority over its original functionality
+ feed('<C-E>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{n: define }{1: }|
+ {1:~ }{s: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{n: unplace }{1: }|
+ :sign jump^ |
+ ]])
+
+ feed('<Esc>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+
+ -- Escape key can be wildchar too. Double-<Esc> is hard-coded to escape
+ -- command-line, and we need to make sure to clean up properly.
+ command('set wildchar=<Esc>')
+ feed(':sign <Esc>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{s: define }{1: }|
+ {1:~ }{n: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{n: unplace }{1: }|
+ :sign define^ |
+ ]])
+
+ feed('<Esc>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+
+ -- <C-\> can also be wildchar. <C-\><C-N> however will still escape cmdline
+ -- and we again need to make sure we clean up properly.
+ command([[set wildchar=<C-\>]])
+ feed([[:sign <C-\><C-\>]])
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{s: define }{1: }|
+ {1:~ }{n: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{n: unplace }{1: }|
+ :sign define^ |
+ ]])
+
+ feed('<C-N>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
end)
end
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index 0355c57b5a..3201135b67 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -17,6 +17,85 @@ describe("'wildmenu'", function()
screen:attach()
end)
+ -- oldtest: Test_wildmenu_screendump()
+ it('works', function()
+ screen:set_default_attr_ids({
+ [0] = {bold = true, foreground = Screen.colors.Blue}; -- NonText
+ [1] = {foreground = Screen.colors.Black, background = Screen.colors.Yellow}; -- WildMenu
+ [2] = {bold = true, reverse = true}; -- StatusLine
+ })
+ -- Test simple wildmenu
+ feed(':sign <Tab>')
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }|
+ {1:define}{2: jump list > }|
+ :sign define^ |
+ ]]}
+
+ feed('<Tab>')
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }|
+ {2:define }{1:jump}{2: list > }|
+ :sign jump^ |
+ ]]}
+
+ feed('<Tab>')
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }|
+ {2:define jump }{1:list}{2: > }|
+ :sign list^ |
+ ]]}
+
+ -- Looped back to the original value
+ feed('<Tab><Tab><Tab><Tab>')
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }|
+ {2:define jump list > }|
+ :sign ^ |
+ ]]}
+
+ -- Test that the wild menu is cleared properly
+ feed('<Space>')
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ :sign ^ |
+ ]]}
+
+ -- Test that a different wildchar still works
+ feed('<Esc>')
+ command('set wildchar=<Esc>')
+ feed(':sign <Esc>')
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }|
+ {1:define}{2: jump list > }|
+ :sign define^ |
+ ]]}
+
+ -- Double-<Esc> is a hard-coded method to escape while wildchar=<Esc>. Make
+ -- sure clean up is properly done in edge case like this.
+ feed('<Esc>')
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ end)
+
it('C-E to cancel wildmenu completion restore original input', function()
feed(':sign <tab>')
screen:expect([[
diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim
index 61ee59068d..49c14c9c74 100644
--- a/test/old/testdir/test_cmdline.vim
+++ b/test/old/testdir/test_cmdline.vim
@@ -177,8 +177,9 @@ func Test_wildmenu_screendump()
let lines =<< trim [SCRIPT]
set wildmenu hlsearch
[SCRIPT]
- call writefile(lines, 'XTest_wildmenu')
+ call writefile(lines, 'XTest_wildmenu', 'D')
+ " Test simple wildmenu
let buf = RunVimInTerminal('-S XTest_wildmenu', {'rows': 8})
call term_sendkeys(buf, ":vim\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_1', {})
@@ -189,13 +190,26 @@ func Test_wildmenu_screendump()
call term_sendkeys(buf, "\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_3', {})
- call term_sendkeys(buf, "\<Tab>")
+ " Looped back to the original value
+ call term_sendkeys(buf, "\<Tab>\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_4', {})
+
+ " Test that the wild menu is cleared properly
+ call term_sendkeys(buf, " ")
+ call VerifyScreenDump(buf, 'Test_wildmenu_5', {})
+
+ " Test that a different wildchar still works
+ call term_sendkeys(buf, "\<Esc>:set wildchar=<Esc>\<CR>")
+ call term_sendkeys(buf, ":vim\<Esc>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_1', {})
+
+ " Double-<Esc> is a hard-coded method to escape while wildchar=<Esc>. Make
+ " sure clean up is properly done in edge case like this.
call term_sendkeys(buf, "\<Esc>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_6', {})
" clean up
call StopVimInTerminal(buf)
- call delete('XTest_wildmenu')
endfunc
func Test_redraw_in_autocmd()
@@ -2789,7 +2803,7 @@ func Test_wildmenu_pum_from_terminal()
let cmds = ['set wildmenu wildoptions=pum']
let pcmd = python .. ' -c "import sys; sys.stdout.write(sys.stdin.read())"'
call add(cmds, "call term_start('" .. pcmd .. "')")
- call writefile(cmds, 'Xtest')
+ call writefile(cmds, 'Xtest', 'D')
let buf = RunVimInTerminal('-S Xtest', #{rows: 10})
call term_sendkeys(buf, "\r\r\r")
call term_wait(buf)
@@ -2798,13 +2812,13 @@ func Test_wildmenu_pum_from_terminal()
call VerifyScreenDump(buf, 'Test_wildmenu_pum_term_01', {})
call term_wait(buf)
call StopVimInTerminal(buf)
- call delete('Xtest')
endfunc
-func Test_wildmenu_pum_clear_entries()
+func Test_wildmenu_pum_odd_wildchar()
CheckRunVimInTerminal
- " This was using freed memory. Run in a terminal to get the pum to update.
+ " Test odd wildchar interactions with pum. Make sure they behave properly
+ " and don't lead to memory corruption due to improperly cleaned up memory.
let lines =<< trim END
set wildoptions=pum
set wildchar=<C-E>
@@ -2812,10 +2826,35 @@ func Test_wildmenu_pum_clear_entries()
call writefile(lines, 'XwildmenuTest', 'D')
let buf = RunVimInTerminal('-S XwildmenuTest', #{rows: 10})
- call term_sendkeys(buf, ":\<C-E>\<C-E>")
- call VerifyScreenDump(buf, 'Test_wildmenu_pum_clear_entries_1', {})
+ call term_sendkeys(buf, ":\<C-E>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_1', {})
+
+ " <C-E> being a wildchar takes priority over its original functionality
+ call term_sendkeys(buf, "\<C-E>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_2', {})
+
+ call term_sendkeys(buf, "\<Esc>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_3', {})
+
+ " Escape key can be wildchar too. Double-<Esc> is hard-coded to escape
+ " command-line, and we need to make sure to clean up properly.
+ call term_sendkeys(buf, ":set wildchar=<Esc>\<CR>")
+ call term_sendkeys(buf, ":\<Esc>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_1', {})
+
+ call term_sendkeys(buf, "\<Esc>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_3', {})
- set wildoptions& wildchar&
+ " <C-\> can also be wildchar. <C-\><C-N> however will still escape cmdline
+ " and we again need to make sure we clean up properly.
+ call term_sendkeys(buf, ":set wildchar=<C-\\>\<CR>")
+ call term_sendkeys(buf, ":\<C-\>\<C-\>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_1', {})
+
+ call term_sendkeys(buf, "\<C-N>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_3', {})
+
+ call StopVimInTerminal(buf)
endfunc
" Test for completion after a :substitute command followed by a pipe (|)
diff --git a/test/old/testdir/test_options.vim b/test/old/testdir/test_options.vim
index 1a3a909344..418aa81939 100644
--- a/test/old/testdir/test_options.vim
+++ b/test/old/testdir/test_options.vim
@@ -232,6 +232,11 @@ func Test_keymap_valid()
call assert_fails(":set kmp=trunc\x00name", "trunc")
endfunc
+func Test_wildchar_valid()
+ call assert_fails("set wildchar=<CR>", "E474:")
+ call assert_fails("set wildcharm=<C-C>", "E474:")
+endfunc
+
func Check_dir_option(name)
" Check that it's possible to set the option.
exe 'set ' . a:name . '=/usr/share/dict/words'