summaryrefslogtreecommitdiffstats
path: root/src/map.c
diff options
context:
space:
mode:
authorErnie Rael <errael@raelity.com>2022-05-04 15:40:22 +0100
committerBram Moolenaar <Bram@vim.org>2022-05-04 15:40:22 +0100
commit51d04d16f21e19d6eded98f9530d84089102f925 (patch)
tree20bb53da9296e31af0101070f69c689724c04f61 /src/map.c
parent05cf63e9bdca1ac070df3e7d9c6dfc45e68ac916 (diff)
patch 8.2.4861: it is not easy to restore saved mappingsv8.2.4861
Problem: It is not easy to restore saved mappings. Solution: Make mapset() accept a dict argument. (Ernie Rael, closes #10295)
Diffstat (limited to 'src/map.c')
-rw-r--r--src/map.c108
1 files changed, 94 insertions, 14 deletions
diff --git a/src/map.c b/src/map.c
index ad2e8313e1..6ea73ebce2 100644
--- a/src/map.c
+++ b/src/map.c
@@ -2283,7 +2283,8 @@ mapblock2dict(
mapblock_T *mp,
dict_T *dict,
char_u *lhsrawalt, // may be NULL
- int buffer_local) // false if not buffer local mapping
+ int buffer_local, // false if not buffer local mapping
+ int abbr) // true if abbreviation
{
char_u *lhs = str2special_save(mp->m_keys, TRUE);
char_u *mapmode = map_mode_to_chars(mp->m_mode);
@@ -2307,6 +2308,7 @@ mapblock2dict(
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, "abbr", abbr ? 1L : 0L);
vim_free(mapmode);
}
@@ -2381,7 +2383,8 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
}
else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL)
mapblock2dict(mp, rettv->vval.v_dict,
- did_simplify ? keys_simplified : NULL, buffer_local);
+ did_simplify ? keys_simplified : NULL,
+ buffer_local, abbr);
vim_free(keys_buf);
vim_free(alt_keys_buf);
@@ -2448,7 +2451,8 @@ f_maplist(typval_T *argvars UNUSED, typval_T *rettv)
vim_free(lhs);
mapblock2dict(mp, d,
- did_simplify ? keys_buf : NULL, buffer_local);
+ did_simplify ? keys_buf : NULL,
+ buffer_local, abbr);
vim_free(keys_buf);
}
}
@@ -2490,6 +2494,56 @@ f_mapcheck(typval_T *argvars, typval_T *rettv)
}
/*
+ * Get the mapping mode from the mode string.
+ * It may contain multiple characters, eg "nox", or "!", or ' '
+ * Return 0 if there is an error.
+ */
+ static int
+get_map_mode_string(char_u *mode_string, int abbr)
+{
+ char_u *p = mode_string;
+ int mode = 0;
+ int tmode;
+ int modec;
+ const int MASK_V = VISUAL + SELECTMODE;
+ const int MASK_MAP = VISUAL + SELECTMODE + NORMAL + OP_PENDING;
+ const int MASK_BANG = INSERT + CMDLINE;
+
+ if (*p == NUL)
+ p = (char_u *)" "; // compatibility
+ while ((modec = *p++))
+ {
+ switch (modec)
+ {
+ case 'i': tmode = INSERT; break;
+ case 'l': tmode = LANGMAP; break;
+ case 'c': tmode = CMDLINE; break;
+ case 'n': tmode = NORMAL; break;
+ case 'x': tmode = VISUAL; break;
+ case 's': tmode = SELECTMODE; break;
+ case 'o': tmode = OP_PENDING; break;
+ case 't': tmode = TERMINAL; break;
+ case 'v': tmode = MASK_V; break;
+ case '!': tmode = MASK_BANG; break;
+ case ' ': tmode = MASK_MAP; break;
+ default:
+ return 0; // error, unknown mode character
+ }
+ mode |= tmode;
+ }
+ if ((abbr && (mode & ~MASK_BANG) != 0)
+ || (!abbr && (mode & (mode-1)) != 0 // more than one bit set
+ && (
+ // false if multiple bits set in mode and mode is fully
+ // contained in one mask
+ !(((mode & MASK_BANG) != 0 && (mode & ~MASK_BANG) == 0)
+ || ((mode & MASK_MAP) != 0 && (mode & ~MASK_MAP) == 0)))))
+ return 0;
+
+ return mode;
+}
+
+/*
* "mapset()" function
*/
void
@@ -2518,25 +2572,51 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
mapblock_T **abbr_table = &first_abbr;
int nowait;
char_u *arg;
+ int dict_only;
+ // If first arg is a dict, then that's the only arg permitted.
+ dict_only = argvars[0].v_type == VAR_DICT;
if (in_vim9script()
- && (check_for_string_arg(argvars, 0) == FAIL
- || check_for_bool_arg(argvars, 1) == FAIL
- || check_for_dict_arg(argvars, 2) == FAIL))
+ && (check_for_string_or_dict_arg(argvars, 0) == FAIL
+ || (dict_only && check_for_unknown_arg(argvars, 1) == FAIL)
+ || (!dict_only
+ && (check_for_string_arg(argvars, 0) == FAIL
+ || check_for_bool_arg(argvars, 1) == FAIL
+ || check_for_dict_arg(argvars, 2) == FAIL))))
return;
- which = tv_get_string_buf_chk(&argvars[0], buf);
- if (which == NULL)
- return;
- mode = get_map_mode(&which, 0);
- is_abbr = (int)tv_get_bool(&argvars[1]);
+ if (dict_only)
+ {
+ d = argvars[0].vval.v_dict;
+ which = dict_get_string(d, (char_u *)"mode", FALSE);
+ is_abbr = dict_get_bool(d, (char_u *)"abbr", -1);
+ if (which == NULL || is_abbr < 0)
+ {
+ emsg(_(e_entries_missing_in_mapset_dict_argument));
+ return;
+ }
+ }
+ else
+ {
+ which = tv_get_string_buf_chk(&argvars[0], buf);
+ if (which == NULL)
+ return;
+ is_abbr = (int)tv_get_bool(&argvars[1]);
- if (argvars[2].v_type != VAR_DICT)
+ if (argvars[2].v_type != VAR_DICT)
+ {
+ emsg(_(e_dictionary_required));
+ return;
+ }
+ d = argvars[2].vval.v_dict;
+ }
+ mode = get_map_mode_string(which, is_abbr);
+ if (mode == 0)
{
- emsg(_(e_key_not_present_in_dictionary));
+ semsg(_(e_illegal_map_mode_string_str), which);
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);