summaryrefslogtreecommitdiffstats
path: root/src/map.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-05-22 13:10:44 +0200
committerBram Moolenaar <Bram@vim.org>2020-05-22 13:10:44 +0200
commit4c9243f9fb708c9010867d3cc8e928f36b58509a (patch)
tree2e22d7b67780863b0b7af5e42a90fd2f904e3c5a /src/map.c
parent74fae513f8032cfa9e129eedc33454f0bf68668b (diff)
patch 8.2.0807: cannot easily restore a mappingv8.2.0807
Problem: Cannot easily restore a mapping. Solution: Add mapset().
Diffstat (limited to 'src/map.c')
-rw-r--r--src/map.c222
1 files changed, 172 insertions, 50 deletions
diff --git a/src/map.c b/src/map.c
index 2e20d401cb..34a956e0be 100644
--- a/src/map.c
+++ b/src/map.c
@@ -204,6 +204,86 @@ showmap(
out_flush(); // show one line at a time
}
+ static int
+map_add(
+ mapblock_T **map_table,
+ mapblock_T **abbr_table,
+ char_u *keys,
+ char_u *rhs,
+ char_u *orig_rhs,
+ int expr,
+ int noremap,
+ int nowait,
+ int silent,
+ int mode,
+ int is_abbr,
+#ifdef FEAT_EVAL
+ scid_T sid, // -1 to use current_sctx
+ linenr_T lnum,
+#endif
+ int simplified)
+{
+ mapblock_T *mp = ALLOC_ONE(mapblock_T);
+
+ if (mp == NULL)
+ return FAIL;
+
+ // If CTRL-C has been mapped, don't always use it for Interrupting.
+ if (*keys == Ctrl_C)
+ {
+ if (map_table == curbuf->b_maphash)
+ curbuf->b_mapped_ctrl_c |= mode;
+ else
+ mapped_ctrl_c |= mode;
+ }
+
+ mp->m_keys = vim_strsave(keys);
+ mp->m_str = vim_strsave(rhs);
+ mp->m_orig_str = vim_strsave(orig_rhs);
+ if (mp->m_keys == NULL || mp->m_str == NULL)
+ {
+ vim_free(mp->m_keys);
+ vim_free(mp->m_str);
+ vim_free(mp->m_orig_str);
+ vim_free(mp);
+ return FAIL;
+ }
+ mp->m_keylen = (int)STRLEN(mp->m_keys);
+ mp->m_noremap = noremap;
+ mp->m_nowait = nowait;
+ mp->m_silent = silent;
+ mp->m_mode = mode;
+ mp->m_simplified = simplified;
+#ifdef FEAT_EVAL
+ mp->m_expr = expr;
+ 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;
+ }
+#endif
+
+ // add the new entry in front of the abbrlist or maphash[] list
+ if (is_abbr)
+ {
+ mp->m_next = *abbr_table;
+ *abbr_table = mp;
+ }
+ else
+ {
+ int n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
+
+ mp->m_next = map_table[n];
+ map_table[n] = mp;
+ }
+ return OK;
+}
+
/*
* map[!] : show all key mappings
* map[!] {lhs} : show key mapping for {lhs}
@@ -501,7 +581,8 @@ do_map(
msg_start();
// Check if a new local mapping wasn't already defined globally.
- if (map_table == curbuf->b_maphash && haskey && hasarg && maptype != 1)
+ if (unique && map_table == curbuf->b_maphash
+ && haskey && hasarg && maptype != 1)
{
// need to loop over all global hash lists
for (hash = 0; hash < 256 && !got_int; ++hash)
@@ -519,7 +600,6 @@ do_map(
// check entries with the same mode
if ((mp->m_mode & mode) != 0
&& mp->m_keylen == len
- && unique
&& STRNCMP(mp->m_keys, keys, (size_t)len) == 0)
{
if (abbrev)
@@ -759,57 +839,16 @@ do_map(
continue; // have added the new entry already
// Get here when adding a new entry to the maphash[] list or abbrlist.
- mp = ALLOC_ONE(mapblock_T);
- if (mp == NULL)
- {
- retval = 4; // no mem
- goto theend;
- }
-
- // If CTRL-C has been mapped, don't always use it for Interrupting.
- if (*keys == Ctrl_C)
- {
- if (map_table == curbuf->b_maphash)
- curbuf->b_mapped_ctrl_c |= mode;
- else
- mapped_ctrl_c |= mode;
- }
-
- mp->m_keys = vim_strsave(keys);
- mp->m_str = vim_strsave(rhs);
- mp->m_orig_str = vim_strsave(orig_rhs);
- if (mp->m_keys == NULL || mp->m_str == NULL)
- {
- vim_free(mp->m_keys);
- vim_free(mp->m_str);
- vim_free(mp->m_orig_str);
- vim_free(mp);
- retval = 4; // no mem
- goto theend;
- }
- mp->m_keylen = (int)STRLEN(mp->m_keys);
- mp->m_noremap = noremap;
- mp->m_nowait = nowait;
- mp->m_silent = silent;
- mp->m_mode = mode;
- mp->m_simplified = did_simplify && keyround == 1;
+ if (map_add(map_table, abbr_table, keys, rhs, orig_rhs, expr,
+ noremap, nowait, silent, mode,
+ abbrev,
#ifdef FEAT_EVAL
- mp->m_expr = expr;
- mp->m_script_ctx = current_sctx;
- mp->m_script_ctx.sc_lnum += SOURCING_LNUM;
+ /* sid */ -1, /* lnum */ 0,
#endif
-
- // add the new entry in front of the abbrlist or maphash[] list
- if (abbrev)
- {
- mp->m_next = *abbr_table;
- *abbr_table = mp;
- }
- else
+ did_simplify && keyround == 1) == FAIL)
{
- n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
- mp->m_next = map_table[n];
- map_table[n] = mp;
+ retval = 4; // no mem
+ goto theend;
}
}
@@ -2209,13 +2248,96 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
dict_add_number(dict, "buffer", (long)buffer_local);
dict_add_number(dict, "nowait", mp->m_nowait ? 1L : 0L);
dict_add_string(dict, "mode", mapmode);
+ dict_add_number(dict, "simplified", mp->m_simplified);
vim_free(lhs);
vim_free(mapmode);
}
}
+
+/*
+ * "mapset()" function
+ */
+ void
+f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
+{
+ char_u *keys;
+ char_u *keys_buf = NULL;
+ char_u *which;
+ int mode;
+ char_u buf[NUMBUFLEN];
+ int is_abbr;
+ dict_T *d;
+ char_u *lhs;
+ char_u *rhs;
+ int noremap;
+ int expr;
+ int silent;
+ scid_T sid;
+ linenr_T lnum;
+ mapblock_T **map_table = maphash;
+ mapblock_T **abbr_table = &first_abbr;
+ int nowait;
+ int simplified;
+ char_u *arg;
+
+ which = tv_get_string_buf_chk(&argvars[0], buf);
+ mode = get_map_mode(&which, 0);
+ is_abbr = (int)tv_get_number(&argvars[1]);
+
+ if (argvars[2].v_type != VAR_DICT)
+ {
+ emsg(_(e_dictkey));
+ return;
+ }
+ d = argvars[2].vval.v_dict;
+
+ // Get the values in the same order as above in get_maparg().
+ lhs = dict_get_string(d, (char_u *)"lhs", FALSE);
+ if (lhs == NULL)
+ {
+ emsg(_("E99: lhs entry missing in mapset() dict argument"));
+ return;
+ }
+ rhs = dict_get_string(d, (char_u *)"rhs", FALSE);
+ if (rhs == NULL)
+ {
+ emsg(_("E99: rhs entry missing in mapset() dict argument"));
+ return;
+ }
+
+ noremap = dict_get_number(d, (char_u *)"noremap") ? REMAP_NONE: 0;
+ if (dict_get_number(d, (char_u *)"script") != 0)
+ noremap = REMAP_SCRIPT;
+ expr = dict_get_number(d, (char_u *)"expr") != 0;
+ silent = dict_get_number(d, (char_u *)"silent") != 0;
+ sid = dict_get_number(d, (char_u *)"sid");
+ lnum = dict_get_number(d, (char_u *)"lnum");
+ if (dict_get_number(d, (char_u *)"buffer"))
+ {
+ map_table = curbuf->b_maphash;
+ abbr_table = &curbuf->b_first_abbr;
+ }
+ nowait = dict_get_number(d, (char_u *)"nowait") != 0;
+ // mode from the dict is not used
+ simplified = dict_get_number(d, (char_u *)"simplified") != 0;
+
+ // Delete any existing mapping for this lhs and mode.
+ arg = vim_strsave(lhs);
+ if (arg == NULL)
+ return;
+ do_map(1, arg, mode, is_abbr);
+ vim_free(arg);
+
+ keys = replace_termcodes(lhs, &keys_buf,
+ REPTERM_FROM_PART | REPTERM_DO_LT, NULL);
+ (void)map_add(map_table, abbr_table, keys, rhs, rhs, expr,
+ noremap, nowait, silent, mode, is_abbr, sid, lnum, simplified);
+ vim_free(keys_buf);
+}
#endif
+
#if defined(MSWIN) || defined(MACOS_X)
# define VIS_SEL (VISUAL+SELECTMODE) // abbreviation