vim-patch:8.2.0807: cannot easily restore a mapping

Problem:    Cannot easily restore a mapping.
Solution:   Add mapset().
4c9243f9fb

Use MapArgument to reduce number of arguments of map_add().

N/A patches for version.c:

vim-patch:8.2.0809: build failure with small features

Problem:    Build failure with small features. (Tony Mechelynck)
Solution:   Move "expr" inside #ifdef.
5a80f8ad5d
This commit is contained in:
zeertzjq
2022-08-01 12:27:37 +08:00
parent db6e93c48d
commit 083865071b
4 changed files with 187 additions and 58 deletions

View File

@@ -295,6 +295,8 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]])
rhs of mapping {name} in mode {mode}
mapcheck({name} [, {mode} [, {abbr}]])
String check for mappings matching {name}
mapset({name}, {mode}, {abbr}, {dict}
none restore mapping from |maparg()| result
match({expr}, {pat} [, {start} [, {count}]])
Number position where {pat} matches in {expr}
matchadd({group}, {pattern} [, {priority} [, {id} [, {dict}]]])
@@ -4716,6 +4718,7 @@ map({expr1}, {expr2}) *map()*
Can also be used as a |method|: >
mylist->map(expr2)
maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
When {dict} is omitted or zero: Return the rhs of mapping
{name} in mode {mode}. The returned String has special
@@ -4767,6 +4770,10 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
"lnum" The line number in "sid", zero if unknown.
"nowait" Do not wait for other, longer mappings.
(|:map-<nowait>|).
"simplified"
The dictionary can be used to restore a mapping with
|mapset()|.
The mappings local to the current buffer are checked first,
then the global mappings.
@@ -4813,6 +4820,18 @@ mapcheck({name} [, {mode} [, {abbr}]]) *mapcheck()*
Can also be used as a |method|: >
GetKey()->mapcheck('n')
mapset({mode}, {abbr}, {dict}) *mapset()*
Restore a mapping from a dictionary returned by |maparg()|.
{name}, {mode} and {abbr} should be the same as for the call
to |maparg()|.
{mode} is used to define the mode in which the mapping is set,
not the "mode" entry in {dict}.
Example for saving and restoring a mapping: >
let save_map = maparg('K', 'n', 0, 1)
nnoremap K somethingelse
...
call mapset('n', 0, save_map)
<
match({expr}, {pat} [, {start} [, {count}]]) *match()*
When {expr} is a |List| then this returns the index of the
first item where {pat} matches. Each item is used as a

View File

@@ -250,6 +250,7 @@ return {
map={args=2, base=1},
maparg={args={1, 4}, base=1},
mapcheck={args={1, 3}, base=1},
mapset={args=3, base=1},
match={args={2, 4}, base=1},
matchadd={args={2, 5}, base=1},
matchaddpos={args={2, 5}, base=1},

View File

@@ -428,6 +428,63 @@ static int str_to_mapargs(const char_u *strargs, bool is_unmap, MapArguments *ma
return 0;
}
/// @param sid -1 to use current_sctx
static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table, const char_u *keys,
MapArguments *args, int noremap, int mode, bool is_abbr, scid_T sid,
linenr_T lnum, bool simplified)
{
mapblock_T *mp = xcalloc(1, sizeof(mapblock_T));
// If CTRL-C has been mapped, don't always use it for Interrupting.
if (*keys == Ctrl_C) {
if (map_table == buf->b_maphash) {
buf->b_mapped_ctrl_c |= mode;
} else {
mapped_ctrl_c |= mode;
}
}
mp->m_keys = vim_strsave(keys);
mp->m_str = args->rhs;
mp->m_orig_str = args->orig_rhs;
mp->m_luaref = args->rhs_lua;
if (!simplified) {
args->rhs = NULL;
args->orig_rhs = NULL;
args->rhs_lua = LUA_NOREF;
}
mp->m_keylen = (int)STRLEN(mp->m_keys);
mp->m_noremap = noremap;
mp->m_nowait = args->nowait;
mp->m_silent = args->silent;
mp->m_mode = mode;
mp->m_simplified = simplified;
mp->m_expr = args->expr;
mp->m_replace_keycodes = args->replace_keycodes;
if (sid >= 0) {
mp->m_script_ctx.sc_sid = sid;
mp->m_script_ctx.sc_lnum = lnum;
} else {
mp->m_script_ctx = current_sctx;
mp->m_script_ctx.sc_lnum += sourcing_lnum;
nlua_set_sctx(&mp->m_script_ctx);
}
mp->m_desc = NULL;
if (args->desc != NULL) {
mp->m_desc = xstrdup(args->desc);
}
// add the new entry in front of the abbrlist or maphash[] list
if (is_abbr) {
mp->m_next = *abbr_table;
*abbr_table = mp;
} else {
const int n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
mp->m_next = map_table[n];
map_table[n] = mp;
}
}
/// Sets or removes a mapping or abbreviation in buffer `buf`.
///
/// @param maptype @see do_map
@@ -780,51 +837,10 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
}
// Get here when adding a new entry to the maphash[] list or abbrlist.
mp = xmalloc(sizeof(mapblock_T));
// If CTRL-C has been mapped, don't always use it for Interrupting.
if (*lhs == Ctrl_C) {
if (map_table == buf->b_maphash) {
buf->b_mapped_ctrl_c |= mode;
} else {
mapped_ctrl_c |= mode;
}
}
mp->m_keys = vim_strsave(lhs);
mp->m_str = args->rhs;
mp->m_orig_str = args->orig_rhs;
mp->m_luaref = args->rhs_lua;
if (!keyround1_simplified) {
args->rhs = NULL;
args->orig_rhs = NULL;
args->rhs_lua = LUA_NOREF;
}
mp->m_keylen = (int)STRLEN(mp->m_keys);
mp->m_noremap = noremap;
mp->m_nowait = args->nowait;
mp->m_silent = args->silent;
mp->m_mode = mode;
mp->m_simplified = keyround1_simplified; // Notice this when porting patch 8.2.0807
mp->m_expr = args->expr;
mp->m_replace_keycodes = args->replace_keycodes;
mp->m_script_ctx = current_sctx;
mp->m_script_ctx.sc_lnum += sourcing_lnum;
nlua_set_sctx(&mp->m_script_ctx);
mp->m_desc = NULL;
if (args->desc != NULL) {
mp->m_desc = xstrdup(args->desc);
}
// add the new entry in front of the abbrlist or maphash[] list
if (is_abbrev) {
mp->m_next = *abbr_table;
*abbr_table = mp;
} else {
n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
mp->m_next = map_table[n];
map_table[n] = mp;
}
map_add(buf, map_table, abbr_table, lhs, args, noremap, mode, is_abbrev,
-1, // sid
0, // lnum
keyround1_simplified);
}
theend:
@@ -2023,6 +2039,7 @@ static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, l
tv_dict_add_nr(dict, S_LEN("replace_keycodes"), 1);
}
tv_dict_add_allocated_str(dict, S_LEN("mode"), mapmode);
tv_dict_add_nr(dict, S_LEN("simplified"), mp->m_simplified ? 1 : 0);
}
static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
@@ -2108,6 +2125,73 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
xfree(alt_keys_buf);
}
/// "mapset()" function
void f_mapset(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char buf[NUMBUFLEN];
const char *which = tv_get_string_buf_chk(&argvars[0], buf);
int mode = get_map_mode((char **)&which, 0);
bool is_abbr = tv_get_number(&argvars[1]) != 0;
if (argvars[2].v_type != VAR_DICT) {
emsg(_(e_dictreq));
return;
}
dict_T *d = argvars[2].vval.v_dict;
// Get the values in the same order as above in get_maparg().
char *lhs = tv_dict_get_string(d, "lhs", false);
if (lhs == NULL) {
emsg(_("E99: lhs entry missing in mapset() dict argument"));
return;
}
char *rhs = tv_dict_get_string(d, "rhs", false);
if (rhs == NULL) {
emsg(_("E99: rhs entry missing in mapset() dict argument"));
return;
}
int noremap = tv_dict_get_number(d, "noremap") ? REMAP_NONE : 0;
if (tv_dict_get_number(d, "script") != 0) {
noremap = REMAP_SCRIPT;
}
// TODO: support "callback" and "desc"
MapArguments args = {
.rhs = vim_strsave((char_u *)rhs),
.rhs_lua = LUA_NOREF,
.orig_rhs = vim_strsave((char_u *)rhs),
.expr = tv_dict_get_number(d, "expr") != 0,
.silent = tv_dict_get_number(d, "silent") != 0,
.nowait = tv_dict_get_number(d, "nowait") != 0,
};
scid_T sid = (scid_T)tv_dict_get_number(d, "sid");
linenr_T lnum = (linenr_T)tv_dict_get_number(d, "lnum");
mapblock_T **map_table = maphash;
mapblock_T **abbr_table = &first_abbr;
if (tv_dict_get_number(d, "buffer") != 0) {
map_table = curbuf->b_maphash;
abbr_table = &curbuf->b_first_abbr;
}
// mode from the dict is not used
bool simplified = tv_dict_get_number(d, "simplified") != 0;
// Delete any existing mapping for this lhs and mode.
char_u *arg = vim_strsave((char_u *)lhs);
do_map(1, arg, mode, is_abbr); // TODO: refactor this later
xfree(arg);
char *keys_buf = NULL;
char *keys = replace_termcodes(lhs, STRLEN(lhs), &keys_buf, REPTERM_FROM_PART | REPTERM_DO_LT,
NULL, CPO_TO_CPO_FLAGS);
map_add(curbuf, map_table, abbr_table, (char_u *)keys, &args, noremap, mode, is_abbr, sid, lnum,
simplified);
xfree(keys_buf);
}
/// "maparg()" function
void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{

View File

@@ -1,12 +1,12 @@
" Tests for maparg().
" Tests for maparg(), mapcheck() and mapset().
" Also test utf8 map with a 0x80 byte.
" Also test mapcheck()
function s:SID()
func s:SID()
return str2nr(matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$'))
endfun
endfunc
function Test_maparg()
funct Test_maparg()
new
set cpo-=<
set encoding=utf8
@@ -17,24 +17,24 @@ function Test_maparg()
vnoremap <script> <buffer> <expr> <silent> bar isbar
call assert_equal("is<F4>foo", maparg('foo<C-V>'))
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo<C-V>',
\ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1,
\ 'rhs': 'is<F4>foo', 'buffer': 0},
\ maparg('foo<C-V>', '', 0, 1))
\ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1,
\ 'simplified': 1, 'rhs': 'is<F4>foo', 'buffer': 0},
\ maparg('foo<C-V>', '', 0, 1))
call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar', 'mode': 'v',
\ 'nowait': 0, 'expr': 1, 'sid': sid, 'lnum': lnum + 2,
\ 'rhs': 'isbar', 'buffer': 1},
\ 'simplified': 0, 'rhs': 'isbar', 'buffer': 1},
\ 'bar'->maparg('', 0, 1))
let lnum = expand('<sflnum>')
map <buffer> <nowait> foo bar
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo', 'mode': ' ',
\ 'nowait': 1, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'bar',
\ 'buffer': 1},
\ 'simplified': 0, 'buffer': 1},
\ maparg('foo', '', 0, 1))
let lnum = expand('<sflnum>')
tmap baz foo
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'baz', 'mode': 't',
\ 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'foo',
\ 'buffer': 0},
\ 'simplified': 0, 'buffer': 0},
\ maparg('baz', 't', 0, 1))
map abc x<char-114>x
@@ -89,7 +89,7 @@ function Test_maparg()
let d = maparg('esc', 'i', 1, 1)
call assert_equal(['esc', "\<C-V>\<C-V>\<Esc>", '!'], [d.lhs, d.rhs, d.mode])
abclear
endfunction
endfunc
func Test_mapcheck()
call assert_equal('', mapcheck('a'))
@@ -130,7 +130,7 @@ func Test_mapcheck()
unabbr ab
endfunc
function Test_range_map()
func Test_range_map()
new
" Outside of the range, minimum
inoremap <Char-0x1040> a
@@ -145,6 +145,31 @@ function Test_range_map()
inoremap <Char-0xf040> d
execute "normal a\uf040\<Esc>"
call assert_equal("abcd", getline(1))
endfunction
endfunc
func One_mapset_test(keys)
exe 'nnoremap ' .. a:keys .. ' original<CR>'
let orig = maparg(a:keys, 'n', 0, 1)
call assert_equal(a:keys, orig.lhs)
call assert_equal('original<CR>', orig.rhs)
call assert_equal('n', orig.mode)
exe 'nunmap ' .. a:keys
let d = maparg(a:keys, 'n', 0, 1)
call assert_equal({}, d)
call mapset('n', 0, orig)
let d = maparg(a:keys, 'n', 0, 1)
call assert_equal(a:keys, d.lhs)
call assert_equal('original<CR>', d.rhs)
call assert_equal('n', d.mode)
exe 'nunmap ' .. a:keys
endfunc
func Test_mapset()
call One_mapset_test('K')
call One_mapset_test('<F3>')
endfunc
" vim: shiftwidth=2 sts=2 expandtab