Mercurial > vim
diff src/misc1.c @ 28397:d1702731786c v8.2.4723
patch 8.2.4723: the ModeChanged autocmd event is inefficient
Commit: https://github.com/vim/vim/commit/2bf52dd065495cbf28e28792f2c2d50d44546d9f
Author: LemonBoy <thatlemon@gmail.com>
Date: Sat Apr 9 18:17:34 2022 +0100
patch 8.2.4723: the ModeChanged autocmd event is inefficient
Problem: The ModeChanged autocmd event is inefficient.
Solution: Avoid allocating memory. (closes https://github.com/vim/vim/issues/10134) Rename
trigger_modechanged() to may_trigger_modechanged().
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 09 Apr 2022 19:30:02 +0200 |
parents | 41e0dcf38521 |
children | f4d2dcfd18ac |
line wrap: on
line diff
--- a/src/misc1.c +++ b/src/misc1.c @@ -625,6 +625,107 @@ ask_yesno(char_u *str, int direct) #if defined(FEAT_EVAL) || defined(PROTO) /* + * 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 +get_mode(char_u *buf) +{ + int i = 0; + + if (time_for_testing == 93784) + { + // Testing the two-character code. + buf[i++] = 'x'; + buf[i++] = '!'; + } +#ifdef FEAT_TERMINAL + else if (term_use_loop()) + buf[i++] = 't'; +#endif + else if (VIsual_active) + { + if (VIsual_select) + buf[i++] = VIsual_mode + 's' - 'v'; + else + { + buf[i++] = VIsual_mode; + if (restart_VIsual_select) + buf[i++] = 's'; + } + } + else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE + || State == CONFIRM) + { + buf[i++] = 'r'; + if (State == ASKMORE) + buf[i++] = 'm'; + else if (State == CONFIRM) + buf[i++] = '?'; + } + else if (State == EXTERNCMD) + buf[i++] = '!'; + else if (State & INSERT) + { + if (State & VREPLACE_FLAG) + { + buf[i++] = 'R'; + buf[i++] = 'v'; + + if (ins_compl_active()) + buf[i++] = 'c'; + else if (ctrl_x_mode_not_defined_yet()) + buf[i++] = 'x'; + } + else + { + if (State & REPLACE_FLAG) + buf[i++] = 'R'; + else + buf[i++] = 'i'; + + if (ins_compl_active()) + buf[i++] = 'c'; + else if (ctrl_x_mode_not_defined_yet()) + buf[i++] = 'x'; + } + } + else if ((State & CMDLINE) || exmode_active) + { + buf[i++] = 'c'; + if (exmode_active == EXMODE_VIM) + buf[i++] = 'v'; + else if (exmode_active == EXMODE_NORMAL) + buf[i++] = 'e'; + } + else + { + buf[i++] = 'n'; + if (finish_op) + { + buf[i++] = 'o'; + // to be able to detect force-linewise/blockwise/characterwise + // operations + buf[i++] = motion_force; + } + else if (restart_edit == 'I' || restart_edit == 'R' + || restart_edit == 'V') + { + buf[i++] = 'i'; + buf[i++] = restart_edit; + } +#ifdef FEAT_TERMINAL + else if (term_in_normal_mode()) + buf[i++] = 't'; +#endif + } + + buf[i] = NUL; +} + +/* * "mode()" function */ void @@ -635,94 +736,7 @@ f_mode(typval_T *argvars, typval_T *rett if (in_vim9script() && check_for_opt_bool_arg(argvars, 0) == FAIL) return; - CLEAR_FIELD(buf); - - if (time_for_testing == 93784) - { - // Testing the two-character code. - buf[0] = 'x'; - buf[1] = '!'; - } -#ifdef FEAT_TERMINAL - else if (term_use_loop()) - buf[0] = 't'; -#endif - else if (VIsual_active) - { - if (VIsual_select) - buf[0] = VIsual_mode + 's' - 'v'; - else - { - buf[0] = VIsual_mode; - if (restart_VIsual_select) - buf[1] = 's'; - } - } - else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE - || State == CONFIRM) - { - buf[0] = 'r'; - if (State == ASKMORE) - buf[1] = 'm'; - else if (State == CONFIRM) - buf[1] = '?'; - } - else if (State == EXTERNCMD) - buf[0] = '!'; - else if (State & INSERT) - { - if (State & VREPLACE_FLAG) - { - buf[0] = 'R'; - buf[1] = 'v'; - - if (ins_compl_active()) - buf[2] = 'c'; - else if (ctrl_x_mode_not_defined_yet()) - buf[2] = 'x'; - } - else - { - if (State & REPLACE_FLAG) - buf[0] = 'R'; - else - buf[0] = 'i'; - - if (ins_compl_active()) - buf[1] = 'c'; - else if (ctrl_x_mode_not_defined_yet()) - buf[1] = 'x'; - } - } - else if ((State & CMDLINE) || exmode_active) - { - buf[0] = 'c'; - if (exmode_active == EXMODE_VIM) - buf[1] = 'v'; - else if (exmode_active == EXMODE_NORMAL) - buf[1] = 'e'; - } - else - { - buf[0] = 'n'; - if (finish_op) - { - buf[1] = 'o'; - // to be able to detect force-linewise/blockwise/characterwise - // operations - buf[2] = motion_force; - } - else if (restart_edit == 'I' || restart_edit == 'R' - || restart_edit == 'V') - { - buf[1] = 'i'; - buf[2] = restart_edit; - } -#ifdef FEAT_TERMINAL - else if (term_in_normal_mode()) - buf[1] = 't'; -#endif - } + get_mode(buf); // Clear out the minor mode when the argument is not a non-zero number or // non-empty string. @@ -2691,47 +2705,36 @@ restore_v_event(dict_T *v_event, save_v_ #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 }