Skip to content

Commit 9c65253

Browse files
committed
patch 8.2.0815: maparg() does not provide enough information for mapset()
Problem: maparg() does not provide enough information for mapset(). Solution: Add "lhsraw" and "lhsrawalt" items. Drop "simplified"
1 parent 3718427 commit 9c65253

File tree

4 files changed

+92
-35
lines changed

4 files changed

+92
-35
lines changed

runtime/doc/eval.txt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2586,7 +2586,7 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]])
25862586
rhs of mapping {name} in mode {mode}
25872587
mapcheck({name} [, {mode} [, {abbr}]])
25882588
String check for mappings matching {name}
2589-
mapset({name}, {mode}, {abbr}, {dict}
2589+
mapset({mode}, {abbr}, {dict})
25902590
none restore mapping from |maparg()| result
25912591
match({expr}, {pat} [, {start} [, {count}]])
25922592
Number position where {pat} matches in {expr}
@@ -6829,7 +6829,10 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
68296829
When {dict} is there and it is |TRUE| return a dictionary
68306830
containing all the information of the mapping with the
68316831
following items:
6832-
"lhs" The {lhs} of the mapping.
6832+
"lhs" The {lhs} of the mapping as it would be typed
6833+
"lhsraw" The {lhs} of the mapping as raw bytes
6834+
"lhsrawalt" The {lhs} of the mapping as raw bytes, alternate
6835+
form, only present when it differs from "lhsraw"
68336836
"rhs" The {rhs} of the mapping as typed.
68346837
"silent" 1 for a |:map-silent| mapping, else 0.
68356838
"noremap" 1 if the {rhs} of the mapping is not remappable.
@@ -6847,7 +6850,6 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
68476850
"lnum" The line number in "sid", zero if unknown.
68486851
"nowait" Do not wait for other, longer mappings.
68496852
(|:map-<nowait>|).
6850-
"simplified"
68516853

68526854
The dictionary can be used to restore a mapping with
68536855
|mapset()|.
@@ -6897,18 +6899,23 @@ mapcheck({name} [, {mode} [, {abbr}]]) *mapcheck()*
68976899
Can also be used as a |method|: >
68986900
GetKey()->mapcheck('n')
68996901
6902+
69006903
mapset({mode}, {abbr}, {dict}) *mapset()*
69016904
Restore a mapping from a dictionary returned by |maparg()|.
6902-
{name}, {mode} and {abbr} should be the same as for the call
6903-
to |maparg()|.
6905+
{mode} and {abbr} should be the same as for the call to
6906+
|maparg()|. *E460*
69046907
{mode} is used to define the mode in which the mapping is set,
69056908
not the "mode" entry in {dict}.
69066909
Example for saving and restoring a mapping: >
69076910
let save_map = maparg('K', 'n', 0, 1)
69086911
nnoremap K somethingelse
69096912
...
69106913
call mapset('n', 0, save_map)
6911-
<
6914+
< Note that if you are going to replace a map in several modes,
6915+
e.g. with `:map!`, you need to save the mapping for all of
6916+
them, since they can differe.
6917+
6918+
69126919
match({expr}, {pat} [, {start} [, {count}]]) *match()*
69136920
When {expr} is a |List| then this returns the index of the
69146921
first item where {pat} matches. Each item is used as a

src/map.c

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,15 +2176,20 @@ check_map(
21762176
get_maparg(typval_T *argvars, typval_T *rettv, int exact)
21772177
{
21782178
char_u *keys;
2179+
char_u *keys_simplified;
21792180
char_u *which;
21802181
char_u buf[NUMBUFLEN];
21812182
char_u *keys_buf = NULL;
2183+
char_u *alt_keys_buf = NULL;
2184+
int did_simplify = FALSE;
21822185
char_u *rhs;
21832186
int mode;
21842187
int abbr = FALSE;
21852188
int get_dict = FALSE;
21862189
mapblock_T *mp;
2190+
mapblock_T *mp_simplified;
21872191
int buffer_local;
2192+
int flags = REPTERM_FROM_PART | REPTERM_DO_LT;
21882193

21892194
// return empty string for failure
21902195
rettv->v_type = VAR_STRING;
@@ -2211,10 +2216,20 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
22112216

22122217
mode = get_map_mode(&which, 0);
22132218

2214-
keys = replace_termcodes(keys, &keys_buf,
2215-
REPTERM_FROM_PART | REPTERM_DO_LT, NULL);
2216-
rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local);
2217-
vim_free(keys_buf);
2219+
keys_simplified = replace_termcodes(keys, &keys_buf, flags, &did_simplify);
2220+
rhs = check_map(keys_simplified, mode, exact, FALSE, abbr,
2221+
&mp, &buffer_local);
2222+
if (did_simplify)
2223+
{
2224+
// When the lhs is being simplified the not-simplified keys are
2225+
// preferred for priting, like in do_map().
2226+
// The "rhs" and "buffer_local" values are not expected to change.
2227+
mp_simplified = mp;
2228+
(void)replace_termcodes(keys, &alt_keys_buf,
2229+
flags | REPTERM_NO_SIMPLIFY, NULL);
2230+
rhs = check_map(alt_keys_buf, mode, exact, FALSE, abbr, &mp,
2231+
&buffer_local);
2232+
}
22182233

22192234
if (!get_dict)
22202235
{
@@ -2236,6 +2251,11 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
22362251
dict_T *dict = rettv->vval.v_dict;
22372252

22382253
dict_add_string(dict, "lhs", lhs);
2254+
vim_free(lhs);
2255+
dict_add_string(dict, "lhsraw", mp->m_keys);
2256+
if (did_simplify)
2257+
// Also add the value for the simplified entry.
2258+
dict_add_string(dict, "lhsrawalt", mp_simplified->m_keys);
22392259
dict_add_string(dict, "rhs", mp->m_orig_str);
22402260
dict_add_number(dict, "noremap", mp->m_noremap ? 1L : 0L);
22412261
dict_add_number(dict, "script", mp->m_noremap == REMAP_SCRIPT
@@ -2247,11 +2267,12 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
22472267
dict_add_number(dict, "buffer", (long)buffer_local);
22482268
dict_add_number(dict, "nowait", mp->m_nowait ? 1L : 0L);
22492269
dict_add_string(dict, "mode", mapmode);
2250-
dict_add_number(dict, "simplified", mp->m_simplified);
22512270

2252-
vim_free(lhs);
22532271
vim_free(mapmode);
22542272
}
2273+
2274+
vim_free(keys_buf);
2275+
vim_free(alt_keys_buf);
22552276
}
22562277

22572278
/*
@@ -2260,14 +2281,15 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
22602281
void
22612282
f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
22622283
{
2263-
char_u *keys;
22642284
char_u *keys_buf = NULL;
22652285
char_u *which;
22662286
int mode;
22672287
char_u buf[NUMBUFLEN];
22682288
int is_abbr;
22692289
dict_T *d;
22702290
char_u *lhs;
2291+
char_u *lhsraw;
2292+
char_u *lhsrawalt;
22712293
char_u *rhs;
22722294
char_u *orig_rhs;
22732295
char_u *arg_buf = NULL;
@@ -2279,7 +2301,6 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
22792301
mapblock_T **map_table = maphash;
22802302
mapblock_T **abbr_table = &first_abbr;
22812303
int nowait;
2282-
int simplified;
22832304
char_u *arg;
22842305

22852306
which = tv_get_string_buf_chk(&argvars[0], buf);
@@ -2295,15 +2316,12 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
22952316

22962317
// Get the values in the same order as above in get_maparg().
22972318
lhs = dict_get_string(d, (char_u *)"lhs", FALSE);
2298-
if (lhs == NULL)
2299-
{
2300-
emsg(_("E99: lhs entry missing in mapset() dict argument"));
2301-
return;
2302-
}
2319+
lhsraw = dict_get_string(d, (char_u *)"lhsraw", FALSE);
2320+
lhsrawalt = dict_get_string(d, (char_u *)"lhsrawalt", FALSE);
23032321
rhs = dict_get_string(d, (char_u *)"rhs", FALSE);
2304-
if (rhs == NULL)
2322+
if (lhs == NULL || lhsraw == NULL || rhs == NULL)
23052323
{
2306-
emsg(_("E99: rhs entry missing in mapset() dict argument"));
2324+
emsg(_("E460: entries missing in mapset() dict argument"));
23072325
return;
23082326
}
23092327
orig_rhs = rhs;
@@ -2324,7 +2342,6 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
23242342
}
23252343
nowait = dict_get_number(d, (char_u *)"nowait") != 0;
23262344
// mode from the dict is not used
2327-
simplified = dict_get_number(d, (char_u *)"simplified") != 0;
23282345

23292346
// Delete any existing mapping for this lhs and mode.
23302347
arg = vim_strsave(lhs);
@@ -2333,10 +2350,11 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
23332350
do_map(1, arg, mode, is_abbr);
23342351
vim_free(arg);
23352352

2336-
keys = replace_termcodes(lhs, &keys_buf,
2337-
REPTERM_FROM_PART | REPTERM_DO_LT, NULL);
2338-
(void)map_add(map_table, abbr_table, keys, rhs, orig_rhs, noremap,
2339-
nowait, silent, mode, is_abbr, expr, sid, lnum, simplified);
2353+
(void)map_add(map_table, abbr_table, lhsraw, rhs, orig_rhs, noremap,
2354+
nowait, silent, mode, is_abbr, expr, sid, lnum, 0);
2355+
if (lhsrawalt != NULL)
2356+
(void)map_add(map_table, abbr_table, lhsrawalt, rhs, orig_rhs, noremap,
2357+
nowait, silent, mode, is_abbr, expr, sid, lnum, 1);
23402358
vim_free(keys_buf);
23412359
vim_free(arg_buf);
23422360
}

src/testdir/test_maparg.vim

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,28 @@ func Test_maparg()
1717
vnoremap <script> <buffer> <expr> <silent> bar isbar
1818
call assert_equal("is<F4>foo", maparg('foo<C-V>'))
1919
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo<C-V>',
20+
\ 'lhsraw': "foo\x80\xfc\x04V", 'lhsrawalt': "foo\x16",
2021
\ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1,
21-
\ 'simplified': 1, 'rhs': 'is<F4>foo', 'buffer': 0},
22+
\ 'rhs': 'is<F4>foo', 'buffer': 0},
2223
\ maparg('foo<C-V>', '', 0, 1))
23-
call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar', 'mode': 'v',
24+
call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar',
25+
\ 'lhsraw': 'bar', 'mode': 'v',
2426
\ 'nowait': 0, 'expr': 1, 'sid': sid, 'lnum': lnum + 2,
25-
\ 'simplified': 0, 'rhs': 'isbar', 'buffer': 1},
27+
\ 'rhs': 'isbar', 'buffer': 1},
2628
\ 'bar'->maparg('', 0, 1))
2729
let lnum = expand('<sflnum>')
2830
map <buffer> <nowait> foo bar
29-
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo', 'mode': ' ',
31+
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo',
32+
\ 'lhsraw': 'foo', 'mode': ' ',
3033
\ 'nowait': 1, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'bar',
31-
\ 'simplified': 0, 'buffer': 1},
34+
\ 'buffer': 1},
3235
\ maparg('foo', '', 0, 1))
3336
let lnum = expand('<sflnum>')
3437
tmap baz foo
35-
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'baz', 'mode': 't',
38+
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'baz',
39+
\ 'lhsraw': 'baz', 'mode': 't',
3640
\ 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'foo',
37-
\ 'simplified': 0, 'buffer': 0},
41+
\ 'buffer': 0},
3842
\ maparg('baz', 't', 0, 1))
3943

4044
map abc x<char-114>x
@@ -199,7 +203,6 @@ func Test_mapset()
199203
call assert_equal('one<CR>two', getline(1))
200204

201205
iunmap K
202-
let &cpo = cpo_save
203206

204207
" Test literal <CR> using CTRL-V
205208
inoremap K one<CR>two
@@ -221,8 +224,35 @@ func Test_mapset()
221224

222225
iunmap K
223226
let &cpo = cpo_save
224-
225227
bwipe!
226228
endfunc
227229

230+
func Check_ctrlb_map(d, check_alt)
231+
call assert_equal('<C-B>', a:d.lhs)
232+
if a:check_alt
233+
call assert_equal("\x80\xfc\x04B", a:d.lhsraw)
234+
call assert_equal("\x02", a:d.lhsrawalt)
235+
else
236+
call assert_equal("\x02", a:d.lhsraw)
237+
endif
238+
endfunc
239+
240+
func Test_map_restore()
241+
" Test restoring map with alternate keycode
242+
nmap <C-B> back
243+
let d = maparg('<C-B>', 'n', 0, 1)
244+
call Check_ctrlb_map(d, 1)
245+
let dsimp = maparg("\x02", 'n', 0, 1)
246+
call Check_ctrlb_map(dsimp, 0)
247+
nunmap <C-B>
248+
call mapset('n', 0, d)
249+
let d = maparg('<C-B>', 'n', 0, 1)
250+
call Check_ctrlb_map(d, 1)
251+
let dsimp = maparg("\x02", 'n', 0, 1)
252+
call Check_ctrlb_map(dsimp, 0)
253+
254+
nunmap <C-B>
255+
256+
endfunc
257+
228258
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,8 @@ static char *(features[]) =
746746

747747
static int included_patches[] =
748748
{ /* Add new patch number below this line */
749+
/**/
750+
815,
749751
/**/
750752
814,
751753
/**/

0 commit comments

Comments
 (0)