@ 261105.2

251129.12 · b51b97ffa3cbd9baddedfe2e06a7cfb6f68d5440

chore: fix more types

chore: prefer local alias

chore: reuse debounce logic

chore: remove uncessary assert

chore: unused/deprecated

reading declarations

.emmyrc.json

@@ -12,32 +12,14 @@     "disable": [       "unnecessary-if",       "param-type-not-match",-      "type-not-found",-      "preferred-local-alias",       "need-check-nil",-      "undefined-field",-      "assign-type-mismatch",-      "inject-field",-      "redundant-return-value",-      "unnecessary-assert",-      "return-type-mismatch",-      "generic-constraint-mismatch",       "await-in-sync",-      "redundant-parameter",-      "missing-fields",-      "missing-return-value",-      "cast-type-mismatch",-      "missing-parameter",-      "access-invisible",-      "global-in-non-module",-      "duplicate-require",-      "unused"+      "global-in-non-module"     ]   },   "workspace": {     "library": [       "$VIMRUNTIME",-      "${3rd}/luv/library",       "deps/mini.nvim",       "deps/nvim-web-devicons",       "deps/nvim-cmp",

.luarc.jsonc

@@ -25,13 +25,16 @@       "unbalanced": "Opened",       "unused": "Opened",     },-    "disable": ["different-requires"],+    "disable": [+      "different-requires",+      "unknown-diag-code",+      "unknown-cast-variable",+    ],     "unusedLocalExclude": ["_*"],   },   "workspace": {     "library": [       "$VIMRUNTIME",-      "${3rd}/luv/library",       // For "cmp_src.lua" type resolving       "deps/mini.nvim",       "deps/nvim-web-devicons",

lua/fzf-lua/_health.lua

@@ -53,6 +53,7 @@ function M.check()   end    local run = vim.fn.stdpath("run")+  ---@cast run -string[]   if not uv.fs_access(run, "rwx") then     error(       "Your 'run' directory is invalid `"

lua/fzf-lua/actions.lua

@@ -152,7 +152,7 @@ local edit_entry = function(entry, fullpath, will_replace_curbuf, opts)     -- We normalize the path or Windows will fail with directories starting     -- with special characters, for example "C:\app\(web)" will be translated     -- by neovim to "c:\app(web)" (#1082)-    local relpath = path.normalize(path.relative_to(fullpath, assert(uv.cwd())))+    local relpath = path.normalize(path.relative_to(fullpath, uv.cwd()))     local bufnr0 = vim.fn.bufadd(relpath)     if bufnr0 == 0 and not opts.silent then       utils.warn("Unable to add buffer %s", relpath)@@ -251,12 +251,13 @@ M.vimcmd_entry = function(vimcmd, selected, opts, bufedit)         return       end       -- Java LSP entries, 'jdt://...' or LSP locations-      if entry.uri then+      if entry.uri and entry.range then         -- pcall for two failed cases         -- (1) nvim_exec2(): Vim(normal):Can't re-enter normal mode from terminal mode         -- (2) save dialog cancellation-        pcall(utils.jump_to_location, entry, "utf-16", opts.reuse_win)-      elseif entry.ctag and entry.line == 0 then+        pcall(utils.jump_to_location, { uri = entry.uri, range = entry.range }, "utf-16",+          opts.reuse_win)+      elseif entry.line == 0 and entry.ctag then         vim.api.nvim_win_set_cursor(0, { 1, 0 })         vim.fn.search(entry.ctag, "W")       elseif not opts.no_action_set_cursor and entry.line > 0 or entry.col > 0 then@@ -400,11 +401,11 @@ M.file_switch = function(selected, opts)   if not selected[1] then return false end   -- If called from `:FzfLua tabs` switch to requested tab/win   local tabh, winid = selected[1]:match("(%d+)\t(%d+)%)")+  tabh = utils.tointeger(tabh)+  winid = utils.tointeger(winid)   if tabh and winid then-    vim.api.nvim_set_current_tabpage(tonumber(tabh))-    if tonumber(winid) > 0 then-      vim.api.nvim_set_current_win(tonumber(winid))-    end+    vim.api.nvim_set_current_tabpage(tabh)+    vim.api.nvim_set_current_win(winid)     return true   end   local entry = path.entry_to_file(selected[1], opts)@@ -821,6 +822,7 @@ end M.git_switch = function(selected, opts)   if not selected[1] then return end   local cmd = path.git_cwd({ "git", "checkout" }, opts)+  ---@cast cmd -string   local git_ver = utils.git_version()   -- git switch was added with git version 2.23   if git_ver and git_ver >= 2.23 then@@ -1135,10 +1137,8 @@ end  M.git_goto_line = function(selected, _)   if #selected == 0 then return end-  local line = selected[1] and selected[1]:match("^.-(%d+)%)")-  if tonumber(line) then-    vim.api.nvim_win_set_cursor(0, { tonumber(line), 0 })-  end+  local line = utils.tointeger(selected[1]:match("^.-(%d+)%)"))+  if line then vim.api.nvim_win_set_cursor(0, { line, 0 }) end end  M.grep_lgrep = function(_, opts)@@ -1235,6 +1235,8 @@ M.apply_profile = function(selected, opts)   end end +---@param selected string[]+---@param opts fzf-lua.config.Resolved M.complete = function(selected, opts)   if #selected == 0 then     if opts.__CTX.mode == "i" then

lua/fzf-lua/class.lua

@@ -22,6 +22,7 @@ function Object:extend()   local cls = {}   for k, v in pairs(self) do     if k:find("__") == 1 then+      ---@diagnostic disable-next-line: assign-type-mismatch       cls[k] = v     end   end

lua/fzf-lua/cmd.lua

@@ -6,6 +6,8 @@ local serpent = require "fzf-lua.lib.serpent"  local M = {} +---@param cmd string+---@param ...string function M.run_command(cmd, ...)   local args = { ... }   cmd = cmd or "builtin"

lua/fzf-lua/cmp_src.lua

@@ -1,3 +1,4 @@+---@diagnostic disable: unused local Src = {}  Src.new = function(_)

lua/fzf-lua/complete.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local core = require "fzf-lua.core" local path = require "fzf-lua.path"

lua/fzf-lua/config.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local path = require "fzf-lua.path" local utils = require "fzf-lua.utils"@@ -60,6 +61,7 @@ end  -- proxy table (with logic) for accessing the global config M.setup_opts = {}+---@type fzf-lua.Config|{} M.globals = setmetatable({}, {   __index = function(_, index)     local function setup_opts()@@ -88,7 +90,8 @@ M.globals = setmetatable({}, {         if type(setup_value) == "function" then setup_value = setup_value() end         ret[k] = setup_value and type(setup_value[k]) == "table"             and vim.tbl_deep_extend("keep",-              utils.map_tolower(utils.tbl_deep_clone(setup_value[k]), exclude_case_sensitive_alt),+              utils.map_tolower(utils.tbl_deep_clone(setup_value[k]), exclude_case_sensitive_alt) or+              {},               setup_value[k][1] == true and               utils.map_tolower(fzflua_default[k], exclude_case_sensitive_alt) or {})             or utils.map_tolower(utils.tbl_deep_clone(fzflua_default[k]), exclude_case_sensitive_alt)@@ -127,7 +130,7 @@ M.globals = setmetatable({}, {     return ret   end,   __newindex = function(_, index, _)-    assert(false, string.format("modifying globals directly isn't allowed [index: %s]", index))+    error(string.format("modifying globals directly isn't allowed [index: %s]", index))   end }) @@ -164,12 +167,12 @@ end  ---@generic T table ---@param opts T|{}|fun():T?----@param globals string|table?+---@param globals string|(fzf-lua.Config|{})? ---@param __resume_key string? ---@return T function M.normalize_opts(opts, globals, __resume_key)   -- opts can also be a function that returns an opts table-  ---@type fzf-lua.config.Resolved|{}+  ---@type fzf-lua.config.Resolved   opts = eval(opts) or {}    if opts._normalized then@@ -207,6 +210,7 @@ function M.normalize_opts(opts, globals, __resume_key)     globals = M.globals[globals]     assert(type(globals) == "table")   else+    assert(globals)     -- backward compat: globals sent directly as table     -- merge with setup options "defaults" table     globals = vim.tbl_deep_extend("keep", globals, M.setup_opts.defaults or {})@@ -252,7 +256,7 @@ function M.normalize_opts(opts, globals, __resume_key)   -- normalize all binds as lowercase or we can have duplicate keys (#654)   ---@param m {fzf: table<string, unknown>, builtin: table<string, unknown>}   ---@param exclude_patterns string-  ---@return {fzf: table<string, unknown>, builtin: table<string, unknown>}?+  ---@return {fzf?: table<string, unknown>, builtin?: table<string, unknown>}?   local keymap_tolower = function(m, exclude_patterns)     return m and {       fzf = utils.map_tolower(m.fzf, exclude_patterns),@@ -267,6 +271,7 @@ function M.normalize_opts(opts, globals, __resume_key)    -- inherit from globals.actions?   if type(globals._actions) == "function" then+    ---@diagnostic disable-next-line: assign-type-mismatch     globals.actions = vim.tbl_deep_extend("keep", globals.actions or {}, globals._actions())   end @@ -463,6 +468,7 @@ function M.normalize_opts(opts, globals, __resume_key)    -- Setup completion options   if opts.complete then+    ---@diagnostic disable-next-line: assign-type-mismatch     opts.actions = opts.actions or {}     opts.actions.enter = actions.complete     opts.actions["ctrl-c"] = function() end@@ -1005,6 +1011,7 @@ M.bytecode = function(s, datatype)   local keys = utils.strsplit(s, "%.")   local iter = M   for i = 1, #keys do+    ---@diagnostic disable-next-line: assign-type-mismatch     iter = iter[keys[i]]     if not iter then break end     if i == #keys and type(iter) == datatype then

lua/fzf-lua/core.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local fzf = require "fzf-lua.fzf" local path = require "fzf-lua.path"@@ -91,13 +92,14 @@ M.ACTION_DEFINITIONS = {  -- converts contents array sent to `fzf_exec` into a single contents -- argument with an optional prefix, currently used to combine LSP providers+---@param cont_arr table+---@return fzf-lua.content local contents_from_arr = function(cont_arr)   -- must have at least one contents item in index 1   assert(cont_arr[1].contents)   local cont_type = type(cont_arr[1].contents)-  local contents   if cont_type == "table" then-    contents = {}+    local contents = {}     for _, t in ipairs(cont_arr) do       assert(type(t.contents) == cont_type, "Unable to combine contents of different types")       contents = utils.tbl_join(contents, t.prefix and@@ -106,9 +108,11 @@ local contents_from_arr = function(cont_arr)         end, t.contents)         or t.contents)     end-  elseif cont_type == "function" then+    return contents+  end+  if cont_type == "function" then     ---@type fzf-lua.fncContent-    contents = function(fzf_cb)+    return function(fzf_cb)       coroutine.wrap(function()         local co = coroutine.running()         for _, t in ipairs(cont_arr) do@@ -134,14 +138,12 @@ local contents_from_arr = function(cont_arr)         fzf_cb()       end)()     end-  elseif cont_type == "string" then-    assert(false, "Not yet supported")   end-  return contents+  error("Not yet supported" .. cont_type) end  ---@alias fzf-lua.fzfCb fun(entry?: string|number, cb?: function)----@alias fzf-lua.fncContent fun(wnl: fzf-lua.fzfCb, w: fzf-lua.fzfCb)+---@alias fzf-lua.fncContent fun(wnl: fzf-lua.fzfCb, w: fzf-lua.fzfCb, ...) ---@alias fzf-lua.content fzf-lua.fncContent|(string|number)[]|string  -- Main API, see:@@ -150,8 +152,9 @@ end ---@param opts? fzf-lua.config.Base|{} ---@return thread?, string?, table? M.fzf_exec = function(contents, opts)-  assert(contents, "must supply contents")-  ---@type fzf-lua.config.Resolved|{}+  if not contents then error("must supply contents") end+  ---@type fzf-lua.config.Resolved+  ---@diagnostic disable-next-line: assign-type-mismatch   opts = config.normalize_opts(opts or {}, {})   if not opts then return end   if type(contents) == "table" and type(contents[1]) == "table" then@@ -195,8 +198,7 @@ local cmd2fnc = function(contents)   local cmd = add_query_placeholder(contents)   return function(args, _)     local query = args[1] or ""-    query = (query:gsub("%%", "%%%%"))-    query = libuv.shellescape(query)+    query = libuv.shellescape(utils.lua_escape(query))     return M.expand_query(cmd, query)   end end@@ -205,12 +207,13 @@ end -- each keypress reloads fzf's input usually based on the typed query -- utilizes fzf's 'change:reload' event or skim's "interactive" mode ---@param contents string|fzf-lua.shell.data2----@param opts? fzf-lua.config.Base|{}+---@param opts? fzf-lua.config.Resolved ---@return thread?, string?, table? M.fzf_live = function(contents, opts)   opts = opts or {}   opts.is_live = true-  ---@type fzf-lua.config.Resolved|{}+  ---@diagnostic disable-next-line: assign-type-mismatch+  ---@type fzf-lua.config.Resolved   opts = config.normalize_opts(opts, {})   if not opts then return end   local fzf_field_index = M.fzf_field_index(opts)@@ -242,11 +245,11 @@ M.fzf_resume = function(opts)   -- resume a picker when using "hide" and no_resume=true (#2425)   local query = utils.map_get(opts, opts.is_live and "__call_opts.search" or "__call_opts.query")   if query and #query > 0 then opts.query = query end-  M.fzf_wrap(config.__resume_data.contents, config.__resume_data.opts)+  M.fzf_wrap(assert(config.__resume_data.contents), config.__resume_data.opts) end ----@param cmd string?----@param opts table+---@param cmd string+---@param opts? fzf-lua.config.Resolved|{} ---@param convert_actions boolean? ---@return thread?, string, table M.fzf_wrap = function(cmd, opts, convert_actions)@@ -286,7 +289,7 @@ M.fzf_wrap = function(cmd, opts, convert_actions) end  ---@param contents string?----@param opts {}?+---@param opts? fzf-lua.config.Resolved ---@return string[]? ---@return integer? exit_code M.fzf = function(contents, opts)@@ -297,7 +300,7 @@ M.fzf = function(contents, opts)     return nil, nil   end   -- normalize with globals if not already normalized-  ---@type fzf-lua.config.Resolved|{}+  ---@type fzf-lua.config.Resolved   opts = config.normalize_opts(opts or {}, {})   if not opts then return nil, nil end   -- Store contents for unhide@@ -334,14 +337,14 @@ M.fzf = function(contents, opts)   opts.__INFO = FzfLua.get_info()    -- setup the fzf window and preview layout-  local fzf_win = win:new(opts)+  local fzf_win = win.new(opts)   -- instantiate the previewer   local previewer = require("fzf-lua.previewer").new(opts.previewer, opts)   if previewer then     -- Attach the previewer to the windows     fzf_win:attach_previewer(previewer)     -- Setup --preview/--preview-window/--bind=zero:... etc-    if type(previewer.setup_opts) == "function" then+    if type(previewer.setup_opts) == "function" then ---@diagnostic disable-next-line: assign-type-mismatch       opts = previewer:setup_opts(opts)     end   elseif opts.preview and type(opts.preview) ~= "string" then@@ -432,9 +435,9 @@ M.fzf = function(contents, opts) end  -- Best approximation of neovim border types to fzf border types----@param winopts fzf-lua.config.Winopts|{}+---@param winopts fzf-lua.config.PreviewOpts ---@param metadata fzf-lua.win.borderMetadata----@return string|table+---@return string|table? local function translate_border(winopts, metadata)   local neovim2fzf = {     none       = "noborder",@@ -461,7 +464,7 @@ local function translate_border(winopts, metadata)   return border end ----@param o table+---@param o fzf-lua.config.Resolved ---@param fzf_win fzf-lua.Win ---@return string M.preview_window = function(o, fzf_win)@@ -506,9 +509,7 @@ M.preview_window = function(o, fzf_win)         prefix, o.winopts.preview.vertical)     end   end-  if not layout then-    layout = string.format("%s:%s", prefix, fzf_win:fzf_preview_layout_str())-  end+  layout = layout or string.format("%s:%s", prefix, fzf_win:fzf_preview_layout_str())   if o.preview_offset and #o.preview_offset > 0 then     layout = layout .. ":" .. o.preview_offset   end@@ -748,9 +749,9 @@ M.set_title_flags = function(opts, titles)   if not cmd then return opts end   local flags = {}   local patterns = {-    { { utils.lua_regex_escape(opts.toggle_hidden_flag) or "%-%-hidden" },     "h" },-    { { utils.lua_regex_escape(opts.toggle_ignore_flag) or "%-%-no%-ignore" }, "i" },-    { { utils.lua_regex_escape(opts.toggle_follow_flag) or "%-L" },            "f" },+    { { opts.toggle_hidden_flag and utils.lua_regex_escape(opts.toggle_hidden_flag) or "%-%-hidden" },     "h" },+    { { opts.toggle_ignore_flag and utils.lua_regex_escape(opts.toggle_ignore_flag) or "%-%-no%-ignore" }, "i" },+    { { opts.toggle_follow_flag and utils.lua_regex_escape(opts.toggle_follow_flag) or "%-L" },            "f" },   }   for _, def in ipairs(patterns) do     for _, p in ipairs(def[1]) do@@ -880,6 +881,7 @@ M.set_header = function(opts)             local def, to = nil, type(v) == "table" and v.header or nil             if not to and type(action) == "function" and defs[action] then               def = defs[action]+              ---@diagnostic disable-next-line: undefined-field               to = def[1]             end             if to then@@ -907,7 +909,7 @@ M.set_header = function(opts)   }   -- override header text with the user's settings   for _, h in ipairs(opts._headers) do-    assert(definitions[h])+    if not definitions[h] then error("no header def:" .. h) end     local hdr_text = opts[definitions[h].hdr_txt_opt]     if hdr_text then       definitions[h].hdr_txt_str = hdr_text@@ -916,7 +918,7 @@ M.set_header = function(opts)   -- build the header string   local hdr_str   for _, h in ipairs(opts._headers) do-    assert(definitions[h])+    if not definitions[h] then error("no header def:" .. h) end     local def = definitions[h]     local txt = def.val(opts)     if def and txt then@@ -1133,7 +1135,7 @@ end -- query placeholder for "live" queries M.fzf_query_placeholder = "<query>" ----@param opts { field_index?: boolean, _is_skim?: boolean }+---@param opts { field_index?: string, _is_skim?: boolean } ---@return string M.fzf_field_index = function(opts)   -- fzf already adds single quotes around the placeholder when expanding.

lua/fzf-lua/ctx.lua

@@ -14,7 +14,7 @@ local ctx = {} ---@field alt_bufnr integer ---@field tabnr integer ---@field tabh integer----@field cursor integer[]+---@field cursor [integer, integer] ---@field line string ---@field curtab_wins { [string]: boolean } ---@field winopts { winhl: string, cursorline: boolean }@@ -30,7 +30,7 @@ M.reset = function() ctx = {} end ---conditionally update the context if fzf-lua ---interface isn't open ---@param opts? { includeBuflist?: boolean, buf?: integer|string, bufnr?: integer|string }----@return fzf-lua.Ctx+---@return fzf-lua.Ctx|{} M.refresh = function(opts)   opts = opts or {}   -- save caller win/buf context, ignore when fzf

lua/fzf-lua/defaults.lua

@@ -152,6 +152,8 @@ M.defaults        = {     ["--highlight-line"] = true,   },   fzf_tmux_opts = { ["-p"] = "80%,80%", ["--margin"] = "0,0" },+  ---@class fzf-lua.config.Previewers+  ---@field [string] fzf-lua.config.Previewer   previewers    = {     cat = {       cmd   = "cat",@@ -280,7 +282,8 @@ M.defaults        = {         from = function(s, _)           s = s:gsub("\xc2\xa0     .*$", "") -- gsub v2 postfix           local parts = utils.strsplit(s, utils.nbsp)-          local last = parts[#parts] ---@type string+          local last = parts[#parts]+          ---@cast last -?           -- Lines from grep, lsp, tags are formatted <file>:<line>:<col>:<text>           -- the pattern below makes sure tab doesn't come from the line text           local filename, rest = last:match("^([^:]-)\t(.+)$")@@ -428,6 +431,7 @@ M.defaults.global = vim.tbl_deep_extend("force", M.defaults.files, {  ---@class fzf-lua.config.GitBase: fzf-lua.config.Base ---@field git_dir? string+---@field cmd string  ---@class fzf-lua.config.Git ---@field files     fzf-lua.config.GitFiles@@ -861,11 +865,12 @@ M.defaults.lines                 = {     to   = false,     from = function(s, _)       -- restore the format to something that `path.entry_to_file` can handle-      local bufnr, lnum, text = s:match("%[(%d+)%].-(%d+) (.+)$")+      local bufnr0, lnum, text = s:match("%[(%d+)%].-(%d+) (.+)$")+      local bufnr = tonumber(bufnr0)       if not bufnr then return "" end       return string.format("[%s]%s%s:%s:%s",         bufnr, utils.nbsp,-        path.tail(vim.api.nvim_buf_get_name(tonumber(bufnr))),+        path.tail(vim.api.nvim_buf_get_name(bufnr)),         lnum, text)     end   },@@ -1041,6 +1046,7 @@ M.defaults.awesome_colorschemes  = {   dbfile       = "data/colorschemes.json",   icons        = { utils.ansi_codes.blue("󰇚"), utils.ansi_codes.yellow(""), " " },   packpath     = function()+    ---@diagnostic disable-next-line: assign-type-mismatch     return path.join({ vim.fn.stdpath("cache"), "fzf-lua" })   end,   actions      = {@@ -1288,8 +1294,8 @@ M.defaults.lsp.code_actions      = { ---@class fzf-lua.config.Diagnostics: fzf-lua.config.Base ---@field signs? table ---@field severity_only? vim.diagnostic.SeverityFilter----@field severity_limit? "string"|1|2|3|4----@field severity_bound? "string"|1|2|3|4+---@field severity_limit? vim.diagnostic.Severity|1|2|3|4+---@field severity_bound? vim.diagnostic.Severity|1|2|3|4 ---@field namespace? integer ---@field diag_all? boolean ---@field client_id? integer@@ -1634,7 +1640,8 @@ M.defaults.zoxide            = {  ---@class fzf-lua.config.CompleteLine: fzf-lua.config.Lines ---@field current_buffer_only? boolean-M.defaults.complete_line         = vim.tbl_deep_extend("force", M.defaults.blines, {+---@field complete? (fun(s: string[], _o: fzf-lua.config.Resolved, l: string, c: integer):string?, integer?)|boolean+M.defaults.complete_line     = vim.tbl_deep_extend("force", M.defaults.blines, {   complete = true, }) 

lua/fzf-lua/devicons.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local path = require "fzf-lua.path" local utils = require "fzf-lua.utils"@@ -292,6 +293,7 @@ function FzfLuaServer:new()   return self end +---@diagnostic disable-next-line: unused function FzfLuaServer:path()   ---@diagnostic disable-next-line: undefined-field   return _G._fzf_lua_server or vim.g.fzf_lua_server

lua/fzf-lua/fzf.lua

@@ -3,6 +3,7 @@ -- does not close the pipe before all writes are complete -- option to not add '\n' on content function callbacks -- https://github.com/vijaymarupudi/nvim-fzf/blob/master/lua/fzf.lua+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop  local utils = require "fzf-lua.utils"@@ -181,7 +182,7 @@ function M.raw_fzf(contents, fzf_cli_args, opts)       ["RUST_LOG"] = "",     },     on_exit = function(_, rc, _)-      local output = {}+      local output = nil ---@type string[]?       local f = io.open(outputtmpname)       if f then         output = vim.split(f:read("*a"), printEOL)@@ -192,7 +193,7 @@ function M.raw_fzf(contents, fzf_cli_args, opts)       -- Windows only, restore `shellslash` if was true before `jobstart`       if nvim_opt_shellslash then vim.o.shellslash = nvim_opt_shellslash end       vim.fn.delete(outputtmpname)-      if #output == 0 then output = nil end+      if output and #output == 0 then output = nil end       coroutine.resume(co, output, rc)     end   })

lua/fzf-lua/init.lua

@@ -1,3 +1,4 @@+---@diagnostic disable: duplicate-require local gen = _G.arg[0] == "lua/fzf-lua/init.lua" if gen then   vim.opt.rtp:append(vim.fn.fnamemodify(debug.getinfo(1, "S").source:gsub("^@", ""), ":h:h:h:p"))@@ -190,7 +191,7 @@ end -- case the user decides not to call `setup()` M.setup_highlights() ----@param opts? fzf-lua.profile|fzf-lua.Config+---@param opts? fzf-lua.profile|fzf-lua.Config|{} ---@param do_not_reset_defaults? boolean function M.setup(opts, do_not_reset_defaults)   opts = type(opts) == "table" and opts or {}@@ -427,7 +428,6 @@ for _, m in ipairs(exported_modules) do   M[m] = require("fzf-lua." .. m) end ----@private M._excluded_metamap = {} for _, t in pairs({ M._excluded_meta, exported_modules }) do   for _, m in ipairs(t) do@@ -435,7 +435,7 @@ for _, t in pairs({ M._excluded_meta, exported_modules }) do   end end ----@param opts fzf-lua.config.Builtin+---@param opts? fzf-lua.config.Builtin|{} ---@return thread?, string?, table? M.builtin = function(opts)   opts = config.normalize_opts(opts, "builtin")

lua/fzf-lua/lib/utf8.lua

@@ -1,4 +1,5 @@----@diagnostic disable: codestyle-check+---@diagnostic disable+---@format disable -- https://gist.github.com/subsoap/05c02690956499a84708365337eb0a99 -- https://github.com/Stepets/utf8.lua -- $Id: utf8.lua 179 2009-04-03 18:10:03Z pasta $

lua/fzf-lua/libuv.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop  local _is_win = vim.fn.has("win32") == 1 or vim.fn.has("win64") == 1@@ -64,10 +65,24 @@ M.uv_spawn = function(cmd, opts, on_exit) end if false then M.uv_spawn = uv.spawn end ----@param opts {cwd: string, cmd: string|table, env: table?, cb_finish: function,----cb_write: function?, cb_write_lines: function?, cb_err: function, cb_pid: function,----fn_transform: function?, EOL: string?, EOL_data: string?, process1: boolean?,----profiler: boolean?, use_queue: boolean?}++---@class fzf-lua.SpawnOpts+---@field cwd? string+---@field cmd string|table+---@field env? table+---@field cb_finish fun(code: integer, sig: integer, from: string, pid: integer)+---@field cb_write? fun(data: string, cb: fun(err: any): nil): nil+---@field cb_write_lines? fun(lines: string[])+---@field cb_err fun(data: string)+---@field cb_pid? fun(pid: integer)+---@field fn_transform? fun()+---@field EOL? string+---@field EOL_data? string+---@field process1? boolean+---@field profiler? boolean+---@field use_queue? boolean++---@param opts fzf-lua.SpawnOpts ---@param fn_transform function? ---@param fn_done function? ---@return uv.uv_process_t proc@@ -88,7 +103,7 @@ M.spawn = function(opts, fn_transform, fn_done)   local error_pipe = assert(uv.new_pipe(false))   local write_cb_count, read_cb_count = 0, 0   local prev_line_content ---@type string?-  local handle, pid+  local handle, pid ---@type uv.uv_process_t, integer   local co = coroutine.running()   local queue = require("fzf-lua.lib.queue").new()   local work_ctx@@ -98,6 +113,7 @@ M.spawn = function(opts, fn_transform, fn_done)   opts.use_queue = not _G._fzf_lua_is_headless and opts.use_queue    -- cb_write_lines trumps cb_write+  ---@diagnostic disable-next-line: assign-type-mismatch   if opts.cb_write_lines then opts.cb_write = opts.cb_write_lines end    local can_finish = function()@@ -391,7 +407,7 @@ local posix_exec = function(cmd)   require("ffi").C.execl("/bin/sh", "sh", "-c", cmd, nil) end ----@param opts table+---@param opts fzf-lua.SpawnStdioOpts ---@return uv.uv_process_t, integer M.spawn_stdio = function(opts)   -- stdin/stdout are already buffered, not stderr. This means@@ -452,9 +468,9 @@ M.spawn_stdio = function(opts)   -- run the preprocessing fn   if fn_preprocess then fn_preprocess(opts) end -  ---@type fzf-lua.content|fzf-lua.shell.data2-  local cmd = opts.contents-  if type(cmd) == "string" and cmd:match("%-%-color[=%s]+never") then+  ---@type fzf-lua.content|fzf-lua.shell.data2?+  local content = opts.contents+  if type(content) == "string" and content:match("%-%-color[=%s]+never") then     -- perf: skip stripping ansi coloring in `make_file.entry`     opts.no_ansi_colors = true   end@@ -464,7 +480,7 @@ M.spawn_stdio = function(opts)       io.stdout:write(string.format("[DEBUG] %s=%s" .. EOL, k, vim.inspect(v)))     end   elseif opts.debug then-    io.stdout:write("[DEBUG] [mt] " .. tostring(cmd) .. EOL)+    io.stdout:write("[DEBUG] [mt] " .. tostring(content) .. EOL)   end    local stderr, stdout = nil, nil@@ -522,70 +538,77 @@ M.spawn_stdio = function(opts)     stdout = pipe_open(opts.stdout)   end -  local on_finish = opts.on_finish or-      function(code)-        pipe_close(stdout)-        pipe_close(stderr)-        if fn_postprocess then-          vim.schedule(function()-            fn_postprocess(opts)-            exit(code)-          end)-        else-          exit(code)-        end-      end+  local on_finish = function(code)+    pipe_close(stdout)+    pipe_close(stderr)+    if fn_postprocess then+      vim.schedule(function()+        fn_postprocess(opts)+        exit(code)+      end)+    else+      exit(code)+    end+  end -  local on_write = opts.on_write or-      function(data, cb)-        if stdout then-          pipe_write(stdout, data, cb)-        else-          -- on success: rc=true, err=nil-          -- on failure: rc=nil, err="Broken pipe"-          -- cb with an err ends the process-          local rc, err = io.stdout:write(data)-          if not rc then-            stderr_write(("io.stdout:write error: %s" .. EOL):format(err))-            cb(err or true)-          else-            cb(nil)-          end-        end+  local on_write = function(data, cb)+    if stdout then+      pipe_write(stdout, data, cb)+    else+      -- on success: rc=true, err=nil+      -- on failure: rc=nil, err="Broken pipe"+      -- cb with an err ends the process+      local rc, err = io.stdout:write(data)+      if not rc then+        stderr_write(("io.stdout:write error: %s" .. EOL):format(err))+        cb(err or true)+      else+        cb(nil)       end+    end+  end -  local on_err = opts.on_err or-      function(data)-        if stderr then-          pipe_write(stderr, data)-        elseif opts.stderr ~= false then-          if opts.stderr_to_stdout then-            io.stdout:write(data)-          else-            io.stderr:write(data)-          end-        end+  local on_err = function(data)+    if stderr then+      pipe_write(stderr, data)+    elseif opts.stderr ~= false then+      if opts.stderr_to_stdout then+        io.stdout:write(data)+      else+        io.stderr:write(data)       end+    end+  end++  local args = function()+    local items = vim.deepcopy(_G.arg)+    items[0] = nil+    table.remove(items, 1)+    return items+  end -  if type(cmd) ~= "string" then+  local cmd ---@type string+  if type(content) == "string" then+    cmd = content+  else     local f = fn_transform or function(x) return x end     local w = function(s) if s then io.stdout:write(f(s) .. EOL) else on_finish(0) end end     local wn = function(s) if s then return io.stdout:write(f(s)) else on_finish(0) end end-    if opts.is_live then ---@cast cmd fzf-lua.shell.data2-      local items = vim.deepcopy(_G.arg)-      items[0] = nil-      table.remove(items, 1)-      cmd = cmd(items, opts)-    end ---@cast cmd fzf-lua.content-    if type(cmd) == "function" then cmd(w, wn) end-    if type(cmd) == "table" then for _, v in ipairs(cmd) do w(v) end end-    if type(cmd) ~= "string" then on_finish(0) end+    if opts.is_live then ---@cast content fzf-lua.shell.data2+      local res = content(args(), opts)+      if not res then on_finish(0) end ---@cast res-?+      content = res+    end+    if type(content) == "function" then content(w, wn) end+    if type(content) == "table" then for _, v in ipairs(content) do w(v) end end+    if type(content) ~= "string" then on_finish(0) end ---@cast content string+    cmd = content     if opts.debug then-      io.stdout:write(("[DEBUG] [mt] %s" .. EOL):format(cmd))+      io.stdout:write(("[DEBUG] [mt] %s" .. EOL):format(content))     end   end -  if not fn_transform and not fn_postprocess then posix_exec(cmd) end+  if not fn_transform and not fn_postprocess then posix_exec(content) end    return M.spawn({       cwd = opts.cwd,

lua/fzf-lua/make_entry.lua

@@ -1,5 +1,6 @@ local M = {} +---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local path = require "fzf-lua.path" local utils = require "fzf-lua.utils"@@ -18,20 +19,10 @@ end local function load_config()   ---@diagnostic disable-next-line: undefined-field   if not _G._fzf_lua_server then return end-  local res = nil-  local ok, errmsg = pcall(function()-    ---@diagnostic disable-next-line: undefined-field-    local chan_id = vim.fn.sockconnect("pipe", _G._fzf_lua_server, { rpc = true })-    res = vim.rpcrequest(chan_id, "nvim_exec_lua", [[-      return FzfLua.libuv.serialize(FzfLua.config)-    ]], {})-    res = libuv.deserialize(assert(res))-    vim.fn.chanclose(chan_id)-  end)-  if not ok then-    dump(res)-    dump(errmsg)-  end+  local ok, res = utils.rpcexec(_G._fzf_lua_server, "nvim_exec_lua",+    [[return FzfLua.libuv.serialize(FzfLua.config)]], {})+  if not ok then error(res) end+  res = libuv.deserialize(res)   return res end @@ -42,7 +33,6 @@ local function load_config_section(s, datatype, optional)     ---@diagnostic disable-next-line: undefined-field   elseif _G._fzf_lua_server then     -- load config from our running instance-    local res = nil     local is_bytecode = false     local exec_str, exec_opts = nil, nil     if datatype == "function" then@@ -165,6 +155,8 @@ M.glob_parse = function(query, opts)   end   local glob_args = ""   local search_query, glob_str = query:match("(.*)" .. opts.glob_separator .. "(.*)")+  search_query = search_query or ""+  glob_str = glob_str or ""   for _, s in ipairs(utils.strsplit(glob_str, "%s+")) do     if #s > 0 then       glob_args = glob_args .. ("%s %s "):format(opts.glob_flag, libuv.shellescape(s))@@ -468,7 +460,7 @@ M.expand_query = function(opts, query, cmd)       local search_query, glob_args = M.glob_parse(query, opts)       if glob_args then         -- gsub doesn't like single % on rhs-        search_query = search_query:gsub("%%", "%%%%")+        search_query = utils.lua_escape(search_query)         -- reset argvz so it doesn't get replaced again below         -- insert glob args before `-- {argvz}` or `-e {argvz}` repositioned         -- at the end of the command preceding the search query (#781, #794)@@ -657,7 +649,7 @@ M.file = function(x, opts)     ret[#ret + 1] = file_is_ansi > 0         -- filename is ansi escape colored, replace the inner string (#819)         -- escape `%` in path, since `string.gsub` also use it in target (#1443)-        and file_part:gsub(utils.lua_regex_escape(stripped_filepath), (filepath:gsub("%%", "%%%%")))+        and file_part:gsub(utils.lua_regex_escape(stripped_filepath), utils.lua_escape(filepath))         or filepath   end   -- multiline is only enabled with grep-like output PATH:LINE:COL:@@ -732,8 +724,10 @@ M.git_status = function(x, opts)   local f1, f2 = x:sub(4):gsub([["]], ""), nil   -- renames separate files with '->'   if f1:match("%s%->%s") then+    ---@diagnostic disable-next-line: assign-type-mismatch     f1, f2 = f1:match("(.*)%s%->%s(.*)")   end+  ---@diagnostic disable-next-line: assign-type-mismatch   f1 = f1 and M.file(f1, opts)   -- accommodate 'file_ignore_patterns'   if not f1 then return end

lua/fzf-lua/path.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local utils = require "fzf-lua.utils" local libuv = require "fzf-lua.libuv"@@ -168,18 +169,18 @@ function M.is_relative_to(path, relative_to)   relative_to = M.add_trailing(M.tilde_to_HOME(relative_to))   local pidx, ridx = 1, 1   repeat-    local pbyte = string.byte(path, pidx)-    local rbyte = string.byte(relative_to, ridx)+    local pbyte = string_byte(path, pidx)+    local rbyte = string_byte(relative_to, ridx)     if M.byte_is_separator(pbyte) and M.byte_is_separator(rbyte) then       -- both path and relative_to have a separator part       -- which may differ in length if there are multiple       -- separators, e.g. "/some/path" and "//some//path"       repeat         pidx = pidx + 1-      until not M.byte_is_separator(string.byte(path, pidx))+      until not M.byte_is_separator(string_byte(path, pidx))       repeat         ridx = ridx + 1-      until not M.byte_is_separator(string.byte(relative_to, ridx))+      until not M.byte_is_separator(string_byte(relative_to, ridx))     elseif utils.__IS_WINDOWS and pbyte and rbyte         -- case insensitive matching on windows         and string.char(pbyte):lower() == string.char(rbyte):lower()@@ -387,9 +388,9 @@ end ---@param opts table ---@return fzf-lua.path.Entry function M.entry_to_location(entry, opts)-  local uri, line, col = entry:match("^(.*://.*):(%d+):(%d+):")-  line = line and tonumber(line) > 0 and tonumber(line) or 1-  col = col and tonumber(col) > 0 and tonumber(col) or 1+  local uri, line0, col0 = entry:match("^(.*://.*):(%d+):(%d+):")+  local line = utils.tointeger(line0) or 1+  local col = utils.tointeger(col0) or 1   if opts.path_shorten and uri:match("file://") then     uri = "file://" .. M.lengthen(uri:sub(8))   end@@ -402,6 +403,10 @@ function M.entry_to_location(entry, opts)       start = {         line = line - 1,         character = col - 1,+      },+      ["end"] = {+        line = line - 1,+        character = col - 1,       }     }   }@@ -466,7 +471,8 @@ function M.entry_to_file(entry, opts, force_uri)   end   -- Entry metadata (before `utils.nbsp`) can contain `[bufnr]` which should   -- be used instead of the file path, used in buffers, tabs, lines|blines-  local bufnr = not opts._ctag and idx > 1 and entry:sub(1, idx):match("%[(%d+)%]") or nil+  local bufnr0 = not opts._ctag and idx > 1 and entry:sub(1, idx):match("%[(%d+)%]") or nil+  local bufnr = utils.tointeger(bufnr0)   if isURI and not bufnr then     -- LSP entries can appear as URIs, for example when using nvim-jdtls     -- references inside ".jar" files will have a prefix of "jdt://..."@@ -522,16 +528,17 @@ function M.entry_to_file(entry, opts, force_uri)   if opts.path_shorten and not M.is_uri(stripped) then     file = M.lengthen(file)   end+  ---@type fzf-lua.path.Entry   return {     stripped = stripped,-    bufnr    = tonumber(bufnr),-    bufname  = bufnr and vim.api.nvim_buf_is_valid(tonumber(bufnr))-        and vim.api.nvim_buf_get_name(tonumber(bufnr)),+    bufnr    = bufnr,+    bufname  = bufnr and vim.api.nvim_buf_is_valid(bufnr)+        and vim.api.nvim_buf_get_name(bufnr),     terminal = terminal,     path     = file,-    line     = tonumber(opts.line_query and+    line     = utils.tointeger(opts.line_query and       (opts.line_query(opts._last_query or opts.last_query)) or line) or 0,-    col      = tonumber(col) or 0,+    col      = utils.tointeger(col) or 0,     ctag     = opts._ctag and M.entry_to_ctag(stripped) or nil,     debug    = opts.debug and entry:match("^%[DEBUG]") and entry or nil,   }@@ -564,6 +571,7 @@ function M.git_cwd(cmd, opts)   elseif type(cmd) == "table" then     local idx = 2     cmd = utils.tbl_deep_clone(cmd)+    ---@cast cmd -?     for _, a in ipairs(git_args) do       if o[a[1]] then         o[a[1]] = a.noexpand and o[a[1]] or libuv.expand(o[a[1]])@@ -624,13 +632,16 @@ end  -- Minimal functionality so we can hijack during `vim.filetype.match` -- As of neovim 0.10 we only need to implement mode ":t"+---@param fname string+---@param mods string+---@return string M._fnamemodify = function(fname, mods)   if mods == ":t" then     return M.tail(fname)   end   if mods == ":r" then     local tail = M.tail(fname)-    return tail and tail[1] ~= "." and (fname:gsub("%.[^.]*$", "")) or tail+    return tail and tail:sub(1, 1) ~= "." and (fname:gsub("%.[^.]*$", "")) or tail   end   return fname end

lua/fzf-lua/previewer/builtin.lua

@@ -4,6 +4,7 @@ local utils = require "fzf-lua.utils" local libuv = require "fzf-lua.libuv" local Object = require "fzf-lua.class" +---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local api = vim.api local fn = vim.fn@@ -74,10 +75,12 @@ function TSContext.toggle(winid, bufnr) end  function TSContext.inc_dec_maxlines(num, winid, bufnr)-  if not TSContext._setup or not tonumber(num) then return end+  if not TSContext._setup then return end+  local n = tonumber(num)+  if not n then return end   local config = require("treesitter-context.config")   local max_lines = config.max_lines or 0-  config.max_lines = math.max(0, max_lines + tonumber(num))+  config.max_lines = math.max(0, max_lines + n)   utils.info("treesitter-context `max_lines` set to %d.", config.max_lines)   if TSContext.is_attached(winid) then     for _, t in ipairs({ 0, 20 }) do@@ -93,7 +96,7 @@ end function TSContext.update(winid, bufnr, opts)   opts = opts or {}   if not TSContext.setup(opts) then return end-  assert(not vim.api.nvim_win_is_valid(winid) or bufnr == vim.api.nvim_win_get_buf(winid))+  assert(not api.nvim_win_is_valid(winid) or bufnr == api.nvim_win_get_buf(winid))   local render = require("treesitter-context.render")   local context_ranges, context_lines = require("treesitter-context.context").get(winid)   if not context_ranges or #context_ranges == 0 then@@ -101,7 +104,7 @@ function TSContext.update(winid, bufnr, opts)   else     assert(context_lines)     local function open()-      if vim.api.nvim_buf_is_valid(bufnr) and vim.api.nvim_win_is_valid(winid) then+      if api.nvim_buf_is_valid(bufnr) and api.nvim_win_is_valid(winid) then         -- ensure context win is above         local fix = function(win, zindex)           if win and api.nvim_win_is_valid(win) and api.nvim_win_get_config(win).zindex ~= zindex then@@ -139,6 +142,37 @@ end local Previewer = {}  ---@class fzf-lua.previewer.Builtin : fzf-lua.Object,{}+---@field last_entry? string+---@field type "builtin"+---@field new function+---@field setup_opts function+---@field opts table+---@field win fzf-lua.Win+---@field delay integer+---@field title any+---@field title_pos "center"|"left"|"right"+---@field title_fnamemodify fun(title: string, width: integer?): string+---@field render_markdown table?+---@field snacks_image table?+---@field winopts fzf-lua.config.Winopts|{}?+---@field syntax boolean+---@field syntax_delay integer+---@field syntax_limit_b integer+---@field syntax_limit_l integer+---@field limit_b integer+---@field _ts_limit_b_per_line integer+---@field treesitter table+---@field toggle_behavior "default"|"extend"+---@field winopts_orig table+---@field winblend integer+---@field extensions { [string]: string[]? }+---@field ueberzug_scaler "crop"|"distort"|"contain"|"fit_contain"|"cover"|"forced_cover"+---@field cached_bufnrs { [string]: [integer, integer]|true? }+---@field cached_buffers { [string]: fzf-lua.buffer_or_file.Bcache? }+---@field listed_buffers { [string]: boolean? }+---@field clear_on_redraw boolean?+---@field timers? table<string, uv.uv_timer_t?>+---@field orig_pos? [integer, integer] Previewer.base = Object:extend()  ---@param o table@@ -201,11 +235,11 @@ function Previewer.base:new(o, opts)   self.listed_buffers = (function()     local map = {}     vim.tbl_map(function(b)-      if vim.fn.buflisted(b) == 1 then+      if fn.buflisted(b) == 1 then         -- Save key as string or this gets treated as an array         map[tostring(b)] = true       end-    end, vim.api.nvim_list_bufs())+    end, api.nvim_list_bufs())     return map   end)()   return self@@ -261,6 +295,8 @@ function Previewer.base:preview_is_terminal()   return utils.getwininfo(self.win.preview_winid).terminal == 1 end +---@diagnostic disable-next-line: unused+---@return integer function Previewer.base:get_tmp_buffer()   local tmp_buf = api.nvim_create_buf(false, true)   vim.bo[tmp_buf].modeline = true@@ -279,7 +315,7 @@ function Previewer.base:safe_buf_delete(bufnr, del_cached)   if self.listed_buffers[tostring(bufnr)] then     -- print("safe_buf_delete LISTED", bufnr)     return-  elseif not vim.api.nvim_buf_is_valid(bufnr) then+  elseif not api.nvim_buf_is_valid(bufnr) then     -- print("safe_buf_delete INVALID", bufnr)     return   elseif not del_cached and self.cached_bufnrs[tostring(bufnr)] then@@ -288,11 +324,11 @@ function Previewer.base:safe_buf_delete(bufnr, del_cached)   end   -- print("safe_buf_delete DELETE", bufnr)   -- delete buffer marks-  vim.api.nvim_buf_call(bufnr, function()+  api.nvim_buf_call(bufnr, function()     vim.cmd([[delm \"]])   end)   -- delete the buffer-  vim.api.nvim_buf_delete(bufnr, { force = true })+  api.nvim_buf_delete(bufnr, { force = true }) end  ---@param newbuf integer@@ -300,7 +336,7 @@ end function Previewer.base:set_preview_buf(newbuf, min_winopts)   if not self.win or not self.win:validate_preview() then return end   -- Set the preview window to the new buffer-  local curbuf = vim.api.nvim_win_get_buf(self.win.preview_winid)+  local curbuf = api.nvim_win_get_buf(self.win.preview_winid)   if curbuf == newbuf then return end   -- Something went terribly wrong   assert(curbuf ~= newbuf)@@ -308,7 +344,7 @@ function Previewer.base:set_preview_buf(newbuf, min_winopts)   -- to make gc work, don't reference `win._previewer` in a callback   local winid = self.win.fzf_winid   vim.keymap.set("", "i", function()-    vim.api.nvim_set_current_win(winid)+    api.nvim_set_current_win(winid)     vim.cmd("startinsert")   end, { buffer = newbuf })   self.preview_bufnr = newbuf@@ -325,17 +361,12 @@ function Previewer.base:set_preview_buf(newbuf, min_winopts)   self:safe_buf_delete(curbuf) end ----@param bufnr integer?----@param key string?+---@param bufnr integer+---@param key string ---@param min_winopts boolean?----@return table? cached+---@return fzf-lua.buffer_or_file.Bcache? function Previewer.base:cache_buffer(bufnr, key, min_winopts)   if not key then return end-  if not bufnr then-    -- can happen with slow loading buffers such as image previews-    -- with viu while spamming f5/f6 to rotate the preview window-    return-  end   local cached = self.cached_buffers[key]   if cached then     if cached.bufnr == bufnr then@@ -364,7 +395,7 @@ function Previewer.base:clear_cached_buffers() end  ---@param newbuf boolean?----@return integer+---@return integer? function Previewer.base:clear_preview_buf(newbuf)   local retbuf = nil   if ((self.win and self.win._reuse) or newbuf)@@ -403,10 +434,29 @@ function Previewer.base:display_last_entry()   self:display_entry(self.last_entry) end +---@diagnostic disable-next-line: unused function Previewer.base:should_clear_preview(_) end -- for lint +---@diagnostic disable-next-line: unused function Previewer.base:populate_preview_buf(_) end -- for lint +---@param name string+---@param delay integer+---@param func function+function Previewer.base:debounce(name, delay, func)+  self.timers = self.timers or {}+  local timer = self.timers[name]+  if tonumber(delay) > 0 then+    if timer and type(timer.is_closing) == "function" and not timer:is_closing() then+      timer:stop()+      timer:close()+    end+    self.timers[name] = vim.defer_fn(func, delay)+  else+    func()+  end+end+ ---@param entry_str string? function Previewer.base:display_entry(entry_str)   if not entry_str then return end@@ -435,22 +485,9 @@ function Previewer.base:display_entry(entry_str)   end    -- debounce preview entries-  if tonumber(self.delay) > 0 then-    if not self._entry_count then-      self._entry_count = 1-    else-      self._entry_count = self._entry_count + 1-    end-    local entry_count = self._entry_count-    vim.defer_fn(function()-      -- only display if entry hasn't changed-      if self._entry_count == entry_count then-        populate_preview_buf(entry_str)-      end-    end, self.delay)-  else+  self:debounce("preview", self.delay, function()     populate_preview_buf(entry_str)-  end+  end) end  function Previewer.base:cmdline(_)@@ -482,7 +519,7 @@ function Previewer.base:zero(_)   -- currently awaiting an upstream fix:   -- https://github.com/junegunn/fzf/issues/3516   ---  self._zero_lock = self._zero_lock or path.normalize(vim.fn.tempname())+  self._zero_lock = self._zero_lock or path.normalize(fn.tempname())   local act = string.format("execute-silent(mkdir %s && %s)",     libuv.shellescape(self._zero_lock),     shell.stringify_data(function(_, _, _)@@ -495,7 +532,7 @@ function Previewer.base:zero(_)           self.win:update_preview_title("")         end         self.last_entry = nil-        vim.fn.delete(self._zero_lock, "d")+        fn.delete(self._zero_lock, "d")       end, self.delay)     end, self.opts, ""))   return act@@ -532,7 +569,7 @@ function Previewer.base:scroll(direction)   if not input then return end    if direction == "reset" then-    pcall(vim.api.nvim_win_call, preview_winid, function()+    pcall(api.nvim_win_call, preview_winid, function()       -- for some reason 'nvim_win_set_cursor'       -- only moves forward, so set to (1,0) first       api.nvim_win_set_cursor(0, { 1, 0 })@@ -542,10 +579,11 @@ function Previewer.base:scroll(direction)       utils.zz()     end)   else-    pcall(vim.api.nvim_win_call, preview_winid, function()+    pcall(api.nvim_win_call, preview_winid, function()       vim.cmd([[norm! ]] .. input)       -- `zb` at bottom?       local wi = utils.getwininfo(preview_winid)+      ---@cast wi -?       if wi.height > (wi.botline - wi.topline) then         api.nvim_win_set_cursor(0, { wi.botline, 1 })         vim.cmd("norm! zvzb")@@ -562,7 +600,7 @@ function Previewer.base:scroll(direction)     if direction == "reset" then       self.cached_bufnrs[tostring(self.preview_bufnr)] = true     else-      self.cached_bufnrs[tostring(self.preview_bufnr)] = vim.api.nvim_win_get_cursor(preview_winid)+      self.cached_bufnrs[tostring(self.preview_bufnr)] = api.nvim_win_get_cursor(preview_winid)     end   end   self.win:update_preview_scrollbar()@@ -604,15 +642,15 @@ function Previewer.buffer_or_file:close(do_not_clear_cache) end  ---@param entry_str string----@return fzf-lua.path.Entry+---@return fzf-lua.path.Entry|{} function Previewer.buffer_or_file:entry_to_file(entry_str)   return path.entry_to_file(entry_str, self.opts) end  ---@param entry_str string----@return fzf-lua.buffer_or_file.Entry+---@return fzf-lua.buffer_or_file.Entry|{} function Previewer.buffer_or_file:parse_entry(entry_str)-  ---@type fzf-lua.buffer_or_file.Entry+  ---@type fzf-lua.buffer_or_file.Entry|{}   local entry = self:entry_to_file(entry_str)   entry.buf_is_loaded = entry.bufnr and api.nvim_buf_is_loaded(entry.bufnr)   entry.buf_is_valid = entry.bufnr and api.nvim_buf_is_valid(entry.bufnr)@@ -624,7 +662,7 @@ function Previewer.buffer_or_file:parse_entry(entry_str)   -- or when starting nvim with an arglist, fix entry.path since it contains   -- filename only   if entry.buf_is_valid then-    entry.path = path.relative_to(vim.api.nvim_buf_get_name(entry.bufnr), uv.cwd())+    entry.path = path.relative_to(api.nvim_buf_get_name(entry.bufnr), uv.cwd())   end   if entry.path then     entry.fs_stat = uv.fs_stat(entry.path)@@ -638,11 +676,13 @@ function Previewer.buffer_or_file:parse_entry(entry_str)   return entry end +---@diagnostic disable-next-line: unused+---@return boolean function Previewer.buffer_or_file:should_clear_preview(_)   return false end ----@param entry fzf-lua.buffer_or_file.Entry+---@param entry fzf-lua.buffer_or_file.Entry|{} ---@return boolean function Previewer.buffer_or_file:should_load_buffer(entry)   -- we don't have a previous entry to compare to or `do_not_cache` is set meaning@@ -659,11 +699,11 @@ end function Previewer.buffer_or_file:start_ueberzug()   if self._ueberzug_fifo then return self._ueberzug_fifo end   self._ueberzug_fifo = path.join({-    vim.fn.fnamemodify(vim.fn.tempname(), ":h"),-    string.format("fzf-lua-%d-ueberzug", vim.fn.getpid())+    fn.fnamemodify(fn.tempname(), ":h"),+    string.format("fzf-lua-%d-ueberzug", fn.getpid())   })   utils.io_system({ "mkfifo", self._ueberzug_fifo })-  self._ueberzug_job = vim.fn.jobstart({ "sh", "-c",+  self._ueberzug_job = fn.jobstart({ "sh", "-c",     string.format(       "tail -f %s | ueberzug layer --parser json",       libuv.shellescape(self._ueberzug_fifo))@@ -682,23 +722,23 @@ function Previewer.buffer_or_file:start_ueberzug()       end       -- populate the preview buffer with the error message       if self.preview_bufnr and self.preview_bufnr > 0 and-          vim.api.nvim_buf_is_valid(self.preview_bufnr) then-        local lines = vim.api.nvim_buf_get_lines(self.preview_bufnr, 0, -1, false)+          api.nvim_buf_is_valid(self.preview_bufnr) then+        local lines = api.nvim_buf_get_lines(self.preview_bufnr, 0, -1, false)         for _, l in ipairs(data or {}) do           table.insert(lines, l)         end-        vim.api.nvim_buf_set_lines(self.preview_bufnr, 0, -1, false, lines)+        api.nvim_buf_set_lines(self.preview_bufnr, 0, -1, false, lines)       end     end   }   )-  self._ueberzug_pid = vim.fn.jobpid(self._ueberzug_job)+  self._ueberzug_pid = fn.jobpid(self._ueberzug_job)   return self._ueberzug_fifo end  function Previewer.buffer_or_file:stop_ueberzug()   if self._ueberzug_job then-    vim.fn.jobstop(self._ueberzug_job)+    fn.jobstop(self._ueberzug_job)     if type(uv.os_getpriority(self._ueberzug_pid)) == "number" then       uv.kill(self._ueberzug_pid, 9)     end@@ -706,7 +746,7 @@ function Previewer.buffer_or_file:stop_ueberzug()     self._ueberzug_pid = nil   end   if self._ueberzug_fifo and uv.fs_stat(self._ueberzug_fifo) then-    vim.fn.delete(self._ueberzug_fifo)+    fn.delete(self._ueberzug_fifo)     self._ueberzug_fifo = nil   end end@@ -714,7 +754,7 @@ end function Previewer.buffer_or_file:populate_terminal_cmd(tmpbuf, cmd, entry)   if not cmd then return end   cmd = type(cmd) == "table" and utils.deepcopy(cmd) or { cmd }-  if not cmd[1] or vim.fn.executable(cmd[1]) ~= 1 then+  if not cmd[1] or fn.executable(cmd[1]) ~= 1 then     return false   end   -- no caching: preview buf must be reattached for@@ -732,8 +772,8 @@ function Previewer.buffer_or_file:populate_terminal_cmd(tmpbuf, cmd, entry)   if cmd[1]:match("ueberzug") then     local fifo = self:start_ueberzug()     if not fifo then return end-    local wincfg = vim.api.nvim_win_get_config(self.win.preview_winid)-    local winpos = vim.api.nvim_win_get_position(self.win.preview_winid)+    local wincfg = api.nvim_win_get_config(self.win.preview_winid)+    local winpos = api.nvim_win_get_position(self.win.preview_winid)     local params = {       action     = "add",       identifier = "preview",@@ -746,10 +786,10 @@ function Previewer.buffer_or_file:populate_terminal_cmd(tmpbuf, cmd, entry)           path.join({ self.opts.cwd or uv.cwd(), entry.path }),     }     local json = vim.json.encode(params)-    -- both 'fs_open|write|close' and 'vim.fn.system' work.+    -- both 'fs_open|write|close' and 'fn.system' work.     -- We prefer the libuv method as it doesn't rely on the shell     -- cmd = { "sh", "-c", ("echo '%s' > %s"):format(json, self._ueberzug_fifo) }-    -- vim.fn.system(cmd)+    -- fn.system(cmd)     local fd = uv.fs_open(self._ueberzug_fifo, "a", -1)     if fd then       uv.fs_write(fd, json .. "\n", nil, function(_)@@ -771,7 +811,7 @@ function Previewer.buffer_or_file:populate_terminal_cmd(tmpbuf, cmd, entry)     end     -- must be modifiable or 'termopen' fails     vim.bo[tmpbuf].modifiable = true-    vim.api.nvim_buf_call(tmpbuf, function()+    api.nvim_buf_call(tmpbuf, function()       self._job_id = utils.termopen(cmd, {         cwd = self.opts.cwd,         on_exit = function()@@ -790,13 +830,13 @@ function Previewer.buffer_or_file:populate_terminal_cmd(tmpbuf, cmd, entry)   return true end +---@diagnostic disable-next-line: unused ---@param entry fzf-lua.buffer_or_file.Entry ---@return string function Previewer.buffer_or_file:key_from_entry(entry)-  assert(entry)-  return entry.bufnr and string.format("bufnr:%d", entry.bufnr)-      or entry.uri-      or entry.path+  return assert(entry.bufnr and string.format("bufnr:%d", entry.bufnr)+    or entry.uri+    or entry.path) end  ---@param entry fzf-lua.buffer_or_file.Entry@@ -804,10 +844,10 @@ end function Previewer.buffer_or_file:get_bcache(entry)   if entry.do_not_cache then return end   local key = self:key_from_entry(entry)-  assert(type(key) == "string" and #key > 0)+  assert(#key > 0)   local cached = self.cached_buffers[key]   assert(not cached or self.cached_bufnrs[tostring(cached.bufnr)])-  assert(not cached or vim.api.nvim_buf_is_valid(cached.bufnr))+  assert(not cached or api.nvim_buf_is_valid(cached.bufnr))   if not cached then return end   if not cached.tick then -- in case cache don't have "tick"     assert(cached.tick == entry.tick)@@ -855,7 +895,7 @@ function Previewer.buffer_or_file:populate_preview_buf(entry_str)   -- kill previously running terminal jobs   -- when using external commands extension map   if self._job_id and self._job_id > 0 then-    vim.fn.jobstop(self._job_id)+    fn.jobstop(self._job_id)     self._job_id = nil   end   if entry.buf_is_loaded or (entry.bufnr and api.nvim_buf_is_loaded(entry.bufnr)) then@@ -863,19 +903,19 @@ function Previewer.buffer_or_file:populate_preview_buf(entry_str)     -- this changes the buffer's 'getbufinfo[1].lastused'     -- which messes up our `buffers()` sort     entry.filetype = vim.bo[entry.bufnr].filetype-    local lines = vim.api.nvim_buf_get_lines(entry.bufnr, 0, -1, false)+    local lines = api.nvim_buf_get_lines(entry.bufnr, 0, -1, false)     local tmpbuf = invalid_cached and invalid_cached.bufnr or self:get_tmp_buffer()-    vim.api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)+    api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)     -- terminal buffers use minimal window style (2nd arg)     self:set_preview_buf(tmpbuf, entry.terminal)     self:preview_buf_post(entry, entry.terminal)   elseif entry.uri then     -- LSP 'jdt://' entries, see issue #195     -- https://github.com/ibhagwan/fzf-lua/issues/195-    vim.api.nvim_win_call(self.win.preview_winid, function()+    api.nvim_win_call(self.win.preview_winid, function()       local ok, res = pcall(utils.jump_to_location, entry, "utf-16", false)       if ok then-        self.preview_bufnr = vim.api.nvim_get_current_buf()+        self.preview_bufnr = api.nvim_get_current_buf()       else         -- in case of an error display the stacktrace in the preview buffer         local lines = type(res) == "string" and utils.strsplit(res, "\n") or { "null" }@@ -884,7 +924,7 @@ function Previewer.buffer_or_file:populate_preview_buf(entry_str)             utils.__HAS_NVIM_011 and "show_document" or "jump_to_location", entry.uri))         table.insert(lines, 2, "")         local tmpbuf = invalid_cached and invalid_cached.bufnr or self:get_tmp_buffer()-        vim.api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)+        api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)         self:set_preview_buf(tmpbuf)       end     end)@@ -937,7 +977,7 @@ function Previewer.buffer_or_file:populate_preview_buf(entry_str)         end       end       if lines then-        pcall(vim.api.nvim_buf_set_lines, tmpbuf, 0, -1, false, lines)+        pcall(api.nvim_buf_set_lines, tmpbuf, 0, -1, false, lines)         -- swap preview buffer with new one         self:set_preview_buf(tmpbuf)         self:preview_buf_post(entry)@@ -953,7 +993,7 @@ function Previewer.buffer_or_file:populate_preview_buf(entry_str)       if data:sub(#data, #data) == "\n" or data:sub(#data - 1, #data) == "\r\n" then         table.remove(lines)       end-      vim.api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)+      api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)       -- swap preview buffer with new one       self:set_preview_buf(tmpbuf)       self:preview_buf_post(entry)@@ -962,6 +1002,9 @@ function Previewer.buffer_or_file:populate_preview_buf(entry_str) end  -- Attach ts highlighter, neovim >= v0.9+---@param bufnr integer+---@param ft string+---@return boolean? local ts_attach = function(bufnr, ft)   -- ts is already attach, see $VIMRUNTIME/lua/vim/treesitter/highlighter.lua   if vim.b[bufnr].ts_highlight then return true end@@ -1001,7 +1044,7 @@ function Previewer.base:update_ts_context()     TSContext.close(self.win.preview_winid)     return   end-  local parser, err = vim.treesitter.get_parser(self.preview_bufnr, lang, { error = false })+  local parser, err = vim.treesitter.get_parser(bufnr, lang, { error = false })   -- TODO: fix `has_ts_parser` regression from a953548 (#2366)   -- should never fail since `utils.has_ts_parser` returned true   -- assert(parser, "'vim.treesitter.get_parser' err: " .. tostring(err))@@ -1013,15 +1056,15 @@ function Previewer.base:update_ts_context()   TSContext.zindex = self.win.winopts.zindex + 20   for _, t in ipairs({ 0, 20, 50, 100 }) do     vim.defer_fn(function()-      if context_updated-          or not tonumber(self.preview_bufnr)-          or not vim.api.nvim_buf_is_valid(self.preview_bufnr)+      if context_updated ---@diagnostic disable-next-line: preferred-local-alias+          or bufnr ~= self.preview_bufnr+          or not api.nvim_buf_is_valid(bufnr)       then         return       end       if parser:is_valid(true) then         context_updated = true-        TSContext.update(self.win.preview_winid, self.preview_bufnr, vim.tbl_extend("force",+        TSContext.update(self.win.preview_winid, bufnr, vim.tbl_extend("force",           type(self.treesitter.context) == "table" and self.treesitter.context or {}, {             -- `multiwindow` must be set regardless of user options             multiwindow = true,@@ -1033,7 +1076,7 @@ end  function Previewer.base:update_render_markdown()   local bufnr = self.preview_bufnr-  local ft = vim.b[bufnr] and vim.b[bufnr]._ft+  local ft = bufnr and vim.b[bufnr] and vim.b[bufnr]._ft or nil   if not ft       or not self.render_markdown.enabled       or not self.render_markdown.filetypes[ft]@@ -1118,7 +1161,7 @@ local filetype_detect = function(bufnr, filepath)   return vim.bo[bufnr].filetype end ----@param entry? fzf-lua.buffer_or_file.Entry+---@param entry? fzf-lua.buffer_or_file.Entry|{} function Previewer.buffer_or_file:do_syntax(entry)   if not self.preview_bufnr or not entry or not entry.path then return end   local bufnr = self.preview_bufnr@@ -1216,13 +1259,14 @@ function Previewer.base:maybe_set_cursorline(win, pos)       and pos[1] <= wininfo.botline   then     -- reset cursor pos even when it's already there, no bigggie-    -- local curpos = vim.api.nvim_win_get_cursor(win)-    vim.api.nvim_win_set_cursor(win, pos)-    cursorline = self.winopts.cursorline+    -- local curpos = api.nvim_win_get_cursor(win)+    api.nvim_win_set_cursor(win, pos)+    cursorline = self.winopts.cursorline or false   end-  utils.wo[win].cursorline = cursorline+  utils.wo[win].cursorline = cursorline and true or false end +---@param entry fzf-lua.buffer_or_file.Entry function Previewer.buffer_or_file:set_cursor_hl(entry)   local mgrep, glob_args = require("fzf-lua.providers.grep"), nil   local regex = self.opts.__ACT_TO == mgrep.grep and self.opts._last_query@@ -1251,10 +1295,10 @@ function Previewer.buffer_or_file:set_cursor_hl(entry)   regex = regex and #regex > 0 and utils.regex_to_magic(regex)       or entry.ctag and utils.ctag_to_magic(entry.ctag) -  pcall(vim.api.nvim_win_call, self.win.preview_winid, function()+  pcall(api.nvim_win_call, self.win.preview_winid, function()     local cached_pos = self.cached_bufnrs[tostring(self.preview_bufnr)]     if type(cached_pos) ~= "table" then cached_pos = nil end-    local lnum, col = tonumber(entry.line), tonumber(entry.col) or 0+    local lnum, col = entry.line, entry.col or 0     if not lnum or lnum < 1 then       -- set win option is slow with bigfile       utils.wo.cursorline = false@@ -1287,12 +1331,14 @@ function Previewer.buffer_or_file:set_cursor_hl(entry)           regex, reg)       end       if regex_start > 0 then+        ---@diagnostic disable-next-line: assign-type-mismatch         self.match_id = fn.matchaddpos(self.win.hls.search, { { lnum, regex_start, regex_end } }, 11)       end     end      -- Fallback to cursor hl, only if column exists     if regex_start <= 0 and self.win.hls.cursor and col > 0 then+      ---@diagnostic disable-next-line: assign-type-mismatch       self.match_id = fn.matchaddpos(self.win.hls.cursor, { { lnum, math.max(1, col) } }, 11)     end @@ -1312,7 +1358,7 @@ function Previewer.buffer_or_file:update_title(entry)   local title = entry.debug and "[DEBUG]" or filepath or entry.uri or entry.bufname   -- was transform function defined?   if self.title_fnamemodify then-    local wincfg = vim.api.nvim_win_get_config(self.win.preview_winid)+    local wincfg = api.nvim_win_get_config(self.win.preview_winid)     title = self.title_fnamemodify(title, wincfg and wincfg.width)   end   if entry.bufnr then@@ -1339,16 +1385,7 @@ function Previewer.buffer_or_file:preview_buf_post(entry, min_winopts)      -- syntax highlighting     if self.syntax then-      if self.syntax_delay > 0 then-        local syntax_bufnr = self.preview_bufnr-        vim.defer_fn(function()-          if self.preview_bufnr == syntax_bufnr then-            syntax()-          end-        end, self.syntax_delay)-      else-        syntax()-      end+      self:debounce("syntax", self.syntax_delay, syntax)     end   end @@ -1367,8 +1404,7 @@ function Previewer.buffer_or_file:preview_buf_post(entry, min_winopts)    -- Should we cache the current preview buffer?   -- we cache only named buffers with valid path/uri-  if not entry.do_not_cache then-    ---@type fzf-lua.buffer_or_file.Bcache+  if not entry.do_not_cache and self.preview_bufnr then     local cached = self:cache_buffer(self.preview_bufnr, self:key_from_entry(entry), min_winopts)     cached.tick = entry.tick   end@@ -1383,6 +1419,7 @@ function Previewer.help_tags:new(o, opts)   return self end +---@diagnostic disable-next-line: unused function Previewer.help_tags:parse_entry(entry_str)   local tag = entry_str:match("^[^%s]+")   if not tag then@@ -1418,6 +1455,10 @@ function Previewer.help_tags:gen_winopts()   return vim.tbl_extend("keep", winopts, self.winopts) end +---@class fzf-lua.help_tags.Entry: fzf-lua.buffer_or_file.Entry+---@field hregex? string++---@param entry fzf-lua.help_tags.Entry function Previewer.help_tags:set_cursor_hl(entry)   pcall(api.nvim_win_call, self.win.preview_winid, function()     -- start searching at line 1 in case we@@ -1437,6 +1478,8 @@ end ---@field super fzf-lua.previewer.Builtin,{} Previewer.man_pages = Previewer.base:extend() +---@diagnostic disable-next-line: unused+---@return boolean function Previewer.man_pages:should_clear_preview(_)   return false end@@ -1458,6 +1501,7 @@ function Previewer.man_pages:new(o, opts)   return self end +---@diagnostic disable-next-line: unused function Previewer.man_pages:parse_entry(entry_str)   return require("fzf-lua.providers.manpages").manpage_sh_arg(entry_str) end@@ -1469,8 +1513,8 @@ function Previewer.man_pages:populate_preview_buf(entry_str)   if type(cmd) == "string" then cmd = { "sh", "-c", cmd } end   local output, _ = utils.io_systemlist(cmd)   local tmpbuf = self:get_tmp_buffer()-  -- vim.api.nvim_buf_set_option(tmpbuf, 'modifiable', true)-  vim.api.nvim_buf_set_lines(tmpbuf, 0, -1, false, output)+  -- api.nvim_buf_set_option(tmpbuf, 'modifiable', true)+  api.nvim_buf_set_lines(tmpbuf, 0, -1, false, output)   vim.bo[tmpbuf].filetype = self.filetype   self:set_preview_buf(tmpbuf)   self.win:update_preview_scrollbar()@@ -1494,10 +1538,10 @@ function Previewer.marks:parse_entry(entry_str)    -- nvim_buf_get_mark cannot get `'` mark correctly without curwin   -- https://github.com/neovim/neovim/issues/29807-  local win = vim.api.nvim_win_is_valid(self.win.src_winid) and self.win.src_winid or 0-  local buf = vim.api.nvim_buf_is_valid(self.win.src_bufnr) and self.win.src_bufnr or 0+  local win = api.nvim_win_is_valid(self.win.src_winid) and self.win.src_winid or 0+  local buf = api.nvim_buf_is_valid(self.win.src_bufnr) and self.win.src_bufnr or 0   local pos = api.nvim_win_call(win, function()-    return vim.api.nvim_buf_get_mark(buf, mark)+    return api.nvim_buf_get_mark(buf, mark)   end)   if pos and pos[1] > 0 then     bufnr = self.win.src_bufnr@@ -1541,7 +1585,7 @@ function Previewer.jumps:parse_entry(entry_str)       -- file is not accessible,       -- text is a string from current buffer       bufnr = self.win.src_bufnr-      filepath = vim.api.nvim_buf_get_name(self.win.src_bufnr)+      filepath = api.nvim_buf_get_name(self.win.src_bufnr)     end   end   return {@@ -1561,12 +1605,13 @@ function Previewer.tags:new(o, opts)   return self end +---@param entry fzf-lua.buffer_or_file.Entry function Previewer.tags:set_cursor_hl(entry)   if tonumber(entry.line) and entry.line > 0 then     Previewer.buffer_or_file.set_cursor_hl(self, entry)     return   end-  -- pcall(vim.fn.clearmatches, self.win.preview_winid)+  -- pcall(fn.clearmatches, self.win.preview_winid)   pcall(api.nvim_win_call, self.win.preview_winid, function()     -- start searching at line 1 in case we     -- didn't reload the buffer (same file)@@ -1585,6 +1630,8 @@ end ---@field super fzf-lua.previewer.Builtin,{} Previewer.highlights = Previewer.base:extend() +---@diagnostic disable-next-line: unused+---@return boolean function Previewer.highlights:should_clear_preview(_)   return false end@@ -1599,7 +1646,7 @@ end  function Previewer.highlights:new(o, opts)   Previewer.highlights.super.new(self, o, opts)-  self.ns_previewer = vim.api.nvim_create_namespace("fzf-lua.previewer.hl")+  self.ns_previewer = api.nvim_create_namespace("fzf-lua.previewer.hl")   return self end @@ -1618,7 +1665,7 @@ function Previewer.highlights:populate_preview_buf(entry_str)   local hlgroup = hl   local lines = {}   repeat-    local hl_def = vim.api.nvim_get_hl(0, { name = hl, link = true })+    local hl_def = api.nvim_get_hl(0, { name = hl, link = true })     local block = utils.strsplit(serpent.block(hl_def, { comment = false, sortkeys = false }), "\n")     block[1] = string.format("%s = %s", hl, block[1])     vim.tbl_map(function(l) table.insert(lines, l) end, block)@@ -1626,10 +1673,10 @@ function Previewer.highlights:populate_preview_buf(entry_str)   until not hl   table.insert(lines, [[]])   table.insert(lines, [["THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG"]])-  vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)+  api.nvim_buf_set_lines(buf, 0, -1, false, lines)   self.win:update_preview_title(hl)   self.win:update_preview_scrollbar()-  vim.api.nvim_win_call(self.win.preview_winid, function()+  api.nvim_win_call(self.win.preview_winid, function()     if self.match_id then       pcall(fn.matchdelete, self.match_id)       self.match_id = nil@@ -1642,6 +1689,8 @@ end ---@field super fzf-lua.previewer.Builtin,{} Previewer.quickfix = Previewer.base:extend() +---@diagnostic disable-next-line: unused+---@return boolean function Previewer.quickfix:should_clear_preview(_)   return true end@@ -1671,8 +1720,8 @@ function Previewer.quickfix:populate_preview_buf(entry_str)   end    local qf_list = self.opts._is_loclist-      and vim.fn.getloclist(self.win.src_winid, { all = "", nr = tonumber(nr) })-      or vim.fn.getqflist({ all = "", nr = tonumber(nr) })+      and fn.getloclist(self.win.src_winid, { all = "", nr = tonumber(nr) })+      or fn.getqflist({ all = "", nr = tonumber(nr) })   if utils.tbl_isempty(qf_list) or utils.tbl_isempty(qf_list.items) then     return   end@@ -1681,11 +1730,11 @@ function Previewer.quickfix:populate_preview_buf(entry_str)   for _, e in ipairs(qf_list.items) do     table.insert(lines, string.format("%s|%d col %d|%s",       path.HOME_to_tilde(path.relative_to(-        vim.api.nvim_buf_get_name(e.bufnr), uv.cwd())),+        api.nvim_buf_get_name(e.bufnr), uv.cwd())),       e.lnum, e.col, e.text))   end   self.tmpbuf = self:get_tmp_buffer()-  vim.api.nvim_buf_set_lines(self.tmpbuf, 0, -1, false, lines)+  api.nvim_buf_set_lines(self.tmpbuf, 0, -1, false, lines)   vim.bo[self.tmpbuf].filetype = "qf"   self:set_preview_buf(self.tmpbuf)   self.win:update_preview_title(string.format(" %s: %s ", nr, qf_list.title))@@ -1701,6 +1750,7 @@ function Previewer.autocmds:new(o, opts)   return self end +---@return fzf-lua.config.Winopts|{}? function Previewer.autocmds:gen_winopts()   if not self._is_vimL_command then     return self.winopts@@ -1725,7 +1775,7 @@ function Previewer.autocmds:populate_preview_buf(entry_str)     local viml = entry_str:match("[^│]+$")     local lines = vim.split(viml, "\n")     local tmpbuf = self:get_tmp_buffer()-    vim.api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)+    api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)     vim.bo[tmpbuf].filetype = "vim"     self:set_preview_buf(tmpbuf)     self:preview_buf_post(entry)@@ -1757,9 +1807,10 @@ function Previewer.keymaps:populate_preview_buf(entry_str)     -- so we display the vimL code instead     local lines = utils.strsplit(entry.vmap:match("[^%s]+$"), "\n")     local tmpbuf = self:get_tmp_buffer()-    vim.api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)+    api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)     vim.bo[tmpbuf].filetype = "vim"     self:set_preview_buf(tmpbuf)+    ---@diagnostic disable-next-line: assign-type-mismatch     local title_fnamemodify = self.title_fnamemodify     self.title_fnamemodify = nil     -- hack entry.uri for title display@@ -1776,8 +1827,8 @@ Previewer.nvim_options = Previewer.base:extend()  function Previewer.nvim_options:new(o, opts)   Previewer.nvim_options.super.new(self, o, opts)-  local paths = vim.fn.globpath(vim.o.rtp, "doc/options.txt", false, true)-  self.lines = vim.fn.readfile(paths[1])+  local paths = fn.globpath(vim.o.rtp, "doc/options.txt", false, true)+  self.lines = fn.readfile(paths[1])   return self end @@ -1842,12 +1893,12 @@ function Previewer.nvim_options:populate_preview_buf(entry_str)   }    local tmpbuf = self:get_tmp_buffer()-  vim.api.nvim_set_option_value("filetype", "help", { buf = tmpbuf })+  api.nvim_set_option_value("filetype", "help", { buf = tmpbuf })    -- get_help_text might be slow. pcall to prevent errors when scrolling the list too quickly   pcall(function()     local lines = vim.list_extend(header, self:get_help_text(entry.name) or {})-    vim.api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)+    api.nvim_buf_set_lines(tmpbuf, 0, -1, false, lines)     self:set_preview_buf(tmpbuf)   end) 

lua/fzf-lua/previewer/codeaction.lua

@@ -167,7 +167,8 @@ local function preview_action_tuple(self, idx, callback)       -- runtime/lua/lsp/buf.lua:on_user_choice       and (function()         ---@var choice {action: lsp.Command|lsp.CodeAction, ctx: lsp.HandlerContext}-        local ms = require("vim.lsp.protocol").Methods+        ---@diagnostic disable-next-line: deprecated+        local ms = vim.lsp.protocol.Methods or require("vim.lsp.protocol").Methods         local choice = self.opts._items[idx]         local bufnr = assert(choice.ctx.bufnr, "Must have buffer number")         local reg = client.dynamic_capabilities:get(ms.textDocument_codeAction, { bufnr = bufnr })

lua/fzf-lua/previewer/fzf.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local path = require "fzf-lua.path" local shell = require "fzf-lua.shell"@@ -11,6 +12,9 @@ local Previewer = {} Previewer.base = Object:extend()  -- Previewer base object+---@param o fzf-lua.config.Previewer+---@param opts fzf-lua.config.Resolved+---@return fzf-lua.previewer.Fzf function Previewer.base:new(o, opts)   o = o or {}   self.type = "cmd";@@ -35,6 +39,12 @@ function Previewer.base:setup_opts(opts)   return opts end +---@diagnostic disable-next-line: unused+function Previewer.base:cmdline(_)+  return ""+end++---@diagnostic disable-next-line: unused function Previewer.base:preview_window(_)   return nil end@@ -57,6 +67,7 @@ function Previewer.base:_preview_offset(lnum)   end end +---@return string function Previewer.base:fzf_delimiter()   -- set delimiter to ':'   -- entry format is 'file:line:col: text'@@ -85,6 +96,7 @@ function Previewer.cmd:new(o, opts)   return self end +---@diagnostic disable-next-line: unused function Previewer.cmd:format_cmd(cmd, args, action, extra_args)   return string.format([[%s %s %s "$(%s)"]],     cmd, args or "", extra_args or "", action)@@ -188,11 +200,11 @@ local grep_tag = function(file, tag)   table.insert(cmd, filepath)   local out, rc = utils.io_system(cmd)   if rc == 0 then-    line = tonumber(out:match("[^:]+")) or 1+    line = utils.tointeger(out:match("[^:]+")) or 1   else     utils.warn(("previewer: unable to find pattern '%s' in file '%s'"):format(pattern, file))   end-  return tonumber(line)+  return line end  function Previewer.cmd_async:parse_entry_and_verify(entrystr)@@ -298,7 +310,7 @@ function Previewer.bat_async:cmdline(o)       -- this is a ctag without line numbers, since we can't       -- provide the preview file offset to fzf via the field       -- index expression we use '--line-range' instead-      local start_line = math.max(1, entry.line - fzf_lines / 2)+      local start_line = utils.tointeger(math.max(1, entry.line - fzf_lines / 2))       local end_line = start_line + fzf_lines - 1       line_range = ("--line-range=%d:%d"):format(start_line, end_line)     end@@ -346,7 +358,7 @@ function Previewer.git_diff:cmdline(o)   local act = shell.stringify_cmd(function(items, fzf_lines, fzf_columns)     if not items or utils.tbl_isempty(items) then       utils.warn("shell error while running preview action.")-      return+      return utils.shell_nop()     end     local is_deleted = items[1]:match(self.git_icons["D"] .. utils.nbsp) ~= nil     local is_modified = items[1]:match("[" ..@@ -371,7 +383,8 @@ function Previewer.git_diff:cmdline(o)     elseif is_deleted then       cmd = self.cmd_deleted     elseif is_untracked then-      local stat = uv.fs_stat(entry.path)+      local stat = entry.path and uv.fs_stat(entry.path)+      ---@diagnostic disable-next-line: undefined-field       if stat and stat.type == "directory" then         cmd = utils._if_win({ "dir" }, { "ls", "-la" })       else@@ -425,6 +438,7 @@ Previewer.man_pages = Previewer.base:extend() function Previewer.man_pages:new(o, opts)   Previewer.man_pages.super.new(self, o, opts)   self.cmd = o.cmd or "man -c %s | col -bx"+  ---@diagnostic disable-next-line: assign-type-mismatch   self.cmd = type(self.cmd) == "function" and self.cmd() or self.cmd   return self end

lua/fzf-lua/previewer/init.lua

@@ -32,6 +32,22 @@ Previewer.swiper = {} Previewer.swiper.default = function() return require "fzf-lua.previewer.swiper".default end  +---@class fzf-lua.config.Previewer+---@field new? fun(opts: fzf-lua.config.Previewer, opt: fzf-lua.config.Previewer, o: fzf-lua.config.Resolved)+---@field _new? function(opt: fzf-lua.config.Previewer, o: fzf-lua.config.Resolved)+---@field _ctor? function(opt: fzf-lua.config.Previewer, o: fzf-lua.config.Resolved)+---@field cmd? string+---@field args? string+---@field preview_offset? string+---@field cmd_deleted? string+---@field cmd_modified? string+---@field cmd_untracked? string+---@field theme? string+---@field pager? string|function+---@field _fn_git_icons? table[]|fun():table+---builtin+---@field title_fnamemodify? function+ ---Instantiate previewer from spec ---@param spec table ---@param opts table@@ -58,14 +74,14 @@ Previewer.new = function(spec, opts)   return previewer end ----@alias fzf-lua.preview.Spec function|{[1]: function?, fn: function?, field_index: string?}+---@alias fzf-lua.preview.Spec function|{[1]: function?, fn: function?, field_index: string?}|string ---convert preview action functions to strings using our shell wrapper ---@param preview fzf-lua.preview.Spec ---@param opts table ---@return string? Previewer.normalize_spec = function(preview, opts)   if type(preview) == "function" then-    return FzfLua.shell.stringify_data(preview, opts, "{}")+    return (FzfLua.shell.stringify_data(preview, opts, "{}"))   elseif type(preview) == "table" then     preview = vim.tbl_extend("keep", preview, {       fn = preview.fn or preview[1],@@ -74,9 +90,9 @@ Previewer.normalize_spec = function(preview, opts)       field_index = "{}",     })     if preview.type == "cmd" then-      return FzfLua.shell.stringify_cmd(preview.fn, opts, preview.field_index)+      return (FzfLua.shell.stringify_cmd(preview.fn, opts, preview.field_index))     end-    return FzfLua.shell.stringify_data(preview.fn, opts, preview.field_index)+    return (FzfLua.shell.stringify_data(preview.fn, opts, preview.field_index))   else     return preview   end

lua/fzf-lua/previewer/swiper.lua

@@ -13,10 +13,9 @@ function M.base:new(o, opts)   o = o or {}   self.opts = opts;   local ctx = utils.__CTX()-  assert(ctx, "CTX shoud not be nil")   self.ctx_winid = ctx.winid   self.ctx_bufnr = ctx.bufnr-  self.ctx_winopts = vim.deepcopy(ctx.winopts)+  self.ctx_winopts = vim.deepcopy(ctx.winopts or {})   assert(vim.api.nvim_buf_is_valid(self.ctx_bufnr), "origin buf is not valid")   assert(vim.api.nvim_win_is_valid(self.ctx_winid), "origin win is not valid")   assert(self.ctx_bufnr == vim.api.nvim_win_get_buf(self.ctx_winid), "win buf mismatch")@@ -60,8 +59,7 @@ end ---@return integer? col_valid_idx ---@return integer? col_offset function M.base:parse_lnum_col(line, is_entry)-  local off = 0-  local prefix, lnum, col+  local prefix, lnum, col, off   if self.picker == "git_blame" then     prefix, lnum = line:match("^(.-)(%d+)%)")     off = 1 + (lnum and #tostring(lnum) or 0)@@ -81,11 +79,12 @@ function M.base:parse_lnum_col(line, is_entry)   elseif self.picker == "treesitter" or self.picker == "lsp_document_symbols" then     prefix = line:gsub("%s+$", ""):match("(.*%s+).+$")     lnum, col = line:match("^.-(%d+):(%d+)%s")-    off = col and (1 - tonumber(col) - 1)+    off = col and (1 - assert(tonumber(col)) - 1)   end   if lnum then     -- use `vin.fn.strwidth` for proper adjustment of fzf's marker/pointer if unicode-    return tonumber(lnum), tonumber(col), prefix and vim.fn.strwidth(prefix) or 0, off or 0+    return utils.tointeger(lnum), utils.tointeger(col), prefix and vim.fn.strwidth(prefix) or 0,+        off or 0   end end 

lua/fzf-lua/profiles/cli.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local api, uv, fn = vim.api, vim.uv or vim.loop, vim.fn ---@module 'ffi'? local ffi = vim.F.npcall(require, "ffi")@@ -20,7 +21,7 @@ end) local function quit() vim.cmd.quit() end  local function posix_exec(cmd, ...)-  local _is_win = vim.fn.has("win32") == 1 or vim.fn.has("win64") == 1+  local _is_win = fn.has("win32") == 1 or fn.has("win64") == 1   if type(cmd) ~= "string" or _is_win or not ffi then return end   ffi.C.execl(cmd, cmd, ...) end@@ -30,17 +31,19 @@ local function parse_entry(e) return e and e:match("%((.-)%)") or nil end _G.fzf_tty_get_width = function()   if not ffi then return (assert(uv.new_tty(0, false)):get_winsize()) end   local TIOCGWINSZ = 0x5413-  local ws = ffi.new("struct winsize[1]")+  ---@diagnostic disable-next-line: assign-type-mismatch+  local ws = ffi.new("struct winsize[1]") ---@type [{ ws_row: integer, ws_col: integer }]   local ret = ffi.C.ioctl(0, TIOCGWINSZ, ws)+  ---@diagnostic disable-next-line: undefined-field   if ret == 0 then return ws[0].ws_col end-  return nil end  _G.fzf_pty_spawn = function(cmd, opts)   local function openpty(rows, cols)+    ---@diagnostic disable: assign-type-mismatch     -- Lua doesn't have out-args so we create short arrays of numbers.-    local amaster = ffi.new("int[1]")-    local aslave = ffi.new("int[1]")+    local amaster = ffi.new("int[1]") ---@type [integer]+    local aslave = ffi.new("int[1]") ---@type [integer]     ---@type { ws_row: integer, ws_col: integer }     local winp = ffi.new("struct winsize")     winp.ws_row = rows@@ -109,7 +112,7 @@ return {             entries[1].col and ("+norm! %s|"):format(entries[1].col) or nil)         elseif ffi and #entries > 1 then           local file = fn.tempname()-          vim.fn.writefile(vim.tbl_map(function(e) -- Format: {filename}:{lnum}:{col}: {text}+          fn.writefile(vim.tbl_map(function(e) -- Format: {filename}:{lnum}:{col}: {text}             local text = e.stripped:match(":%d+:%d?%d?%d?%d?:?(.*)$") or ""             return ("%s:%d:%d: %s"):format(e.path, e.line or 1, e.col or 1, text)           end, entries), file)

lua/fzf-lua/profiles/hide.lua

@@ -1,5 +1,8 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local fzf = require("fzf-lua")++---@type fzf-lua.Config|{} return {   desc     = "hide interface instead of abort",   keymap   = {@@ -45,6 +48,7 @@ return {           _on_create(e)         end       end+      ---@diagnostic disable: assign-type-mismatch       opts.actions["esc"] = {         fn = fzf.actions.dummy_abort,         desc = "hide",@@ -70,7 +74,7 @@ return {           act.desc = act.desc or fzf.config.get_action_helpstr(fn)           act.fn = function(...)             fzf.hide()-            fn(...)+            if fn then fn(...) end             -- As the process never terminates fzf history is never written             -- manually append to the fzf history file if needed             local o = select(2, ...)

lua/fzf-lua/providers/buffers.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local core = require "fzf-lua.core" local path = require "fzf-lua.path"@@ -72,7 +73,7 @@ local filter_buffers = function(opts, unfiltered)         if buf_valid and vim.api.nvim_get_option_value("ft", { buf = b }) == "qf" then           excluded[b] = not opts.show_quickfix and true or nil         end-        if not excluded[b] and b > max_bufnr then+        if not excluded[b] and b > max_bufnr then ---@diagnostic disable-next-line: assign-type-mismatch           max_bufnr = b         end         return not excluded[b]@@ -270,9 +271,8 @@ M.buffer_lines = function(opts)       local bnames = {}       local longest_bname = 0       for _, b in ipairs(buffers) do-        ---@type string         local bname = utils.nvim_buf_get_name(b)-        if not bname:match("^%[") then+        if bname and not bname:match("^%[") then           bname = path.shorten(vim.fn.fnamemodify(bname, ":~:."))         end         longest_bname = math.max(longest_bname, #bname)@@ -327,10 +327,11 @@ M.buffer_lines = function(opts)           lines = end_line - start_line + 1           if opts.start == "cursor" then             -- start display from current line and wrap from bottom (#822)-            offset = utils.CTX().cursor[1] - start_line+            offset = assert(utils.CTX().cursor[1]) - start_line           end         end +        assert(opts.hls)         for i = 1, lines do           local lnum = i + offset           if lnum > lines then@@ -418,6 +419,7 @@ M.tabs = function(opts)       return ret     end)() +    assert(opts.hls)     for tabnr, tabh in ipairs(vim.api.nvim_list_tabpages()) do       (function()         if opts.current_tab_only and tabh ~= utils.CTX().tabh then return end@@ -482,10 +484,10 @@ M.treesitter = function(opts)   end    -- Default to current buffer-  local bufnr0 = tonumber(opts.bufnr) or vim.api.nvim_get_current_buf()+  local bufnr0 = utils.tointeger(opts.bufnr) or vim.api.nvim_get_current_buf()   local bufname0 = path.basename(vim.api.nvim_buf_get_name(bufnr0))   if not bufname0 or #bufname0 == 0 then-    bufname0 = utils.nvim_buf_get_name(bufnr0)+    bufname0 = assert(utils.nvim_buf_get_name(bufnr0))   end    local ts = vim.treesitter@@ -577,15 +579,16 @@ M.treesitter = function(opts)             vim.schedule(function()               -- Remove node prefix, e.g. `locals.definition.var`               node.kind = node.kind and node.kind:gsub(".*%.", "")-              local lnum, col, _, _ = vim.treesitter.get_node_range(node.node)-              local node_text = vim.treesitter.get_node_text(node.node, bufnr0)+              local lnum, col, _, _ = ts.get_node_range(node.node)+              local node_text = ts.get_node_text(node.node, bufnr0)               local node_kind = node.kind and utils.ansi_from_hl(kind2hl(node.kind), node.kind)+              local hls = assert(opts.hls)               local entry = string.format("[%s]%s%s:%s:%s\t\t[%s] %s",-                utils.ansi_codes[opts.hls.buf_nr](tostring(bufnr0)),+                utils.ansi_codes[hls.buf_nr](tostring(bufnr0)),                 utils.nbsp,-                utils.ansi_codes[opts.hls.buf_name](bufname0),-                utils.ansi_codes[opts.hls.buf_linenr](tostring(lnum + 1)),-                utils.ansi_codes[opts.hls.path_colnr](tostring(col + 1)),+                utils.ansi_codes[hls.buf_name](bufname0),+                utils.ansi_codes[hls.buf_linenr](tostring(lnum + 1)),+                utils.ansi_codes[hls.path_colnr](tostring(col + 1)),                 node_kind or "",                 node_text)               cb(entry, function(err)@@ -620,7 +623,7 @@ M.spellcheck = function(opts)   local bufnr0 = tonumber(opts.bufnr) or vim.api.nvim_get_current_buf()   local bufname0 = path.basename(vim.api.nvim_buf_get_name(bufnr0))   if not bufname0 or #bufname0 == 0 then-    bufname0 = utils.nvim_buf_get_name(bufnr0)+    bufname0 = assert(utils.nvim_buf_get_name(bufnr0))   end    if utils.mode_is_visual() then@@ -664,7 +667,7 @@ M.spellcheck = function(opts)            if opts.start == "cursor" then             -- start display from current line and wrap from bottom-            offset = utils.CTX().cursor[1] - start_line+            offset = assert(utils.CTX().cursor[1]) - start_line           end            for i = 1, lines do@@ -674,6 +677,7 @@ M.spellcheck = function(opts)             end             lnum = lnum + start_line - 1 +            ---@type integer, integer?, integer?             local line, from, to = data[lnum], 1, nil             repeat               local word_separator = opts.word_separator or "[%s%p]"@@ -691,12 +695,13 @@ M.spellcheck = function(opts)                 local _, lead = word:find("^" .. word_separator .. "+")                 local spell = vim.spell.check(trim(word))[1]                 if spell then+                  local hls = assert(opts.hls)                   cb(string.format("[%s]%s%s:%s:%-26s\t\t%s",-                    utils.ansi_codes[opts.hls.buf_nr](tostring(bufnr0)),+                    utils.ansi_codes[hls.buf_nr](tostring(bufnr0)),                     utils.nbsp,-                    utils.ansi_codes[opts.hls.buf_name](bufname0),-                    utils.ansi_codes[opts.hls.buf_linenr](tostring(lnum)),-                    utils.ansi_codes[opts.hls.path_colnr](tostring(from + (lead or 0))),+                    utils.ansi_codes[hls.buf_name](bufname0),+                    utils.ansi_codes[hls.buf_linenr](tostring(lnum)),+                    utils.ansi_codes[hls.path_colnr](tostring(from + (lead or 0))),                     trim(word)                   ), function(err)                     -- coroutine.resume(co)

lua/fzf-lua/providers/colorschemes.lua

@@ -7,6 +7,7 @@ local actions = require "fzf-lua.actions"  -- For AsyncDownloadManager local Object = require "fzf-lua.class"+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop  local function get_current_colorscheme()@@ -68,6 +69,7 @@ M.colorschemes = function(opts)         live = sel[1]         vim.cmd("colorscheme " .. sel[1])       end+      ---@diagnostic disable-next-line: param-type-mismatch     end, opts, "{}")   end @@ -473,7 +475,7 @@ M.awesome_colorschemes = function(opts)   if opts.live_preview then     opts.fzf_opts["--preview-window"] = "nohidden:right:0"     opts.preview = shell.stringify_data(function(sel)-      if opts.live_preview and sel then+      if opts.live_preview and sel and sel[1] then         local dbkey, idx = sel[1]:match("^(.-):(%d+):")         if opts._adm:downloaded(dbkey) then           -- some colorschemes choose a different theme based on dark|light bg

lua/fzf-lua/providers/dap.lua

@@ -1,4 +1,5 @@----@diagnostic disable: undefined-field, param-type-mismatch+---@diagnostic disable: undefined-field+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local core = require "fzf-lua.core" local utils = require "fzf-lua.utils"@@ -15,6 +16,7 @@ local M = {} -- in case the plugin was lazy loaded local function dap()   if _has_dap and _dap then return _dap end+  ---@diagnostic disable-next-line: assign-type-mismatch   _has_dap, _dap = pcall(require, "dap")   if not _has_dap or not _dap then     utils.info("DAP requires 'mfussenegger/nvim-dap'")@@ -192,6 +194,7 @@ M.frames = function(opts)   opts.previewer = {     _ctor = function()       local p = require("fzf-lua.previewer.builtin").buffer_or_file:extend()+      ---@diagnostic disable-next-line: unused       ---@param entry_str string       ---@return fzf-lua.buffer_or_file.Entry       function p:parse_entry(entry_str)@@ -208,7 +211,7 @@ M.frames = function(opts)           if fs_stat and fs_stat.type == "file" then             return {               path = path,-              line = f.line,+              line = utils.tointeger(f.line),               -- col = f.column,             }           end@@ -226,7 +229,7 @@ M.frames = function(opts)           return {             path = f.source.path,             content = result and vim.split(result.content or "", "\n") or nil,-            line = f.line,+            line = utils.tointeger(f.line),           }         end 

lua/fzf-lua/providers/diagnostic.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local core = require "fzf-lua.core" local utils = require "fzf-lua.utils"@@ -210,8 +211,8 @@ M.diagnostics = function(opts)                 diag_entry.filename = utils.ansi_from_hl(sign_def.texthl, diag_entry.filename)               end -              local entry = make_entry.lcol(diag_entry, opts)-              entry = make_entry.file(entry, opts)+              local entry0 = make_entry.lcol(diag_entry, opts)+              local entry = make_entry.file(entry0, opts)               if entry == nil then entry = "" end               if not entry then                 -- entry to be skipped (e.g. 'cwd_only')@@ -269,7 +270,7 @@ M.diagnostics = function(opts) end  ---@param opts fzf-lua.config.Diagnostics|{}?----@return thread?, string?, table?+---@return (thread|table)?, string?, table? M.all = function(opts)   if not opts then opts = {} end   opts.diag_all = true

lua/fzf-lua/providers/files.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local core = require "fzf-lua.core" local path = require "fzf-lua.path"@@ -120,9 +121,10 @@ M.args = function(opts)       for i = 0, argc - 1 do         vim.schedule(function()           local s = vim.fn.argv(i)+          ---@cast s string           local st = uv.fs_stat(s)           if opts.files_only == false or st and st.type == "file" then-            s = make_entry.file(s, opts)+            s = assert(make_entry.file(s, opts))             cb(s, function()               coroutine.resume(co)             end)

lua/fzf-lua/providers/grep.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local path = require "fzf-lua.path" local core = require "fzf-lua.core"

lua/fzf-lua/providers/lsp.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local core = require "fzf-lua.core" local path = require "fzf-lua.path"@@ -144,8 +145,8 @@ local function location_handler(opts, cb, _, result, ctx, _)     if opts.current_buffer_only and not path.equals(utils.CTX().bname, item.filename) then       return false     end-    local entry = make_entry.lcol(item, opts)-    entry = make_entry.file(entry, opts)+    local entry0 = make_entry.lcol(item, opts)+    local entry = make_entry.file(entry0, opts)     if not entry then       -- Filtered by cwd / file_ignore_patterns, etc       return false@@ -167,13 +168,13 @@ local function call_hierarchy_handler(opts, cb, _, result, ctx, _)       local location = {         uri = call_hierarchy_item.uri,         range = range,-        filename = assert(vim.uri_to_fname(call_hierarchy_item.uri)),+        filename = vim.uri_to_fname(call_hierarchy_item.uri),         text = call_hierarchy_item.name,         lnum = range.start.line + 1,         col = range.start.character + 1,       }-      local entry = make_entry.lcol(location, opts)-      entry = make_entry.file(entry, opts)+      local entry0 = make_entry.lcol(location, opts)+      local entry = make_entry.file(entry0, opts)       if entry then cb(entry, { result = location, encoding = encoding }) end     end   end@@ -419,10 +420,7 @@ local function gen_lsp_contents(opts)    if not opts.async then     -- SYNC-    local timeout = 5000-    if type(opts.async_or_timeout) == "number" then-      timeout = opts.async_or_timeout-    end+    local timeout = utils.tointeger(opts.async_or_timeout) or 5000     local lsp_results, err = vim.lsp.buf_request_sync(utils.CTX().bufnr,       lsp_handler.method, lsp_params, timeout)     if err then@@ -581,10 +579,7 @@ end  -- see $VIMRUNTIME/lua/vim/buf.lua:pick_call_hierarchy_item() local function gen_lsp_contents_hierarchy(opts)-  local timeout = 5000-  if type(opts.async_or_timeout) == "number" then-    timeout = opts.async_or_timeout-  end+  local timeout = utils.tointeger(opts.async_or_timeout) or 5000   local lsp_params = opts.lsp_params       ---@diagnostic disable-next-line: missing-parameter       or not utils.__HAS_NVIM_011 and vim.lsp.util.make_position_params(utils.CTX().winid)

lua/fzf-lua/providers/meta.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local core = require "fzf-lua.core" local path = require "fzf-lua.path"@@ -7,7 +8,7 @@ local config = require "fzf-lua.config"  local M = {} ----@param opts fzf-lua.config.Builtin+---@param opts fzf-lua.config.Builtin|{} ---@return thread?, string?, table? M.metatable = function(opts)   if not opts then return end@@ -262,6 +263,7 @@ M.global = function(opts)     end, opts, "{q}")   end +  opts._fzf_cli_args = opts._fzf_cli_args or {}   -- Insert at the start of the args table so `line_query` callback is first   table.insert(opts._fzf_cli_args, 1, "--bind="     .. libuv.shellescape("start:+transform:" .. transform_picker(true)))

lua/fzf-lua/providers/nvim.lua

@@ -76,6 +76,7 @@ M.commands = function(opts)   end    opts.flatten = opts.flatten or {}+  assert(opts.hls)   for k, _ in pairs(global_commands) do     table.insert(entries, utils.ansi_codes[opts.hls.cmd_global](k))     add_subcommand(k, utils.ansi_codes[opts.hls.cmd_global])@@ -94,6 +95,7 @@ M.commands = function(opts)   end    for k, _ in pairs(builtin_commands) do+    ---@diagnostic disable-next-line: undefined-field     table.insert(entries, utils.ansi_codes[opts.hls.cmd_ex](k))   end @@ -265,6 +267,7 @@ M.marks = function(opts)   opts = config.normalize_opts(opts, "marks")   if not opts then return end +  assert(opts.hls)   local contents = function(cb)     local buf = utils.CTX().bufnr     local entries = {}

lua/fzf-lua/providers/oldfiles.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local core = require "fzf-lua.core" local utils = require "fzf-lua.utils"@@ -35,7 +36,7 @@ M.oldfiles = function(opts)    if opts.include_current_session then     for _, buffer in ipairs(vim.split(vim.fn.execute(":buffers! t"), "\n")) do-      local bufnr = tonumber(buffer:match("%s*(%d+)")) ---@type integer+      local bufnr = tonumber(buffer:match("%s*(%d+)"))       if bufnr then         local file = vim.api.nvim_buf_get_name(bufnr)         local fs_stat = stat_fn(file)

lua/fzf-lua/providers/quickfix.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local core = require "fzf-lua.core" local utils = require "fzf-lua.utils"@@ -36,8 +37,8 @@ local quickfix_run = function(opts, cfg)       (function()         if opts.valid_only and loc.valid ~= 1 then return end         loc.text = loc.text:gsub("\r?\n", " ")-        local entry = make_entry.lcol(loc, opts)-        entry = make_entry.file(entry, opts)+        local entry0 = make_entry.lcol(loc, opts)+        local entry = make_entry.file(entry0, opts)         if not entry then return end         cb(string.format("[%s]%s%s",             utils.ansi_codes.yellow(tostring(loc.bufnr)),

lua/fzf-lua/providers/tags.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local path = require "fzf-lua.path" local utils = require "fzf-lua.utils"

lua/fzf-lua/providers/ui_select.lua

@@ -94,7 +94,6 @@ M.ui_select = function(items, ui_opts, on_choice)   -- deepcopy register opts so we don't poullute the original tbl ref (#2241)   if type(opts) == "table" then     opts = utils.tbl_deep_clone(opts)-    assert(opts) -- lint nil check   end    opts.fzf_opts = vim.tbl_extend("keep", opts.fzf_opts or {}, {@@ -155,6 +154,7 @@ M.ui_select = function(items, ui_opts, on_choice)    -- ui.select is code actions   -- inherit from defaults if not triggered by lsp_code_actions+  ---@type 'error'|'keep'|'force'   local opts_merge_strategy = "keep"    -- fix error when vim.lsp.buf.code_action() called but didn't triggers vim.ui.select

lua/fzf-lua/rpc.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop  local _is_win = vim.fn.has("win32") == 1 or vim.fn.has("win64") == 1

lua/fzf-lua/shell.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local utils = require "fzf-lua.utils" local path = require "fzf-lua.path"@@ -12,7 +13,7 @@ local __FILE__ = debug.getinfo(1, "S").source:gsub("^@", "") ---@field last_id integer ---@field mru integer[] ---@field store any[]----@field lookup table<integer, integer>+---@field lookup table<integer, integer?> local LRU = {}  function LRU:new(size)@@ -44,6 +45,7 @@ function LRU:set(value)     -- Evict the least recently used (last in MRU)     evicted_id = table.remove(self.mru)     store_idx = self.lookup[evicted_id]+    assert(store_idx)     self.lookup[evicted_id] = nil   else     store_idx = #self.store + 1@@ -187,11 +189,11 @@ end -- config over RPC, if the command doesn't require any processing it will be piped -- directly to fzf using $FZF_DEFAULT_COMMAND ---@param contents fzf-lua.content|fzf-lua.shell.data2----@param opts fzf-lua.config.Resolved|{}+---@param opts fzf-lua.config.Resolved ---@return string? M.stringify_mt = function(contents, opts)   if opts.multiprocess == false then return end-  ---@param o fzf-lua.config.Resolved|{}+  ---@param o fzf-lua.config.Resolved   ---@return table   local filter_opts = function(o)     local names = {@@ -233,7 +235,7 @@ M.stringify_mt = function(contents, opts)     end     local t = {}     for _, name in ipairs(names) do-      if o[name] ~= nil then+      if o[name] ~= nil then ---@diagnostic disable-next-line: assign-type-mismatch         t[name] = o[name]       end     end@@ -272,13 +274,15 @@ end -- Contents sent to fzf can only be nil or a shell command (string) -- the API accepts both tables and functions which we "stringify" ---@param contents table|string|fzf-lua.content|fzf-lua.shell.cmd|fzf-lua.shell.data|fzf-lua.shell.data2----@param opts {}+---@param opts fzf-lua.config.Resolved|{} ---@param fzf_field_index string? Fzf field index expression, e.g. "{+}" (selected), "{q}" (query) ---@return string, integer? M.stringify = function(contents, opts, fzf_field_index)   -- TODO: should we let this assert?   -- are there any conditions in which stringify is called subsequently?-  if opts.__stringified then return contents end+  if opts.__stringified then ---@cast contents string+    return contents+  end    -- Mark opts as already "stringified"   assert(not opts.__stringified, "twice stringified")@@ -295,7 +299,7 @@ M.stringify = function(contents, opts, fzf_field_index)     -- generates a different command based on the typed query     -- redefine local contents to prevent override on function call     ---@type fzf-lua.content, table?-    ---@diagnostic disable-next-line: redefined-local+    ---@diagnostic disable-next-line: redefined-local, assign-type-mismatch     local contents, env = (function()       local ret = opts.is_live and type(contents) == "function" and contents(unpack(args), opts)           or opts.__stringify_cmd and contents(unpack(args))@@ -439,7 +443,7 @@ end ---@alias fzf-lua.shell.cmdSpec string|{ cmd: string|string[], env: table? }? ---@alias fzf-lua.shell.cmd fun(items: string[], fzf_lines: integer, fzf_columns: integer): fzf-lua.shell.cmdSpec ---@alias fzf-lua.shell.data fun(items: string[], fzf_lines: integer, fzf_columns: integer): fzf-lua.content?----@alias fzf-lua.shell.data2 fun(items: string[], opts: fzf-lua.config.Resolved): fzf-lua.content?+---@alias fzf-lua.shell.data2 fun(items: string[], opts: fzf-lua.config.Resolved|{}): fzf-lua.content?  ---@param fn fzf-lua.shell.cmd ---@param opts table@@ -455,7 +459,7 @@ M.stringify_cmd = function(fn, opts, fzf_field_index) end  ---@param fn fzf-lua.shell.data----@param opts table+---@param opts fzf-lua.config.Resolved|{} ---@param fzf_field_index string? ---@return string, integer? M.stringify_data = function(fn, opts, fzf_field_index)@@ -490,7 +494,7 @@ M.stringify_data2 = function(fn, opts, field_index)     did_override = true   end   -- replace the action with shell cmd proxy to the original action-  return M.stringify_data(function(items, _, _)+  return (M.stringify_data(function(items, _, _)     local query, idx = items[#items - 1], items[#items]     FzfLua.config.resume_set("query", query, opts)     if did_override then@@ -511,10 +515,10 @@ M.stringify_data2 = function(fn, opts, field_index)       items = (zero_matched and zero_selected) and {} or items     end     return fn(items, opts)-  end, opts, field_index)+  end, opts, field_index)) end ----@param opts table+---@param opts fzf-lua.SpawnStdioOpts ---@return string M.wrap_spawn_stdio = function(opts)   local is_win = utils.__IS_WINDOWS

lua/fzf-lua/spawn.lua

@@ -33,6 +33,7 @@ end  -- global var indicating a headless instance _G._fzf_lua_is_headless = true+---@type fzf-lua.SpawnStdioOpts local opts = require("fzf-lua.libuv").deserialize(_G.arg[1]) local _, pid = require("fzf-lua.libuv").spawn_stdio(opts) -- while vim.uv.run() do end -- os.exit in spawn_stdio

lua/fzf-lua/test/helpers.lua

@@ -44,7 +44,7 @@ local os_detect = { for k, v in pairs(os_detect) do   M["IS_" .. k] = function()     local var = "_IS_" .. k-    if M[var] == nil then+    if M[var] == nil then ---@diagnostic disable-next-line: assign-type-mismatch       M[var] = v.fn()     end     return M[var]@@ -109,6 +109,7 @@ M.expect.equality_partial_tbl = MiniTest.new_expectation(  -- Monkey-patch `MiniTest.new_child_neovim` with helpful wrappers M.new_child_neovim = function()+  ---@class fzf-lua.test.chlid: MiniTest.child   local child = MiniTest.new_child_neovim()    local prevent_hanging = function(method)

lua/fzf-lua/types.lua

@@ -12,63 +12,21 @@ _G.FzfLua = require("fzf-lua") ---@field highlight_matches function? ---@field win fzf-lua.Win ----@class fzf-lua.previewer.Fzf----@field new function----@field setup_opts function----@field zero function?----@field cmdline function?----@field fzf_delimiter function?----@field preview_window function?----@field _preview_offset function?-----@class fzf-lua.previewer.Builtin----@field type "builtin"----@field new function----@field setup_opts function----@field opts table----@field win fzf-lua.Win----@field delay integer----@field title any----@field title_pos "center"|"left"|"right"----@field title_fnamemodify fun(title: string, width: integer?): string----@field render_markdown table?----@field snacks_image table?----@field winopts table?----@field syntax boolean----@field syntax_delay integer----@field syntax_limit_b integer----@field syntax_limit_l integer----@field limit_b integer----@field _ts_limit_b_per_line integer----@field treesitter table----@field toggle_behavior "default"|"extend"----@field winopts_orig table----@field winblend integer----@field extensions { [string]: string[]? }----@field ueberzug_scaler "crop"|"distort"|"contain"|"fit_contain"|"cover"|"forced_cover"----@field cached_bufnrs { [string]: fzf-lua.previewer.CursorPos? }----@field cached_buffers { [string]: fzf-lua.buffer_or_file.Bcache? }----@field listed_buffers { [string]: boolean? }----@field clear_on_redraw boolean?--------@field orig_pos fzf-lua.previewer.CursorPos----@alias fzf-lua.previewer.CursorPos (true|[integer, integer])- ---@class fzf-lua.previewer.BufferOrFile----@field match_id integer?+---@field match_id? integer  ---@class fzf-lua.path.Entry----@field stripped string----@field bufnr integer?----@field bufname string?----@field terminal boolean?----@field path string?----@field line integer----@field col integer----@field ctag string?----@field uri string?----@field range { start: { line: integer, col: integer } }?----@field debug string? debug information+---@field stripped? string+---@field bufnr? integer+---@field line? integer+---@field col? integer+---@field bufname? string+---@field terminal? boolean+---@field path? string+---@field ctag? string+---@field uri? string+---@field range? lsp.Range+---@field debug? string debug information  ---@class fzf-lua.buffer_or_file.Entry : fzf-lua.path.Entry, {} ---@field do_not_cache boolean?@@ -88,43 +46,44 @@ _G.FzfLua = require("fzf-lua") ---@field key string?  ---@class fzf-lua.buffer_or_file.Bcache----@field bufnr integer----@field min_winopts boolean?----@field invalid boolean? buffer content changed----@field invalid_pos boolean? position changed----@field tick integer?+---@field bufnr? integer+---@field min_winopts? boolean+---@field invalid? boolean buffer content changed+---@field invalid_pos? boolean position changed+---@field tick? integer  ---@alias fzf-lua.config.Action fzf-lua.ActionSpec|fzf-lua.shell.data2|fzf-lua.shell.data2[]|false----@alias fzf-lua.config.Actions { [1]: fzf-lua, [string]: fzf-lua.config.Action }+---@alias fzf-lua.config.Actions { [1]?: boolean, [string]: fzf-lua.config.Action }  ---@class fzf-lua.ActionSpec ---@field [1] fzf-lua.shell.data2?----@field fn fzf-lua.shell.data2?----@field exec_silent boolean?----@field reload boolean----@field field_index string?----@field desc string?----@field prefix string?----@field postfix string?----@field reuse boolean?----@field noclose boolean?----@field _ignore boolean?+---@field fn? fzf-lua.shell.data2?+---@field exec_silent? boolean+---@field reload? boolean+---@field field_index? string+---@field desc? string+---@field prefix? string+---@field postfix? string+---@field reuse? boolean+---@field noclose? boolean+---@field _ignore? boolean  ---@alias fzf-lua.profile "border-fused"|"borderless-full"|"borderless"|"cli"|"default-prompt"|"default-title"|"default"|"fzf-native"|"fzf-tmux"|"fzf-vim"|"hide"|"ivy"|"max-perf"|"skim"|"telescope"  ---@class fzf-lua.Config: fzf-lua.config.Defaults,{} ---@field [1]? fzf-lua.profile|fzf-lua.profile[]+---@field [2]? boolean|integer ---@field defaults fzf-lua.config.Defaults|{}  ---@class fzf-lua.config.Defaults: fzf-lua.config.Base,{} ---@field nbsp string----@field winopts fzf-lua.config.Winopts|{}----@field keymap fzf-lua.config.Keymap|{}----@field actions table<string, fzf-lua.config.Actions>|{}+---@field winopts fzf-lua.config.Winopts+---@field keymap fzf-lua.config.Keymap+---@field actions table<string, fzf-lua.config.Actions> ---@field fzf_bin string? ---@field fzf_opts table<string, any> ---@field fzf_tmux_opts table<string, any>----@field previewers table<string, fzf-lua.config.Previewer|{}>+---@field previewers fzf-lua.config.Previewers ---@field formatters table<string, any> ---@field files fzf-lua.config.Files ---@field global fzf-lua.config.Global@@ -181,32 +140,11 @@ _G.FzfLua = require("fzf-lua") ---@field __HLS fzf-lua.config.HLS ---@field [string] any ----@class fzf-lua.config.Winopts----@field height number----@field width number----@field row number----@field col number----@field border any----@field zindex integer----@field relative string----@field hide boolean----@field split string|function|false----@field backdrop number|boolean----@field fullscreen boolean----@field title any----@field title_pos "center"|"left"|"right"----@field treesitter fzf-lua.config.TreesitterWinopts----@field preview fzf-lua.config.PreviewWinopts----@field on_create fun(e: { winid: integer, bufnr: integer })----@field on_close fun()----@field toggle_behavior string?----@field __winhls { main: [string, string][], prev: [string, string][] }- ---@class fzf-lua.config.TreesitterWinopts ---@field enabled boolean ---@field fzf_colors? table<string, string> ----@class fzf-lua.config.PreviewWinopts+---@class fzf-lua.config.PreviewOpts ---@field default? string ---@field border? any ---@field wrap? boolean@@ -233,46 +171,67 @@ _G.FzfLua = require("fzf-lua") ---@field foldenable? boolean ---@field foldmethod? string ---@field scrolloff? integer+---@field winblend? integer  ---@class fzf-lua.config.Keymap ---@field builtin? table<string, string> ---@field fzf? table<string, string> ----@class fzf-lua.config.Previewer----@field cmd? string|fun():string----@field args? string----@field _ctor? fun(...)----@field pager? fun(...)----@field cmd_deleted? string----@field cmd_modified? string----@field cmd_untracked? string----@field _fn_git_icons? fun():any----@field syntax? boolean----@field syntax_delay? integer----@field syntax_limit_l? integer----@field syntax_limit_b? integer----@field limit_b? integer----@field treesitter? table----@field ueberzug_scaler? string----@field title_fnamemodify? fun(s:string):string----@field render_markdown? table----@field snacks_image? table----@field diff_opts? table+---@class fzf-lua.SpawnStdioOpts+---@field debug? boolean+---@field profiler? boolean+---@field process1? boolean+---@field silent? boolean|integer+---@field cmd? string|string[]+---@field cwd? string+---@field cwd_only? boolean+---@field stdout? boolean+---@field stderr? boolean+---@field stderr_to_stdout? boolean+---@field formatter? fun(line:string):string|nil+---@field multiline? boolean+---@field git_dir? string+---@field git_worktree? string+---@field git_icons? boolean+---@field file_icons? boolean+---@field color_icons? boolean+---@field path_shorten? boolean+---@field absolute_path? boolean+---@field strip_cwd_prefix? boolean+---@field render_crlf? boolean+---@field exec_empty_query? boolean+---@field file_ignore_patterns? string[]+---@field rg_glob? boolean+---@field fn_transform? string|fun(line:string, opts: fzf-lua.SpawnStdioOpts):string|nil+---@field fn_preprocess? string|fun(opts: fzf-lua.SpawnStdioOpts):string[]|nil+---@field fn_postprocess? string|fun(opts: fzf-lua.SpawnStdioOpts):string[]|nil+---@field is_live? boolean+---@field contents? fzf-lua.content|fzf-lua.shell.data2+---@field __FZF_VERSION? string+---@field glob_flag? string+---@field glob_separator? string+---@field g? fzf-lua.SpawnStdioOpts.g+---@field no_ansi_colors? boolean++---@class fzf-lua.SpawnStdioOpts.g+---@field _fzf_lua_server? string+---@field _EOL? string+---@field _debug? boolean  ---a basic config can be used by fzf_exec? ---generated from the result of `:=FzfLua.config.normalize_opts({}, {})` ---@class fzf-lua.config.Base ---@field cwd_prompt? boolean ---@field dir_icon? string----@field enrich? function+---@field enrich? fun(opts: fzf-lua.config.Resolved):fzf-lua.config.Resolved|{} ---@field fzf_bin? string----@field fzf_colors? table<string, string>+---@field fzf_colors? { [1]?: boolean, [string]: string? } ---@field fzf_opts? table<string, any> ---@field fzf_tmux_opts? table<string, any>----@field hls? table<string, any>----@field winopts? fzf-lua.config.Winopts|(fun(opts: fzf-lua.Config):fzf-lua.config.Winopts)|{}----@field keymap? fzf-lua.config.Keymap|(fun(opts: fzf-lua.Config):fzf-lua.config.Keymap)|{}----@field actions? fzf-lua.config.Actions|(fun(opts: fzf-lua.Config):fzf-lua.config.Actions)|{}+---@field hls? fzf-lua.config.HLS+---@field winopts? fzf-lua.config.Winopts|(fun(opts: fzf-lua.Config):fzf-lua.config.Winopts)+---@field keymap? fzf-lua.config.Keymap|(fun(opts: fzf-lua.Config):fzf-lua.config.Keymap)+---@field actions? fzf-lua.config.Actions|(fun(opts: fzf-lua.Config):fzf-lua.config.Actions) ---@field no_header? boolean ---@field no_header_i? boolean ---@field prompt? string@@ -284,10 +243,10 @@ _G.FzfLua = require("fzf-lua") ---@field file_icons? boolean|integer ---@field color_icons? boolean ---@field git_icons? boolean----@field silent? boolean+---@field silent? boolean|integer ---@field previewer? fun(...)|table|string ---@field preview? string|function|table----@field complete? (fun(_, _, _ ,_):_, _)|boolean+---@field complete? (fun(s: string[], _o: fzf-lua.config.Resolved, l: string, c: integer):string?, integer?)|boolean ---@field header string ---@field query? string ---@field resume? boolean@@ -300,39 +259,60 @@ _G.FzfLua = require("fzf-lua") ---@field cwd_prompt_shorten_val integer? ---@field header_prefix? string ---@field header_separator? string----@field fn_selected string+---@field fn_selected function ---@field cb_co fun(co: thread) ---@field cwd_only boolean ---@field cmd? string ---@field debug? boolean|'v'|'verbose'+---@field preview_offset? string ---@field _fzf_cli_args? string[] ---@field __INFO? fzf-lua.Info----@field __CTX? fzf-lua.Ctx+---@field __CTX? fzf-lua.Ctx|{} ---@field _normalized? boolean ---@field __call_fn? function ---@field __call_opts? table ---@field is_live? boolean is "live" picker ---@field contents? fzf-lua.content|fzf-lua.shell.data2----@field _actions? fun():fzf-lua.config.Actions+---@field _actions? fun():fzf-lua.config.Actions? ---@field __ACT_TO? function ---@field _start? boolean ---@field _is_skim? boolean----@field _treesitter (fun(line:string):string,string?,string?,string?)|boolean?+---@field _treesitter? (fun(line: string):string?,string?,string?,string?)|boolean?+---@field help_open_win? fun(buf: integer, enter: boolean, config: vim.api.keyset.win_config): integer+---@field autoclose? boolean+---@field line_field_index? string+---@field field_index_expr? string+---@field _ctag? string+---@field preview_pager? string  ---@class fzf-lua.config.Resolved: fzf-lua.config.Base ---@field PidObject? table ---@field _headers? string[]----@field _fmt table+---@field _fmt? table ---@field pipe_cmd? string ---@field RIPGREP_CONFIG_PATH? string ---@field _ctx? fzf-lua.Ctx ---@field __FZF_VERSION? number[] ---@field __resume_key? function|string ---@field _cwd? string----@field _type "file"?+---@field _type? "file"? ---@field _cached_hls? string[] ---@field _multiline? boolean ---@field __resume_set? function ---@field __resume_get? function ---@field _contents? string ---@field _is_fzf_tmux? boolean+---@field _is_skim? boolean+---@field __stringified? boolean+---@field __stringify_cmd? boolean+---@field __sigwinches? string[]+---@field __sigwinch_on_scope table<string, function>+---@field __sigwinch_on_any function[]+---+---@field process1? boolean+---@field profiler? boolean+---@field use_queue? boolean+---@field throttle? boolean+---@field env? boolean+---@field winopts? fzf-lua.config.Winopts+---@field _resume_reload? boolean

lua/fzf-lua/utils.lua

@@ -6,6 +6,7 @@ function _G.dump(...)   print(unpack(objects)) end +---@diagnostic disable-next-line: deprecated local uv = vim.uv or vim.loop local memoize = vim.func and vim.func._memoize @@ -68,7 +69,7 @@ if _VERSION and type(_VERSION) == "string" then   if ver < 5.2 then     M.nbsp = M.nbsp:gsub("\\x(%x%x)",       function(x)-        return string.char(tonumber(x, 16))+        return string.char(assert(tonumber(x, 16)))       end)   end end@@ -138,7 +139,7 @@ M._notify_header = "LineNr"  --- Fancy notification wrapper, idea borrowed from blink.nvim --- @param lvl? number---- @param ... string|number|[string, string?][]+--- @param ... any function M.notify(lvl, ...)   -- Message can be specified directly as table with highlights, i.e. { "foo", "Error" }   -- or as a vararg of strings/numbers to be sent to string.format@@ -210,7 +211,6 @@ end ---@param str string ---@return string function M.rg_escape(str)-  if not str then return str end   -- [(~'"\/$?'`*&&||;[]<>)]   -- escape "\~$?*|[()^-."   local ret = str:gsub("[\\~$?*|{\\[()^%-%.%+]", function(x)@@ -242,17 +242,15 @@ function M.sk_escape(str) end  function M.lua_escape(str)-  if not str then return str end-  return str:gsub("[%%]", function(x)-    return "%" .. x-  end)+  return (str:gsub("%%", "%%%%")) end  ---@see vim.pesc+---@param str string+---@return string function M.lua_regex_escape(str)   -- escape all lua special chars   -- ( ) % . + - * [ ? ^ $-  if not str then return nil end   -- gsub returns a tuple, return the string only or unexpected happens (#1257)   return (str:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%1")) end@@ -359,14 +357,18 @@ M.read_file_async = function(filepath, callback)       end)       return     end+    ---@cast fd -?     uv.fs_fstat(fd, function(err_fstat, stat)       assert(not err_fstat and stat, err_fstat)-      if stat.type ~= "file" then return callback("") end+      if stat.type ~= "file" then+        callback("")+        return+      end       uv.fs_read(fd, stat.size, 0, function(err_read, data)         assert(not err_read, err_read)         uv.fs_close(fd, function(err_close)           assert(not err_close, err_close)-          return callback(data)+          callback(data)         end)       end)     end)@@ -376,9 +378,9 @@ end -- deepcopy can fail with: "Cannot deepcopy object of type userdata" (#353) -- this can happen when copying items/on_choice params of vim.ui.select -- run in a pcall and fallback to our poor man's clone----@generic T: table----@param t T?----@return T?+---@generic T+---@param t T+---@return T function M.deepcopy(t)   local ok, res = pcall(vim.deepcopy, t)   if ok then@@ -388,19 +390,15 @@ function M.deepcopy(t)   end end ----@generic T: table----@param t T?----@return T?+---@generic T+---@param t T+---@return T function M.tbl_deep_clone(t)-  if not t then return end+  if type(t) ~= "table" then return t end   local clone = {}    for k, v in pairs(t) do-    if type(v) == "table" then-      clone[k] = M.tbl_deep_clone(v)-    else-      clone[k] = v-    end+    clone[k] = M.tbl_deep_clone(v)   end    return clone@@ -410,12 +408,13 @@ end -- Recursively merge two or more tables by extending -- the first table and returning its original pointer ---@param behavior "keep"|"force"|"error"+---@param tbl table<any,any> ---@param ... table<any,any> ---@return table-function M.tbl_deep_extend(behavior, ...)+function M.tbl_deep_extend(behavior, tbl, ...)   local tbls = { ... }-  local ret = tbls[1]-  for i = 2, #tbls do+  local ret = tbl+  for i = 1, #tbls do     local t = tbls[i]     for k, v in pairs(t) do       ret[k] = (function()@@ -575,9 +574,9 @@ end --     ["a.a1"] = ..., --     ["a.a2"] = ..., --   }----@param m table<string, unknown>?----@param prefix string?----@return table<string, unknown>?+---@param m table Table to flatten+---@param prefix string? Optional prefix for keys+---@return table Flattened table function M.map_flatten(m, prefix)   if M.tbl_isempty(m) then return {} end   local ret = {}@@ -871,11 +870,12 @@ function M.get_visual_selection()   if cerow < csrow then csrow, cerow = cerow, csrow end   if cecol < cscol then cscol, cecol = cecol, cscol end   local lines = vim.fn.getline(csrow, cerow)+  ---@cast lines -string   -- local n = cerow-csrow+1   local n = #lines   if n <= 0 then return "" end-  lines[n] = string.sub(lines[n], 1, cecol)-  lines[1] = string.sub(lines[1], cscol)+  lines[n] = string.sub(assert(lines[n]), 1, cecol)+  lines[1] = string.sub(assert(lines[1]), cscol)   return table.concat(lines, "\n"), {     start   = { line = csrow, char = cscol },     ["end"] = { line = cerow, char = cecol },@@ -896,7 +896,7 @@ function M.fzf_winobj() end  ---@param opts? { includeBuflist?: boolean, buf?: integer|string, bufnr?: integer|string }----@return fzf-lua.Ctx+---@return fzf-lua.Ctx|{} function M.CTX(opts)   return require("fzf-lua.ctx").refresh(opts) end@@ -948,6 +948,7 @@ function M.load_profile_fname(fname, name, silent)     end     return res   end+  ---@cast res -table   -- If called from `setup` we set `silent=1` so we can alert the user on   -- errors loading the requested profiles   if silent ~= true and not ok then@@ -958,7 +959,7 @@ function M.load_profile_fname(fname, name, silent) end  ---@param profiles table|string----@param silent boolean|integer+---@param silent? boolean|integer ---@return table function M.load_profiles(profiles, silent)   local ret = {}@@ -1007,8 +1008,9 @@ function M.is_term_bufname(bufname)   return false end +---@param bufnr integer+---@return boolean function M.is_term_buffer(bufnr)-  bufnr = tonumber(bufnr) or 0   -- convert bufnr=0 to current buf so we can call 'bufwinid'   bufnr = bufnr == 0 and vim.api.nvim_get_current_buf() or bufnr   local winid = vim.fn.bufwinid(bufnr)@@ -1019,8 +1021,12 @@ function M.is_term_buffer(bufnr)   return M.is_term_bufname(bufname) end +---@param bufnr integer+---@param warn? boolean+---@param only_if_last_buffer? boolean+---@return boolean function M.buffer_is_dirty(bufnr, warn, only_if_last_buffer)-  bufnr = tonumber(bufnr) or vim.api.nvim_get_current_buf()+  bufnr = bufnr or vim.api.nvim_get_current_buf()   local info = bufnr and M.getbufinfo(bufnr)   if info and info.changed ~= 0 then     if only_if_last_buffer and 1 < #vim.fn.win_findbuf(bufnr) then@@ -1061,7 +1067,7 @@ end --   1 for qf list --   2 for loc list ---@param winid integer----@param wininfo table?+---@param wininfo (vim.fn.getwininfo.ret.item|vim.fn.getwininfo.ret.item[]|false|table)? ---@return 1|2|false function M.win_is_qf(winid, wininfo)   wininfo = wininfo or (vim.api.nvim_win_is_valid(winid) and M.getwininfo(winid))@@ -1072,14 +1078,16 @@ function M.win_is_qf(winid, wininfo) end  ---@param bufnr integer----@param bufinfo table?+---@param bufinfo (vim.fn.getwininfo.ret.item|vim.fn.getwininfo.ret.item[]|false|table)? ---@return 1|2|false function M.buf_is_qf(bufnr, bufinfo)   bufinfo = bufinfo or (vim.api.nvim_buf_is_valid(bufnr) and M.getbufinfo(bufnr))   if bufinfo and bufinfo.variables and       bufinfo.variables.current_syntax == "qf" and       not M.tbl_isempty(bufinfo.windows) then-    return M.win_is_qf(bufinfo.windows[1])+    local window = bufinfo.windows[1]+    ---@cast window integer+    return M.win_is_qf(window)   end   return false end@@ -1145,7 +1153,7 @@ end  local function _zz()   -- skip for terminal buffers-  if M.is_term_buffer() then return end+  if M.is_term_buffer(0) then return end   local lnum1 = vim.api.nvim_win_get_cursor(0)[1]   local lcount = vim.api.nvim_buf_line_count(0)   local zb = "keepj norm! %dzb"@@ -1203,7 +1211,7 @@ end  function M.nvim_open_win0(bufnr, enter, config)   local winid = M.CTX().winid-  if not vim.api.nvim_win_is_valid(winid) then+  if not winid or not vim.api.nvim_win_is_valid(winid) then     return vim.api.nvim_open_win(bufnr, enter, config)   end   return vim.api.nvim_win_call(winid, function()@@ -1255,21 +1263,23 @@ function M.upvfind(func, upval_name)   return nil end +---@param bufnr? integer+---@return vim.fn.getbufinfo.ret.item function M.getbufinfo(bufnr)   if M.__HAS_AUTOLOAD_FNS then     return vim.fn["fzf_lua#getbufinfo"](bufnr)   else-    local info = vim.fn.getbufinfo(bufnr)-    return info[1] or info+    return vim.fn.getbufinfo(bufnr)[1] or {}   end end +---@param winid? integer+---@return vim.fn.getwininfo.ret.item? function M.getwininfo(winid)   if M.__HAS_AUTOLOAD_FNS then     return vim.fn["fzf_lua#getwininfo"](winid)   else-    local info = vim.fn.getwininfo(winid)-    return info[1] or info+    return vim.fn.getwininfo(winid)[1]   end end @@ -1358,8 +1368,8 @@ function M.parse_verstr(str)   if type(str) ~= "string" then return end   local major, minor, patch = str:match("(%d+).(%d+)%.?(.*)")   -- Fzf on HEAD edge case-  major = tonumber(major) or str:match("HEAD") and 100 or nil-  return major and { major, tonumber(minor) or 0, tonumber(patch) or 0 } or nil+  local major0 = tonumber(major) or str:match("HEAD") and 100 or nil+  return major0 and { major0, tonumber(minor) or 0, tonumber(patch) or 0 } or nil end  function M.ver2str(v)@@ -1424,7 +1434,7 @@ end  function M.find_version()   local out, rc = M.io_systemlist({ "find", "--version" })-  return rc == 0 and tonumber(out[1]:match("(%d+.%d+)")) or nil+  return rc == 0 and out[1] and tonumber(out[1]:match("(%d+.%d+)")) or nil end  ---@return string@@ -1481,13 +1491,16 @@ function M.setmetatable(t, mt)   return setmetatable(t, mt) end +---always ensure chan is closed on error ---@param addr string ---@param method string----@param ...? any----@return boolean, ...+---@param ... any+---@return boolean, string|any, ...any function M.rpcexec(addr, method, ...)+  ---@type boolean, any   local ok, chan = pcall(vim.fn.sockconnect, "pipe", addr, { rpc = true })-  if not ok or chan == 0 then return ok end+  if not ok or chan == 0 then return false, "Invalid channel" end+  ---@cast chan integer   local ret = { pcall(vim.rpcrequest, chan, method, ...) }   vim.fn.chanclose(chan)   return unpack(ret)@@ -1629,7 +1642,7 @@ local function new_win_opt_accessor(winid)     end,   }) end----@type {}|vim.wo+---@class fzf-lua.wo: vim.wo,{} M.wo = new_win_opt_accessor()  

lua/fzf-lua/win.lua

@@ -7,18 +7,27 @@ local actions = require "fzf-lua.actions" local api = vim.api local fn = vim.fn +---@class fzf-lua.TSInjector+---@field cache table<integer, table<string, fzf-lua.TSInjectorLangEntry>>+---@field _setup boolean?+---@field _ns integer?+---@field _has_on_range boolean? local TSInjector = {} ----@type table<number, table<string,{parser: vim.treesitter.LanguageTree, highlighter:vim.treesitter.highlighter, enabled:boolean}>>+---@class fzf-lua.TSInjectorLangEntry+---@field parser vim.treesitter.LanguageTree+---@field highlighter vim.treesitter.highlighter+---@field enabled? boolean+ TSInjector.cache = {}  function TSInjector.setup()   if TSInjector._setup then return true end    TSInjector._setup = true-  TSInjector._ns = TSInjector._ns or vim.api.nvim_create_namespace("fzf-lua.win.highlighter")+  TSInjector._ns = TSInjector._ns or api.nvim_create_namespace("fzf-lua.win.highlighter")   TSInjector._has_on_range = TSInjector._has_on_range == nil-      and pcall(vim.api.nvim_set_decoration_provider, TSInjector._ns, { on_range = function() end })+      and pcall(api.nvim_set_decoration_provider, TSInjector._ns, { on_range = function() end })       or TSInjector._has_on_range    local function wrap_ts_hl_callback(name)@@ -39,7 +48,7 @@ function TSInjector.setup()     end   end -  vim.api.nvim_set_decoration_provider(TSInjector._ns, {+  api.nvim_set_decoration_provider(TSInjector._ns, {     on_win = wrap_ts_hl_callback("_on_win"),     on_start = wrap_ts_hl_callback("_on_start"),     on_line = wrap_ts_hl_callback("_on_line"),@@ -51,7 +60,7 @@ end  function TSInjector.deregister()   if not TSInjector._ns then return end-  vim.api.nvim_set_decoration_provider(TSInjector._ns,+  api.nvim_set_decoration_provider(TSInjector._ns,     { on_win = nil, on_line = nil, on_range = nil })   TSInjector._setup = nil end@@ -82,13 +91,13 @@ function TSInjector.attach(buf, regions) end  ---@param buf integer----@param lang? string----@param regions table<string, TSRegion>+---@param lang string+---@param regions TSRegion function TSInjector._attach_lang(buf, lang, regions)-  if not lang then return end   if not TSInjector.cache[buf][lang] then     local ok, parser = pcall(vim.treesitter.languagetree.new, buf, lang)-    if not ok then return end+    if not ok then return end ---@cast parser -string+    ---@type fzf-lua.TSInjectorLangEntry     TSInjector.cache[buf][lang] = {       parser = parser,       highlighter = vim.treesitter.highlighter.new(parser),@@ -99,20 +108,56 @@ function TSInjector._attach_lang(buf, lang, regions)   if not parser then return end    TSInjector.cache[buf][lang].enabled = true-  ---@diagnostic disable-next-line: invisible+  ---@diagnostic disable-next-line: invisible, access-invisible   parser:set_included_regions(regions) end  ---@alias fzf-lua.win.previewPos "up"|"down"|"left"|"right" ---@alias fzf-lua.win.previewLayout { pos: fzf-lua.win.previewPos, size: number, str: string } +---@class fzf-lua.config.WinoptsResolved: fzf-lua.config.Winopts+---@field height integer+---@field width integer+---@field row integer+---@field col integer+---@field __winhls { main: [string, string][], prev: [string, string][] }++---@class fzf-lua.config.Winopts: vim.api.keyset.win_config+---@field height? number+---@field width? number+---@field row? number+---@field col? number+---@field preview? fzf-lua.config.PreviewOpts+---@field split? string|function|false+---@field backdrop? number|boolean+---@field fullscreen? boolean+---@field treesitter? fzf-lua.config.TreesitterWinopts+---@field on_create? fun(e: { winid?: integer, bufnr?: integer })+---@field on_close? fun()+---@field toggle_behavior? string+---@field winblend? boolean+---@field winhl? boolean+---@field cursorline? boolean+---@field __winhls? { main: [string, string?][], prev: [string, string?][] }+ ---@class fzf-lua.Win----@field winopts fzf-lua.config.Winopts|{}----@field km_winid integer?----@field km_bufnr integer?----@field _previewer fzf-lua.previewer.Builtin|fzf-lua.previewer.Fzf?----@field _preview_pos_force fzf-lua.win.previewPos----@field _last_view [integer, integer, integer]?+---@field winopts fzf-lua.config.Winopts+---@field actions fzf-lua.config.Actions|{}+---@field layout fzf-lua.WinLayout+---@field preview_hidden? boolean+---@field preview_wrap? boolean+---@field km_winid? integer+---@field km_bufnr? integer+---@field fullscreen? boolean+---@field hls? fzf-lua.config.HLS+---@field previewer? fun(...)|table|string+---@field fzf_bufnr? integer+---@field _hidden_fzf_bufnr? integer+---@field toggle_behavior? "extend"|"default"+---@field _previewer? fzf-lua.previewer.Builtin|fzf-lua.previewer.Fzf?+---@field _preview_pos_force? fzf-lua.win.previewPos+---@field _last_view? [integer, integer, integer]?+---@field _o fzf-lua.config.Resolved local FzfWin = {}  -- singleton instance used in win_leave@@ -239,9 +284,8 @@ function FzfWin:normalize_preview_layout()   local preview_str, pos ---@type string, fzf-lua.win.previewPos   if self._preview_pos_force then     -- Get the correct layout string and size when set from `:toggle_preview_cw`-    preview_str = (self._preview_pos_force == "up" or self._preview_pos_force == "down")-        and self.winopts.preview.vertical or self.winopts.preview.horizontal-    assert(preview_str)+    preview_str = assert((self._preview_pos_force == "up" or self._preview_pos_force == "down")+      and self.winopts.preview.vertical or self.winopts.preview.horizontal)     pos = self._preview_pos_force   else     preview_str = self:fzf_preview_layout_str()@@ -273,44 +317,52 @@ function FzfWin:normalize_layout()   return nwin, true end -function FzfWin:generate_layout()-  self:normalize_winopts()-  local winopts = self.winopts+---@class fzf-lua.WinLayout+---@field fzf vim.api.keyset.win_config+---@field preview? vim.api.keyset.win_config +function FzfWin:generate_layout()+  local winopts = self:normalize_winopts()   local nwin, preview = self:normalize_layout()   local layout = self:normalize_preview_layout()-  local border, h, w = self:normalize_border(self._o.winopts.border,-    { type = "nvim", name = "fzf", layout = preview and layout.pos, nwin = nwin, opts = self._o })+  local border, h, w = self:normalize_border(self._o.winopts.border, {+    type = "nvim",+    name = "fzf",+    layout = preview and layout.pos or nil,+    nwin = nwin,+    opts = self._o+  })   if not preview then     self.layout = {       fzf = {-        row = self.winopts.row,-        col = self.winopts.col,-        width = self.winopts.width,-        height = self.winopts.height,+        row = winopts.row,+        col = winopts.col,+        width = winopts.width,+        height = winopts.height,         border = border,         style = "minimal",-        relative = self.winopts.relative or "editor",-        zindex = self.winopts.zindex,-        hide = self.winopts.hide,+        relative = winopts.relative or "editor",+        zindex = winopts.zindex,+        hide = winopts.hide,       }     }     return   end -  if self.previewer_is_builtin and self.winopts.split then-    local wininfo = utils.getwininfo(self.fzf_winid)+  if self.previewer_is_builtin and winopts.split then+    local wininfo = assert(utils.getwininfo(self.fzf_winid))     -- no signcolumn/number/relativenumber (in set_style_minimal)+    ---@diagnostic disable-next-line: missing-fields     winopts = {       height = wininfo.height,       width = wininfo.width,-      split = self.winopts.split,+      split = winopts.split,     }   end    local pwopts   local row, col = winopts.row, winopts.col-  local height, width = winopts.height, winopts.width+  local height, width = winopts.height, winopts.width ---@type integer, integer   local preview_pos, preview_size = layout.pos, layout.size   local pborder, ph, pw = self:normalize_border(self._o.winopts.preview.border,     { type = "nvim", name = "prev", layout = preview and layout.pos, nwin = nwin, opts = self._o })@@ -382,16 +434,16 @@ function FzfWin:generate_layout()     fzf = vim.tbl_extend("force", { row = row, col = col, height = height, width = width }, {       style = "minimal",       border = border,-      relative = self.winopts.relative or "editor",-      zindex = self.winopts.zindex,-      hide = self.winopts.hide,+      relative = winopts.relative or "editor",+      zindex = winopts.zindex,+      hide = winopts.hide,     }),     preview = vim.tbl_extend("force", pwopts, {       style = "minimal",-      zindex = self.winopts.zindex,+      zindex = winopts.zindex,       border = pborder,       focusable = true,-      hide = self.winopts.hide,+      hide = winopts.hide,     }),   } end@@ -433,29 +485,35 @@ function FzfWin:tmux_columns() end  function FzfWin:columns(no_fullscreen)-  assert(self.winopts)   -- When called from `core.preview_window` we need to get the no-fullscreen columns   -- in order to get an accurate alternate layout trigger that will also be consistent   -- when starting with `winopts.fullscreen == true`   local winopts = no_fullscreen and self._o.winopts or self.winopts   return self._o._is_fzf_tmux and self:tmux_columns()       or vim.is_callable(_G.fzf_tty_get_width) and _G.fzf_tty_get_width()-      or winopts.split and vim.api.nvim_win_get_width(self.fzf_winid or 0)+      or winopts.split and api.nvim_win_get_width(self.fzf_winid or 0)       or self:normalize_size(winopts.width, vim.o.columns) end  function FzfWin:fzf_preview_layout_str()-  assert(self.winopts)   local columns = self:columns()   local is_hsplit = self.winopts.preview.layout == "horizontal"       or self.winopts.preview.layout == "flex" and columns > self.winopts.preview.flip_columns   return is_hsplit and self._o.winopts.preview.horizontal or self._o.winopts.preview.vertical end ----@alias fzf-lua.win.borderMetadata { type: "nvim"|"fzf", name: "fzf"|"prev", nwin: integer, layout: fzf-lua.win.previewPos }+---@class fzf-lua.win.borderMetadata+---@field type? 'nvim'|'fzf'+---@field name? 'fzf'|'prev'+---@field nwin? integer+---@field layout? fzf-lua.win.previewPos+---@field opts? fzf-lua.config.Resolved++---@alias fzf-lua.winborder string[]|"none"|"single"|"double"|"rounded"|"solid"|"shadow"+ ---@param border any ---@param metadata fzf-lua.win.borderMetadata----@return string|table, integer, integer+---@return fzf-lua.winborder, integer, integer function FzfWin:normalize_border(border, metadata)   if type(border) == "function" then     border = border(self, metadata)@@ -527,22 +585,25 @@ function FzfWin:normalize_border(border, metadata)   else     up, down, left, right = 1, 1, 1, 1   end+  ---@diagnostic disable-next-line: return-type-mismatch   return border, up + down, left + right end ----@param size number+---@param size number|integer ---@param max integer ---@return integer function FzfWin:normalize_size(size, max)   local _ = self-  return size <= 1 and math.floor(max * size) or math.min(size, max)+  if size <= 1 then return math.floor(max * size) end+  ---@cast size integer+  return math.min(size, max) end ----@return fzf-lua.config.Winopts|{}+---@return fzf-lua.config.WinoptsResolved function FzfWin:normalize_winopts()   -- make a local copy of winopts so we don't pollute the user's options-  local winopts = utils.tbl_deep_clone(self._o.winopts) or {}-  self.winopts = winopts+  self.winopts = utils.tbl_deep_clone(self._o.winopts or {}) or {}+  local winopts = self.winopts    if self.fullscreen then     -- NOTE: we set `winopts.relative=editor` so fullscreen@@ -590,28 +651,29 @@ function FzfWin:normalize_winopts()   local ch = winopts.zindex >= 200 and 0 or vim.o.cmdheight   local max_width = vim.o.columns   local max_height = vim.o.lines - ch-  winopts.width = self:normalize_size(tonumber(winopts.width), max_width)-  winopts.height = self:normalize_size(tonumber(winopts.height), max_height)+  winopts.width = self:normalize_size(assert(tonumber(winopts.width)), max_width)+  winopts.height = self:normalize_size(assert(tonumber(winopts.height)), max_height)   if winopts.relative == "cursor" then     -- convert cursor relative to absolute ('editor'),     -- this solves the preview positioning seamlessly     -- use the calling window context for correct pos-    local winid = utils.CTX().winid-    local pos = vim.api.nvim_win_get_cursor(winid)-    local screenpos = vim.fn.screenpos(winid, pos[1], pos[2])+    local winid = assert(utils.CTX().winid)+    local pos = api.nvim_win_get_cursor(winid)+    local screenpos = fn.screenpos(winid, pos[1], pos[2])     winopts.row = math.floor((winopts.row or 0) + screenpos.row - 1)     winopts.col = math.floor((winopts.col or 0) + screenpos.col - 1)     winopts.relative = nil   else     -- make row close to the center of screen (include cmdheight)     -- avoid breaking existing test-    winopts.row = self:normalize_size(tonumber(winopts.row), vim.o.lines - winopts.height)-    winopts.col = self:normalize_size(tonumber(winopts.col), max_width - winopts.width)+    winopts.row = self:normalize_size(assert(tonumber(winopts.row)), vim.o.lines - winopts.height)+    winopts.col = self:normalize_size(assert(tonumber(winopts.col)), max_width - winopts.width)     winopts.row = math.min(winopts.row, max_height - winopts.height)   end   -- width/height can be used for text area   winopts.width = math.max(1, winopts.width - w)   winopts.height = math.max(1, winopts.height - h)+  ---@type fzf-lua.config.WinoptsResolved   return winopts end @@ -625,7 +687,7 @@ function FzfWin:reset_win_highlights(win)     hl = self._previewer:gen_winopts().winhl   end   if not hl then-    for _, h in ipairs(self.winopts.__winhls[key]) do+    for _, h in ipairs(assert(self.winopts.__winhls)[key]) do       if h[2] then         hl = string.format("%s%s:%s", hl and hl .. "," or "", h[1], h[2])       end@@ -635,7 +697,7 @@ function FzfWin:reset_win_highlights(win) end  ---@param exit_code integer----@param fzf_bufnr integer+---@param fzf_bufnr integer? function FzfWin:check_exit_status(exit_code, fzf_bufnr)   -- see the comment in `FzfWin:close` for more info   if fzf_bufnr and fzf_bufnr ~= self.fzf_bufnr then@@ -648,7 +710,7 @@ function FzfWin:check_exit_status(exit_code, fzf_bufnr)   --    2      Error   --    130    Interrupted with CTRL-C or ESC   if exit_code == 2 then-    local lines = vim.api.nvim_buf_get_lines(self.fzf_bufnr, 0, 1, false)+    local lines = api.nvim_buf_get_lines(self.fzf_bufnr, 0, 1, false)     utils.error("fzf error %d: %s", exit_code, lines and #lines[1] > 0 and lines[1] or "<null>")   end end@@ -677,8 +739,8 @@ function FzfWin:set_backdrop()   if self.winopts.split then return end   -- Called from redraw?   if self.backdrop_win then-    if vim.api.nvim_win_is_valid(self.backdrop_win) then-      vim.api.nvim_win_set_config(self.backdrop_win, {+    if api.nvim_win_is_valid(self.backdrop_win) then+      api.nvim_win_set_config(self.backdrop_win, {         width = vim.o.columns,         height = vim.o.lines,       })@@ -698,7 +760,7 @@ function FzfWin:set_backdrop()   if #utils.hexcol_from_hl("Normal", "bg") == 0 then return end    -- Code from lazy.nvim (#1344)-  self.backdrop_buf = vim.api.nvim_create_buf(false, true)+  self.backdrop_buf = api.nvim_create_buf(false, true)   self.backdrop_win = utils.nvim_open_win0(self.backdrop_buf, false, {     relative = "editor",     width = vim.o.columns,@@ -714,27 +776,27 @@ function FzfWin:set_backdrop()     -- hide = self.winopts.hide,   })   utils.wo[self.backdrop_win].winhl = "Normal:" .. self.hls.backdrop-  utils.wo[self.backdrop_win].winblend = self.winopts.backdrop+  utils.wo[self.backdrop_win].winblend = utils.tointeger(self.winopts.backdrop)   vim.bo[self.backdrop_buf].buftype = "nofile"   vim.bo[self.backdrop_buf].filetype = "fzflua_backdrop" end  function FzfWin:close_backdrop()   if not self.backdrop_win or not self.backdrop_buf then return end-  if self.backdrop_win and vim.api.nvim_win_is_valid(self.backdrop_win) then-    vim.api.nvim_win_close(self.backdrop_win, true)+  if self.backdrop_win and api.nvim_win_is_valid(self.backdrop_win) then+    api.nvim_win_close(self.backdrop_win, true)   end-  if self.backdrop_buf and vim.api.nvim_buf_is_valid(self.backdrop_buf) then-    vim.api.nvim_buf_delete(self.backdrop_buf, { force = true })+  if self.backdrop_buf and api.nvim_buf_is_valid(self.backdrop_buf) then+    api.nvim_buf_delete(self.backdrop_buf, { force = true })   end   self.backdrop_buf = nil   self.backdrop_win = nil   -- vim.cmd("redraw") end ----@param o fzf-lua.Config+---@param o fzf-lua.config.Resolved ---@return fzf-lua.Win-function FzfWin:new(o)+function FzfWin.new(o)   if not _self then   elseif _self:was_hidden() or _self:hidden() then     _self:close(nil, nil, true) -- do not clear info@@ -744,8 +806,8 @@ function FzfWin:new(o)     _self._reuse = true     -- switch to fzf-lua's main window in case the user switched out     -- NOTE: `self.fzf_winid == nil` when using fzf-tmux-    if _self.fzf_winid and _self.fzf_winid ~= vim.api.nvim_get_current_win() then-      vim.api.nvim_set_current_win(_self.fzf_winid)+    if _self.fzf_winid and _self.fzf_winid ~= api.nvim_get_current_win() then+      api.nvim_set_current_win(_self.fzf_winid)     end     -- Update main win title, required for toggle action flags     _self:update_main_title(o.winopts.title)@@ -757,11 +819,11 @@ function FzfWin:new(o)     _self:attach_previewer(nil)     return _self   end-  o = o or {}+  o = o or {} ---@type fzf-lua.config.Resolved+  ---@type fzf-lua.Win+  local self = utils.setmetatable({}, -- gc is unused now, only used to test _self is nullrified+    { __index = FzfWin, __gc = function() _G._fzf_lua_gc_called = true end })   self._o = o-  -- gc is unused now, only used to test _self is nullrified-  self = utils.setmetatable({},-    { __index = self, __gc = function() _G._fzf_lua_gc_called = true end })   self.hls = o.hls   self.actions = o.actions   self.fullscreen = o.winopts.fullscreen@@ -771,20 +833,23 @@ function FzfWin:new(o)   self.keymap = o.keymap   self.previewer = o.previewer   self:_set_autoclose(o.autoclose)-  self:normalize_winopts()+  self.winopts = self:normalize_winopts()   -- Backward compat since removal of "border" scrollbar   if self.winopts.preview.scrollbar == "border" then+    ---@diagnostic disable-next-line: assign-type-mismatch     self.hls.scrollfloat_f = false+    ---@diagnostic disable-next-line: undefined-field     -- Reverse "FzfLuaScrollBorderFull" color-    if type(self.hls.scrollborder_f) == "string" then-      local fg = utils.hexcol_from_hl(self.hls.scrollborder_f, "fg")-      local bg = utils.hexcol_from_hl(self.hls.scrollborder_f, "bg")+    local scrollborder_f = self.hls.scrollborder_f+    if type(scrollborder_f) == "string" then+      local fg = utils.hexcol_from_hl(scrollborder_f, "fg")+      local bg = utils.hexcol_from_hl(scrollborder_f, "bg")       if fg and #fg > 0 then         local hlgroup = "FzfLuaScrollBorderBackCompat"         self.hls.scrollfloat_f = hlgroup-        vim.api.nvim_set_hl(0, hlgroup,+        api.nvim_set_hl(0, hlgroup,           vim.o.termguicolors and { default = false, fg = bg, bg = fg }-          or { default = false, ctermfg = tonumber(bg), ctermbg = tonumber(fg) })+          or { default = false, ctermfg = utils.tointeger(bg), ctermbg = utils.tointeger(fg) })       end     end   end@@ -821,7 +886,7 @@ function FzfWin:set_winopts(win, opts, ignore_events)   end, ei) end ----@param previewer fzf-lua.previewer.Builtin? nil to "detach" previewer+---@param previewer fzf-lua.previewer.Builtin|fzf-lua.previewer.Fzf? nil to "detach" previewer function FzfWin:attach_previewer(previewer)   if previewer then     previewer.win = self@@ -838,7 +903,7 @@ function FzfWin:attach_previewer(previewer)     -- won't be closed properly and remain lingering (visible in `:ls!`)     -- make sure the previewer is aware of this buffer     if not self._previewer.preview_bufnr and self:validate_preview() then-      self._previewer.preview_bufnr = vim.api.nvim_win_get_buf(self.preview_winid)+      self._previewer.preview_bufnr = api.nvim_win_get_buf(self.preview_winid)     end     self:close_preview()   end@@ -930,7 +995,7 @@ function FzfWin:redraw_main()   else     -- save 'cursorline' setting prior to opening the popup     local cursorline = vim.o.cursorline-    self.fzf_bufnr = self.fzf_bufnr or vim.api.nvim_create_buf(false, true)+    self.fzf_bufnr = self.fzf_bufnr or api.nvim_create_buf(false, true)     self.fzf_winid = utils.nvim_open_win(self.fzf_bufnr, true, winopts)     -- disable search highlights as they interfere with fzf's highlights     if vim.o.hlsearch and vim.v.hlsearch == 1 then@@ -946,20 +1011,20 @@ function FzfWin:redraw_main()   end end -function FzfWin:_nvim_create_autocmd(e, callback)-  vim.api.nvim_create_autocmd(e, {-    group = vim.api.nvim_create_augroup("FzfLua" .. e, { clear = true }),+function FzfWin:_on(e, callback)+  api.nvim_create_autocmd(e, {+    group = api.nvim_create_augroup("FzfLua" .. e, { clear = true }),     buffer = self.fzf_bufnr,     callback = callback,   }) end  function FzfWin:set_redraw_autocmd()-  self:_nvim_create_autocmd("VimResized", function() self:redraw() end)+  self:_on("VimResized", function() self:redraw() end) end  function FzfWin:set_winleave_autocmd()-  self:_nvim_create_autocmd("WinClosed", self.win_leave)+  self:_on("WinClosed", self.win_leave) end  function FzfWin:treesitter_detach(buf)@@ -972,11 +1037,11 @@ function FzfWin:treesitter_attach()   if not self._o.winopts.treesitter then return end   -- local utf8 = require("fzf-lua.lib.utf8")   local function trim(s) return (string.gsub(s, "^%s*(.-)%s*$", "%1")) end-  ---@type fun(filepath: string, _lnum: string?, text: string?)-  local line_parser = vim.is_callable(self._o._treesitter) and self._o._treesitter or function(line)-    return line:match("(.-):?(%d+)[: ](.+)$")-  end-  vim.api.nvim_buf_attach(self.fzf_bufnr, false, {+  ---@type fun(line: string):string?,string?,string?,string?+  local default_line_parser = function(line) return line:match("(.-):?(%d+)[: ](.+)$") end+  local line_parser = vim.is_callable(self._o._treesitter) and self._o._treesitter or+      default_line_parser+  api.nvim_buf_attach(self.fzf_bufnr, false, {     on_lines = function(_, bufnr)       -- Called after `:close` triggers an attach after clear_cache (#2322)       if self.closing then return end@@ -990,9 +1055,9 @@ function FzfWin:treesitter_attach()         local min, max, tr = 0, nil, 4         if not self.preview_hidden             and (not self.previewer_is_builtin or self.winopts.split)-            and vim.api.nvim_win_is_valid(self.fzf_winid)+            and api.nvim_win_is_valid(self.fzf_winid)         then-          local win_width = vim.api.nvim_win_get_width(self.fzf_winid)+          local win_width = api.nvim_win_get_width(self.fzf_winid)           local layout = self:normalize_preview_layout()           local prev_width = self:normalize_size(layout.size, win_width)           if layout.pos == "left" then@@ -1024,8 +1089,8 @@ function FzfWin:treesitter_attach()               if string.byte(text, 1) == 32 then text = text:sub(2) end  -- remove leading SPACE               -- IMPORTANT: use the `__CTX` version that doesn't trigger a new context               local __CTX = utils.__CTX()-              local b = tonumber(filepath:match("^%d+") or __CTX and __CTX.bufnr) ---@type integer-              return b and vim.api.nvim_buf_is_valid(b) and b or nil+              local b = utils.tointeger(filepath:match("^%d+") or __CTX and __CTX.bufnr)+              return b and api.nvim_buf_is_valid(b) and b or nil             end           end)() @@ -1155,10 +1220,10 @@ function FzfWin:create()   self:set_backdrop()    -- save sending bufnr/winid-  self.src_bufnr = vim.api.nvim_get_current_buf()-  self.src_winid = vim.api.nvim_get_current_win()+  self.src_bufnr = api.nvim_get_current_buf()+  self.src_winid = api.nvim_get_current_win()   -- save current window layout cmd-  self.winrestcmd = vim.fn.winrestcmd()+  self.winrestcmd = fn.winrestcmd()   self.cmdheight = vim.o.cmdheight    if self.winopts.split then@@ -1170,10 +1235,10 @@ function FzfWin:create()       vim.cmd(tostring(self.winopts.split))     end -    local split_bufnr = vim.api.nvim_get_current_buf()-    self.fzf_winid = vim.api.nvim_get_current_win()+    local split_bufnr = api.nvim_get_current_buf()+    self.fzf_winid = api.nvim_get_current_win() -    if tonumber(self.fzf_bufnr) and vim.api.nvim_buf_is_valid(self.fzf_bufnr) then+    if self.fzf_bufnr and api.nvim_buf_is_valid(self.fzf_bufnr) then       -- set to fzf bufnr set by `:unhide()`       utils.win_set_buf_noautocmd(self.fzf_winid, self.fzf_bufnr)     else@@ -1226,7 +1291,7 @@ function FzfWin:close_preview(do_not_clear_cache)   if self._previewer and self._previewer.close then     self._previewer:close(do_not_clear_cache)   end-  if self.preview_winid and vim.api.nvim_win_is_valid(self.preview_winid) then+  if self.preview_winid and api.nvim_win_is_valid(self.preview_winid) then     utils.nvim_win_close(self.preview_winid, true)   end   self.preview_winid = nil@@ -1251,13 +1316,13 @@ function FzfWin:close(fzf_bufnr, hide, hidden)   self:close_preview(hide)   -- Abort hidden fzf job?   if not hide and self._hidden_fzf_bufnr and self._hidden_fzf_bufnr ~= self.fzf_bufnr then-    pcall(vim.api.nvim_buf_delete, self._hidden_fzf_bufnr, { force = true })+    pcall(api.nvim_buf_delete, self._hidden_fzf_bufnr, { force = true })   end   -- Clear treesitter buffer cache and deregister decoration callbacks   self:treesitter_detach(self._hidden_fzf_bufnr or self.fzf_bufnr)   -- If this is a hidden buffer closure nothing else to do   if hidden then return end-  if self.fzf_winid and vim.api.nvim_win_is_valid(self.fzf_winid) then+  if self.fzf_winid and api.nvim_win_is_valid(self.fzf_winid) then     -- run in a pcall due to potential errors while closing the window     -- Vim(lua):E5108: Error executing lua     -- experienced while accessing 'vim.b[]' from my statusline code@@ -1275,36 +1340,36 @@ function FzfWin:close(fzf_bufnr, hide, hidden)       -- also restore the original alternate buffer       local alt_bname = (function()         local alt_bufnr = utils.__CTX() and utils.__CTX().alt_bufnr-        if alt_bufnr and vim.api.nvim_buf_is_valid(alt_bufnr) then-          return vim.fn.bufname(alt_bufnr)+        if alt_bufnr and api.nvim_buf_is_valid(alt_bufnr) then+          return fn.bufname(alt_bufnr)         end       end)()       if alt_bname and #alt_bname > 0 then-        vim.cmd("balt " .. vim.fn.bufname(alt_bname))+        vim.cmd("balt " .. fn.bufname(alt_bname))       end     else-      pcall(vim.api.nvim_win_close, self.fzf_winid, true)+      pcall(api.nvim_win_close, self.fzf_winid, true)     end   end   if self.fzf_bufnr then-    pcall(vim.api.nvim_buf_delete, self.fzf_bufnr, { force = true })+    pcall(api.nvim_buf_delete, self.fzf_bufnr, { force = true })   end   -- when using `split = "belowright new"` closing the fzf   -- window may not always return to the correct source win   -- depending on the user's split configuration (#397)   if self.winopts and self.winopts.split-      and tonumber(self.src_winid)-      and vim.api.nvim_win_is_valid(self.src_winid)-      and self.src_winid ~= vim.api.nvim_get_current_win()+      and self.src_winid+      and api.nvim_win_is_valid(self.src_winid)+      and self.src_winid ~= api.nvim_get_current_win()   then-    vim.api.nvim_set_current_win(self.src_winid)+    api.nvim_set_current_win(self.src_winid)   end   if self.winopts.split then     -- remove all windows from the restore cmd that have been closed in the meantime     -- if we're not doing this the result might be all over the place     local winnrs = vim.tbl_map(function(win)-      return vim.api.nvim_win_get_number(win) .. ""-    end, vim.api.nvim_tabpage_list_wins(0))+      return api.nvim_win_get_number(win) .. ""+    end, api.nvim_tabpage_list_wins(0))      local cmd = {}     for cmd_part in string.gmatch(self.winrestcmd, "[^|]+") do@@ -1372,21 +1437,17 @@ function FzfWin:resized() end  function FzfWin:hidden()-  return tonumber(self._hidden_fzf_bufnr)-      and tonumber(self._hidden_fzf_bufnr) > 0-      and vim.api.nvim_buf_is_valid(self._hidden_fzf_bufnr)+  return self._hidden_fzf_bufnr and api.nvim_buf_is_valid(self._hidden_fzf_bufnr) end  -- True after a `:new()` call for a different picker, used in `core.fzf` -- to avoid post processing an fzf process that was discarded (e.g. kill by :%bw!) function FzfWin:was_hidden()-  return tonumber(self._hidden_fzf_bufnr)-      and tonumber(self._hidden_fzf_bufnr) > 0-      and not vim.api.nvim_buf_is_valid(self._hidden_fzf_bufnr)+  return self._hidden_fzf_bufnr and not api.nvim_buf_is_valid(self._hidden_fzf_bufnr) end  ---SIGWINCH/on_SIGWINCH is nop if fzf < v0.46----@param opts table+---@param opts fzf-lua.config.Resolved ---@param scope string? nil means on any sigwinch ---@param cb function ---@return boolean?@@ -1405,6 +1466,7 @@ function FzfWin.on_SIGWINCH(opts, scope, cb)     s[#s + 1] = cb   end   if not first then return true end+  opts._fzf_cli_args = opts._fzf_cli_args or {}   table.insert(opts._fzf_cli_args, "--bind="     .. libuv.shellescape("resize:+transform:" .. FzfLua.shell.stringify_data(function(args)       local scopes = opts.__sigwinches or {}@@ -1425,9 +1487,9 @@ function FzfWin:SIGWINCH(scopes)   -- avoid racing when multiple SIGWINCH trigger at the same time   if not utils.has(self._o, "fzf", { 0, 46 }) or self._o.__sigwinches then return end   local bufnr = self._hidden_fzf_bufnr or self.fzf_bufnr-  if not tonumber(bufnr) or not vim.api.nvim_buf_is_valid(bufnr) then return end+  if not bufnr or not api.nvim_buf_is_valid(bufnr) then return end   local ok, pid = pcall(fn.jobpid, vim.bo[bufnr].channel)-  if ok and tonumber(pid) > 0 then ---@cast pid integer+  if ok and pid > 0 then ---@cast pid integer     self._o.__sigwinches = scopes or {}     vim.tbl_map(function(_pid) libuv.process_kill(_pid, 28) end, api.nvim_get_proc_children(pid))   end@@ -1451,7 +1513,7 @@ function FzfWin.unhide() end  local function ensure_tmp_buf(bufnr)-  if bufnr and vim.api.nvim_buf_is_valid(bufnr) then+  if bufnr and api.nvim_buf_is_valid(bufnr) then     return bufnr   end   bufnr = api.nvim_create_buf(false, true)@@ -1462,16 +1524,16 @@ local function ensure_tmp_buf(bufnr) end  function FzfWin:close_preview_scrollbar()-  if self._sbuf1 and vim.api.nvim_buf_is_valid(self._sbuf1) then-    vim.api.nvim_buf_delete(self._sbuf1, { force = true })+  if self._sbuf1 and api.nvim_buf_is_valid(self._sbuf1) then+    api.nvim_buf_delete(self._sbuf1, { force = true })   end-  if self._swin1 and vim.api.nvim_win_is_valid(self._swin1) then+  if self._swin1 and api.nvim_win_is_valid(self._swin1) then     utils.nvim_win_close(self._swin1, true)   end-  if self._sbuf2 and vim.api.nvim_buf_is_valid(self._sbuf2) then-    vim.api.nvim_buf_delete(self._sbuf2, { force = true })+  if self._sbuf2 and api.nvim_buf_is_valid(self._sbuf2) then+    api.nvim_buf_delete(self._sbuf2, { force = true })   end-  if self._swin2 and vim.api.nvim_win_is_valid(self._swin2) then+  if self._swin2 and api.nvim_win_is_valid(self._swin2) then     utils.nvim_win_close(self._swin2, true)   end   self._sbuf1 = nil@@ -1487,22 +1549,20 @@ function FzfWin:update_preview_scrollbar()     return   end -  local o = {}   local buf = api.nvim_win_get_buf(self.preview_winid)-  o.wininfo = utils.getwininfo(self.preview_winid)-  o.line_count = utils.line_count(self.preview_winid, buf)+  local wininfo = assert(utils.getwininfo(self.preview_winid))+  local line_count = utils.line_count(self.preview_winid, buf) -  local topline, height = o.wininfo.topline, o.wininfo.height+  local topline, height = wininfo.topline, wininfo.height   if api.nvim_win_text_height then     topline = topline == 1 and topline or         api.nvim_win_text_height(self.preview_winid, { end_row = topline - 1 }).all + 1   end-  assert(height, height)-  o.bar_height = math.min(height, math.ceil(height * height / o.line_count))-  o.bar_offset = math.min(height - o.bar_height, math.floor(height * topline / o.line_count))+  local bar_height = math.min(height, math.ceil(height * height / line_count))+  local bar_offset = math.min(height - bar_height, math.floor(height * topline / line_count))    -- do not display on files that are fully contained-  if o.bar_height >= o.line_count then+  if bar_height >= line_count then     self:close_preview_scrollbar()     return   end@@ -1518,22 +1578,22 @@ function FzfWin:update_preview_scrollbar()     anchor = "NW",     win = self.preview_winid,     width = 1,-    height = o.wininfo.height,+    height = height,     zindex = self.winopts.zindex + 1,     row = 0,-    col = o.wininfo.width + scrolloff,+    col = wininfo.width + scrolloff,     border = "none",     hide = self.winopts.hide,   }   local full = vim.tbl_extend("keep", {     zindex = empty.zindex + 1,-    height = o.bar_height,-    row = empty.row + o.bar_offset,+    height = bar_height,+    row = empty.row + bar_offset,   }, empty)   -- We hide the "empty" win in `scrollbar="border"` back compat   if self.winopts.preview.scrollbar ~= "border" then-    if self._swin1 and vim.api.nvim_win_is_valid(self._swin1) then-      vim.api.nvim_win_set_config(self._swin1, empty)+    if self._swin1 and api.nvim_win_is_valid(self._swin1) then+      api.nvim_win_set_config(self._swin1, empty)     else       empty.noautocmd = true       self._sbuf1 = ensure_tmp_buf(self._sbuf1)@@ -1544,8 +1604,8 @@ function FzfWin:update_preview_scrollbar()           ("Normal:%s,NormalNC:%s,NormalFloat:%s,EndOfBuffer:%s"):format(hl, hl, hl, hl)     end   end-  if self._swin2 and vim.api.nvim_win_is_valid(self._swin2) then-    vim.api.nvim_win_set_config(self._swin2, full)+  if self._swin2 and api.nvim_win_is_valid(self._swin2) then+    api.nvim_win_set_config(self._swin2, full)   else     full.noautocmd = true     self._sbuf2 = ensure_tmp_buf(self._sbuf2)@@ -1609,7 +1669,7 @@ function FzfWin:update_main_title(title) end  function FzfWin:update_preview_title(title)-  if type(title) ~= "string" and type(title) ~= "table" then+  if type(title) ~= "string" and type(title) ~= "table" or not self.layout.preview then     return   end   -- since `nvim_win_set_config` removes all styling, save backup@@ -1635,7 +1695,7 @@ end function FzfWin.focus_preview()   if not _self then return end   local self = _self-  vim.api.nvim_set_current_win(self.preview_winid)+  api.nvim_set_current_win(self.preview_winid) end  function FzfWin.toggle_preview()@@ -1658,7 +1718,7 @@ function FzfWin.toggle_preview()       utils.warn("missing 'toggle-preview' in opts.keymap.fzf or opts.keymap.builtin")     end     -- TODO: this don't work with <a-x> or <fxx> (wrong keycode)-    -- vim.api.nvim_chan_send(vim.bo.channel, vim.keycode(self._fzf_toggle_prev_bind))+    -- api.nvim_chan_send(vim.bo.channel, vim.keycode(self._fzf_toggle_prev_bind))   end   if self.preview_hidden then     if self:validate_preview() then self:close_preview(true) end@@ -1748,11 +1808,11 @@ function FzfWin.close_help()    local self = _self -  if self.km_winid and vim.api.nvim_win_is_valid(self.km_winid) then+  if self.km_winid and api.nvim_win_is_valid(self.km_winid) then     utils.nvim_win_close(self.km_winid, true)   end-  if self.km_bufnr and vim.api.nvim_buf_is_valid(self.km_bufnr) then-    vim.api.nvim_buf_delete(self.km_bufnr, { force = true })+  if self.km_bufnr and api.nvim_buf_is_valid(self.km_bufnr) then+    api.nvim_buf_delete(self.km_bufnr, { force = true })   end   self.km_winid = nil   self.km_bufnr = nil@@ -1883,6 +1943,7 @@ function FzfWin.toggle_help()    local zindex = self.winopts.zindex + 2   local ch = zindex >= 200 and 0 or vim.o.cmdheight+  ---@type vim.api.keyset.win_config   local winopts = {     relative = "editor",     style = "minimal",@@ -1904,13 +1965,13 @@ function FzfWin.toggle_help()   end    local nvim_open_win = type(self._o.help_open_win) == "function"-      and self._o.help_open_win or vim.api.nvim_open_win+      and self._o.help_open_win or api.nvim_open_win -  self.km_bufnr = vim.api.nvim_create_buf(false, true)+  self.km_bufnr = api.nvim_create_buf(false, true)   vim.bo[self.km_bufnr].modifiable = true   vim.bo[self.km_bufnr].bufhidden = "wipe"   self.km_winid = nvim_open_win(self.km_bufnr, false, winopts)-  vim.api.nvim_buf_set_name(self.km_bufnr, "_FzfLuaHelp")+  api.nvim_buf_set_name(self.km_bufnr, "_FzfLuaHelp")   utils.wo[self.km_winid].winhl =       string.format("Normal:%s,FloatBorder:%s", opts.normal_hl, opts.border_hl)   utils.wo[self.km_winid].winblend = opts.winblend@@ -1919,7 +1980,7 @@ function FzfWin.toggle_help()   utils.wo[self.km_winid].spell = false   vim.bo[self.km_bufnr].filetype = "help" -  vim.api.nvim_buf_set_lines(self.km_bufnr, 0, -1, false, lines)+  api.nvim_buf_set_lines(self.km_bufnr, 0, -1, false, lines) end  return FzfWin

scripts/cli.lua

@@ -1,3 +1,4 @@+---@diagnostic disable-next-line: deprecated local api, uv, fn = vim.api, vim.uv or vim.loop, vim.fn assert(#api.nvim_list_uis() == 0) local __FILE__ = debug.getinfo(1, "S").source:gsub("^@", "")@@ -17,7 +18,7 @@ api.nvim_create_autocmd("Signal", {   callback = function(ev)     vim.tbl_map(function(pid)       FzfLua.libuv.process_kill(pid, ev.match)-    end, api.nvim_get_proc_children(uv.os_getpid()))+    end, api.nvim_get_proc_children(fn.getpid()))   end }) @@ -47,7 +48,7 @@ _G.fzf_jobstart = function(cmd, opts)     },     vim.schedule_wrap(function(rc)       opts.on_exit(nil, rc, nil)-      if not opts.no_quit and #vim.api.nvim_get_proc_children(uv.os_getpid()) == 0 then+      if not opts.no_quit and #api.nvim_get_proc_children(fn.getpid()) == 0 then         vim.cmd.cquit { count = rc, bang = true }       end     end))

tests/actions_spec.lua

@@ -1,8 +1,8 @@----@diagnostic disable: unused-local, unused-function+---@diagnostic disable: unused-local, unused-function, unused local MiniTest = require("mini.test") local helpers = require("fzf-lua.test.helpers") local child = helpers.new_child_neovim()-local expect, eq = helpers.expect, helpers.expect.equality+local eq = helpers.expect.equality local new_set = MiniTest.new_set  ---@format disable-next

tests/api_spec.lua

@@ -1,8 +1,8 @@----@diagnostic disable: unused-local, unused-function+---@diagnostic disable: unused-local, unused-function, unused local MiniTest = require("mini.test") local helpers = require("fzf-lua.test.helpers") local child = helpers.new_child_neovim()-local expect, eq = helpers.expect, helpers.expect.equality+local eq = helpers.expect.equality local new_set = MiniTest.new_set  local T = helpers.new_set_with_child(child)

tests/cache_spec.lua

@@ -5,6 +5,7 @@ local fzf = require("fzf-lua") local LRU = fzf.shell.LRU  describe("Testing cache module", function()+  ---@type fzf-lua.lru   local cache   local cached_fun = function(id) return function() return "CACHED" .. tostring(id) end end @@ -103,11 +104,11 @@ describe("Testing cache module", function()   it("size set: err", function()     local ok, err = pcall(cache.set_size, cache, 10)     assert.is.False(ok)-    assert.is.True(err:match("cannot be smaller than current length") ~= nil)+    assert.is.True(err and err:match("cannot be smaller than current length") ~= nil)   end)    it("size set: ok", function()-    cache:set_size(50)  -- should not err, same size+    cache:set_size(50) -- should not err, same size     cache:set_size(51)     local id, evicted_id = cache:set(cached_fun(52))     assert.is.same(id, 52)@@ -118,5 +119,4 @@ describe("Testing cache module", function()     assert.is.same(cache.mru[4], 1)     assert.is.same(cache.mru[51], 3)   end)- end)

tests/devicons_spec.lua

@@ -3,7 +3,7 @@ local MiniTest = require("mini.test") local helpers = require("fzf-lua.test.helpers") local assert = helpers.assert local child = helpers.new_child_neovim()-local expect, eq = helpers.expect, helpers.expect.equality+local eq = helpers.expect.equality local new_set = MiniTest.new_set local exec_lua = child.lua @@ -96,6 +96,7 @@ T["setup"]["headless RPC, vim.g.fzf_lua_server"] = function()   eq(#fzf_lua_server > 0, true)   local headless_child = helpers.new_child_neovim()   headless_child.init()+  ---@diagnostic disable-next-line: preferred-local-alias   headless_child.lua(string.format([==[     _G._fzf_lua_is_headless = true     _G._devicons_path = nil

tests/files_spec.lua

@@ -1,8 +1,8 @@----@diagnostic disable: unused-local, unused-function+---@diagnostic disable: unused-local, unused-function, unused local MiniTest = require("mini.test") local helpers = require("fzf-lua.test.helpers") local child = helpers.new_child_neovim()-local expect, eq = helpers.expect, helpers.expect.equality+local eq = helpers.expect.equality local new_set = MiniTest.new_set local exec_lua = child.lua 

tests/grep_spec.lua

@@ -1,8 +1,8 @@----@diagnostic disable: unused-local, unused-function+---@diagnostic disable: unused-local, unused-function, unused local MiniTest = require("mini.test") local helpers = require("fzf-lua.test.helpers") local child = helpers.new_child_neovim()-local expect, eq = helpers.expect, helpers.expect.equality+local eq = helpers.expect.equality local new_set = MiniTest.new_set local exec_lua = child.lua 

tests/headless_spec.lua

@@ -2,7 +2,7 @@ local MiniTest = require("mini.test") local helpers = require("fzf-lua.test.helpers") local child = helpers.new_child_neovim()-local expect, eq = helpers.expect, helpers.expect.equality+local eq = helpers.expect.equality local new_set = MiniTest.new_set local exec_lua = child.lua 

tests/init_spec.lua

@@ -2,7 +2,8 @@ local MiniTest = require("mini.test") local helpers = require("fzf-lua.test.helpers") local child = helpers.new_child_neovim()-local expect, eq = helpers.expect, helpers.expect.equality+local expect = helpers.expect+local eq = expect.equality local new_set = MiniTest.new_set  local T = helpers.new_set_with_child(child, nil, { winopts = { col = 0, row = 1 } })

tests/libuv_spec.lua

@@ -20,129 +20,129 @@ describe("Testing libuv module", function()   end)    it("shellescape (win bslash)", function()-    assert.are.same(libuv.shellescape([[]], 1), [[""]])-    assert.are.same(libuv.shellescape([[^]], 1), [["^"]])-    assert.are.same(libuv.shellescape([[""]], 1), [["\"\""]])-    assert.are.same(libuv.shellescape([["^"]], 1), [["\"^\""]])-    assert.are.same(libuv.shellescape([[foo]], 1), [["foo"]])-    assert.are.same(libuv.shellescape([["foo"]], 1), [["\"foo\""]])-    assert.are.same(libuv.shellescape([["foo"bar"]], 1), [["\"foo\"bar\""]])-    assert.are.same(libuv.shellescape([[foo"bar]], 1), [["foo\"bar"]])-    assert.are.same(libuv.shellescape([[foo""bar]], 1), [["foo\"\"bar"]])-    assert.are.same(libuv.shellescape([["foo\"bar"]], 1), [["\"foo\\\"bar\""]])-    assert.are.same(libuv.shellescape([[foo\]], 1), [["foo\\"]])-    assert.are.same(libuv.shellescape([[foo\\]], 1), [["foo\\\\"]])-    assert.are.same(libuv.shellescape([[foo\^]], 1), [["foo\^"]])-    assert.are.same(libuv.shellescape([[foo\\\\]], 1), [["foo\\\\\\\\"]])-    assert.are.same(libuv.shellescape([[foo\"]], 1), [["foo\\\""]])-    assert.are.same(libuv.shellescape([["foo\"]], 1), [["\"foo\\\""]])-    assert.are.same(libuv.shellescape([["foo\""]], 1), [["\"foo\\\"\""]])-    assert.are.same(libuv.shellescape([[foo\bar]], 1), [["foo\bar"]])-    assert.are.same(libuv.shellescape([[foo\\bar]], 1), [["foo\\bar"]])-    assert.are.same(libuv.shellescape([[foo\\"bar]], 1), [["foo\\\\\"bar"]])-    assert.are.same(libuv.shellescape([[foo\\\"bar]], 1), [["foo\\\\\\\"bar"]])+    eq(libuv.shellescape([[]], 1), [[""]])+    eq(libuv.shellescape([[^]], 1), [["^"]])+    eq(libuv.shellescape([[""]], 1), [["\"\""]])+    eq(libuv.shellescape([["^"]], 1), [["\"^\""]])+    eq(libuv.shellescape([[foo]], 1), [["foo"]])+    eq(libuv.shellescape([["foo"]], 1), [["\"foo\""]])+    eq(libuv.shellescape([["foo"bar"]], 1), [["\"foo\"bar\""]])+    eq(libuv.shellescape([[foo"bar]], 1), [["foo\"bar"]])+    eq(libuv.shellescape([[foo""bar]], 1), [["foo\"\"bar"]])+    eq(libuv.shellescape([["foo\"bar"]], 1), [["\"foo\\\"bar\""]])+    eq(libuv.shellescape([[foo\]], 1), [["foo\\"]])+    eq(libuv.shellescape([[foo\\]], 1), [["foo\\\\"]])+    eq(libuv.shellescape([[foo\^]], 1), [["foo\^"]])+    eq(libuv.shellescape([[foo\\\\]], 1), [["foo\\\\\\\\"]])+    eq(libuv.shellescape([[foo\"]], 1), [["foo\\\""]])+    eq(libuv.shellescape([["foo\"]], 1), [["\"foo\\\""]])+    eq(libuv.shellescape([["foo\""]], 1), [["\"foo\\\"\""]])+    eq(libuv.shellescape([[foo\bar]], 1), [["foo\bar"]])+    eq(libuv.shellescape([[foo\\bar]], 1), [["foo\\bar"]])+    eq(libuv.shellescape([[foo\\"bar]], 1), [["foo\\\\\"bar"]])+    eq(libuv.shellescape([[foo\\\"bar]], 1), [["foo\\\\\\\"bar"]])   end)    it("shellescape (win caret)", function()-    assert.are.same(libuv.shellescape([[]], 2), [[^"^"]])-    assert.are.same(libuv.shellescape([["]], 2), [[^"\^"^"]])-    assert.are.same(libuv.shellescape([[^"]], 2), [[^"^^\^"^"]])-    assert.are.same(libuv.shellescape([[\"]], 2), [[^"\\\^"^"]])-    assert.are.same(libuv.shellescape([[\^"]], 2), [[^"^^\\\^"^"]])-    assert.are.same(libuv.shellescape([[^"^"]], 2), [[^"^^\^"^^\^"^"]])-    assert.are.same(libuv.shellescape([[__^^"^"__]], 2), [[^"__^^^^\^"^^\^"__^"]])-    assert.are.same(libuv.shellescape([[__!^^"^"__]], 2),+    eq(libuv.shellescape([[]], 2), [[^"^"]])+    eq(libuv.shellescape([["]], 2), [[^"\^"^"]])+    eq(libuv.shellescape([[^"]], 2), [[^"^^\^"^"]])+    eq(libuv.shellescape([[\"]], 2), [[^"\\\^"^"]])+    eq(libuv.shellescape([[\^"]], 2), [[^"^^\\\^"^"]])+    eq(libuv.shellescape([[^"^"]], 2), [[^"^^\^"^^\^"^"]])+    eq(libuv.shellescape([[__^^"^"__]], 2), [[^"__^^^^\^"^^\^"__^"]])+    eq(libuv.shellescape([[__!^^"^"__]], 2),       -- 1st: ^"_^!^^^^\^"^^\^"_^"       -- 2nd: ^"_^^^!^^^^^^^^^^\\\^"^^^^^^\\\^"_^"       [[^"__^^^!^^^^^^^^^^\\\^"^^^^^^\\\^"__^"]])-    assert.are.same(libuv.shellescape([[__^^^^\^"^^\^"__]], 2),+    eq(libuv.shellescape([[__^^^^\^"^^\^"__]], 2),       [[^"__^^^^^^^^^^\\\^"^^^^^^\\\^"__^"]])-    assert.are.same(libuv.shellescape([[^]], 2), [[^"^^^"]])-    assert.are.same(libuv.shellescape([[^^]], 2), [[^"^^^^^"]])-    assert.are.same(libuv.shellescape([[^^^]], 2), [[^"^^^^^^^"]])-    assert.are.same(libuv.shellescape([[^!^]], 2), [[^"^^^^^^^!^^^^^"]])-    assert.are.same(libuv.shellescape([[!^"]], 2),+    eq(libuv.shellescape([[^]], 2), [[^"^^^"]])+    eq(libuv.shellescape([[^^]], 2), [[^"^^^^^"]])+    eq(libuv.shellescape([[^^^]], 2), [[^"^^^^^^^"]])+    eq(libuv.shellescape([[^!^]], 2), [[^"^^^^^^^!^^^^^"]])+    eq(libuv.shellescape([[!^"]], 2),       -- 1st inner: ^!^^\^"       -- 2nd inner: ^^^!^^^^^^\\\^"       [[^"^^^!^^^^^^\\\^"^"]])-    assert.are.same(libuv.shellescape([[!\"]], 2), [[^"^^^!^^\\\\\\\^"^"]])-    assert.are.same(libuv.shellescape([[!\^"]], 2), [[^"^^^!^^^^^^\\\\\\\^"^"]])-    assert.are.same(libuv.shellescape([[()%^"<>&|;]], 2), [[^"^(^)^%^^\^"^<^>^&^|^;^"]])-    assert.are.same(libuv.shellescape([[()%^"<>&|;!]], 2),+    eq(libuv.shellescape([[!\"]], 2), [[^"^^^!^^\\\\\\\^"^"]])+    eq(libuv.shellescape([[!\^"]], 2), [[^"^^^!^^^^^^\\\\\\\^"^"]])+    eq(libuv.shellescape([[()%^"<>&|;]], 2), [[^"^(^)^%^^\^"^<^>^&^|^;^"]])+    eq(libuv.shellescape([[()%^"<>&|;!]], 2),       -- 1st inner: ^(^)^%^^\^"^<^>^&^|^!       -- 2nd inner: ^^^(^^^)^^^%^^^^^^\^"^^^<^^^>^^^&^^^|^^^!       [[^"^^^(^^^)^^^%^^^^^^\\\^"^^^<^^^>^^^&^^^|^^^;^^^!^"]])-    assert.are.same(libuv.shellescape([[foo]], 2), [[^"foo^"]])-    assert.are.same(libuv.shellescape([[foo\]], 2), [[^"foo\\^"]])-    assert.are.same(libuv.shellescape([[foo^]], 2), [[^"foo^^^"]])-    assert.are.same(libuv.shellescape([[foo\\]], 2), [[^"foo\\\\^"]])-    assert.are.same(libuv.shellescape([[foo\\\]], 2), [[^"foo\\\\\\^"]])-    assert.are.same(libuv.shellescape([[foo\\\\]], 2), [[^"foo\\\\\\\\^"]])-    assert.are.same(libuv.shellescape([[f!oo]], 2), [[^"f^^^!oo^"]])-    assert.are.same(libuv.shellescape([[^"foo^"]], 2), [[^"^^\^"foo^^\^"^"]])-    assert.are.same(libuv.shellescape([[\^"foo\^"]], 2), [[^"^^\\\^"foo^^\\\^"^"]])-    assert.are.same(libuv.shellescape([[foo""bar]], 2), [[^"foo\^"\^"bar^"]])-    assert.are.same(libuv.shellescape([[foo^"^"bar]], 2), [[^"foo^^\^"^^\^"bar^"]])-    assert.are.same(libuv.shellescape([["foo\"bar"]], 2), [[^"\^"foo\\\^"bar\^"^"]])-    assert.are.same(libuv.shellescape([[foo\^"]], 2), [[^"foo^^\\\^"^"]])-    assert.are.same(libuv.shellescape([[foo\"]], 2), [[^"foo\\\^"^"]])-    assert.are.same(libuv.shellescape([[^"foo\^"^"]], 2), [[^"^^\^"foo^^\\\^"^^\^"^"]])-    assert.are.same(libuv.shellescape([[foo\"bar]], 2), [[^"foo\\\^"bar^"]])-    assert.are.same(libuv.shellescape([[foo\\"bar]], 2), [[^"foo\\\\\^"bar^"]])-    assert.are.same(libuv.shellescape([[foo\\^^"bar]], 2), [[^"foo\\^^^^\^"bar^"]])-    assert.are.same(libuv.shellescape([[foo\\\^^^"]], 2), [[^"foo\\\^^^^^^\^"^"]])+    eq(libuv.shellescape([[foo]], 2), [[^"foo^"]])+    eq(libuv.shellescape([[foo\]], 2), [[^"foo\\^"]])+    eq(libuv.shellescape([[foo^]], 2), [[^"foo^^^"]])+    eq(libuv.shellescape([[foo\\]], 2), [[^"foo\\\\^"]])+    eq(libuv.shellescape([[foo\\\]], 2), [[^"foo\\\\\\^"]])+    eq(libuv.shellescape([[foo\\\\]], 2), [[^"foo\\\\\\\\^"]])+    eq(libuv.shellescape([[f!oo]], 2), [[^"f^^^!oo^"]])+    eq(libuv.shellescape([[^"foo^"]], 2), [[^"^^\^"foo^^\^"^"]])+    eq(libuv.shellescape([[\^"foo\^"]], 2), [[^"^^\\\^"foo^^\\\^"^"]])+    eq(libuv.shellescape([[foo""bar]], 2), [[^"foo\^"\^"bar^"]])+    eq(libuv.shellescape([[foo^"^"bar]], 2), [[^"foo^^\^"^^\^"bar^"]])+    eq(libuv.shellescape([["foo\"bar"]], 2), [[^"\^"foo\\\^"bar\^"^"]])+    eq(libuv.shellescape([[foo\^"]], 2), [[^"foo^^\\\^"^"]])+    eq(libuv.shellescape([[foo\"]], 2), [[^"foo\\\^"^"]])+    eq(libuv.shellescape([[^"foo\^"^"]], 2), [[^"^^\^"foo^^\\\^"^^\^"^"]])+    eq(libuv.shellescape([[foo\"bar]], 2), [[^"foo\\\^"bar^"]])+    eq(libuv.shellescape([[foo\\"bar]], 2), [[^"foo\\\\\^"bar^"]])+    eq(libuv.shellescape([[foo\\^^"bar]], 2), [[^"foo\\^^^^\^"bar^"]])+    eq(libuv.shellescape([[foo\\\^^^"]], 2), [[^"foo\\\^^^^^^\^"^"]])   end)    it("escape {q} (win, fzf v0.50)", function()-    assert.are.same(libuv.escape_fzf([[]], 0.50, true), [[]])-    assert.are.same(libuv.escape_fzf([[\]], 0.50, true), [[\]])-    assert.are.same(libuv.escape_fzf([[\\]], 0.50, true), [[\\]])-    assert.are.same(libuv.escape_fzf([[foo]], 0.50, true), [[foo]])-    assert.are.same(libuv.escape_fzf([[\foo]], 0.50, true), [[\\foo]])-    assert.are.same(libuv.escape_fzf([[\\foo]], 0.50, true), [[\\\\foo]])-    assert.are.same(libuv.escape_fzf([[\\\foo]], 0.50, true), [[\\\\\\foo]])-    assert.are.same(libuv.escape_fzf([[\\\\foo]], 0.50, true), [[\\\\\\\\foo]])-    assert.are.same(libuv.escape_fzf([[foo\]], 0.50, true), [[foo\]])-    assert.are.same(libuv.escape_fzf([[foo\\]], 0.50, true), [[foo\\]])+    eq(libuv.escape_fzf([[]], 0.50, true), [[]])+    eq(libuv.escape_fzf([[\]], 0.50, true), [[\]])+    eq(libuv.escape_fzf([[\\]], 0.50, true), [[\\]])+    eq(libuv.escape_fzf([[foo]], 0.50, true), [[foo]])+    eq(libuv.escape_fzf([[\foo]], 0.50, true), [[\\foo]])+    eq(libuv.escape_fzf([[\\foo]], 0.50, true), [[\\\\foo]])+    eq(libuv.escape_fzf([[\\\foo]], 0.50, true), [[\\\\\\foo]])+    eq(libuv.escape_fzf([[\\\\foo]], 0.50, true), [[\\\\\\\\foo]])+    eq(libuv.escape_fzf([[foo\]], 0.50, true), [[foo\]])+    eq(libuv.escape_fzf([[foo\\]], 0.50, true), [[foo\\]])   end)    it("unescape {q} (win, fzf v0.50)", function()-    assert.are.same(libuv.unescape_fzf([[]], 0.50, true), [[]])-    assert.are.same(libuv.unescape_fzf([[\]], 0.50, true), [[\]])-    assert.are.same(libuv.unescape_fzf([[\\]], 0.50, true), [[\\]])-    assert.are.same(libuv.unescape_fzf([[foo]], 0.50, true), [[foo]])-    assert.are.same(libuv.unescape_fzf([[\foo]], 0.50, true), [[\foo]])-    assert.are.same(libuv.unescape_fzf([[\\foo]], 0.50, true), [[\foo]])-    assert.are.same(libuv.unescape_fzf([[\\\foo]], 0.50, true), [[\foo]])-    assert.are.same(libuv.unescape_fzf([[\\\\foo]], 0.50, true), [[\\foo]])-    assert.are.same(libuv.unescape_fzf([[foo\]], 0.50, true), [[foo\]])-    assert.are.same(libuv.unescape_fzf([[foo\\]], 0.50, true), [[foo\\]])+    eq(libuv.unescape_fzf([[]], 0.50, true), [[]])+    eq(libuv.unescape_fzf([[\]], 0.50, true), [[\]])+    eq(libuv.unescape_fzf([[\\]], 0.50, true), [[\\]])+    eq(libuv.unescape_fzf([[foo]], 0.50, true), [[foo]])+    eq(libuv.unescape_fzf([[\foo]], 0.50, true), [[\foo]])+    eq(libuv.unescape_fzf([[\\foo]], 0.50, true), [[\foo]])+    eq(libuv.unescape_fzf([[\\\foo]], 0.50, true), [[\foo]])+    eq(libuv.unescape_fzf([[\\\\foo]], 0.50, true), [[\\foo]])+    eq(libuv.unescape_fzf([[foo\]], 0.50, true), [[foo\]])+    eq(libuv.unescape_fzf([[foo\\]], 0.50, true), [[foo\\]])   end)    it("escape {q} (win, fzf v0.52)", function()-    assert.are.same(libuv.escape_fzf([[]], 0.52, true), [[]])-    assert.are.same(libuv.escape_fzf([[\]], 0.52, true), [[\]])-    assert.are.same(libuv.escape_fzf([[\\]], 0.52, true), [[\\]])-    assert.are.same(libuv.escape_fzf([[foo]], 0.52, true), [[foo]])-    assert.are.same(libuv.escape_fzf([[\foo]], 0.52, true), [[\foo]])-    assert.are.same(libuv.escape_fzf([[\\foo]], 0.52, true), [[\\foo]])-    assert.are.same(libuv.escape_fzf([[\\\foo]], 0.52, true), [[\\\foo]])-    assert.are.same(libuv.escape_fzf([[\\\\foo]], 0.52, true), [[\\\\foo]])-    assert.are.same(libuv.escape_fzf([[foo\]], 0.52, true), [[foo\]])-    assert.are.same(libuv.escape_fzf([[foo\\]], 0.52, true), [[foo\\]])+    eq(libuv.escape_fzf([[]], 0.52, true), [[]])+    eq(libuv.escape_fzf([[\]], 0.52, true), [[\]])+    eq(libuv.escape_fzf([[\\]], 0.52, true), [[\\]])+    eq(libuv.escape_fzf([[foo]], 0.52, true), [[foo]])+    eq(libuv.escape_fzf([[\foo]], 0.52, true), [[\foo]])+    eq(libuv.escape_fzf([[\\foo]], 0.52, true), [[\\foo]])+    eq(libuv.escape_fzf([[\\\foo]], 0.52, true), [[\\\foo]])+    eq(libuv.escape_fzf([[\\\\foo]], 0.52, true), [[\\\\foo]])+    eq(libuv.escape_fzf([[foo\]], 0.52, true), [[foo\]])+    eq(libuv.escape_fzf([[foo\\]], 0.52, true), [[foo\\]])   end)    it("unescape {q} (win, fzf v0.52)", function()-    assert.are.same(libuv.unescape_fzf([[]], 0.52, true), [[]])-    assert.are.same(libuv.unescape_fzf([[\]], 0.52, true), [[\]])-    assert.are.same(libuv.unescape_fzf([[\\]], 0.52, true), [[\\]])-    assert.are.same(libuv.unescape_fzf([[foo]], 0.52, true), [[foo]])-    assert.are.same(libuv.unescape_fzf([[\foo]], 0.52, true), [[\foo]])-    assert.are.same(libuv.unescape_fzf([[\\foo]], 0.52, true), [[\\foo]])-    assert.are.same(libuv.unescape_fzf([[\\\foo]], 0.52, true), [[\\\foo]])-    assert.are.same(libuv.unescape_fzf([[\\\\foo]], 0.52, true), [[\\\\foo]])-    assert.are.same(libuv.unescape_fzf([[foo\]], 0.52, true), [[foo\]])-    assert.are.same(libuv.unescape_fzf([[foo\\]], 0.52, true), [[foo\\]])+    eq(libuv.unescape_fzf([[]], 0.52, true), [[]])+    eq(libuv.unescape_fzf([[\]], 0.52, true), [[\]])+    eq(libuv.unescape_fzf([[\\]], 0.52, true), [[\\]])+    eq(libuv.unescape_fzf([[foo]], 0.52, true), [[foo]])+    eq(libuv.unescape_fzf([[\foo]], 0.52, true), [[\foo]])+    eq(libuv.unescape_fzf([[\\foo]], 0.52, true), [[\\foo]])+    eq(libuv.unescape_fzf([[\\\foo]], 0.52, true), [[\\\foo]])+    eq(libuv.unescape_fzf([[\\\\foo]], 0.52, true), [[\\\\foo]])+    eq(libuv.unescape_fzf([[foo\]], 0.52, true), [[foo\]])+    eq(libuv.unescape_fzf([[foo\\]], 0.52, true), [[foo\\]])   end)    it("field index", function()@@ -184,10 +184,10 @@ describe("Testing libuv module", function()     end)()     -- usually new job channel is the last one     local chans = vim.api.nvim_list_chans()-    local job = chans[#chans].id+    local job = (chans[#chans] or {}).id     eq({ 0 }, vim.fn.jobwait({ job }))     eq(0, exit_code)-    assert.are.equal(selected, {+    eq(selected, {       "f", "foo", "foo", "0", "0",       "'f'", "'foo'", "'foo'", "0", "0",       "f", "foo", "foo", "0", "0",

tests/minicons_spec.lua

@@ -1,9 +1,9 @@----@diagnostic disable: unused-local, unused-function+---@diagnostic disable: unused-local, unused-function, unused local MiniTest = require("mini.test") local helpers = require("fzf-lua.test.helpers") local assert = helpers.assert local child = helpers.new_child_neovim()-local expect, eq = helpers.expect, helpers.expect.equality+local eq = helpers.expect.equality local new_set = MiniTest.new_set local exec_lua = child.lua @@ -117,6 +117,7 @@ T["setup"]["headless RPC, vim.g.fzf_lua_server"] = function()   eq(#fzf_lua_server > 0, true)   local headless_child = helpers.new_child_neovim()   headless_child.init()+  ---@diagnostic disable-next-line: preferred-local-alias   headless_child.lua(string.format([==[     _G._fzf_lua_is_headless = true     _G._devicons_path = nil

tests/path_spec.lua

@@ -9,19 +9,19 @@ local eq = assert.are.equal describe("Testing path module", function()   it("separator", function()     utils.__IS_WINDOWS = false-    assert.are.same(path.separator(), "/")-    assert.are.same(path.separator(""), "/")-    assert.are.same(path.separator("~/foo"), "/")-    assert.are.same(path.separator([[~\foo]]), "/")-    assert.are.same(path.separator([[c:\foo]]), "/")+    eq(path.separator(), "/")+    eq(path.separator(""), "/")+    eq(path.separator("~/foo"), "/")+    eq(path.separator([[~\foo]]), "/")+    eq(path.separator([[c:\foo]]), "/")      utils.__IS_WINDOWS = true-    assert.are.same(path.separator(), [[\]])-    assert.are.same(path.separator(""), [[\]])-    assert.are.same(path.separator("~/foo"), "/")-    assert.are.same(path.separator([[~\foo]]), [[\]])-    assert.are.same(path.separator([[c:\foo]]), [[\]])-    assert.are.same(path.separator([[foo\bar]]), [[\]])+    eq(path.separator(), [[\]])+    eq(path.separator(""), [[\]])+    eq(path.separator("~/foo"), "/")+    eq(path.separator([[~\foo]]), [[\]])+    eq(path.separator([[c:\foo]]), [[\]])+    eq(path.separator([[foo\bar]]), [[\]])   end)    it("Ends with separator", function()@@ -44,41 +44,41 @@ describe("Testing path module", function()    it("Add trailing separator", function()     utils.__IS_WINDOWS = false-    assert.are.equal(path.add_trailing(""), "/")-    assert.are.equal(path.add_trailing("/"), "/")-    assert.are.equal(path.add_trailing("/some"), "/some/")-    assert.are.equal(path.add_trailing("/some/"), "/some/")+    eq(path.add_trailing(""), "/")+    eq(path.add_trailing("/"), "/")+    eq(path.add_trailing("/some"), "/some/")+    eq(path.add_trailing("/some/"), "/some/")     utils.__IS_WINDOWS = true-    assert.are.equal(path.add_trailing(""), [[\]])-    assert.are.equal(path.add_trailing("/"), [[/]])-    assert.are.equal(path.add_trailing("/some"), [[/some\]])-    assert.are.equal(path.add_trailing("/some/"), [[/some/]])-    assert.are.equal(path.add_trailing([[C:\some\]]), [[C:\some\]])-    assert.are.equal(path.add_trailing([[C:\some]]), [[C:\some\]])-    assert.are.equal(path.add_trailing([[C:/some]]), [[C:/some/]])-    assert.are.equal(path.add_trailing([[~/some]]), [[~/some/]])-    assert.are.equal(path.add_trailing([[some\path]]), [[some\path\]])+    eq(path.add_trailing(""), [[\]])+    eq(path.add_trailing("/"), [[/]])+    eq(path.add_trailing("/some"), [[/some\]])+    eq(path.add_trailing("/some/"), [[/some/]])+    eq(path.add_trailing([[C:\some\]]), [[C:\some\]])+    eq(path.add_trailing([[C:\some]]), [[C:\some\]])+    eq(path.add_trailing([[C:/some]]), [[C:/some/]])+    eq(path.add_trailing([[~/some]]), [[~/some/]])+    eq(path.add_trailing([[some\path]]), [[some\path\]])   end)    it("Remove trailing separator", function()     utils.__IS_WINDOWS = false-    assert.are.equal(path.remove_trailing(""), "")-    assert.are.equal(path.remove_trailing("/"), "")-    assert.are.equal(path.remove_trailing("//"), "")-    assert.are.equal(path.remove_trailing("/some"), "/some")-    assert.are.equal(path.remove_trailing("/some/"), "/some")-    assert.are.equal(path.remove_trailing("/some/////"), "/some")-    assert.are.equal(path.remove_trailing([[/some\]]), [[/some\]])+    eq(path.remove_trailing(""), "")+    eq(path.remove_trailing("/"), "")+    eq(path.remove_trailing("//"), "")+    eq(path.remove_trailing("/some"), "/some")+    eq(path.remove_trailing("/some/"), "/some")+    eq(path.remove_trailing("/some/////"), "/some")+    eq(path.remove_trailing([[/some\]]), [[/some\]])     utils.__IS_WINDOWS = true-    assert.are.equal(path.remove_trailing(""), "")-    assert.are.equal(path.remove_trailing("/"), "")-    assert.are.equal(path.remove_trailing("//"), "")-    assert.are.equal(path.remove_trailing("/some"), "/some")-    assert.are.equal(path.remove_trailing("/some/"), "/some")-    assert.are.equal(path.remove_trailing("/some/////"), "/some")-    assert.are.equal(path.remove_trailing([[/some\]]), [[/some]])-    assert.are.equal(path.remove_trailing([[C:\some\]]), [[C:\some]])-    assert.are.equal(path.remove_trailing([[C:\some\\\\//]]), [[C:\some]])+    eq(path.remove_trailing(""), "")+    eq(path.remove_trailing("/"), "")+    eq(path.remove_trailing("//"), "")+    eq(path.remove_trailing("/some"), "/some")+    eq(path.remove_trailing("/some/"), "/some")+    eq(path.remove_trailing("/some/////"), "/some")+    eq(path.remove_trailing([[/some\]]), [[/some]])+    eq(path.remove_trailing([[C:\some\]]), [[C:\some]])+    eq(path.remove_trailing([[C:\some\\\\//]]), [[C:\some]])   end)    it("Is absolute", function()@@ -123,76 +123,76 @@ describe("Testing path module", function()    it("Strip cwd prefix", function()     utils.__IS_WINDOWS = false-    assert.are.equal(path.strip_cwd_prefix(""), "")-    assert.are.equal(path.strip_cwd_prefix("./"), "")-    assert.are.equal(path.strip_cwd_prefix([[.\]]), [[.\]])-    assert.are.equal(path.strip_cwd_prefix("/some/path"), "/some/path")-    assert.are.equal(path.strip_cwd_prefix("./some/path/"), "some/path/")+    eq(path.strip_cwd_prefix(""), "")+    eq(path.strip_cwd_prefix("./"), "")+    eq(path.strip_cwd_prefix([[.\]]), [[.\]])+    eq(path.strip_cwd_prefix("/some/path"), "/some/path")+    eq(path.strip_cwd_prefix("./some/path/"), "some/path/")      utils.__IS_WINDOWS = true-    assert.are.equal(path.strip_cwd_prefix(""), "")-    assert.are.equal(path.strip_cwd_prefix("./"), "")-    assert.are.equal(path.strip_cwd_prefix([[.\]]), "")-    assert.are.equal(path.strip_cwd_prefix("/some/path"), "/some/path")-    assert.are.equal(path.strip_cwd_prefix("./some/path/"), "some/path/")-    assert.are.equal(path.strip_cwd_prefix([[.\some\path/]]), [[some\path/]])-    assert.are.equal(path.strip_cwd_prefix([[c:\some\path]]), [[c:\some\path]])+    eq(path.strip_cwd_prefix(""), "")+    eq(path.strip_cwd_prefix("./"), "")+    eq(path.strip_cwd_prefix([[.\]]), "")+    eq(path.strip_cwd_prefix("/some/path"), "/some/path")+    eq(path.strip_cwd_prefix("./some/path/"), "some/path/")+    eq(path.strip_cwd_prefix([[.\some\path/]]), [[some\path/]])+    eq(path.strip_cwd_prefix([[c:\some\path]]), [[c:\some\path]])   end)    it("Tail", function()     utils.__IS_WINDOWS = false-    assert.are.equal(path.tail(""), "")-    assert.are.equal(path.tail("/"), "/")-    assert.are.equal(path.tail("foo"), "foo")-    assert.are.equal(path.tail(".foo"), ".foo")-    assert.are.equal(path.tail("/foo"), "foo")-    assert.are.equal(path.tail("/foo/"), "foo/")-    assert.are.equal(path.tail("/foo/bar"), "bar")-    assert.are.equal(path.tail([[/foo\bar]]), [[foo\bar]])+    eq(path.tail(""), "")+    eq(path.tail("/"), "/")+    eq(path.tail("foo"), "foo")+    eq(path.tail(".foo"), ".foo")+    eq(path.tail("/foo"), "foo")+    eq(path.tail("/foo/"), "foo/")+    eq(path.tail("/foo/bar"), "bar")+    eq(path.tail([[/foo\bar]]), [[foo\bar]])      utils.__IS_WINDOWS = true-    assert.are.equal(path.tail(""), "")-    assert.are.equal(path.tail("/"), "/")-    assert.are.equal(path.tail([[\]]), [[\]])-    assert.are.equal(path.tail("foo"), "foo")-    assert.are.equal(path.tail(".foo"), ".foo")-    assert.are.equal(path.tail([[c:\foo]]), "foo")-    assert.are.equal(path.tail([[c:\foo\]]), [[foo\]])-    assert.are.equal(path.tail([[c:\foo\bar]]), "bar")-    assert.are.equal(path.tail([[c:/foo\bar]]), "bar")-    assert.are.equal(path.tail([[c:/foo//\//bar]]), "bar")+    eq(path.tail(""), "")+    eq(path.tail("/"), "/")+    eq(path.tail([[\]]), [[\]])+    eq(path.tail("foo"), "foo")+    eq(path.tail(".foo"), ".foo")+    eq(path.tail([[c:\foo]]), "foo")+    eq(path.tail([[c:\foo\]]), [[foo\]])+    eq(path.tail([[c:\foo\bar]]), "bar")+    eq(path.tail([[c:/foo\bar]]), "bar")+    eq(path.tail([[c:/foo//\//bar]]), "bar")   end)    it("Parent", function()     utils.__IS_WINDOWS = false-    assert.are.equal(path.parent(""), nil)-    assert.are.equal(path.parent("/"), nil)-    assert.are.equal(path.parent("/foo"), "/")-    assert.are.equal(path.parent("/foo/bar"), "/foo/")-    assert.are.equal(path.parent("/foo/bar", true), "/foo")-    assert.are.equal(path.parent([[/foo\bar]]), [[/]])+    eq(path.parent(""), nil)+    eq(path.parent("/"), nil)+    eq(path.parent("/foo"), "/")+    eq(path.parent("/foo/bar"), "/foo/")+    eq(path.parent("/foo/bar", true), "/foo")+    eq(path.parent([[/foo\bar]]), [[/]])      utils.__IS_WINDOWS = true-    assert.are.equal(path.parent(""), nil)-    assert.are.equal(path.parent("/"), nil)-    assert.are.equal(path.parent([[\]]), nil)-    assert.are.equal(path.parent([[c:]]), nil)-    assert.are.equal(path.parent([[c:\foo]]), [[c:\]])-    assert.are.equal(path.parent([[c:\foo]], true), [[c:]])-    assert.are.equal(path.parent([[c:\foo\bar]]), [[c:\foo\]])-    assert.are.equal(path.parent([[c:\foo/bar]]), [[c:\foo/]])-    assert.are.equal(path.parent([[c:/foo//\//bar]], true), [[c:/foo]])+    eq(path.parent(""), nil)+    eq(path.parent("/"), nil)+    eq(path.parent([[\]]), nil)+    eq(path.parent([[c:]]), nil)+    eq(path.parent([[c:\foo]]), [[c:\]])+    eq(path.parent([[c:\foo]], true), [[c:]])+    eq(path.parent([[c:\foo\bar]]), [[c:\foo\]])+    eq(path.parent([[c:\foo/bar]]), [[c:\foo/]])+    eq(path.parent([[c:/foo//\//bar]], true), [[c:/foo]])   end)    it("Normalize", function()     utils.__IS_WINDOWS = false-    assert.are.equal(path.normalize("/some/path"), "/some/path")-    assert.are.equal(path.normalize([[\some\path]]), [[\some\path]])-    assert.are.equal(path.normalize("~/some/path"), path.HOME() .. "/some/path")+    eq(path.normalize("/some/path"), "/some/path")+    eq(path.normalize([[\some\path]]), [[\some\path]])+    eq(path.normalize("~/some/path"), path.HOME() .. "/some/path")     utils.__IS_WINDOWS = true-    assert.are.equal(path.normalize("/some/path"), "/some/path")-    assert.are.equal(path.normalize([[\some\path]]), "/some/path")-    assert.are.equal(path.normalize("~/some/path"), path.normalize(path.HOME()) .. "/some/path")+    eq(path.normalize("/some/path"), "/some/path")+    eq(path.normalize([[\some\path]]), "/some/path")+    eq(path.normalize("~/some/path"), path.normalize(path.HOME()) .. "/some/path")   end)    it("Equals", function()@@ -261,27 +261,27 @@ describe("Testing path module", function()     }     utils.__IS_WINDOWS = false     for _, v in ipairs(unix) do-      assert.are.same({ path.is_relative_to(v[1], v[2]) }, v[3])+      eq({ path.is_relative_to(v[1], v[2]) }, v[3])       -- mini.nvim shim support 2 args only       -- string.format('\n\nis_relative_to("%s", "%s") ~= "%s"\n', v[1], v[2], v[3][2])     end     utils.__IS_WINDOWS = true     for _, v in ipairs(win) do-      assert.are.same({ path.is_relative_to(v[1], v[2]) }, v[3])+      eq({ path.is_relative_to(v[1], v[2]) }, v[3])       -- string.format('\n\nis_relative_to("%s", "%s") ~= "%s"\n', v[1], v[2], v[3][2])     end   end)    it("Extension", function()     utils.__IS_WINDOWS = false-    assert.are.equal(path.extension("/some/path/foobar"), nil)-    assert.are.equal(path.extension("/some/pa.th/foobar"), nil)+    eq(path.extension("/some/path/foobar"), nil)+    eq(path.extension("/some/pa.th/foobar"), nil)     assert.is.same(path.extension("/some/path/foobar."), "")     assert.is.same(path.extension("/some/path/foo.bar"), "bar")     assert.is.same(path.extension("/some/path/foo.bar.baz"), "baz")     assert.is.same(path.extension("/some/path/.foobar"), "foobar")     -- override that doesn't "tail" the path-    assert.are.equal(path.extension("/some/pa.th/foobar", true), "th/foobar")+    eq(path.extension("/some/pa.th/foobar", true), "th/foobar")   end)    it("Join", function()@@ -309,50 +309,50 @@ describe("Testing path module", function()    it("Shorten", function()     utils.__IS_WINDOWS = false-    assert.are.equal(path.shorten(""), "")-    assert.are.equal(path.shorten("/"), "/")-    assert.are.equal(path.shorten("/foo"), "/foo")-    assert.are.equal(path.shorten("/foo/"), "/f/")-    assert.are.equal(path.shorten("/foo/bar"), "/f/bar")-    assert.are.equal(path.shorten("/foo/bar/baz"), "/f/b/baz")-    assert.are.equal(path.shorten("~/foo/bar/baz"), "~/f/b/baz")-    assert.are.equal(path.shorten("~/foo/bar/baz/"), "~/f/b/b/")-    assert.are.equal(path.shorten("~/foo/bar/baz//"), "~/f/b/b//")-    assert.are.equal(path.shorten("~/.foo/.bar/baz"), "~/.f/.b/baz")-    assert.are.equal(path.shorten("~/foo/bar/baz", 2), "~/fo/ba/baz")-    assert.are.equal(path.shorten("~/fo/barrr/baz", 3), "~/fo/bar/baz")-    assert.are.equal(path.shorten([[/foo\bar]]), [[/foo\bar]])+    eq(path.shorten(""), "")+    eq(path.shorten("/"), "/")+    eq(path.shorten("/foo"), "/foo")+    eq(path.shorten("/foo/"), "/f/")+    eq(path.shorten("/foo/bar"), "/f/bar")+    eq(path.shorten("/foo/bar/baz"), "/f/b/baz")+    eq(path.shorten("~/foo/bar/baz"), "~/f/b/baz")+    eq(path.shorten("~/foo/bar/baz/"), "~/f/b/b/")+    eq(path.shorten("~/foo/bar/baz//"), "~/f/b/b//")+    eq(path.shorten("~/.foo/.bar/baz"), "~/.f/.b/baz")+    eq(path.shorten("~/foo/bar/baz", 2), "~/fo/ba/baz")+    eq(path.shorten("~/fo/barrr/baz", 3), "~/fo/bar/baz")+    eq(path.shorten([[/foo\bar]]), [[/foo\bar]])     -- multibyte characters-    assert.are.equal(path.shorten("/ñab/bar"), "/ñ/bar")-    assert.are.equal(path.shorten("/אבגד/bar"), "/א/bar")-    assert.are.equal(path.shorten("/こんにちは/bar"), "/こ/bar")-    assert.are.equal(vim.fn.pathshorten("/ñab/bar"), path.shorten("/ñab/bar"))-    assert.are.equal(vim.fn.pathshorten("/אבגד/bar"), path.shorten("/אבגד/bar"))-    assert.are.equal(vim.fn.pathshorten("/こんにちは/bar"), path.shorten("/こんにちは/bar"))+    eq(path.shorten("/ñab/bar"), "/ñ/bar")+    eq(path.shorten("/אבגד/bar"), "/א/bar")+    eq(path.shorten("/こんにちは/bar"), "/こ/bar")+    eq(vim.fn.pathshorten("/ñab/bar"), path.shorten("/ñab/bar"))+    eq(vim.fn.pathshorten("/אבגד/bar"), path.shorten("/אבגד/bar"))+    eq(vim.fn.pathshorten("/こんにちは/bar"), path.shorten("/こんにちは/bar"))      utils.__IS_WINDOWS = true-    assert.are.equal(path.shorten("/foo"), [[\foo]])-    assert.are.equal(path.shorten([[/foo\bar]]), [[\f\bar]])-    assert.are.equal(path.shorten([[/foo/bar]]), [[\f\bar]])-    assert.are.equal(path.shorten([[/foo/bar\baz]]), [[\f\b\baz]])-    assert.are.equal(path.shorten([[\]]), [[\]])-    assert.are.equal(path.shorten([[c:/]]), [[c:/]])-    assert.are.equal(path.shorten([[c:\]]), [[c:\]])-    assert.are.equal(path.shorten([[c:\foo]]), [[c:\foo]])-    assert.are.equal(path.shorten([[c:\foo\bar]]), [[c:\f\bar]])-    assert.are.equal(path.shorten([[c:\foo\bar\baz]]), [[c:\f\b\baz]])-    assert.are.equal(path.shorten([[c:\.foo\.bar\baz]]), [[c:\.f\.b\baz]])-    assert.are.equal(path.shorten([[c:/foo\bar]]), [[c:/f/bar]])-    assert.are.equal(path.shorten([[~/foo/bar]]), [[~/f/bar]])-    assert.are.equal(path.shorten([[~\foo\bar]]), [[~\f\bar]])-    assert.are.equal(path.shorten([[~\foo/bar]]), [[~\f\bar]])-    assert.are.equal(path.shorten([[~\foo\bar\]]), [[~\f\b\]])+    eq(path.shorten("/foo"), [[\foo]])+    eq(path.shorten([[/foo\bar]]), [[\f\bar]])+    eq(path.shorten([[/foo/bar]]), [[\f\bar]])+    eq(path.shorten([[/foo/bar\baz]]), [[\f\b\baz]])+    eq(path.shorten([[\]]), [[\]])+    eq(path.shorten([[c:/]]), [[c:/]])+    eq(path.shorten([[c:\]]), [[c:\]])+    eq(path.shorten([[c:\foo]]), [[c:\foo]])+    eq(path.shorten([[c:\foo\bar]]), [[c:\f\bar]])+    eq(path.shorten([[c:\foo\bar\baz]]), [[c:\f\b\baz]])+    eq(path.shorten([[c:\.foo\.bar\baz]]), [[c:\.f\.b\baz]])+    eq(path.shorten([[c:/foo\bar]]), [[c:/f/bar]])+    eq(path.shorten([[~/foo/bar]]), [[~/f/bar]])+    eq(path.shorten([[~\foo\bar]]), [[~\f\bar]])+    eq(path.shorten([[~\foo/bar]]), [[~\f\bar]])+    eq(path.shorten([[~\foo\bar\]]), [[~\f\b\]])     -- override separator auto-detect-    assert.are.equal(path.shorten([[c:\foo\bar]], nil, [[/]]), [[c:/f/bar]])-    assert.are.equal(path.shorten([[c:/foo\bar]], nil, [[\]]), [[c:\f\bar]])+    eq(path.shorten([[c:\foo\bar]], nil, [[/]]), [[c:/f/bar]])+    eq(path.shorten([[c:/foo\bar]], nil, [[\]]), [[c:\f\bar]])     -- shorten len-    assert.are.equal(path.shorten([[c:\foo\bar\baz]], 2), [[c:\fo\ba\baz]])-    assert.are.equal(path.shorten([[c:/foo\bar\baz]], 2), [[c:/fo/ba/baz]])+    eq(path.shorten([[c:\foo\bar\baz]], 2), [[c:\fo\ba\baz]])+    eq(path.shorten([[c:/foo\bar\baz]], 2), [[c:/fo/ba/baz]])     utils.__IS_WINDOWS = nil   end) @@ -454,7 +454,10 @@ describe("Testing path module", function()       local r = {         col = 1,         line = 1,-        range = { start = { character = 0, line = 0 } },+        range = {+          start = { character = 0, line = 0 },+          ["end"] = { character = 0, line = 0 },+        },         stripped = "file:///tmp/test.txt:5:6"       }       eq(path.entry_to_file("/tmp/test.txt:5:6", {}, true), r)

tests/shell_spec.lua

@@ -12,6 +12,7 @@ describe("Testing shell module", function()      err(shell.check_upvalue, (function()       local upvalue+      ---@diagnostic disable-next-line: undefined-field       return function() return upvalue.index end     end)(), "index upvalue") 

tests/utils_spec.lua

@@ -8,99 +8,100 @@ local utils = fzf.utils describe("Testing utils module", function()   it("separator", function()     utils.__IS_WINDOWS = false-    assert.are.same(utils._if_win_normalize_vars("--w=$COLUMNS"), "--w=$COLUMNS")+    eq(utils._if_win_normalize_vars("--w=$COLUMNS"), "--w=$COLUMNS")      utils.__IS_WINDOWS = true-    assert.are.same(utils._if_win_normalize_vars("--w=$COLUMNS", 1), "--w=%COLUMNS%")-    assert.are.same(utils._if_win_normalize_vars("--w=%COLUMNS%", 1), "--w=%COLUMNS%")-    assert.are.same(utils._if_win_normalize_vars("-w=$C -l=$L", 1), "-w=%C% -l=%L%")-    assert.are.same(utils._if_win_normalize_vars("--w=$COLUMNS", 2), "--w=!COLUMNS!")-    assert.are.same(utils._if_win_normalize_vars("--w=%COLUMNS%", 2), "--w=!COLUMNS!")-    assert.are.same(utils._if_win_normalize_vars("-w=$C -l=$L", 2), "-w=!C! -l=!L!")+    eq(utils._if_win_normalize_vars("--w=$COLUMNS", 1), "--w=%COLUMNS%")+    eq(utils._if_win_normalize_vars("--w=%COLUMNS%", 1), "--w=%COLUMNS%")+    eq(utils._if_win_normalize_vars("-w=$C -l=$L", 1), "-w=%C% -l=%L%")+    eq(utils._if_win_normalize_vars("--w=$COLUMNS", 2), "--w=!COLUMNS!")+    eq(utils._if_win_normalize_vars("--w=%COLUMNS%", 2), "--w=!COLUMNS!")+    eq(utils._if_win_normalize_vars("-w=$C -l=$L", 2), "-w=!C! -l=!L!")     utils.__IS_WINDOWS = nil   end)    it("version formatter", function()-    assert.are.same(utils.ver2str(), nil)-    assert.are.same(utils.ver2str(""), nil)-    assert.are.same(utils.ver2str({}), nil)-    assert.are.same(utils.ver2str({ 0 }), "0.0.0")-    assert.are.same(utils.ver2str({ 1 }), "1.0.0")-    assert.are.same(utils.ver2str({ 1, 2 }), "1.2.0")-    assert.are.same(utils.ver2str({ 0, 1, 2 }), "0.1.2")-    assert.are.same(utils.ver2str({ 1, 2, 3 }), "1.2.3")+    eq(utils.ver2str(), nil)+    eq(utils.ver2str(""), nil)+    eq(utils.ver2str({}), nil)+    eq(utils.ver2str({ 0 }), "0.0.0")+    eq(utils.ver2str({ 1 }), "1.0.0")+    eq(utils.ver2str({ 1, 2 }), "1.2.0")+    eq(utils.ver2str({ 0, 1, 2 }), "0.1.2")+    eq(utils.ver2str({ 1, 2, 3 }), "1.2.3")   end)    it("version parser", function()-    assert.are.same(utils.parse_verstr(), nil)      -- Invalid-    assert.are.same(utils.parse_verstr(""), nil)    -- Invalid-    assert.are.same(utils.parse_verstr("0"), nil)   -- Invalid-    assert.are.same(utils.parse_verstr("all"), nil) -- Invalid-    assert.are.same(utils.parse_verstr("HEAD"), { 100, 0, 0 })-    assert.are.same(utils.parse_verstr("0.5"), { 0, 5, 0 })-    assert.are.same(utils.parse_verstr("0.5.0"), { 0, 5, 0 })-    assert.are.same(utils.parse_verstr("0.56"), { 0, 56, 0 })-    assert.are.same(utils.parse_verstr("0.56.3"), { 0, 56, 3 })-    assert.are.same(utils.parse_verstr("01.56.03"), { 1, 56, 3 })-    assert.are.same(utils.parse_verstr("10.56.30"), { 10, 56, 30 })+    eq(utils.parse_verstr(), nil)      -- Invalid+    eq(utils.parse_verstr(""), nil)    -- Invalid+    eq(utils.parse_verstr("0"), nil)   -- Invalid+    eq(utils.parse_verstr("all"), nil) -- Invalid+    eq(utils.parse_verstr("HEAD"), { 100, 0, 0 })+    eq(utils.parse_verstr("0.5"), { 0, 5, 0 })+    eq(utils.parse_verstr("0.5.0"), { 0, 5, 0 })+    eq(utils.parse_verstr("0.56"), { 0, 56, 0 })+    eq(utils.parse_verstr("0.56.3"), { 0, 56, 3 })+    eq(utils.parse_verstr("01.56.03"), { 1, 56, 3 })+    eq(utils.parse_verstr("10.56.30"), { 10, 56, 30 })   end)    it("has", function()-    assert.are.same(utils.has({}), false)-    assert.are.same(utils.has({}, "fzf"), false)-    assert.are.same(utils.has({ __SK_VERSION = {} }, "sk"), true)-    assert.are.same(utils.has({ __FZF_VERSION = {} }, "fzf"), true)-    assert.are.same(utils.has({ __FZF_VERSION = {} }, "sk"), false)-    assert.are.same(utils.has({ __SK_VERSION = {} }, "fzf"), false)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", ""), false)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", "0"), false)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", "0.1"), true)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", "0.4.9"), true)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 15, 5 } }, "sk", "0.15"), true)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 15, 5 } }, "sk", "0.15.0"), true)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 15, 5 } }, "sk", "0.15.5"), true)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 15, 5 } }, "sk", "0.15.6"), false)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", "0.16"), false)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0, 5, 0 }), true)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0, 6, 0 }), false)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0, 5 }), true)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0, 6 }), false)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0 }), true)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0 }), true)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 1 }), false)-    assert.are.same(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "fzf", "0.5"), false)-    assert.are.same(utils.has({ __FZF_VERSION = { 1, 5, 0 } }, "fzf", "1.4"), true)-    assert.are.same(utils.has({ __FZF_VERSION = { 1, 5, 0 } }, "fzf", "1.5.0"), true)-    assert.are.same(utils.has({ __FZF_VERSION = { 0, 0, 5 } }, "fzf", "0.0.4"), true)-    assert.are.same(utils.has({ __FZF_VERSION = { 0, 0, 5 } }, "fzf", "0.0.5"), true)-    assert.are.same(utils.has({ __FZF_VERSION = { 0, 0, 5 } }, "fzf", "0.0.6"), false)-    assert.are.same(utils.has({ __FZF_VERSION = { 0, 5, 5 } }, "fzf", "0.5.4"), true)-    assert.are.same(utils.has({ __FZF_VERSION = { 0, 5, 5 } }, "fzf", "0.0.5"), true)-    assert.are.same(utils.has({ __FZF_VERSION = { 0, 5, 5 } }, "fzf", "0.5.6"), false)-    assert.are.same(utils.has({ __FZF_VERSION = { 2, 5, 5 } }, "fzf", "2.5.4"), true)-    assert.are.same(utils.has({ __FZF_VERSION = { 2, 5, 5 } }, "fzf", "2.5.5"), true)-    assert.are.same(utils.has({ __FZF_VERSION = { 2, 5, 5 } }, "fzf", "2.5.6"), false)+    eq(utils.has({}), false)+    eq(utils.has({}, "fzf"), false)+    eq(utils.has({ __SK_VERSION = {} }, "sk"), true)+    eq(utils.has({ __FZF_VERSION = {} }, "fzf"), true)+    eq(utils.has({ __FZF_VERSION = {} }, "sk"), false)+    eq(utils.has({ __SK_VERSION = {} }, "fzf"), false)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", ""), false)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", "0"), false)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", "0.1"), true)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", "0.4.9"), true)+    eq(utils.has({ __SK_VERSION = { 0, 15, 5 } }, "sk", "0.15"), true)+    eq(utils.has({ __SK_VERSION = { 0, 15, 5 } }, "sk", "0.15.0"), true)+    eq(utils.has({ __SK_VERSION = { 0, 15, 5 } }, "sk", "0.15.5"), true)+    eq(utils.has({ __SK_VERSION = { 0, 15, 5 } }, "sk", "0.15.6"), false)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", "0.16"), false)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0, 5, 0 }), true)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0, 6, 0 }), false)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0, 5 }), true)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0, 6 }), false)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0 }), true)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 0 }), true)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "sk", { 1 }), false)+    eq(utils.has({ __SK_VERSION = { 0, 5, 0 } }, "fzf", "0.5"), false)+    eq(utils.has({ __FZF_VERSION = { 1, 5, 0 } }, "fzf", "1.4"), true)+    eq(utils.has({ __FZF_VERSION = { 1, 5, 0 } }, "fzf", "1.5.0"), true)+    eq(utils.has({ __FZF_VERSION = { 0, 0, 5 } }, "fzf", "0.0.4"), true)+    eq(utils.has({ __FZF_VERSION = { 0, 0, 5 } }, "fzf", "0.0.5"), true)+    eq(utils.has({ __FZF_VERSION = { 0, 0, 5 } }, "fzf", "0.0.6"), false)+    eq(utils.has({ __FZF_VERSION = { 0, 5, 5 } }, "fzf", "0.5.4"), true)+    eq(utils.has({ __FZF_VERSION = { 0, 5, 5 } }, "fzf", "0.0.5"), true)+    eq(utils.has({ __FZF_VERSION = { 0, 5, 5 } }, "fzf", "0.5.6"), false)+    eq(utils.has({ __FZF_VERSION = { 2, 5, 5 } }, "fzf", "2.5.4"), true)+    eq(utils.has({ __FZF_VERSION = { 2, 5, 5 } }, "fzf", "2.5.5"), true)+    eq(utils.has({ __FZF_VERSION = { 2, 5, 5 } }, "fzf", "2.5.6"), false)   end)    it("setmetatable with gc", function()     local gc_called = nil     local _obj = utils.setmetatable({}, { __gc = function() gc_called = true end })-    assert.are.same(gc_called, nil)+    eq(gc_called, nil)+    ---@diagnostic disable-next-line: assign-type-mismatch     _obj = nil     collectgarbage("collect")-    assert.are.same(gc_called, true)+    eq(gc_called, true)   end)    it("wo", function()     utils.wo.nonexist = "this is nop"-    assert.are.same(nil, utils.wo.nonexist)+    eq(nil, utils.wo.nonexist)     vim.wo[0][0].nu = true -- setlocal     vim.wo[0].rnu = true   -- setglobal-    assert.are.same(vim.wo[0][0].nu, vim.wo.nu)-    assert.are.same(vim.wo[0][0].rnu, vim.wo.rnu)+    eq(vim.wo[0][0].nu, vim.wo.nu)+    eq(vim.wo[0][0].rnu, vim.wo.rnu)     vim.cmd.new()-    assert.are.same(vim.wo[0][0].nu, vim.wo.nu)-    assert.are.same(vim.wo[0][0].rnu, vim.wo.rnu)+    eq(vim.wo[0][0].nu, vim.wo.nu)+    eq(vim.wo[0][0].rnu, vim.wo.rnu)   end)    it("strsplit", function()

tests/win_spec.lua

@@ -1,8 +1,8 @@----@diagnostic disable: unused-local, unused-function+---@diagnostic disable: unused-local, unused-function, unused local MiniTest = require("mini.test") local helpers = require("fzf-lua.test.helpers") local child = helpers.new_child_neovim()-local expect, eq = helpers.expect, helpers.expect.equality+local eq = helpers.expect.equality local new_set = MiniTest.new_set local exec_lua = child.lua @@ -133,7 +133,7 @@ end T["win"]["keymap"] = new_set({ n_retry = not helpers.IS_LINUX() and 5 or nil })  T["win"]["keymap"]["no error"] = new_set({-  parametrize = vim.iter(require("fzf-lua.defaults").defaults.keymap.builtin)+  parametrize = vim.iter(assert(require("fzf-lua.defaults").defaults.keymap).builtin)       :map(function(key, action) return { key, action } end)       :totable() }, {