Skip to content

Commit

Permalink
patch 8.2.4723: the ModeChanged autocmd event is inefficient
Browse files Browse the repository at this point in the history
Problem:    The ModeChanged autocmd event is inefficient.
Solution:   Avoid allocating memory. (closes #10134)  Rename
            trigger_modechanged() to may_trigger_modechanged().
  • Loading branch information
LemonBoy authored and brammool committed Apr 9, 2022
1 parent 81b46a6 commit 2bf52dd
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 88 deletions.
12 changes: 1 addition & 11 deletions src/autocmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1240,17 +1240,7 @@ do_autocmd_event(
// 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);
}
get_mode(last_mode);
#endif
// Initialize the fields checked by the WinScrolled trigger to
// stop it from firing right after the first autocmd is defined.
Expand Down
6 changes: 3 additions & 3 deletions src/edit.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ edit(
else
State = INSERT;

trigger_modechanged();
may_trigger_modechanged();
stop_insert_mode = FALSE;

#ifdef FEAT_CONCEAL
Expand Down Expand Up @@ -3701,7 +3701,7 @@ ins_esc(
#endif

State = NORMAL;
trigger_modechanged();
may_trigger_modechanged();
// need to position cursor again when on a TAB
if (gchar_cursor() == TAB)
curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
Expand Down Expand Up @@ -3838,7 +3838,7 @@ ins_insert(int replaceState)
State = INSERT | (State & LANGMAP);
else
State = replaceState | (State & LANGMAP);
trigger_modechanged();
may_trigger_modechanged();
AppendCharToRedobuff(K_INS);
showmode();
#ifdef CURSOR_SHAPE
Expand Down
2 changes: 1 addition & 1 deletion src/ex_docmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ do_exmode(
else
exmode_active = EXMODE_NORMAL;
State = NORMAL;
trigger_modechanged();
may_trigger_modechanged();

// When using ":global /pat/ visual" and then "Q" we return to continue
// the :global command.
Expand Down
4 changes: 2 additions & 2 deletions src/ex_getln.c
Original file line number Diff line number Diff line change
Expand Up @@ -1714,7 +1714,7 @@ getcmdline_int(
trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINEENTER);
#ifdef FEAT_EVAL
if (!debug_mode)
trigger_modechanged();
may_trigger_modechanged();
#endif

init_history();
Expand Down Expand Up @@ -2555,7 +2555,7 @@ getcmdline_int(

#ifdef FEAT_EVAL
if (!debug_mode)
trigger_modechanged();
may_trigger_modechanged();
#endif

#ifdef HAVE_INPUT_METHOD
Expand Down
8 changes: 4 additions & 4 deletions src/insexpand.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ ins_ctrl_x(void)
// CTRL-V look like CTRL-N
ctrl_x_mode = CTRL_X_CMDLINE_CTRL_X;

trigger_modechanged();
may_trigger_modechanged();
}

/*
Expand Down Expand Up @@ -2381,7 +2381,7 @@ ins_compl_prep(int c)
// upon the (possibly failed) completion.
ins_apply_autocmds(EVENT_COMPLETEDONE);

trigger_modechanged();
may_trigger_modechanged();

// reset continue_* if we left expansion-mode, if we stay they'll be
// (re)set properly in ins_complete()
Expand Down Expand Up @@ -2865,7 +2865,7 @@ set_completion(colnr_T startcol, list_T *list)
// Lazily show the popup menu, unless we got interrupted.
if (!compl_interrupted)
show_pum(save_w_wrow, save_w_leftcol);
trigger_modechanged();
may_trigger_modechanged();
out_flush();
}

Expand Down Expand Up @@ -3818,7 +3818,7 @@ ins_compl_get_exp(pos_T *ini)
if (compl_curr_match == NULL)
compl_curr_match = compl_old_match;
}
trigger_modechanged();
may_trigger_modechanged();

return i;
}
Expand Down
117 changes: 60 additions & 57 deletions src/misc1.c
Original file line number Diff line number Diff line change
Expand Up @@ -625,105 +625,119 @@ ask_yesno(char_u *str, int direct)
#if defined(FEAT_EVAL) || defined(PROTO)

/*
* "mode()" function
* Returns the current mode as a string in "buf[MODE_MAX_LENGTH]", NUL
* terminated.
* The first character represents the major mode, the following ones the minor
* ones.
*/
void
f_mode(typval_T *argvars, typval_T *rettv)
get_mode(char_u *buf)
{
char_u buf[MODE_MAX_LENGTH];

if (in_vim9script() && check_for_opt_bool_arg(argvars, 0) == FAIL)
return;

CLEAR_FIELD(buf);
int i = 0;

if (time_for_testing == 93784)
{
// Testing the two-character code.
buf[0] = 'x';
buf[1] = '!';
buf[i++] = 'x';
buf[i++] = '!';
}
#ifdef FEAT_TERMINAL
else if (term_use_loop())
buf[0] = 't';
buf[i++] = 't';
#endif
else if (VIsual_active)
{
if (VIsual_select)
buf[0] = VIsual_mode + 's' - 'v';
buf[i++] = VIsual_mode + 's' - 'v';
else
{
buf[0] = VIsual_mode;
buf[i++] = VIsual_mode;
if (restart_VIsual_select)
buf[1] = 's';
buf[i++] = 's';
}
}
else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE
|| State == CONFIRM)
{
buf[0] = 'r';
buf[i++] = 'r';
if (State == ASKMORE)
buf[1] = 'm';
buf[i++] = 'm';
else if (State == CONFIRM)
buf[1] = '?';
buf[i++] = '?';
}
else if (State == EXTERNCMD)
buf[0] = '!';
buf[i++] = '!';
else if (State & INSERT)
{
if (State & VREPLACE_FLAG)
{
buf[0] = 'R';
buf[1] = 'v';
buf[i++] = 'R';
buf[i++] = 'v';

if (ins_compl_active())
buf[2] = 'c';
buf[i++] = 'c';
else if (ctrl_x_mode_not_defined_yet())
buf[2] = 'x';
buf[i++] = 'x';
}
else
{
if (State & REPLACE_FLAG)
buf[0] = 'R';
buf[i++] = 'R';
else
buf[0] = 'i';
buf[i++] = 'i';

if (ins_compl_active())
buf[1] = 'c';
buf[i++] = 'c';
else if (ctrl_x_mode_not_defined_yet())
buf[1] = 'x';
buf[i++] = 'x';
}
}
else if ((State & CMDLINE) || exmode_active)
{
buf[0] = 'c';
buf[i++] = 'c';
if (exmode_active == EXMODE_VIM)
buf[1] = 'v';
buf[i++] = 'v';
else if (exmode_active == EXMODE_NORMAL)
buf[1] = 'e';
buf[i++] = 'e';
}
else
{
buf[0] = 'n';
buf[i++] = 'n';
if (finish_op)
{
buf[1] = 'o';
buf[i++] = 'o';
// to be able to detect force-linewise/blockwise/characterwise
// operations
buf[2] = motion_force;
buf[i++] = motion_force;
}
else if (restart_edit == 'I' || restart_edit == 'R'
|| restart_edit == 'V')
{
buf[1] = 'i';
buf[2] = restart_edit;
buf[i++] = 'i';
buf[i++] = restart_edit;
}
#ifdef FEAT_TERMINAL
else if (term_in_normal_mode())
buf[1] = 't';
buf[i++] = 't';
#endif
}

buf[i] = NUL;
}

/*
* "mode()" function
*/
void
f_mode(typval_T *argvars, typval_T *rettv)
{
char_u buf[MODE_MAX_LENGTH];

if (in_vim9script() && check_for_opt_bool_arg(argvars, 0) == FAIL)
return;

get_mode(buf);

// Clear out the minor mode when the argument is not a non-zero number or
// non-empty string.
if (!non_zero_arg(&argvars[0]))
Expand Down Expand Up @@ -2691,47 +2705,36 @@ restore_v_event(dict_T *v_event, save_v_event_T *sve)
#endif

/*
* Fires a ModeChanged autocmd
* Fires a ModeChanged autocmd event if appropriate.
*/
void
trigger_modechanged()
may_trigger_modechanged()
{
#ifdef FEAT_EVAL
dict_T *v_event;
typval_T rettv;
typval_T tv[2];
char_u *pat_pre;
char_u *pat;
save_v_event_T save_v_event;
char_u curr_mode[MODE_MAX_LENGTH];
char_u pattern_buf[2 * MODE_MAX_LENGTH];

if (!has_modechanged())
return;

tv[0].v_type = VAR_NUMBER;
tv[0].vval.v_number = 1; // get full mode
tv[1].v_type = VAR_UNKNOWN;
f_mode(tv, &rettv);
if (STRCMP(rettv.vval.v_string, last_mode) == 0)
{
vim_free(rettv.vval.v_string);
get_mode(curr_mode);
if (STRCMP(curr_mode, last_mode) == 0)
return;
}

v_event = get_v_event(&save_v_event);
(void)dict_add_string(v_event, "new_mode", rettv.vval.v_string);
(void)dict_add_string(v_event, "new_mode", curr_mode);
(void)dict_add_string(v_event, "old_mode", last_mode);
dict_set_items_ro(v_event);

// concatenate modes in format "old_mode:new_mode"
pat_pre = concat_str(last_mode, (char_u*)":");
pat = concat_str(pat_pre, rettv.vval.v_string);
vim_free(pat_pre);
vim_snprintf((char *)pattern_buf, sizeof(pattern_buf), "%s:%s", last_mode,
curr_mode);

apply_autocmds(EVENT_MODECHANGED, pat, NULL, FALSE, curbuf);
STRCPY(last_mode, rettv.vval.v_string);
apply_autocmds(EVENT_MODECHANGED, pattern_buf, NULL, FALSE, curbuf);
STRCPY(last_mode, curr_mode);

vim_free(pat);
restore_v_event(v_event, &save_v_event);
vim_free(rettv.vval.v_string);
#endif
}
16 changes: 8 additions & 8 deletions src/normal.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,7 @@ normal_cmd(
# endif
}
#endif
trigger_modechanged();
may_trigger_modechanged();

// When not finishing an operator and no register name typed, reset the
// count.
Expand Down Expand Up @@ -971,7 +971,7 @@ normal_cmd(
c = finish_op;
#endif
finish_op = FALSE;
trigger_modechanged();
may_trigger_modechanged();
#ifdef CURSOR_SHAPE
// Redraw the cursor with another shape, if we were in Operator-pending
// mode or did a replace command.
Expand Down Expand Up @@ -1027,7 +1027,7 @@ normal_cmd(
if (restart_VIsual_select == 1)
{
VIsual_select = TRUE;
trigger_modechanged();
may_trigger_modechanged();
showmode();
restart_VIsual_select = 0;
VIsual_select_reg = 0;
Expand Down Expand Up @@ -1151,7 +1151,7 @@ end_visual_mode_keep_button()
may_clear_cmdline();

adjust_cursor_eol();
trigger_modechanged();
may_trigger_modechanged();
}

/*
Expand Down Expand Up @@ -3222,7 +3222,7 @@ nv_ctrlg(cmdarg_T *cap)
if (VIsual_active) // toggle Selection/Visual mode
{
VIsual_select = !VIsual_select;
trigger_modechanged();
may_trigger_modechanged();
showmode();
}
else if (!checkclearop(cap->oap))
Expand Down Expand Up @@ -3285,7 +3285,7 @@ nv_ctrlo(cmdarg_T *cap)
if (VIsual_active && VIsual_select)
{
VIsual_select = FALSE;
trigger_modechanged();
may_trigger_modechanged();
showmode();
restart_VIsual_select = 2; // restart Select mode later
}
Expand Down Expand Up @@ -5422,7 +5422,7 @@ nv_visual(cmdarg_T *cap)
{ // or char/line mode
VIsual_mode = cap->cmdchar;
showmode();
trigger_modechanged();
may_trigger_modechanged();
}
redraw_curbuf_later(INVERTED); // update the inversion
}
Expand Down Expand Up @@ -5549,7 +5549,7 @@ n_start_visual_mode(int c)
foldAdjustVisual();
#endif

trigger_modechanged();
may_trigger_modechanged();
setmouse();
#ifdef FEAT_CONCEAL
// Check if redraw is needed after changing the state.
Expand Down

0 comments on commit 2bf52dd

Please sign in to comment.