diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-10-25 07:16:54 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-24 23:16:54 +0000 |
commit | e4a74e986c40ca60ad49ea89020d6a9be36e928b (patch) | |
tree | 72dd847fb4ddda9e82fafbc5b77e6c4dc1e037e9 /src | |
parent | 54249d051c3e0b97321939e6a3ae3d2e83971ce7 (diff) | |
download | rneovim-e4a74e986c40ca60ad49ea89020d6a9be36e928b.tar.gz rneovim-e4a74e986c40ca60ad49ea89020d6a9be36e928b.tar.bz2 rneovim-e4a74e986c40ca60ad49ea89020d6a9be36e928b.zip |
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
https://github.com/vim/vim/commit/fdf135a0525746cc0ff85bed2fbbde320ddb6d0d
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/mapping.c | 20 | ||||
-rw-r--r-- | src/nvim/mapping.h | 7 |
2 files changed, 18 insertions, 9 deletions
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index e055ebc2fa..23efd2a841 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -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 *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. int noremap = args->script ? REMAP_SCRIPT : 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" // to be unmapped by typing ":unab foo", where "foo" will be replaced by // "bar" because of the abbreviation. - for (int round = 0; (round == 0 || maptype == MAPTYPE_UNMAP) && round <= 1 - && !did_it && !got_int; round++) { + const int num_rounds = maptype == MAPTYPE_UNMAP && !unmap_lhs_only ? 2 : 1; + for (int round = 0; round < num_rounds && !did_it && !got_int; round++) { int hash_start, hash_end; if ((round == 0 && has_lhs) || is_abbrev) { // just use one hash @@ -935,9 +941,11 @@ theend: /// for :cabbr mode is MODE_CMDLINE /// ``` /// -/// @param maptype MAPTYPE_MAP for |:map| -/// MAPTYPE_UNMAP for |:unmap| -/// MAPTYPE_NOREMAP for |:noremap|. +/// @param 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}. /// @param arg C-string containing the arguments of the map/abbrev /// command, i.e. everything except the initial `:[X][nore]map`. /// - 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; set_maparg_lhs_rhs(lhs, strlen(lhs), "", 0, LUA_NOREF, p_cpo, &unmap_args); 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.orig_rhs); diff --git a/src/nvim/mapping.h b/src/nvim/mapping.h index b82117ea86..fc120b683c 100644 --- a/src/nvim/mapping.h +++ b/src/nvim/mapping.h @@ -19,9 +19,10 @@ /// Used for the first argument of do_map() enum { - MAPTYPE_MAP = 0, - MAPTYPE_UNMAP = 1, - MAPTYPE_NOREMAP = 2, + MAPTYPE_MAP = 0, + MAPTYPE_UNMAP = 1, + MAPTYPE_NOREMAP = 2, + MAPTYPE_UNMAP_LHS = 3, }; /// Adjust chars in a language according to 'langmap' option. |