Skip to content

Commit fdf135a

Browse files
zeertzjqchrisbra
authored andcommitted
patch 9.1.0814: mapset() may remove unrelated mapping
Problem: mapset() may remove unrelated mapping whose {rhs} matches the restored mapping's {lhs}. Solution: only match by {lhs} when unmapping for mapset() (zeertzjq). closes: #15935 Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent 1180728 commit fdf135a

4 files changed

Lines changed: 41 additions & 9 deletions

File tree

src/map.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,9 +408,11 @@ list_mappings(
408408
* noreabbr {lhs} {rhs} : same, but no remapping for {rhs}
409409
* unabbr {lhs} : remove abbreviation for {lhs}
410410
*
411-
* maptype: MAPTYPE_MAP for :map
412-
* MAPTYPE_UNMAP for :unmap
413-
* MAPTYPE_NOREMAP for noremap
411+
* maptype: MAPTYPE_MAP for :map or :abbr
412+
* MAPTYPE_UNMAP for :unmap or :unabbr
413+
* MAPTYPE_NOREMAP for :noremap or :noreabbr
414+
* MAPTYPE_UNMAP_LHS is like MAPTYPE_UNMAP, but doesn't try to match
415+
* with {rhs} if there is no match with {lhs}.
414416
*
415417
* arg is pointer to any arguments. Note: arg cannot be a read-only string,
416418
* it will be modified.
@@ -470,13 +472,20 @@ do_map(
470472
int expr = FALSE;
471473
#endif
472474
int did_simplify = FALSE;
475+
int unmap_lhs_only = FALSE;
473476
int noremap;
474477
char_u *orig_rhs;
475478

476479
keys = arg;
477480
map_table = maphash;
478481
abbr_table = &first_abbr;
479482

483+
if (maptype == MAPTYPE_UNMAP_LHS)
484+
{
485+
unmap_lhs_only = TRUE;
486+
maptype = MAPTYPE_UNMAP;
487+
}
488+
480489
// For ":noremap" don't remap, otherwise do remap.
481490
if (maptype == MAPTYPE_NOREMAP)
482491
noremap = REMAP_NONE;
@@ -619,6 +628,7 @@ do_map(
619628
int did_local = FALSE;
620629
int keyround1_simplified = keyround == 1 && did_simplify;
621630
int round;
631+
int num_rounds;
622632

623633
if (keyround == 2)
624634
{
@@ -742,8 +752,8 @@ do_map(
742752
// an entry with a matching 'to' part. This was done to allow
743753
// ":ab foo bar" to be unmapped by typing ":unab foo", where "foo" will
744754
// be replaced by "bar" because of the abbreviation.
745-
for (round = 0; (round == 0 || maptype == MAPTYPE_UNMAP) && round <= 1
746-
&& !did_it && !got_int; ++round)
755+
num_rounds = maptype == MAPTYPE_UNMAP && !unmap_lhs_only ? 2 : 1;
756+
for (round = 0; round < num_rounds && !did_it && !got_int; ++round)
747757
{
748758
// need to loop over all hash lists
749759
for (int hash = 0; hash < 256 && !got_int; ++hash)
@@ -2817,7 +2827,7 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
28172827
if (arg == NULL)
28182828
return;
28192829
}
2820-
do_map(MAPTYPE_UNMAP, arg, mode, is_abbr);
2830+
do_map(MAPTYPE_UNMAP_LHS, arg, mode, is_abbr);
28212831
vim_free(arg);
28222832

28232833
mp_result[0] = map_add(map_table, abbr_table, lhsraw, rhs, orig_rhs,

src/testdir/test_map_functions.vim

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,25 @@ func Test_map_restore_negative_sid()
540540
call delete('Xresult')
541541
endfunc
542542

543+
" Check that restoring a mapping doesn't remove a mapping whose {rhs} matches
544+
" the restored mapping's {lhs}.
545+
func Test_map_restore_with_rhs_match_lhs()
546+
nnoremap <F2> <F3>
547+
nnoremap <F3> <F4>
548+
call assert_equal('<F3>', maparg('<F2>', 'n'))
549+
call assert_equal('<F4>', maparg('<F3>', 'n'))
550+
let d = maparg('<F3>', 'n', v:false, v:true)
551+
nunmap <F3>
552+
call assert_equal('<F3>', maparg('<F2>', 'n'))
553+
call assert_equal('', maparg('<F3>', 'n'))
554+
call mapset(d)
555+
call assert_equal('<F3>', maparg('<F2>', 'n'))
556+
call assert_equal('<F4>', maparg('<F3>', 'n'))
557+
558+
nunmap <F2>
559+
nunmap <F3>
560+
endfunc
561+
543562
def Test_maplist()
544563
new
545564
def ClearMappingsAbbreviations()

src/version.c

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

705705
static int included_patches[] =
706706
{ /* Add new patch number below this line */
707+
/**/
708+
814,
707709
/**/
708710
813,
709711
/**/

src/vim.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,9 +1013,10 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
10131013
#define KEY_COMPLETE 0x103 // end of completion
10141014

10151015
// Used for the first argument of do_map()
1016-
#define MAPTYPE_MAP 0
1017-
#define MAPTYPE_UNMAP 1
1018-
#define MAPTYPE_NOREMAP 2
1016+
#define MAPTYPE_MAP 0
1017+
#define MAPTYPE_UNMAP 1
1018+
#define MAPTYPE_NOREMAP 2
1019+
#define MAPTYPE_UNMAP_LHS 3
10191020

10201021
// Values for "noremap" argument of ins_typebuf(). Also used for
10211022
// map->m_noremap and menu->noremap[].

0 commit comments

Comments
 (0)