From 0e42c81c7fd429529d89458349c7cdde254d5406 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 12 Oct 2024 08:07:05 +0800 Subject: fix(lua): avoid recursive vim.on_key() callback (#30753) --- runtime/lua/vim/_editor.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 2e829578a7..17a87dd9fd 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -658,6 +658,8 @@ local on_key_cbs = {} --- @type table --- and cannot be toggled dynamically. --- ---@note {fn} will be removed on error. +---@note {fn} won't be invoked recursively, i.e. if {fn} itself consumes input, +--- 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)? -- cgit From 45f8f957c05ca18ea86b8b6bb6c0a903c9140b7b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 12 Oct 2024 12:20:06 +0800 Subject: docs(lua): clarify when on_key "typed" will be empty (#30774) --- runtime/lua/vim/_editor.lua | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 17a87dd9fd..ce269f087d 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -662,15 +662,18 @@ local on_key_cbs = {} --- @type table --- 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 on every key press. |i_CTRL-V| ---- {key} is the key after mappings have been applied, and ---- {typed} is the key(s) before mappings are applied, which ---- may be empty if {key} is produced by non-typed keys. ---- When {fn} is nil and {ns_id} is specified, the callback ---- associated with namespace {ns_id} is removed. +---@param 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 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. +--- new |nvim_create_namespace()| id. +--- +---@see |keytrans()| --- ---@return integer Namespace id associated with {fn}. Or count of all callbacks ---if on_key() is called without arguments. -- cgit From 3f3e4837d5f7d2d9cb1c89bd3a5b2ee8a730772a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 16 Oct 2024 17:03:48 +0100 Subject: perf(validate): use lighter version - Also fix `vim.validate()` for PUC Lua when showing errors for values that aren't string or number. --- runtime/lua/vim/_editor.lua | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index ce269f087d..f0b8cf6a52 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -473,9 +473,7 @@ do --- @param handle? false|integer --- @return vim.var_accessor local function make_dict_accessor(scope, handle) - validate({ - scope = { scope, 's' }, - }) + validate('scope', scope, 'string') local mt = {} function mt:__newindex(k, v) return vim._setvar(scope, handle or 0, k, v) @@ -1171,12 +1169,10 @@ function vim.deprecate(name, alternative, version, plugin, backtrace) local displayed = vim._truncated_echo_once(msg) return displayed and msg or nil else - vim.validate { - name = { name, 'string' }, - alternative = { alternative, 'string', true }, - version = { version, 'string', true }, - plugin = { plugin, 'string', true }, - } + vim.validate('name', name, 'string') + vim.validate('alternative', alternative, 'string', true) + vim.validate('version', version, 'string', true) + vim.validate('plugin', plugin, 'string', true) local msg = ('%s is deprecated'):format(name) msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or (msg .. '.') -- cgit From 960fdc775a88389d8b19389b8c74c98921b9acac Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 17 Oct 2024 17:58:13 +0200 Subject: fix(lua): vim.deprecate does not support major>0 --- runtime/lua/vim/_editor.lua | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index f0b8cf6a52..037cef9383 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -1149,16 +1149,22 @@ function vim.deprecate(name, alternative, version, plugin, backtrace) if plugin == 'Nvim' then require('vim.deprecated.health').add(name, version, traceback(), alternative) - -- Only issue warning if feature is hard-deprecated as specified by MAINTAIN.md. - -- Example: if removal_version is 0.12 (soft-deprecated since 0.10-dev), show warnings starting at - -- 0.11, including 0.11-dev + -- Show a warning only if feature is hard-deprecated (see MAINTAIN.md). + -- Example: if removal `version` is 0.12 (soft-deprecated since 0.10-dev), show warnings + -- starting at 0.11, including 0.11-dev. local major, minor = version:match('(%d+)%.(%d+)') major, minor = tonumber(major), tonumber(minor) + local nvim_major = 0 --- Current Nvim major version. + + -- We can't "subtract" from a major version, so: + -- * Always treat `major > nvim_major` as soft-deprecation. + -- * Compare `minor - 1` if `major == nvim_major`. + if major > nvim_major then + return -- Always soft-deprecation (see MAINTAIN.md). + end local hard_deprecated_since = string.format('nvim-%d.%d', major, minor - 1) - -- Assume there will be no next minor version before bumping up the major version - local is_hard_deprecated = minor == 0 or vim.fn.has(hard_deprecated_since) == 1 - if not is_hard_deprecated then + if major == nvim_major and vim.fn.has(hard_deprecated_since) == 0 then return end -- cgit From 18b43c331d8a0ed87d7cbefe2a18543b8e4ad360 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 17 Oct 2024 11:16:16 +0200 Subject: refactor: rename vim.highlight => vim.hl Problem: - `vim.highlight` module does not follow `:help dev-name-common`, which documents the name for "highlight" as "hl". - Shorter names are usually preferred. Solution: Rename `vim.highlight` to `vim.hl`. This is not a breaking change until 2.0 (or maybe never). --- runtime/lua/vim/_editor.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 037cef9383..7aba7498f9 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -32,7 +32,7 @@ for k, v in pairs({ func = true, F = true, lsp = true, - highlight = true, + hl = true, diagnostic = true, keymap = true, ui = true, @@ -1197,4 +1197,7 @@ require('vim._options') ---@deprecated vim.loop = vim.uv +-- Deprecated. Remove at Nvim 2.0 +vim.highlight = vim._defer_deprecated_module('vim.highlight', 'vim.hl') + return vim -- cgit From 3572319b4cb1a4163624a5fe328886f1928dbc4a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 18 Oct 2024 11:33:12 +0100 Subject: feat(vim.validate): improve fast form and deprecate spec form Problem: `vim.validate()` takes two forms when it only needs one. Solution: - Teach the fast form all the features of the spec form. - Deprecate the spec form. - General optimizations for both forms. - Add a `message` argument which can be used alongside or in place of the `optional` argument. --- runtime/lua/vim/_editor.lua | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 7aba7498f9..58283ac64b 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -467,13 +467,11 @@ vim.cmd = setmetatable({}, { -- These are the vim.env/v/g/o/bo/wo variable magic accessors. do - local validate = vim.validate - --- @param scope string --- @param handle? false|integer --- @return vim.var_accessor local function make_dict_accessor(scope, handle) - validate('scope', scope, 'string') + vim.validate('scope', scope, 'string') local mt = {} function mt:__newindex(k, v) return vim._setvar(scope, handle or 0, k, v) @@ -589,7 +587,7 @@ end ---@param timeout integer Number of milliseconds to wait before calling `fn` ---@return table timer luv timer object function vim.defer_fn(fn, timeout) - vim.validate({ fn = { fn, 'c', true } }) + vim.validate('fn', fn, 'callable', true) local timer = assert(vim.uv.new_timer()) timer:start( timeout, @@ -680,10 +678,8 @@ function vim.on_key(fn, ns_id) return vim.tbl_count(on_key_cbs) end - vim.validate({ - fn = { fn, 'c', true }, - ns_id = { ns_id, 'n', true }, - }) + vim.validate('fn', fn, 'callable', true) + vim.validate('ns_id', ns_id, 'number', true) if ns_id == nil or ns_id == 0 then ns_id = vim.api.nvim_create_namespace('') -- cgit From 230b0c7f021a57647a658edce27fe115343f083f Mon Sep 17 00:00:00 2001 From: Tristan Knight Date: Wed, 23 Oct 2024 14:33:57 +0100 Subject: feat(stdlib): overload vim.str_byteindex, vim.str_utfindex #30735 PROBLEM: There are several limitations to vim.str_byteindex, vim.str_utfindex: 1. They throw given out-of-range indexes. An invalid (often user/lsp-provided) index doesn't feel exceptional and should be handled by the caller. `:help dev-error-patterns` suggests that `retval, errmsg` is the preferred way to handle this kind of failure. 2. They cannot accept an encoding. So LSP needs wrapper functions. #25272 3. The current signatures are not extensible. * Calling: The function currently uses a fairly opaque boolean value to indicate to identify the encoding. * Returns: The fact it can throw requires wrapping in pcall. 4. The current name doesn't follow suggestions in `:h dev-naming` and I think `get` would be suitable. SOLUTION: - Because these are performance-sensitive, don't introduce `opts`. - Introduce an "overload" that accepts `encoding:string` and `strict_indexing:bool` params. ```lua local col = vim.str_utfindex(line, encoding, [index, [no_out_of_range]]) ``` Support the old versions by dispatching on the type of argument 2, and deprecate that form. ```lua vim.str_utfindex(line) -- (utf-32 length, utf-16 length), deprecated vim.str_utfindex(line, index) -- (utf-32 index, utf-16 index), deprecated vim.str_utfindex(line, 'utf-16') -- utf-16 length vim.str_utfindex(line, 'utf-16', index) -- utf-16 index vim.str_utfindex(line, 'utf-16', math.huge) -- error: index out of range vim.str_utfindex(line, 'utf-16', math.huge, false) -- utf-16 length ``` --- runtime/lua/vim/_editor.lua | 128 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 58283ac64b..496bbf747c 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -68,6 +68,12 @@ vim.log = { }, } +local utfs = { + ['utf-8'] = true, + ['utf-16'] = true, + ['utf-32'] = true, +} + -- TODO(lewis6991): document that the signature is system({cmd}, [{opts},] {on_exit}) --- Runs a system command or throws an error if {cmd} cannot be run. --- @@ -714,7 +720,127 @@ function vim._on_key(buf, typed_buf) end end ---- Generates a list of possible completions for the string. +--- Convert UTF-32, UTF-16 or UTF-8 {index} to byte index. +--- If {strict_indexing} is false +--- then then an out of range index will return byte length +--- instead of throwing an error. +--- +--- Invalid UTF-8 and NUL is treated like in |vim.str_utfindex()|. +--- An {index} in the middle of a UTF-16 sequence is rounded upwards to +--- the end of that sequence. +---@param s string +---@param encoding "utf-8"|"utf-16"|"utf-32" +---@param index integer +---@param strict_indexing? boolean # default: true +---@return integer +function vim.str_byteindex(s, encoding, index, strict_indexing) + if type(encoding) == 'number' then + -- Legacy support for old API + -- Parameters: ~ + -- • {str} (`string`) + -- • {index} (`integer`) + -- • {use_utf16} (`boolean?`) + local old_index = encoding + local use_utf16 = index or false + return vim.__str_byteindex(s, old_index, use_utf16) or error('index out of range') + end + + vim.validate('s', s, 'string') + vim.validate('index', index, 'number') + + local len = #s + + if index == 0 or len == 0 then + return 0 + end + + vim.validate('encoding', encoding, function(v) + return utfs[v], 'invalid encoding' + end) + + vim.validate('strict_indexing', strict_indexing, 'boolean', true) + if strict_indexing == nil then + strict_indexing = true + end + + if encoding == 'utf-8' then + if index > len then + return strict_indexing and error('index out of range') or len + end + return index + end + return vim.__str_byteindex(s, index, encoding == 'utf-16') + or strict_indexing and error('index out of range') + or len +end + +--- Convert byte index to UTF-32, UTF-16 or UTF-8 indices. If {index} is not +--- supplied, the length of the string is used. All indices are zero-based. +--- +--- If {strict_indexing} is false then an out of range index will return string +--- length instead of throwing an error. +--- Invalid UTF-8 bytes, and embedded surrogates are counted as one code point +--- each. An {index} in the middle of a UTF-8 sequence is rounded upwards to the end of +--- that sequence. +---@param s string +---@param encoding "utf-8"|"utf-16"|"utf-32" +---@param index? integer +---@param strict_indexing? boolean # default: true +---@return integer +function vim.str_utfindex(s, encoding, index, strict_indexing) + if encoding == nil or type(encoding) == 'number' then + -- Legacy support for old API + -- Parameters: ~ + -- • {str} (`string`) + -- • {index} (`integer?`) + local old_index = encoding + local col32, col16 = vim.__str_utfindex(s, old_index) --[[@as integer,integer]] + if not col32 or not col16 then + error('index out of range') + end + -- Return (multiple): ~ + -- (`integer`) UTF-32 index + -- (`integer`) UTF-16 index + return col32, col16 + end + + vim.validate('s', s, 'string') + vim.validate('index', index, 'number', true) + if not index then + index = math.huge + strict_indexing = false + end + + if index == 0 then + return 0 + end + + vim.validate('encoding', encoding, function(v) + return utfs[v], 'invalid encoding' + end) + + vim.validate('strict_indexing', strict_indexing, 'boolean', true) + if strict_indexing == nil then + strict_indexing = true + end + + if encoding == 'utf-8' then + local len = #s + return index <= len and index or (strict_indexing and error('index out of range') or len) + end + local col32, col16 = vim.__str_utfindex(s, index) --[[@as integer?,integer?]] + local col = encoding == 'utf-16' and col16 or col32 + if col then + return col + end + if strict_indexing then + error('index out of range') + end + local max32, max16 = vim.__str_utfindex(s)--[[@as integer integer]] + return encoding == 'utf-16' and max16 or max32 +end + +--- Generates a list of possible completions for the str --- String has the pattern. --- --- 1. Can we get it to just return things in the global namespace with that name prefix -- cgit From 25b53b593ef6f229fbec5b3dc205a7539579d13a Mon Sep 17 00:00:00 2001 From: Tristan Knight Date: Sat, 26 Oct 2024 15:38:25 +0100 Subject: refactor(lsp): drop str_byteindex/str_utfindex wrappers #30915 * deprecate old signatures * move to new str_byteindex/str_utfindex signature * use single-underscore name (double-underscore is reserved for Lua itself) --- runtime/lua/vim/_editor.lua | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 496bbf747c..c6aa303124 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -545,7 +545,7 @@ function vim.region(bufnr, pos1, pos2, regtype, inclusive) -- TODO: handle double-width characters if regtype:byte() == 22 then local bufline = vim.api.nvim_buf_get_lines(bufnr, pos1[1], pos1[1] + 1, true)[1] - pos1[2] = vim.str_utfindex(bufline, pos1[2]) + pos1[2] = vim.str_utfindex(bufline, 'utf-32', pos1[2]) end local region = {} @@ -557,14 +557,14 @@ function vim.region(bufnr, pos1, pos2, regtype, inclusive) c2 = c1 + tonumber(regtype:sub(2)) -- and adjust for non-ASCII characters local bufline = vim.api.nvim_buf_get_lines(bufnr, l, l + 1, true)[1] - local utflen = vim.str_utfindex(bufline, #bufline) + local utflen = vim.str_utfindex(bufline, 'utf-32', #bufline) if c1 <= utflen then - c1 = assert(tonumber(vim.str_byteindex(bufline, c1))) + c1 = assert(tonumber(vim.str_byteindex(bufline, 'utf-32', c1))) else c1 = #bufline + 1 end if c2 <= utflen then - c2 = assert(tonumber(vim.str_byteindex(bufline, c2))) + c2 = assert(tonumber(vim.str_byteindex(bufline, 'utf-32', c2))) else c2 = #bufline + 1 end @@ -740,9 +740,14 @@ function vim.str_byteindex(s, encoding, index, strict_indexing) -- • {str} (`string`) -- • {index} (`integer`) -- • {use_utf16} (`boolean?`) + vim.deprecate( + 'vim.str_byteindex', + 'vim.str_byteindex(s, encoding, index, strict_indexing)', + '1.0' + ) local old_index = encoding local use_utf16 = index or false - return vim.__str_byteindex(s, old_index, use_utf16) or error('index out of range') + return vim._str_byteindex(s, old_index, use_utf16) or error('index out of range') end vim.validate('s', s, 'string') @@ -769,7 +774,7 @@ function vim.str_byteindex(s, encoding, index, strict_indexing) end return index end - return vim.__str_byteindex(s, index, encoding == 'utf-16') + return vim._str_byteindex(s, index, encoding == 'utf-16') or strict_indexing and error('index out of range') or len end @@ -793,8 +798,13 @@ function vim.str_utfindex(s, encoding, index, strict_indexing) -- Parameters: ~ -- • {str} (`string`) -- • {index} (`integer?`) + vim.deprecate( + 'vim.str_utfindex', + 'vim.str_utfindex(s, encoding, index, strict_indexing)', + '1.0' + ) local old_index = encoding - local col32, col16 = vim.__str_utfindex(s, old_index) --[[@as integer,integer]] + local col32, col16 = vim._str_utfindex(s, old_index) --[[@as integer,integer]] if not col32 or not col16 then error('index out of range') end @@ -828,7 +838,7 @@ function vim.str_utfindex(s, encoding, index, strict_indexing) local len = #s return index <= len and index or (strict_indexing and error('index out of range') or len) end - local col32, col16 = vim.__str_utfindex(s, index) --[[@as integer?,integer?]] + local col32, col16 = vim._str_utfindex(s, index) --[[@as integer?,integer?]] local col = encoding == 'utf-16' and col16 or col32 if col then return col @@ -836,7 +846,7 @@ function vim.str_utfindex(s, encoding, index, strict_indexing) if strict_indexing then error('index out of range') end - local max32, max16 = vim.__str_utfindex(s)--[[@as integer integer]] + local max32, max16 = vim._str_utfindex(s)--[[@as integer integer]] return encoding == 'utf-16' and max16 or max32 end -- cgit From b34e137e43d359c8db4fb76028dea3b410842aff Mon Sep 17 00:00:00 2001 From: errael Date: Thu, 31 Oct 2024 18:11:15 -0700 Subject: feat(lua): allow vim.on_key() callback to consume the key (#30939) --- runtime/lua/vim/_editor.lua | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'runtime/lua/vim/_editor.lua') 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 +local on_key_cbs = {} --- @type 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 --- 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. -- cgit From 3688a333544251c887d78e6501eec55f0fb685f8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 2 Nov 2024 10:11:06 +0800 Subject: fix(lua): show stacktrace for error in vim.on_key() callback (#31021) --- runtime/lua/vim/_editor.lua | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 3167721a70..cbab2a0165 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -701,11 +701,13 @@ end --- Executes the on_key callbacks. ---@private function vim._on_key(buf, typed_buf) - local failed_ns_ids = {} - local failed_messages = {} + local failed = {} ---@type [integer, string][] local discard = false for k, v in pairs(on_key_cbs) do - local ok, rv = pcall(v[1], buf, typed_buf) + local fn = v[1] + local ok, rv = xpcall(function() + return fn(buf, typed_buf) + end, debug.traceback) if ok and rv ~= nil then if type(rv) == 'string' and #rv == 0 then discard = true @@ -718,19 +720,16 @@ function vim._on_key(buf, typed_buf) end if not ok then vim.on_key(nil, k) - table.insert(failed_ns_ids, k) - table.insert(failed_messages, rv) + table.insert(failed, { k, rv }) end end - if failed_ns_ids[1] then - error( - string.format( - "Error executing 'on_key' with ns_ids '%s'\n Messages: %s", - table.concat(failed_ns_ids, ', '), - table.concat(failed_messages, '\n') - ) - ) + if #failed > 0 then + local errmsg = '' + for _, v in ipairs(failed) do + errmsg = errmsg .. string.format('\nWith ns_id %d: %s', v[1], v[2]) + end + error(errmsg) end return discard end -- cgit From 3e855d533f4477ffddfe94ccea48255979c8b7fb Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 11 Nov 2024 14:23:38 +0000 Subject: perf(lsp): use faster version of str_byteindex --- runtime/lua/vim/_editor.lua | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index cbab2a0165..b4a1e0fc15 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -764,8 +764,11 @@ function vim.str_byteindex(s, encoding, index, strict_indexing) return vim._str_byteindex(s, old_index, use_utf16) or error('index out of range') end - vim.validate('s', s, 'string') - vim.validate('index', index, 'number') + -- Avoid vim.validate for performance. + if type(s) ~= 'string' or type(index) ~= 'number' then + vim.validate('s', s, 'string') + vim.validate('index', index, 'number') + end local len = #s @@ -773,11 +776,15 @@ function vim.str_byteindex(s, encoding, index, strict_indexing) return 0 end - vim.validate('encoding', encoding, function(v) - return utfs[v], 'invalid encoding' - end) + if not utfs[encoding] then + vim.validate('encoding', encoding, function(v) + return utfs[v], 'invalid encoding' + end) + end - vim.validate('strict_indexing', strict_indexing, 'boolean', true) + if strict_indexing ~= nil and type(strict_indexing) ~= 'boolean' then + vim.validate('strict_indexing', strict_indexing, 'boolean', true) + end if strict_indexing == nil then strict_indexing = true end @@ -828,8 +835,11 @@ function vim.str_utfindex(s, encoding, index, strict_indexing) return col32, col16 end - vim.validate('s', s, 'string') - vim.validate('index', index, 'number', true) + if type(s) ~= 'string' or (index ~= nil and type(index) ~= 'number') then + vim.validate('s', s, 'string') + vim.validate('index', index, 'number', true) + end + if not index then index = math.huge strict_indexing = false @@ -839,11 +849,15 @@ function vim.str_utfindex(s, encoding, index, strict_indexing) return 0 end - vim.validate('encoding', encoding, function(v) - return utfs[v], 'invalid encoding' - end) + if not utfs[encoding] then + vim.validate('encoding', encoding, function(v) + return utfs[v], 'invalid encoding' + end) + end - vim.validate('strict_indexing', strict_indexing, 'boolean', true) + if strict_indexing ~= nil and type(strict_indexing) ~= 'boolean' then + vim.validate('strict_indexing', strict_indexing, 'boolean', true) + end if strict_indexing == nil then strict_indexing = true end -- cgit From e025f5a5b30a1ef92e88fed0f0c548d2240d30c0 Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Sun, 17 Nov 2024 19:21:50 +0100 Subject: fix(messages): proper multiline Lua print() messages #31205 Problem: Separate message emitted for each newline present in Lua print() arguments. Solution: Make msg_multiline() handle NUL bytes. Refactor print() to use msg_multiline(). Refactor vim.print() to use print(). --- runtime/lua/vim/_editor.lua | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index b4a1e0fc15..44f17b3f85 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -1151,21 +1151,16 @@ end --- @param ... any --- @return any # given arguments. function vim.print(...) - if vim.in_fast_event() then - print(...) - return ... - end - + local msg = {} for i = 1, select('#', ...) do local o = select(i, ...) if type(o) == 'string' then - vim.api.nvim_out_write(o) + table.insert(msg, o) else - vim.api.nvim_out_write(vim.inspect(o, { newline = '\n', indent = ' ' })) + table.insert(msg, vim.inspect(o, { newline = '\n', indent = ' ' })) end - vim.api.nvim_out_write('\n') end - + print(table.concat(msg, '\n')) return ... end -- cgit