mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
Merge 29017852cf
into ae917dbd06
This commit is contained in:
commit
f7705dfbb5
@ -736,6 +736,26 @@ 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 after mappings
|
||||
matched against a string that indicates the
|
||||
have been applied. The pattern is matched
|
||||
current mode, which is the same as what is
|
||||
against a string that indicates the current
|
||||
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.
|
||||
typedchar The (actual) typed key since
|
||||
the last |KeyInputPre| call.
|
||||
Note: "typedchar" may be empty if successive
|
||||
|KeyInputPre| autocmds are processed.
|
||||
It is not allowed to change the text
|
||||
|textlock| or the current mode.
|
||||
*MenuPopup*
|
||||
MenuPopup Just before showing the popup menu (under the
|
||||
right mouse button). Useful for adjusting the
|
||||
|
@ -71,6 +71,7 @@ return {
|
||||
'InsertEnter', -- when entering Insert mode
|
||||
'InsertLeave', -- just after leaving Insert mode
|
||||
'InsertLeavePre', -- just before leaving Insert mode
|
||||
'KeyInputPre', -- just before a key is processed
|
||||
'LspAttach', -- after an LSP client attaches to a buffer
|
||||
'LspDetach', -- after an LSP client detaches from a buffer
|
||||
'LspRequest', -- after an LSP request is started, canceled, or completed
|
||||
|
@ -1713,6 +1713,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
|
||||
|| event == EVENT_DIRCHANGEDPRE
|
||||
|| event == EVENT_FILETYPE
|
||||
|| event == EVENT_FUNCUNDEFINED
|
||||
|| event == EVENT_KEYINPUTPRE
|
||||
|| event == EVENT_MENUPOPUP
|
||||
|| event == EVENT_MODECHANGED
|
||||
|| event == EVENT_OPTIONSET
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/ascii_defs.h"
|
||||
#include "nvim/autocmd.h"
|
||||
#include "nvim/buffer_defs.h"
|
||||
#include "nvim/charset.h"
|
||||
#include "nvim/cursor.h"
|
||||
@ -112,6 +113,9 @@ static size_t on_key_ignore_len = 0;
|
||||
|
||||
static int typeahead_char = 0; ///< typeahead char that's not flushed
|
||||
|
||||
static uint8_t typedchars[MAXMAPLEN + 1] = { NUL }; // typed chars before map
|
||||
static int typedchars_pos = 0;
|
||||
|
||||
/// When block_redo is true the redo buffer will not be changed.
|
||||
/// Used by edit() to repeat insertions.
|
||||
static bool block_redo = false;
|
||||
@ -1482,6 +1486,10 @@ static void updatescript(int c)
|
||||
(!!p_fs || idle)); // Always fsync at idle (CursorHold).
|
||||
count = 0;
|
||||
}
|
||||
if (typedchars_pos < MAXMAPLEN) {
|
||||
typedchars[typedchars_pos] = (uint8_t)c;
|
||||
typedchars_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge "modifiers" into "c_arg".
|
||||
@ -1561,6 +1569,74 @@ static void add_byte_to_showcmd(uint8_t byte)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the InsertCharPre autocommand.
|
||||
// "c" is the character that was typed.
|
||||
// Return new input character.
|
||||
static int do_key_input_pre(int c)
|
||||
{
|
||||
// Return quickly when there is nothing to do.
|
||||
if (!has_event(EVENT_KEYINPUTPRE)) {
|
||||
return c;
|
||||
}
|
||||
|
||||
uint8_t buf[MB_MAXBYTES + 1];
|
||||
char curr_mode[MODE_MAX_LENGTH];
|
||||
int save_State = State;
|
||||
save_v_event_T save_v_event;
|
||||
|
||||
if (IS_SPECIAL(c)) {
|
||||
buf[0] = K_SPECIAL;
|
||||
buf[1] = KEY2TERMCAP0(c);
|
||||
buf[2] = KEY2TERMCAP1(c);
|
||||
buf[3] = NUL;
|
||||
} else {
|
||||
buf[utf_char2bytes(c, (char *)buf)] = NUL;
|
||||
}
|
||||
|
||||
typedchars[typedchars_pos] = NUL;
|
||||
vim_unescape_ks((char *)typedchars);
|
||||
|
||||
get_mode(curr_mode);
|
||||
|
||||
// Lock the text to avoid weird things from happening.
|
||||
textlock++;
|
||||
set_vim_var_string(VV_CHAR, (char *)buf, -1); // set v:char
|
||||
|
||||
dict_T *v_event;
|
||||
v_event = get_v_event(&save_v_event);
|
||||
(void)tv_dict_add_bool(v_event, S_LEN("typed"), KeyTyped);
|
||||
(void)tv_dict_add_str(v_event, S_LEN("typedchar"), (char *)typedchars);
|
||||
|
||||
int res = c;
|
||||
|
||||
if (apply_autocmds(EVENT_KEYINPUTPRE, curr_mode, curr_mode, false, curbuf)
|
||||
&& strcmp((char *)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 *v_char;
|
||||
|
||||
v_char = get_vim_var_str(VV_CHAR);
|
||||
|
||||
// Convert special bytes when it is special string.
|
||||
if (strlen(v_char) >= 3 && IS_SPECIAL(v_char[0])) {
|
||||
res = TERMCAP2KEY(v_char[1], v_char[2]);
|
||||
} else if (strlen(v_char) > 0) {
|
||||
res = utf_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;
|
||||
}
|
||||
|
||||
/// Get the next input character.
|
||||
/// Can return a special key or a multi-byte character.
|
||||
/// Can return NUL when called recursively, use safe_vgetc() if that's not
|
||||
@ -1769,6 +1845,11 @@ int vgetc(void)
|
||||
kvi_destroy(on_key_buf);
|
||||
kvi_init(on_key_buf);
|
||||
|
||||
// Execute KeyInputPre callbacks.
|
||||
c = do_key_input_pre(c);
|
||||
// Clear the next typedchars_pos
|
||||
typedchars_pos = 0;
|
||||
|
||||
// Need to process the character before we know it's safe to do something
|
||||
// else.
|
||||
if (c != K_IGNORE) {
|
||||
|
@ -4152,4 +4152,83 @@ 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
|
||||
|
||||
" Test for v:event.typedchar
|
||||
nnoremap j k
|
||||
au KeyInputPre n
|
||||
\ call assert_equal(v:event.typedchar, 'j')
|
||||
\ | call assert_equal(v:char, 'k')
|
||||
call feedkeys('j', 'tx')
|
||||
|
||||
au! KeyInputPre
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
Loading…
Reference in New Issue
Block a user