diff options
author | ii14 <59243201+ii14@users.noreply.github.com> | 2022-08-01 15:35:08 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-01 21:35:08 +0800 |
commit | db6e93c48df551e2906c9e0f4472f9e54cea3dd9 (patch) | |
tree | a62b94332e6f23a49adce724759a4c23edf7cf03 | |
parent | 9f5d5aa3da30aab40bbb38fddfc70257444d50a8 (diff) | |
download | rneovim-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.txt | 4 | ||||
-rw-r--r-- | runtime/doc/lua.txt | 5 | ||||
-rw-r--r-- | runtime/lua/vim/keymap.lua | 20 | ||||
-rw-r--r-- | src/nvim/api/keysets.lua | 1 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 3 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/mapping.c | 23 | ||||
-rw-r--r-- | src/nvim/mapping.h | 3 | ||||
-rw-r--r-- | test/functional/api/keymap_spec.lua | 25 |
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 |