aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2018-12-12 21:40:10 +0100
committerGitHub <noreply@github.com>2018-12-12 21:40:10 +0100
commit2f3a18695e41ec6afa98194b22d064ec81154dbf (patch)
tree936600d127e522fef943cdf44090dd76581a8ab2
parentb9a441eb78349088d54eaa6e12c35aa06f0b1c6b (diff)
parent5f82889be78856ee189c254110bf087dba918b23 (diff)
downloadrneovim-2f3a18695e41ec6afa98194b22d064ec81154dbf.tar.gz
rneovim-2f3a18695e41ec6afa98194b22d064ec81154dbf.tar.bz2
rneovim-2f3a18695e41ec6afa98194b22d064ec81154dbf.zip
Merge pull request #7946 from bfredl/vim-8.0.1445
implement CmdlineChanged: vim-patch:8.0.1445 + nvim specific v:event stuff
-rw-r--r--runtime/doc/autocmd.txt9
-rw-r--r--src/nvim/auevents.lua1
-rw-r--r--src/nvim/ex_getln.c31
-rw-r--r--src/nvim/testdir/test_autocmd.vim12
-rw-r--r--test/functional/autocmd/cmdline_spec.lua106
5 files changed, 155 insertions, 4 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index c34dbaaf60..d7b74f99c2 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -521,10 +521,11 @@ CmdUndefined When a user command is used but it isn't
command is defined. An alternative is to
always define the user command and have it
invoke an autoloaded function. See |autoload|.
- *CmdlineChanged*
-CmdlineChanged After a change was made to the text in the
- command line. Be careful not to mess up
- the command line, it may cause Vim to lock up.
+ *CmdlineChanged*
+CmdlineChanged After a change was made to the text inside
+ command line. Be careful not to mess up the
+ command line, it may cause Vim to lock up.
+ <afile> is set to the |cmdline-char|.
*CmdlineEnter*
CmdlineEnter After entering the command-line (including
non-interactive use of ":" in a mapping: use
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index ab92e84799..3cffd66dee 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -21,6 +21,7 @@ return {
'BufWritePre', -- before writing a buffer
'ChanInfo', -- info was received about channel
'ChanOpen', -- channel was opened
+ 'CmdLineChanged', -- command line was modified
'CmdLineEnter', -- after entering cmdline mode
'CmdLineLeave', -- before leaving cmdline mode
'CmdUndefined', -- command undefined
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 19a52c913a..bfc32887ca 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1804,6 +1804,37 @@ static int empty_pattern(char_u *p)
static int command_line_changed(CommandLineState *s)
{
+ // Trigger CmdlineChanged autocommands.
+ if (has_event(EVENT_CMDLINECHANGED)) {
+ TryState tstate;
+ Error err = ERROR_INIT;
+ bool tl_ret = true;
+ dict_T *dict = get_vim_var_dict(VV_EVENT);
+
+ char firstcbuf[2];
+ firstcbuf[0] = s->firstc > 0 ? s->firstc : '-';
+ firstcbuf[1] = 0;
+
+ // set v:event to a dictionary with information about the commandline
+ tv_dict_add_str(dict, S_LEN("cmdtype"), firstcbuf);
+ tv_dict_add_nr(dict, S_LEN("cmdlevel"), ccline.level);
+ tv_dict_set_keys_readonly(dict);
+ try_enter(&tstate);
+
+ apply_autocmds(EVENT_CMDLINECHANGED, (char_u *)firstcbuf,
+ (char_u *)firstcbuf, false, curbuf);
+ tv_dict_clear(dict);
+
+ tl_ret = try_leave(&tstate, &err);
+ if (!tl_ret && ERROR_SET(&err)) {
+ msg_putchar('\n');
+ msg_printf_attr(HL_ATTR(HLF_E)|MSG_HIST, (char *)e_autocmd_err, err.msg);
+ api_clear_error(&err);
+ redrawcmd();
+ }
+ tl_ret = true;
+ }
+
// 'incsearch' highlighting.
if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) {
pos_T end_pos;
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 9e8d2081c8..5deb789f48 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -818,6 +818,18 @@ func Test_QuitPre()
endfunc
func Test_Cmdline()
+ au! CmdlineChanged : let g:text = getcmdline()
+ let g:text = 0
+ call feedkeys(":echom 'hello'\<CR>", 'xt')
+ call assert_equal("echom 'hello'", g:text)
+ au! CmdlineChanged
+
+ au! CmdlineChanged : let g:entered = expand('<afile>')
+ let g:entered = 0
+ call feedkeys(":echom 'hello'\<CR>", 'xt')
+ call assert_equal(':', g:entered)
+ au! CmdlineChanged
+
au! CmdlineEnter : let g:entered = expand('<afile>')
au! CmdlineLeave : let g:left = expand('<afile>')
let g:entered = 0
diff --git a/test/functional/autocmd/cmdline_spec.lua b/test/functional/autocmd/cmdline_spec.lua
index 3f0504d02f..51b7b819e9 100644
--- a/test/functional/autocmd/cmdline_spec.lua
+++ b/test/functional/autocmd/cmdline_spec.lua
@@ -5,6 +5,7 @@ local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
local expect = helpers.expect
+local eval = helpers.eval
local next_msg = helpers.next_msg
local feed = helpers.feed
local meths = helpers.meths
@@ -63,6 +64,7 @@ describe('cmdline autocommands', function()
})
command("autocmd CmdlineEnter * echoerr 'FAIL'")
command("autocmd CmdlineLeave * echoerr 'very error'")
+
feed(':')
screen:expect([[
|
@@ -74,6 +76,7 @@ describe('cmdline autocommands', function()
{2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
:^ |
]])
+
feed("put ='lorem ipsum'<cr>")
screen:expect([[
|
@@ -86,6 +89,7 @@ describe('cmdline autocommands', function()
{3:Press ENTER or type command to continue}^ |
]])
+ -- cmdline was still executed
feed('<cr>')
screen:expect([[
|
@@ -97,6 +101,71 @@ describe('cmdline autocommands', function()
{1:~ }|
|
]])
+
+ command("autocmd CmdlineChanged * echoerr 'change erreor'")
+
+ -- history recall still works
+ feed(":<c-p>")
+ screen:expect([[
+ |
+ lorem ipsum |
+ {4: }|
+ : |
+ {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
+ :put ='lorem ipsum' |
+ {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ :put ='lorem ipsum'^ |
+ ]])
+
+ feed("<left>")
+ screen:expect([[
+ |
+ lorem ipsum |
+ {4: }|
+ : |
+ {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
+ :put ='lorem ipsum' |
+ {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ :put ='lorem ipsum^' |
+ ]])
+
+ -- edit still works
+ feed(".")
+ screen:expect([[
+ {4: }|
+ : |
+ {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
+ :put ='lorem ipsum' |
+ {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ :put ='lorem ipsum.' |
+ {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ :put ='lorem ipsum.^' |
+ ]])
+
+ feed('<cr>')
+ screen:expect([[
+ :put ='lorem ipsum' |
+ {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ :put ='lorem ipsum.' |
+ {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ :put ='lorem ipsum.' |
+ {2:E5500: autocmd has thrown an exception: Vim(echoerr):very error} |
+ |
+ {3:Press ENTER or type command to continue}^ |
+ ]])
+
+ -- cmdline was still executed
+ feed('<cr>')
+ screen:expect([[
+ |
+ lorem ipsum |
+ ^lorem ipsum. |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
end)
it('works with nested cmdline', function()
@@ -115,4 +184,41 @@ describe('cmdline autocommands', function()
feed('1+2<cr>')
eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg())
end)
+
+ it('supports CmdlineChanged' ,function()
+ command("autocmd CmdlineChanged * call rpcnotify(g:channel, 'CmdlineChanged', v:event, getcmdline())")
+ feed(':')
+ eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg())
+ feed('l')
+ eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "l"}}, next_msg())
+ feed('e')
+ eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "le"}}, next_msg())
+ feed('t')
+ eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let"}}, next_msg())
+ feed('<space>')
+ eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let "}}, next_msg())
+ feed('x')
+ eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x"}}, next_msg())
+ feed('<space>')
+ eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x "}}, next_msg())
+ feed('=')
+ eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x ="}}, next_msg())
+ feed('<space>')
+ eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = "}}, next_msg())
+ feed('<c-r>=')
+ eq({'notification', 'CmdlineEnter', {{cmdtype='=', cmdlevel=2}}}, next_msg())
+ feed('1')
+ eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1"}}, next_msg())
+ feed('+')
+ eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+"}}, next_msg())
+ feed('1')
+ eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+1"}}, next_msg())
+ feed('<cr>')
+ eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg())
+ eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = "}}, next_msg())
+ eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = 2"}}, next_msg())
+ feed('<cr>')
+ eq({'notification', 'CmdlineLeave', {{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg())
+ eq(2, eval('x'))
+ end)
end)