mirror of
https://github.com/neovim/neovim.git
synced 2025-09-28 14:08:32 +00:00
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:
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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"));
|
||||
|
@@ -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
|
||||
|
@@ -78,6 +78,7 @@ static char *features[] = {
|
||||
|
||||
// clang-format off
|
||||
static const int included_patches[] = {
|
||||
1206,
|
||||
// 1026,
|
||||
1025,
|
||||
1024,
|
||||
|
Reference in New Issue
Block a user