mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 11:28:22 +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`).
(cherry picked from commit ec18ebcb41
)
This commit is contained in:

committed by
github-actions[bot]
![github-actions[bot]](/assets/img/avatar_default.png)
parent
2b2a90051e
commit
5fc6bd6454
@@ -681,12 +681,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
|
|||||||
if ((mp->m_mode & mode) != 0
|
if ((mp->m_mode & mode) != 0
|
||||||
&& mp->m_keylen == len
|
&& mp->m_keylen == len
|
||||||
&& strncmp(mp->m_keys, lhs, (size_t)len) == 0) {
|
&& strncmp(mp->m_keys, lhs, (size_t)len) == 0) {
|
||||||
if (is_abbrev) {
|
retval = 6;
|
||||||
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;
|
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -799,11 +794,6 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
|
|||||||
did_it = true;
|
did_it = true;
|
||||||
break;
|
break;
|
||||||
} else if (args->unique) {
|
} 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;
|
retval = 5;
|
||||||
goto theend;
|
goto theend;
|
||||||
} else {
|
} else {
|
||||||
@@ -962,6 +952,7 @@ theend:
|
|||||||
/// - 2 for no match
|
/// - 2 for no match
|
||||||
/// - 4 for out of mem (deprecated, WON'T HAPPEN)
|
/// - 4 for out of mem (deprecated, WON'T HAPPEN)
|
||||||
/// - 5 for entry not unique
|
/// - 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)
|
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;
|
char *cmdp = eap->cmd;
|
||||||
int mode = get_map_mode(&cmdp, eap->forceit || isabbrev);
|
int mode = get_map_mode(&cmdp, eap->forceit || isabbrev);
|
||||||
|
|
||||||
switch (do_map((*cmdp == 'n') ? MAPTYPE_NOREMAP
|
int maptype;
|
||||||
: (*cmdp == 'u') ? MAPTYPE_UNMAP : MAPTYPE_MAP,
|
if (*cmdp == 'n') {
|
||||||
eap->arg, mode, isabbrev)) {
|
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:
|
case 1:
|
||||||
emsg(_(e_invarg));
|
emsg(_(e_invarg));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
emsg(isabbrev ? _(e_noabbr) : _(e_nomap));
|
emsg(isabbrev ? _(e_noabbr) : _(e_nomap));
|
||||||
break;
|
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.
|
/// ":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
|
is_abbrev ? e_abbreviation_already_exists_for_str
|
||||||
: e_mapping_already_exists_for_str, lhs.data);
|
: e_mapping_already_exists_for_str, lhs.data);
|
||||||
goto fail_and_free;
|
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:
|
default:
|
||||||
assert(false && "Unrecognized return code!");
|
assert(false && "Unrecognized return code!");
|
||||||
goto fail_and_free;
|
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(1, exec_lua [[return GlobalCount]])
|
||||||
eq('\nNo mapping found', n.exec_capture('nmap <C-I>'))
|
eq('\nNo mapping found', n.exec_capture('nmap <C-I>'))
|
||||||
end)
|
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)
|
end)
|
||||||
|
Reference in New Issue
Block a user