mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.2.3555: ModeChanged is not triggered on every mode change
Problem: ModeChanged is not triggered on every mode change.
Solution: Also trigger on minor mode changes. (Maguns Gross, closes vim/vim#8999)
25def2c8b8
This commit is contained in:
parent
60c154687a
commit
11683193f5
@ -721,18 +721,23 @@ MenuPopup Just before showing the popup menu (under the
|
||||
*ModeChanged*
|
||||
ModeChanged After changing the mode. The pattern is
|
||||
matched against `'old_mode:new_mode'`, for
|
||||
example match against `i:*` to simulate
|
||||
|InsertLeave|.
|
||||
example match against `*:c` to simulate
|
||||
|CmdlineEnter|.
|
||||
The following values of |v:event| are set:
|
||||
old_mode The mode before it changed.
|
||||
new_mode The new mode as also returned
|
||||
by |mode()|.
|
||||
by |mode()| called with a
|
||||
non-zero argument.
|
||||
When ModeChanged is triggered, old_mode will
|
||||
have the value of new_mode when the event was
|
||||
last triggered.
|
||||
This will be triggered on every minor mode
|
||||
change.
|
||||
Usage example to use relative line numbers
|
||||
when entering visual mode: >
|
||||
:autocmd ModeChanged *:v set rnu
|
||||
:au ModeChanged [vV\x16]*:* let &l:rnu = mode() =~# '^[vV\x16]'
|
||||
:au ModeChanged *:[vV\x16]* let &l:rnu = mode() =~# '^[vV\x16]'
|
||||
:au WinEnter,WinLeave * let &l:rnu = mode() =~# '^[vV\x16]'
|
||||
< *OptionSet*
|
||||
OptionSet After setting an option (except during
|
||||
|startup|). The |autocmd-pattern| is matched
|
||||
|
@ -925,6 +925,13 @@ static int do_autocmd_event(event_T event, char_u *pat, bool once, int nested, c
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// need to initialize last_mode for the first ModeChanged autocmd
|
||||
if (event == EVENT_MODECHANGED && !has_event(EVENT_MODECHANGED)) {
|
||||
xfree(last_mode);
|
||||
last_mode = get_mode();
|
||||
}
|
||||
|
||||
ap->cmds = NULL;
|
||||
*prev_ap = ap;
|
||||
last_autopat[(int)event] = ap;
|
||||
|
@ -2049,6 +2049,8 @@ static void ins_ctrl_x(void)
|
||||
// CTRL-V look like CTRL-N
|
||||
ctrl_x_mode = CTRL_X_CMDLINE_CTRL_X;
|
||||
}
|
||||
|
||||
trigger_modechanged();
|
||||
}
|
||||
|
||||
// Whether other than default completion has been selected.
|
||||
@ -2661,6 +2663,7 @@ void set_completion(colnr_T startcol, list_T *list)
|
||||
show_pum(save_w_wrow, save_w_leftcol);
|
||||
}
|
||||
|
||||
trigger_modechanged();
|
||||
ui_flush();
|
||||
}
|
||||
|
||||
@ -3839,6 +3842,8 @@ static bool ins_compl_prep(int c)
|
||||
ins_apply_autocmds(EVENT_COMPLETEDONE);
|
||||
}
|
||||
|
||||
trigger_modechanged();
|
||||
|
||||
/* reset continue_* if we left expansion-mode, if we stay they'll be
|
||||
* (re)set properly in ins_complete() */
|
||||
if (!vim_is_ctrl_x_key(c)) {
|
||||
@ -4587,6 +4592,8 @@ static int ins_compl_get_exp(pos_T *ini)
|
||||
compl_curr_match = compl_old_match;
|
||||
}
|
||||
}
|
||||
trigger_modechanged();
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -1067,12 +1067,13 @@ void trigger_modechanged(void)
|
||||
return;
|
||||
}
|
||||
|
||||
dict_T *v_event = get_vim_var_dict(VV_EVENT);
|
||||
|
||||
char *mode = get_mode();
|
||||
if (last_mode == NULL) {
|
||||
last_mode = (char *)vim_strsave((char_u *)"n");
|
||||
if (STRCMP(mode, last_mode) == 0) {
|
||||
xfree(mode);
|
||||
return;
|
||||
}
|
||||
|
||||
dict_T *v_event = get_vim_var_dict(VV_EVENT);
|
||||
tv_dict_add_str(v_event, S_LEN("new_mode"), mode);
|
||||
tv_dict_add_str(v_event, S_LEN("old_mode"), last_mode);
|
||||
|
||||
|
@ -487,6 +487,7 @@ static void normal_prepare(NormalState *s)
|
||||
if (finish_op != c) {
|
||||
ui_cursor_shape(); // may show different cursor shape
|
||||
}
|
||||
trigger_modechanged();
|
||||
|
||||
// When not finishing an operator and no register name typed, reset the count.
|
||||
if (!finish_op && !s->oa.regname) {
|
||||
@ -928,6 +929,7 @@ normal_end:
|
||||
// Reset finish_op, in case it was set
|
||||
s->c = finish_op;
|
||||
finish_op = false;
|
||||
trigger_modechanged();
|
||||
// Redraw the cursor with another shape, if we were in Operator-pending
|
||||
// mode or did a replace command.
|
||||
if (s->c || s->ca.cmdchar == 'r') {
|
||||
@ -965,6 +967,7 @@ normal_end:
|
||||
&& s->oa.regname == 0) {
|
||||
if (restart_VIsual_select == 1) {
|
||||
VIsual_select = true;
|
||||
trigger_modechanged();
|
||||
showmode();
|
||||
restart_VIsual_select = 0;
|
||||
}
|
||||
@ -3050,7 +3053,6 @@ static int get_mouse_class(char_u *p)
|
||||
void end_visual_mode(void)
|
||||
{
|
||||
VIsual_active = false;
|
||||
trigger_modechanged();
|
||||
setmouse();
|
||||
mouse_dragging = 0;
|
||||
|
||||
@ -3067,6 +3069,7 @@ void end_visual_mode(void)
|
||||
may_clear_cmdline();
|
||||
|
||||
adjust_cursor_eol();
|
||||
trigger_modechanged();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4852,6 +4855,7 @@ static void nv_ctrlg(cmdarg_T *cap)
|
||||
{
|
||||
if (VIsual_active) { // toggle Selection/Visual mode
|
||||
VIsual_select = !VIsual_select;
|
||||
trigger_modechanged();
|
||||
showmode();
|
||||
} else if (!checkclearop(cap->oap)) {
|
||||
// print full name if count given or :cd used
|
||||
@ -4895,6 +4899,7 @@ static void nv_ctrlo(cmdarg_T *cap)
|
||||
{
|
||||
if (VIsual_active && VIsual_select) {
|
||||
VIsual_select = false;
|
||||
trigger_modechanged();
|
||||
showmode();
|
||||
restart_VIsual_select = 2; // restart Select mode later
|
||||
} else {
|
||||
|
@ -1646,12 +1646,8 @@ endfunc
|
||||
|
||||
" Test for ModeChanged pattern
|
||||
func Test_mode_changes()
|
||||
let g:count = 0
|
||||
func! DoIt()
|
||||
let g:count += 1
|
||||
endfunc
|
||||
let g:index = 0
|
||||
let g:mode_seq = ['n', 'i', 'n', 'v', 'V', 'n', 'V', 'v', 'n']
|
||||
let g:mode_seq = ['n', 'i', 'n', 'v', 'V', 'i', 'ix', 'i', 'ic', 'i', 'n', 'no', 'n', 'V', 'v', 's', 'n']
|
||||
func! TestMode()
|
||||
call assert_equal(g:mode_seq[g:index], get(v:event, "old_mode"))
|
||||
call assert_equal(g:mode_seq[g:index + 1], get(v:event, "new_mode"))
|
||||
@ -1660,13 +1656,15 @@ func Test_mode_changes()
|
||||
endfunc
|
||||
|
||||
au ModeChanged * :call TestMode()
|
||||
au ModeChanged n:* :call DoIt()
|
||||
call feedkeys("i\<esc>vV\<esc>", 'tnix')
|
||||
call assert_equal(2, g:count)
|
||||
let g:n_to_any = 0
|
||||
au ModeChanged n:* let g:n_to_any += 1
|
||||
call feedkeys("i\<esc>vVca\<CR>\<C-X>\<C-L>\<esc>ggdG", 'tnix')
|
||||
|
||||
au ModeChanged V:v :call DoIt()
|
||||
call feedkeys("Vv\<esc>", 'tnix')
|
||||
call assert_equal(4, g:count)
|
||||
let g:V_to_v = 0
|
||||
au ModeChanged V:v let g:V_to_v += 1
|
||||
call feedkeys("Vv\<C-G>\<esc>", 'tnix')
|
||||
call assert_equal(len(filter(g:mode_seq[1:], {idx, val -> val == 'n'})), g:n_to_any)
|
||||
call assert_equal(1, g:V_to_v)
|
||||
call assert_equal(len(g:mode_seq) - 1, g:index)
|
||||
|
||||
let g:n_to_i = 0
|
||||
@ -1695,12 +1693,32 @@ func Test_mode_changes()
|
||||
call assert_equal(2, g:i_to_any)
|
||||
call assert_equal(3, g:nori_to_any)
|
||||
|
||||
if has('terminal')
|
||||
let g:mode_seq += ['c', 'n', 't', 'nt', 'c', 'nt', 'n']
|
||||
call feedkeys(":term\<CR>\<C-W>N:bd!\<CR>", 'tnix')
|
||||
call assert_equal(len(g:mode_seq) - 1, g:index)
|
||||
call assert_equal(1, g:n_to_i)
|
||||
call assert_equal(1, g:n_to_niI)
|
||||
call assert_equal(1, g:niI_to_i)
|
||||
call assert_equal(2, g:nany_to_i)
|
||||
call assert_equal(1, g:i_to_n)
|
||||
call assert_equal(2, g:i_to_any)
|
||||
call assert_equal(5, g:nori_to_any)
|
||||
endif
|
||||
|
||||
au! ModeChanged
|
||||
delfunc TestMode
|
||||
unlet! g:mode_seq
|
||||
unlet! g:index
|
||||
delfunc DoIt
|
||||
unlet! g:count
|
||||
unlet! g:n_to_any
|
||||
unlet! g:V_to_v
|
||||
unlet! g:n_to_i
|
||||
unlet! g:n_to_niI
|
||||
unlet! g:niI_to_i
|
||||
unlet! g:nany_to_i
|
||||
unlet! g:i_to_n
|
||||
unlet! g:nori_to_any
|
||||
unlet! g:i_to_any
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
Loading…
Reference in New Issue
Block a user