diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-08-12 06:08:07 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-12 06:08:07 +0800 |
commit | 713311be62db5c5453bcd0a7f1dbed8d1d1add15 (patch) | |
tree | ad7e949fcda8d40a01872c398d21f27e15600fe1 | |
parent | 6e0c36ba0e6691401726fd4215f89729138ba82f (diff) | |
download | rneovim-713311be62db5c5453bcd0a7f1dbed8d1d1add15.tar.gz rneovim-713311be62db5c5453bcd0a7f1dbed8d1d1add15.tar.bz2 rneovim-713311be62db5c5453bcd0a7f1dbed8d1d1add15.zip |
vim-patch:9.0.1687: mapset() not properly handling script ID (#24666)
Problem: mapset() not properly handling script ID
Solution: replace_termcodes() may accept a script ID
closes: vim/vim#12699
closes: vim/vim#12697
https://github.com/vim/vim/commit/7e0bae024d4c1673cff31763227ad52b936fa56f
-rw-r--r-- | src/nvim/api/vim.c | 2 | ||||
-rw-r--r-- | src/nvim/keycodes.c | 10 | ||||
-rw-r--r-- | src/nvim/mapping.c | 37 | ||||
-rw-r--r-- | src/nvim/menu.c | 2 | ||||
-rw-r--r-- | src/nvim/usercmd.c | 2 | ||||
-rw-r--r-- | test/old/testdir/test_maparg.vim | 26 |
6 files changed, 52 insertions, 27 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 22fe69e447..4179ae40b8 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -431,7 +431,7 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Bool } char *ptr = NULL; - replace_termcodes(str.data, str.size, &ptr, flags, NULL, CPO_TO_CPO_FLAGS); + replace_termcodes(str.data, str.size, &ptr, 0, flags, NULL, CPO_TO_CPO_FLAGS); return cstr_as_string(ptr); } diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c index 34442ae5c4..6c64a2ca4a 100644 --- a/src/nvim/keycodes.c +++ b/src/nvim/keycodes.c @@ -873,6 +873,7 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag) /// If `*bufp` is non-NULL, it will be used directly, /// and is assumed to be 128 bytes long (enough for transcoding LHS of mapping), /// and will be set to NULL in case of failure. +/// @param[in] sid_arg Script ID to use for <SID>, or 0 to use current_sctx /// @param[in] flags REPTERM_FROM_PART see above /// REPTERM_DO_LT also translate <lt> /// REPTERM_NO_SPECIAL do not accept <key> notation @@ -882,7 +883,8 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag) /// /// @return The same as what `*bufp` is set to. char *replace_termcodes(const char *const from, const size_t from_len, char **const bufp, - const int flags, bool *const did_simplify, const int cpo_flags) + const scid_T sid_arg, const int flags, bool *const did_simplify, + const int cpo_flags) FUNC_ATTR_NONNULL_ARG(1, 3) { ssize_t i; @@ -916,15 +918,15 @@ char *replace_termcodes(const char *const from, const size_t from_len, char **co // 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) { - if (current_sctx.sc_sid <= 0) { + if (sid_arg < 0 || (sid_arg == 0 && current_sctx.sc_sid <= 0)) { emsg(_(e_usingsid)); } else { + const scid_T sid = sid_arg != 0 ? sid_arg : current_sctx.sc_sid; src += 5; result[dlen++] = (char)K_SPECIAL; result[dlen++] = (char)KS_EXTRA; result[dlen++] = KE_SNR; - snprintf(result + dlen, buf_len - dlen, "%" PRId64, - (int64_t)current_sctx.sc_sid); + snprintf(result + dlen, buf_len - dlen, "%" PRId64, (int64_t)sid); dlen += strlen(result + dlen); result[dlen++] = '_'; continue; diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 0cb94e6f5b..f2732184db 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -279,16 +279,16 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs bool did_simplify = false; const int flags = REPTERM_FROM_PART | REPTERM_DO_LT; char *bufarg = lhs_buf; - char *replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, flags, &did_simplify, - cpo_flags); + char *replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, 0, + flags, &did_simplify, cpo_flags); if (replaced == NULL) { return false; } mapargs->lhs_len = strlen(replaced); xstrlcpy(mapargs->lhs, replaced, sizeof(mapargs->lhs)); if (did_simplify) { - replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, flags | REPTERM_NO_SIMPLIFY, - NULL, cpo_flags); + replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, 0, + flags | REPTERM_NO_SIMPLIFY, NULL, cpo_flags); if (replaced == NULL) { return false; } @@ -298,14 +298,15 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs mapargs->alt_lhs_len = 0; } - set_maparg_rhs(orig_rhs, orig_rhs_len, rhs_lua, cpo_flags, mapargs); + set_maparg_rhs(orig_rhs, orig_rhs_len, rhs_lua, 0, cpo_flags, mapargs); return true; } /// @see set_maparg_lhs_rhs static void set_maparg_rhs(const char *const orig_rhs, const size_t orig_rhs_len, - const LuaRef rhs_lua, const int cpo_flags, MapArguments *const mapargs) + const LuaRef rhs_lua, const scid_T sid, const int cpo_flags, + MapArguments *const mapargs) { mapargs->rhs_lua = rhs_lua; @@ -319,8 +320,8 @@ static void set_maparg_rhs(const char *const orig_rhs, const size_t orig_rhs_len mapargs->rhs_is_noop = true; } else { char *rhs_buf = NULL; - char *replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf, REPTERM_DO_LT, NULL, - cpo_flags); + char *replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf, sid, + REPTERM_DO_LT, NULL, cpo_flags); mapargs->rhs_len = strlen(replaced); // NB: replace_termcodes may produce an empty string even if orig_rhs is non-empty // (e.g. a single ^V, see :h map-empty-rhs) @@ -1079,9 +1080,8 @@ bool map_to_exists(const char *const str, const char *const modechars, const boo int retval; char *buf = NULL; - const char *const rhs = replace_termcodes(str, strlen(str), - &buf, REPTERM_DO_LT, - NULL, CPO_TO_CPO_FLAGS); + const char *const rhs = replace_termcodes(str, strlen(str), &buf, 0, + REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); #define MAPMODE(mode, modechars, chr, modeflags) \ do { \ @@ -1657,7 +1657,7 @@ char *eval_map_expr(mapblock_T *mp, int c) char *res = NULL; if (replace_keycodes) { - replace_termcodes(p, strlen(p), &res, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); + replace_termcodes(p, strlen(p), &res, 0, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); } else { // Escape K_SPECIAL in the result to be able to use the string as typeahead. res = vim_strsave_escape_ks(p); @@ -2157,8 +2157,8 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) const int flags = REPTERM_FROM_PART | REPTERM_DO_LT; const int mode = get_map_mode((char **)&which, 0); - char *keys_simplified = replace_termcodes(keys, strlen(keys), &keys_buf, flags, &did_simplify, - CPO_TO_CPO_FLAGS); + char *keys_simplified = replace_termcodes(keys, strlen(keys), &keys_buf, 0, + flags, &did_simplify, CPO_TO_CPO_FLAGS); mapblock_T *mp = NULL; int buffer_local; LuaRef rhs_lua; @@ -2167,10 +2167,8 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) if (did_simplify) { // When the lhs is being simplified the not-simplified keys are // preferred for printing, like in do_map(). - (void)replace_termcodes(keys, - strlen(keys), - &alt_keys_buf, flags | REPTERM_NO_SIMPLIFY, NULL, - CPO_TO_CPO_FLAGS); + (void)replace_termcodes(keys, strlen(keys), &alt_keys_buf, 0, + flags | REPTERM_NO_SIMPLIFY, NULL, CPO_TO_CPO_FLAGS); rhs = check_map(alt_keys_buf, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua); } @@ -2252,12 +2250,13 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) .replace_keycodes = tv_dict_get_number(d, "replace_keycodes") != 0, .desc = tv_dict_get_string(d, "desc", false), }; - set_maparg_rhs(orig_rhs, strlen(orig_rhs), rhs_lua, CPO_TO_CPO_FLAGS, &args); scid_T sid = (scid_T)tv_dict_get_number(d, "sid"); linenr_T lnum = (linenr_T)tv_dict_get_number(d, "lnum"); bool buffer = tv_dict_get_number(d, "buffer") != 0; // mode from the dict is not used + set_maparg_rhs(orig_rhs, strlen(orig_rhs), rhs_lua, sid, CPO_TO_CPO_FLAGS, &args); + mapblock_T **map_table = buffer ? curbuf->b_maphash : maphash; mapblock_T **abbr_table = buffer ? &curbuf->b_first_abbr : &first_abbr; diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 898e3ddd27..1d35c97b39 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -232,7 +232,7 @@ void ex_menu(exarg_T *eap) map_buf = NULL; // Menu tips are plain text. } else { map_buf = NULL; - map_to = replace_termcodes(map_to, strlen(map_to), &map_buf, + map_to = replace_termcodes(map_to, strlen(map_to), &map_buf, 0, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); } menuarg.modes = modes; diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c index 41a8ad2d97..65720342ce 100644 --- a/src/nvim/usercmd.c +++ b/src/nvim/usercmd.c @@ -876,7 +876,7 @@ int uc_add_command(char *name, size_t name_len, const char *rep, uint32_t argt, char *rep_buf = NULL; garray_T *gap; - replace_termcodes(rep, strlen(rep), &rep_buf, 0, NULL, CPO_TO_CPO_FLAGS); + replace_termcodes(rep, strlen(rep), &rep_buf, 0, 0, NULL, CPO_TO_CPO_FLAGS); if (rep_buf == NULL) { // Can't replace termcodes - try using the string as is rep_buf = xstrdup(rep); diff --git a/test/old/testdir/test_maparg.vim b/test/old/testdir/test_maparg.vim index 12670671dd..46b65d45cf 100644 --- a/test/old/testdir/test_maparg.vim +++ b/test/old/testdir/test_maparg.vim @@ -322,8 +322,32 @@ func Test_map_restore() nunmap <C-B> endfunc -" Test restoring the script context of a mapping +" Test restoring an <SID> mapping func Test_map_restore_sid() + func RestoreMap() + const d = maparg('<CR>', 'i', v:false, v:true) + iunmap <buffer> <CR> + call mapset('i', v:false, d) + endfunc + + let mapscript =<< trim [CODE] + inoremap <silent><buffer> <SID>Return <C-R>=42<CR> + inoremap <script><buffer> <CR> <CR><SID>Return + [CODE] + call writefile(mapscript, 'Xmapscript', 'D') + + new + source Xmapscript + inoremap <buffer> <C-B> <Cmd>call RestoreMap()<CR> + call feedkeys("i\<CR>\<C-B>\<CR>", 'xt') + call assert_equal(['', '42', '42'], getline(1, '$')) + + bwipe! + delfunc RestoreMap +endfunc + +" Test restoring a mapping with a negative script ID +func Test_map_restore_negative_sid() let after =<< trim [CODE] call assert_equal("\tLast set from --cmd argument", \ execute('verbose nmap ,n')->trim()->split("\n")[-1]) |