mirror of
https://github.com/neovim/neovim.git
synced 2025-09-14 07:18:17 +00:00
vim-patch:8.2.4861: it is not easy to restore saved mappings
Problem: It is not easy to restore saved mappings.
Solution: Make mapset() accept a dict argument. (Ernie Rael, closes vim/vim#10295)
51d04d16f2
Co-authored-by: Ernie Rael <errael@raelity.com>
This commit is contained in:
@@ -123,6 +123,8 @@ static const char e_mapping_already_exists_for_str[]
|
||||
= N_("E227: Mapping already exists for %s");
|
||||
static const char e_entries_missing_in_mapset_dict_argument[]
|
||||
= N_("E460: Entries missing in mapset() dict argument");
|
||||
static const char e_illegal_map_mode_string_str[]
|
||||
= N_("E1276: Illegal map mode string: '%s'");
|
||||
|
||||
/// Get the start of the hashed map list for "state" and first character "c".
|
||||
mapblock_T *get_maphash_list(int state, int c)
|
||||
@@ -2070,11 +2072,12 @@ void f_hasmapto(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
///
|
||||
/// @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 compatible)
|
||||
const int buffer_value, const bool abbr, const bool compatible)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
Dictionary dict = ARRAY_DICT_INIT;
|
||||
@@ -2121,6 +2124,7 @@ static Dictionary mapblock_fill_dict(const mapblock_T *const mp, const char *lhs
|
||||
PUT(dict, "replace_keycodes", INTEGER_OBJ(1));
|
||||
}
|
||||
PUT(dict, "mode", CSTR_AS_OBJ(mapmode));
|
||||
PUT(dict, "abbr", INTEGER_OBJ(abbr ? 1 : 0));
|
||||
|
||||
return dict;
|
||||
}
|
||||
@@ -2193,7 +2197,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
|
||||
if (mp != NULL && (rhs != NULL || rhs_lua != LUA_NOREF)) {
|
||||
Dictionary dict = mapblock_fill_dict(mp,
|
||||
did_simplify ? keys_simplified : NULL,
|
||||
buffer_local, true);
|
||||
buffer_local, abbr, true);
|
||||
(void)object_to_vim(DICTIONARY_OBJ(dict), rettv, NULL);
|
||||
api_free_dictionary(dict);
|
||||
} else {
|
||||
@@ -2206,21 +2210,99 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
|
||||
xfree(alt_keys_buf);
|
||||
}
|
||||
|
||||
/// 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(const char *const mode_string, const bool abbr)
|
||||
{
|
||||
const char *p = mode_string;
|
||||
const int MASK_V = MODE_VISUAL | MODE_SELECT;
|
||||
const int MASK_MAP = MODE_VISUAL | MODE_SELECT | MODE_NORMAL | MODE_OP_PENDING;
|
||||
const int MASK_BANG = MODE_INSERT | MODE_CMDLINE;
|
||||
|
||||
if (*p == NUL) {
|
||||
p = " "; // compatibility
|
||||
}
|
||||
int mode = 0;
|
||||
int modec;
|
||||
while ((modec = (uint8_t)(*p++))) {
|
||||
int tmode;
|
||||
switch (modec) {
|
||||
case 'i':
|
||||
tmode = MODE_INSERT; break;
|
||||
case 'l':
|
||||
tmode = MODE_LANGMAP; break;
|
||||
case 'c':
|
||||
tmode = MODE_CMDLINE; break;
|
||||
case 'n':
|
||||
tmode = MODE_NORMAL; break;
|
||||
case 'x':
|
||||
tmode = MODE_VISUAL; break;
|
||||
case 's':
|
||||
tmode = MODE_SELECT; break;
|
||||
case 'o':
|
||||
tmode = MODE_OP_PENDING; break;
|
||||
case 't':
|
||||
tmode = MODE_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 f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
{
|
||||
const char *which;
|
||||
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;
|
||||
int is_abbr;
|
||||
dict_T *d;
|
||||
|
||||
if (tv_check_for_dict_arg(argvars, 2) == FAIL) {
|
||||
// If first arg is a dict, then that's the only arg permitted.
|
||||
const bool dict_only = argvars[0].v_type == VAR_DICT;
|
||||
|
||||
if (dict_only) {
|
||||
d = argvars[0].vval.v_dict;
|
||||
which = tv_dict_get_string(d, "mode", false);
|
||||
is_abbr = (int)tv_dict_get_bool(d, "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 (tv_check_for_dict_arg(argvars, 2) == FAIL) {
|
||||
return;
|
||||
}
|
||||
d = argvars[2].vval.v_dict;
|
||||
}
|
||||
const int mode = get_map_mode_string(which, is_abbr);
|
||||
if (mode == 0) {
|
||||
semsg(_(e_illegal_map_mode_string_str), which);
|
||||
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);
|
||||
@@ -2322,7 +2404,7 @@ void f_maplist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
|
||||
Dictionary dict = mapblock_fill_dict(mp,
|
||||
did_simplify ? keys_buf : NULL,
|
||||
buffer_local, true);
|
||||
buffer_local, abbr, true);
|
||||
typval_T d = TV_INITIAL_VALUE;
|
||||
(void)object_to_vim(DICTIONARY_OBJ(dict), &d, NULL);
|
||||
assert(d.v_type == VAR_DICT);
|
||||
@@ -2751,7 +2833,8 @@ 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)));
|
||||
DICTIONARY_OBJ(mapblock_fill_dict(current_maphash, NULL,
|
||||
buffer_value, false, false)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user