aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/mapping.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/mapping.c')
-rw-r--r--src/nvim/mapping.c122
1 files changed, 67 insertions, 55 deletions
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index 9320390d68..e055ebc2fa 100644
--- a/src/nvim/mapping.c
+++ b/src/nvim/mapping.c
@@ -19,6 +19,7 @@
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
#include "nvim/cmdexpand_defs.h"
+#include "nvim/errors.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
@@ -150,12 +151,14 @@ 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);
+ xfree(mp->m_desc);
}
- xfree(mp->m_desc);
*mpp = mp->m_next;
xfree(mp);
}
@@ -492,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));
@@ -515,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;
@@ -536,10 +534,7 @@ static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table,
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);
- }
+ mp->m_desc = args->desc;
// add the new entry in front of the abbrlist or maphash[] list
if (is_abbr) {
@@ -550,6 +545,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`.
@@ -570,6 +566,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
@@ -803,20 +800,17 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
// new rhs for existing entry
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);
+ xfree(mp->m_desc);
}
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;
@@ -827,9 +821,8 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
mp->m_script_ctx = current_sctx;
mp->m_script_ctx.sc_lnum += SOURCING_LNUM;
nlua_set_sctx(&mp->m_script_ctx);
- if (args->desc != NULL) {
- mp->m_desc = xstrdup(args->desc);
- }
+ mp->m_desc = args->desc;
+ mp_result[keyround - 1] = mp;
did_it = true;
}
}
@@ -888,13 +881,25 @@ 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;
+ args->desc = NULL;
+ }
return retval;
}
@@ -1646,12 +1651,12 @@ char *eval_map_expr(mapblock_T *mp, int c)
p = string_to_cstr(ret.data.string);
}
api_free_object(ret);
- if (err.type != kErrorTypeNone) {
+ if (ERROR_SET(&err)) {
semsg_multiline("E5108: %s", err.msg);
api_clear_error(&err);
}
} else {
- p = eval_to_string(expr, false);
+ p = eval_to_string(expr, false, false);
xfree(expr);
}
expr_map_lock--;
@@ -2056,20 +2061,20 @@ void f_hasmapto(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = map_to_exists(name, mode, abbr);
}
-/// Fill a Dictionary with all applicable maparg() like dictionaries
+/// Fill a Dict with all applicable maparg() like dictionaries
///
/// @param mp The maphash that contains the mapping information
/// @param buffer_value The "buffer" value
/// @param abbr True if abbreviation
/// @param compatible True for compatible with old maparg() dict
///
-/// @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,
- Arena *arena)
+/// @return Dict.
+static Dict mapblock_fill_dict(const mapblock_T *const mp, const char *lhsrawalt,
+ const int buffer_value, const bool abbr, const bool compatible,
+ Arena *arena)
FUNC_ATTR_NONNULL_ARG(1)
{
- Dictionary dict = arena_dict(arena, 19);
+ Dict 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);
@@ -2188,9 +2193,9 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
// Return a dictionary.
if (mp != NULL && (rhs != NULL || rhs_lua != LUA_NOREF)) {
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);
+ Dict dict = mapblock_fill_dict(mp, did_simplify ? keys_simplified : NULL,
+ buffer_local, abbr, true, &arena);
+ object_to_vim_take_luaref(&DICT_OBJ(dict), rettv, true, NULL);
arena_mem_free(arena_finish(&arena));
} else {
// Return an empty dictionary.
@@ -2327,7 +2332,7 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
.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),
+ .desc = tv_dict_get_string(d, "desc", true),
};
scid_T sid = (scid_T)tv_dict_get_number(d, "sid");
linenr_T lnum = (linenr_T)tv_dict_get_number(d, "lnum");
@@ -2347,12 +2352,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
@@ -2394,10 +2406,10 @@ void f_maplist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
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, &arena);
+ Dict dict = mapblock_fill_dict(mp, did_simplify ? keys_buf : NULL, buffer_local, abbr, true,
+ &arena);
typval_T d = TV_INITIAL_VALUE;
- object_to_vim_take_luaref(&DICTIONARY_OBJ(dict), &d, true, NULL);
+ object_to_vim_take_luaref(&DICT_OBJ(dict), &d, true, NULL);
assert(d.v_type == VAR_DICT);
tv_list_append_dict(rettv->vval.v_list, d.vval.v_dict);
arena_mem_free(arena_finish(&arena));
@@ -2802,7 +2814,7 @@ 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, Arena *arena)
+ArrayOf(Dict) keymap_array(String mode, buf_T *buf, Arena *arena)
{
ArrayBuilder mappings = KV_INITIAL_VALUE;
kvi_init(mappings);
@@ -2831,8 +2843,8 @@ ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, Arena *arena)
}
// Check for correct mode
if (int_mode & current_maphash->m_mode) {
- kvi_push(mappings, DICTIONARY_OBJ(mapblock_fill_dict(current_maphash, NULL, buffer_value,
- is_abbrev, false, arena)));
+ kvi_push(mappings, DICT_OBJ(mapblock_fill_dict(current_maphash, NULL, buffer_value,
+ is_abbrev, false, arena)));
}
}
}