Mercurial > vim
comparison 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 |
comparison
equal
deleted
inserted
replaced
28396:cf018ac0499c | 28397:d1702731786c |
---|---|
623 } | 623 } |
624 | 624 |
625 #if defined(FEAT_EVAL) || defined(PROTO) | 625 #if defined(FEAT_EVAL) || defined(PROTO) |
626 | 626 |
627 /* | 627 /* |
628 * Returns the current mode as a string in "buf[MODE_MAX_LENGTH]", NUL | |
629 * terminated. | |
630 * The first character represents the major mode, the following ones the minor | |
631 * ones. | |
632 */ | |
633 void | |
634 get_mode(char_u *buf) | |
635 { | |
636 int i = 0; | |
637 | |
638 if (time_for_testing == 93784) | |
639 { | |
640 // Testing the two-character code. | |
641 buf[i++] = 'x'; | |
642 buf[i++] = '!'; | |
643 } | |
644 #ifdef FEAT_TERMINAL | |
645 else if (term_use_loop()) | |
646 buf[i++] = 't'; | |
647 #endif | |
648 else if (VIsual_active) | |
649 { | |
650 if (VIsual_select) | |
651 buf[i++] = VIsual_mode + 's' - 'v'; | |
652 else | |
653 { | |
654 buf[i++] = VIsual_mode; | |
655 if (restart_VIsual_select) | |
656 buf[i++] = 's'; | |
657 } | |
658 } | |
659 else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE | |
660 || State == CONFIRM) | |
661 { | |
662 buf[i++] = 'r'; | |
663 if (State == ASKMORE) | |
664 buf[i++] = 'm'; | |
665 else if (State == CONFIRM) | |
666 buf[i++] = '?'; | |
667 } | |
668 else if (State == EXTERNCMD) | |
669 buf[i++] = '!'; | |
670 else if (State & INSERT) | |
671 { | |
672 if (State & VREPLACE_FLAG) | |
673 { | |
674 buf[i++] = 'R'; | |
675 buf[i++] = 'v'; | |
676 | |
677 if (ins_compl_active()) | |
678 buf[i++] = 'c'; | |
679 else if (ctrl_x_mode_not_defined_yet()) | |
680 buf[i++] = 'x'; | |
681 } | |
682 else | |
683 { | |
684 if (State & REPLACE_FLAG) | |
685 buf[i++] = 'R'; | |
686 else | |
687 buf[i++] = 'i'; | |
688 | |
689 if (ins_compl_active()) | |
690 buf[i++] = 'c'; | |
691 else if (ctrl_x_mode_not_defined_yet()) | |
692 buf[i++] = 'x'; | |
693 } | |
694 } | |
695 else if ((State & CMDLINE) || exmode_active) | |
696 { | |
697 buf[i++] = 'c'; | |
698 if (exmode_active == EXMODE_VIM) | |
699 buf[i++] = 'v'; | |
700 else if (exmode_active == EXMODE_NORMAL) | |
701 buf[i++] = 'e'; | |
702 } | |
703 else | |
704 { | |
705 buf[i++] = 'n'; | |
706 if (finish_op) | |
707 { | |
708 buf[i++] = 'o'; | |
709 // to be able to detect force-linewise/blockwise/characterwise | |
710 // operations | |
711 buf[i++] = motion_force; | |
712 } | |
713 else if (restart_edit == 'I' || restart_edit == 'R' | |
714 || restart_edit == 'V') | |
715 { | |
716 buf[i++] = 'i'; | |
717 buf[i++] = restart_edit; | |
718 } | |
719 #ifdef FEAT_TERMINAL | |
720 else if (term_in_normal_mode()) | |
721 buf[i++] = 't'; | |
722 #endif | |
723 } | |
724 | |
725 buf[i] = NUL; | |
726 } | |
727 | |
728 /* | |
628 * "mode()" function | 729 * "mode()" function |
629 */ | 730 */ |
630 void | 731 void |
631 f_mode(typval_T *argvars, typval_T *rettv) | 732 f_mode(typval_T *argvars, typval_T *rettv) |
632 { | 733 { |
633 char_u buf[MODE_MAX_LENGTH]; | 734 char_u buf[MODE_MAX_LENGTH]; |
634 | 735 |
635 if (in_vim9script() && check_for_opt_bool_arg(argvars, 0) == FAIL) | 736 if (in_vim9script() && check_for_opt_bool_arg(argvars, 0) == FAIL) |
636 return; | 737 return; |
637 | 738 |
638 CLEAR_FIELD(buf); | 739 get_mode(buf); |
639 | |
640 if (time_for_testing == 93784) | |
641 { | |
642 // Testing the two-character code. | |
643 buf[0] = 'x'; | |
644 buf[1] = '!'; | |
645 } | |
646 #ifdef FEAT_TERMINAL | |
647 else if (term_use_loop()) | |
648 buf[0] = 't'; | |
649 #endif | |
650 else if (VIsual_active) | |
651 { | |
652 if (VIsual_select) | |
653 buf[0] = VIsual_mode + 's' - 'v'; | |
654 else | |
655 { | |
656 buf[0] = VIsual_mode; | |
657 if (restart_VIsual_select) | |
658 buf[1] = 's'; | |
659 } | |
660 } | |
661 else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE | |
662 || State == CONFIRM) | |
663 { | |
664 buf[0] = 'r'; | |
665 if (State == ASKMORE) | |
666 buf[1] = 'm'; | |
667 else if (State == CONFIRM) | |
668 buf[1] = '?'; | |
669 } | |
670 else if (State == EXTERNCMD) | |
671 buf[0] = '!'; | |
672 else if (State & INSERT) | |
673 { | |
674 if (State & VREPLACE_FLAG) | |
675 { | |
676 buf[0] = 'R'; | |
677 buf[1] = 'v'; | |
678 | |
679 if (ins_compl_active()) | |
680 buf[2] = 'c'; | |
681 else if (ctrl_x_mode_not_defined_yet()) | |
682 buf[2] = 'x'; | |
683 } | |
684 else | |
685 { | |
686 if (State & REPLACE_FLAG) | |
687 buf[0] = 'R'; | |
688 else | |
689 buf[0] = 'i'; | |
690 | |
691 if (ins_compl_active()) | |
692 buf[1] = 'c'; | |
693 else if (ctrl_x_mode_not_defined_yet()) | |
694 buf[1] = 'x'; | |
695 } | |
696 } | |
697 else if ((State & CMDLINE) || exmode_active) | |
698 { | |
699 buf[0] = 'c'; | |
700 if (exmode_active == EXMODE_VIM) | |
701 buf[1] = 'v'; | |
702 else if (exmode_active == EXMODE_NORMAL) | |
703 buf[1] = 'e'; | |
704 } | |
705 else | |
706 { | |
707 buf[0] = 'n'; | |
708 if (finish_op) | |
709 { | |
710 buf[1] = 'o'; | |
711 // to be able to detect force-linewise/blockwise/characterwise | |
712 // operations | |
713 buf[2] = motion_force; | |
714 } | |
715 else if (restart_edit == 'I' || restart_edit == 'R' | |
716 || restart_edit == 'V') | |
717 { | |
718 buf[1] = 'i'; | |
719 buf[2] = restart_edit; | |
720 } | |
721 #ifdef FEAT_TERMINAL | |
722 else if (term_in_normal_mode()) | |
723 buf[1] = 't'; | |
724 #endif | |
725 } | |
726 | 740 |
727 // Clear out the minor mode when the argument is not a non-zero number or | 741 // Clear out the minor mode when the argument is not a non-zero number or |
728 // non-empty string. | 742 // non-empty string. |
729 if (!non_zero_arg(&argvars[0])) | 743 if (!non_zero_arg(&argvars[0])) |
730 buf[1] = NUL; | 744 buf[1] = NUL; |
2689 hash_init(&v_event->dv_hashtab); | 2703 hash_init(&v_event->dv_hashtab); |
2690 } | 2704 } |
2691 #endif | 2705 #endif |
2692 | 2706 |
2693 /* | 2707 /* |
2694 * Fires a ModeChanged autocmd | 2708 * Fires a ModeChanged autocmd event if appropriate. |
2695 */ | 2709 */ |
2696 void | 2710 void |
2697 trigger_modechanged() | 2711 may_trigger_modechanged() |
2698 { | 2712 { |
2699 #ifdef FEAT_EVAL | 2713 #ifdef FEAT_EVAL |
2700 dict_T *v_event; | 2714 dict_T *v_event; |
2701 typval_T rettv; | |
2702 typval_T tv[2]; | |
2703 char_u *pat_pre; | |
2704 char_u *pat; | |
2705 save_v_event_T save_v_event; | 2715 save_v_event_T save_v_event; |
2716 char_u curr_mode[MODE_MAX_LENGTH]; | |
2717 char_u pattern_buf[2 * MODE_MAX_LENGTH]; | |
2706 | 2718 |
2707 if (!has_modechanged()) | 2719 if (!has_modechanged()) |
2708 return; | 2720 return; |
2709 | 2721 |
2710 tv[0].v_type = VAR_NUMBER; | 2722 get_mode(curr_mode); |
2711 tv[0].vval.v_number = 1; // get full mode | 2723 if (STRCMP(curr_mode, last_mode) == 0) |
2712 tv[1].v_type = VAR_UNKNOWN; | |
2713 f_mode(tv, &rettv); | |
2714 if (STRCMP(rettv.vval.v_string, last_mode) == 0) | |
2715 { | |
2716 vim_free(rettv.vval.v_string); | |
2717 return; | 2724 return; |
2718 } | |
2719 | 2725 |
2720 v_event = get_v_event(&save_v_event); | 2726 v_event = get_v_event(&save_v_event); |
2721 (void)dict_add_string(v_event, "new_mode", rettv.vval.v_string); | 2727 (void)dict_add_string(v_event, "new_mode", curr_mode); |
2722 (void)dict_add_string(v_event, "old_mode", last_mode); | 2728 (void)dict_add_string(v_event, "old_mode", last_mode); |
2723 dict_set_items_ro(v_event); | 2729 dict_set_items_ro(v_event); |
2724 | 2730 |
2725 // concatenate modes in format "old_mode:new_mode" | 2731 // concatenate modes in format "old_mode:new_mode" |
2726 pat_pre = concat_str(last_mode, (char_u*)":"); | 2732 vim_snprintf((char *)pattern_buf, sizeof(pattern_buf), "%s:%s", last_mode, |
2727 pat = concat_str(pat_pre, rettv.vval.v_string); | 2733 curr_mode); |
2728 vim_free(pat_pre); | 2734 |
2729 | 2735 apply_autocmds(EVENT_MODECHANGED, pattern_buf, NULL, FALSE, curbuf); |
2730 apply_autocmds(EVENT_MODECHANGED, pat, NULL, FALSE, curbuf); | 2736 STRCPY(last_mode, curr_mode); |
2731 STRCPY(last_mode, rettv.vval.v_string); | 2737 |
2732 | |
2733 vim_free(pat); | |
2734 restore_v_event(v_event, &save_v_event); | 2738 restore_v_event(v_event, &save_v_event); |
2735 vim_free(rettv.vval.v_string); | 2739 #endif |
2736 #endif | 2740 } |
2737 } |