mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #7946 from bfredl/vim-8.0.1445
implement CmdlineChanged: vim-patch:8.0.1445 + nvim specific v:event stuff
This commit is contained in:
commit
2f3a18695e
@ -521,10 +521,11 @@ CmdUndefined When a user command is used but it isn't
|
|||||||
command is defined. An alternative is to
|
command is defined. An alternative is to
|
||||||
always define the user command and have it
|
always define the user command and have it
|
||||||
invoke an autoloaded function. See |autoload|.
|
invoke an autoloaded function. See |autoload|.
|
||||||
*CmdlineChanged*
|
*CmdlineChanged*
|
||||||
CmdlineChanged After a change was made to the text in the
|
CmdlineChanged After a change was made to the text inside
|
||||||
command line. Be careful not to mess up
|
command line. Be careful not to mess up the
|
||||||
the command line, it may cause Vim to lock up.
|
command line, it may cause Vim to lock up.
|
||||||
|
<afile> is set to the |cmdline-char|.
|
||||||
*CmdlineEnter*
|
*CmdlineEnter*
|
||||||
CmdlineEnter After entering the command-line (including
|
CmdlineEnter After entering the command-line (including
|
||||||
non-interactive use of ":" in a mapping: use
|
non-interactive use of ":" in a mapping: use
|
||||||
|
@ -21,6 +21,7 @@ return {
|
|||||||
'BufWritePre', -- before writing a buffer
|
'BufWritePre', -- before writing a buffer
|
||||||
'ChanInfo', -- info was received about channel
|
'ChanInfo', -- info was received about channel
|
||||||
'ChanOpen', -- channel was opened
|
'ChanOpen', -- channel was opened
|
||||||
|
'CmdLineChanged', -- command line was modified
|
||||||
'CmdLineEnter', -- after entering cmdline mode
|
'CmdLineEnter', -- after entering cmdline mode
|
||||||
'CmdLineLeave', -- before leaving cmdline mode
|
'CmdLineLeave', -- before leaving cmdline mode
|
||||||
'CmdUndefined', -- command undefined
|
'CmdUndefined', -- command undefined
|
||||||
|
@ -1804,6 +1804,37 @@ static int empty_pattern(char_u *p)
|
|||||||
|
|
||||||
static int command_line_changed(CommandLineState *s)
|
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.
|
// 'incsearch' highlighting.
|
||||||
if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) {
|
if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) {
|
||||||
pos_T end_pos;
|
pos_T end_pos;
|
||||||
|
@ -818,6 +818,18 @@ func Test_QuitPre()
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_Cmdline()
|
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! CmdlineEnter : let g:entered = expand('<afile>')
|
||||||
au! CmdlineLeave : let g:left = expand('<afile>')
|
au! CmdlineLeave : let g:left = expand('<afile>')
|
||||||
let g:entered = 0
|
let g:entered = 0
|
||||||
|
@ -5,6 +5,7 @@ local clear = helpers.clear
|
|||||||
local command = helpers.command
|
local command = helpers.command
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
local expect = helpers.expect
|
local expect = helpers.expect
|
||||||
|
local eval = helpers.eval
|
||||||
local next_msg = helpers.next_msg
|
local next_msg = helpers.next_msg
|
||||||
local feed = helpers.feed
|
local feed = helpers.feed
|
||||||
local meths = helpers.meths
|
local meths = helpers.meths
|
||||||
@ -63,6 +64,7 @@ describe('cmdline autocommands', function()
|
|||||||
})
|
})
|
||||||
command("autocmd CmdlineEnter * echoerr 'FAIL'")
|
command("autocmd CmdlineEnter * echoerr 'FAIL'")
|
||||||
command("autocmd CmdlineLeave * echoerr 'very error'")
|
command("autocmd CmdlineLeave * echoerr 'very error'")
|
||||||
|
|
||||||
feed(':')
|
feed(':')
|
||||||
screen:expect([[
|
screen:expect([[
|
||||||
|
|
|
|
||||||
@ -74,6 +76,7 @@ describe('cmdline autocommands', function()
|
|||||||
{2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
|
{2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
|
||||||
:^ |
|
:^ |
|
||||||
]])
|
]])
|
||||||
|
|
||||||
feed("put ='lorem ipsum'<cr>")
|
feed("put ='lorem ipsum'<cr>")
|
||||||
screen:expect([[
|
screen:expect([[
|
||||||
|
|
|
|
||||||
@ -86,6 +89,7 @@ describe('cmdline autocommands', function()
|
|||||||
{3:Press ENTER or type command to continue}^ |
|
{3:Press ENTER or type command to continue}^ |
|
||||||
]])
|
]])
|
||||||
|
|
||||||
|
-- cmdline was still executed
|
||||||
feed('<cr>')
|
feed('<cr>')
|
||||||
screen:expect([[
|
screen:expect([[
|
||||||
|
|
|
|
||||||
@ -97,6 +101,71 @@ describe('cmdline autocommands', function()
|
|||||||
{1:~ }|
|
{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)
|
end)
|
||||||
|
|
||||||
it('works with nested cmdline', function()
|
it('works with nested cmdline', function()
|
||||||
@ -115,4 +184,41 @@ describe('cmdline autocommands', function()
|
|||||||
feed('1+2<cr>')
|
feed('1+2<cr>')
|
||||||
eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg())
|
eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg())
|
||||||
end)
|
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)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user