aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorii14 <59243201+ii14@users.noreply.github.com>2022-08-01 15:35:08 +0200
committerGitHub <noreply@github.com>2022-08-01 21:35:08 +0800
commitdb6e93c48df551e2906c9e0f4472f9e54cea3dd9 (patch)
treea62b94332e6f23a49adce724759a4c23edf7cf03
parent9f5d5aa3da30aab40bbb38fddfc70257444d50a8 (diff)
downloadrneovim-db6e93c48df551e2906c9e0f4472f9e54cea3dd9.tar.gz
rneovim-db6e93c48df551e2906c9e0f4472f9e54cea3dd9.tar.bz2
rneovim-db6e93c48df551e2906c9e0f4472f9e54cea3dd9.zip
feat(api): add replace_keycodes to nvim_set_keymap (#19598)
-rw-r--r--runtime/doc/api.txt4
-rw-r--r--runtime/doc/lua.txt5
-rw-r--r--runtime/lua/vim/keymap.lua20
-rw-r--r--src/nvim/api/keysets.lua1
-rw-r--r--src/nvim/api/vim.c3
-rw-r--r--src/nvim/buffer_defs.h1
-rw-r--r--src/nvim/mapping.c23
-rw-r--r--src/nvim/mapping.h3
-rw-r--r--test/functional/api/keymap_spec.lua25
9 files changed, 56 insertions, 29 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 1426404da9..aaafa21a59 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -1508,7 +1508,9 @@ nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()*
used to give a description to the mapping. When
called from Lua, also accepts a "callback" key
that takes a Lua function to call when the mapping
- is executed.
+ is executed. "replace_keycodes" can be used with
+ "expr" to replace keycodes, see
+ |nvim_replace_termcodes()|.
nvim_set_var({name}, {value}) *nvim_set_var()*
Sets a global (g:) variable.
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 3302a00b6a..6dfb0b5791 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -2228,13 +2228,10 @@ set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
• buffer: (number or boolean) Add a mapping to the
given buffer. When "true" or 0, use the current
buffer.
- • replace_keycodes: (boolean, default true) When
- both this and expr is "true",
- |nvim_replace_termcodes()| is applied to the
- result of Lua expr maps.
• remap: (boolean) Make the mapping recursive.
This is the inverse of the "noremap" option from
|nvim_set_keymap()|. Default `false`.
+ • replace_keycodes: (boolean) defaults to true.
See also: ~
|nvim_set_keymap()|
diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua
index f4c2b507a9..3592855606 100644
--- a/runtime/lua/vim/keymap.lua
+++ b/runtime/lua/vim/keymap.lua
@@ -42,11 +42,10 @@ local keymap = {}
--- listed in |nvim_set_keymap()|, this table also accepts the following keys:
--- - buffer: (number or boolean) Add a mapping to the given buffer. When "true"
--- or 0, use the current buffer.
---- - replace_keycodes: (boolean, default true) When both this and expr is "true",
---- |nvim_replace_termcodes()| is applied to the result of Lua expr maps.
--- - remap: (boolean) Make the mapping recursive. This is the
--- inverse of the "noremap" option from |nvim_set_keymap()|.
--- Default `false`.
+--- - replace_keycodes: (boolean) defaults to true.
---@see |nvim_set_keymap()|
function keymap.set(mode, lhs, rhs, opts)
vim.validate({
@@ -60,22 +59,9 @@ function keymap.set(mode, lhs, rhs, opts)
local is_rhs_luaref = type(rhs) == 'function'
mode = type(mode) == 'string' and { mode } or mode
- if is_rhs_luaref and opts.expr then
- local user_rhs = rhs
- rhs = function()
- local res = user_rhs()
- if res == nil then
- -- TODO(lewis6991): Handle this in C?
- return ''
- elseif opts.replace_keycodes ~= false then
- return vim.api.nvim_replace_termcodes(res, true, true, true)
- else
- return res
- end
- end
+ if opts.expr and opts.replace_keycodes ~= false then
+ opts.replace_keycodes = true
end
- -- clear replace_keycodes from opts table
- opts.replace_keycodes = nil
if opts.remap == nil then
-- default remap value is false
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index 21319fb7a6..4f4ac40ce9 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -39,6 +39,7 @@ return {
"unique";
"callback";
"desc";
+ "replace_keycodes";
};
get_commands = {
"builtin";
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 256482fb38..dc57841b96 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -1447,7 +1447,8 @@ ArrayOf(Dictionary) nvim_get_keymap(uint64_t channel_id, String mode)
/// Unknown key is an error. "desc" can be used to give a
/// description to the mapping. When called from Lua, also accepts a
/// "callback" key that takes a Lua function to call when the
-/// mapping is executed.
+/// mapping is executed. "replace_keycodes" can be used with "expr"
+/// to replace keycodes, see |nvim_replace_termcodes()|.
/// @param[out] err Error details, if any.
void nvim_set_keymap(uint64_t channel_id, String mode, String lhs, String rhs, Dict(keymap) *opts,
Error *err)
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 174eb1cec9..aeba3acbc3 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -369,6 +369,7 @@ struct mapblock {
char m_expr; // <expr> used, m_str is an expression
sctx_T m_script_ctx; // SCTX where map was defined
char *m_desc; // description of keymap
+ bool m_replace_keycodes; // replace termcodes in lua function
};
/// Used for highlighting in the status line.
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index 237586dc22..93374a41bd 100644
--- a/src/nvim/mapping.c
+++ b/src/nvim/mapping.c
@@ -715,6 +715,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
mp->m_mode = mode;
mp->m_simplified = keyround1_simplified;
mp->m_expr = args->expr;
+ mp->m_replace_keycodes = args->replace_keycodes;
mp->m_script_ctx = current_sctx;
mp->m_script_ctx.sc_lnum += sourcing_lnum;
nlua_set_sctx(&mp->m_script_ctx);
@@ -806,6 +807,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
mp->m_mode = mode;
mp->m_simplified = keyround1_simplified; // Notice this when porting patch 8.2.0807
mp->m_expr = args->expr;
+ mp->m_replace_keycodes = args->replace_keycodes;
mp->m_script_ctx = current_sctx;
mp->m_script_ctx.sc_lnum += sourcing_lnum;
nlua_set_sctx(&mp->m_script_ctx);
@@ -1513,7 +1515,6 @@ bool check_abbr(int c, char_u *ptr, int col, int mincol)
/// @param c NUL or typed character for abbreviation
char_u *eval_map_expr(mapblock_T *mp, int c)
{
- char_u *res;
char_u *p = NULL;
char_u *expr = NULL;
pos_T save_cursor;
@@ -1560,8 +1561,15 @@ char_u *eval_map_expr(mapblock_T *mp, int c)
if (p == NULL) {
return NULL;
}
- // Escape K_SPECIAL in the result to be able to use the string as typeahead.
- res = (char_u *)vim_strsave_escape_ks((char *)p);
+
+ char_u *res = NULL;
+
+ if (mp->m_replace_keycodes) {
+ replace_termcodes((char *)p, STRLEN(p), (char **)&res, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS);
+ } else {
+ // Escape K_SPECIAL in the result to be able to use the string as typeahead.
+ res = (char_u *)vim_strsave_escape_ks((char *)p);
+ }
xfree(p);
return res;
@@ -2011,6 +2019,9 @@ static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, l
tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)mp->m_script_ctx.sc_lnum);
tv_dict_add_nr(dict, S_LEN("buffer"), (varnumber_T)buffer_value);
tv_dict_add_nr(dict, S_LEN("nowait"), mp->m_nowait ? 1 : 0);
+ if (mp->m_replace_keycodes) {
+ tv_dict_add_nr(dict, S_LEN("replace_keycodes"), 1);
+ }
tv_dict_add_allocated_str(dict, S_LEN("mode"), mapmode);
}
@@ -2392,10 +2403,16 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod
KEY_TO_BOOL(script);
KEY_TO_BOOL(expr);
KEY_TO_BOOL(unique);
+ KEY_TO_BOOL(replace_keycodes);
#undef KEY_TO_BOOL
}
parsed_args.buffer = !global;
+ if (parsed_args.replace_keycodes && !parsed_args.expr) {
+ api_set_error(err, kErrorTypeValidation, "\"replace_keycodes\" requires \"expr\"");
+ goto fail_and_free;
+ }
+
if (!set_maparg_lhs_rhs(lhs.data, lhs.size,
rhs.data, rhs.size, lua_funcref,
CPO_TO_CPO_FLAGS, &parsed_args)) {
diff --git a/src/nvim/mapping.h b/src/nvim/mapping.h
index b19131a686..98d0074075 100644
--- a/src/nvim/mapping.h
+++ b/src/nvim/mapping.h
@@ -21,6 +21,7 @@ struct map_arguments {
bool script;
bool silent;
bool unique;
+ bool replace_keycodes;
/// The {lhs} of the mapping.
///
@@ -44,7 +45,7 @@ struct map_arguments {
char *desc; /// map description
};
typedef struct map_arguments MapArguments;
-#define MAP_ARGUMENTS_INIT { false, false, false, false, false, false, false, \
+#define MAP_ARGUMENTS_INIT { false, false, false, false, false, false, false, false, \
{ 0 }, 0, { 0 }, 0, NULL, 0, LUA_NOREF, false, NULL, 0, NULL }
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua
index 6bc6651e04..23c0a14d39 100644
--- a/test/functional/api/keymap_spec.lua
+++ b/test/functional/api/keymap_spec.lua
@@ -822,7 +822,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it('can make lua expr mappings', function()
exec_lua [[
- vim.api.nvim_set_keymap ('n', 'aa', '', {callback = function() return vim.api.nvim_replace_termcodes(':lua SomeValue = 99<cr>', true, false, true) end, expr = true })
+ vim.api.nvim_set_keymap ('n', 'aa', '', {callback = function() return ':lua SomeValue = 99<cr>' end, expr = true, replace_keycodes = true })
]]
feed('aa')
@@ -830,6 +830,16 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq(99, exec_lua[[return SomeValue]])
end)
+ it('can make lua expr mappings without replacing keycodes', function()
+ exec_lua [[
+ vim.api.nvim_set_keymap ('i', 'aa', '', {callback = function() return '<space>' end, expr = true })
+ ]]
+
+ feed('iaa<esc>')
+
+ eq({'<space>'}, meths.buf_get_lines(0, 0, -1, false))
+ end)
+
it('does not reset pum in lua mapping', function()
eq(0, exec_lua [[
VisibleCount = 0
@@ -1020,7 +1030,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
it('can make lua expr mappings', function()
exec_lua [[
- vim.api.nvim_buf_set_keymap (0, 'n', 'aa', '', {callback = function() return vim.api.nvim_replace_termcodes(':lua SomeValue = 99<cr>', true, false, true) end, expr = true })
+ vim.api.nvim_buf_set_keymap (0, 'n', 'aa', '', {callback = function() return ':lua SomeValue = 99<cr>' end, expr = true, replace_keycodes = true })
]]
feed('aa')
@@ -1028,6 +1038,17 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
eq(99, exec_lua[[return SomeValue ]])
end)
+ it('can make lua expr mappings without replacing keycodes', function()
+ exec_lua [[
+ vim.api.nvim_buf_set_keymap (0, 'i', 'aa', '', {callback = function() return '<space>' end, expr = true })
+ ]]
+
+ feed('iaa<esc>')
+
+ eq({'<space>'}, meths.buf_get_lines(0, 0, -1, false))
+ end)
+
+
it('can overwrite lua mappings', function()
eq(0, exec_lua [[
GlobalCount = 0