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:
committed by
Bram Moolenaar
parent
a2ffb43520
commit
25def2c8b8
@@ -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.
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
src/misc1.c
11
src/misc1.c
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user