aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2023-05-28 12:09:52 +0200
committerbfredl <bjorn.linse@gmail.com>2023-06-09 21:25:43 +0200
commit42bbc4fabcf948ac6b8798b8992bcba1fc1d3e59 (patch)
treedbb621867adf58beac42647e3e6267e55521909e
parent49019da86e283052c042509689f3a287056d1340 (diff)
downloadrneovim-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.txt4
-rw-r--r--runtime/doc/news.txt2
-rw-r--r--src/nvim/api/vim.c1
-rw-r--r--src/nvim/mapping.c14
-rw-r--r--test/functional/api/keymap_spec.lua48
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()