diff options
author | LemonBoy <thatlemon@gmail.com> | 2022-04-09 18:17:34 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-04-09 18:17:34 +0100 |
commit | 2bf52dd065495cbf28e28792f2c2d50d44546d9f (patch) | |
tree | f6c2fabb35e2f7f12f441d76048b3f1575f4a6b4 | |
parent | 81b46a6ccd818609e1ca8cd410e26a58428c30ba (diff) | |
download | vim-git-2bf52dd065495cbf28e28792f2c2d50d44546d9f.tar.gz |
patch 8.2.4723: the ModeChanged autocmd event is inefficientv8.2.4723
Problem: The ModeChanged autocmd event is inefficient.
Solution: Avoid allocating memory. (closes #10134) Rename
trigger_modechanged() to may_trigger_modechanged().
-rw-r--r-- | src/autocmd.c | 12 | ||||
-rw-r--r-- | src/edit.c | 6 | ||||
-rw-r--r-- | src/ex_docmd.c | 2 | ||||
-rw-r--r-- | src/ex_getln.c | 4 | ||||
-rw-r--r-- | src/insexpand.c | 8 | ||||
-rw-r--r-- | src/misc1.c | 117 | ||||
-rw-r--r-- | src/normal.c | 16 | ||||
-rw-r--r-- | src/proto/misc1.pro | 3 | ||||
-rw-r--r-- | src/terminal.c | 2 | ||||
-rw-r--r-- | src/version.c | 2 |
10 files changed, 84 insertions, 88 deletions
diff --git a/src/autocmd.c b/src/autocmd.c index a0065decb..3b384f5f9 100644 --- a/src/autocmd.c +++ b/src/autocmd.c @@ -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. diff --git a/src/edit.c b/src/edit.c index 1585f8518..fad2a7b1a 100644 --- a/src/edit.c +++ b/src/edit.c @@ -284,7 +284,7 @@ edit( else State = INSERT; - trigger_modechanged(); + may_trigger_modechanged(); stop_insert_mode = FALSE; #ifdef FEAT_CONCEAL @@ -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); @@ -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 diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 0b8825959..7e3cb7ec3 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -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. diff --git a/src/ex_getln.c b/src/ex_getln.c index 4b149716d..3cacf9df7 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -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(); @@ -2555,7 +2555,7 @@ returncmd: #ifdef FEAT_EVAL if (!debug_mode) - trigger_modechanged(); + may_trigger_modechanged(); #endif #ifdef HAVE_INPUT_METHOD diff --git a/src/insexpand.c b/src/insexpand.c index b7b6c0256..2c549f828 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -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(); } /* @@ -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() @@ -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(); } @@ -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; } diff --git a/src/misc1.c b/src/misc1.c index 7fc625b51..82dbbba6e 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -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])) @@ -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 } diff --git a/src/normal.c b/src/normal.c index e39fb772a..d7a285714 100644 --- a/src/normal.c +++ b/src/normal.c @@ -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. @@ -971,7 +971,7 @@ normal_end: 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. @@ -1027,7 +1027,7 @@ normal_end: if (restart_VIsual_select == 1) { VIsual_select = TRUE; - trigger_modechanged(); + may_trigger_modechanged(); showmode(); restart_VIsual_select = 0; VIsual_select_reg = 0; @@ -1151,7 +1151,7 @@ end_visual_mode_keep_button() may_clear_cmdline(); adjust_cursor_eol(); - trigger_modechanged(); + may_trigger_modechanged(); } /* @@ -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)) @@ -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 } @@ -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 } @@ -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. diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro index db60a6dc2..cc7e07a20 100644 --- a/src/proto/misc1.pro +++ b/src/proto/misc1.pro @@ -14,6 +14,7 @@ void pchar_cursor(int c); char_u *skip_to_option_part(char_u *p); void check_status(buf_T *buf); int ask_yesno(char_u *str, int direct); +void get_mode(char_u *buf); void f_mode(typval_T *argvars, typval_T *rettv); void f_state(typval_T *argvars, typval_T *rettv); int get_keystroke(void); @@ -49,5 +50,5 @@ int path_is_url(char_u *p); int path_with_url(char_u *fname); dict_T *get_v_event(save_v_event_T *sve); void restore_v_event(dict_T *v_event, save_v_event_T *sve); -void trigger_modechanged(void); +void may_trigger_modechanged(void); /* vim: set ft=c : */ diff --git a/src/terminal.c b/src/terminal.c index 0849f2c00..b6efb493e 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -2035,7 +2035,7 @@ term_check_timers(int next_due_arg, proftime_T *now) set_terminal_mode(term_T *term, int normal_mode) { term->tl_normal_mode = normal_mode; - trigger_modechanged(); + may_trigger_modechanged(); if (!normal_mode) handle_postponed_scrollback(term); VIM_CLEAR(term->tl_status_text); diff --git a/src/version.c b/src/version.c index 410fe2aa5..574bacbaa 100644 --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4723, +/**/ 4722, /**/ 4721, |