diff options
Diffstat (limited to 'src/nvim/mapping.c')
-rw-r--r-- | src/nvim/mapping.c | 261 |
1 files changed, 129 insertions, 132 deletions
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 17593a9121..43a4c10ea7 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -22,19 +22,24 @@ #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" +#include "nvim/eval/userfunc.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_session.h" -#include "nvim/func_attr.h" #include "nvim/garray.h" +#include "nvim/garray_defs.h" #include "nvim/getchar.h" -#include "nvim/gettext.h" +#include "nvim/getchar_defs.h" +#include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/highlight.h" +#include "nvim/highlight_defs.h" #include "nvim/keycodes.h" #include "nvim/lua/executor.h" #include "nvim/macros_defs.h" #include "nvim/mapping.h" +#include "nvim/mapping_defs.h" #include "nvim/mbyte.h" +#include "nvim/mbyte_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/option_defs.h" @@ -48,6 +53,7 @@ #include "nvim/strings.h" #include "nvim/types_defs.h" #include "nvim/ui.h" +#include "nvim/ui_defs.h" #include "nvim/vim_defs.h" /// List used for abbreviations. @@ -138,20 +144,6 @@ mapblock_T *get_buf_maphash_list(int state, int c) return curbuf->b_maphash[MAP_HASH(state, c)]; } -/// Retrieve the mapblock at the index either globally or for a certain buffer -/// -/// @param index The index in the maphash[] -/// @param buf The buffer to get the maphash from. NULL for global -mapblock_T *get_maphash(int index, buf_T *buf) - FUNC_ATTR_PURE -{ - if (index >= MAX_MAPHASH) { - return NULL; - } - - return (buf == NULL) ? maphash[index] : buf->b_maphash[index]; -} - /// Delete one entry from the abbrlist or maphash[]. /// "mpp" is a pointer to the m_next field of the PREVIOUS entry! static void mapblock_free(mapblock_T **mpp) @@ -168,51 +160,47 @@ static void mapblock_free(mapblock_T **mpp) xfree(mp); } -/// Return characters to represent the map mode in an allocated string +/// put characters to represent the map mode in a string buffer /// -/// @return [allocated] NUL-terminated string with characters. -static char *map_mode_to_chars(int mode) - FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET +/// @param[out] buf must be at least 7 bytes (including NUL) +void map_mode_to_chars(int mode, char *buf) + FUNC_ATTR_NONNULL_ALL { - garray_T mapmode; - - ga_init(&mapmode, 1, 7); - + char *p = buf; if ((mode & (MODE_INSERT | MODE_CMDLINE)) == (MODE_INSERT | MODE_CMDLINE)) { - ga_append(&mapmode, '!'); // :map! + *p++ = '!'; // :map! } else if (mode & MODE_INSERT) { - ga_append(&mapmode, 'i'); // :imap + *p++ = 'i'; // :imap } else if (mode & MODE_LANGMAP) { - ga_append(&mapmode, 'l'); // :lmap + *p++ = 'l'; // :lmap } else if (mode & MODE_CMDLINE) { - ga_append(&mapmode, 'c'); // :cmap + *p++ = 'c'; // :cmap } else if ((mode & (MODE_NORMAL | MODE_VISUAL | MODE_SELECT | MODE_OP_PENDING)) == (MODE_NORMAL | MODE_VISUAL | MODE_SELECT | MODE_OP_PENDING)) { - ga_append(&mapmode, ' '); // :map + *p++ = ' '; // :map } else { if (mode & MODE_NORMAL) { - ga_append(&mapmode, 'n'); // :nmap + *p++ = 'n'; // :nmap } if (mode & MODE_OP_PENDING) { - ga_append(&mapmode, 'o'); // :omap + *p++ = 'o'; // :omap } if (mode & MODE_TERMINAL) { - ga_append(&mapmode, 't'); // :tmap + *p++ = 't'; // :tmap } if ((mode & (MODE_VISUAL | MODE_SELECT)) == (MODE_VISUAL | MODE_SELECT)) { - ga_append(&mapmode, 'v'); // :vmap + *p++ = 'v'; // :vmap } else { if (mode & MODE_VISUAL) { - ga_append(&mapmode, 'x'); // :xmap + *p++ = 'x'; // :xmap } if (mode & MODE_SELECT) { - ga_append(&mapmode, 's'); // :smap + *p++ = 's'; // :smap } } } - ga_append(&mapmode, NUL); - return (char *)mapmode.ga_data; + *p = NUL; } /// @param local true for buffer-local map @@ -231,10 +219,10 @@ static void showmap(mapblock_T *mp, bool local) } } - char *const mapchars = map_mode_to_chars(mp->m_mode); + char mapchars[7]; + map_mode_to_chars(mp->m_mode, mapchars); msg_puts(mapchars); size_t len = strlen(mapchars); - xfree(mapchars); while (++len <= 3) { msg_putchar(' '); @@ -264,7 +252,7 @@ static void showmap(mapblock_T *mp, bool local) // Use false below if we only want things like <Up> to show up as such on // the rhs, and not M-x etc, true gets both -- webb if (mp->m_luaref != LUA_NOREF) { - char *str = nlua_funcref_str(mp->m_luaref); + char *str = nlua_funcref_str(mp->m_luaref, NULL); msg_puts_attr(str, HL_ATTR(HLF_8)); xfree(str); } else if (mp->m_str[0] == NUL) { @@ -304,11 +292,11 @@ static void showmap(mapblock_T *mp, bool local) /// @param[in] orig_rhs Original mapping RHS, with characters to replace. /// @param[in] rhs_lua Lua reference for Lua mappings. /// @param[in] orig_rhs_len `strlen` of orig_rhs. -/// @param[in] cpo_flags See param docs for @ref replace_termcodes. +/// @param[in] cpo_val See param docs for @ref replace_termcodes. /// @param[out] mapargs MapArguments struct holding the replaced strings. static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs_len, const char *const orig_rhs, const size_t orig_rhs_len, - const LuaRef rhs_lua, const int cpo_flags, + const LuaRef rhs_lua, const char *const cpo_val, MapArguments *const mapargs) { char lhs_buf[128]; @@ -320,12 +308,13 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs // replace_termcodes() may move the result to allocated memory, which // needs to be freed later (*lhs_buf and *rhs_buf). // replace_termcodes() also removes CTRL-Vs and sometimes backslashes. - // If something like <C-H> is simplified to 0x08 then mark it as simplified. + // If something like <C-H> is simplified to 0x08 then mark it as simplified + // and also add en entry with a modifier. bool did_simplify = false; const int flags = REPTERM_FROM_PART | REPTERM_DO_LT; char *bufarg = lhs_buf; char *replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, 0, - flags, &did_simplify, cpo_flags); + flags, &did_simplify, cpo_val); if (replaced == NULL) { return false; } @@ -333,7 +322,7 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs xstrlcpy(mapargs->lhs, replaced, sizeof(mapargs->lhs)); if (did_simplify) { replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, 0, - flags | REPTERM_NO_SIMPLIFY, NULL, cpo_flags); + flags | REPTERM_NO_SIMPLIFY, NULL, cpo_val); if (replaced == NULL) { return false; } @@ -343,14 +332,14 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs mapargs->alt_lhs_len = 0; } - set_maparg_rhs(orig_rhs, orig_rhs_len, rhs_lua, 0, cpo_flags, mapargs); + set_maparg_rhs(orig_rhs, orig_rhs_len, rhs_lua, 0, cpo_val, mapargs); return true; } /// @see set_maparg_lhs_rhs static void set_maparg_rhs(const char *const orig_rhs, const size_t orig_rhs_len, - const LuaRef rhs_lua, const scid_T sid, const int cpo_flags, + const LuaRef rhs_lua, const scid_T sid, const char *const cpo_val, MapArguments *const mapargs) { mapargs->rhs_lua = rhs_lua; @@ -366,7 +355,7 @@ static void set_maparg_rhs(const char *const orig_rhs, const size_t orig_rhs_len } else { char *rhs_buf = NULL; char *replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf, sid, - REPTERM_DO_LT, NULL, cpo_flags); + REPTERM_DO_LT, NULL, cpo_val); mapargs->rhs_len = strlen(replaced); // NB: replace_termcodes may produce an empty string even if orig_rhs is non-empty // (e.g. a single ^V, see :h map-empty-rhs) @@ -493,7 +482,7 @@ static int str_to_mapargs(const char *strargs, bool is_unmap, MapArguments *mapa size_t orig_rhs_len = strlen(rhs_start); if (!set_maparg_lhs_rhs(lhs_to_replace, orig_lhs_len, rhs_start, orig_rhs_len, LUA_NOREF, - CPO_TO_CPO_FLAGS, mapargs)) { + p_cpo, mapargs)) { return 1; } @@ -1104,7 +1093,7 @@ bool map_to_exists(const char *const str, const char *const modechars, const boo char *buf = NULL; const char *const rhs = replace_termcodes(str, strlen(str), &buf, 0, - REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); + REPTERM_DO_LT, NULL, p_cpo); #define MAPMODE(mode, modechars, chr, modeflags) \ do { \ @@ -1122,7 +1111,7 @@ bool map_to_exists(const char *const str, const char *const modechars, const boo MAPMODE(mode, modechars, 'c', MODE_CMDLINE); #undef MAPMODE - int retval = map_to_exists_mode(rhs, mode, abbr); + bool retval = map_to_exists_mode(rhs, mode, abbr); xfree(buf); return retval; @@ -1138,7 +1127,7 @@ bool map_to_exists(const char *const str, const char *const modechars, const boo /// @param[in] abbr true if checking abbreviations in place of mappings. /// /// @return true if there is at least one mapping with given parameters. -int map_to_exists_mode(const char *const rhs, const int mode, const bool abbr) +bool map_to_exists_mode(const char *const rhs, const int mode, const bool abbr) { bool exp_buffer = false; @@ -1190,16 +1179,16 @@ static bool expand_buffer = false; /// wider than the original description. The caller has to free the string /// afterwards. /// -/// @param cpo_flags Value of various flags present in &cpo +/// @param[in] cpo_val See param docs for @ref replace_termcodes. /// /// @return NULL when there is a problem. -static char *translate_mapping(char *str_in, int cpo_flags) +static char *translate_mapping(const char *const str_in, const char *const cpo_val) { - uint8_t *str = (uint8_t *)str_in; + const uint8_t *str = (const uint8_t *)str_in; garray_T ga; ga_init(&ga, 1, 40); - bool cpo_bslash = cpo_flags & FLAG_CPO_BSLASH; + const bool cpo_bslash = (vim_strchr(cpo_val, CPO_BSLASH) != NULL); for (; *str; str++) { int c = *str; @@ -1378,7 +1367,7 @@ int ExpandMappings(char *pat, regmatch_T *regmatch, int *numMatches, char ***mat continue; } - char *p = translate_mapping(mp->m_keys, CPO_TO_CPO_FLAGS); + char *p = translate_mapping(mp->m_keys, p_cpo); if (p == NULL) { continue; } @@ -1529,7 +1518,6 @@ bool check_abbr(int c, char *ptr, int col, int mincol) : (mp = mp->m_next)) { int qlen = mp->m_keylen; char *q = mp->m_keys; - int match; if (strchr(mp->m_keys, K_SPECIAL) != NULL) { // Might have K_SPECIAL escaped mp->m_keys. @@ -1538,9 +1526,9 @@ bool check_abbr(int c, char *ptr, int col, int mincol) qlen = (int)strlen(q); } // find entries with right mode and keys - match = (mp->m_mode & State) - && qlen == len - && !strncmp(q, ptr, (size_t)len); + int match = (mp->m_mode & State) + && qlen == len + && !strncmp(q, ptr, (size_t)len); if (q != mp->m_keys) { xfree(q); } @@ -1588,7 +1576,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol) } tb[j] = NUL; // insert the last typed char - (void)ins_typebuf((char *)tb, 1, 0, true, mp->m_silent); + ins_typebuf((char *)tb, 1, 0, true, mp->m_silent); } // copy values here, calling eval_map_expr() may make "mp" invalid! @@ -1604,7 +1592,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol) } if (s != NULL) { // insert the to string - (void)ins_typebuf(s, noremap, 0, true, silent); + ins_typebuf(s, noremap, 0, true, silent); // no abbrev. for these chars typebuf.tb_no_abbr_cnt += (int)strlen(s) + j + 1; if (expr) { @@ -1616,7 +1604,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol) tb[1] = NUL; len = clen; // Delete characters instead of bytes while (len-- > 0) { // delete the from string - (void)ins_typebuf((char *)tb, 1, 0, true, silent); + ins_typebuf((char *)tb, 1, 0, true, silent); } return true; } @@ -1653,7 +1641,7 @@ char *eval_map_expr(mapblock_T *mp, int c) if (mp->m_luaref != LUA_NOREF) { Error err = ERROR_INIT; Array args = ARRAY_DICT_INIT; - Object ret = nlua_call_ref(mp->m_luaref, NULL, args, true, &err); + Object ret = nlua_call_ref(mp->m_luaref, NULL, args, kRetObject, NULL, &err); if (ret.type == kObjectTypeString) { p = string_to_cstr(ret.data.string); } @@ -1678,7 +1666,7 @@ char *eval_map_expr(mapblock_T *mp, int c) char *res = NULL; if (replace_keycodes) { - replace_termcodes(p, strlen(p), &res, 0, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); + replace_termcodes(p, strlen(p), &res, 0, REPTERM_DO_LT, NULL, p_cpo); } else { // Escape K_SPECIAL in the result to be able to use the string as typeahead. res = vim_strsave_escape_ks(p); @@ -2078,12 +2066,14 @@ void f_hasmapto(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// /// @return A Dictionary. static Dictionary mapblock_fill_dict(const mapblock_T *const mp, const char *lhsrawalt, - const int buffer_value, const bool abbr, const bool compatible) + const int buffer_value, const bool abbr, const bool compatible, + Arena *arena) FUNC_ATTR_NONNULL_ARG(1) { - Dictionary dict = ARRAY_DICT_INIT; - char *const lhs = str2special_save(mp->m_keys, compatible, !compatible); - char *const mapmode = map_mode_to_chars(mp->m_mode); + Dictionary dict = arena_dict(arena, 19); + char *const lhs = str2special_arena(mp->m_keys, compatible, !compatible, arena); + char *mapmode = arena_alloc(arena, 7, false); + map_mode_to_chars(mp->m_mode, mapmode); int noremap_value; if (compatible) { @@ -2097,36 +2087,37 @@ static Dictionary mapblock_fill_dict(const mapblock_T *const mp, const char *lhs } if (mp->m_luaref != LUA_NOREF) { - PUT(dict, "callback", LUAREF_OBJ(api_new_luaref(mp->m_luaref))); + PUT_C(dict, "callback", LUAREF_OBJ(api_new_luaref(mp->m_luaref))); } else { - PUT(dict, "rhs", STRING_OBJ(compatible - ? cstr_to_string(mp->m_orig_str) - : cstr_as_string(str2special_save(mp->m_str, false, true)))); + String rhs = cstr_as_string(compatible + ? mp->m_orig_str + : str2special_arena(mp->m_str, false, true, arena)); + PUT_C(dict, "rhs", STRING_OBJ(rhs)); } if (mp->m_desc != NULL) { - PUT(dict, "desc", CSTR_TO_OBJ(mp->m_desc)); + PUT_C(dict, "desc", CSTR_AS_OBJ(mp->m_desc)); } - PUT(dict, "lhs", CSTR_AS_OBJ(lhs)); - PUT(dict, "lhsraw", CSTR_TO_OBJ(mp->m_keys)); + PUT_C(dict, "lhs", CSTR_AS_OBJ(lhs)); + PUT_C(dict, "lhsraw", CSTR_AS_OBJ(mp->m_keys)); if (lhsrawalt != NULL) { // Also add the value for the simplified entry. - PUT(dict, "lhsrawalt", CSTR_TO_OBJ(lhsrawalt)); - } - PUT(dict, "noremap", INTEGER_OBJ(noremap_value)); - PUT(dict, "script", INTEGER_OBJ(mp->m_noremap == REMAP_SCRIPT ? 1 : 0)); - PUT(dict, "expr", INTEGER_OBJ(mp->m_expr ? 1 : 0)); - PUT(dict, "silent", INTEGER_OBJ(mp->m_silent ? 1 : 0)); - PUT(dict, "sid", INTEGER_OBJ(mp->m_script_ctx.sc_sid)); - PUT(dict, "scriptversion", INTEGER_OBJ(1)); - PUT(dict, "lnum", INTEGER_OBJ(mp->m_script_ctx.sc_lnum)); - PUT(dict, "buffer", INTEGER_OBJ(buffer_value)); - PUT(dict, "nowait", INTEGER_OBJ(mp->m_nowait ? 1 : 0)); + PUT_C(dict, "lhsrawalt", CSTR_AS_OBJ(lhsrawalt)); + } + PUT_C(dict, "noremap", INTEGER_OBJ(noremap_value)); + PUT_C(dict, "script", INTEGER_OBJ(mp->m_noremap == REMAP_SCRIPT ? 1 : 0)); + PUT_C(dict, "expr", INTEGER_OBJ(mp->m_expr ? 1 : 0)); + PUT_C(dict, "silent", INTEGER_OBJ(mp->m_silent ? 1 : 0)); + PUT_C(dict, "sid", INTEGER_OBJ(mp->m_script_ctx.sc_sid)); + PUT_C(dict, "scriptversion", INTEGER_OBJ(1)); + PUT_C(dict, "lnum", INTEGER_OBJ(mp->m_script_ctx.sc_lnum)); + PUT_C(dict, "buffer", INTEGER_OBJ(buffer_value)); + PUT_C(dict, "nowait", INTEGER_OBJ(mp->m_nowait ? 1 : 0)); if (mp->m_replace_keycodes) { - PUT(dict, "replace_keycodes", INTEGER_OBJ(1)); + PUT_C(dict, "replace_keycodes", INTEGER_OBJ(1)); } - PUT(dict, "mode", CSTR_AS_OBJ(mapmode)); - PUT(dict, "abbr", INTEGER_OBJ(abbr ? 1 : 0)); - PUT(dict, "mode_bits", INTEGER_OBJ(mp->m_mode)); + PUT_C(dict, "mode", CSTR_AS_OBJ(mapmode)); + PUT_C(dict, "abbr", INTEGER_OBJ(abbr ? 1 : 0)); + PUT_C(dict, "mode_bits", INTEGER_OBJ(mp->m_mode)); return dict; } @@ -2169,7 +2160,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) const int mode = get_map_mode((char **)&which, 0); char *keys_simplified = replace_termcodes(keys, strlen(keys), &keys_buf, 0, - flags, &did_simplify, CPO_TO_CPO_FLAGS); + flags, &did_simplify, p_cpo); mapblock_T *mp = NULL; int buffer_local; LuaRef rhs_lua; @@ -2178,8 +2169,8 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) if (did_simplify) { // When the lhs is being simplified the not-simplified keys are // preferred for printing, like in do_map(). - (void)replace_termcodes(keys, strlen(keys), &alt_keys_buf, 0, - flags | REPTERM_NO_SIMPLIFY, NULL, CPO_TO_CPO_FLAGS); + replace_termcodes(keys, strlen(keys), &alt_keys_buf, 0, + flags | REPTERM_NO_SIMPLIFY, NULL, p_cpo); rhs = check_map(alt_keys_buf, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua); } @@ -2192,16 +2183,16 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) rettv->vval.v_string = str2special_save(rhs, false, false); } } else if (rhs_lua != LUA_NOREF) { - rettv->vval.v_string = nlua_funcref_str(mp->m_luaref); + rettv->vval.v_string = nlua_funcref_str(mp->m_luaref, NULL); } } else { // Return a dictionary. if (mp != NULL && (rhs != NULL || rhs_lua != LUA_NOREF)) { - Dictionary dict = mapblock_fill_dict(mp, - did_simplify ? keys_simplified : NULL, - buffer_local, abbr, true); - (void)object_to_vim(DICTIONARY_OBJ(dict), rettv, NULL); - api_free_dictionary(dict); + Arena arena = ARENA_EMPTY; + Dictionary dict = mapblock_fill_dict(mp, did_simplify ? keys_simplified : NULL, + buffer_local, abbr, true, &arena); + object_to_vim_take_luaref(&DICTIONARY_OBJ(dict), rettv, true, NULL); + arena_mem_free(arena_finish(&arena)); } else { // Return an empty dictionary. tv_dict_alloc_ret(rettv); @@ -2314,13 +2305,13 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) LuaRef rhs_lua = LUA_NOREF; dictitem_T *callback_di = tv_dict_find(d, S_LEN("callback")); if (callback_di != NULL) { - Object callback_obj = vim_to_object(&callback_di->di_tv); - if (callback_obj.type == kObjectTypeLuaRef && callback_obj.data.luaref != LUA_NOREF) { - rhs_lua = callback_obj.data.luaref; - orig_rhs = ""; - callback_obj.data.luaref = LUA_NOREF; + if (callback_di->di_tv.v_type == VAR_FUNC) { + ufunc_T *fp = find_func(callback_di->di_tv.vval.v_string); + if (fp != NULL && (fp->uf_flags & FC_LUAREF)) { + rhs_lua = api_new_luaref(fp->uf_luaref); + orig_rhs = ""; + } } - api_free_object(callback_obj); } if (lhs == NULL || lhsraw == NULL || orig_rhs == NULL) { emsg(_(e_entries_missing_in_mapset_dict_argument)); @@ -2344,14 +2335,14 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) bool buffer = tv_dict_get_number(d, "buffer") != 0; // mode from the dict is not used - set_maparg_rhs(orig_rhs, strlen(orig_rhs), rhs_lua, sid, CPO_TO_CPO_FLAGS, &args); + set_maparg_rhs(orig_rhs, strlen(orig_rhs), rhs_lua, sid, p_cpo, &args); mapblock_T **map_table = buffer ? curbuf->b_maphash : maphash; mapblock_T **abbr_table = buffer ? &curbuf->b_first_abbr : &first_abbr; // Delete any existing mapping for this lhs and mode. MapArguments unmap_args = MAP_ARGUMENTS_INIT; - set_maparg_lhs_rhs(lhs, strlen(lhs), "", 0, LUA_NOREF, 0, &unmap_args); + 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); xfree(unmap_args.rhs); @@ -2399,19 +2390,18 @@ void f_maplist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) char *keys_buf = NULL; bool did_simplify = false; - char *lhs = str2special_save(mp->m_keys, true, false); - (void)replace_termcodes(lhs, strlen(lhs), &keys_buf, 0, flags, &did_simplify, - CPO_TO_CPO_FLAGS); - xfree(lhs); + Arena arena = ARENA_EMPTY; + char *lhs = str2special_arena(mp->m_keys, true, false, &arena); + replace_termcodes(lhs, strlen(lhs), &keys_buf, 0, flags, &did_simplify, + p_cpo); - Dictionary dict = mapblock_fill_dict(mp, - did_simplify ? keys_buf : NULL, - buffer_local, abbr, true); + Dictionary dict = mapblock_fill_dict(mp, did_simplify ? keys_buf : NULL, + buffer_local, abbr, true, &arena); typval_T d = TV_INITIAL_VALUE; - (void)object_to_vim(DICTIONARY_OBJ(dict), &d, NULL); + object_to_vim_take_luaref(&DICTIONARY_OBJ(dict), &d, true, NULL); assert(d.v_type == VAR_DICT); tv_list_append_dict(rettv->vval.v_list, d.vval.v_dict); - api_free_dictionary(dict); + arena_mem_free(arena_finish(&arena)); xfree(keys_buf); } } @@ -2441,7 +2431,7 @@ void f_mapcheck(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) void add_map(char *lhs, char *rhs, int mode, bool buffer) { MapArguments args = MAP_ARGUMENTS_INIT; - set_maparg_lhs_rhs(lhs, strlen(lhs), rhs, strlen(rhs), LUA_NOREF, 0, &args); + set_maparg_lhs_rhs(lhs, strlen(lhs), rhs, strlen(rhs), LUA_NOREF, p_cpo, &args); args.buffer = buffer; buf_do_map(MAPTYPE_NOREMAP, &args, mode, false, curbuf); @@ -2721,7 +2711,7 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod if (!set_maparg_lhs_rhs(lhs.data, lhs.size, rhs.data, rhs.size, lua_funcref, - CPO_TO_CPO_FLAGS, &parsed_args)) { + p_cpo, &parsed_args)) { api_set_error(err, kErrorTypeValidation, "LHS exceeds maximum map length: %s", lhs.data); goto fail_and_free; } @@ -2813,20 +2803,28 @@ fail_and_free: /// @param mode The abbreviation for the mode /// @param buf The buffer to get the mapping array. NULL for global /// @returns Array of maparg()-like dictionaries describing mappings -ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf) +ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, Arena *arena) { - Array mappings = ARRAY_DICT_INIT; + ArrayBuilder mappings = KV_INITIAL_VALUE; + kvi_init(mappings); - // Convert the string mode to the integer mode - // that is stored within each mapblock - char *p = mode.data; - int int_mode = get_map_mode(&p, 0); + char *p = mode.size > 0 ? mode.data : "m"; + bool forceit = *p == '!'; + // Convert the string mode to the integer mode stored within each mapblock. + int int_mode = get_map_mode(&p, forceit); + if (forceit) { + assert(p == mode.data); + p++; + } + bool is_abbrev = (int_mode & (MODE_INSERT | MODE_CMDLINE)) != 0 && *p == 'a'; // Determine the desired buffer value int buffer_value = (buf == NULL) ? 0 : buf->handle; - for (int i = 0; i < MAX_MAPHASH; i++) { - for (const mapblock_T *current_maphash = get_maphash(i, buf); + for (int i = 0; i < (is_abbrev ? 1 : MAX_MAPHASH); i++) { + for (const mapblock_T *current_maphash = is_abbrev + ? (buf ? buf->b_first_abbr : first_abbr) + : (buf ? buf->b_maphash[i] : maphash[i]); current_maphash; current_maphash = current_maphash->m_next) { if (current_maphash->m_simplified) { @@ -2834,12 +2832,11 @@ ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf) } // Check for correct mode if (int_mode & current_maphash->m_mode) { - ADD(mappings, - DICTIONARY_OBJ(mapblock_fill_dict(current_maphash, NULL, - buffer_value, false, false))); + kvi_push(mappings, DICTIONARY_OBJ(mapblock_fill_dict(current_maphash, NULL, buffer_value, + is_abbrev, false, arena))); } } } - return mappings; + return arena_take_arraybuilder(arena, &mappings); } |