diff options
author | bfredl <bjorn.linse@gmail.com> | 2023-05-28 12:09:52 +0200 |
---|---|---|
committer | bfredl <bjorn.linse@gmail.com> | 2023-06-09 21:25:43 +0200 |
commit | 42bbc4fabcf948ac6b8798b8992bcba1fc1d3e59 (patch) | |
tree | dbb621867adf58beac42647e3e6267e55521909e | |
parent | 49019da86e283052c042509689f3a287056d1340 (diff) | |
download | rneovim-42bbc4fabcf948ac6b8798b8992bcba1fc1d3e59.tar.gz rneovim-42bbc4fabcf948ac6b8798b8992bcba1fc1d3e59.tar.bz2 rneovim-42bbc4fabcf948ac6b8798b8992bcba1fc1d3e59.zip |
feat(api): support abbreviations in nvim_set_keymap
closes #19198
-rw-r--r-- | runtime/doc/api.txt | 4 | ||||
-rw-r--r-- | runtime/doc/news.txt | 2 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 1 | ||||
-rw-r--r-- | src/nvim/mapping.c | 14 | ||||
-rw-r--r-- | test/functional/api/keymap_spec.lua | 48 |
5 files changed, 65 insertions, 4 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 83422c9501..8c44db1867 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -1486,7 +1486,9 @@ nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()* Parameters: ~ • {mode} Mode short-name (map command prefix: "n", "i", "v", "x", …) or - "!" for |:map!|, or empty string for |:map|. + "!" for |:map!|, or empty string for |:map|. "ia", "ca" or + "!a" for abbreviation in insert mode, cmdline mode, or both, + respectively • {lhs} Left-hand-side |{lhs}| of the mapping. • {rhs} Right-hand-side |{rhs}| of the mapping. • {opts} Optional parameters map: Accepts all |:map-arguments| as keys diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 87dfefcce8..a901c4f13c 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -82,6 +82,8 @@ The following new APIs or features were added. • |vim.system()| for running system commands. +• |nvim_set_keymap()| now supports abbreviations. + ============================================================================== CHANGED FEATURES *news-changed* diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index d93af6a2a4..4bbbf644a8 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1420,6 +1420,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode) /// @param channel_id /// @param mode Mode short-name (map command prefix: "n", "i", "v", "x", …) /// or "!" for |:map!|, or empty string for |:map|. +/// "ia", "ca" or "!a" for abbreviation in insert mode, cmdline mode, or both, respectively /// @param lhs Left-hand-side |{lhs}| of the mapping. /// @param rhs Right-hand-side |{rhs}| of the mapping. /// @param opts Optional parameters map: Accepts all |:map-arguments| as keys except |<buffer>|, diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index e40e67cead..d7747ee291 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -2603,13 +2603,21 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod goto fail_and_free; } - if (mode.size > 1) { + bool is_abbrev = false; + if (mode.size > 2) { api_set_error(err, kErrorTypeValidation, "Shortname is too long: %s", mode.data); goto fail_and_free; + } else if (mode.size == 2) { + if ((mode.data[0] != '!' && mode.data[0] != 'i' && mode.data[0] != 'c') + || mode.data[1] != 'a') { + api_set_error(err, kErrorTypeValidation, "Shortname is too long: %s", mode.data); + goto fail_and_free; + } + is_abbrev = true; } int mode_val; // integer value of the mapping mode, to be passed to do_map() char *p = (mode.size) ? mode.data : "m"; - if (strncmp(p, "!", 2) == 0) { + if (*p == '!') { mode_val = get_map_mode(&p, true); // mapmode-ic } else { mode_val = get_map_mode(&p, false); @@ -2654,7 +2662,7 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod maptype_val = MAPTYPE_NOREMAP; } - switch (buf_do_map(maptype_val, &parsed_args, mode_val, 0, target_buf)) { + switch (buf_do_map(maptype_val, &parsed_args, mode_val, is_abbrev, target_buf)) { case 0: break; case 1: diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua index e239717d3a..e56dfd483a 100644 --- a/test/functional/api/keymap_spec.lua +++ b/test/functional/api/keymap_spec.lua @@ -988,6 +988,54 @@ describe('nvim_set_keymap, nvim_del_keymap', function() eq("\nn lhs rhs\n map description", helpers.exec_capture("nmap lhs")) end) + + it('can define !-mode abbreviations with lua callbacks', function() + exec_lua [[ + GlobalCount = 0 + vim.api.nvim_set_keymap('!a', 'foo', '', {expr = true, callback = function() + GlobalCount = GlobalCount + 1 + return tostring(GlobalCount) + end}) + ]] + + feed 'iThe foo and the bar and the foo again<esc>' + eq('The 1 and the bar and the 2 again', meths.get_current_line()) + + feed ':let x = "The foo is the one"<cr>' + eq('The 3 is the one', meths.eval'x') + end) + + it('can define insert mode abbreviations with lua callbacks', function() + exec_lua [[ + GlobalCount = 0 + vim.api.nvim_set_keymap('ia', 'foo', '', {expr = true, callback = function() + GlobalCount = GlobalCount + 1 + return tostring(GlobalCount) + end}) + ]] + + feed 'iThe foo and the bar and the foo again<esc>' + eq('The 1 and the bar and the 2 again', meths.get_current_line()) + + feed ':let x = "The foo is the one"<cr>' + eq('The foo is the one', meths.eval'x') + end) + + it('can define cmdline mode abbreviations with lua callbacks', function() + exec_lua [[ + GlobalCount = 0 + vim.api.nvim_set_keymap('ca', 'foo', '', {expr = true, callback = function() + GlobalCount = GlobalCount + 1 + return tostring(GlobalCount) + end}) + ]] + + feed 'iThe foo and the bar and the foo again<esc>' + eq('The foo and the bar and the foo again', meths.get_current_line()) + + feed ':let x = "The foo is the one"<cr>' + eq('The 1 is the one', meths.eval'x') + end) end) describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() |