patch 9.1.0814: mapset() may remove unrelated mapping Commit: https://github.com/vim/vim/commit/fdf135a0525746cc0ff85bed2fbbde320ddb6d0d Author: zeertzjq <zeert...@outlook.com> Date: Thu Oct 24 21:43:43 2024 +0200
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 <zeert...@outlook.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/map.c b/src/map.c index 91ab6e3f1..209d9d237 100644 --- a/src/map.c +++ b/src/map.c @@ -408,9 +408,11 @@ list_mappings( * noreabbr {lhs} {rhs} : same, but no remapping for {rhs} * unabbr {lhs} : remove abbreviation for {lhs} * - * maptype: MAPTYPE_MAP for :map - * MAPTYPE_UNMAP for :unmap - * MAPTYPE_NOREMAP for noremap + * maptype: MAPTYPE_MAP for :map or :abbr + * MAPTYPE_UNMAP for :unmap or :unabbr + * MAPTYPE_NOREMAP for :noremap or :noreabbr + * MAPTYPE_UNMAP_LHS is like MAPTYPE_UNMAP, but doesn't try to match + * with {rhs} if there is no match with {lhs}. * * arg is pointer to any arguments. Note: arg cannot be a read-only string, * it will be modified. @@ -470,6 +472,7 @@ do_map( int expr = FALSE; #endif int did_simplify = FALSE; + int unmap_lhs_only = FALSE; int noremap; char_u *orig_rhs; @@ -477,6 +480,12 @@ do_map( map_table = maphash; abbr_table = &first_abbr; + if (maptype == MAPTYPE_UNMAP_LHS) + { + unmap_lhs_only = TRUE; + maptype = MAPTYPE_UNMAP; + } + // For ":noremap" don't remap, otherwise do remap. if (maptype == MAPTYPE_NOREMAP) noremap = REMAP_NONE; @@ -619,6 +628,7 @@ do_map( int did_local = FALSE; int keyround1_simplified = keyround == 1 && did_simplify; int round; + int num_rounds; if (keyround == 2) { @@ -742,8 +752,8 @@ do_map( // an entry with a matching 'to' part. This was done to allow // ":ab foo bar" to be unmapped by typing ":unab foo", where "foo" will // be replaced by "bar" because of the abbreviation. - for (round = 0; (round == 0 || maptype == MAPTYPE_UNMAP) && round <= 1 - && !did_it && !got_int; ++round) + num_rounds = maptype == MAPTYPE_UNMAP && !unmap_lhs_only ? 2 : 1; + for (round = 0; round < num_rounds && !did_it && !got_int; ++round) { // need to loop over all hash lists for (int hash = 0; hash < 256 && !got_int; ++hash) @@ -2817,7 +2827,7 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED) if (arg == NULL) return; } - do_map(MAPTYPE_UNMAP, arg, mode, is_abbr); + do_map(MAPTYPE_UNMAP_LHS, arg, mode, is_abbr); vim_free(arg); mp_result[0] = map_add(map_table, abbr_table, lhsraw, rhs, orig_rhs, diff --git a/src/testdir/test_map_functions.vim b/src/testdir/test_map_functions.vim index c65636815..db639337f 100644 --- a/src/testdir/test_map_functions.vim +++ b/src/testdir/test_map_functions.vim @@ -540,6 +540,25 @@ func Test_map_restore_negative_sid() call delete('Xresult') endfunc +" Check that restoring a mapping doesn't remove a mapping whose {rhs} matches +" the restored mapping's {lhs}. +func Test_map_restore_with_rhs_match_lhs() + nnoremap <F2> <F3> + nnoremap <F3> <F4> + call assert_equal('<F3>', maparg('<F2>', 'n')) + call assert_equal('<F4>', maparg('<F3>', 'n')) + let d = maparg('<F3>', 'n', v:false, v:true) + nunmap <F3> + call assert_equal('<F3>', maparg('<F2>', 'n')) + call assert_equal('', maparg('<F3>', 'n')) + call mapset(d) + call assert_equal('<F3>', maparg('<F2>', 'n')) + call assert_equal('<F4>', maparg('<F3>', 'n')) + + nunmap <F2> + nunmap <F3> +endfunc + def Test_maplist() new def ClearMappingsAbbreviations() diff --git a/src/version.c b/src/version.c index 1b3c92192..aa05ea2c3 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 814, /**/ 813, /**/ diff --git a/src/vim.h b/src/vim.h index 387fe4fd9..74e6b9543 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1013,9 +1013,10 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring); #define KEY_COMPLETE 0x103 // end of completion // Used for the first argument of do_map() -#define MAPTYPE_MAP 0 -#define MAPTYPE_UNMAP 1 -#define MAPTYPE_NOREMAP 2 +#define MAPTYPE_MAP 0 +#define MAPTYPE_UNMAP 1 +#define MAPTYPE_NOREMAP 2 +#define MAPTYPE_UNMAP_LHS 3 // Values for "noremap" argument of ins_typebuf(). Also used for // map->m_noremap and menu->noremap[]. -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1t4404-004wix-KX%40256bit.org.