mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:9.1.0814: mapset() may remove unrelated mapping (#30941)
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: vim/vim#15935
fdf135a052
This commit is contained in:
parent
54249d051c
commit
e4a74e986c
@ -568,6 +568,12 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
|
|||||||
mapblock_T **abbr_table = args->buffer ? &buf->b_first_abbr : &first_abbr;
|
mapblock_T **abbr_table = args->buffer ? &buf->b_first_abbr : &first_abbr;
|
||||||
mapblock_T *mp_result[2] = { NULL, NULL };
|
mapblock_T *mp_result[2] = { NULL, NULL };
|
||||||
|
|
||||||
|
bool unmap_lhs_only = false;
|
||||||
|
if (maptype == MAPTYPE_UNMAP_LHS) {
|
||||||
|
unmap_lhs_only = true;
|
||||||
|
maptype = MAPTYPE_UNMAP;
|
||||||
|
}
|
||||||
|
|
||||||
// For ":noremap" don't remap, otherwise do remap.
|
// For ":noremap" don't remap, otherwise do remap.
|
||||||
int noremap = args->script ? REMAP_SCRIPT
|
int noremap = args->script ? REMAP_SCRIPT
|
||||||
: maptype == MAPTYPE_NOREMAP ? REMAP_NONE : REMAP_YES;
|
: maptype == MAPTYPE_NOREMAP ? REMAP_NONE : REMAP_YES;
|
||||||
@ -720,8 +726,8 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
|
|||||||
// entry with a matching 'to' part. This was done to allow ":ab foo bar"
|
// 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
|
// to be unmapped by typing ":unab foo", where "foo" will be replaced by
|
||||||
// "bar" because of the abbreviation.
|
// "bar" because of the abbreviation.
|
||||||
for (int round = 0; (round == 0 || maptype == MAPTYPE_UNMAP) && round <= 1
|
const int num_rounds = maptype == MAPTYPE_UNMAP && !unmap_lhs_only ? 2 : 1;
|
||||||
&& !did_it && !got_int; round++) {
|
for (int round = 0; round < num_rounds && !did_it && !got_int; round++) {
|
||||||
int hash_start, hash_end;
|
int hash_start, hash_end;
|
||||||
if ((round == 0 && has_lhs) || is_abbrev) {
|
if ((round == 0 && has_lhs) || is_abbrev) {
|
||||||
// just use one hash
|
// just use one hash
|
||||||
@ -935,9 +941,11 @@ theend:
|
|||||||
/// for :cabbr mode is MODE_CMDLINE
|
/// for :cabbr mode is MODE_CMDLINE
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// @param maptype MAPTYPE_MAP for |:map|
|
/// @param maptype MAPTYPE_MAP for |:map| or |:abbr|
|
||||||
/// MAPTYPE_UNMAP for |:unmap|
|
/// MAPTYPE_UNMAP for |:unmap| or |:unabbr|
|
||||||
/// MAPTYPE_NOREMAP for |:noremap|.
|
/// 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}.
|
||||||
/// @param arg C-string containing the arguments of the map/abbrev
|
/// @param arg C-string containing the arguments of the map/abbrev
|
||||||
/// command, i.e. everything except the initial `:[X][nore]map`.
|
/// command, i.e. everything except the initial `:[X][nore]map`.
|
||||||
/// - Cannot be a read-only string; it will be modified.
|
/// - Cannot be a read-only string; it will be modified.
|
||||||
@ -2348,7 +2356,7 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
|||||||
MapArguments unmap_args = MAP_ARGUMENTS_INIT;
|
MapArguments unmap_args = MAP_ARGUMENTS_INIT;
|
||||||
set_maparg_lhs_rhs(lhs, strlen(lhs), "", 0, LUA_NOREF, p_cpo, &unmap_args);
|
set_maparg_lhs_rhs(lhs, strlen(lhs), "", 0, LUA_NOREF, p_cpo, &unmap_args);
|
||||||
unmap_args.buffer = buffer;
|
unmap_args.buffer = buffer;
|
||||||
buf_do_map(MAPTYPE_UNMAP, &unmap_args, mode, is_abbr, curbuf);
|
buf_do_map(MAPTYPE_UNMAP_LHS, &unmap_args, mode, is_abbr, curbuf);
|
||||||
xfree(unmap_args.rhs);
|
xfree(unmap_args.rhs);
|
||||||
xfree(unmap_args.orig_rhs);
|
xfree(unmap_args.orig_rhs);
|
||||||
|
|
||||||
|
@ -19,9 +19,10 @@
|
|||||||
|
|
||||||
/// Used for the first argument of do_map()
|
/// Used for the first argument of do_map()
|
||||||
enum {
|
enum {
|
||||||
MAPTYPE_MAP = 0,
|
MAPTYPE_MAP = 0,
|
||||||
MAPTYPE_UNMAP = 1,
|
MAPTYPE_UNMAP = 1,
|
||||||
MAPTYPE_NOREMAP = 2,
|
MAPTYPE_NOREMAP = 2,
|
||||||
|
MAPTYPE_UNMAP_LHS = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Adjust chars in a language according to 'langmap' option.
|
/// Adjust chars in a language according to 'langmap' option.
|
||||||
|
@ -527,6 +527,25 @@ func Test_map_restore_negative_sid()
|
|||||||
call delete('Xresult')
|
call delete('Xresult')
|
||||||
endfunc
|
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
|
||||||
|
|
||||||
func Test_maplist()
|
func Test_maplist()
|
||||||
new
|
new
|
||||||
func s:ClearMappingsAbbreviations()
|
func s:ClearMappingsAbbreviations()
|
||||||
|
Loading…
Reference in New Issue
Block a user