diff options
author | Björn Linse <bjorn.linse@gmail.com> | 2017-11-22 22:35:20 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-22 22:35:20 +0100 |
commit | a4f6cec7a31ff8dbfa089b9e22227afbeb951e9b (patch) | |
tree | 9bcf55ca9e4ecdbea9390dc750d39027ba7d3acf /src | |
parent | 9393be477a733183c2a992cc8728e3ebc65a3118 (diff) | |
download | rneovim-a4f6cec7a31ff8dbfa089b9e22227afbeb951e9b.tar.gz rneovim-a4f6cec7a31ff8dbfa089b9e22227afbeb951e9b.tar.bz2 rneovim-a4f6cec7a31ff8dbfa089b9e22227afbeb951e9b.zip |
cmdline: CmdlineEnter and CmdlineLeave autocommands (#7422)
vim-patch:fafcf0dd59fd
patch 8.0.1206: no autocmd for entering or leaving the command line
Problem: No autocmd for entering or leaving the command line.
Solution: Add CmdlineEnter and CmdlineLeave.
https://github.com/vim/vim/commit/fafcf0dd59fd9c4ef743bb333ae40d1d322b6079
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/auevents.lua | 2 | ||||
-rw-r--r-- | src/nvim/eval/typval.c | 23 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 57 | ||||
-rw-r--r-- | src/nvim/globals.h | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_autocmd.vim | 22 | ||||
-rw-r--r-- | src/nvim/version.c | 1 |
6 files changed, 106 insertions, 1 deletions
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index 68a47c244f..7dfaf54ff0 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -19,6 +19,8 @@ return { 'BufWriteCmd', -- write buffer using command 'BufWritePost', -- after writing a buffer 'BufWritePre', -- before writing a buffer + 'CmdLineEnter', -- after entering cmdline mode + 'CmdLineLeave', -- before leaving cmdline mode 'CmdUndefined', -- command undefined 'CmdWinEnter', -- after entering the cmdline window 'CmdWinLeave', -- before leaving the cmdline window diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index c339a5cdd2..262ea922ef 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1374,6 +1374,29 @@ int tv_dict_add_nr(dict_T *const d, const char *const key, return OK; } +/// Add a special entry to dictionary +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param[in] val SpecialVarValue to add. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_special(dict_T *const d, const char *const key, + const size_t key_len, SpecialVarValue val) +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + item->di_tv.v_lock = VAR_UNLOCKED; + item->di_tv.v_type = VAR_SPECIAL; + item->di_tv.vval.v_special = val; + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + /// Add a string entry to dictionary /// /// @param[out] d Dictionary to add entry to. diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 9c9ccbca4d..c1500e3121 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -348,8 +348,57 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) got_int = false; s->state.check = command_line_check; s->state.execute = command_line_execute; + + TryState tstate; + Error err = ERROR_INIT; + bool tl_ret = true; + dict_T *dict = get_vim_var_dict(VV_EVENT); + char firstcbuf[2]; + firstcbuf[0] = firstc > 0 ? firstc : '-'; + firstcbuf[1] = 0; + + if (has_event(EVENT_CMDLINEENTER)) { + // 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_CMDLINEENTER, (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; + } + state_enter(&s->state); + if (has_event(EVENT_CMDLINELEAVE)) { + 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); + // not readonly: + tv_dict_add_special(dict, S_LEN("abort"), + s->gotesc ? kSpecialVarTrue : kSpecialVarFalse); + try_enter(&tstate); + apply_autocmds(EVENT_CMDLINELEAVE, (char_u *)firstcbuf, (char_u *)firstcbuf, + false, curbuf); + // error printed below, to avoid redraw issues + tl_ret = try_leave(&tstate, &err); + if (tv_dict_get_number(dict, "abort") != 0) { + s->gotesc = 1; + } + tv_dict_clear(dict); + } + cmdmsg_rl = false; cmd_fkmap = 0; @@ -410,8 +459,14 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) msg_scroll = s->save_msg_scroll; redir_off = false; + 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); + } + // When the command line was typed, no need for a wait-return prompt. - if (s->some_key_typed) { + if (s->some_key_typed && tl_ret) { need_wait_return = false; } diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 8f804ff888..2b025c2c50 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -1167,6 +1167,8 @@ EXTERN char_u e_dirnotf[] INIT(= N_( EXTERN char_u e_unsupportedoption[] INIT(= N_("E519: Option not supported")); EXTERN char_u e_fnametoolong[] INIT(= N_("E856: Filename too long")); EXTERN char_u e_float_as_string[] INIT(= N_("E806: using Float as a String")); +EXTERN char_u e_autocmd_err[] INIT(=N_( + "E920: autocmd has thrown an exception: %s")); EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM")); diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 835df42a10..82c04abf5b 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -420,3 +420,25 @@ function Test_autocmd_bufwipe_in_SessLoadPost2() call delete(file) endfor endfunc + +func Test_Cmdline() + au! CmdlineEnter : let g:entered = expand('<afile>') + au! CmdlineLeave : let g:left = expand('<afile>') + let g:entered = 0 + let g:left = 0 + call feedkeys(":echo 'hello'\<CR>", 'xt') + call assert_equal(':', g:entered) + call assert_equal(':', g:left) + au! CmdlineEnter + au! CmdlineLeave + + au! CmdlineEnter / let g:entered = expand('<afile>') + au! CmdlineLeave / let g:left = expand('<afile>') + let g:entered = 0 + let g:left = 0 + call feedkeys("/hello<CR>", 'xt') + call assert_equal('/', g:entered) + call assert_equal('/', g:left) + au! CmdlineEnter + au! CmdlineLeave +endfunc diff --git a/src/nvim/version.c b/src/nvim/version.c index 1ceda55cf1..205c25b6cd 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -78,6 +78,7 @@ static char *features[] = { // clang-format off static const int included_patches[] = { + 1206, // 1026, 1025, 1024, |