diff options
-rw-r--r-- | src/nvim/getchar.c | 10 | ||||
-rw-r--r-- | src/nvim/message.c | 36 | ||||
-rw-r--r-- | src/nvim/testdir/test_mapping.vim | 34 |
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 |