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 }