diff options
author | James McCoy <jamessan@jamessan.com> | 2017-04-15 13:54:40 -0400 |
---|---|---|
committer | James McCoy <jamessan@jamessan.com> | 2017-04-19 22:26:30 -0400 |
commit | cb02137dfac7357650a2e9cc32acb66326e59058 (patch) | |
tree | e196f6fa8b9c03009f383349c86b5ca79acf7199 | |
parent | ac05c8585c0837dd47568335486b7d815d15dec4 (diff) | |
download | rneovim-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.c | 2 | ||||
-rw-r--r-- | src/nvim/keymap.c | 40 | ||||
-rw-r--r-- | src/nvim/option.c | 2 | ||||
-rw-r--r-- | src/nvim/os/input.c | 3 | ||||
-rw-r--r-- | src/nvim/testdir/test_mapping.vim | 8 | ||||
-rw-r--r-- | src/nvim/version.c | 2 |
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 |