mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	vim-patch:9.0.1687: mapset() not properly handling script ID
Problem: mapset() not properly handling script ID
Solution: replace_termcodes() may accept a script ID
closes: vim/vim#12699
closes: vim/vim#12697
7e0bae024d
			
			
This commit is contained in:
		| @@ -431,7 +431,7 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Bool | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   char *ptr = NULL; |   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); |   return cstr_as_string(ptr); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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, | ///                    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 is assumed to be 128 bytes long (enough for transcoding LHS of mapping), | ||||||
| ///                    and will be set to NULL in case of failure. | ///                    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 | /// @param[in]  flags  REPTERM_FROM_PART    see above | ||||||
| ///                    REPTERM_DO_LT        also translate <lt> | ///                    REPTERM_DO_LT        also translate <lt> | ||||||
| ///                    REPTERM_NO_SPECIAL   do not accept <key> notation | ///                    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. | /// @return  The same as what `*bufp` is set to. | ||||||
| char *replace_termcodes(const char *const from, const size_t from_len, char **const bufp, | 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) |   FUNC_ATTR_NONNULL_ARG(1, 3) | ||||||
| { | { | ||||||
|   ssize_t i; |   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> _. |       // Replace <SID> by K_SNR <script-nr> _. | ||||||
|       // (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14) |       // (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14) | ||||||
|       if (end - src >= 4 && STRNICMP(src, "<SID>", 5) == 0) { |       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)); |           emsg(_(e_usingsid)); | ||||||
|         } else { |         } else { | ||||||
|  |           const scid_T sid = sid_arg != 0 ? sid_arg : current_sctx.sc_sid; | ||||||
|           src += 5; |           src += 5; | ||||||
|           result[dlen++] = (char)K_SPECIAL; |           result[dlen++] = (char)K_SPECIAL; | ||||||
|           result[dlen++] = (char)KS_EXTRA; |           result[dlen++] = (char)KS_EXTRA; | ||||||
|           result[dlen++] = KE_SNR; |           result[dlen++] = KE_SNR; | ||||||
|           snprintf(result + dlen, buf_len - dlen, "%" PRId64, |           snprintf(result + dlen, buf_len - dlen, "%" PRId64, (int64_t)sid); | ||||||
|                    (int64_t)current_sctx.sc_sid); |  | ||||||
|           dlen += strlen(result + dlen); |           dlen += strlen(result + dlen); | ||||||
|           result[dlen++] = '_'; |           result[dlen++] = '_'; | ||||||
|           continue; |           continue; | ||||||
|   | |||||||
| @@ -279,16 +279,16 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs | |||||||
|   bool did_simplify = false; |   bool did_simplify = false; | ||||||
|   const int flags = REPTERM_FROM_PART | REPTERM_DO_LT; |   const int flags = REPTERM_FROM_PART | REPTERM_DO_LT; | ||||||
|   char *bufarg = lhs_buf; |   char *bufarg = lhs_buf; | ||||||
|   char *replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, flags, &did_simplify, |   char *replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, 0, | ||||||
|                                      cpo_flags); |                                      flags, &did_simplify, cpo_flags); | ||||||
|   if (replaced == NULL) { |   if (replaced == NULL) { | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|   mapargs->lhs_len = strlen(replaced); |   mapargs->lhs_len = strlen(replaced); | ||||||
|   xstrlcpy(mapargs->lhs, replaced, sizeof(mapargs->lhs)); |   xstrlcpy(mapargs->lhs, replaced, sizeof(mapargs->lhs)); | ||||||
|   if (did_simplify) { |   if (did_simplify) { | ||||||
|     replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, flags | REPTERM_NO_SIMPLIFY, |     replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, 0, | ||||||
|                                  NULL, cpo_flags); |                                  flags | REPTERM_NO_SIMPLIFY, NULL, cpo_flags); | ||||||
|     if (replaced == NULL) { |     if (replaced == NULL) { | ||||||
|       return false; |       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; |     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; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @see set_maparg_lhs_rhs | /// @see set_maparg_lhs_rhs | ||||||
| static void set_maparg_rhs(const char *const orig_rhs, const size_t orig_rhs_len, | 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; |   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; |       mapargs->rhs_is_noop = true; | ||||||
|     } else { |     } else { | ||||||
|       char *rhs_buf = NULL; |       char *rhs_buf = NULL; | ||||||
|       char *replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf, REPTERM_DO_LT, NULL, |       char *replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf, sid, | ||||||
|                                          cpo_flags); |                                          REPTERM_DO_LT, NULL, cpo_flags); | ||||||
|       mapargs->rhs_len = strlen(replaced); |       mapargs->rhs_len = strlen(replaced); | ||||||
|       // NB: replace_termcodes may produce an empty string even if orig_rhs is non-empty |       // 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) |       // (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; |   int retval; | ||||||
|  |  | ||||||
|   char *buf = NULL; |   char *buf = NULL; | ||||||
|   const char *const rhs = replace_termcodes(str, strlen(str), |   const char *const rhs = replace_termcodes(str, strlen(str), &buf, 0, | ||||||
|                                             &buf, REPTERM_DO_LT, |                                             REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); | ||||||
|                                             NULL, CPO_TO_CPO_FLAGS); |  | ||||||
|  |  | ||||||
| #define MAPMODE(mode, modechars, chr, modeflags) \ | #define MAPMODE(mode, modechars, chr, modeflags) \ | ||||||
|   do { \ |   do { \ | ||||||
| @@ -1657,7 +1657,7 @@ char *eval_map_expr(mapblock_T *mp, int c) | |||||||
|   char *res = NULL; |   char *res = NULL; | ||||||
|  |  | ||||||
|   if (replace_keycodes) { |   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 { |   } else { | ||||||
|     // Escape K_SPECIAL in the result to be able to use the string as typeahead. |     // Escape K_SPECIAL in the result to be able to use the string as typeahead. | ||||||
|     res = vim_strsave_escape_ks(p); |     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 flags = REPTERM_FROM_PART | REPTERM_DO_LT; | ||||||
|   const int mode = get_map_mode((char **)&which, 0); |   const int mode = get_map_mode((char **)&which, 0); | ||||||
|  |  | ||||||
|   char *keys_simplified = replace_termcodes(keys, strlen(keys), &keys_buf, flags, &did_simplify, |   char *keys_simplified = replace_termcodes(keys, strlen(keys), &keys_buf, 0, | ||||||
|                                             CPO_TO_CPO_FLAGS); |                                             flags, &did_simplify, CPO_TO_CPO_FLAGS); | ||||||
|   mapblock_T *mp = NULL; |   mapblock_T *mp = NULL; | ||||||
|   int buffer_local; |   int buffer_local; | ||||||
|   LuaRef rhs_lua; |   LuaRef rhs_lua; | ||||||
| @@ -2167,10 +2167,8 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) | |||||||
|   if (did_simplify) { |   if (did_simplify) { | ||||||
|     // When the lhs is being simplified the not-simplified keys are |     // When the lhs is being simplified the not-simplified keys are | ||||||
|     // preferred for printing, like in do_map(). |     // preferred for printing, like in do_map(). | ||||||
|     (void)replace_termcodes(keys, |     (void)replace_termcodes(keys, strlen(keys), &alt_keys_buf, 0, | ||||||
|                             strlen(keys), |                             flags | REPTERM_NO_SIMPLIFY, NULL, CPO_TO_CPO_FLAGS); | ||||||
|                             &alt_keys_buf, flags | REPTERM_NO_SIMPLIFY, NULL, |  | ||||||
|                             CPO_TO_CPO_FLAGS); |  | ||||||
|     rhs = check_map(alt_keys_buf, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua); |     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, |     .replace_keycodes = tv_dict_get_number(d, "replace_keycodes") != 0, | ||||||
|     .desc = tv_dict_get_string(d, "desc", false), |     .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"); |   scid_T sid = (scid_T)tv_dict_get_number(d, "sid"); | ||||||
|   linenr_T lnum = (linenr_T)tv_dict_get_number(d, "lnum"); |   linenr_T lnum = (linenr_T)tv_dict_get_number(d, "lnum"); | ||||||
|   bool buffer = tv_dict_get_number(d, "buffer") != 0; |   bool buffer = tv_dict_get_number(d, "buffer") != 0; | ||||||
|   // mode from the dict is not used |   // 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 **map_table = buffer ? curbuf->b_maphash : maphash; | ||||||
|   mapblock_T **abbr_table = buffer ? &curbuf->b_first_abbr : &first_abbr; |   mapblock_T **abbr_table = buffer ? &curbuf->b_first_abbr : &first_abbr; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -232,7 +232,7 @@ void ex_menu(exarg_T *eap) | |||||||
|       map_buf = NULL;  // Menu tips are plain text. |       map_buf = NULL;  // Menu tips are plain text. | ||||||
|     } else { |     } else { | ||||||
|       map_buf = NULL; |       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); |                                  REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); | ||||||
|     } |     } | ||||||
|     menuarg.modes = modes; |     menuarg.modes = modes; | ||||||
|   | |||||||
| @@ -876,7 +876,7 @@ int uc_add_command(char *name, size_t name_len, const char *rep, uint32_t argt, | |||||||
|   char *rep_buf = NULL; |   char *rep_buf = NULL; | ||||||
|   garray_T *gap; |   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) { |   if (rep_buf == NULL) { | ||||||
|     // Can't replace termcodes - try using the string as is |     // Can't replace termcodes - try using the string as is | ||||||
|     rep_buf = xstrdup(rep); |     rep_buf = xstrdup(rep); | ||||||
|   | |||||||
| @@ -322,8 +322,32 @@ func Test_map_restore() | |||||||
|   nunmap <C-B> |   nunmap <C-B> | ||||||
| endfunc | endfunc | ||||||
|  |  | ||||||
| " Test restoring the script context of a mapping | " Test restoring an <SID> mapping | ||||||
| func Test_map_restore_sid() | 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] |   let after =<< trim [CODE] | ||||||
|     call assert_equal("\tLast set from --cmd argument", |     call assert_equal("\tLast set from --cmd argument", | ||||||
|           \ execute('verbose nmap ,n')->trim()->split("\n")[-1]) |           \ execute('verbose nmap ,n')->trim()->split("\n")[-1]) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 zeertzjq
					zeertzjq