mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
fix(api): nvim_set_keymap() throws error even in pcall() #33228
Problem: When `nvim_set_keymap` tries to overwrite a `<unique>` mapping, it throws an error even when called in `pcall`. Solution: src/nvim/mapping.c:buf_do_map no longer calls `semsg`. Its callers now decide whether to ignore the error, or use `semsg` (not caught)/`api_set_error` (caught by `pcall`).
This commit is contained in:
@@ -681,12 +681,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
|
||||
if ((mp->m_mode & mode) != 0
|
||||
&& mp->m_keylen == len
|
||||
&& strncmp(mp->m_keys, lhs, (size_t)len) == 0) {
|
||||
if (is_abbrev) {
|
||||
semsg(_(e_global_abbreviation_already_exists_for_str), mp->m_keys);
|
||||
} else {
|
||||
semsg(_(e_global_mapping_already_exists_for_str), mp->m_keys);
|
||||
}
|
||||
retval = 5;
|
||||
retval = 6;
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
@@ -799,11 +794,6 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
|
||||
did_it = true;
|
||||
break;
|
||||
} else if (args->unique) {
|
||||
if (is_abbrev) {
|
||||
semsg(_(e_abbreviation_already_exists_for_str), p);
|
||||
} else {
|
||||
semsg(_(e_mapping_already_exists_for_str), p);
|
||||
}
|
||||
retval = 5;
|
||||
goto theend;
|
||||
} else {
|
||||
@@ -962,6 +952,7 @@ theend:
|
||||
/// - 2 for no match
|
||||
/// - 4 for out of mem (deprecated, WON'T HAPPEN)
|
||||
/// - 5 for entry not unique
|
||||
/// - 6 for buflocal unique entry conflicts with global entry
|
||||
///
|
||||
int do_map(int maptype, char *arg, int mode, bool is_abbrev)
|
||||
{
|
||||
@@ -2637,16 +2628,47 @@ static void do_exmap(exarg_T *eap, int isabbrev)
|
||||
char *cmdp = eap->cmd;
|
||||
int mode = get_map_mode(&cmdp, eap->forceit || isabbrev);
|
||||
|
||||
switch (do_map((*cmdp == 'n') ? MAPTYPE_NOREMAP
|
||||
: (*cmdp == 'u') ? MAPTYPE_UNMAP : MAPTYPE_MAP,
|
||||
eap->arg, mode, isabbrev)) {
|
||||
int maptype;
|
||||
if (*cmdp == 'n') {
|
||||
maptype = MAPTYPE_NOREMAP;
|
||||
} else if (*cmdp == 'u') {
|
||||
maptype = MAPTYPE_UNMAP;
|
||||
} else {
|
||||
maptype = MAPTYPE_MAP;
|
||||
}
|
||||
MapArguments parsed_args;
|
||||
int result = str_to_mapargs(eap->arg, maptype == MAPTYPE_UNMAP, &parsed_args);
|
||||
switch (result) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
emsg(_(e_invarg));
|
||||
goto free_rhs;
|
||||
break;
|
||||
default:
|
||||
assert(false && "Unknown return code from str_to_mapargs!");
|
||||
goto free_rhs;
|
||||
}
|
||||
switch (buf_do_map(maptype, &parsed_args, mode, isabbrev, curbuf)) {
|
||||
case 1:
|
||||
emsg(_(e_invarg));
|
||||
break;
|
||||
case 2:
|
||||
emsg(isabbrev ? _(e_noabbr) : _(e_nomap));
|
||||
break;
|
||||
case 5:
|
||||
semsg(isabbrev ? _(e_abbreviation_already_exists_for_str)
|
||||
: _(e_mapping_already_exists_for_str),
|
||||
parsed_args.lhs);
|
||||
break;
|
||||
case 6:
|
||||
semsg(isabbrev ? _(e_global_abbreviation_already_exists_for_str)
|
||||
: _(e_global_mapping_already_exists_for_str),
|
||||
parsed_args.lhs);
|
||||
}
|
||||
free_rhs:
|
||||
xfree(parsed_args.rhs);
|
||||
xfree(parsed_args.orig_rhs);
|
||||
}
|
||||
|
||||
/// ":abbreviate" and friends.
|
||||
@@ -2808,6 +2830,12 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod
|
||||
is_abbrev ? e_abbreviation_already_exists_for_str
|
||||
: e_mapping_already_exists_for_str, lhs.data);
|
||||
goto fail_and_free;
|
||||
break;
|
||||
case 6:
|
||||
api_set_error(err, kErrorTypeException,
|
||||
is_abbrev ? e_global_abbreviation_already_exists_for_str
|
||||
: e_global_mapping_already_exists_for_str, lhs.data);
|
||||
goto fail_and_free;
|
||||
default:
|
||||
assert(false && "Unrecognized return code!");
|
||||
goto fail_and_free;
|
||||
|
@@ -1465,4 +1465,24 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
|
||||
eq(1, exec_lua [[return GlobalCount]])
|
||||
eq('\nNo mapping found', n.exec_capture('nmap <C-I>'))
|
||||
end)
|
||||
|
||||
it('does not overwrite in <unique> mappings', function()
|
||||
api.nvim_buf_set_keymap(0, 'i', 'lhs', 'rhs', {})
|
||||
eq(
|
||||
'E227: Mapping already exists for lhs',
|
||||
pcall_err(api.nvim_buf_set_keymap, 0, 'i', 'lhs', 'rhs', { unique = true })
|
||||
)
|
||||
|
||||
api.nvim_buf_set_keymap(0, 'ia', 'lhs2', 'rhs2', {})
|
||||
eq(
|
||||
'E226: Abbreviation already exists for lhs2',
|
||||
pcall_err(api.nvim_buf_set_keymap, 0, 'ia', 'lhs2', 'rhs2', { unique = true })
|
||||
)
|
||||
|
||||
api.nvim_set_keymap('n', 'lhs', 'rhs', {})
|
||||
eq(
|
||||
'E225: Global mapping already exists for lhs',
|
||||
pcall_err(api.nvim_buf_set_keymap, 0, 'n', 'lhs', 'rhs', { unique = true })
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
Reference in New Issue
Block a user