]> granicus.if.org Git - vim/commitdiff
patch 8.2.4723: the ModeChanged autocmd event is inefficient v8.2.4723
authorLemonBoy <thatlemon@gmail.com>
Sat, 9 Apr 2022 17:17:34 +0000 (18:17 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 9 Apr 2022 17:17:34 +0000 (18:17 +0100)
Problem:    The ModeChanged autocmd event is inefficient.
Solution:   Avoid allocating memory. (closes #10134)  Rename
            trigger_modechanged() to may_trigger_modechanged().

src/autocmd.c
src/edit.c
src/ex_docmd.c
src/ex_getln.c
src/insexpand.c
src/misc1.c
src/normal.c
src/proto/misc1.pro
src/terminal.c
src/version.c

index a0065decba8da79a096daa7054ba69e261b4d194..3b384f5f96a1a60056b370f91bf717d36f3c37c5 100644 (file)
@@ -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.
index 1585f851843247a435165908ead49f5a1a9ee6e0..fad2a7b1a474024dfbcf76bcc577b59f2f1df392 100644 (file)
@@ -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
index 0b8825959e6260ac32070d46177629d83b3736fa..7e3cb7ec37b971fed64130d399c9ea68371fdc0f 100644 (file)
@@ -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.
index 4b149716d4a5473fe82c63d2ca78151db273bda7..3cacf9df76ccf855d6c1a050265d935595ce3195 100644 (file)
@@ -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
index b7b6c0256cae0a3d1147ba30f7b85248e9f3ef2d..2c549f828c0901dce78330ba8feb1cfa87399350 100644 (file)
@@ -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;
 }
index 7fc625b51d50d0ffd50b067109930329f895bb62..82dbbba6e684d2b1a7eaae7f3e993c86a94c4471 100644 (file)
@@ -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
 }
index e39fb772ae15c5ca7edd7d08b738d13cc1ce6e3a..d7a2857146a7290dc53d9f8b12688b872251d093 100644 (file)
@@ -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.
index db60a6dc2e9916e0767958387d37c02adc9bd098..cc7e07a20c42585b4b33be44caf8812a099c370d 100644 (file)
@@ -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 : */
index 0849f2c007b73c74fba59f496c35597b6f685f98..b6efb493e74ad56fdfc7c550eb4907027dfbcfdb 100644 (file)
@@ -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);
index 410fe2aa59a22d3073172626e3e4ccdf4a7bc1b6..574bacbaa61eb659db874096433e6b1f4f4835c2 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4723,
 /**/
     4722,
 /**/