mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.1.2145: cannot map <C-H> when modifyOtherKeys is enabled
Problem: Cannot map <C-H> when modifyOtherKeys is enabled.
Solution: Add the <C-H> mapping twice, both with modifier and as 0x08. Use
only the first one when modifyOtherKeys has been detected.
459fd785e4
Add REPTERM_NO_SPECIAL instead of REPTERM_SPECIAL because the meaning of
"special" is different between Vim and Nvim.
Omit seenModifyOtherKeys as Nvim supports attaching multiple UIs.
Omit tests as they send terminal codes.
Keep the behavior of API functions.
This commit is contained in:
parent
188537efb3
commit
dde4f09f51
@ -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
|
||||
|
@ -4965,7 +4965,7 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
|
||||
|
||||
// Special key, e.g.: "\<C-W>"
|
||||
case '<':
|
||||
extra = trans_special((const char_u **)&p, STRLEN(p), name, true, true);
|
||||
extra = trans_special((const char_u **)&p, STRLEN(p), name, true, true, true, NULL);
|
||||
if (extra != 0) {
|
||||
name += extra;
|
||||
if (name >= rettv->vval.v_string + len) {
|
||||
|
@ -5684,7 +5684,7 @@ 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,
|
||||
keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, REPTERM_FROM_PART | REPTERM_DO_LT, NULL,
|
||||
CPO_TO_CPO_FLAGS);
|
||||
rhs = check_map(keys, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua);
|
||||
xfree(keys_buf);
|
||||
|
@ -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);
|
||||
|
@ -2711,11 +2711,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 +2726,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 +2754,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 +2773,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 +2908,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 +2937,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 +2947,325 @@ 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;
|
||||
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_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 = 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;
|
||||
}
|
||||
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
|
||||
showmap(mp, map_table != maphash);
|
||||
did_it = true;
|
||||
} else if (n != len) { // new entry is ambiguous
|
||||
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
|
||||
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 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 = did_simplify && keyround == 1;
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
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 = did_simplify && keyround == 1;
|
||||
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 +3634,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
|
||||
|
@ -570,16 +570,18 @@ char_u *get_special_key_name(int c, int modifiers)
|
||||
// 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] simplify simplify <C-H>, etc.
|
||||
/// @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 bool keycode, const bool in_string, const bool simplify,
|
||||
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, keycode, false, in_string, simplify,
|
||||
did_simplify);
|
||||
if (key == 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -626,11 +628,14 @@ unsigned int special_to_buf(int key, int modifiers, bool keycode, char_u *dst)
|
||||
/// @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] simplify simplify <C-H>, etc.
|
||||
/// @param[out] did_simplify 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 bool keycode, const bool keep_x_key, const bool in_string,
|
||||
const bool simplify, 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;
|
||||
@ -748,7 +753,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, simplify, did_simplify);
|
||||
}
|
||||
|
||||
*modp = modifiers;
|
||||
@ -762,7 +767,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 +781,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 == 0) { // <C-@> is <Nul>
|
||||
key = K_ZERO;
|
||||
}
|
||||
if (did_simplify != NULL) {
|
||||
*did_simplify = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -853,34 +865,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 +897,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 +910,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 +925,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 +945,15 @@ 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, true, false,
|
||||
(flags & REPTERM_NO_SIMPLIFY) == 0, 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 +993,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;
|
||||
|
@ -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;
|
||||
|
@ -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,7 @@ 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, true, true, false, true, NULL);
|
||||
if (modifiers) { // can't handle modifiers here
|
||||
key = 0;
|
||||
}
|
||||
|
@ -239,8 +239,7 @@ size_t input_enqueue(String keys)
|
||||
// K_SPECIAL(0x80).
|
||||
uint8_t buf[19] = { 0 };
|
||||
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, true, false, true, NULL);
|
||||
|
||||
if (new_size) {
|
||||
new_size = handle_mouse_event(&ptr, buf, new_size);
|
||||
|
@ -318,4 +318,10 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext()
|
||||
#define REPLACE_CR_NCHAR (-1)
|
||||
#define REPLACE_NL_NCHAR (-2)
|
||||
|
||||
// Flags for replace_termcodes()
|
||||
#define REPTERM_FROM_PART 1
|
||||
#define REPTERM_DO_LT 2
|
||||
#define REPTERM_NO_SPECIAL 4
|
||||
#define REPTERM_NO_SIMPLIFY 8
|
||||
|
||||
#endif // NVIM_VIM_H
|
||||
|
@ -1817,9 +1817,8 @@ 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));
|
||||
const size_t special_len = trans_special((const char_u **)&p, (size_t)(e - p),
|
||||
(char_u *)v_p, true, true, true, NULL);
|
||||
if (special_len != 0) {
|
||||
v_p += special_len;
|
||||
} else {
|
||||
|
@ -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()
|
||||
|
@ -6,6 +6,7 @@ local eq = helpers.eq
|
||||
local neq = helpers.neq
|
||||
|
||||
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, false, false, false, false, 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, false, false, false, false, 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, false, false, false, false, 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, false, false, false, false, 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, false, false, false, false, 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, false, false, false, false, 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, false, false, false, false, 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, false, false, true, false, 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, false, false, false, false, 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, false, false, true, false, NULL))
|
||||
end)
|
||||
end)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user