From 083865071b52d746de50294a0603bc6dbe20b3ec Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 1 Aug 2022 12:27:37 +0800 Subject: vim-patch:8.2.0807: cannot easily restore a mapping Problem: Cannot easily restore a mapping. Solution: Add mapset(). https://github.com/vim/vim/commit/4c9243f9fb708c9010867d3cc8e928f36b58509a Use MapArgument to reduce number of arguments of map_add(). N/A patches for version.c: vim-patch:8.2.0809: build failure with small features Problem: Build failure with small features. (Tony Mechelynck) Solution: Move "expr" inside #ifdef. https://github.com/vim/vim/commit/5a80f8ad5dc0b2cc63400255dcf3c63f6c1a2ef9 --- src/nvim/eval.lua | 1 + src/nvim/mapping.c | 174 +++++++++++++++++++++++++++++---------- src/nvim/testdir/test_maparg.vim | 51 +++++++++--- 3 files changed, 168 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 3db0d27018..c8eb0334fa 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -250,6 +250,7 @@ return { map={args=2, base=1}, maparg={args={1, 4}, base=1}, mapcheck={args={1, 3}, base=1}, + mapset={args=3, base=1}, match={args={2, 4}, base=1}, matchadd={args={2, 5}, base=1}, matchaddpos={args={2, 5}, base=1}, diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 93374a41bd..384497174d 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -428,6 +428,63 @@ static int str_to_mapargs(const char_u *strargs, bool is_unmap, MapArguments *ma return 0; } +/// @param sid -1 to use current_sctx +static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table, const char_u *keys, + MapArguments *args, int noremap, int mode, bool is_abbr, scid_T sid, + linenr_T lnum, bool simplified) +{ + mapblock_T *mp = xcalloc(1, sizeof(mapblock_T)); + + // If CTRL-C has been mapped, don't always use it for Interrupting. + if (*keys == Ctrl_C) { + if (map_table == buf->b_maphash) { + buf->b_mapped_ctrl_c |= mode; + } else { + mapped_ctrl_c |= mode; + } + } + + mp->m_keys = vim_strsave(keys); + 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; + mp->m_silent = args->silent; + mp->m_mode = mode; + mp->m_simplified = simplified; + mp->m_expr = args->expr; + mp->m_replace_keycodes = args->replace_keycodes; + if (sid >= 0) { + mp->m_script_ctx.sc_sid = sid; + mp->m_script_ctx.sc_lnum = lnum; + } else { + mp->m_script_ctx = current_sctx; + mp->m_script_ctx.sc_lnum += sourcing_lnum; + nlua_set_sctx(&mp->m_script_ctx); + } + mp->m_desc = NULL; + if (args->desc != NULL) { + mp->m_desc = xstrdup(args->desc); + } + + // add the new entry in front of the abbrlist or maphash[] list + if (is_abbr) { + mp->m_next = *abbr_table; + *abbr_table = mp; + } else { + const int n = MAP_HASH(mp->m_mode, mp->m_keys[0]); + mp->m_next = map_table[n]; + map_table[n] = mp; + } +} + /// Sets or removes a mapping or abbreviation in buffer `buf`. /// /// @param maptype @see do_map @@ -780,51 +837,10 @@ 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. - mp = xmalloc(sizeof(mapblock_T)); - - // If CTRL-C has been mapped, don't always use it for Interrupting. - if (*lhs == Ctrl_C) { - if (map_table == buf->b_maphash) { - buf->b_mapped_ctrl_c |= mode; - } else { - mapped_ctrl_c |= mode; - } - } - - mp->m_keys = vim_strsave(lhs); - 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_keylen = (int)STRLEN(mp->m_keys); - mp->m_noremap = noremap; - mp->m_nowait = args->nowait; - mp->m_silent = args->silent; - mp->m_mode = mode; - mp->m_simplified = keyround1_simplified; // Notice this when porting patch 8.2.0807 - mp->m_expr = args->expr; - mp->m_replace_keycodes = args->replace_keycodes; - mp->m_script_ctx = current_sctx; - mp->m_script_ctx.sc_lnum += sourcing_lnum; - nlua_set_sctx(&mp->m_script_ctx); - mp->m_desc = NULL; - if (args->desc != NULL) { - mp->m_desc = xstrdup(args->desc); - } - - // add the new entry in front of the abbrlist or maphash[] list - if (is_abbrev) { - mp->m_next = *abbr_table; - *abbr_table = mp; - } else { - n = MAP_HASH(mp->m_mode, mp->m_keys[0]); - mp->m_next = map_table[n]; - map_table[n] = mp; - } + map_add(buf, map_table, abbr_table, lhs, args, noremap, mode, is_abbrev, + -1, // sid + 0, // lnum + keyround1_simplified); } theend: @@ -2023,6 +2039,7 @@ static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, l tv_dict_add_nr(dict, S_LEN("replace_keycodes"), 1); } tv_dict_add_allocated_str(dict, S_LEN("mode"), mapmode); + tv_dict_add_nr(dict, S_LEN("simplified"), mp->m_simplified ? 1 : 0); } static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) @@ -2108,6 +2125,73 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) xfree(alt_keys_buf); } +/// "mapset()" function +void f_mapset(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + char buf[NUMBUFLEN]; + const char *which = tv_get_string_buf_chk(&argvars[0], buf); + int mode = get_map_mode((char **)&which, 0); + bool is_abbr = tv_get_number(&argvars[1]) != 0; + + if (argvars[2].v_type != VAR_DICT) { + emsg(_(e_dictreq)); + return; + } + dict_T *d = argvars[2].vval.v_dict; + + // Get the values in the same order as above in get_maparg(). + char *lhs = tv_dict_get_string(d, "lhs", false); + if (lhs == NULL) { + emsg(_("E99: lhs entry missing in mapset() dict argument")); + return; + } + char *rhs = tv_dict_get_string(d, "rhs", false); + if (rhs == NULL) { + emsg(_("E99: rhs entry missing in mapset() dict argument")); + return; + } + + int noremap = tv_dict_get_number(d, "noremap") ? REMAP_NONE : 0; + if (tv_dict_get_number(d, "script") != 0) { + noremap = REMAP_SCRIPT; + } + + // TODO: support "callback" and "desc" + MapArguments args = { + .rhs = vim_strsave((char_u *)rhs), + .rhs_lua = LUA_NOREF, + .orig_rhs = vim_strsave((char_u *)rhs), + .expr = tv_dict_get_number(d, "expr") != 0, + .silent = tv_dict_get_number(d, "silent") != 0, + .nowait = tv_dict_get_number(d, "nowait") != 0, + }; + + scid_T sid = (scid_T)tv_dict_get_number(d, "sid"); + linenr_T lnum = (linenr_T)tv_dict_get_number(d, "lnum"); + + mapblock_T **map_table = maphash; + mapblock_T **abbr_table = &first_abbr; + + if (tv_dict_get_number(d, "buffer") != 0) { + map_table = curbuf->b_maphash; + abbr_table = &curbuf->b_first_abbr; + } + // mode from the dict is not used + bool simplified = tv_dict_get_number(d, "simplified") != 0; + + // Delete any existing mapping for this lhs and mode. + char_u *arg = vim_strsave((char_u *)lhs); + do_map(1, arg, mode, is_abbr); // TODO: refactor this later + xfree(arg); + + char *keys_buf = NULL; + char *keys = replace_termcodes(lhs, STRLEN(lhs), &keys_buf, REPTERM_FROM_PART | REPTERM_DO_LT, + NULL, CPO_TO_CPO_FLAGS); + map_add(curbuf, map_table, abbr_table, (char_u *)keys, &args, noremap, mode, is_abbr, sid, lnum, + simplified); + xfree(keys_buf); +} + /// "maparg()" function void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { diff --git a/src/nvim/testdir/test_maparg.vim b/src/nvim/testdir/test_maparg.vim index f9429a8020..ec9af3d825 100644 --- a/src/nvim/testdir/test_maparg.vim +++ b/src/nvim/testdir/test_maparg.vim @@ -1,12 +1,12 @@ -" Tests for maparg(). +" Tests for maparg(), mapcheck() and mapset(). " Also test utf8 map with a 0x80 byte. " Also test mapcheck() -function s:SID() +func s:SID() return str2nr(matchstr(expand(''), '\zs\d\+\ze_SID$')) -endfun +endfunc -function Test_maparg() +funct Test_maparg() new set cpo-=< set encoding=utf8 @@ -17,24 +17,24 @@ function Test_maparg() vnoremap