mirror of
https://github.com/vim/vim
synced 2025-07-16 01:01:58 +00:00
patch 9.1.0563: Cannot process any Key event
Problem: Cannot process any Key event Solution: Add the KeyInputPre autocmd (Shougo Matsushita) closes: #15182 Co-authored-by: zeertzjq <zeertzjq@outlook.com> Co-authored-by: K.Takata <kentkt@csc.jp> Signed-off-by: Shougo Matsushita <Shougo.Matsu@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
e7b98ab96e
commit
8367884909
@ -1,4 +1,4 @@
|
||||
*autocmd.txt* For Vim version 9.1. Last change: 2024 Jul 09
|
||||
*autocmd.txt* For Vim version 9.1. Last change: 2024 Jul 11
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -439,6 +439,8 @@ Name triggered by ~
|
||||
|CompleteDone| after Insert mode completion is done, after clearing
|
||||
info
|
||||
|
||||
|KeyInputPre| just before a key is processed
|
||||
|
||||
|User| to be used in combination with ":doautocmd"
|
||||
|SigUSR1| after the SIGUSR1 signal has been detected
|
||||
|
||||
@ -977,6 +979,21 @@ InsertLeavePre Just before leaving Insert mode. Also when
|
||||
*InsertLeave*
|
||||
InsertLeave Just after leaving Insert mode. Also when
|
||||
using CTRL-O |i_CTRL-O|. But not for |i_CTRL-C|.
|
||||
*KeyInputPre*
|
||||
KeyInputPre Just before a key is processed. The pattern is
|
||||
matched against a string that indicates the
|
||||
current mode, which is the same as what is
|
||||
returned by `mode(1)`.
|
||||
The |v:char| variable indicates the key typed
|
||||
and can be changed during the event to process
|
||||
a different key. When |v:char| is not a
|
||||
single character or a special key, the first
|
||||
character is used.
|
||||
The following values of |v:event| are set:
|
||||
typed The key is typed or not.
|
||||
It is not allowed to change the text
|
||||
|textlock| or the current mode.
|
||||
{only with the +eval feature}
|
||||
*MenuPopup*
|
||||
MenuPopup Just before showing the popup menu (under the
|
||||
right mouse button). Useful for adjusting the
|
||||
|
@ -1995,7 +1995,8 @@ v:beval_winid The |window-ID| of the window, over which the mouse pointer
|
||||
*v:char* *char-variable*
|
||||
v:char Argument for evaluating 'formatexpr' and used for the typed
|
||||
character when using <expr> in an abbreviation |:map-<expr>|.
|
||||
It is also used by the |InsertCharPre| and |InsertEnter| events.
|
||||
It is also used by the |InsertCharPre|, |InsertEnter| and
|
||||
|KeyInputPre| events.
|
||||
|
||||
*v:charconvert_from* *charconvert_from-variable*
|
||||
v:charconvert_from
|
||||
|
@ -5554,6 +5554,7 @@ Jobs eval.txt /*Jobs*
|
||||
K various.txt /*K*
|
||||
KDE gui_x11.txt /*KDE*
|
||||
KVim gui_x11.txt /*KVim*
|
||||
KeyInputPre autocmd.txt /*KeyInputPre*
|
||||
Kibaale uganda.txt /*Kibaale*
|
||||
Korean mbyte.txt /*Korean*
|
||||
L motion.txt /*L*
|
||||
|
@ -41607,6 +41607,7 @@ Functions: ~
|
||||
Autocommands: ~
|
||||
|
||||
|CursorMovedC| after the cursor was moved in the comamnd-line
|
||||
|KeyInputPre| process any Key event in any mode
|
||||
|SessionWritePost| after writing the session file |:mksession|
|
||||
|TermResponseAll| after the terminal response to |t_RV| and others is
|
||||
received
|
||||
|
@ -155,6 +155,7 @@ static keyvalue_T event_tab[] = {
|
||||
KEYVALUE_ENTRY(EVENT_INSERTENTER, "InsertEnter"),
|
||||
KEYVALUE_ENTRY(EVENT_INSERTLEAVE, "InsertLeave"),
|
||||
KEYVALUE_ENTRY(EVENT_INSERTLEAVEPRE, "InsertLeavePre"),
|
||||
KEYVALUE_ENTRY(EVENT_KEYINPUTPRE, "KeyInputPre"),
|
||||
KEYVALUE_ENTRY(EVENT_MENUPOPUP, "MenuPopup"),
|
||||
KEYVALUE_ENTRY(EVENT_MODECHANGED, "ModeChanged"),
|
||||
KEYVALUE_ENTRY(EVENT_OPTIONSET, "OptionSet"),
|
||||
@ -2021,6 +2022,15 @@ has_insertcharpre(void)
|
||||
return (first_autopat[(int)EVENT_INSERTCHARPRE] != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE when there is an KeyInputPre autocommand defined.
|
||||
*/
|
||||
int
|
||||
has_keyinputpre(void)
|
||||
{
|
||||
return (first_autopat[(int)EVENT_KEYINPUTPRE] != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE when there is an CmdUndefined autocommand defined.
|
||||
*/
|
||||
@ -2256,6 +2266,7 @@ apply_autocmds_group(
|
||||
|| event == EVENT_CMDWINLEAVE
|
||||
|| event == EVENT_CMDUNDEFINED
|
||||
|| event == EVENT_FUNCUNDEFINED
|
||||
|| event == EVENT_KEYINPUTPRE
|
||||
|| event == EVENT_REMOTEREPLY
|
||||
|| event == EVENT_SPELLFILEMISSING
|
||||
|| event == EVENT_QUICKFIXCMDPRE
|
||||
|
@ -96,6 +96,9 @@ static void closescript(void);
|
||||
static void updatescript(int c);
|
||||
static int vgetorpeek(int);
|
||||
static int inchar(char_u *buf, int maxlen, long wait_time);
|
||||
#ifdef FEAT_EVAL
|
||||
static int do_key_input_pre(int c);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Free and clear a buffer.
|
||||
@ -2130,6 +2133,10 @@ vgetc(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
c = do_key_input_pre(c);
|
||||
#endif
|
||||
|
||||
// Need to process the character before we know it's safe to do something
|
||||
// else.
|
||||
if (c != K_IGNORE)
|
||||
@ -2138,6 +2145,74 @@ vgetc(void)
|
||||
return c;
|
||||
}
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
/*
|
||||
* Handle the InsertCharPre autocommand.
|
||||
* "c" is the character that was typed.
|
||||
* Return new input character.
|
||||
*/
|
||||
static int
|
||||
do_key_input_pre(int c)
|
||||
{
|
||||
int res = c;
|
||||
char_u buf[MB_MAXBYTES + 1];
|
||||
char_u curr_mode[MODE_MAX_LENGTH];
|
||||
int save_State = State;
|
||||
save_v_event_T save_v_event;
|
||||
dict_T *v_event;
|
||||
|
||||
// Return quickly when there is nothing to do.
|
||||
if (!has_keyinputpre())
|
||||
return res;
|
||||
|
||||
if (IS_SPECIAL(c))
|
||||
{
|
||||
buf[0] = K_SPECIAL;
|
||||
buf[1] = KEY2TERMCAP0(c);
|
||||
buf[2] = KEY2TERMCAP1(c);
|
||||
buf[3] = NUL;
|
||||
}
|
||||
else
|
||||
buf[(*mb_char2bytes)(c, buf)] = NUL;
|
||||
|
||||
get_mode(curr_mode);
|
||||
|
||||
// Lock the text to avoid weird things from happening.
|
||||
++textlock;
|
||||
set_vim_var_string(VV_CHAR, buf, -1); // set v:char
|
||||
|
||||
v_event = get_v_event(&save_v_event);
|
||||
(void)dict_add_bool(v_event, "typed", KeyTyped);
|
||||
|
||||
if (apply_autocmds(EVENT_KEYINPUTPRE, curr_mode, curr_mode, FALSE, curbuf)
|
||||
&& STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0)
|
||||
{
|
||||
// Get the value of v:char. It may be empty or more than one
|
||||
// character. Only use it when changed, otherwise continue with the
|
||||
// original character.
|
||||
char_u *v_char;
|
||||
|
||||
v_char = get_vim_var_str(VV_CHAR);
|
||||
|
||||
// Convert special bytes when it is special string.
|
||||
if (STRLEN(v_char) >= 3 && v_char[0] == K_SPECIAL)
|
||||
res = TERMCAP2KEY(v_char[1], v_char[2]);
|
||||
else if (STRLEN(v_char) > 0)
|
||||
res = PTR2CHAR(v_char);
|
||||
}
|
||||
|
||||
restore_v_event(v_event, &save_v_event);
|
||||
|
||||
set_vim_var_string(VV_CHAR, NULL, -1); // clear v:char
|
||||
--textlock;
|
||||
|
||||
// Restore the State, it may have been changed.
|
||||
State = save_State;
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Like vgetc(), but never return a NUL when called recursively, get a key
|
||||
* directly from the user (ignoring typeahead).
|
||||
|
@ -26,6 +26,7 @@ int has_textchanged(void);
|
||||
int has_textchangedI(void);
|
||||
int has_textchangedP(void);
|
||||
int has_insertcharpre(void);
|
||||
int has_keyinputpre(void);
|
||||
int has_cmdundefined(void);
|
||||
int has_textyankpost(void);
|
||||
int has_completechanged(void);
|
||||
|
@ -4752,4 +4752,74 @@ func Test_BufEnter_botline()
|
||||
set hidden&vim
|
||||
endfunc
|
||||
|
||||
func Test_KeyInputPre()
|
||||
" Consume previous keys
|
||||
call feedkeys('', 'ntx')
|
||||
|
||||
" KeyInputPre can record input keys.
|
||||
let s:keys = []
|
||||
au KeyInputPre n call add(s:keys, v:char)
|
||||
|
||||
call feedkeys('jkjkjjj', 'ntx')
|
||||
call assert_equal(
|
||||
\ ['j', 'k', 'j', 'k', 'j', 'j', 'j'],
|
||||
\ s:keys)
|
||||
|
||||
unlet s:keys
|
||||
au! KeyInputPre
|
||||
|
||||
" KeyInputPre can handle multibyte.
|
||||
let s:keys = []
|
||||
au KeyInputPre * call add(s:keys, v:char)
|
||||
edit Xxx1
|
||||
|
||||
call feedkeys("iあ\<ESC>", 'ntx')
|
||||
call assert_equal(['i', "あ", "\<ESC>"], s:keys)
|
||||
|
||||
bwipe! Xxx1
|
||||
unlet s:keys
|
||||
au! KeyInputPre
|
||||
|
||||
" KeyInputPre can change input keys.
|
||||
au KeyInputPre i if v:char ==# 'a' | let v:char = 'b' | endif
|
||||
edit Xxx1
|
||||
|
||||
call feedkeys("iaabb\<ESC>", 'ntx')
|
||||
call assert_equal(getline('.'), 'bbbb')
|
||||
|
||||
bwipe! Xxx1
|
||||
au! KeyInputPre
|
||||
|
||||
" KeyInputPre returns multiple characters.
|
||||
au KeyInputPre i if v:char ==# 'a' | let v:char = 'cccc' | endif
|
||||
edit Xxx1
|
||||
|
||||
call feedkeys("iaabb\<ESC>", 'ntx')
|
||||
call assert_equal(getline('.'), 'ccbb')
|
||||
|
||||
bwipe! Xxx1
|
||||
au! KeyInputPre
|
||||
|
||||
" KeyInputPre can use special keys.
|
||||
au KeyInputPre i if v:char ==# 'a' | let v:char = "\<Ignore>" | endif
|
||||
edit Xxx1
|
||||
|
||||
call feedkeys("iaabb\<ESC>", 'ntx')
|
||||
call assert_equal(getline('.'), 'bb')
|
||||
|
||||
bwipe! Xxx1
|
||||
au! KeyInputPre
|
||||
|
||||
" Test for v:event.typed
|
||||
au KeyInputPre n call assert_true(v:event.typed)
|
||||
call feedkeys('j', 'ntx')
|
||||
|
||||
au! KeyInputPre
|
||||
|
||||
au KeyInputPre n call assert_false(v:event.typed)
|
||||
call feedkeys('j', 'nx')
|
||||
|
||||
au! KeyInputPre
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
563,
|
||||
/**/
|
||||
562,
|
||||
/**/
|
||||
|
@ -1397,6 +1397,7 @@ enum auto_event
|
||||
EVENT_INSERTENTER, // when entering Insert mode
|
||||
EVENT_INSERTLEAVEPRE, // just before leaving Insert mode
|
||||
EVENT_INSERTLEAVE, // just after leaving Insert mode
|
||||
EVENT_KEYINPUTPRE, // before key input
|
||||
EVENT_MENUPOPUP, // just before popup menu is displayed
|
||||
EVENT_MODECHANGED, // after changing the mode
|
||||
EVENT_OPTIONSET, // option was set
|
||||
|
Reference in New Issue
Block a user