0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

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 #8999)
This commit is contained in:
=?UTF-8?q?Magnus=20Gro=C3=9F?=
2021-10-22 18:56:39 +01:00
committed by Bram Moolenaar
parent a2ffb43520
commit 25def2c8b8
8 changed files with 81 additions and 21 deletions

View File

@@ -930,18 +930,23 @@ MenuPopup Just before showing the popup menu (under the
*ModeChanged* *ModeChanged*
ModeChanged After changing the mode. The pattern is ModeChanged After changing the mode. The pattern is
matched against `'old_mode:new_mode'`, for matched against `'old_mode:new_mode'`, for
example match against `i:*` to simulate example match against `*:c*` to simulate
|InsertLeave|. |CmdlineEnter|.
The following values of |v:event| are set: The following values of |v:event| are set:
old_mode The mode before it changed. old_mode The mode before it changed.
new_mode The new mode as also returned 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 When ModeChanged is triggered, old_mode will
have the value of new_mode when the event was have the value of new_mode when the event was
last triggered. last triggered.
This will be triggered on every minor mode
change.
Usage example to use relative line numbers Usage example to use relative line numbers
when entering Visual mode: > when entering Visual mode: >
:autocmd ModeChanged *:v set relativenumber :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*
OptionSet After setting an option. The pattern is OptionSet After setting an option. The pattern is
matched against the long option name. matched against the long option name.

View File

@@ -1218,6 +1218,23 @@ do_autocmd_event(
return FAIL; return FAIL;
} }
#ifdef FEAT_EVAL
// need to initialize last_mode for the first ModeChanged
// autocmd
if (event == EVENT_MODECHANGED && !has_modechanged())
{
typval_T rettv;
typval_T tv[2];
tv[0].v_type = VAR_NUMBER;
tv[0].vval.v_number = 1;
tv[1].v_type = VAR_UNKNOWN;
f_mode(tv, &rettv);
STRCPY(last_mode, rettv.vval.v_string);
vim_free(rettv.vval.v_string);
}
#endif
if (is_buflocal) if (is_buflocal)
{ {
ap->buflocal_nr = buflocal_nr; ap->buflocal_nr = buflocal_nr;

View File

@@ -243,6 +243,8 @@ ins_ctrl_x(void)
// CTRL-X in CTRL-X CTRL-V mode behaves differently to make CTRL-X // CTRL-X in CTRL-X CTRL-V mode behaves differently to make CTRL-X
// CTRL-V look like CTRL-N // CTRL-V look like CTRL-N
ctrl_x_mode = CTRL_X_CMDLINE_CTRL_X; ctrl_x_mode = CTRL_X_CMDLINE_CTRL_X;
trigger_modechanged();
} }
/* /*
@@ -2150,6 +2152,8 @@ ins_compl_prep(int c)
// upon the (possibly failed) completion. // upon the (possibly failed) completion.
ins_apply_autocmds(EVENT_COMPLETEDONE); ins_apply_autocmds(EVENT_COMPLETEDONE);
trigger_modechanged();
// reset continue_* if we left expansion-mode, if we stay they'll be // reset continue_* if we left expansion-mode, if we stay they'll be
// (re)set properly in ins_complete() // (re)set properly in ins_complete()
if (!vim_is_ctrl_x_key(c)) if (!vim_is_ctrl_x_key(c))
@@ -2487,6 +2491,7 @@ set_completion(colnr_T startcol, list_T *list)
// Lazily show the popup menu, unless we got interrupted. // Lazily show the popup menu, unless we got interrupted.
if (!compl_interrupted) if (!compl_interrupted)
show_pum(save_w_wrow, save_w_leftcol); show_pum(save_w_wrow, save_w_leftcol);
trigger_modechanged();
out_flush(); out_flush();
} }
@@ -3255,6 +3260,8 @@ ins_compl_get_exp(pos_T *ini)
if (compl_curr_match == NULL) if (compl_curr_match == NULL)
compl_curr_match = compl_old_match; compl_curr_match = compl_old_match;
} }
trigger_modechanged();
return i; return i;
} }

View File

@@ -2670,12 +2670,17 @@ trigger_modechanged()
if (!has_modechanged()) if (!has_modechanged())
return; return;
v_event = get_vim_var_dict(VV_EVENT);
tv[0].v_type = VAR_NUMBER; tv[0].v_type = VAR_NUMBER;
tv[0].vval.v_number = 1; // get full mode tv[0].vval.v_number = 1; // get full mode
tv[1].v_type = VAR_UNKNOWN; tv[1].v_type = VAR_UNKNOWN;
f_mode(tv, &rettv); f_mode(tv, &rettv);
if (STRCMP(rettv.vval.v_string, last_mode) == 0)
{
vim_free(rettv.vval.v_string);
return;
}
v_event = get_vim_var_dict(VV_EVENT);
(void)dict_add_string(v_event, "new_mode", rettv.vval.v_string); (void)dict_add_string(v_event, "new_mode", rettv.vval.v_string);
(void)dict_add_string(v_event, "old_mode", last_mode); (void)dict_add_string(v_event, "old_mode", last_mode);
dict_set_items_ro(v_event); dict_set_items_ro(v_event);
@@ -2688,9 +2693,9 @@ trigger_modechanged()
apply_autocmds(EVENT_MODECHANGED, pat, NULL, FALSE, curbuf); apply_autocmds(EVENT_MODECHANGED, pat, NULL, FALSE, curbuf);
STRCPY(last_mode, rettv.vval.v_string); STRCPY(last_mode, rettv.vval.v_string);
vim_free(rettv.vval.v_string);
vim_free(pat); vim_free(pat);
dict_free_contents(v_event); dict_free_contents(v_event);
hash_init(&v_event->dv_hashtab); hash_init(&v_event->dv_hashtab);
vim_free(rettv.vval.v_string);
#endif #endif
} }

View File

@@ -527,6 +527,7 @@ normal_cmd(
# endif # endif
} }
#endif #endif
trigger_modechanged();
// When not finishing an operator and no register name typed, reset the // When not finishing an operator and no register name typed, reset the
// count. // count.
@@ -1221,6 +1222,7 @@ normal_end:
c = finish_op; c = finish_op;
#endif #endif
finish_op = FALSE; finish_op = FALSE;
trigger_modechanged();
#ifdef CURSOR_SHAPE #ifdef CURSOR_SHAPE
// Redraw the cursor with another shape, if we were in Operator-pending // Redraw the cursor with another shape, if we were in Operator-pending
// mode or did a replace command. // mode or did a replace command.
@@ -1278,6 +1280,7 @@ normal_end:
if (restart_VIsual_select == 1) if (restart_VIsual_select == 1)
{ {
VIsual_select = TRUE; VIsual_select = TRUE;
trigger_modechanged();
showmode(); showmode();
restart_VIsual_select = 0; restart_VIsual_select = 0;
} }
@@ -1386,7 +1389,6 @@ end_visual_mode_keep_button()
#endif #endif
VIsual_active = FALSE; VIsual_active = FALSE;
trigger_modechanged();
setmouse(); setmouse();
mouse_dragging = 0; mouse_dragging = 0;
@@ -1403,6 +1405,7 @@ end_visual_mode_keep_button()
may_clear_cmdline(); may_clear_cmdline();
adjust_cursor_eol(); adjust_cursor_eol();
trigger_modechanged();
} }
/* /*
@@ -3439,6 +3442,7 @@ nv_ctrlg(cmdarg_T *cap)
if (VIsual_active) // toggle Selection/Visual mode if (VIsual_active) // toggle Selection/Visual mode
{ {
VIsual_select = !VIsual_select; VIsual_select = !VIsual_select;
trigger_modechanged();
showmode(); showmode();
} }
else if (!checkclearop(cap->oap)) else if (!checkclearop(cap->oap))
@@ -3501,6 +3505,7 @@ nv_ctrlo(cmdarg_T *cap)
if (VIsual_active && VIsual_select) if (VIsual_active && VIsual_select)
{ {
VIsual_select = FALSE; VIsual_select = FALSE;
trigger_modechanged();
showmode(); showmode();
restart_VIsual_select = 2; // restart Select mode later restart_VIsual_select = 2; // restart Select mode later
} }

View File

@@ -1995,6 +1995,7 @@ term_check_timers(int next_due_arg, proftime_T *now)
set_terminal_mode(term_T *term, int normal_mode) set_terminal_mode(term_T *term, int normal_mode)
{ {
term->tl_normal_mode = normal_mode; term->tl_normal_mode = normal_mode;
trigger_modechanged();
if (!normal_mode) if (!normal_mode)
handle_postponed_scrollback(term); handle_postponed_scrollback(term);
VIM_CLEAR(term->tl_status_text); VIM_CLEAR(term->tl_status_text);

View File

@@ -1959,12 +1959,8 @@ endfunc
" Test for ModeChanged pattern " Test for ModeChanged pattern
func Test_mode_changes() func Test_mode_changes()
let g:count = 0
func! DoIt()
let g:count += 1
endfunc
let g:index = 0 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() func! TestMode()
call assert_equal(g:mode_seq[g:index], get(v:event, "old_mode")) 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")) call assert_equal(g:mode_seq[g:index + 1], get(v:event, "new_mode"))
@@ -1973,13 +1969,15 @@ func Test_mode_changes()
endfunc endfunc
au ModeChanged * :call TestMode() au ModeChanged * :call TestMode()
au ModeChanged n:* :call DoIt() let g:n_to_any = 0
call feedkeys("i\<esc>vV\<esc>", 'tnix') au ModeChanged n:* let g:n_to_any += 1
call assert_equal(2, g:count) call feedkeys("i\<esc>vVca\<CR>\<C-X>\<C-L>\<esc>ggdG", 'tnix')
au ModeChanged V:v :call DoIt() let g:V_to_v = 0
call feedkeys("Vv\<esc>", 'tnix') au ModeChanged V:v let g:V_to_v += 1
call assert_equal(4, g:count) 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) call assert_equal(len(g:mode_seq) - 1, g:index)
let g:n_to_i = 0 let g:n_to_i = 0
@@ -2008,12 +2006,32 @@ func Test_mode_changes()
call assert_equal(2, g:i_to_any) call assert_equal(2, g:i_to_any)
call assert_equal(3, g:nori_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 au! ModeChanged
delfunc TestMode delfunc TestMode
unlet! g:mode_seq unlet! g:mode_seq
unlet! g:index unlet! g:index
delfunc DoIt unlet! g:n_to_any
unlet! g:count 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 endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -757,6 +757,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
3555,
/**/ /**/
3554, 3554,
/**/ /**/