mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 11:28:22 +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