mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #17932 from zeertzjq/vim-8.1.2145
vim-patch:8.1.{2145,2159,2165,2167,2333,2346,2350},8.2.{0839,0851,0855,0867,0916,0919,2084,2728,3595,4504,4819,4824,4827,4828,4829,4833,4837}
This commit is contained in:
commit
35a7b0f9b9
@ -67,12 +67,19 @@ CTRL-V Insert next non-digit literally. Up to three digits form the
|
||||
decimal value of a single byte. The non-digit and the three
|
||||
digits are not considered for mapping. This works the same
|
||||
way as in Insert mode (see above, |i_CTRL-V|).
|
||||
For special keys, the CTRL modifier may be included into the
|
||||
key to produce a control character. If there is no control
|
||||
character for the key then its |key-notation| is inserted.
|
||||
Note: Under Windows CTRL-V is often mapped to paste text.
|
||||
Use CTRL-Q instead then.
|
||||
*c_CTRL-Q*
|
||||
CTRL-Q Same as CTRL-V. But with some terminals it is used for
|
||||
control flow, it doesn't work then.
|
||||
|
||||
CTRL-SHIFT-V *c_CTRL-SHIFT-V* *c_CTRL-SHIFT-Q*
|
||||
CTRL-SHIFT-Q Works just like CTRL-V, but do not try to include the CTRL
|
||||
modifier into the key.
|
||||
|
||||
*c_<Left>* *c_Left*
|
||||
<Left> cursor left
|
||||
*c_<Right>* *c_Right*
|
||||
|
@ -1325,6 +1325,9 @@ A string constant accepts these special characters:
|
||||
To use the double quote character it must be escaped: "<M-\">".
|
||||
Don't use <Char-xxxx> to get a UTF-8 character, use \uxxxx as
|
||||
mentioned above.
|
||||
\<*xxx> Like \<xxx> but prepends a modifier instead of including it in the
|
||||
character. E.g. "\<C-w>" is one character 0x17 while "\<*C-w>" is four
|
||||
bytes: 3 for the CTRL modifier and then character "W".
|
||||
|
||||
Note that "\xff" is stored as the byte 255, which may be invalid in some
|
||||
encodings. Use "\u00ff" to store character 255 correctly as UTF-8.
|
||||
|
@ -192,12 +192,14 @@ CTRL-D Delete one shiftwidth of indent at the start of the current
|
||||
label.
|
||||
|
||||
*i_CTRL-V*
|
||||
CTRL-V Insert next non-digit literally. For special keys, the
|
||||
terminal code is inserted. It's also possible to enter the
|
||||
decimal, octal or hexadecimal value of a character
|
||||
CTRL-V Insert next non-digit literally. It's also possible to enter
|
||||
the decimal, octal or hexadecimal value of a character
|
||||
|i_CTRL-V_digit|.
|
||||
The characters typed right after CTRL-V are not considered for
|
||||
mapping.
|
||||
For special keys, the CTRL modifier may be included into the
|
||||
key to produce a control character. If there is no control
|
||||
character for the key then its |key-notation| is inserted.
|
||||
Note: When CTRL-V is mapped (e.g., to paste text) you can
|
||||
often use CTRL-Q instead |i_CTRL-Q|.
|
||||
|
||||
@ -206,6 +208,10 @@ CTRL-Q Same as CTRL-V.
|
||||
Note: Some terminal connections may eat CTRL-Q, it doesn't
|
||||
work then. It does work in the GUI.
|
||||
|
||||
CTRL-SHIFT-V *i_CTRL-SHIFT-V* *i_CTRL-SHIFT-Q*
|
||||
CTRL-SHIFT-Q Works just like CTRL-V, but do not try to include the CTRL
|
||||
modifier into the key.
|
||||
|
||||
CTRL-X Enter CTRL-X mode. This is a sub-mode where commands can
|
||||
be given to complete words or scroll the window. See
|
||||
|i_CTRL-X| and |ins-completion|.
|
||||
|
@ -4483,8 +4483,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
Note that typing <F10> in paste mode inserts "<F10>", since in paste
|
||||
mode everything is inserted literally, except the 'pastetoggle' key
|
||||
sequence.
|
||||
No timeout is used, this means that a multi-key 'pastetoggle' can not
|
||||
be triggered manually.
|
||||
When the value has several bytes 'ttimeoutlen' applies.
|
||||
|
||||
*'pex'* *'patchexpr'*
|
||||
'patchexpr' 'pex' string (default "")
|
||||
|
@ -365,6 +365,10 @@ Macro/|recording| behavior
|
||||
macros and 'keymap' at the same time. This also means you can use |:imap| on
|
||||
the results of keys from 'keymap'.
|
||||
|
||||
Mappings:
|
||||
Creating a mapping for a simplifiable key (e.g. <C-I>) doesn't replace an
|
||||
existing mapping for its simplified form (e.g. <Tab>).
|
||||
|
||||
Motion:
|
||||
The |jumplist| avoids useless/phantom jumps.
|
||||
|
||||
|
@ -632,7 +632,7 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod
|
||||
} else {
|
||||
parsed_args.desc = NULL;
|
||||
}
|
||||
if (parsed_args.lhs_len > MAXMAPLEN) {
|
||||
if (parsed_args.lhs_len > MAXMAPLEN || parsed_args.alt_lhs_len > MAXMAPLEN) {
|
||||
api_set_error(err, kErrorTypeValidation, "LHS exceeds maximum map length: %s", lhs.data);
|
||||
goto fail_and_free;
|
||||
}
|
||||
@ -1128,6 +1128,9 @@ ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, bool from_lua)
|
||||
for (const mapblock_T *current_maphash = get_maphash(i, buf);
|
||||
current_maphash;
|
||||
current_maphash = current_maphash->m_next) {
|
||||
if (current_maphash->m_simplified) {
|
||||
continue;
|
||||
}
|
||||
// Check for correct mode
|
||||
if (int_mode & current_maphash->m_mode) {
|
||||
mapblock_fill_dict(dict, current_maphash, buffer_value, false);
|
||||
|
@ -403,9 +403,19 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Bool
|
||||
return (String) { .data = NULL, .size = 0 };
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
if (from_part) {
|
||||
flags |= REPTERM_FROM_PART;
|
||||
}
|
||||
if (do_lt) {
|
||||
flags |= REPTERM_DO_LT;
|
||||
}
|
||||
if (!special) {
|
||||
flags |= REPTERM_NO_SPECIAL;
|
||||
}
|
||||
|
||||
char *ptr = NULL;
|
||||
replace_termcodes((char_u *)str.data, str.size, (char_u **)&ptr,
|
||||
from_part, do_lt, special, CPO_TO_CPO_FLAGS);
|
||||
replace_termcodes((char_u *)str.data, str.size, (char_u **)&ptr, flags, NULL, CPO_TO_CPO_FLAGS);
|
||||
return cstr_as_string(ptr);
|
||||
}
|
||||
|
||||
|
@ -356,6 +356,8 @@ struct mapblock {
|
||||
LuaRef m_luaref; // lua function reference as rhs
|
||||
int m_keylen; // strlen(m_keys)
|
||||
int m_mode; // valid mode
|
||||
int m_simplified; // m_keys was simplified, do no use this map
|
||||
// if keys are typed
|
||||
int m_noremap; // if non-zero no re-mapping for m_str
|
||||
char m_silent; // <silent> used, don't echo commands
|
||||
char m_nowait; // <nowait> used
|
||||
|
@ -1513,8 +1513,10 @@ char_u *get_digraph_for_char(int val_arg)
|
||||
int get_digraph(bool cmdline)
|
||||
{
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
int c = plain_vgetc();
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
|
||||
if (c != ESC) {
|
||||
// ESC cancels CTRL-K
|
||||
@ -1531,8 +1533,10 @@ int get_digraph(bool cmdline)
|
||||
add_to_showcmd(c);
|
||||
}
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
int cc = plain_vgetc();
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
|
||||
if (cc != ESC) {
|
||||
// ESC cancels CTRL-K
|
||||
|
@ -762,8 +762,10 @@ static int insert_execute(VimState *state, int key)
|
||||
// may need to redraw when no more chars available now
|
||||
ins_redraw(false);
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
s->c = plain_vgetc();
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
if (s->c != Ctrl_N && s->c != Ctrl_G && s->c != Ctrl_O) {
|
||||
// it's something else
|
||||
vungetc(s->c);
|
||||
@ -1587,7 +1589,8 @@ static void ins_ctrl_v(void)
|
||||
|
||||
add_to_showcmd_c(Ctrl_V);
|
||||
|
||||
c = get_literal();
|
||||
// Do not include modifiers into the key for CTRL-SHIFT-V.
|
||||
c = get_literal(mod_mask & MOD_MASK_SHIFT);
|
||||
if (did_putchar) {
|
||||
// when the line fits in 'columns' the '^' is at the start of the next
|
||||
// line and will not removed by the redraw
|
||||
@ -5612,13 +5615,13 @@ static unsigned quote_meta(char_u *dest, char_u *src, int len)
|
||||
return m;
|
||||
}
|
||||
|
||||
/*
|
||||
* Next character is interpreted literally.
|
||||
* A one, two or three digit decimal number is interpreted as its byte value.
|
||||
* If one or two digits are entered, the next character is given to vungetc().
|
||||
* For Unicode a character > 255 may be returned.
|
||||
*/
|
||||
int get_literal(void)
|
||||
/// Next character is interpreted literally.
|
||||
/// A one, two or three digit decimal number is interpreted as its byte value.
|
||||
/// If one or two digits are entered, the next character is given to vungetc().
|
||||
/// For Unicode a character > 255 may be returned.
|
||||
///
|
||||
/// @param no_simplify do not include modifiers into the key
|
||||
int get_literal(bool no_simplify)
|
||||
{
|
||||
int cc;
|
||||
int nc;
|
||||
@ -5636,6 +5639,9 @@ int get_literal(void)
|
||||
i = 0;
|
||||
for (;;) {
|
||||
nc = plain_vgetc();
|
||||
if (!no_simplify) {
|
||||
nc = merge_modifiers(nc, &mod_mask);
|
||||
}
|
||||
if ((mod_mask & ~MOD_MASK_SHIFT) != 0) {
|
||||
// A character with non-Shift modifiers should not be a valid
|
||||
// character for i_CTRL-V_digit.
|
||||
@ -7811,11 +7817,10 @@ static void ins_reg(void)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Don't map the register name. This also prevents the mode message to be
|
||||
* deleted when ESC is hit.
|
||||
*/
|
||||
++no_mapping;
|
||||
// Don't map the register name. This also prevents the mode message to be
|
||||
// deleted when ESC is hit.
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
regname = plain_vgetc();
|
||||
LANGMAP_ADJUST(regname, TRUE);
|
||||
if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P) {
|
||||
@ -7825,7 +7830,8 @@ static void ins_reg(void)
|
||||
regname = plain_vgetc();
|
||||
LANGMAP_ADJUST(regname, TRUE);
|
||||
}
|
||||
--no_mapping;
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
|
||||
// Don't call u_sync() while typing the expression or giving an error
|
||||
// message for it. Only call it explicitly.
|
||||
@ -7893,13 +7899,13 @@ static void ins_ctrl_g(void)
|
||||
// Right after CTRL-X the cursor will be after the ruler.
|
||||
setcursor();
|
||||
|
||||
/*
|
||||
* Don't map the second key. This also prevents the mode message to be
|
||||
* deleted when ESC is hit.
|
||||
*/
|
||||
++no_mapping;
|
||||
// Don't map the second key. This also prevents the mode message to be
|
||||
// deleted when ESC is hit.
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
c = plain_vgetc();
|
||||
--no_mapping;
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
switch (c) {
|
||||
// CTRL-G k and CTRL-G <Up>: cursor up to Insstart.col
|
||||
case K_UP:
|
||||
@ -9233,8 +9239,10 @@ static int ins_digraph(void)
|
||||
// don't map the digraph chars. This also prevents the
|
||||
// mode message to be deleted when ESC is hit
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
c = plain_vgetc();
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
if (did_putchar) {
|
||||
// when the line fits in 'columns' the '?' is at the start of the next
|
||||
// line and will not be removed by the redraw
|
||||
@ -9260,8 +9268,10 @@ static int ins_digraph(void)
|
||||
add_to_showcmd_c(c);
|
||||
}
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
cc = plain_vgetc();
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
if (did_putchar) {
|
||||
// when the line fits in 'columns' the '?' is at the start of the
|
||||
// next line and will not be removed by a redraw
|
||||
|
@ -4964,8 +4964,13 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
|
||||
break;
|
||||
|
||||
// Special key, e.g.: "\<C-W>"
|
||||
case '<':
|
||||
extra = trans_special((const char_u **)&p, STRLEN(p), name, true, true);
|
||||
case '<': {
|
||||
int flags = FSK_KEYCODE | FSK_IN_STRING;
|
||||
|
||||
if (p[1] != '*') {
|
||||
flags |= FSK_SIMPLIFY;
|
||||
}
|
||||
extra = trans_special((const char_u **)&p, STRLEN(p), name, flags, NULL);
|
||||
if (extra != 0) {
|
||||
name += extra;
|
||||
if (name >= rettv->vval.v_string + len) {
|
||||
@ -4973,6 +4978,7 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
FALLTHROUGH;
|
||||
|
||||
default:
|
||||
|
@ -2975,6 +2975,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
|
||||
bool error = false;
|
||||
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
for (;;) {
|
||||
// Position the cursor. Needed after a message that ends in a space,
|
||||
// or if event processing caused a redraw.
|
||||
@ -3012,6 +3013,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
|
||||
break;
|
||||
}
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
|
||||
set_vim_var_nr(VV_MOUSE_WIN, 0);
|
||||
set_vim_var_nr(VV_MOUSE_WINID, 0);
|
||||
@ -5648,6 +5650,8 @@ static void f_localtime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
|
||||
{
|
||||
char_u *keys_buf = NULL;
|
||||
char_u *alt_keys_buf = NULL;
|
||||
bool did_simplify = false;
|
||||
char_u *rhs;
|
||||
LuaRef rhs_lua;
|
||||
int mode;
|
||||
@ -5655,6 +5659,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
|
||||
int get_dict = FALSE;
|
||||
mapblock_T *mp;
|
||||
int buffer_local;
|
||||
int flags = REPTERM_FROM_PART | REPTERM_DO_LT;
|
||||
|
||||
// Return empty string for failure.
|
||||
rettv->v_type = VAR_STRING;
|
||||
@ -5684,10 +5689,16 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
|
||||
|
||||
mode = get_map_mode((char_u **)&which, 0);
|
||||
|
||||
keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, true,
|
||||
CPO_TO_CPO_FLAGS);
|
||||
rhs = check_map(keys, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua);
|
||||
xfree(keys_buf);
|
||||
char_u *keys_simplified
|
||||
= replace_termcodes(keys, STRLEN(keys), &keys_buf, flags, &did_simplify, CPO_TO_CPO_FLAGS);
|
||||
rhs = check_map(keys_simplified, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua);
|
||||
if (did_simplify) {
|
||||
// When the lhs is being simplified the not-simplified keys are
|
||||
// preferred for printing, like in do_map().
|
||||
(void)replace_termcodes(keys, STRLEN(keys), &alt_keys_buf, flags | REPTERM_NO_SIMPLIFY, NULL,
|
||||
CPO_TO_CPO_FLAGS);
|
||||
rhs = check_map(alt_keys_buf, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua);
|
||||
}
|
||||
|
||||
if (!get_dict) {
|
||||
// Return a string.
|
||||
@ -5710,6 +5721,9 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
|
||||
mapblock_fill_dict(rettv->vval.v_dict, mp, buffer_local, true);
|
||||
}
|
||||
}
|
||||
|
||||
xfree(keys_buf);
|
||||
xfree(alt_keys_buf);
|
||||
}
|
||||
|
||||
/// luaeval() function implementation
|
||||
|
@ -3951,8 +3951,10 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
|
||||
RedrawingDisabled = temp;
|
||||
|
||||
no_mapping++; // don't map this key
|
||||
allow_keys++; // allow special keys
|
||||
typed = plain_vgetc();
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
|
||||
// clear the question
|
||||
msg_didout = false; // don't scroll up
|
||||
|
@ -5180,8 +5180,7 @@ int uc_add_command(char_u *name, size_t name_len, char_u *rep, uint32_t argt, lo
|
||||
char_u *rep_buf = NULL;
|
||||
garray_T *gap;
|
||||
|
||||
replace_termcodes(rep, STRLEN(rep), &rep_buf, false, false, true,
|
||||
CPO_TO_CPO_FLAGS);
|
||||
replace_termcodes(rep, STRLEN(rep), &rep_buf, 0, NULL, CPO_TO_CPO_FLAGS);
|
||||
if (rep_buf == NULL) {
|
||||
// Can't replace termcodes - try using the string as is
|
||||
rep_buf = vim_strsave(rep);
|
||||
|
@ -1335,8 +1335,10 @@ static int command_line_execute(VimState *state, int key)
|
||||
// mode when 'insertmode' is set, CTRL-\ e prompts for an expression.
|
||||
if (s->c == Ctrl_BSL) {
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
s->c = plain_vgetc();
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
// CTRL-\ e doesn't work when obtaining an expression, unless it
|
||||
// is in a mapping.
|
||||
if (s->c != Ctrl_N
|
||||
@ -1889,6 +1891,7 @@ static int command_line_handle_key(CommandLineState *s)
|
||||
case Ctrl_R: { // insert register
|
||||
putcmdline('"', true);
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
int i = s->c = plain_vgetc(); // CTRL-R <char>
|
||||
if (i == Ctrl_O) {
|
||||
i = Ctrl_R; // CTRL-R CTRL-O == CTRL-R CTRL-R
|
||||
@ -1897,7 +1900,8 @@ static int command_line_handle_key(CommandLineState *s)
|
||||
if (i == Ctrl_R) {
|
||||
s->c = plain_vgetc(); // CTRL-R CTRL-R <char>
|
||||
}
|
||||
--no_mapping;
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
// Insert the result of an expression.
|
||||
// Need to save the current command line, to be able to enter
|
||||
// a new one...
|
||||
@ -2208,7 +2212,11 @@ static int command_line_handle_key(CommandLineState *s)
|
||||
case Ctrl_Q:
|
||||
s->ignore_drag_release = true;
|
||||
putcmdline('^', true);
|
||||
s->c = get_literal(); // get next (two) character(s)
|
||||
|
||||
// Get next (two) characters.
|
||||
// Do not include modifiers into the key for CTRL-SHIFT-V.
|
||||
s->c = get_literal(mod_mask & MOD_MASK_SHIFT);
|
||||
|
||||
s->do_abbr = false; // don't do abbreviation now
|
||||
ccline.special_char = NUL;
|
||||
// may need to remove ^ when composing char was typed
|
||||
|
@ -872,10 +872,8 @@ void init_default_mappings(void)
|
||||
int ins_typebuf(char_u *str, int noremap, int offset, bool nottyped, bool silent)
|
||||
{
|
||||
char_u *s1, *s2;
|
||||
int newlen;
|
||||
int addlen;
|
||||
int i;
|
||||
int newoff;
|
||||
int val;
|
||||
int nrm;
|
||||
|
||||
@ -901,13 +899,15 @@ int ins_typebuf(char_u *str, int noremap, int offset, bool nottyped, bool silent
|
||||
// In typebuf.tb_buf there must always be room for 3 * (MAXMAPLEN + 4)
|
||||
// characters. We add some extra room to avoid having to allocate too
|
||||
// often.
|
||||
newoff = MAXMAPLEN + 4;
|
||||
newlen = typebuf.tb_len + addlen + newoff + 4 * (MAXMAPLEN + 4);
|
||||
if (newlen < 0) { // string is getting too long
|
||||
int newoff = MAXMAPLEN + 4;
|
||||
int extra = addlen + newoff + 4 * (MAXMAPLEN + 4);
|
||||
if (typebuf.tb_len > 2147483674 - extra) {
|
||||
// string is getting too long for 32 bit int
|
||||
emsg(_(e_toocompl)); // also calls flush_buffers
|
||||
setcursor();
|
||||
return FAIL;
|
||||
}
|
||||
int newlen = typebuf.tb_len + extra;
|
||||
s1 = xmalloc((size_t)newlen);
|
||||
s2 = xmalloc((size_t)newlen);
|
||||
typebuf.tb_buflen = newlen;
|
||||
@ -1442,6 +1442,28 @@ static void updatescript(int c)
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge "modifiers" into "c_arg".
|
||||
int merge_modifiers(int c_arg, int *modifiers)
|
||||
{
|
||||
int c = c_arg;
|
||||
|
||||
if (*modifiers & MOD_MASK_CTRL) {
|
||||
if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_')) {
|
||||
c &= 0x1f;
|
||||
if (c == NUL) {
|
||||
c = K_ZERO;
|
||||
}
|
||||
} else if (c == '6') {
|
||||
// CTRL-6 is equivalent to CTRL-^
|
||||
c = 0x1e;
|
||||
}
|
||||
if (c != c_arg) {
|
||||
*modifiers &= ~MOD_MASK_CTRL;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/// 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
|
||||
@ -1478,6 +1500,8 @@ int vgetc(void)
|
||||
static size_t last_vgetc_recorded_len = 0;
|
||||
|
||||
mod_mask = 0;
|
||||
vgetc_mod_mask = 0;
|
||||
vgetc_char = 0;
|
||||
|
||||
// last_recorded_len can be larger than last_vgetc_recorded_len
|
||||
// if peeking records more
|
||||
@ -1487,19 +1511,24 @@ int vgetc(void)
|
||||
bool did_inc = false;
|
||||
if (mod_mask) { // no mapping after modifier has been read
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
did_inc = true; // mod_mask may change value
|
||||
}
|
||||
c = vgetorpeek(true);
|
||||
if (did_inc) {
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
}
|
||||
|
||||
// Get two extra bytes for special keys
|
||||
if (c == K_SPECIAL) {
|
||||
int save_allow_keys = allow_keys;
|
||||
no_mapping++;
|
||||
allow_keys = 0; // make sure BS is not found
|
||||
c2 = vgetorpeek(true); // no mapping for these chars
|
||||
c = vgetorpeek(true);
|
||||
no_mapping--;
|
||||
allow_keys = save_allow_keys;
|
||||
if (c2 == KS_MODIFIER) {
|
||||
mod_mask = c;
|
||||
continue;
|
||||
@ -1601,20 +1630,9 @@ int vgetc(void)
|
||||
c = utf_ptr2char(buf);
|
||||
}
|
||||
|
||||
// A modifier was not used for a mapping, apply it to ASCII
|
||||
// keys. Shift would already have been applied.
|
||||
if (mod_mask & MOD_MASK_CTRL) {
|
||||
if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_')) {
|
||||
c &= 0x1f;
|
||||
mod_mask &= ~MOD_MASK_CTRL;
|
||||
if (c == 0) {
|
||||
c = K_ZERO;
|
||||
}
|
||||
} else if (c == '6') {
|
||||
// CTRL-6 is equivalent to CTRL-^
|
||||
c = 0x1e;
|
||||
mod_mask &= ~MOD_MASK_CTRL;
|
||||
}
|
||||
if (vgetc_char == 0) {
|
||||
vgetc_mod_mask = mod_mask;
|
||||
vgetc_char = c;
|
||||
}
|
||||
|
||||
// If mappings are enabled (i.e., not Ctrl-v) and the user directly typed
|
||||
@ -1731,11 +1749,87 @@ typedef enum {
|
||||
map_result_nomatch, // no matching mapping, get char
|
||||
} map_result_T;
|
||||
|
||||
/// Put "string[new_slen]" in typebuf.
|
||||
/// Remove "slen" bytes.
|
||||
/// @return FAIL for error, OK otherwise.
|
||||
static int put_string_in_typebuf(int offset, int slen, char_u *string, int new_slen)
|
||||
{
|
||||
int extra = new_slen - slen;
|
||||
string[new_slen] = NUL;
|
||||
if (extra < 0) {
|
||||
// remove matched chars, taking care of noremap
|
||||
del_typebuf(-extra, offset);
|
||||
} else if (extra > 0) {
|
||||
// insert the extra space we need
|
||||
if (ins_typebuf(string + slen, REMAP_YES, offset, false, false) == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
// Careful: del_typebuf() and ins_typebuf() may have reallocated
|
||||
// typebuf.tb_buf[]!
|
||||
memmove(typebuf.tb_buf + typebuf.tb_off + offset, string, (size_t)new_slen);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/// Check if typebuf.tb_buf[] contains a modifer plus key that can be changed
|
||||
/// into just a key, apply that.
|
||||
/// Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off + "max_offset"].
|
||||
/// @return the length of the replaced bytes, 0 if nothing changed, -1 for error.
|
||||
static int check_simplify_modifier(int max_offset)
|
||||
{
|
||||
for (int offset = 0; offset < max_offset; offset++) {
|
||||
if (offset + 3 >= typebuf.tb_len) {
|
||||
break;
|
||||
}
|
||||
char_u *tp = typebuf.tb_buf + typebuf.tb_off + offset;
|
||||
if (tp[0] == K_SPECIAL && tp[1] == KS_MODIFIER) {
|
||||
// A modifier was not used for a mapping, apply it to ASCII
|
||||
// keys. Shift would already have been applied.
|
||||
int modifier = tp[2];
|
||||
int c = tp[3];
|
||||
int new_c = merge_modifiers(c, &modifier);
|
||||
|
||||
if (new_c != c) {
|
||||
if (offset == 0) {
|
||||
// At the start: remember the character and mod_mask before
|
||||
// merging, in some cases, e.g. at the hit-return prompt,
|
||||
// they are put back in the typeahead buffer.
|
||||
vgetc_char = c;
|
||||
vgetc_mod_mask = tp[2];
|
||||
}
|
||||
char_u new_string[MB_MAXBYTES];
|
||||
int len;
|
||||
if (IS_SPECIAL(new_c)) {
|
||||
new_string[0] = K_SPECIAL;
|
||||
new_string[1] = (char_u)K_SECOND(new_c);
|
||||
new_string[2] = (char_u)K_THIRD(new_c);
|
||||
len = 3;
|
||||
} else {
|
||||
len = utf_char2bytes(new_c, new_string);
|
||||
}
|
||||
if (modifier == 0) {
|
||||
if (put_string_in_typebuf(offset, 4, new_string, len) == FAIL) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
tp[2] = (char_u)modifier;
|
||||
if (put_string_in_typebuf(offset + 3, 1, new_string, len) == FAIL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Handle mappings in the typeahead buffer.
|
||||
/// - When something was mapped, return map_result_retry for recursive mappings.
|
||||
/// - When nothing mapped and typeahead has a character: return map_result_get.
|
||||
/// - When there is no match yet, return map_result_nomatch, need to get more
|
||||
/// typeahead.
|
||||
/// - On failure (out of memory) return map_result_fail.
|
||||
static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
|
||||
{
|
||||
mapblock_T *mp = NULL;
|
||||
@ -1889,7 +1983,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
|
||||
}
|
||||
|
||||
// If no partly match found, use the longest full match.
|
||||
if (keylen != KEYLEN_PART_MAP) {
|
||||
if (keylen != KEYLEN_PART_MAP && mp_match != NULL) {
|
||||
mp = mp_match;
|
||||
keylen = mp_match_len;
|
||||
}
|
||||
@ -1928,17 +2022,54 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
|
||||
}
|
||||
}
|
||||
|
||||
if ((mp == NULL || max_mlen >= mp_match_len) && keylen != KEYLEN_PART_MAP) {
|
||||
// No matching mapping found or found a non-matching mapping that
|
||||
// matches at least what the matching mapping matched
|
||||
keylen = 0;
|
||||
(void)keylen; // suppress clang/dead assignment
|
||||
// If there was no mapping, use the character from the typeahead
|
||||
// buffer right here. Otherwise, use the mapping (loop around).
|
||||
if (mp == NULL) {
|
||||
*keylenp = keylen;
|
||||
return map_result_get; // get character from typeahead
|
||||
if ((mp == NULL || max_mlen > mp_match_len) && keylen != KEYLEN_PART_MAP) {
|
||||
// When no matching mapping found or found a non-matching mapping that
|
||||
// matches at least what the matching mapping matched:
|
||||
// Try to include the modifier into the key when mapping is allowed.
|
||||
if (no_mapping == 0 || allow_keys != 0) {
|
||||
if (tb_c1 == K_SPECIAL
|
||||
&& (typebuf.tb_len < 2
|
||||
|| (typebuf.tb_buf[typebuf.tb_off + 1] == KS_MODIFIER && typebuf.tb_len < 4))) {
|
||||
// Incomplete modifier sequence: cannot decide whether to simplify yet.
|
||||
keylen = KEYLEN_PART_KEY;
|
||||
} else if (keylen == KEYLEN_PART_KEY && !*timedout) {
|
||||
// If 'pastetoggle' matched partially, don't simplify.
|
||||
// When the last characters were not typed, don't wait for a typed character to
|
||||
// complete 'pastetoggle'.
|
||||
if (typebuf.tb_len == typebuf.tb_maplen) {
|
||||
keylen = 0;
|
||||
}
|
||||
} else {
|
||||
// Try to include the modifier into the key.
|
||||
keylen = check_simplify_modifier(max_mlen + 1);
|
||||
if (keylen < 0) {
|
||||
// ins_typebuf() failed
|
||||
return map_result_fail;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
keylen = 0;
|
||||
}
|
||||
if (keylen == 0) { // no simplication has been done
|
||||
// If there was no mapping at all use the character from the
|
||||
// typeahead buffer right here.
|
||||
if (mp == NULL) {
|
||||
*keylenp = keylen;
|
||||
return map_result_get; // get character from typeahead
|
||||
}
|
||||
}
|
||||
|
||||
if (keylen > 0) { // keys have been simplified
|
||||
*keylenp = keylen;
|
||||
return map_result_retry; // try mapping again
|
||||
}
|
||||
|
||||
if (keylen < 0) {
|
||||
// Incomplete key sequence: get some more characters.
|
||||
assert(keylen == KEYLEN_PART_KEY);
|
||||
} else {
|
||||
assert(mp != NULL);
|
||||
// When a matching mapping was found use that one.
|
||||
keylen = mp_match_len;
|
||||
}
|
||||
}
|
||||
@ -2620,7 +2751,7 @@ int inchar(char_u *buf, int maxlen, long wait_time)
|
||||
|
||||
for (;;) {
|
||||
len = os_inchar(dum, DUM_LEN, 0L, 0, NULL);
|
||||
if (len == 0 || (len == 1 && dum[0] == 3)) {
|
||||
if (len == 0 || (len == 1 && dum[0] == Ctrl_C)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2711,11 +2842,12 @@ int fix_input_buffer(char_u *buf, int len)
|
||||
/// @param[in] orig_rhs_len `strlen` of orig_rhs.
|
||||
/// @param[in] cpo_flags See param docs for @ref replace_termcodes.
|
||||
/// @param[out] mapargs MapArguments struct holding the replaced strings.
|
||||
void set_maparg_lhs_rhs(const char_u *orig_lhs, const size_t orig_lhs_len, const char_u *orig_rhs,
|
||||
const size_t orig_rhs_len, LuaRef rhs_lua, int cpo_flags,
|
||||
MapArguments *mapargs)
|
||||
void set_maparg_lhs_rhs(const char_u *const orig_lhs, const size_t orig_lhs_len,
|
||||
const char_u *const orig_rhs, const size_t orig_rhs_len,
|
||||
const LuaRef rhs_lua, const int cpo_flags, MapArguments *const mapargs)
|
||||
{
|
||||
char_u *lhs_buf = NULL;
|
||||
char_u *alt_lhs_buf = NULL;
|
||||
char_u *rhs_buf = NULL;
|
||||
|
||||
// If mapping has been given as ^V<C_UP> say, then replace the term codes
|
||||
@ -2725,10 +2857,22 @@ void set_maparg_lhs_rhs(const char_u *orig_lhs, const size_t orig_lhs_len, const
|
||||
// replace_termcodes() may move the result to allocated memory, which
|
||||
// needs to be freed later (*lhs_buf and *rhs_buf).
|
||||
// replace_termcodes() also removes CTRL-Vs and sometimes backslashes.
|
||||
char_u *replaced = replace_termcodes(orig_lhs, orig_lhs_len, &lhs_buf,
|
||||
true, true, true, cpo_flags);
|
||||
// If something like <C-H> is simplified to 0x08 then mark it as simplified.
|
||||
bool did_simplify = false;
|
||||
const int flags = REPTERM_FROM_PART | REPTERM_DO_LT;
|
||||
char_u *replaced = replace_termcodes(orig_lhs, orig_lhs_len, &lhs_buf, flags, &did_simplify,
|
||||
cpo_flags);
|
||||
mapargs->lhs_len = STRLEN(replaced);
|
||||
STRLCPY(mapargs->lhs, replaced, sizeof(mapargs->lhs));
|
||||
if (did_simplify) {
|
||||
replaced = replace_termcodes(orig_lhs, orig_lhs_len, &alt_lhs_buf, flags | REPTERM_NO_SIMPLIFY,
|
||||
NULL, cpo_flags);
|
||||
mapargs->alt_lhs_len = STRLEN(replaced);
|
||||
STRLCPY(mapargs->alt_lhs, replaced, sizeof(mapargs->alt_lhs));
|
||||
} else {
|
||||
mapargs->alt_lhs_len = 0;
|
||||
}
|
||||
|
||||
mapargs->rhs_lua = rhs_lua;
|
||||
|
||||
if (rhs_lua == LUA_NOREF) {
|
||||
@ -2741,8 +2885,8 @@ void set_maparg_lhs_rhs(const char_u *orig_lhs, const size_t orig_lhs_len, const
|
||||
mapargs->rhs_len = 0;
|
||||
mapargs->rhs_is_noop = true;
|
||||
} else {
|
||||
replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf,
|
||||
false, true, true, cpo_flags);
|
||||
replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf, REPTERM_DO_LT, NULL,
|
||||
cpo_flags);
|
||||
mapargs->rhs_len = STRLEN(replaced);
|
||||
mapargs->rhs_is_noop = false;
|
||||
mapargs->rhs = xcalloc(mapargs->rhs_len + 1, sizeof(char_u));
|
||||
@ -2760,6 +2904,7 @@ void set_maparg_lhs_rhs(const char_u *orig_lhs, const size_t orig_lhs_len, const
|
||||
}
|
||||
|
||||
xfree(lhs_buf);
|
||||
xfree(alt_lhs_buf);
|
||||
xfree(rhs_buf);
|
||||
}
|
||||
|
||||
@ -2894,15 +3039,9 @@ int str_to_mapargs(const char_u *strargs, bool is_unmap, MapArguments *mapargs)
|
||||
int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, buf_T *buf)
|
||||
{
|
||||
mapblock_T *mp, **mpp;
|
||||
char_u *p;
|
||||
const char_u *p;
|
||||
int n;
|
||||
int len = 0; // init for GCC
|
||||
int did_it = false;
|
||||
int did_local = false;
|
||||
int round;
|
||||
int retval = 0;
|
||||
int hash;
|
||||
int new_hash;
|
||||
mapblock_T **abbr_table;
|
||||
mapblock_T **map_table;
|
||||
int noremap;
|
||||
@ -2929,8 +3068,9 @@ int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, buf_T
|
||||
|
||||
validate_maphash();
|
||||
|
||||
bool has_lhs = (args->lhs[0] != NUL);
|
||||
bool has_rhs = args->rhs_lua != LUA_NOREF || (args->rhs[0] != NUL) || args->rhs_is_noop;
|
||||
const bool has_lhs = (args->lhs[0] != NUL);
|
||||
const bool has_rhs = args->rhs_lua != LUA_NOREF || (args->rhs[0] != NUL) || args->rhs_is_noop;
|
||||
const bool do_print = !has_lhs || (maptype != 1 && !has_rhs);
|
||||
|
||||
// check for :unmap without argument
|
||||
if (maptype == 1 && !has_lhs) {
|
||||
@ -2938,300 +3078,343 @@ int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, buf_T
|
||||
goto theend;
|
||||
}
|
||||
|
||||
char_u *lhs = (char_u *)&args->lhs;
|
||||
char_u *rhs = args->rhs;
|
||||
char_u *orig_rhs = args->orig_rhs;
|
||||
const char_u *lhs = (char_u *)&args->lhs;
|
||||
const char_u *const rhs = args->rhs;
|
||||
const char_u *const orig_rhs = args->orig_rhs;
|
||||
const bool did_simplify = args->alt_lhs_len != 0;
|
||||
|
||||
// check arguments and translate function keys
|
||||
if (has_lhs) {
|
||||
len = (int)args->lhs_len;
|
||||
if (len > MAXMAPLEN) {
|
||||
retval = 1;
|
||||
goto theend;
|
||||
// The following is done twice if we have two versions of keys
|
||||
for (int keyround = 1; keyround <= 2; keyround++) {
|
||||
bool did_it = false;
|
||||
bool did_local = false;
|
||||
bool keyround1_simplified = keyround == 1 && did_simplify;
|
||||
int len = (int)args->lhs_len;
|
||||
|
||||
if (keyround == 2) {
|
||||
if (!did_simplify) {
|
||||
break;
|
||||
}
|
||||
lhs = (char_u *)&args->alt_lhs;
|
||||
len = (int)args->alt_lhs_len;
|
||||
} else if (did_simplify && do_print) {
|
||||
// when printing always use the not-simplified map
|
||||
lhs = (char_u *)&args->alt_lhs;
|
||||
len = (int)args->alt_lhs_len;
|
||||
}
|
||||
|
||||
if (is_abbrev && maptype != 1) {
|
||||
//
|
||||
// If an abbreviation ends in a keyword character, the
|
||||
// rest must be all keyword-char or all non-keyword-char.
|
||||
// Otherwise we won't be able to find the start of it in a
|
||||
// vi-compatible way.
|
||||
//
|
||||
int same = -1;
|
||||
|
||||
const int first = vim_iswordp(lhs);
|
||||
int last = first;
|
||||
p = lhs + utfc_ptr2len(lhs);
|
||||
n = 1;
|
||||
while (p < lhs + len) {
|
||||
n++; // nr of (multi-byte) chars
|
||||
last = vim_iswordp(p); // type of last char
|
||||
if (same == -1 && last != first) {
|
||||
same = n - 1; // count of same char type
|
||||
}
|
||||
p += utfc_ptr2len(p);
|
||||
}
|
||||
if (last && n > 2 && same >= 0 && same < n - 1) {
|
||||
// check arguments and translate function keys
|
||||
if (has_lhs) {
|
||||
if (len > MAXMAPLEN) {
|
||||
retval = 1;
|
||||
goto theend;
|
||||
}
|
||||
// An abbreviation cannot contain white space.
|
||||
for (n = 0; n < len; n++) {
|
||||
if (ascii_iswhite(lhs[n])) {
|
||||
|
||||
if (is_abbrev && maptype != 1) {
|
||||
//
|
||||
// If an abbreviation ends in a keyword character, the
|
||||
// rest must be all keyword-char or all non-keyword-char.
|
||||
// Otherwise we won't be able to find the start of it in a
|
||||
// vi-compatible way.
|
||||
//
|
||||
int same = -1;
|
||||
|
||||
const int first = vim_iswordp(lhs);
|
||||
int last = first;
|
||||
p = lhs + utfc_ptr2len(lhs);
|
||||
n = 1;
|
||||
while (p < lhs + len) {
|
||||
n++; // nr of (multi-byte) chars
|
||||
last = vim_iswordp(p); // type of last char
|
||||
if (same == -1 && last != first) {
|
||||
same = n - 1; // count of same char type
|
||||
}
|
||||
p += utfc_ptr2len(p);
|
||||
}
|
||||
if (last && n > 2 && same >= 0 && same < n - 1) {
|
||||
retval = 1;
|
||||
goto theend;
|
||||
}
|
||||
} // for
|
||||
}
|
||||
}
|
||||
|
||||
if (has_lhs && has_rhs && is_abbrev) { // if we will add an abbreviation,
|
||||
no_abbr = false; // reset flag that indicates there are no abbreviations
|
||||
}
|
||||
|
||||
if (!has_lhs || (maptype != 1 && !has_rhs)) {
|
||||
msg_start();
|
||||
}
|
||||
|
||||
// Check if a new local mapping wasn't already defined globally.
|
||||
if (map_table == buf->b_maphash && has_lhs && has_rhs && maptype != 1) {
|
||||
// need to loop over all global hash lists
|
||||
for (hash = 0; hash < 256 && !got_int; hash++) {
|
||||
if (is_abbrev) {
|
||||
if (hash != 0) { // there is only one abbreviation list
|
||||
break;
|
||||
}
|
||||
mp = first_abbr;
|
||||
} else {
|
||||
mp = maphash[hash];
|
||||
}
|
||||
for (; mp != NULL && !got_int; mp = mp->m_next) {
|
||||
// check entries with the same mode
|
||||
if ((mp->m_mode & mode) != 0
|
||||
&& mp->m_keylen == len
|
||||
&& args->unique
|
||||
&& STRNCMP(mp->m_keys, lhs, (size_t)len) == 0) {
|
||||
if (is_abbrev) {
|
||||
semsg(_("E224: global abbreviation already exists for %s"),
|
||||
mp->m_keys);
|
||||
} else {
|
||||
semsg(_("E225: global mapping already exists for %s"), mp->m_keys);
|
||||
// An abbreviation cannot contain white space.
|
||||
for (n = 0; n < len; n++) {
|
||||
if (ascii_iswhite(lhs[n])) {
|
||||
retval = 1;
|
||||
goto theend;
|
||||
}
|
||||
} // for
|
||||
}
|
||||
}
|
||||
|
||||
if (has_lhs && has_rhs && is_abbrev) { // if we will add an abbreviation,
|
||||
no_abbr = false; // reset flag that indicates there are no abbreviations
|
||||
}
|
||||
|
||||
if (do_print) {
|
||||
msg_start();
|
||||
}
|
||||
|
||||
// Check if a new local mapping wasn't already defined globally.
|
||||
if (map_table == buf->b_maphash && has_lhs && has_rhs && maptype != 1) {
|
||||
// need to loop over all global hash lists
|
||||
for (int hash = 0; hash < 256 && !got_int; hash++) {
|
||||
if (is_abbrev) {
|
||||
if (hash != 0) { // there is only one abbreviation list
|
||||
break;
|
||||
}
|
||||
mp = first_abbr;
|
||||
} else {
|
||||
mp = maphash[hash];
|
||||
}
|
||||
for (; mp != NULL && !got_int; mp = mp->m_next) {
|
||||
// check entries with the same mode
|
||||
if ((mp->m_mode & mode) != 0
|
||||
&& mp->m_keylen == len
|
||||
&& args->unique
|
||||
&& STRNCMP(mp->m_keys, lhs, (size_t)len) == 0) {
|
||||
if (is_abbrev) {
|
||||
semsg(_("E224: global abbreviation already exists for %s"),
|
||||
mp->m_keys);
|
||||
} else {
|
||||
semsg(_("E225: global mapping already exists for %s"), mp->m_keys);
|
||||
}
|
||||
retval = 5;
|
||||
goto theend;
|
||||
}
|
||||
retval = 5;
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When listing global mappings, also list buffer-local ones here.
|
||||
if (map_table != buf->b_maphash && !has_rhs && maptype != 1) {
|
||||
// need to loop over all global hash lists
|
||||
for (hash = 0; hash < 256 && !got_int; hash++) {
|
||||
if (is_abbrev) {
|
||||
if (hash != 0) { // there is only one abbreviation list
|
||||
break;
|
||||
// When listing global mappings, also list buffer-local ones here.
|
||||
if (map_table != buf->b_maphash && !has_rhs && maptype != 1) {
|
||||
// need to loop over all global hash lists
|
||||
for (int hash = 0; hash < 256 && !got_int; hash++) {
|
||||
if (is_abbrev) {
|
||||
if (hash != 0) { // there is only one abbreviation list
|
||||
break;
|
||||
}
|
||||
mp = buf->b_first_abbr;
|
||||
} else {
|
||||
mp = buf->b_maphash[hash];
|
||||
}
|
||||
mp = buf->b_first_abbr;
|
||||
} else {
|
||||
mp = buf->b_maphash[hash];
|
||||
}
|
||||
for (; mp != NULL && !got_int; mp = mp->m_next) {
|
||||
// check entries with the same mode
|
||||
if ((mp->m_mode & mode) != 0) {
|
||||
if (!has_lhs) { // show all entries
|
||||
showmap(mp, true);
|
||||
did_local = true;
|
||||
} else {
|
||||
n = mp->m_keylen;
|
||||
if (STRNCMP(mp->m_keys, lhs, (size_t)(n < len ? n : len)) == 0) {
|
||||
for (; mp != NULL && !got_int; mp = mp->m_next) {
|
||||
// check entries with the same mode
|
||||
if (!mp->m_simplified && (mp->m_mode & mode) != 0) {
|
||||
if (!has_lhs) { // show all entries
|
||||
showmap(mp, true);
|
||||
did_local = true;
|
||||
} else {
|
||||
n = mp->m_keylen;
|
||||
if (STRNCMP(mp->m_keys, lhs, (size_t)(n < len ? n : len)) == 0) {
|
||||
showmap(mp, true);
|
||||
did_local = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find an entry in the maphash[] list that matches.
|
||||
// For :unmap we may loop two times: once to try to unmap an entry with a
|
||||
// matching 'from' part, a second time, if the first fails, to unmap an
|
||||
// entry with a matching 'to' part. This was done to allow ":ab foo bar"
|
||||
// to be unmapped by typing ":unab foo", where "foo" will be replaced by
|
||||
// "bar" because of the abbreviation.
|
||||
for (round = 0; (round == 0 || maptype == 1) && round <= 1
|
||||
&& !did_it && !got_int; round++) {
|
||||
// need to loop over all hash lists
|
||||
for (hash = 0; hash < 256 && !got_int; hash++) {
|
||||
if (is_abbrev) {
|
||||
if (hash > 0) { // there is only one abbreviation list
|
||||
break;
|
||||
}
|
||||
mpp = abbr_table;
|
||||
} else {
|
||||
mpp = &(map_table[hash]);
|
||||
}
|
||||
for (mp = *mpp; mp != NULL && !got_int; mp = *mpp) {
|
||||
if (!(mp->m_mode & mode)) { // skip entries with wrong mode
|
||||
mpp = &(mp->m_next);
|
||||
continue;
|
||||
}
|
||||
if (!has_lhs) { // show all entries
|
||||
showmap(mp, map_table != maphash);
|
||||
did_it = true;
|
||||
} else { // do we have a match?
|
||||
if (round) { // second round: Try unmap "rhs" string
|
||||
n = (int)STRLEN(mp->m_str);
|
||||
p = mp->m_str;
|
||||
} else {
|
||||
n = mp->m_keylen;
|
||||
p = mp->m_keys;
|
||||
// Find an entry in the maphash[] list that matches.
|
||||
// For :unmap we may loop two times: once to try to unmap an entry with a
|
||||
// matching 'from' part, a second time, if the first fails, to unmap an
|
||||
// entry with a matching 'to' part. This was done to allow ":ab foo bar"
|
||||
// to be unmapped by typing ":unab foo", where "foo" will be replaced by
|
||||
// "bar" because of the abbreviation.
|
||||
for (int round = 0; (round == 0 || maptype == 1) && round <= 1
|
||||
&& !did_it && !got_int; round++) {
|
||||
// need to loop over all hash lists
|
||||
for (int hash = 0; hash < 256 && !got_int; hash++) {
|
||||
if (is_abbrev) {
|
||||
if (hash > 0) { // there is only one abbreviation list
|
||||
break;
|
||||
}
|
||||
if (STRNCMP(p, lhs, (size_t)(n < len ? n : len)) == 0) {
|
||||
if (maptype == 1) { // delete entry
|
||||
// Only accept a full match. For abbreviations we
|
||||
// ignore trailing space when matching with the
|
||||
// "lhs", since an abbreviation can't have
|
||||
// trailing space.
|
||||
if (n != len && (!is_abbrev || round || n > len
|
||||
|| *skipwhite(lhs + n) != NUL)) {
|
||||
mpp = &(mp->m_next);
|
||||
continue;
|
||||
}
|
||||
// We reset the indicated mode bits. If nothing is
|
||||
// left the entry is deleted below.
|
||||
mp->m_mode &= ~mode;
|
||||
did_it = true; // remember we did something
|
||||
} else if (!has_rhs) { // show matching entry
|
||||
mpp = abbr_table;
|
||||
} else {
|
||||
mpp = &(map_table[hash]);
|
||||
}
|
||||
for (mp = *mpp; mp != NULL && !got_int; mp = *mpp) {
|
||||
if ((mp->m_mode & mode) == 0) {
|
||||
// skip entries with wrong mode
|
||||
mpp = &(mp->m_next);
|
||||
continue;
|
||||
}
|
||||
if (!has_lhs) { // show all entries
|
||||
if (!mp->m_simplified) {
|
||||
showmap(mp, map_table != maphash);
|
||||
did_it = true;
|
||||
} else if (n != len) { // new entry is ambiguous
|
||||
mpp = &(mp->m_next);
|
||||
continue;
|
||||
} else if (args->unique) {
|
||||
if (is_abbrev) {
|
||||
semsg(_("E226: abbreviation already exists for %s"), p);
|
||||
} else {
|
||||
semsg(_("E227: mapping already exists for %s"), p);
|
||||
}
|
||||
retval = 5;
|
||||
goto theend;
|
||||
} else { // new rhs for existing entry
|
||||
mp->m_mode &= ~mode; // remove mode bits
|
||||
if (mp->m_mode == 0 && !did_it) { // reuse entry
|
||||
XFREE_CLEAR(mp->m_str);
|
||||
XFREE_CLEAR(mp->m_orig_str);
|
||||
XFREE_CLEAR(mp->m_desc);
|
||||
NLUA_CLEAR_REF(mp->m_luaref);
|
||||
|
||||
mp->m_str = vim_strsave(rhs);
|
||||
mp->m_orig_str = vim_strsave(orig_rhs);
|
||||
mp->m_luaref = args->rhs_lua;
|
||||
mp->m_noremap = noremap;
|
||||
mp->m_nowait = args->nowait;
|
||||
mp->m_silent = args->silent;
|
||||
mp->m_mode = mode;
|
||||
mp->m_expr = args->expr;
|
||||
mp->m_script_ctx = current_sctx;
|
||||
mp->m_script_ctx.sc_lnum += sourcing_lnum;
|
||||
nlua_set_sctx(&mp->m_script_ctx);
|
||||
if (args->desc != NULL) {
|
||||
mp->m_desc = xstrdup(args->desc);
|
||||
}
|
||||
} else { // do we have a match?
|
||||
if (round) { // second round: Try unmap "rhs" string
|
||||
n = (int)STRLEN(mp->m_str);
|
||||
p = mp->m_str;
|
||||
} else {
|
||||
n = mp->m_keylen;
|
||||
p = mp->m_keys;
|
||||
}
|
||||
if (STRNCMP(p, lhs, (size_t)(n < len ? n : len)) == 0) {
|
||||
if (maptype == 1) {
|
||||
// Delete entry.
|
||||
// Only accept a full match. For abbreviations
|
||||
// we ignore trailing space when matching with
|
||||
// the "lhs", since an abbreviation can't have
|
||||
// trailing space.
|
||||
if (n != len && (!is_abbrev || round || n > len
|
||||
|| *skipwhite(lhs + n) != NUL)) {
|
||||
mpp = &(mp->m_next);
|
||||
continue;
|
||||
}
|
||||
// In keyround for simplified keys, don't unmap
|
||||
// a mapping without m_simplified flag.
|
||||
if (keyround1_simplified && !mp->m_simplified) {
|
||||
break;
|
||||
}
|
||||
// We reset the indicated mode bits. If nothing
|
||||
// is left the entry is deleted below.
|
||||
mp->m_mode &= ~mode;
|
||||
did_it = true; // remember we did something
|
||||
} else if (!has_rhs) { // show matching entry
|
||||
if (!mp->m_simplified) {
|
||||
showmap(mp, map_table != maphash);
|
||||
did_it = true;
|
||||
}
|
||||
} else if (n != len) { // new entry is ambiguous
|
||||
mpp = &(mp->m_next);
|
||||
continue;
|
||||
} else if (keyround1_simplified && !mp->m_simplified) {
|
||||
// In keyround for simplified keys, don't replace
|
||||
// a mapping without m_simplified flag.
|
||||
did_it = true;
|
||||
break;
|
||||
} else if (args->unique) {
|
||||
if (is_abbrev) {
|
||||
semsg(_("E226: abbreviation already exists for %s"), p);
|
||||
} else {
|
||||
semsg(_("E227: mapping already exists for %s"), p);
|
||||
}
|
||||
retval = 5;
|
||||
goto theend;
|
||||
} else {
|
||||
// new rhs for existing entry
|
||||
mp->m_mode &= ~mode; // remove mode bits
|
||||
if (mp->m_mode == 0 && !did_it) { // reuse entry
|
||||
XFREE_CLEAR(mp->m_str);
|
||||
XFREE_CLEAR(mp->m_orig_str);
|
||||
XFREE_CLEAR(mp->m_desc);
|
||||
NLUA_CLEAR_REF(mp->m_luaref);
|
||||
|
||||
mp->m_str = vim_strsave(rhs);
|
||||
mp->m_orig_str = vim_strsave(orig_rhs);
|
||||
mp->m_luaref = args->rhs_lua;
|
||||
mp->m_noremap = noremap;
|
||||
mp->m_nowait = args->nowait;
|
||||
mp->m_silent = args->silent;
|
||||
mp->m_mode = mode;
|
||||
mp->m_simplified = keyround1_simplified;
|
||||
mp->m_expr = args->expr;
|
||||
mp->m_script_ctx = current_sctx;
|
||||
mp->m_script_ctx.sc_lnum += sourcing_lnum;
|
||||
nlua_set_sctx(&mp->m_script_ctx);
|
||||
if (args->desc != NULL) {
|
||||
mp->m_desc = xstrdup(args->desc);
|
||||
}
|
||||
did_it = true;
|
||||
}
|
||||
}
|
||||
if (mp->m_mode == 0) { // entry can be deleted
|
||||
mapblock_free(mpp);
|
||||
continue; // continue with *mpp
|
||||
}
|
||||
}
|
||||
if (mp->m_mode == 0) { // entry can be deleted
|
||||
mapblock_free(mpp);
|
||||
continue; // continue with *mpp
|
||||
}
|
||||
|
||||
// May need to put this entry into another hash list.
|
||||
new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
|
||||
if (!is_abbrev && new_hash != hash) {
|
||||
*mpp = mp->m_next;
|
||||
mp->m_next = map_table[new_hash];
|
||||
map_table[new_hash] = mp;
|
||||
// May need to put this entry into another hash list.
|
||||
int new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
|
||||
if (!is_abbrev && new_hash != hash) {
|
||||
*mpp = mp->m_next;
|
||||
mp->m_next = map_table[new_hash];
|
||||
map_table[new_hash] = mp;
|
||||
|
||||
continue; // continue with *mpp
|
||||
continue; // continue with *mpp
|
||||
}
|
||||
}
|
||||
}
|
||||
mpp = &(mp->m_next);
|
||||
}
|
||||
mpp = &(mp->m_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maptype == 1) { // delete entry
|
||||
if (!did_it) {
|
||||
retval = 2; // no match
|
||||
} else if (*lhs == Ctrl_C) {
|
||||
// If CTRL-C has been unmapped, reuse it for Interrupting.
|
||||
if (maptype == 1) {
|
||||
// delete entry
|
||||
if (!did_it) {
|
||||
if (!keyround1_simplified) {
|
||||
retval = 2; // no match
|
||||
}
|
||||
} else if (*lhs == Ctrl_C) {
|
||||
// If CTRL-C has been unmapped, reuse it for Interrupting.
|
||||
if (map_table == buf->b_maphash) {
|
||||
buf->b_mapped_ctrl_c &= ~mode;
|
||||
} else {
|
||||
mapped_ctrl_c &= ~mode;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!has_lhs || !has_rhs) {
|
||||
// print entries
|
||||
if (!did_it && !did_local) {
|
||||
if (is_abbrev) {
|
||||
msg(_("No abbreviation found"));
|
||||
} else {
|
||||
msg(_("No mapping found"));
|
||||
}
|
||||
}
|
||||
goto theend; // listing finished
|
||||
}
|
||||
|
||||
if (did_it) {
|
||||
continue; // have added the new entry already
|
||||
}
|
||||
|
||||
// Get here when adding a new entry to the maphash[] list or abbrlist.
|
||||
mp = xmalloc(sizeof(mapblock_T));
|
||||
|
||||
// If CTRL-C has been mapped, don't always use it for Interrupting.
|
||||
if (*lhs == Ctrl_C) {
|
||||
if (map_table == buf->b_maphash) {
|
||||
buf->b_mapped_ctrl_c &= ~mode;
|
||||
buf->b_mapped_ctrl_c |= mode;
|
||||
} else {
|
||||
mapped_ctrl_c &= ~mode;
|
||||
mapped_ctrl_c |= mode;
|
||||
}
|
||||
}
|
||||
goto theend;
|
||||
}
|
||||
|
||||
if (!has_lhs || !has_rhs) { // print entries
|
||||
if (!did_it && !did_local) {
|
||||
if (is_abbrev) {
|
||||
msg(_("No abbreviation found"));
|
||||
} else {
|
||||
msg(_("No mapping found"));
|
||||
}
|
||||
mp->m_keys = vim_strsave(lhs);
|
||||
mp->m_str = vim_strsave(rhs);
|
||||
mp->m_orig_str = vim_strsave(orig_rhs);
|
||||
mp->m_luaref = args->rhs_lua;
|
||||
mp->m_keylen = (int)STRLEN(mp->m_keys);
|
||||
mp->m_noremap = noremap;
|
||||
mp->m_nowait = args->nowait;
|
||||
mp->m_silent = args->silent;
|
||||
mp->m_mode = mode;
|
||||
mp->m_simplified = keyround1_simplified; // Notice this when porting patch 8.2.0807
|
||||
mp->m_expr = args->expr;
|
||||
mp->m_script_ctx = current_sctx;
|
||||
mp->m_script_ctx.sc_lnum += sourcing_lnum;
|
||||
nlua_set_sctx(&mp->m_script_ctx);
|
||||
mp->m_desc = NULL;
|
||||
if (args->desc != NULL) {
|
||||
mp->m_desc = xstrdup(args->desc);
|
||||
}
|
||||
goto theend; // listing finished
|
||||
}
|
||||
|
||||
if (did_it) { // have added the new entry already
|
||||
goto theend;
|
||||
}
|
||||
|
||||
// Get here when adding a new entry to the maphash[] list or abbrlist.
|
||||
mp = xmalloc(sizeof(mapblock_T));
|
||||
|
||||
// If CTRL-C has been mapped, don't always use it for Interrupting.
|
||||
if (*lhs == Ctrl_C) {
|
||||
if (map_table == buf->b_maphash) {
|
||||
buf->b_mapped_ctrl_c |= mode;
|
||||
// add the new entry in front of the abbrlist or maphash[] list
|
||||
if (is_abbrev) {
|
||||
mp->m_next = *abbr_table;
|
||||
*abbr_table = mp;
|
||||
} else {
|
||||
mapped_ctrl_c |= mode;
|
||||
n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
|
||||
mp->m_next = map_table[n];
|
||||
map_table[n] = mp;
|
||||
}
|
||||
}
|
||||
|
||||
mp->m_keys = vim_strsave(lhs);
|
||||
mp->m_str = vim_strsave(rhs);
|
||||
mp->m_orig_str = vim_strsave(orig_rhs);
|
||||
mp->m_luaref = args->rhs_lua;
|
||||
mp->m_keylen = (int)STRLEN(mp->m_keys);
|
||||
mp->m_noremap = noremap;
|
||||
mp->m_nowait = args->nowait;
|
||||
mp->m_silent = args->silent;
|
||||
mp->m_mode = mode;
|
||||
mp->m_expr = args->expr;
|
||||
mp->m_script_ctx = current_sctx;
|
||||
mp->m_script_ctx.sc_lnum += sourcing_lnum;
|
||||
nlua_set_sctx(&mp->m_script_ctx);
|
||||
mp->m_desc = NULL;
|
||||
if (args->desc != NULL) {
|
||||
mp->m_desc = xstrdup(args->desc);
|
||||
}
|
||||
|
||||
// add the new entry in front of the abbrlist or maphash[] list
|
||||
if (is_abbrev) {
|
||||
mp->m_next = *abbr_table;
|
||||
*abbr_table = mp;
|
||||
} else {
|
||||
n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
|
||||
mp->m_next = map_table[n];
|
||||
map_table[n] = mp;
|
||||
}
|
||||
|
||||
theend:
|
||||
return retval;
|
||||
}
|
||||
@ -3600,9 +3783,8 @@ bool map_to_exists(const char *const str, const char *const modechars, const boo
|
||||
int retval;
|
||||
|
||||
char_u *buf;
|
||||
char_u *const rhs = replace_termcodes((const char_u *)str, strlen(str), &buf,
|
||||
false, true, true,
|
||||
CPO_TO_CPO_FLAGS);
|
||||
const char_u *const rhs = replace_termcodes((const char_u *)str, strlen(str), &buf, REPTERM_DO_LT,
|
||||
NULL, CPO_TO_CPO_FLAGS);
|
||||
|
||||
#define MAPMODE(mode, modechars, chr, modeflags) \
|
||||
do { \
|
||||
|
@ -48,6 +48,10 @@ struct map_arguments {
|
||||
char_u lhs[MAXMAPLEN + 1];
|
||||
size_t lhs_len;
|
||||
|
||||
/// Unsimplifed {lhs} of the mapping. If no simplification has been done then alt_lhs_len is 0.
|
||||
char_u alt_lhs[MAXMAPLEN + 1];
|
||||
size_t alt_lhs_len;
|
||||
|
||||
char_u *rhs; /// The {rhs} of the mapping.
|
||||
size_t rhs_len;
|
||||
LuaRef rhs_lua; /// lua function as rhs
|
||||
@ -59,7 +63,7 @@ struct map_arguments {
|
||||
};
|
||||
typedef struct map_arguments MapArguments;
|
||||
#define MAP_ARGUMENTS_INIT { false, false, false, false, false, false, false, \
|
||||
{ 0 }, 0, NULL, 0, LUA_NOREF, false, NULL, 0, NULL }
|
||||
{ 0 }, 0, { 0 }, 0, NULL, 0, LUA_NOREF, false, NULL, 0, NULL }
|
||||
|
||||
#define KEYLEN_PART_KEY (-1) // keylen value for incomplete key-code
|
||||
#define KEYLEN_PART_MAP (-2) // keylen value for incomplete mapping
|
||||
|
@ -129,6 +129,9 @@ typedef off_t off_T;
|
||||
// held down based on the MOD_MASK_* symbols that are read first.
|
||||
EXTERN int mod_mask INIT(= 0); // current key modifiers
|
||||
|
||||
// The value of "mod_mask" and the unmodified character before calling merge_modifiers().
|
||||
EXTERN int vgetc_mod_mask INIT(= 0);
|
||||
EXTERN int vgetc_char INIT(= 0);
|
||||
|
||||
// Cmdline_row is the row where the command line starts, just below the
|
||||
// last window.
|
||||
@ -649,6 +652,7 @@ EXTERN int reg_recorded INIT(= 0); // last recorded register or zero
|
||||
|
||||
EXTERN int no_mapping INIT(= false); // currently no mapping allowed
|
||||
EXTERN int no_zero_mapping INIT(= 0); // mapping zero not allowed
|
||||
EXTERN int allow_keys INIT(= false); // allow key codes when no_mapping is set
|
||||
EXTERN int no_u_sync INIT(= 0); // Don't call u_sync()
|
||||
EXTERN int u_sync_once INIT(= 0); // Call u_sync() once when evaluating
|
||||
// an expression.
|
||||
|
@ -42,6 +42,7 @@ int ask_yesno(const char *const str, const bool direct)
|
||||
State = CONFIRM; // Mouse behaves like with :confirm.
|
||||
setmouse(); // Disable mouse in xterm.
|
||||
no_mapping++;
|
||||
allow_keys++; // no mapping here, but recognize keys
|
||||
|
||||
int r = ' ';
|
||||
while (r != 'y' && r != 'n') {
|
||||
@ -62,6 +63,7 @@ int ask_yesno(const char *const str, const bool direct)
|
||||
State = save_State;
|
||||
setmouse();
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -172,6 +174,7 @@ int get_number(int colon, int *mouse_used)
|
||||
}
|
||||
|
||||
no_mapping++;
|
||||
allow_keys++; // no mapping here, but recognize keys
|
||||
for (;;) {
|
||||
ui_cursor_goto(msg_row, msg_col);
|
||||
c = safe_vgetc();
|
||||
@ -205,6 +208,7 @@ int get_number(int colon, int *mouse_used)
|
||||
}
|
||||
}
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -568,23 +568,21 @@ char_u *get_special_key_name(int c, int modifiers)
|
||||
/// @param[in] src_len Length of the srcp.
|
||||
/// @param[out] dst Location where translation result will be kept. It must
|
||||
// be at least 19 bytes per "<x>" form.
|
||||
/// @param[in] keycode Prefer key code, e.g. K_DEL in place of DEL.
|
||||
/// @param[in] in_string Inside a double quoted string
|
||||
/// @param[in] flags FSK_ values
|
||||
/// @param[out] did_simplify found <C-H>, etc.
|
||||
///
|
||||
/// @return Number of characters added to dst, zero for no match.
|
||||
unsigned int trans_special(const char_u **srcp, const size_t src_len, char_u *const dst,
|
||||
const bool keycode, const bool in_string)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
unsigned int trans_special(const char_u **const srcp, const size_t src_len, char_u *const dst,
|
||||
const int flags, bool *const did_simplify)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
int modifiers = 0;
|
||||
int key;
|
||||
|
||||
key = find_special_key(srcp, src_len, &modifiers, keycode, false, in_string);
|
||||
int key = find_special_key(srcp, src_len, &modifiers, flags, did_simplify);
|
||||
if (key == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return special_to_buf(key, modifiers, keycode, dst);
|
||||
return special_to_buf(key, modifiers, flags & FSK_KEYCODE, dst);
|
||||
}
|
||||
|
||||
/// Put the character sequence for "key" with "modifiers" into "dst" and return
|
||||
@ -623,20 +621,20 @@ unsigned int special_to_buf(int key, int modifiers, bool keycode, char_u *dst)
|
||||
/// @param[in,out] srcp Translated <> name. Is advanced to after the <> name.
|
||||
/// @param[in] src_len srcp length.
|
||||
/// @param[out] modp Location where information about modifiers is saved.
|
||||
/// @param[in] keycode Prefer key code, e.g. K_DEL in place of DEL.
|
||||
/// @param[in] keep_x_key Don’t translate xHome to Home key.
|
||||
/// @param[in] in_string In string, double quote is escaped
|
||||
/// @param[in] flags FSK_ values
|
||||
/// @param[out] did_simplify FSK_SIMPLIFY and found <C-H>, etc.
|
||||
///
|
||||
/// @return Key and modifiers or 0 if there is no match.
|
||||
int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, const bool keycode,
|
||||
const bool keep_x_key, const bool in_string)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
int find_special_key(const char_u **const srcp, const size_t src_len, int *const modp,
|
||||
const int flags, bool *const did_simplify)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3)
|
||||
{
|
||||
const char_u *last_dash;
|
||||
const char_u *end_of_name;
|
||||
const char_u *src;
|
||||
const char_u *bp;
|
||||
const char_u *const end = *srcp + src_len - 1;
|
||||
const bool in_string = flags & FSK_IN_STRING;
|
||||
int modifiers;
|
||||
int bit;
|
||||
int key;
|
||||
@ -651,6 +649,9 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
|
||||
if (src[0] != '<') {
|
||||
return 0;
|
||||
}
|
||||
if (src[1] == '*') { // <*xxx>: do not simplify
|
||||
src++;
|
||||
}
|
||||
|
||||
// Find end of modifier list
|
||||
last_dash = src;
|
||||
@ -662,7 +663,7 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
|
||||
// Anything accepted, like <C-?>.
|
||||
// <C-"> or <M-"> are not special in strings as " is
|
||||
// the string delimiter. With a backslash it works: <M-\">
|
||||
if (end - bp > l && !(in_string && bp[1] == '"') && bp[l+1] == '>') {
|
||||
if (end - bp > l && !(in_string && bp[1] == '"') && bp[l + 1] == '>') {
|
||||
bp += l;
|
||||
} else if (end - bp > 2 && in_string && bp[1] == '\\'
|
||||
&& bp[2] == '"' && bp[3] == '>') {
|
||||
@ -723,7 +724,7 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
|
||||
key = utf_ptr2char(last_dash + off);
|
||||
} else {
|
||||
key = get_special_key_code(last_dash + off);
|
||||
if (!keep_x_key) {
|
||||
if (!(flags & FSK_KEEP_X_KEY)) {
|
||||
key = handle_x_keys(key);
|
||||
}
|
||||
}
|
||||
@ -736,7 +737,7 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
|
||||
// includes the modifier.
|
||||
key = simplify_key(key, &modifiers);
|
||||
|
||||
if (!keycode) {
|
||||
if (!(flags & FSK_KEYCODE)) {
|
||||
// don't want keycode, use single byte code
|
||||
if (key == K_BS) {
|
||||
key = BS;
|
||||
@ -748,7 +749,7 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
|
||||
// Normal Key with modifier:
|
||||
// Try to make a single byte code (except for Alt/Meta modifiers).
|
||||
if (!IS_SPECIAL(key)) {
|
||||
key = extract_modifiers(key, &modifiers);
|
||||
key = extract_modifiers(key, &modifiers, flags & FSK_SIMPLIFY, did_simplify);
|
||||
}
|
||||
|
||||
*modp = modifiers;
|
||||
@ -762,7 +763,10 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
|
||||
|
||||
/// Try to include modifiers (except alt/meta) in the key.
|
||||
/// Changes "Shift-a" to 'A', "Ctrl-@" to <Nul>, etc.
|
||||
static int extract_modifiers(int key, int *modp)
|
||||
/// @param[in] simplify if false, don't do Ctrl
|
||||
/// @param[out] did_simplify set when it is not NULL and "simplify" is true and
|
||||
/// Ctrl is removed from modifiers
|
||||
static int extract_modifiers(int key, int *modp, const bool simplify, bool *const did_simplify)
|
||||
{
|
||||
int modifiers = *modp;
|
||||
|
||||
@ -773,15 +777,19 @@ static int extract_modifiers(int key, int *modp)
|
||||
modifiers &= ~MOD_MASK_SHIFT;
|
||||
}
|
||||
}
|
||||
if ((modifiers & MOD_MASK_CTRL) && ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))) {
|
||||
// <C-H> and <C-h> mean the same thing, always use "H"
|
||||
if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key)) {
|
||||
key = TOUPPER_ASC(key);
|
||||
int new_key = CTRL_CHR(key);
|
||||
if (new_key != TAB && new_key != CAR && new_key != ESC) {
|
||||
key = new_key;
|
||||
modifiers &= ~MOD_MASK_CTRL;
|
||||
if (key == 0) { // <C-@> is <Nul>
|
||||
key = K_ZERO;
|
||||
}
|
||||
}
|
||||
if (simplify && (modifiers & MOD_MASK_CTRL)
|
||||
&& ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))) {
|
||||
key = CTRL_CHR(key);
|
||||
modifiers &= ~MOD_MASK_CTRL;
|
||||
if (key == NUL) { // <C-@> is <Nul>
|
||||
key = K_ZERO;
|
||||
}
|
||||
if (did_simplify != NULL) {
|
||||
*did_simplify = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -853,34 +861,31 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag)
|
||||
return 0; // Shouldn't get here
|
||||
}
|
||||
|
||||
/// Replace any terminal code strings with the equivalent internal
|
||||
/// representation
|
||||
/// Replace any terminal code strings with the equivalent internal representation.
|
||||
///
|
||||
/// Used for the "from" and "to" part of a mapping, and the "to" part of
|
||||
/// a menu command. Any strings like "<C-UP>" are also replaced, unless
|
||||
/// `special` is false. K_SPECIAL by itself is replaced by K_SPECIAL
|
||||
/// KS_SPECIAL KE_FILLER.
|
||||
/// Used for the "from" and "to" part of a mapping, and the "to" part of a menu command.
|
||||
/// Any strings like "<C-UP>" are also replaced, unless `special` is false.
|
||||
/// K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER.
|
||||
///
|
||||
/// When "flags" has REPTERM_FROM_PART, trailing <C-v> is included, otherwise it is removed (to make
|
||||
/// ":map xx ^V" map xx to nothing). When cpo_flags contains FLAG_CPO_BSLASH, a backslash can be
|
||||
/// used in place of <C-v>. All other <C-v> characters are removed.
|
||||
///
|
||||
/// @param[in] from What characters to replace.
|
||||
/// @param[in] from_len Length of the "from" argument.
|
||||
/// @param[out] bufp Location where results were saved in case of success
|
||||
/// (allocated). Will be set to NULL in case of failure.
|
||||
/// @param[in] do_lt If true, also translate <lt>.
|
||||
/// @param[in] from_part If true, trailing <C-v> is included, otherwise it is
|
||||
/// removed (to make ":map xx ^V" map xx to nothing).
|
||||
/// When cpo_flags contains #FLAG_CPO_BSLASH, a backslash
|
||||
/// can be used in place of <C-v>. All other <C-v>
|
||||
/// characters are removed.
|
||||
/// @param[in] special Replace keycodes, e.g. <CR> becomes a "\n" char.
|
||||
/// @param[in] cpo_flags Relevant flags derived from p_cpo, see
|
||||
/// #CPO_TO_CPO_FLAGS.
|
||||
/// @param[out] bufp Location where results were saved in case of success (allocated).
|
||||
/// Will be set to NULL in case of failure.
|
||||
/// @param[in] flags REPTERM_FROM_PART see above
|
||||
/// REPTERM_DO_LT also translate <lt>
|
||||
/// REPTERM_NO_SPECIAL do not accept <key> notation
|
||||
/// REPTERM_NO_SIMPLIFY do not simplify <C-H> into 0x08, etc.
|
||||
/// @param[out] did_simplify set when some <C-H> code was simplied, unless it is NULL.
|
||||
/// @param[in] cpo_flags Relevant flags derived from p_cpo, see CPO_TO_CPO_FLAGS.
|
||||
///
|
||||
/// @return Pointer to an allocated memory in case of success, "from" in case of
|
||||
/// failure. In case of success returned pointer is also saved to
|
||||
/// "bufp".
|
||||
char_u *replace_termcodes(const char_u *from, const size_t from_len, char_u **bufp,
|
||||
const bool from_part, const bool do_lt, const bool special, int cpo_flags)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
/// @return Pointer to an allocated memory, which is also saved to "bufp".
|
||||
char_u *replace_termcodes(const char_u *const from, const size_t from_len, char_u **const bufp,
|
||||
const int flags, bool *const did_simplify, const int cpo_flags)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 3)
|
||||
{
|
||||
ssize_t i;
|
||||
size_t slen;
|
||||
@ -888,10 +893,10 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, char_u **bu
|
||||
size_t dlen = 0;
|
||||
const char_u *src;
|
||||
const char_u *const end = from + from_len - 1;
|
||||
int do_backslash; // backslash is a special character
|
||||
char_u *result; // buffer for resulting string
|
||||
|
||||
do_backslash = !(cpo_flags&FLAG_CPO_BSLASH);
|
||||
const bool do_backslash = !(cpo_flags & FLAG_CPO_BSLASH); // backslash is a special character
|
||||
const bool do_special = !(flags & REPTERM_NO_SPECIAL);
|
||||
|
||||
// Allocate space for the translation. Worst case a single character is
|
||||
// replaced by 6 bytes (shifted special key), plus a NUL at the end.
|
||||
@ -901,7 +906,7 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, char_u **bu
|
||||
src = from;
|
||||
|
||||
// Check for #n at start only: function key n
|
||||
if (from_part && from_len > 1 && src[0] == '#'
|
||||
if ((flags & REPTERM_FROM_PART) && from_len > 1 && src[0] == '#'
|
||||
&& ascii_isdigit(src[1])) { // function key
|
||||
result[dlen++] = K_SPECIAL;
|
||||
result[dlen++] = 'k';
|
||||
@ -916,8 +921,8 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, char_u **bu
|
||||
// Copy each byte from *from to result[dlen]
|
||||
while (src <= end) {
|
||||
// Check for special <> keycodes, like "<C-S-LeftMouse>"
|
||||
if (special && (do_lt || ((end - src) >= 3
|
||||
&& STRNCMP(src, "<lt>", 4) != 0))) {
|
||||
if (do_special && ((flags & REPTERM_DO_LT) || ((end - src) >= 3
|
||||
&& STRNCMP(src, "<lt>", 4) != 0))) {
|
||||
// Replace <SID> by K_SNR <script-nr> _.
|
||||
// (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14)
|
||||
if (end - src >= 4 && STRNICMP(src, "<SID>", 5) == 0) {
|
||||
@ -936,15 +941,16 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, char_u **bu
|
||||
}
|
||||
}
|
||||
|
||||
slen = trans_special(&src, (size_t)(end - src) + 1, result + dlen, true,
|
||||
false);
|
||||
slen = trans_special(&src, (size_t)(end - src) + 1, result + dlen,
|
||||
FSK_KEYCODE | ((flags & REPTERM_NO_SIMPLIFY) ? 0 : FSK_SIMPLIFY),
|
||||
did_simplify);
|
||||
if (slen) {
|
||||
dlen += slen;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (special) {
|
||||
if (do_special) {
|
||||
char_u *p, *s, len;
|
||||
|
||||
// Replace <Leader> by the value of "mapleader".
|
||||
@ -984,7 +990,7 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, char_u **bu
|
||||
if (key == Ctrl_V || (do_backslash && key == '\\')) {
|
||||
src++; // skip CTRL-V or backslash
|
||||
if (src > end) {
|
||||
if (from_part) {
|
||||
if (flags & REPTERM_FROM_PART) {
|
||||
result[dlen++] = key;
|
||||
}
|
||||
break;
|
||||
|
@ -507,6 +507,22 @@ enum key_extra {
|
||||
? 0 \
|
||||
: FLAG_CPO_BSLASH)
|
||||
|
||||
// Flags for replace_termcodes()
|
||||
enum {
|
||||
REPTERM_FROM_PART = 1,
|
||||
REPTERM_DO_LT = 2,
|
||||
REPTERM_NO_SPECIAL = 4,
|
||||
REPTERM_NO_SIMPLIFY = 8,
|
||||
};
|
||||
|
||||
// Flags for find_special_key()
|
||||
enum {
|
||||
FSK_KEYCODE = 0x01, ///< prefer key code, e.g. K_DEL in place of DEL
|
||||
FSK_KEEP_X_KEY = 0x02, ///< don’t translate xHome to Home key
|
||||
FSK_IN_STRING = 0x04, ///< in string, double quote is escaped
|
||||
FSK_SIMPLIFY = 0x08, ///< simplify <C-H>, etc.
|
||||
};
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "keymap.h.generated.h"
|
||||
#endif
|
||||
|
@ -236,8 +236,8 @@ void ex_menu(exarg_T *eap)
|
||||
} else if (modes & MENU_TIP_MODE) {
|
||||
map_buf = NULL; // Menu tips are plain text.
|
||||
} else {
|
||||
map_to = (char *)replace_termcodes((char_u *)map_to, STRLEN(map_to),
|
||||
(char_u **)&map_buf, false, true, true, CPO_TO_CPO_FLAGS);
|
||||
map_to = (char *)replace_termcodes((char_u *)map_to, STRLEN(map_to), (char_u **)&map_buf,
|
||||
REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS);
|
||||
}
|
||||
menuarg.modes = modes;
|
||||
menuarg.noremap[0] = noremap;
|
||||
|
@ -1146,6 +1146,7 @@ void wait_return(int redraw)
|
||||
// Don't do mappings here, we put the character back in the
|
||||
// typeahead buffer.
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
|
||||
// Temporarily disable Recording. If Recording is active, the
|
||||
// character will be recorded later, since it will be added to the
|
||||
@ -1159,6 +1160,7 @@ void wait_return(int redraw)
|
||||
got_int = false;
|
||||
}
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
reg_recording = save_reg_recording;
|
||||
scriptout = save_scriptout;
|
||||
|
||||
@ -1214,7 +1216,7 @@ void wait_return(int redraw)
|
||||
} else if (vim_strchr((char_u *)"\r\n ", c) == NULL && c != Ctrl_C) {
|
||||
// Put the character back in the typeahead buffer. Don't use the
|
||||
// stuff buffer, because lmaps wouldn't work.
|
||||
ins_char_typebuf(c, mod_mask);
|
||||
ins_char_typebuf(vgetc_char, vgetc_mod_mask);
|
||||
do_redraw = true; // need a redraw even though there is
|
||||
// typeahead
|
||||
}
|
||||
|
@ -638,6 +638,7 @@ static void normal_get_additional_char(NormalState *s)
|
||||
int lang; // getting a text character
|
||||
|
||||
no_mapping++;
|
||||
allow_keys++; // no mapping for nchar, but allow key codes
|
||||
// Don't generate a CursorHold event here, most commands can't handle
|
||||
// it, e.g., nv_replace(), nv_csearch().
|
||||
did_cursorhold = true;
|
||||
@ -676,6 +677,7 @@ static void normal_get_additional_char(NormalState *s)
|
||||
if (lang && curbuf->b_p_iminsert == B_IMODE_LMAP) {
|
||||
// Allow mappings defined with ":lmap".
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
if (repl) {
|
||||
State = LREPLACE;
|
||||
} else {
|
||||
@ -689,6 +691,7 @@ static void normal_get_additional_char(NormalState *s)
|
||||
if (langmap_active) {
|
||||
// Undo the decrement done above
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
}
|
||||
State = NORMAL_BUSY;
|
||||
s->need_flushbuf |= add_to_showcmd(*cp);
|
||||
@ -769,6 +772,7 @@ static void normal_get_additional_char(NormalState *s)
|
||||
no_mapping++;
|
||||
}
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
}
|
||||
|
||||
static void normal_invert_horizontal(NormalState *s)
|
||||
@ -826,6 +830,7 @@ static bool normal_get_command_count(NormalState *s)
|
||||
|
||||
if (s->ctrl_w) {
|
||||
no_mapping++;
|
||||
allow_keys++; // no mapping for nchar, but keys
|
||||
}
|
||||
|
||||
no_zero_mapping++; // don't map zero here
|
||||
@ -834,6 +839,7 @@ static bool normal_get_command_count(NormalState *s)
|
||||
no_zero_mapping--;
|
||||
if (s->ctrl_w) {
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
}
|
||||
s->need_flushbuf |= add_to_showcmd(s->c);
|
||||
}
|
||||
@ -844,9 +850,11 @@ static bool normal_get_command_count(NormalState *s)
|
||||
s->ca.opcount = s->ca.count0; // remember first count
|
||||
s->ca.count0 = 0;
|
||||
no_mapping++;
|
||||
allow_keys++; // no mapping for nchar, but keys
|
||||
s->c = plain_vgetc(); // get next character
|
||||
LANGMAP_ADJUST(s->c, true);
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
s->need_flushbuf |= add_to_showcmd(s->c);
|
||||
return true;
|
||||
}
|
||||
@ -995,7 +1003,7 @@ static int normal_execute(VimState *state, int key)
|
||||
// restart automatically.
|
||||
// Insert the typed character in the typeahead buffer, so that it can
|
||||
// be mapped in Insert mode. Required for ":lmap" to work.
|
||||
int len = ins_char_typebuf(s->c, mod_mask);
|
||||
int len = ins_char_typebuf(vgetc_char, vgetc_mod_mask);
|
||||
|
||||
// When recording and gotchars() was called the character will be
|
||||
// recorded again, remove the previous recording.
|
||||
@ -3407,9 +3415,11 @@ static void nv_zet(cmdarg_T *cap)
|
||||
n = nchar - '0';
|
||||
for (;;) {
|
||||
no_mapping++;
|
||||
allow_keys++; // no mapping for nchar, but allow key codes
|
||||
nchar = plain_vgetc();
|
||||
LANGMAP_ADJUST(nchar, true);
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
(void)add_to_showcmd(nchar);
|
||||
if (nchar == K_DEL || nchar == K_KDEL) {
|
||||
n /= 10;
|
||||
@ -3785,9 +3795,11 @@ dozet:
|
||||
|
||||
case 'u': // "zug" and "zuw": undo "zg" and "zw"
|
||||
no_mapping++;
|
||||
allow_keys++; // no mapping for nchar, but allow key codes
|
||||
nchar = plain_vgetc();
|
||||
LANGMAP_ADJUST(nchar, true);
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
(void)add_to_showcmd(nchar);
|
||||
if (vim_strchr((char_u *)"gGwW", nchar) == NULL) {
|
||||
clearopbeep(cap->oap);
|
||||
@ -5154,7 +5166,7 @@ static void nv_replace(cmdarg_T *cap)
|
||||
// get another character
|
||||
if (cap->nchar == Ctrl_V) {
|
||||
had_ctrl_v = Ctrl_V;
|
||||
cap->nchar = get_literal();
|
||||
cap->nchar = get_literal(false);
|
||||
// Don't redo a multibyte character with CTRL-V.
|
||||
if (cap->nchar > DEL) {
|
||||
had_ctrl_v = NUL;
|
||||
@ -5369,7 +5381,7 @@ static void nv_vreplace(cmdarg_T *cap)
|
||||
emsg(_(e_modifiable));
|
||||
} else {
|
||||
if (cap->extra_char == Ctrl_V) { // get another character
|
||||
cap->extra_char = get_literal();
|
||||
cap->extra_char = get_literal(false);
|
||||
}
|
||||
stuffcharReadbuff(cap->extra_char);
|
||||
stuffcharReadbuff(ESC);
|
||||
|
@ -3015,7 +3015,7 @@ ambw_end:
|
||||
} else if (varp == &p_pt) {
|
||||
// 'pastetoggle': translate key codes like in a mapping
|
||||
if (*p_pt) {
|
||||
(void)replace_termcodes(p_pt, STRLEN(p_pt), &p, true, true, true,
|
||||
(void)replace_termcodes(p_pt, STRLEN(p_pt), &p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL,
|
||||
CPO_TO_CPO_FLAGS);
|
||||
if (p != NULL) {
|
||||
if (new_value_alloced) {
|
||||
@ -5222,7 +5222,8 @@ int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt)
|
||||
} else if (has_lt) {
|
||||
arg--; // put arg at the '<'
|
||||
modifiers = 0;
|
||||
key = find_special_key(&arg, len + 1, &modifiers, true, true, false);
|
||||
key = find_special_key(&arg, len + 1, &modifiers,
|
||||
FSK_KEYCODE | FSK_KEEP_X_KEY | FSK_SIMPLIFY, NULL);
|
||||
if (modifiers) { // can't handle modifiers here
|
||||
key = 0;
|
||||
}
|
||||
|
@ -238,9 +238,9 @@ size_t input_enqueue(String keys)
|
||||
// but since the keys are UTF-8, so the first byte cannot be
|
||||
// K_SPECIAL(0x80).
|
||||
uint8_t buf[19] = { 0 };
|
||||
// Do not simplify the keys here. Simplification will be done later.
|
||||
unsigned int new_size
|
||||
= trans_special((const uint8_t **)&ptr, (size_t)(end - ptr), buf, true,
|
||||
false);
|
||||
= trans_special((const uint8_t **)&ptr, (size_t)(end - ptr), buf, FSK_KEYCODE, NULL);
|
||||
|
||||
if (new_size) {
|
||||
new_size = handle_mouse_event(&ptr, buf, new_size);
|
||||
@ -488,7 +488,12 @@ static void process_interrupts(void)
|
||||
|
||||
size_t consume_count = 0;
|
||||
RBUFFER_EACH_REVERSE(input_buffer, c, i) {
|
||||
if ((uint8_t)c == Ctrl_C) {
|
||||
if ((uint8_t)c == Ctrl_C
|
||||
|| ((uint8_t)c == 'C' && i >= 3
|
||||
&& (uint8_t)(*rbuffer_get(input_buffer, i - 3)) == K_SPECIAL
|
||||
&& (uint8_t)(*rbuffer_get(input_buffer, i - 2)) == KS_MODIFIER
|
||||
&& (uint8_t)(*rbuffer_get(input_buffer, i - 1)) == MOD_MASK_CTRL)) {
|
||||
*rbuffer_get(input_buffer, i) = Ctrl_C;
|
||||
got_int = true;
|
||||
consume_count = i;
|
||||
break;
|
||||
|
@ -1348,7 +1348,7 @@ static bool send_mouse_event(Terminal *term, int c)
|
||||
}
|
||||
|
||||
end:
|
||||
ins_char_typebuf(c, mod_mask);
|
||||
ins_char_typebuf(vgetc_char, vgetc_mod_mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ func Test_backspace_ctrl_u()
|
||||
|
||||
set cpo-=<
|
||||
inoremap <c-u> <left><c-u>
|
||||
exe "normal Avim3\<C-U>\<Esc>\<CR>"
|
||||
exe "normal Avim3\<*C-U>\<Esc>\<CR>"
|
||||
iunmap <c-u>
|
||||
exe "normal Avim4\<C-U>\<C-U>\<Esc>\<CR>"
|
||||
|
||||
@ -86,7 +86,7 @@ func Test_backspace_ctrl_u()
|
||||
exe "normal A vim6\<Esc>Azwei\<C-G>u\<C-U>\<Esc>\<CR>"
|
||||
|
||||
inoremap <c-u> <left><c-u>
|
||||
exe "normal A vim7\<C-U>\<C-U>\<Esc>\<CR>"
|
||||
exe "normal A vim7\<*C-U>\<*C-U>\<Esc>\<CR>"
|
||||
|
||||
call assert_equal([
|
||||
\ "1 this shouldn't be deleted",
|
||||
|
@ -185,7 +185,7 @@ func Test_let_register()
|
||||
call Assert_reg('"', 'v', "abc", "['abc']", "abc", "['abc']")
|
||||
let @" = "abc\n"
|
||||
call Assert_reg('"', 'V', "abc\n", "['abc']", "abc\n", "['abc']")
|
||||
let @" = "abc\r"
|
||||
let @" = "abc\<C-m>"
|
||||
call Assert_reg('"', 'V', "abc\r\n", "['abc\r']", "abc\r\n", "['abc\r']")
|
||||
let @= = '"abc"'
|
||||
call Assert_reg('=', 'v', "abc", "['abc']", '"abc"', "['\"abc\"']")
|
||||
|
@ -62,7 +62,7 @@ func Test_map_ctrl_c_insert()
|
||||
inoremap <c-c> <ctrl-c>
|
||||
cnoremap <c-c> dummy
|
||||
cunmap <c-c>
|
||||
call feedkeys("GoTEST2: CTRL-C |\<C-C>A|\<Esc>", "xt")
|
||||
call feedkeys("GoTEST2: CTRL-C |\<*C-C>A|\<Esc>", "xt")
|
||||
call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
|
||||
unmap! <c-c>
|
||||
set nomodified
|
||||
@ -71,7 +71,7 @@ endfunc
|
||||
func Test_map_ctrl_c_visual()
|
||||
" mapping of ctrl-c in Visual mode
|
||||
vnoremap <c-c> :<C-u>$put ='vmap works'
|
||||
call feedkeys("GV\<C-C>\<CR>", "xt")
|
||||
call feedkeys("GV\<*C-C>\<CR>", "xt")
|
||||
call assert_equal('vmap works', getline('$'))
|
||||
vunmap <c-c>
|
||||
set nomodified
|
||||
@ -221,7 +221,7 @@ endfunc
|
||||
|
||||
func Test_map_meta_quotes()
|
||||
imap <M-"> foo
|
||||
call feedkeys("Go-\<M-\">-\<Esc>", "xt")
|
||||
call feedkeys("Go-\<*M-\">-\<Esc>", "xt")
|
||||
call assert_equal("-foo-", getline('$'))
|
||||
set nomodified
|
||||
iunmap <M-">
|
||||
@ -429,6 +429,28 @@ func Test_error_in_map_expr()
|
||||
exe buf .. 'bwipe!'
|
||||
endfunc
|
||||
|
||||
func Test_list_mappings()
|
||||
" Remove default mappings
|
||||
imapclear
|
||||
|
||||
" reset 'isident' to check it isn't used
|
||||
set isident=
|
||||
inoremap <C-m> CtrlM
|
||||
inoremap <A-S> AltS
|
||||
inoremap <S-/> ShiftSlash
|
||||
set isident&
|
||||
call assert_equal([
|
||||
\ 'i <S-/> * ShiftSlash',
|
||||
\ 'i <M-S> * AltS',
|
||||
\ 'i <C-M> * CtrlM',
|
||||
\], execute('imap')->trim()->split("\n"))
|
||||
iunmap <C-M>
|
||||
iunmap <A-S>
|
||||
call assert_equal(['i <S-/> * ShiftSlash'], execute('imap')->trim()->split("\n"))
|
||||
iunmap <S-/>
|
||||
call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
|
||||
endfunc
|
||||
|
||||
func Test_expr_map_gets_cursor()
|
||||
new
|
||||
call setline(1, ['one', 'some w!rd'])
|
||||
@ -739,4 +761,20 @@ func Test_mouse_drag_insert_map()
|
||||
set mouse&
|
||||
endfunc
|
||||
|
||||
func Test_unmap_simplifiable()
|
||||
map <C-I> foo
|
||||
map <Tab> bar
|
||||
call assert_equal('foo', maparg('<C-I>'))
|
||||
call assert_equal('bar', maparg('<Tab>'))
|
||||
unmap <C-I>
|
||||
call assert_equal('', maparg('<C-I>'))
|
||||
call assert_equal('bar', maparg('<Tab>'))
|
||||
unmap <Tab>
|
||||
|
||||
map <C-I> foo
|
||||
unmap <Tab>
|
||||
" This should not error
|
||||
unmap <C-I>
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -112,6 +112,14 @@ func Test_echospace()
|
||||
set ruler& showcmd&
|
||||
endfunc
|
||||
|
||||
func Test_mapping_at_hit_return_prompt()
|
||||
nnoremap <C-B> :echo "hit ctrl-b"<CR>
|
||||
call feedkeys(":ls\<CR>", "xt")
|
||||
call feedkeys("\<*C-B>", "xt")
|
||||
call assert_match('hit ctrl-b', Screenline(&lines - 1))
|
||||
nunmap <C-B>
|
||||
endfunc
|
||||
|
||||
func Test_quit_long_message()
|
||||
CheckScreendump
|
||||
|
||||
|
@ -66,22 +66,22 @@ func Test_regex_char_classes()
|
||||
let save_enc = &encoding
|
||||
set encoding=utf-8
|
||||
|
||||
let input = "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"
|
||||
let input = "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"
|
||||
|
||||
" Format is [cmd_to_run, expected_output]
|
||||
let tests = [
|
||||
\ [':s/\%#=0\d//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1\d//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2\d//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0[0-9]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1[0-9]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2[0-9]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0\D//g',
|
||||
\ "0123456789"],
|
||||
\ [':s/\%#=1\D//g',
|
||||
@ -95,17 +95,17 @@ func Test_regex_char_classes()
|
||||
\ [':s/\%#=2[^0-9]//g',
|
||||
\ "0123456789"],
|
||||
\ [':s/\%#=0\o//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1\o//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2\o//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0[0-7]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1[0-7]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2[0-7]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0\O//g',
|
||||
\ "01234567"],
|
||||
\ [':s/\%#=1\O//g',
|
||||
@ -119,17 +119,17 @@ func Test_regex_char_classes()
|
||||
\ [':s/\%#=2[^0-7]//g',
|
||||
\ "01234567"],
|
||||
\ [':s/\%#=0\x//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1\x//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2\x//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0[0-9A-Fa-f]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1[0-9A-Fa-f]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2[0-9A-Fa-f]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0\X//g',
|
||||
\ "0123456789ABCDEFabcdef"],
|
||||
\ [':s/\%#=1\X//g',
|
||||
@ -143,17 +143,17 @@ func Test_regex_char_classes()
|
||||
\ [':s/\%#=2[^0-9A-Fa-f]//g',
|
||||
\ "0123456789ABCDEFabcdef"],
|
||||
\ [':s/\%#=0\w//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1\w//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2\w//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0[0-9A-Za-z_]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1[0-9A-Za-z_]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2[0-9A-Za-z_]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0\W//g',
|
||||
\ "0123456789ABCDEFGHIXYZ_abcdefghiwxyz"],
|
||||
\ [':s/\%#=1\W//g',
|
||||
@ -167,17 +167,17 @@ func Test_regex_char_classes()
|
||||
\ [':s/\%#=2[^0-9A-Za-z_]//g',
|
||||
\ "0123456789ABCDEFGHIXYZ_abcdefghiwxyz"],
|
||||
\ [':s/\%#=0\h//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1\h//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2\h//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0[A-Za-z_]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1[A-Za-z_]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2[A-Za-z_]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0\H//g',
|
||||
\ "ABCDEFGHIXYZ_abcdefghiwxyz"],
|
||||
\ [':s/\%#=1\H//g',
|
||||
@ -191,17 +191,17 @@ func Test_regex_char_classes()
|
||||
\ [':s/\%#=2[^A-Za-z_]//g',
|
||||
\ "ABCDEFGHIXYZ_abcdefghiwxyz"],
|
||||
\ [':s/\%#=0\a//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1\a//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2\a//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0[A-Za-z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1[A-Za-z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2[A-Za-z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0\A//g',
|
||||
\ "ABCDEFGHIXYZabcdefghiwxyz"],
|
||||
\ [':s/\%#=1\A//g',
|
||||
@ -215,17 +215,17 @@ func Test_regex_char_classes()
|
||||
\ [':s/\%#=2[^A-Za-z]//g',
|
||||
\ "ABCDEFGHIXYZabcdefghiwxyz"],
|
||||
\ [':s/\%#=0\l//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1\l//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2\l//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0[a-z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1[a-z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2[a-z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0\L//g',
|
||||
\ "abcdefghiwxyz"],
|
||||
\ [':s/\%#=1\L//g',
|
||||
@ -239,17 +239,17 @@ func Test_regex_char_classes()
|
||||
\ [':s/\%#=2[^a-z]//g',
|
||||
\ "abcdefghiwxyz"],
|
||||
\ [':s/\%#=0\u//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1\u//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2\u//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0[A-Z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1[A-Z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2[A-Z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0\U//g',
|
||||
\ "ABCDEFGHIXYZ"],
|
||||
\ [':s/\%#=1\U//g',
|
||||
@ -269,11 +269,11 @@ func Test_regex_char_classes()
|
||||
\ [':s/\%#=2\%' . line('.') . 'l^\t...//g',
|
||||
\ "!\"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~\<C-?>\u0080\u0082\u0090\u009b¦±¼ÇÓé"],
|
||||
\ [':s/\%#=0[0-z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=1[0-z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=2[0-z]//g',
|
||||
\ "\t\<C-L>\r !\"#$%&'()#+'-./{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ "\t\<C-L>\<C-M> !\"#$%&'()#+'-./{|}~\<C-?>\u0080\u0082\u0090\u009bΡ记娱"],
|
||||
\ [':s/\%#=0[^0-z]//g',
|
||||
\ "0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz"],
|
||||
\ [':s/\%#=1[^0-z]//g',
|
||||
@ -293,3 +293,5 @@ func Test_regex_char_classes()
|
||||
enew!
|
||||
close
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -177,9 +177,9 @@ func Test_sub_cmd_1()
|
||||
\ ['I', 's/I/\lII/', ['iI']],
|
||||
\ ['J', 's/J/\LJ\EJ/', ['jJ']],
|
||||
\ ['K', 's/K/\Uk\ek/', ['Kk']],
|
||||
\ ['lLl', "s/L/\<C-V>\r/", ["l\<C-V>", 'l']],
|
||||
\ ['lLl', "s/L/\<C-V>\<C-M>/", ["l\<C-V>", 'l']],
|
||||
\ ['mMm', 's/M/\r/', ['m', 'm']],
|
||||
\ ['nNn', "s/N/\\\<C-V>\r/", ["n\<C-V>", 'n']],
|
||||
\ ['nNn', "s/N/\\\<C-V>\<C-M>/", ["n\<C-V>", 'n']],
|
||||
\ ['oOo', 's/O/\n/', ["o\no"]],
|
||||
\ ['pPp', 's/P/\b/', ["p\<C-H>p"]],
|
||||
\ ['qQq', 's/Q/\t/', ["q\tq"]],
|
||||
@ -208,9 +208,9 @@ func Test_sub_cmd_2()
|
||||
\ ['I', 's/I/\lII/', ['iI']],
|
||||
\ ['J', 's/J/\LJ\EJ/', ['jJ']],
|
||||
\ ['K', 's/K/\Uk\ek/', ['Kk']],
|
||||
\ ['lLl', "s/L/\<C-V>\r/", ["l\<C-V>", 'l']],
|
||||
\ ['lLl', "s/L/\<C-V>\<C-M>/", ["l\<C-V>", 'l']],
|
||||
\ ['mMm', 's/M/\r/', ['m', 'm']],
|
||||
\ ['nNn', "s/N/\\\<C-V>\r/", ["n\<C-V>", 'n']],
|
||||
\ ['nNn', "s/N/\\\<C-V>\<C-M>/", ["n\<C-V>", 'n']],
|
||||
\ ['oOo', 's/O/\n/', ["o\no"]],
|
||||
\ ['pPp', 's/P/\b/', ["p\<C-H>p"]],
|
||||
\ ['qQq', 's/Q/\t/', ["q\tq"]],
|
||||
@ -230,9 +230,9 @@ func Test_sub_cmd_3()
|
||||
" List entry format: [input, cmd, output]
|
||||
let tests = [['aAa', "s/A/\\='\\'/", ['a\a']],
|
||||
\ ['bBb', "s/B/\\='\\\\'/", ['b\\b']],
|
||||
\ ['cCc', "s/C/\\='\<C-V>\r'/", ["c\<C-V>", 'c']],
|
||||
\ ['dDd', "s/D/\\='\\\<C-V>\r'/", ["d\\\<C-V>", 'd']],
|
||||
\ ['eEe', "s/E/\\='\\\\\<C-V>\r'/", ["e\\\\\<C-V>", 'e']],
|
||||
\ ['cCc', "s/C/\\='\<C-V>\<C-M>'/", ["c\<C-V>", 'c']],
|
||||
\ ['dDd', "s/D/\\='\\\<C-V>\<C-M>'/", ["d\\\<C-V>", 'd']],
|
||||
\ ['eEe', "s/E/\\='\\\\\<C-V>\<C-M>'/", ["e\\\\\<C-V>", 'e']],
|
||||
\ ['fFf', "s/F/\\='\r'/", ['f', 'f']],
|
||||
\ ['gGg', "s/G/\\='\<C-V>\<C-J>'/", ["g\<C-V>", 'g']],
|
||||
\ ['hHh', "s/H/\\='\\\<C-V>\<C-J>'/", ["h\\\<C-V>", 'h']],
|
||||
@ -254,11 +254,11 @@ func Test_sub_cmd_4()
|
||||
\ ['a\a']],
|
||||
\ ['bBb', "s/B/\\=substitute(submatch(0), '.', '\\', '')/",
|
||||
\ ['b\b']],
|
||||
\ ['cCc', "s/C/\\=substitute(submatch(0), '.', '\<C-V>\r', '')/",
|
||||
\ ['cCc', "s/C/\\=substitute(submatch(0), '.', '\<C-V>\<C-M>', '')/",
|
||||
\ ["c\<C-V>", 'c']],
|
||||
\ ['dDd', "s/D/\\=substitute(submatch(0), '.', '\\\<C-V>\r', '')/",
|
||||
\ ['dDd', "s/D/\\=substitute(submatch(0), '.', '\\\<C-V>\<C-M>', '')/",
|
||||
\ ["d\<C-V>", 'd']],
|
||||
\ ['eEe', "s/E/\\=substitute(submatch(0), '.', '\\\\\<C-V>\r', '')/",
|
||||
\ ['eEe', "s/E/\\=substitute(submatch(0), '.', '\\\\\<C-V>\<C-M>', '')/",
|
||||
\ ["e\\\<C-V>", 'e']],
|
||||
\ ['fFf', "s/F/\\=substitute(submatch(0), '.', '\\r', '')/",
|
||||
\ ['f', 'f']],
|
||||
@ -316,7 +316,7 @@ func Test_sub_cmd_7()
|
||||
set cpo&
|
||||
|
||||
" List entry format: [input, cmd, output]
|
||||
let tests = [ ["A\<C-V>\rA", 's/A./\=submatch(0)/', ['A', 'A']],
|
||||
let tests = [ ["A\<C-V>\<C-M>A", 's/A./\=submatch(0)/', ['A', 'A']],
|
||||
\ ["B\<C-V>\<C-J>B", 's/B./\=submatch(0)/', ['B', 'B']],
|
||||
\ ["C\<C-V>\<C-J>C", 's/C./\=strtrans(string(submatch(0, 1)))/', [strtrans("['C\<C-J>']C")]],
|
||||
\ ["D\<C-V>\<C-J>\nD", 's/D.\nD/\=strtrans(string(submatch(0, 1)))/', [strtrans("['D\<C-J>', 'D']")]],
|
||||
@ -467,11 +467,11 @@ func Test_sub_replace_1()
|
||||
call assert_equal('iI', substitute('I', 'I', '\lII', ''))
|
||||
call assert_equal('jJ', substitute('J', 'J', '\LJ\EJ', ''))
|
||||
call assert_equal('Kk', substitute('K', 'K', '\Uk\ek', ''))
|
||||
call assert_equal("l\<C-V>\rl",
|
||||
\ substitute('lLl', 'L', "\<C-V>\r", ''))
|
||||
call assert_equal("m\rm", substitute('mMm', 'M', '\r', ''))
|
||||
call assert_equal("n\<C-V>\rn",
|
||||
\ substitute('nNn', 'N', "\\\<C-V>\r", ''))
|
||||
call assert_equal("l\<C-V>\<C-M>l",
|
||||
\ substitute('lLl', 'L', "\<C-V>\<C-M>", ''))
|
||||
call assert_equal("m\<C-M>m", substitute('mMm', 'M', '\r', ''))
|
||||
call assert_equal("n\<C-V>\<C-M>n",
|
||||
\ substitute('nNn', 'N', "\\\<C-V>\<C-M>", ''))
|
||||
call assert_equal("o\no", substitute('oOo', 'O', '\n', ''))
|
||||
call assert_equal("p\<C-H>p", substitute('pPp', 'P', '\b', ''))
|
||||
call assert_equal("q\tq", substitute('qQq', 'Q', '\t', ''))
|
||||
@ -480,7 +480,7 @@ func Test_sub_replace_1()
|
||||
call assert_equal("u\nu", substitute('uUu', 'U', "\n", ''))
|
||||
call assert_equal("v\<C-H>v", substitute('vVv', 'V', "\b", ''))
|
||||
call assert_equal("w\\w", substitute('wWw', 'W', "\\", ''))
|
||||
call assert_equal("x\rx", substitute('xXx', 'X', "\r", ''))
|
||||
call assert_equal("x\<C-M>x", substitute('xXx', 'X', "\r", ''))
|
||||
call assert_equal("YyyY", substitute('Y', 'Y', '\L\uyYy\l\EY', ''))
|
||||
call assert_equal("zZZz", substitute('Z', 'Z', '\U\lZzZ\u\Ez', ''))
|
||||
endfunc
|
||||
@ -500,17 +500,17 @@ func Test_sub_replace_2()
|
||||
call assert_equal('iI', substitute('I', 'I', '\lII', ''))
|
||||
call assert_equal('jJ', substitute('J', 'J', '\LJ\EJ', ''))
|
||||
call assert_equal('Kk', substitute('K', 'K', '\Uk\ek', ''))
|
||||
call assert_equal("l\<C-V>\rl",
|
||||
\ substitute('lLl', 'L', "\<C-V>\r", ''))
|
||||
call assert_equal("m\rm", substitute('mMm', 'M', '\r', ''))
|
||||
call assert_equal("n\<C-V>\rn",
|
||||
\ substitute('nNn', 'N', "\\\<C-V>\r", ''))
|
||||
call assert_equal("l\<C-V>\<C-M>l",
|
||||
\ substitute('lLl', 'L', "\<C-V>\<C-M>", ''))
|
||||
call assert_equal("m\<C-M>m", substitute('mMm', 'M', '\r', ''))
|
||||
call assert_equal("n\<C-V>\<C-M>n",
|
||||
\ substitute('nNn', 'N', "\\\<C-V>\<C-M>", ''))
|
||||
call assert_equal("o\no", substitute('oOo', 'O', '\n', ''))
|
||||
call assert_equal("p\<C-H>p", substitute('pPp', 'P', '\b', ''))
|
||||
call assert_equal("q\tq", substitute('qQq', 'Q', '\t', ''))
|
||||
call assert_equal('r\r', substitute('rRr', 'R', '\\', ''))
|
||||
call assert_equal('scs', substitute('sSs', 'S', '\c', ''))
|
||||
call assert_equal("t\rt", substitute('tTt', 'T', "\r", ''))
|
||||
call assert_equal("t\<C-M>t", substitute('tTt', 'T', "\r", ''))
|
||||
call assert_equal("u\nu", substitute('uUu', 'U', "\n", ''))
|
||||
call assert_equal("v\<C-H>v", substitute('vVv', 'V', "\b", ''))
|
||||
call assert_equal('w\w', substitute('wWw', 'W', "\\", ''))
|
||||
@ -528,7 +528,7 @@ func Test_sub_replace_3()
|
||||
call assert_equal("e\\\\\re", substitute('eEe', 'E', "\\=\"\\\\\\\\\r\"", ''))
|
||||
call assert_equal('f\rf', substitute('fFf', 'F', '\="\\r"', ''))
|
||||
call assert_equal('j\nj', substitute('jJj', 'J', '\="\\n"', ''))
|
||||
call assert_equal("k\rk", substitute('kKk', 'K', '\="\r"', ''))
|
||||
call assert_equal("k\<C-M>k", substitute('kKk', 'K', '\="\r"', ''))
|
||||
call assert_equal("l\nl", substitute('lLl', 'L', '\="\n"', ''))
|
||||
endfunc
|
||||
|
||||
@ -540,10 +540,10 @@ func Test_sub_replace_4()
|
||||
\ '\=substitute(submatch(0), ".", "\\", "")', ''))
|
||||
call assert_equal('b\b', substitute('bBb', 'B',
|
||||
\ '\=substitute(submatch(0), ".", "\\\\", "")', ''))
|
||||
call assert_equal("c\<C-V>\rc", substitute('cCc', 'C', '\=substitute(submatch(0), ".", "\<C-V>\r", "")', ''))
|
||||
call assert_equal("d\<C-V>\rd", substitute('dDd', 'D', '\=substitute(submatch(0), ".", "\\\<C-V>\r", "")', ''))
|
||||
call assert_equal("e\\\<C-V>\re", substitute('eEe', 'E', '\=substitute(submatch(0), ".", "\\\\\<C-V>\r", "")', ''))
|
||||
call assert_equal("f\rf", substitute('fFf', 'F', '\=substitute(submatch(0), ".", "\\r", "")', ''))
|
||||
call assert_equal("c\<C-V>\<C-M>c", substitute('cCc', 'C', '\=substitute(submatch(0), ".", "\<C-V>\<C-M>", "")', ''))
|
||||
call assert_equal("d\<C-V>\<C-M>d", substitute('dDd', 'D', '\=substitute(submatch(0), ".", "\\\<C-V>\<C-M>", "")', ''))
|
||||
call assert_equal("e\\\<C-V>\<C-M>e", substitute('eEe', 'E', '\=substitute(submatch(0), ".", "\\\\\<C-V>\<C-M>", "")', ''))
|
||||
call assert_equal("f\<C-M>f", substitute('fFf', 'F', '\=substitute(submatch(0), ".", "\\r", "")', ''))
|
||||
call assert_equal("j\nj", substitute('jJj', 'J', '\=substitute(submatch(0), ".", "\\n", "")', ''))
|
||||
call assert_equal("k\rk", substitute('kKk', 'K', '\=substitute(submatch(0), ".", "\r", "")', ''))
|
||||
call assert_equal("l\nl", substitute('lLl', 'L', '\=substitute(submatch(0), ".", "\n", "")', ''))
|
||||
|
26
src/nvim/testdir/test_termcodes.vim
Normal file
26
src/nvim/testdir/test_termcodes.vim
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
func Test_simplify_ctrl_at()
|
||||
" feeding unsimplified CTRL-@ should still trigger i_CTRL-@
|
||||
call feedkeys("ifoo\<Esc>A\<*C-@>x", 'xt')
|
||||
call assert_equal('foofo', getline(1))
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_simplify_noremap()
|
||||
call feedkeys("i\<*C-M>", 'nx')
|
||||
call assert_equal('', getline(1))
|
||||
call assert_equal([0, 2, 1, 0, 1], getcurpos())
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_simplify_timedout()
|
||||
inoremap <C-M>a b
|
||||
call feedkeys("i\<*C-M>", 'xt')
|
||||
call assert_equal('', getline(1))
|
||||
call assert_equal([0, 2, 1, 0, 1], getcurpos())
|
||||
iunmap <C-M>a
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
@ -1817,9 +1817,13 @@ static void parse_quoted_string(ParserState *const pstate, ExprASTNode *const no
|
||||
}
|
||||
// Special key, e.g.: "\<C-W>"
|
||||
case '<': {
|
||||
const size_t special_len = (
|
||||
trans_special((const char_u **)&p, (size_t)(e - p),
|
||||
(char_u *)v_p, true, true));
|
||||
int flags = FSK_KEYCODE | FSK_IN_STRING;
|
||||
|
||||
if (p[1] != '*') {
|
||||
flags |= FSK_SIMPLIFY;
|
||||
}
|
||||
const size_t special_len = trans_special((const char_u **)&p, (size_t)(e - p),
|
||||
(char_u *)v_p, flags, NULL);
|
||||
if (special_len != 0) {
|
||||
v_p += special_len;
|
||||
} else {
|
||||
|
@ -534,11 +534,13 @@ wingotofile:
|
||||
case Ctrl_G:
|
||||
CHECK_CMDWIN;
|
||||
no_mapping++;
|
||||
allow_keys++; // no mapping for xchar, but allow key codes
|
||||
if (xchar == NUL) {
|
||||
xchar = plain_vgetc();
|
||||
}
|
||||
LANGMAP_ADJUST(xchar, true);
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
(void)add_to_showcmd(xchar);
|
||||
switch (xchar) {
|
||||
case '}':
|
||||
|
@ -582,7 +582,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
|
||||
it('can set mappings containing literal keycodes', function()
|
||||
meths.set_keymap('n', '\n\r\n', 'rhs', {})
|
||||
local expected = generate_mapargs('n', '<NL><CR><NL>', 'rhs')
|
||||
eq(expected, get_mapargs('n', '<C-j><CR><C-j>'))
|
||||
eq(expected, get_mapargs('n', '<NL><CR><NL>'))
|
||||
end)
|
||||
|
||||
it('can set mappings whose RHS is a <Nop>', function()
|
||||
|
@ -213,11 +213,11 @@ describe("'langmap'", function()
|
||||
iii]])
|
||||
end)
|
||||
|
||||
local function testrecording(command_string, expect_string, setup_function)
|
||||
local function testrecording(command_string, expect_string, setup_function, expect_macro)
|
||||
if setup_function then setup_function() end
|
||||
feed('qa' .. command_string .. 'q')
|
||||
expect(expect_string)
|
||||
eq(helpers.funcs.nvim_replace_termcodes(command_string, true, true, true),
|
||||
eq(expect_macro or helpers.funcs.nvim_replace_termcodes(command_string, true, true, true),
|
||||
eval('@a'))
|
||||
if setup_function then setup_function() end
|
||||
-- n.b. may need nvim_replace_termcodes() here.
|
||||
@ -273,8 +273,8 @@ describe("'langmap'", function()
|
||||
it('treats control modified keys as characters', function()
|
||||
command('nnoremap <C-w> iw<esc>')
|
||||
command('nnoremap <C-i> ii<esc>')
|
||||
testrecording('<C-w>', 'whello', local_setup)
|
||||
testrecording('<C-i>', 'ihello', local_setup)
|
||||
testrecording('<C-w>', 'whello', local_setup, eval([["\<*C-w>"]]))
|
||||
testrecording('<C-i>', 'ihello', local_setup, eval([["\<*C-i>"]]))
|
||||
end)
|
||||
|
||||
end)
|
||||
|
@ -3,67 +3,74 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local clear, insert, funcs, eq, feed =
|
||||
helpers.clear, helpers.insert, helpers.funcs, helpers.eq, helpers.feed
|
||||
local eval = helpers.eval
|
||||
local meths = helpers.meths
|
||||
|
||||
describe('cmdline CTRL-R', function()
|
||||
describe('cmdline', function()
|
||||
before_each(clear)
|
||||
|
||||
it('pasting non-special register inserts <CR> *between* lines', function()
|
||||
insert([[
|
||||
line1abc
|
||||
line2somemoretext
|
||||
]])
|
||||
-- Yank 2 lines linewise, then paste to cmdline.
|
||||
feed([[<C-\><C-N>gg0yj:<C-R>0]])
|
||||
-- <CR> inserted between lines, NOT after the final line.
|
||||
eq('line1abc\rline2somemoretext', funcs.getcmdline())
|
||||
describe('Ctrl-R', function()
|
||||
it('pasting non-special register inserts <CR> *between* lines', function()
|
||||
insert([[
|
||||
line1abc
|
||||
line2somemoretext
|
||||
]])
|
||||
-- Yank 2 lines linewise, then paste to cmdline.
|
||||
feed([[<C-\><C-N>gg0yj:<C-R>0]])
|
||||
-- <CR> inserted between lines, NOT after the final line.
|
||||
eq('line1abc\rline2somemoretext', funcs.getcmdline())
|
||||
|
||||
-- Yank 2 lines charwise, then paste to cmdline.
|
||||
feed([[<C-\><C-N>gg05lyvj:<C-R>0]])
|
||||
-- <CR> inserted between lines, NOT after the final line.
|
||||
eq('abc\rline2', funcs.getcmdline())
|
||||
-- Yank 2 lines charwise, then paste to cmdline.
|
||||
feed([[<C-\><C-N>gg05lyvj:<C-R>0]])
|
||||
-- <CR> inserted between lines, NOT after the final line.
|
||||
eq('abc\rline2', funcs.getcmdline())
|
||||
|
||||
-- Yank 1 line linewise, then paste to cmdline.
|
||||
feed([[<C-\><C-N>ggyy:<C-R>0]])
|
||||
-- No <CR> inserted.
|
||||
eq('line1abc', funcs.getcmdline())
|
||||
-- Yank 1 line linewise, then paste to cmdline.
|
||||
feed([[<C-\><C-N>ggyy:<C-R>0]])
|
||||
-- No <CR> inserted.
|
||||
eq('line1abc', funcs.getcmdline())
|
||||
end)
|
||||
|
||||
it('pasting special register inserts <CR>, <NL>', function()
|
||||
feed([[:<C-R>="foo\nbar\rbaz"<CR>]])
|
||||
eq('foo\nbar\rbaz', funcs.getcmdline())
|
||||
end)
|
||||
end)
|
||||
|
||||
it('pasting special register inserts <CR>, <NL>', function()
|
||||
feed([[:<C-R>="foo\nbar\rbaz"<CR>]])
|
||||
eq('foo\nbar\rbaz', funcs.getcmdline())
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('cmdline history', function()
|
||||
before_each(clear)
|
||||
|
||||
it('correctly clears start of the history', function()
|
||||
-- Regression test: check absence of the memory leak when clearing start of
|
||||
-- the history using ex_getln.c/clr_history().
|
||||
eq(1, funcs.histadd(':', 'foo'))
|
||||
eq(1, funcs.histdel(':'))
|
||||
eq('', funcs.histget(':', -1))
|
||||
end)
|
||||
|
||||
it('correctly clears end of the history', function()
|
||||
-- Regression test: check absence of the memory leak when clearing end of
|
||||
-- the history using ex_getln.c/clr_history().
|
||||
meths.set_option('history', 1)
|
||||
eq(1, funcs.histadd(':', 'foo'))
|
||||
eq(1, funcs.histdel(':'))
|
||||
eq('', funcs.histget(':', -1))
|
||||
end)
|
||||
|
||||
it('correctly removes item from history', function()
|
||||
-- Regression test: check that ex_getln.c/del_history_idx() correctly clears
|
||||
-- history index after removing history entry. If it does not then deleting
|
||||
-- history will result in a double free.
|
||||
eq(1, funcs.histadd(':', 'foo'))
|
||||
eq(1, funcs.histadd(':', 'bar'))
|
||||
eq(1, funcs.histadd(':', 'baz'))
|
||||
eq(1, funcs.histdel(':', -2))
|
||||
eq(1, funcs.histdel(':'))
|
||||
eq('', funcs.histget(':', -1))
|
||||
it('Ctrl-Shift-V supports entering unsimplified key notations', function()
|
||||
feed(':"<C-S-V><C-J><C-S-V><C-@><C-S-V><C-[><C-S-V><C-S-M><C-S-V><M-C-I><C-S-V><C-D-J><CR>')
|
||||
|
||||
eq('"<C-J><C-@><C-[><C-S-M><M-C-I><C-D-J>', eval('@:'))
|
||||
end)
|
||||
|
||||
describe('history', function()
|
||||
it('correctly clears start of the history', function()
|
||||
-- Regression test: check absence of the memory leak when clearing start of
|
||||
-- the history using ex_getln.c/clr_history().
|
||||
eq(1, funcs.histadd(':', 'foo'))
|
||||
eq(1, funcs.histdel(':'))
|
||||
eq('', funcs.histget(':', -1))
|
||||
end)
|
||||
|
||||
it('correctly clears end of the history', function()
|
||||
-- Regression test: check absence of the memory leak when clearing end of
|
||||
-- the history using ex_getln.c/clr_history().
|
||||
meths.set_option('history', 1)
|
||||
eq(1, funcs.histadd(':', 'foo'))
|
||||
eq(1, funcs.histdel(':'))
|
||||
eq('', funcs.histget(':', -1))
|
||||
end)
|
||||
|
||||
it('correctly removes item from history', function()
|
||||
-- Regression test: check that ex_getln.c/del_history_idx() correctly clears
|
||||
-- history index after removing history entry. If it does not then deleting
|
||||
-- history will result in a double free.
|
||||
eq(1, funcs.histadd(':', 'foo'))
|
||||
eq(1, funcs.histadd(':', 'bar'))
|
||||
eq(1, funcs.histadd(':', 'baz'))
|
||||
eq(1, funcs.histdel(':', -2))
|
||||
eq(1, funcs.histdel(':'))
|
||||
eq('', funcs.histget(':', -1))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
@ -131,6 +131,11 @@ describe('insert-mode', function()
|
||||
end)
|
||||
end)
|
||||
|
||||
it('Ctrl-Shift-V supports entering unsimplified key notations', function()
|
||||
feed('i<C-S-V><C-J><C-S-V><C-@><C-S-V><C-[><C-S-V><C-S-M><C-S-V><M-C-I><C-S-V><C-D-J><Esc>')
|
||||
expect('<C-J><C-@><C-[><C-S-M><M-C-I><C-D-J>')
|
||||
end)
|
||||
|
||||
describe([[With 'insertmode', Insert mode is not re-entered immediately after <C-L>]], function()
|
||||
before_each(function()
|
||||
command('set insertmode')
|
||||
|
@ -46,7 +46,7 @@ describe('eval', function()
|
||||
command('AR "')
|
||||
command([[let @" = "abc\n"]])
|
||||
source('AR "')
|
||||
command([[let @" = "abc\r"]])
|
||||
command([[let @" = "abc\<C-m>"]])
|
||||
command('AR "')
|
||||
command([[let @= = '"abc"']])
|
||||
command('AR =')
|
||||
|
@ -4,16 +4,14 @@ local clear = helpers.clear
|
||||
local feed = helpers.feed
|
||||
local command = helpers.command
|
||||
local eq = helpers.eq
|
||||
local eval = helpers.eval
|
||||
local sleep = helpers.sleep
|
||||
local expect = helpers.expect
|
||||
local eval = helpers.eval
|
||||
local insert = helpers.insert
|
||||
local meths = helpers.meths
|
||||
local sleep = helpers.sleep
|
||||
|
||||
describe("'pastetoggle' option", function()
|
||||
before_each(function()
|
||||
clear()
|
||||
command('set nopaste')
|
||||
end)
|
||||
|
||||
before_each(clear)
|
||||
it("toggles 'paste'", function()
|
||||
command('set pastetoggle=a')
|
||||
eq(0, eval('&paste'))
|
||||
@ -22,19 +20,71 @@ describe("'pastetoggle' option", function()
|
||||
feed('j')
|
||||
eq(1, eval('&paste'))
|
||||
end)
|
||||
describe("multiple key 'pastetoggle'", function()
|
||||
before_each(function()
|
||||
eq(0, eval('&paste'))
|
||||
command('set timeoutlen=1 ttimeoutlen=10000')
|
||||
end)
|
||||
it('is waited for when chars are typed', function()
|
||||
local pastetoggle = 'lllll'
|
||||
command('set pastetoggle=' .. pastetoggle)
|
||||
feed(pastetoggle:sub(0, 2))
|
||||
-- sleep() for long enough that vgetorpeek() is gotten into, but short
|
||||
-- enough that ttimeoutlen is not reached.
|
||||
sleep(200)
|
||||
feed(pastetoggle:sub(3, -1))
|
||||
-- Need another key so that the vgetorpeek() function returns.
|
||||
feed('j')
|
||||
eq(1, eval('&paste'))
|
||||
end)
|
||||
|
||||
it('is not waited for when there are no typed chars after mapped chars', function()
|
||||
command('set pastetoggle=abc')
|
||||
command('imap d a')
|
||||
meths.feedkeys('id', 't', true)
|
||||
-- sleep() for long enough that vgetorpeek() is gotten into, but short
|
||||
-- enough that ttimeoutlen is not reached.
|
||||
sleep(200)
|
||||
feed('bc')
|
||||
-- Need another key so that the vgetorpeek() function returns.
|
||||
feed('j')
|
||||
-- 'ttimeoutlen' should NOT apply
|
||||
eq(0, eval('&paste'))
|
||||
end)
|
||||
|
||||
it('does not wait for timeout', function()
|
||||
command('set pastetoggle=abc')
|
||||
command('set ttimeoutlen=9999999')
|
||||
eq(0, eval('&paste'))
|
||||
-- n.b. need <esc> to return from vgetorpeek()
|
||||
feed('abc<esc>')
|
||||
eq(1, eval('&paste'))
|
||||
feed('ab')
|
||||
sleep(10)
|
||||
feed('c<esc>')
|
||||
expect('bc')
|
||||
eq(1, eval('&paste'))
|
||||
it('is waited for when there are typed chars after mapped chars', function()
|
||||
command('set pastetoggle=abc')
|
||||
command('imap d a')
|
||||
meths.feedkeys('idb', 't', true)
|
||||
-- sleep() for long enough that vgetorpeek() is gotten into, but short
|
||||
-- enough that ttimeoutlen is not reached.
|
||||
sleep(200)
|
||||
feed('c')
|
||||
-- Need another key so that the vgetorpeek() function returns.
|
||||
feed('j')
|
||||
-- 'ttimeoutlen' should apply
|
||||
eq(1, eval('&paste'))
|
||||
end)
|
||||
|
||||
it('is waited for when there are typed chars after noremapped chars', function()
|
||||
command('set pastetoggle=abc')
|
||||
command('inoremap d a')
|
||||
meths.feedkeys('idb', 't', true)
|
||||
-- sleep() for long enough that vgetorpeek() is gotten into, but short
|
||||
-- enough that ttimeoutlen is not reached.
|
||||
sleep(200)
|
||||
feed('c')
|
||||
-- Need another key so that the vgetorpeek() function returns.
|
||||
feed('j')
|
||||
-- 'ttimeoutlen' should apply
|
||||
eq(1, eval('&paste'))
|
||||
end)
|
||||
end)
|
||||
it('does not interfere with character-find', function()
|
||||
insert('foo,bar')
|
||||
feed('0')
|
||||
command('set pastetoggle=,sp')
|
||||
feed('dt,')
|
||||
expect(',bar')
|
||||
end)
|
||||
end)
|
||||
|
@ -8,6 +8,7 @@ local meths = helpers.meths
|
||||
local exec_lua = helpers.exec_lua
|
||||
local write_file = helpers.write_file
|
||||
local funcs = helpers.funcs
|
||||
local eval = helpers.eval
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
|
||||
before_each(clear)
|
||||
@ -172,11 +173,20 @@ describe('input pairs', function()
|
||||
eq('\t\t', curbuf_contents())
|
||||
end)
|
||||
|
||||
it('can be mapped', function()
|
||||
command('inoremap <tab> TAB!')
|
||||
command('inoremap <c-i> CTRL-I!')
|
||||
feed('i<tab><c-i><esc>')
|
||||
eq('TAB!CTRL-I!', curbuf_contents())
|
||||
describe('can be mapped separately', function()
|
||||
it('if <tab> is mapped after <c-i>', function()
|
||||
command('inoremap <c-i> CTRL-I!')
|
||||
command('inoremap <tab> TAB!')
|
||||
feed('i<tab><c-i><esc>')
|
||||
eq('TAB!CTRL-I!', curbuf_contents())
|
||||
end)
|
||||
|
||||
it('if <tab> is mapped before <c-i>', function()
|
||||
command('inoremap <tab> TAB!')
|
||||
command('inoremap <c-i> CTRL-I!')
|
||||
feed('i<tab><c-i><esc>')
|
||||
eq('TAB!CTRL-I!', curbuf_contents())
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -186,11 +196,20 @@ describe('input pairs', function()
|
||||
eq('unos\ndos\ntres', curbuf_contents())
|
||||
end)
|
||||
|
||||
it('can be mapped', function()
|
||||
command('inoremap <c-m> SNIPPET!')
|
||||
command('inoremap <cr> , and then<cr>')
|
||||
feed('iunos<c-m>dos<cr>tres<esc>')
|
||||
eq('unosSNIPPET!dos, and then\ntres', curbuf_contents())
|
||||
describe('can be mapped separately', function()
|
||||
it('if <cr> is mapped after <c-m>', function()
|
||||
command('inoremap <c-m> SNIPPET!')
|
||||
command('inoremap <cr> , and then<cr>')
|
||||
feed('iunos<c-m>dos<cr>tres<esc>')
|
||||
eq('unosSNIPPET!dos, and then\ntres', curbuf_contents())
|
||||
end)
|
||||
|
||||
it('if <cr> is mapped before <c-m>', function()
|
||||
command('inoremap <cr> , and then<cr>')
|
||||
command('inoremap <c-m> SNIPPET!')
|
||||
feed('iunos<c-m>dos<cr>tres<esc>')
|
||||
eq('unosSNIPPET!dos, and then\ntres', curbuf_contents())
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -200,11 +219,20 @@ describe('input pairs', function()
|
||||
eq('doubledoublesingle', curbuf_contents())
|
||||
end)
|
||||
|
||||
it('can be mapped', function()
|
||||
command('inoremap <c-[> HALLOJ!')
|
||||
command('inoremap <esc> ,<esc>')
|
||||
feed('2adubbel<c-[>upp<esc>')
|
||||
eq('dubbelHALLOJ!upp,dubbelHALLOJ!upp,', curbuf_contents())
|
||||
describe('can be mapped separately', function()
|
||||
it('if <esc> is mapped after <c-[>', function()
|
||||
command('inoremap <c-[> HALLOJ!')
|
||||
command('inoremap <esc> ,<esc>')
|
||||
feed('2adubbel<c-[>upp<esc>')
|
||||
eq('dubbelHALLOJ!upp,dubbelHALLOJ!upp,', curbuf_contents())
|
||||
end)
|
||||
|
||||
it('if <esc> is mapped before <c-[>', function()
|
||||
command('inoremap <esc> ,<esc>')
|
||||
command('inoremap <c-[> HALLOJ!')
|
||||
feed('2adubbel<c-[>upp<esc>')
|
||||
eq('dubbelHALLOJ!upp,dubbelHALLOJ!upp,', curbuf_contents())
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
@ -216,6 +244,75 @@ it('Ctrl-6 is Ctrl-^ vim-patch:8.1.2333', function()
|
||||
eq('aaa', funcs.bufname())
|
||||
end)
|
||||
|
||||
it('c_CTRL-R_CTRL-R, i_CTRL-R_CTRL-R, i_CTRL-G_CTRL-K work properly vim-patch:8.1.2346', function()
|
||||
command('set timeoutlen=10')
|
||||
|
||||
command([[let @a = 'aaa']])
|
||||
feed([[:let x = '<C-R><C-R>a'<CR>]])
|
||||
eq([[let x = 'aaa']], eval('@:'))
|
||||
|
||||
feed('a<C-R><C-R>a<Esc>')
|
||||
expect('aaa')
|
||||
command('bwipe!')
|
||||
|
||||
feed('axx<CR>yy<C-G><C-K>a<Esc>')
|
||||
expect([[
|
||||
axx
|
||||
yy]])
|
||||
end)
|
||||
|
||||
it('typing a simplifiable key at hit-enter prompt triggers mapping vim-patch:8.2.0839', function()
|
||||
local screen = Screen.new(60,8)
|
||||
screen:set_default_attr_ids({
|
||||
[1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
|
||||
[2] = {bold = true, reverse = true}, -- MsgSeparator
|
||||
[3] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
|
||||
})
|
||||
screen:attach()
|
||||
command([[nnoremap <C-6> <Cmd>echo 'hit ctrl-6'<CR>]])
|
||||
feed_command('ls')
|
||||
screen:expect([[
|
||||
|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{2: }|
|
||||
:ls |
|
||||
1 %a "[No Name]" line 1 |
|
||||
{3:Press ENTER or type command to continue}^ |
|
||||
]])
|
||||
feed('<C-6>')
|
||||
screen:expect([[
|
||||
^ |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
hit ctrl-6 |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('mixing simplified and unsimplified keys can trigger mapping vim-patch:8.2.0916', function()
|
||||
command('set timeoutlen=10')
|
||||
command([[imap ' <C-W>]])
|
||||
command('imap <C-W><C-A> c-a')
|
||||
feed([[a'<C-A>]])
|
||||
expect('c-a')
|
||||
end)
|
||||
|
||||
it('unsimplified mapping works when there was a partial match vim-patch:8.2.4504', function()
|
||||
command('set timeoutlen=10')
|
||||
command('nnoremap <C-J> a')
|
||||
command('nnoremap <NL> x')
|
||||
command('nnoremap <C-J>x <Nop>')
|
||||
funcs.setline(1, 'x')
|
||||
-- CTRL-J b should have trigger the <C-J> mapping and then insert "b"
|
||||
feed('<C-J>b<Esc>')
|
||||
expect('xb')
|
||||
end)
|
||||
|
||||
describe('input non-printable chars', function()
|
||||
after_each(function()
|
||||
os.remove('Xtest-overwrite')
|
||||
|
@ -5,7 +5,8 @@ local ffi = helpers.ffi
|
||||
local eq = helpers.eq
|
||||
local neq = helpers.neq
|
||||
|
||||
local keymap = helpers.cimport("./src/nvim/keymap.h")
|
||||
local keymap = helpers.cimport('./src/nvim/keymap.h')
|
||||
local NULL = helpers.NULL
|
||||
|
||||
describe('keymap.c', function()
|
||||
|
||||
@ -15,12 +16,12 @@ describe('keymap.c', function()
|
||||
|
||||
itp('no keycode', function()
|
||||
srcp[0] = 'abc'
|
||||
eq(0, keymap.find_special_key(srcp, 3, modp, false, false, false))
|
||||
eq(0, keymap.find_special_key(srcp, 3, modp, 0, NULL))
|
||||
end)
|
||||
|
||||
itp('keycode with multiple modifiers', function()
|
||||
srcp[0] = '<C-M-S-A>'
|
||||
neq(0, keymap.find_special_key(srcp, 9, modp, false, false, false))
|
||||
neq(0, keymap.find_special_key(srcp, 9, modp, 0, NULL))
|
||||
neq(0, modp[0])
|
||||
end)
|
||||
|
||||
@ -28,22 +29,22 @@ describe('keymap.c', function()
|
||||
-- Compare other capitalizations to this.
|
||||
srcp[0] = '<C-A>'
|
||||
local all_caps_key =
|
||||
keymap.find_special_key(srcp, 5, modp, false, false, false)
|
||||
keymap.find_special_key(srcp, 5, modp, 0, NULL)
|
||||
local all_caps_mod = modp[0]
|
||||
|
||||
srcp[0] = '<C-a>'
|
||||
eq(all_caps_key,
|
||||
keymap.find_special_key(srcp, 5, modp, false, false, false))
|
||||
keymap.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
eq(all_caps_mod, modp[0])
|
||||
|
||||
srcp[0] = '<c-A>'
|
||||
eq(all_caps_key,
|
||||
keymap.find_special_key(srcp, 5, modp, false, false, false))
|
||||
keymap.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
eq(all_caps_mod, modp[0])
|
||||
|
||||
srcp[0] = '<c-a>'
|
||||
eq(all_caps_key,
|
||||
keymap.find_special_key(srcp, 5, modp, false, false, false))
|
||||
keymap.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
eq(all_caps_mod, modp[0])
|
||||
end)
|
||||
|
||||
@ -51,20 +52,20 @@ describe('keymap.c', function()
|
||||
-- Unescaped with in_string=false
|
||||
srcp[0] = '<C-">'
|
||||
eq(string.byte('"'),
|
||||
keymap.find_special_key(srcp, 5, modp, false, false, false))
|
||||
keymap.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
|
||||
-- Unescaped with in_string=true
|
||||
eq(0, keymap.find_special_key(srcp, 5, modp, false, false, true))
|
||||
eq(0, keymap.find_special_key(srcp, 5, modp, keymap.FSK_IN_STRING, NULL))
|
||||
|
||||
-- Escaped with in_string=false
|
||||
srcp[0] = '<C-\\">'
|
||||
-- Should fail because the key is invalid
|
||||
-- (more than 1 non-modifier character).
|
||||
eq(0, keymap.find_special_key(srcp, 6, modp, false, false, false))
|
||||
eq(0, keymap.find_special_key(srcp, 6, modp, 0, NULL))
|
||||
|
||||
-- Escaped with in_string=true
|
||||
eq(string.byte('"'),
|
||||
keymap.find_special_key(srcp, 6, modp, false, false, true))
|
||||
keymap.find_special_key(srcp, 6, modp, keymap.FSK_IN_STRING, NULL))
|
||||
end)
|
||||
end)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user