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.

fafcf0dd59
This commit is contained in:
Björn Linse
2017-11-22 22:35:20 +01:00
committed by GitHub
parent 9393be477a
commit a4f6cec7a3
10 changed files with 256 additions and 5 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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"));

View File

@@ -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

View File

@@ -78,6 +78,7 @@ static char *features[] = {
// clang-format off
static const int included_patches[] = {
1206,
// 1026,
1025,
1024,