diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-07-30 07:35:25 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-30 07:35:25 +0800 |
commit | 4b852bc555121f888a284dde45a56a0b7a42b851 (patch) | |
tree | ef2853df0c60b432398ba802a497ee1470ff34ec /src | |
parent | d131c48c823c30f519506eddcaef662dad5afa43 (diff) | |
download | rneovim-4b852bc555121f888a284dde45a56a0b7a42b851.tar.gz rneovim-4b852bc555121f888a284dde45a56a0b7a42b851.tar.bz2 rneovim-4b852bc555121f888a284dde45a56a0b7a42b851.zip |
vim-patch:9.1.0642: Check that mapping rhs starts with lhs fails if not simplified (#29909)
Problem: Check that mapping rhs starts with lhs doesn't work if lhs is
not simplified.
Solution: Keep track of the mapblock containing the alternative lhs and
also compare with it (zeertzjq).
fixes: vim/vim#15376
closes: vim/vim#15384
https://github.com/vim/vim/commit/9d997addc7bd0fd132a809cf497ed816e61fcd25
Cherry-pick removal of save_m_str from patch 8.2.4059.
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/getchar.c | 24 | ||||
-rw-r--r-- | src/nvim/mapping.c | 71 | ||||
-rw-r--r-- | src/nvim/mapping_defs.h | 3 |
3 files changed, 60 insertions, 38 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index a73824bdf5..6e441757dc 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2341,8 +2341,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) const int save_m_noremap = mp->m_noremap; const bool save_m_silent = mp->m_silent; char *save_m_keys = NULL; // only saved when needed - char *save_m_str = NULL; // only saved when needed - const LuaRef save_m_luaref = mp->m_luaref; + char *save_alt_m_keys = NULL; // only saved when needed // Handle ":map <expr>": evaluate the {rhs} as an // expression. Also save and restore the command line @@ -2356,9 +2355,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) may_garbage_collect = false; save_m_keys = xstrdup(mp->m_keys); - if (save_m_luaref == LUA_NOREF) { - save_m_str = xstrdup(mp->m_str); - } + save_alt_m_keys = mp->m_alt != NULL ? xstrdup(mp->m_alt->m_keys) : NULL; map_str = eval_map_expr(mp, NUL); if ((map_str == NULL || *map_str == NUL)) { @@ -2409,11 +2406,18 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) if (save_m_noremap != REMAP_YES) { noremap = save_m_noremap; - } else if (strncmp(map_str, save_m_keys != NULL ? save_m_keys : mp->m_keys, - (size_t)keylen) != 0) { - noremap = REMAP_YES; - } else { + } else if (save_m_expr + ? strncmp(map_str, save_m_keys, (size_t)keylen) == 0 + || (save_alt_m_keys != NULL + && strncmp(map_str, save_alt_m_keys, + strlen(save_alt_m_keys)) == 0) + : strncmp(map_str, mp->m_keys, (size_t)keylen) == 0 + || (mp->m_alt != NULL + && strncmp(map_str, mp->m_alt->m_keys, + strlen(mp->m_alt->m_keys)) == 0)) { noremap = REMAP_SKIP; + } else { + noremap = REMAP_YES; } i = ins_typebuf(map_str, noremap, 0, true, cmd_silent || save_m_silent); if (save_m_expr) { @@ -2421,7 +2425,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) } } xfree(save_m_keys); - xfree(save_m_str); + xfree(save_alt_m_keys); *keylenp = keylen; if (i == FAIL) { return map_result_fail; diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 167111f3ae..dfb540da84 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -151,7 +151,9 @@ static void mapblock_free(mapblock_T **mpp) { mapblock_T *mp = *mpp; xfree(mp->m_keys); - if (!mp->m_simplified) { + if (mp->m_alt != NULL) { + mp->m_alt->m_alt = NULL; + } else { NLUA_CLEAR_REF(mp->m_luaref); xfree(mp->m_str); xfree(mp->m_orig_str); @@ -493,13 +495,13 @@ static int str_to_mapargs(const char *strargs, bool is_unmap, MapArguments *mapa return 0; } -/// @param args "rhs", "rhs_lua", "orig_rhs", "expr", "silent", "nowait", "replace_keycodes" and -/// and "desc" fields are used. -/// "rhs", "rhs_lua", "orig_rhs" fields are cleared if "simplified" is false. +/// @param args "rhs", "rhs_lua", "orig_rhs", "expr", "silent", "nowait", +/// "replace_keycodes" and "desc" fields are used. /// @param sid 0 to use current_sctx -static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table, const char *keys, - MapArguments *args, int noremap, int mode, bool is_abbr, scid_T sid, - linenr_T lnum, bool simplified) +static mapblock_T *map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table, + const char *keys, MapArguments *args, int noremap, int mode, + bool is_abbr, scid_T sid, linenr_T lnum, bool simplified) + FUNC_ATTR_NONNULL_RET { mapblock_T *mp = xcalloc(1, sizeof(mapblock_T)); @@ -516,11 +518,6 @@ static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table, mp->m_str = args->rhs; mp->m_orig_str = args->orig_rhs; mp->m_luaref = args->rhs_lua; - if (!simplified) { - args->rhs = NULL; - args->orig_rhs = NULL; - args->rhs_lua = LUA_NOREF; - } mp->m_keylen = (int)strlen(mp->m_keys); mp->m_noremap = noremap; mp->m_nowait = args->nowait; @@ -551,6 +548,7 @@ static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table, mp->m_next = map_table[n]; map_table[n] = mp; } + return mp; } /// Sets or removes a mapping or abbreviation in buffer `buf`. @@ -571,6 +569,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, // mappings/abbreviations, not the globals. mapblock_T **map_table = args->buffer ? buf->b_maphash : maphash; mapblock_T **abbr_table = args->buffer ? &buf->b_first_abbr : &first_abbr; + mapblock_T *mp_result[2] = { NULL, NULL }; // For ":noremap" don't remap, otherwise do remap. int noremap = args->script ? REMAP_SCRIPT @@ -805,19 +804,16 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, mp->m_mode &= ~mode; // remove mode bits if (mp->m_mode == 0 && !did_it) { // reuse entry XFREE_CLEAR(mp->m_desc); - if (!mp->m_simplified) { + if (mp->m_alt != NULL) { + mp->m_alt = mp->m_alt->m_alt = NULL; + } else { NLUA_CLEAR_REF(mp->m_luaref); - XFREE_CLEAR(mp->m_str); - XFREE_CLEAR(mp->m_orig_str); + xfree(mp->m_str); + xfree(mp->m_orig_str); } mp->m_str = args->rhs; mp->m_orig_str = args->orig_rhs; mp->m_luaref = args->rhs_lua; - if (!keyround1_simplified) { - args->rhs = NULL; - args->orig_rhs = NULL; - args->rhs_lua = LUA_NOREF; - } mp->m_noremap = noremap; mp->m_nowait = args->nowait; mp->m_silent = args->silent; @@ -831,6 +827,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, if (args->desc != NULL) { mp->m_desc = xstrdup(args->desc); } + mp_result[keyround - 1] = mp; did_it = true; } } @@ -889,13 +886,24 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, } // Get here when adding a new entry to the maphash[] list or abbrlist. - map_add(buf, map_table, abbr_table, lhs, args, noremap, mode, is_abbrev, - 0, // sid - 0, // lnum - keyround1_simplified); + mp_result[keyround - 1] = map_add(buf, map_table, abbr_table, lhs, + args, noremap, mode, is_abbrev, + 0, // sid + 0, // lnum + keyround1_simplified); + } + + if (mp_result[0] != NULL && mp_result[1] != NULL) { + mp_result[0]->m_alt = mp_result[1]; + mp_result[1]->m_alt = mp_result[0]; } theend: + if (mp_result[0] != NULL || mp_result[1] != NULL) { + args->rhs = NULL; + args->orig_rhs = NULL; + args->rhs_lua = LUA_NOREF; + } return retval; } @@ -2348,12 +2356,19 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) xfree(unmap_args.rhs); xfree(unmap_args.orig_rhs); + mapblock_T *mp_result[2] = { NULL, NULL }; + + mp_result[0] = map_add(curbuf, map_table, abbr_table, lhsraw, &args, + noremap, mode, is_abbr, sid, lnum, false); if (lhsrawalt != NULL) { - map_add(curbuf, map_table, abbr_table, lhsrawalt, &args, noremap, mode, is_abbr, - sid, lnum, true); + mp_result[1] = map_add(curbuf, map_table, abbr_table, lhsrawalt, &args, + noremap, mode, is_abbr, sid, lnum, true); + } + + if (mp_result[0] != NULL && mp_result[1] != NULL) { + mp_result[0]->m_alt = mp_result[1]; + mp_result[1]->m_alt = mp_result[0]; } - map_add(curbuf, map_table, abbr_table, lhsraw, &args, noremap, mode, is_abbr, - sid, lnum, false); } /// "maplist()" function diff --git a/src/nvim/mapping_defs.h b/src/nvim/mapping_defs.h index 05b8aef23a..4a04b1ebfb 100644 --- a/src/nvim/mapping_defs.h +++ b/src/nvim/mapping_defs.h @@ -10,6 +10,9 @@ enum { MAXMAPLEN = 50, }; ///< Maximum length of key sequence to be mapped. typedef struct mapblock mapblock_T; struct mapblock { mapblock_T *m_next; ///< next mapblock in list + mapblock_T *m_alt; ///< pointer to mapblock of the same mapping + ///< with an alternative form of m_keys, or NULL + ///< if there is no such mapblock char *m_keys; ///< mapped from, lhs char *m_str; ///< mapped to, rhs char *m_orig_str; ///< rhs as entered by the user |