diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/doc/lua.txt | 20 | ||||
-rw-r--r-- | runtime/doc/news.txt | 1 | ||||
-rw-r--r-- | runtime/lua/vim/_editor.lua | 31 |
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. |