aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/getchar.c10
-rw-r--r--src/nvim/message.c36
-rw-r--r--src/nvim/testdir/test_mapping.vim34
3 files changed, 59 insertions, 21 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index df9297dc0b..374fa11b23 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -2902,7 +2902,8 @@ void set_maparg_lhs_rhs(const char_u *const orig_lhs, const size_t orig_lhs_len,
replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf,
REPTERM_DO_LT | REPTERM_NO_SIMPLIFY, NULL, cpo_flags);
mapargs->rhs_len = STRLEN(replaced);
- mapargs->rhs_is_noop = false;
+ // XXX: even when orig_rhs is non-empty, replace_termcodes may produce an empty string.
+ mapargs->rhs_is_noop = orig_rhs[0] != NUL && mapargs->rhs_len == 0;
mapargs->rhs = xcalloc(mapargs->rhs_len + 1, sizeof(char_u));
STRLCPY(mapargs->rhs, replaced, mapargs->rhs_len + 1);
}
@@ -3765,12 +3766,7 @@ static void showmap(mapblock_T *mp, bool local)
} else if (mp->m_str[0] == NUL) {
msg_puts_attr("<Nop>", HL_ATTR(HLF_8));
} else {
- // Remove escaping of K_SPECIAL, because "m_str" is in a format to be used
- // as typeahead.
- char_u *s = vim_strsave(mp->m_str);
- vim_unescape_ks(s);
- msg_outtrans_special(s, false, 0);
- xfree(s);
+ msg_outtrans_special(mp->m_str, false, 0);
}
if (mp->m_desc != NULL) {
diff --git a/src/nvim/message.c b/src/nvim/message.c
index f0ef4e1d4f..cdcbcc6700 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1671,11 +1671,13 @@ const char *str2special(const char **const sp, const bool replace_spaces, const
{
static char buf[7];
- // Try to un-escape a multi-byte character. Return the un-escaped
- // string if it is a multi-byte character.
- const char *const p = mb_unescape(sp);
- if (p != NULL) {
- return p;
+ {
+ // Try to un-escape a multi-byte character. Return the un-escaped
+ // string if it is a multi-byte character.
+ const char *const p = mb_unescape(sp);
+ if (p != NULL) {
+ return p;
+ }
}
const char *str = *sp;
@@ -1698,18 +1700,24 @@ const char *str2special(const char **const sp, const bool replace_spaces, const
}
if (!IS_SPECIAL(c)) {
- const int len = utf_ptr2len((const char_u *)str);
+ *sp = str;
+ // Try to un-escape a multi-byte character after modifiers.
+ const char *p = mb_unescape(sp);
- // Check for an illegal byte.
- if (MB_BYTE2LEN((uint8_t)(*str)) > len) {
- transchar_nonprint(curbuf, (char_u *)buf, c);
- *sp = str + 1;
- return buf;
+ if (p == NULL) {
+ const int len = utf_ptr2len((const char_u *)str);
+ // Check for an illegal byte.
+ if (MB_BYTE2LEN((uint8_t)(*str)) > len) {
+ transchar_nonprint(curbuf, (char_u *)buf, c);
+ *sp = str + 1;
+ return buf;
+ }
+ *sp = str + len;
+ p = str;
}
- // Since 'special' is TRUE the multi-byte character 'c' will be
+ // Since 'special' is true the multi-byte character 'c' will be
// processed by get_special_key_name().
- c = utf_ptr2char((const char_u *)str);
- *sp = str + len;
+ c = utf_ptr2char((const char_u *)p);
} else {
*sp = str + 1;
}
diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim
index 752b1700d0..b5158295b4 100644
--- a/src/nvim/testdir/test_mapping.vim
+++ b/src/nvim/testdir/test_mapping.vim
@@ -464,6 +464,40 @@ func Test_list_mappings()
call assert_equal(['n ,n <Nop>'],
\ execute('nmap ,n')->trim()->split("\n"))
+ " verbose map
+ call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
+ \ execute('verbose map ,n')->trim()->split("\n")[1])
+
+ " character with K_SPECIAL byte in rhs
+ nmap foo …
+ call assert_equal(['n foo …'],
+ \ execute('nmap foo')->trim()->split("\n"))
+
+ " modified character with K_SPECIAL byte in rhs
+ nmap foo <M-…>
+ call assert_equal(['n foo <M-…>'],
+ \ execute('nmap foo')->trim()->split("\n"))
+
+ " character with K_SPECIAL byte in lhs
+ nmap … foo
+ call assert_equal(['n … foo'],
+ \ execute('nmap …')->trim()->split("\n"))
+
+ " modified character with K_SPECIAL byte in lhs
+ nmap <M-…> foo
+ call assert_equal(['n <M-…> foo'],
+ \ execute('nmap <M-…>')->trim()->split("\n"))
+
+ " map to CTRL-V
+ exe "nmap ,k \<C-V>"
+ call assert_equal(['n ,k <Nop>'],
+ \ execute('nmap ,k')->trim()->split("\n"))
+
+ " map with space at the beginning
+ exe "nmap \<C-V> w <Nop>"
+ call assert_equal(['n <Space>w <Nop>'],
+ \ execute("nmap \<C-V> w")->trim()->split("\n"))
+
nmapclear
endfunc