To: vim_dev@googlegroups.com Subject: Patch 8.2.3555 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3555 Problem: ModeChanged is not triggered on every mode change. Solution: Also trigger on minor mode changes. (Maguns Gross, closes #8999) Files: runtime/doc/autocmd.txt, src/autocmd.c, src/insexpand.c, src/misc1.c, src/normal.c, src/terminal.c, src/testdir/test_edit.vim *** ../vim-8.2.3554/runtime/doc/autocmd.txt 2021-09-12 12:39:04.319467418 +0100 --- runtime/doc/autocmd.txt 2021-10-22 18:49:38.117786968 +0100 *************** *** 927,944 **** *ModeChanged* ModeChanged After changing the mode. The pattern is matched against `'old_mode:new_mode'`, for ! example match against `i:*` to simulate ! |InsertLeave|. The following values of |v:event| are set: old_mode The mode before it changed. new_mode The new mode as also returned ! by |mode()|. When ModeChanged is triggered, old_mode will have the value of new_mode when the event was last triggered. Usage example to use relative line numbers ! when entering visual mode: > ! :autocmd ModeChanged *:v set relativenumber < *OptionSet* OptionSet After setting an option. The pattern is matched against the long option name. --- 930,952 ---- *ModeChanged* ModeChanged After changing the mode. The pattern is matched against `'old_mode:new_mode'`, for ! example match against `*:c*` to simulate ! |CmdlineEnter|. The following values of |v:event| are set: old_mode The mode before it changed. new_mode The new mode as also returned ! by |mode()| called with a ! non-zero argument. When ModeChanged is triggered, old_mode will have the value of new_mode when the event was last triggered. + This will be triggered on every minor mode + change. Usage example to use relative line numbers ! when entering Visual mode: > ! :au ModeChanged [vV\x16]*:* let &l:rnu = mode() =~# '^[vV\x16]' ! :au ModeChanged *:[vV\x16]* let &l:rnu = mode() =~# '^[vV\x16]' ! :au WinEnter,WinLeave * let &l:rnu = mode() =~# '^[vV\x16]' < *OptionSet* OptionSet After setting an option. The pattern is matched against the long option name. *** ../vim-8.2.3554/src/autocmd.c 2021-10-02 11:23:01.566500862 +0100 --- src/autocmd.c 2021-10-22 18:51:58.903728134 +0100 *************** *** 1218,1223 **** --- 1218,1240 ---- return FAIL; } + #ifdef FEAT_EVAL + // 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); + } + #endif + if (is_buflocal) { ap->buflocal_nr = buflocal_nr; *** ../vim-8.2.3554/src/insexpand.c 2021-10-17 14:13:04.836665895 +0100 --- src/insexpand.c 2021-10-22 18:49:38.117786968 +0100 *************** *** 243,248 **** --- 243,250 ---- // CTRL-X in CTRL-X CTRL-V mode behaves differently to make CTRL-X // CTRL-V look like CTRL-N ctrl_x_mode = CTRL_X_CMDLINE_CTRL_X; + + trigger_modechanged(); } /* *************** *** 2150,2155 **** --- 2152,2159 ---- // upon the (possibly failed) completion. ins_apply_autocmds(EVENT_COMPLETEDONE); + trigger_modechanged(); + // reset continue_* if we left expansion-mode, if we stay they'll be // (re)set properly in ins_complete() if (!vim_is_ctrl_x_key(c)) *************** *** 2487,2492 **** --- 2491,2497 ---- // Lazily show the popup menu, unless we got interrupted. if (!compl_interrupted) show_pum(save_w_wrow, save_w_leftcol); + trigger_modechanged(); out_flush(); } *************** *** 3255,3260 **** --- 3260,3267 ---- if (compl_curr_match == NULL) compl_curr_match = compl_old_match; } + trigger_modechanged(); + return i; } *** ../vim-8.2.3554/src/misc1.c 2021-10-21 18:01:10.101023157 +0100 --- src/misc1.c 2021-10-22 18:53:08.824685050 +0100 *************** *** 2670,2681 **** if (!has_modechanged()) return; - v_event = get_vim_var_dict(VV_EVENT); - 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); (void)dict_add_string(v_event, "new_mode", rettv.vval.v_string); (void)dict_add_string(v_event, "old_mode", last_mode); dict_set_items_ro(v_event); --- 2670,2686 ---- 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); + return; + } + + v_event = get_vim_var_dict(VV_EVENT); (void)dict_add_string(v_event, "new_mode", rettv.vval.v_string); (void)dict_add_string(v_event, "old_mode", last_mode); dict_set_items_ro(v_event); *************** *** 2688,2696 **** apply_autocmds(EVENT_MODECHANGED, pat, NULL, FALSE, curbuf); STRCPY(last_mode, rettv.vval.v_string); - vim_free(rettv.vval.v_string); vim_free(pat); dict_free_contents(v_event); hash_init(&v_event->dv_hashtab); #endif } --- 2693,2701 ---- apply_autocmds(EVENT_MODECHANGED, pat, NULL, FALSE, curbuf); STRCPY(last_mode, rettv.vval.v_string); vim_free(pat); dict_free_contents(v_event); hash_init(&v_event->dv_hashtab); + vim_free(rettv.vval.v_string); #endif } *** ../vim-8.2.3554/src/normal.c 2021-10-17 17:20:20.399745698 +0100 --- src/normal.c 2021-10-22 18:49:38.121787024 +0100 *************** *** 527,532 **** --- 527,533 ---- # endif } #endif + trigger_modechanged(); // When not finishing an operator and no register name typed, reset the // count. *************** *** 1221,1226 **** --- 1222,1228 ---- c = finish_op; #endif finish_op = FALSE; + trigger_modechanged(); #ifdef CURSOR_SHAPE // Redraw the cursor with another shape, if we were in Operator-pending // mode or did a replace command. *************** *** 1278,1283 **** --- 1280,1286 ---- if (restart_VIsual_select == 1) { VIsual_select = TRUE; + trigger_modechanged(); showmode(); restart_VIsual_select = 0; } *************** *** 1386,1392 **** #endif VIsual_active = FALSE; - trigger_modechanged(); setmouse(); mouse_dragging = 0; --- 1389,1394 ---- *************** *** 1403,1408 **** --- 1405,1411 ---- may_clear_cmdline(); adjust_cursor_eol(); + trigger_modechanged(); } /* *************** *** 3439,3444 **** --- 3442,3448 ---- if (VIsual_active) // toggle Selection/Visual mode { VIsual_select = !VIsual_select; + trigger_modechanged(); showmode(); } else if (!checkclearop(cap->oap)) *************** *** 3501,3506 **** --- 3505,3511 ---- if (VIsual_active && VIsual_select) { VIsual_select = FALSE; + trigger_modechanged(); showmode(); restart_VIsual_select = 2; // restart Select mode later } *** ../vim-8.2.3554/src/terminal.c 2021-10-17 17:20:20.399745698 +0100 --- src/terminal.c 2021-10-22 18:49:38.121787024 +0100 *************** *** 1995,2000 **** --- 1995,2001 ---- set_terminal_mode(term_T *term, int normal_mode) { term->tl_normal_mode = normal_mode; + trigger_modechanged(); if (!normal_mode) handle_postponed_scrollback(term); VIM_CLEAR(term->tl_status_text); *** ../vim-8.2.3554/src/testdir/test_edit.vim 2021-10-17 14:13:04.836665895 +0100 --- src/testdir/test_edit.vim 2021-10-22 18:49:38.121787024 +0100 *************** *** 1959,1970 **** " Test for ModeChanged pattern func Test_mode_changes() - let g:count = 0 - func! DoIt() - let g:count += 1 - endfunc let g:index = 0 ! let g:mode_seq = ['n', 'i', 'n', 'v', 'V', 'n', 'V', 'v', 'n'] func! TestMode() call assert_equal(g:mode_seq[g:index], get(v:event, "old_mode")) call assert_equal(g:mode_seq[g:index + 1], get(v:event, "new_mode")) --- 1959,1966 ---- " Test for ModeChanged pattern func Test_mode_changes() let g:index = 0 ! let g:mode_seq = ['n', 'i', 'n', 'v', 'V', 'i', 'ix', 'i', 'ic', 'i', 'n', 'no', 'n', 'V', 'v', 's', 'n'] func! TestMode() call assert_equal(g:mode_seq[g:index], get(v:event, "old_mode")) call assert_equal(g:mode_seq[g:index + 1], get(v:event, "new_mode")) *************** *** 1973,1985 **** endfunc au ModeChanged * :call TestMode() ! au ModeChanged n:* :call DoIt() ! call feedkeys("i\vV\", 'tnix') ! call assert_equal(2, g:count) ! ! au ModeChanged V:v :call DoIt() ! call feedkeys("Vv\", 'tnix') ! call assert_equal(4, g:count) call assert_equal(len(g:mode_seq) - 1, g:index) let g:n_to_i = 0 --- 1969,1983 ---- endfunc au ModeChanged * :call TestMode() ! let g:n_to_any = 0 ! au ModeChanged n:* let g:n_to_any += 1 ! call feedkeys("i\vVca\\\\ggdG", 'tnix') ! ! let g:V_to_v = 0 ! au ModeChanged V:v let g:V_to_v += 1 ! call feedkeys("Vv\\", 'tnix') ! call assert_equal(len(filter(g:mode_seq[1:], {idx, val -> val == 'n'})), g:n_to_any) ! call assert_equal(1, g:V_to_v) call assert_equal(len(g:mode_seq) - 1, g:index) let g:n_to_i = 0 *************** *** 2008,2019 **** call assert_equal(2, g:i_to_any) call assert_equal(3, g:nori_to_any) au! ModeChanged delfunc TestMode unlet! g:mode_seq unlet! g:index ! delfunc DoIt ! unlet! g:count endfunc " vim: shiftwidth=2 sts=2 expandtab --- 2006,2037 ---- call assert_equal(2, g:i_to_any) call assert_equal(3, g:nori_to_any) + if has('terminal') + let g:mode_seq += ['c', 'n', 't', 'nt', 'c', 'nt', 'n'] + call feedkeys(":term\\N:bd!\", 'tnix') + call assert_equal(len(g:mode_seq) - 1, g:index) + call assert_equal(1, g:n_to_i) + call assert_equal(1, g:n_to_niI) + call assert_equal(1, g:niI_to_i) + call assert_equal(2, g:nany_to_i) + call assert_equal(1, g:i_to_n) + call assert_equal(2, g:i_to_any) + call assert_equal(5, g:nori_to_any) + endif + au! ModeChanged delfunc TestMode unlet! g:mode_seq unlet! g:index ! unlet! g:n_to_any ! unlet! g:V_to_v ! unlet! g:n_to_i ! unlet! g:n_to_niI ! unlet! g:niI_to_i ! unlet! g:nany_to_i ! unlet! g:i_to_n ! unlet! g:nori_to_any ! unlet! g:i_to_any endfunc " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.3554/src/version.c 2021-10-22 15:55:27.782135449 +0100 --- src/version.c 2021-10-22 18:51:32.783369530 +0100 *************** *** 759,760 **** --- 759,762 ---- { /* Add new patch number below this line */ + /**/ + 3555, /**/ -- If evolution theories are correct, humans will soon grow a third hand for operating the mouse. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///