diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2022-08-03 00:08:17 -0600 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2022-08-03 00:08:17 -0600 |
commit | 9449e1b8d273ff78eb894c588110ffa0c17d6ee3 (patch) | |
tree | 9e4470c33bd4187d9f42f0b2c4aaa995310c5be8 /src/nvim/mapping.c | |
parent | 308e1940dcd64aa6c344c403d4f9e0dda58d9c5c (diff) | |
parent | b8dcbcc732baf84fc48d6b272c3ade0bcb129b3b (diff) | |
download | rneovim-9449e1b8d273ff78eb894c588110ffa0c17d6ee3.tar.gz rneovim-9449e1b8d273ff78eb894c588110ffa0c17d6ee3.tar.bz2 rneovim-9449e1b8d273ff78eb894c588110ffa0c17d6ee3.zip |
Merge remote-tracking branch 'upstream/master' into rahm
Diffstat (limited to 'src/nvim/mapping.c')
-rw-r--r-- | src/nvim/mapping.c | 318 |
1 files changed, 210 insertions, 108 deletions
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 5a11ac686e..1797bb0365 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -235,7 +235,7 @@ static void showmap(mapblock_T *mp, bool local) /// @param[in] orig_lhs Original mapping LHS, with characters to replace. /// @param[in] orig_lhs_len `strlen` of orig_lhs. /// @param[in] orig_rhs Original mapping RHS, with characters to replace. -/// @param[in] rhs_lua Lua reference for Lua maps. +/// @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[out] mapargs MapArguments struct holding the replaced strings. @@ -428,6 +428,66 @@ static int str_to_mapargs(const char_u *strargs, bool is_unmap, MapArguments *ma 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 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 @@ -452,7 +512,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, abbr_table = &first_abbr; // For ":noremap" don't remap, otherwise do remap. - if (maptype == 2) { + if (maptype == MAPTYPE_NOREMAP) { noremap = REMAP_NONE; } else { noremap = REMAP_YES; @@ -470,10 +530,10 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, const bool has_lhs = (args->lhs[0] != NUL); const bool has_rhs = args->rhs_lua != LUA_NOREF || (args->rhs[0] != NUL) || args->rhs_is_noop; - const bool do_print = !has_lhs || (maptype != 1 && !has_rhs); + const bool do_print = !has_lhs || (maptype != MAPTYPE_UNMAP && !has_rhs); // check for :unmap without argument - if (maptype == 1 && !has_lhs) { + if (maptype == MAPTYPE_UNMAP && !has_lhs) { retval = 1; goto theend; } @@ -507,13 +567,11 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, goto theend; } - if (is_abbrev && maptype != 1) { - // + if (is_abbrev && maptype != MAPTYPE_UNMAP) { // If an abbreviation ends in a keyword character, the // rest must be all keyword-char or all non-keyword-char. // Otherwise we won't be able to find the start of it in a // vi-compatible way. - // int same = -1; const int first = vim_iswordp(lhs); @@ -551,7 +609,8 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, } // Check if a new local mapping wasn't already defined globally. - if (args->unique && map_table == buf->b_maphash && has_lhs && has_rhs && maptype != 1) { + if (args->unique && map_table == buf->b_maphash && has_lhs && has_rhs + && maptype != MAPTYPE_UNMAP) { // need to loop over all global hash lists for (int hash = 0; hash < 256 && !got_int; hash++) { if (is_abbrev) { @@ -581,7 +640,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, } // When listing global mappings, also list buffer-local ones here. - if (map_table != buf->b_maphash && !has_rhs && maptype != 1) { + if (map_table != buf->b_maphash && !has_rhs && maptype != MAPTYPE_UNMAP) { // need to loop over all global hash lists for (int hash = 0; hash < 256 && !got_int; hash++) { if (is_abbrev) { @@ -616,7 +675,7 @@ 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 == 1) && round <= 1 + for (int round = 0; (round == 0 || maptype == MAPTYPE_UNMAP) && round <= 1 && !did_it && !got_int; round++) { int hash_start, hash_end; if (has_lhs || is_abbrev) { @@ -650,7 +709,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, p = mp->m_keys; } if (STRNCMP(p, lhs, (size_t)(n < len ? n : len)) == 0) { - if (maptype == 1) { + if (maptype == MAPTYPE_UNMAP) { // Delete entry. // Only accept a full match. For abbreviations // we ignore trailing space when matching with @@ -715,6 +774,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, mp->m_mode = mode; mp->m_simplified = keyround1_simplified; 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); @@ -745,7 +805,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, } } - if (maptype == 1) { + if (maptype == MAPTYPE_UNMAP) { // delete entry if (!did_it) { if (!keyround1_simplified) { @@ -779,50 +839,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_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: @@ -861,7 +881,9 @@ theend: /// for :cabbr mode is MODE_CMDLINE /// ``` /// -/// @param maptype 0 for |:map|, 1 for |:unmap|, 2 for |noremap|. +/// @param maptype MAPTYPE_MAP for |:map| +/// MAPTYPE_UNMAP for |:unmap| +/// MAPTYPE_NOREMAP for |noremap|. /// @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. @@ -878,7 +900,7 @@ theend: int do_map(int maptype, char_u *arg, int mode, bool is_abbrev) { MapArguments parsed_args; - int result = str_to_mapargs(arg, maptype == 1, &parsed_args); + int result = str_to_mapargs(arg, maptype == MAPTYPE_UNMAP, &parsed_args); switch (result) { case 0: break; @@ -1230,7 +1252,7 @@ char_u *set_context_in_map_cmd(expand_T *xp, char_u *cmd, char_u *arg, bool forc /// Find all mapping/abbreviation names that match regexp "regmatch". /// For command line expansion of ":[un]map" and ":[un]abbrev" in all modes. /// @return OK if matches found, FAIL otherwise. -int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file) +int ExpandMappings(regmatch_T *regmatch, int *num_file, char ***file) { mapblock_T *mp; int hash; @@ -1270,7 +1292,7 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file) if (round == 1) { count++; } else { - (*file)[count++] = vim_strsave(p); + (*file)[count++] = (char *)vim_strsave(p); } } } @@ -1293,7 +1315,7 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file) if (round == 1) { count++; } else { - (*file)[count++] = p; + (*file)[count++] = (char *)p; p = NULL; } } @@ -1307,22 +1329,18 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file) } if (round == 1) { - *file = (char_u **)xmalloc((size_t)count * sizeof(char_u *)); + *file = xmalloc((size_t)count * sizeof(char_u *)); } } // for (round) if (count > 1) { - char_u **ptr1; - char_u **ptr2; - char_u **ptr3; - // Sort the matches sort_strings(*file, count); // Remove multiple entries - ptr1 = *file; - ptr2 = ptr1 + 1; - ptr3 = ptr1 + count; + char **ptr1 = *file; + char **ptr2 = ptr1 + 1; + char **ptr3 = ptr1 + count; while (ptr2 < ptr3) { if (STRCMP(*ptr1, *ptr2)) { @@ -1517,12 +1535,8 @@ bool check_abbr(int c, char_u *ptr, int col, int mincol) /// @param c NUL or typed character for abbreviation char_u *eval_map_expr(mapblock_T *mp, int c) { - char_u *res; char_u *p = NULL; char_u *expr = NULL; - pos_T save_cursor; - int save_msg_col; - int save_msg_row; // Remove escaping of K_SPECIAL, because "str" is in a format to be used as // typeahead. @@ -1536,9 +1550,9 @@ char_u *eval_map_expr(mapblock_T *mp, int c) textlock++; ex_normal_lock++; set_vim_var_char(c); // set v:char to the typed character - save_cursor = curwin->w_cursor; - save_msg_col = msg_col; - save_msg_row = msg_row; + const pos_T save_cursor = curwin->w_cursor; + const int save_msg_col = msg_col; + const int save_msg_row = msg_row; if (mp->m_luaref != LUA_NOREF) { Error err = ERROR_INIT; Array args = ARRAY_DICT_INIT; @@ -1564,8 +1578,15 @@ char_u *eval_map_expr(mapblock_T *mp, int c) if (p == NULL) { return NULL; } - // Escape K_SPECIAL in the result to be able to use the string as typeahead. - res = (char_u *)vim_strsave_escape_ks((char *)p); + + char_u *res = NULL; + + if (mp->m_replace_keycodes) { + replace_termcodes((char *)p, STRLEN(p), (char **)&res, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); + } else { + // Escape K_SPECIAL in the result to be able to use the string as typeahead. + res = (char_u *)vim_strsave_escape_ks((char *)p); + } xfree(p); return res; @@ -1612,7 +1633,7 @@ int makemap(FILE *fd, buf_T *buf) continue; } - // skip lua mappings and mappings that contain a <SNR> (script-local thing), + // skip Lua mappings and mappings that contain a <SNR> (script-local thing), // they probably don't work when loaded again if (mp->m_luaref != LUA_NOREF) { continue; @@ -1973,9 +1994,9 @@ void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// @param mp The maphash that contains the mapping information /// @param buffer_value The "buffer" value /// @param compatible True for compatible with old maparg() dict -static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, long buffer_value, - bool compatible) - FUNC_ATTR_NONNULL_ALL +static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, + const char *lhsrawalt, long buffer_value, bool compatible) + FUNC_ATTR_NONNULL_ARG(1, 2) { char *const lhs = str2special_save((const char *)mp->m_keys, compatible, !compatible); @@ -2007,6 +2028,11 @@ static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, l tv_dict_add_allocated_str(dict, S_LEN("desc"), xstrdup(mp->m_desc)); } tv_dict_add_allocated_str(dict, S_LEN("lhs"), lhs); + tv_dict_add_str(dict, S_LEN("lhsraw"), (const char *)mp->m_keys); + if (lhsrawalt != NULL) { + // Also add the value for the simplified entry. + tv_dict_add_str(dict, S_LEN("lhsrawalt"), lhsrawalt); + } tv_dict_add_nr(dict, S_LEN("noremap"), noremap_value); tv_dict_add_nr(dict, S_LEN("script"), mp->m_noremap == REMAP_SCRIPT ? 1 : 0); tv_dict_add_nr(dict, S_LEN("expr"), mp->m_expr ? 1 : 0); @@ -2015,23 +2041,14 @@ static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, l tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)mp->m_script_ctx.sc_lnum); tv_dict_add_nr(dict, S_LEN("buffer"), (varnumber_T)buffer_value); tv_dict_add_nr(dict, S_LEN("nowait"), mp->m_nowait ? 1 : 0); + if (mp->m_replace_keycodes) { + tv_dict_add_nr(dict, S_LEN("replace_keycodes"), 1); + } tv_dict_add_allocated_str(dict, S_LEN("mode"), mapmode); } static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) { - char *keys_buf = NULL; - char_u *alt_keys_buf = NULL; - bool did_simplify = false; - char_u *rhs; - LuaRef rhs_lua; - int mode; - bool abbr = false; - bool get_dict = false; - mapblock_T *mp; - int buffer_local; - int flags = REPTERM_FROM_PART | REPTERM_DO_LT; - // Return empty string for failure. rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -2041,8 +2058,11 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) return; } - char buf[NUMBUFLEN]; const char *which; + char buf[NUMBUFLEN]; + bool abbr = false; + bool get_dict = false; + if (argvars[1].v_type != VAR_UNKNOWN) { which = tv_get_string_buf_chk(&argvars[1], buf); if (argvars[2].v_type != VAR_UNKNOWN) { @@ -2058,13 +2078,19 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) return; } - mode = get_map_mode((char **)&which, 0); + char *keys_buf = NULL; + char_u *alt_keys_buf = NULL; + bool did_simplify = false; + const int flags = REPTERM_FROM_PART | REPTERM_DO_LT; + const int mode = get_map_mode((char **)&which, 0); char_u *keys_simplified - = (char_u *)replace_termcodes(keys, - STRLEN(keys), &keys_buf, flags, &did_simplify, + = (char_u *)replace_termcodes(keys, STRLEN(keys), &keys_buf, flags, &did_simplify, CPO_TO_CPO_FLAGS); - rhs = check_map(keys_simplified, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua); + mapblock_T *mp = NULL; + int buffer_local; + LuaRef rhs_lua; + char_u *rhs = check_map(keys_simplified, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua); if (did_simplify) { // When the lhs is being simplified the not-simplified keys are // preferred for printing, like in do_map(). @@ -2093,7 +2119,8 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) tv_dict_alloc_ret(rettv); if (mp != NULL && (rhs != NULL || rhs_lua != LUA_NOREF)) { // Return a dictionary. - mapblock_fill_dict(rettv->vval.v_dict, mp, buffer_local, true); + mapblock_fill_dict(rettv->vval.v_dict, mp, did_simplify ? (char *)keys_simplified : NULL, + buffer_local, true); } } @@ -2101,6 +2128,74 @@ 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); + if (which == NULL) { + return; + } + const int mode = get_map_mode((char **)&which, 0); + const 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); + char *lhsraw = tv_dict_get_string(d, "lhsraw", false); + char *lhsrawalt = tv_dict_get_string(d, "lhsrawalt", false); + char *rhs = tv_dict_get_string(d, "rhs", false); + if (lhs == NULL || lhsraw == NULL || rhs == NULL) { + emsg(_("E460: entries missing in mapset() dict argument")); + return; + } + char *orig_rhs = rhs; + char *arg_buf = NULL; + rhs = replace_termcodes(rhs, STRLEN(rhs), &arg_buf, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); + + int noremap = tv_dict_get_number(d, "noremap") ? REMAP_NONE : 0; + if (tv_dict_get_number(d, "script") != 0) { + noremap = REMAP_SCRIPT; + } + MapArguments args = { // TODO(zeertzjq): support restoring "callback"? + .rhs = (char_u *)rhs, + .rhs_lua = LUA_NOREF, + .orig_rhs = vim_strsave((char_u *)orig_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, + .replace_keycodes = tv_dict_get_number(d, "replace_keycodes") != 0, + .desc = tv_dict_get_string(d, "desc", false), + }; + scid_T sid = (scid_T)tv_dict_get_number(d, "sid"); + linenr_T lnum = (linenr_T)tv_dict_get_number(d, "lnum"); + bool buffer = tv_dict_get_number(d, "buffer") != 0; + // mode from the dict is not used + + 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), rhs, strlen(rhs), LUA_NOREF, 0, &unmap_args); + unmap_args.buffer = buffer; + buf_do_map(MAPTYPE_UNMAP, &unmap_args, mode, false, curbuf); + xfree(unmap_args.rhs); + xfree(unmap_args.orig_rhs); + + if (lhsrawalt != NULL) { + map_add(curbuf, map_table, abbr_table, (char_u *)lhsrawalt, &args, noremap, mode, is_abbr, + sid, lnum, true); + } + map_add(curbuf, map_table, abbr_table, (char_u *)lhsraw, &args, noremap, mode, is_abbr, + sid, lnum, false); +} + /// "maparg()" function void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -2123,11 +2218,11 @@ void f_mapcheck(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// @param buffer If true, make a buffer-local mapping for curbuf void add_map(char *lhs, char *rhs, int mode, bool buffer) { - MapArguments args = { 0 }; + MapArguments args = MAP_ARGUMENTS_INIT; set_maparg_lhs_rhs(lhs, strlen(lhs), rhs, strlen(rhs), LUA_NOREF, 0, &args); args.buffer = buffer; - buf_do_map(2, &args, mode, false, curbuf); + buf_do_map(MAPTYPE_NOREMAP, &args, mode, false, curbuf); xfree(args.rhs); xfree(args.orig_rhs); } @@ -2307,7 +2402,8 @@ static void do_exmap(exarg_T *eap, int isabbrev) char *cmdp = eap->cmd; mode = get_map_mode(&cmdp, eap->forceit || isabbrev); - switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'), + switch (do_map((*cmdp == 'n') ? MAPTYPE_NOREMAP + : (*cmdp == 'u') ? MAPTYPE_UNMAP : MAPTYPE_MAP, (char_u *)eap->arg, mode, isabbrev)) { case 1: emsg(_(e_invarg)); @@ -2396,10 +2492,16 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod KEY_TO_BOOL(script); KEY_TO_BOOL(expr); KEY_TO_BOOL(unique); + KEY_TO_BOOL(replace_keycodes); #undef KEY_TO_BOOL } parsed_args.buffer = !global; + if (parsed_args.replace_keycodes && !parsed_args.expr) { + api_set_error(err, kErrorTypeValidation, "\"replace_keycodes\" requires \"expr\""); + goto fail_and_free; + } + if (!set_maparg_lhs_rhs(lhs.data, lhs.size, rhs.data, rhs.size, lua_funcref, CPO_TO_CPO_FLAGS, &parsed_args)) { @@ -2461,11 +2563,11 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod } // buf_do_map() reads noremap/unmap as its own argument. - int maptype_val = 0; + int maptype_val = MAPTYPE_MAP; if (is_unmap) { - maptype_val = 1; + maptype_val = MAPTYPE_UNMAP; } else if (is_noremap) { - maptype_val = 2; + maptype_val = MAPTYPE_NOREMAP; } switch (buf_do_map(maptype_val, &parsed_args, mode_val, 0, target_buf)) { @@ -2499,7 +2601,7 @@ fail_and_free: /// /// @param mode The abbreviation for the mode /// @param buf The buffer to get the mapping array. NULL for global -/// @param from_lua Whether it is called from internal lua api. +/// @param from_lua Whether it is called from internal Lua api. /// @returns Array of maparg()-like dictionaries describing mappings ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, bool from_lua) { @@ -2523,7 +2625,7 @@ ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, bool from_lua) } // Check for correct mode if (int_mode & current_maphash->m_mode) { - mapblock_fill_dict(dict, current_maphash, buffer_value, false); + mapblock_fill_dict(dict, current_maphash, NULL, buffer_value, false); Object api_dict = vim_to_object((typval_T[]) { { .v_type = VAR_DICT, .vval.v_dict = dict } }); if (from_lua) { |