aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/doc/lua.txt20
-rw-r--r--runtime/doc/news.txt1
-rw-r--r--runtime/lua/vim/_editor.lua31
3 files changed, 35 insertions, 17 deletions
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 74a0ba821a..6ae1a1a3b8 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1635,7 +1635,7 @@ vim.notify_once({msg}, {level}, {opts}) *vim.notify_once()*
Return: ~
(`boolean`) true if message was displayed, else false
-vim.on_key({fn}, {ns_id}) *vim.on_key()*
+vim.on_key({fn}, {ns_id}, {opts}) *vim.on_key()*
Adds Lua function {fn} with namespace id {ns_id} as a listener to every,
yes every, input key.
@@ -1649,17 +1649,19 @@ vim.on_key({fn}, {ns_id}) *vim.on_key()*
• {fn} will not be cleared by |nvim_buf_clear_namespace()|
Parameters: ~
- • {fn} (`fun(key: string, typed: string)?`) Function invoked for
- every input key, after mappings have been applied but before
- further processing. Arguments {key} and {typed} are raw
- keycodes, where {key} is the key after mappings are applied,
- and {typed} is the key(s) before mappings are applied.
- {typed} may be empty if {key} is produced by non-typed key(s)
- or by the same typed key(s) that produced a previous {key}.
- When {fn} is `nil` and {ns_id} is specified, the callback
+ • {fn} (`fun(key: string, typed: string): string??`) Function
+ invoked for every input key, after mappings have been applied
+ but before further processing. Arguments {key} and {typed}
+ are raw keycodes, where {key} is the key after mappings are
+ applied, and {typed} is the key(s) before mappings are
+ applied. {typed} may be empty if {key} is produced by
+ non-typed key(s) or by the same typed key(s) that produced a
+ previous {key}. If {fn} returns an empty string, {key} is
+ discarded/ignored. When {fn} is `nil`, the callback
associated with namespace {ns_id} is removed.
• {ns_id} (`integer?`) Namespace ID. If nil or 0, generates and returns
a new |nvim_create_namespace()| id.
+ • {opts} (`table?`) Optional parameters
Return: ~
(`integer`) Namespace id associated with {fn}. Or count of all
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 91d36accc7..c01bb46de7 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -191,6 +191,7 @@ EVENTS
• |CompleteDone| now sets the `reason` key in `v:event` which specifies the reason
for completion being done.
+• |vim.on_key()| callbacks can consume the key by returning an empty string.
LSP
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index c6aa303124..3167721a70 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -651,7 +651,7 @@ do
end
end
-local on_key_cbs = {} --- @type table<integer,function>
+local on_key_cbs = {} --- @type table<integer,[function, table]>
--- Adds Lua function {fn} with namespace id {ns_id} as a listener to every,
--- yes every, input key.
@@ -664,34 +664,37 @@ local on_key_cbs = {} --- @type table<integer,function>
--- it won't be invoked for those keys.
---@note {fn} will not be cleared by |nvim_buf_clear_namespace()|
---
----@param fn fun(key: string, typed: string)? Function invoked for every input key,
+---@param fn nil|fun(key: string, typed: string): string? Function invoked for every input key,
--- after mappings have been applied but before further processing. Arguments
--- {key} and {typed} are raw keycodes, where {key} is the key after mappings
--- are applied, and {typed} is the key(s) before mappings are applied.
--- {typed} may be empty if {key} is produced by non-typed key(s) or by the
--- same typed key(s) that produced a previous {key}.
---- When {fn} is `nil` and {ns_id} is specified, the callback associated with
---- namespace {ns_id} is removed.
+--- If {fn} returns an empty string, {key} is discarded/ignored.
+--- When {fn} is `nil`, the callback associated with namespace {ns_id} is removed.
---@param ns_id integer? Namespace ID. If nil or 0, generates and returns a
--- new |nvim_create_namespace()| id.
+---@param opts table? Optional parameters
---
---@see |keytrans()|
---
---@return integer Namespace id associated with {fn}. Or count of all callbacks
---if on_key() is called without arguments.
-function vim.on_key(fn, ns_id)
+function vim.on_key(fn, ns_id, opts)
if fn == nil and ns_id == nil then
return vim.tbl_count(on_key_cbs)
end
vim.validate('fn', fn, 'callable', true)
vim.validate('ns_id', ns_id, 'number', true)
+ vim.validate('opts', opts, 'table', true)
+ opts = opts or {}
if ns_id == nil or ns_id == 0 then
ns_id = vim.api.nvim_create_namespace('')
end
- on_key_cbs[ns_id] = fn
+ on_key_cbs[ns_id] = fn and { fn, opts }
return ns_id
end
@@ -700,12 +703,23 @@ end
function vim._on_key(buf, typed_buf)
local failed_ns_ids = {}
local failed_messages = {}
+ local discard = false
for k, v in pairs(on_key_cbs) do
- local ok, err_msg = pcall(v, buf, typed_buf)
+ local ok, rv = pcall(v[1], buf, typed_buf)
+ if ok and rv ~= nil then
+ if type(rv) == 'string' and #rv == 0 then
+ discard = true
+ -- break -- Without break deliver to all callbacks even when it eventually discards.
+ -- "break" does not make sense unless callbacks are sorted by ???.
+ else
+ ok = false
+ rv = 'return string must be empty'
+ end
+ end
if not ok then
vim.on_key(nil, k)
table.insert(failed_ns_ids, k)
- table.insert(failed_messages, err_msg)
+ table.insert(failed_messages, rv)
end
end
@@ -718,6 +732,7 @@ function vim._on_key(buf, typed_buf)
)
)
end
+ return discard
end
--- Convert UTF-32, UTF-16 or UTF-8 {index} to byte index.