vim-patch:9.1.0507: hard to detect cursor movement in the command line

Problem:  hard to detect cursor movement in the command line
Solution: Add the CursorMovedC autocommand
          (Shougo Matsushita)

closes: vim/vim#15040

d09521476f

Co-authored-by: Shougo Matsushita <Shougo.Matsu@gmail.com>
This commit is contained in:
zeertzjq
2024-06-21 06:29:13 +08:00
parent 26c2a56d99
commit 86ea42ce26
5 changed files with 70 additions and 19 deletions

View File

@@ -522,6 +522,13 @@ CursorMoved After the cursor was moved in Normal or Visual
Careful: This is triggered very often, don't Careful: This is triggered very often, don't
do anything that the user does not expect or do anything that the user does not expect or
that is slow. that is slow.
*CursorMovedC*
CursorMovedC After the cursor was moved in the command
line. Be careful not to mess up the
command line, it may cause Vim to lock up.
<afile> is set to a single character,
indicating the type of command-line.
|cmdwin-char|
*CursorMovedI* *CursorMovedI*
CursorMovedI After the cursor was moved in Insert mode. CursorMovedI After the cursor was moved in Insert mode.
Not triggered when the popup menu is visible. Not triggered when the popup menu is visible.

View File

@@ -36,6 +36,7 @@ return {
'CursorHold', -- cursor in same position for a while 'CursorHold', -- cursor in same position for a while
'CursorHoldI', -- idem, in Insert mode 'CursorHoldI', -- idem, in Insert mode
'CursorMoved', -- cursor was moved 'CursorMoved', -- cursor was moved
'CursorMovedC', -- cursor was moved in Cmdline mode
'CursorMovedI', -- cursor was moved in Insert mode 'CursorMovedI', -- cursor was moved in Insert mode
'DiagnosticChanged', -- diagnostics in a buffer were modified 'DiagnosticChanged', -- diagnostics in a buffer were modified
'DiffUpdated', -- diffs have been updated 'DiffUpdated', -- diffs have been updated

View File

@@ -1700,19 +1700,33 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
} else { } else {
sfname = xstrdup(fname); sfname = xstrdup(fname);
// Don't try expanding the following events. // Don't try expanding the following events.
if (event == EVENT_CMDLINECHANGED || event == EVENT_CMDLINEENTER if (event == EVENT_CMDLINECHANGED
|| event == EVENT_CMDLINELEAVE || event == EVENT_CMDUNDEFINED || event == EVENT_CMDLINEENTER
|| event == EVENT_CMDWINENTER || event == EVENT_CMDWINLEAVE || event == EVENT_CMDLINELEAVE
|| event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEMEPRE || event == EVENT_CMDUNDEFINED
|| event == EVENT_DIRCHANGED || event == EVENT_DIRCHANGEDPRE || event == EVENT_CURSORMOVEDC
|| event == EVENT_FILETYPE || event == EVENT_FUNCUNDEFINED || event == EVENT_CMDWINENTER
|| event == EVENT_MENUPOPUP || event == EVENT_MODECHANGED || event == EVENT_CMDWINLEAVE
|| event == EVENT_OPTIONSET || event == EVENT_QUICKFIXCMDPOST || event == EVENT_COLORSCHEME
|| event == EVENT_QUICKFIXCMDPRE || event == EVENT_REMOTEREPLY || event == EVENT_COLORSCHEMEPRE
|| event == EVENT_SIGNAL || event == EVENT_SPELLFILEMISSING || event == EVENT_DIRCHANGED
|| event == EVENT_SYNTAX || event == EVENT_TABCLOSED || event == EVENT_DIRCHANGEDPRE
|| event == EVENT_USER || event == EVENT_WINCLOSED || event == EVENT_FILETYPE
|| event == EVENT_WINRESIZED || event == EVENT_WINSCROLLED) { || event == EVENT_FUNCUNDEFINED
|| event == EVENT_MENUPOPUP
|| event == EVENT_MODECHANGED
|| event == EVENT_OPTIONSET
|| event == EVENT_QUICKFIXCMDPOST
|| event == EVENT_QUICKFIXCMDPRE
|| event == EVENT_REMOTEREPLY
|| event == EVENT_SIGNAL
|| event == EVENT_SPELLFILEMISSING
|| event == EVENT_SYNTAX
|| event == EVENT_TABCLOSED
|| event == EVENT_USER
|| event == EVENT_WINCLOSED
|| event == EVENT_WINRESIZED
|| event == EVENT_WINSCROLLED) {
fname = xstrdup(fname); fname = xstrdup(fname);
autocmd_fname_full = true; // don't expand it later autocmd_fname_full = true; // don't expand it later
} else { } else {

View File

@@ -134,6 +134,7 @@ typedef struct {
int wim_index; // index in wim_flags[] int wim_index; // index in wim_flags[]
int save_msg_scroll; int save_msg_scroll;
int save_State; // remember State when called int save_State; // remember State when called
int save_cmdspos;
char *save_p_icm; char *save_p_icm;
int some_key_typed; // one of the keys was typed int some_key_typed; // one of the keys was typed
// mouse drag and release events are ignored, unless they are // mouse drag and release events are ignored, unless they are
@@ -223,6 +224,12 @@ static int cmdpreview_ns = 0;
static const char e_active_window_or_buffer_changed_or_deleted[] static const char e_active_window_or_buffer_changed_or_deleted[]
= N_("E199: Active window or buffer changed or deleted"); = N_("E199: Active window or buffer changed or deleted");
static void trigger_cmd_autocmd(int typechar, event_T evt)
{
char typestr[2] = { (char)typechar, NUL };
apply_autocmds(evt, typestr, typestr, false, curbuf);
}
static void save_viewstate(win_T *wp, viewstate_T *vs) static void save_viewstate(win_T *wp, viewstate_T *vs)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
@@ -684,6 +691,7 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear
.indent = indent, .indent = indent,
.save_msg_scroll = msg_scroll, .save_msg_scroll = msg_scroll,
.save_State = State, .save_State = State,
.save_cmdspos = ccline.cmdspos,
.ignore_drag_release = true, .ignore_drag_release = true,
}; };
CommandLineState *s = &state; CommandLineState *s = &state;
@@ -2175,6 +2183,11 @@ static int command_line_handle_key(CommandLineState *s)
static int command_line_not_changed(CommandLineState *s) static int command_line_not_changed(CommandLineState *s)
{ {
// Trigger CursorMovedC autocommands.
if (ccline.cmdspos != s->save_cmdspos) {
trigger_cmd_autocmd(get_cmdline_type(), EVENT_CURSORMOVEDC);
}
// Incremental searches for "/" and "?": // Incremental searches for "/" and "?":
// Enter command_line_not_changed() when a character has been read but the // Enter command_line_not_changed() when a character has been read but the
// command line did not change. Then we only search and redraw if something // command line did not change. Then we only search and redraw if something
@@ -4177,6 +4190,10 @@ static int set_cmdline_pos(int pos)
} else { } else {
new_cmdpos = pos; new_cmdpos = pos;
} }
// Trigger CursorMovedC autocommands.
trigger_cmd_autocmd(get_cmdline_type(), EVENT_CURSORMOVEDC);
return 0; return 0;
} }
@@ -4303,7 +4320,6 @@ static int open_cmdwin(void)
win_T *old_curwin = curwin; win_T *old_curwin = curwin;
int i; int i;
garray_T winsizes; garray_T winsizes;
char typestr[2];
int save_restart_edit = restart_edit; int save_restart_edit = restart_edit;
int save_State = State; int save_State = State;
bool save_exmode = exmode_active; bool save_exmode = exmode_active;
@@ -4446,9 +4462,7 @@ static int open_cmdwin(void)
cmdwin_result = 0; cmdwin_result = 0;
// Trigger CmdwinEnter autocommands. // Trigger CmdwinEnter autocommands.
typestr[0] = (char)cmdwin_type; trigger_cmd_autocmd(cmdwin_type, EVENT_CMDWINENTER);
typestr[1] = NUL;
apply_autocmds(EVENT_CMDWINENTER, typestr, typestr, false, curbuf);
if (restart_edit != 0) { // autocmd with ":startinsert" if (restart_edit != 0) { // autocmd with ":startinsert"
stuffcharReadbuff(K_NOP); stuffcharReadbuff(K_NOP);
} }
@@ -4466,7 +4480,7 @@ static int open_cmdwin(void)
const bool save_KeyTyped = KeyTyped; const bool save_KeyTyped = KeyTyped;
// Trigger CmdwinLeave autocommands. // Trigger CmdwinLeave autocommands.
apply_autocmds(EVENT_CMDWINLEAVE, typestr, typestr, false, curbuf); trigger_cmd_autocmd(cmdwin_type, EVENT_CMDWINLEAVE);
// Restore KeyTyped in case it is modified by autocommands // Restore KeyTyped in case it is modified by autocommands
KeyTyped = save_KeyTyped; KeyTyped = save_KeyTyped;

View File

@@ -2010,6 +2010,21 @@ func Test_Cmdline()
au! CmdlineEnter au! CmdlineEnter
au! CmdlineLeave au! CmdlineLeave
let &shellslash = save_shellslash let &shellslash = save_shellslash
au! CursorMovedC : let g:pos = getcmdpos()
let g:pos = 0
call feedkeys(":hello\<Left>\<ESC>", 'xt')
call assert_equal(5, g:pos)
call feedkeys(":12345678\<C-R>=setcmdpos(3)\<CR>\<ESC>", 'xt')
call assert_equal(3, g:pos)
au! CursorMovedC
" CursorMovedC changes the cursor position.
au! CursorMovedC : let g:pos = getcmdpos() | call setcmdpos(getcmdpos()-1)
let g:pos = 0
call feedkeys(":hello\<Left>\<ESC>", 'xt')
call assert_equal(5, g:pos)
au! CursorMovedC
endfunc endfunc
" Test for BufWritePre autocommand that deletes or unloads the buffer. " Test for BufWritePre autocommand that deletes or unloads the buffer.