aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames McCoy <jamessan@jamessan.com>2017-04-15 13:54:40 -0400
committerJames McCoy <jamessan@jamessan.com>2017-04-19 22:26:30 -0400
commitcb02137dfac7357650a2e9cc32acb66326e59058 (patch)
treee196f6fa8b9c03009f383349c86b5ca79acf7199
parentac05c8585c0837dd47568335486b7d815d15dec4 (diff)
downloadrneovim-cb02137dfac7357650a2e9cc32acb66326e59058.tar.gz
rneovim-cb02137dfac7357650a2e9cc32acb66326e59058.tar.bz2
rneovim-cb02137dfac7357650a2e9cc32acb66326e59058.zip
vim-patch:7.4.2209
Problem: Cannot map <M-">. (Stephen Riehm) Solution: Solve the memory access problem in another way. (Dominique Pelle) Allow for using <M-\"> in a string. https://github.com/vim/vim/commit/35a4cfa200917dd171b1fff3cd5b6cee9add673d
-rw-r--r--src/nvim/eval.c2
-rw-r--r--src/nvim/keymap.c40
-rw-r--r--src/nvim/option.c2
-rw-r--r--src/nvim/os/input.c3
-rw-r--r--src/nvim/testdir/test_mapping.vim8
-rw-r--r--src/nvim/version.c2
6 files changed, 37 insertions, 20 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 60c4e725b7..9f56d8db0c 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -4764,7 +4764,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);
+ extra = trans_special((const char_u **)&p, STRLEN(p), name, true, true);
if (extra != 0) {
name += extra;
break;
diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c
index 72b0d0aa40..9838b63a6b 100644
--- a/src/nvim/keymap.c
+++ b/src/nvim/keymap.c
@@ -490,17 +490,19 @@ char_u *get_special_key_name(int c, int modifiers)
/// @param[out] dst Location where translation result will be kept. Must have
/// at least six bytes.
/// @param[in] keycode Prefer key code, e.g. K_DEL in place of DEL.
+/// @param[in] in_string Inside a double quoted string
///
/// @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)
+ char_u *const dst, const bool keycode,
+ const bool in_string)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int modifiers = 0;
int key;
unsigned int dlen = 0;
- key = find_special_key(srcp, src_len, &modifiers, keycode, false);
+ key = find_special_key(srcp, src_len, &modifiers, keycode, false, in_string);
if (key == 0) {
return 0;
}
@@ -536,10 +538,12 @@ unsigned int trans_special(const char_u **srcp, const size_t src_len,
/// @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
///
/// @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 keycode, const bool keep_x_key,
+ const bool in_string)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
const char_u *last_dash;
@@ -573,10 +577,14 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
} else {
l = 1;
}
- if (end - bp > l && bp[l] != '"' && bp[l + 1] == '>') {
- // Anything accepted, like <C-?>, except <C-">, because the "
- // ends the string.
+ // 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[2] == '>') {
bp += l;
+ } else if (end - bp > 2 && in_string && bp[1] == '\\'
+ && bp[2] == '"' && bp[3] == '>') {
+ bp += 2;
}
}
}
@@ -612,18 +620,17 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
vim_str2nr(last_dash + 6, NULL, NULL, STR2NR_ALL, NULL, &n, 0);
key = (int)n;
} else {
- /*
- * Modifier with single letter, or special key name.
- */
- if (has_mbyte) {
- l = mb_ptr2len(last_dash + 1);
- } else {
- l = 1;
+ int off = 1;
+
+ // Modifier with single letter, or special key name.
+ if (in_string && last_dash[1] == '\\' && last_dash[2] == '"') {
+ off = 2;
}
+ l = mb_ptr2len(last_dash + 1);
if (modifiers != 0 && last_dash[l + 1] == '>') {
- key = PTR2CHAR(last_dash + 1);
+ key = PTR2CHAR(last_dash + off);
} else {
- key = get_special_key_code(last_dash + 1);
+ key = get_special_key_code(last_dash + off);
if (!keep_x_key) {
key = handle_x_keys(key);
}
@@ -828,7 +835,8 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len,
}
}
- slen = trans_special(&src, (size_t) (end - src) + 1, result + dlen, true);
+ slen = trans_special(&src, (size_t)(end - src) + 1, result + dlen, true,
+ true);
if (slen) {
dlen += slen;
continue;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 0070a0056d..8748406ba4 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -4818,7 +4818,7 @@ int find_key_option_len(const char_u *arg, size_t len)
} else {
arg--; // put arg at the '<'
modifiers = 0;
- key = find_special_key(&arg, len + 1, &modifiers, true, true);
+ key = find_special_key(&arg, len + 1, &modifiers, true, true, false);
if (modifiers) { // can't handle modifiers here
key = 0;
}
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 5f0f2ec677..1fa1f52806 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -182,7 +182,8 @@ size_t input_enqueue(String keys)
while (rbuffer_space(input_buffer) >= 6 && ptr < end) {
uint8_t buf[6] = { 0 };
unsigned int new_size
- = trans_special((const uint8_t **)&ptr, (size_t)(end - ptr), buf, true);
+ = trans_special((const uint8_t **)&ptr, (size_t)(end - ptr), buf, true,
+ true);
if (new_size) {
new_size = handle_mouse_event(&ptr, buf, new_size);
diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim
index 6b313ff54f..7f93ddd56e 100644
--- a/src/nvim/testdir/test_mapping.vim
+++ b/src/nvim/testdir/test_mapping.vim
@@ -150,3 +150,11 @@ func Test_break_undo()
call assert_equal('new line here', getline(line('$') - 1))
set nomodified
endfunc
+
+func Test_map_meta_quotes()
+ imap <M-"> foo
+ call feedkeys("Go-\<M-\">-\<Esc>", "xt")
+ call assert_equal("-foo-", getline('$'))
+ set nomodified
+ iunmap <M-">
+endfunc
diff --git a/src/nvim/version.c b/src/nvim/version.c
index cd904da573..f7a78a15f9 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -232,7 +232,7 @@ static const int included_patches[] = {
2212,
// 2211 NA
// 2210 NA
- // 2209,
+ 2209,
2208,
// 2207 NA
// 2206 NA