perf(picker): small optims for abort

This commit is contained in:
Folke Lemaitre 2025-01-21 12:16:14 +01:00
parent d283d9e182
commit 317a2093ea
No known key found for this signature in database
GPG key ID: 41F8B1FBACAE2040
7 changed files with 30 additions and 13 deletions

View file

@ -5,7 +5,6 @@ local Async = require("snacks.picker.util.async")
---@field task snacks.picker.Async
---@field items snacks.picker.finder.Item[]
---@field filter? snacks.picker.Filter
---@field has_scores? boolean
local M = {}
M.__index = M
@ -46,7 +45,6 @@ function M:run(picker)
local default_score = require("snacks.picker.core.matcher").DEFAULT_SCORE
self.task:abort()
self.items = {}
self.has_scores = false
local yield ---@type fun()
self.filter = picker.input.filter:clone({ trim = true })
local finder = self._find(picker.opts, self.filter)
@ -56,7 +54,6 @@ function M:run(picker)
local function add(item)
item.idx, item.score = #self.items + 1, default_score
self.items[item.idx] = item
self.has_scores = self.has_scores or item.score_add ~= nil
end
-- PERF: if finder is a table, we can skip the async part
@ -89,8 +86,10 @@ function M:run(picker)
end, async)
end):on("done", function()
collectgarbage("restart")
picker.matcher.task:resume()
picker:update()
if not self.task:aborted() then
picker.matcher.task:resume()
picker:update()
end
end)
end

View file

@ -470,10 +470,11 @@ function M:close()
end
self.layout:close()
self.updater:stop()
self.finder:abort()
self.matcher:abort()
M._active[self] = nil
vim.schedule(function()
self.matcher:abort()
self.finder:abort()
-- order matters!
self.input:close()
self.preview:close()
end)

View file

@ -108,7 +108,7 @@ function M.files(opts, filter)
return require("snacks.picker.source.proc").proc(vim.tbl_deep_extend("force", {
cmd = cmd,
args = args,
notify = false,
notify = not opts.live,
---@param item snacks.picker.finder.Item
transform = function(item)
item.cwd = cwd

View file

@ -108,7 +108,7 @@ function M.grep(opts, filter)
local cwd = not absolute and vim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil
local cmd, args = get_cmd(opts, filter)
return require("snacks.picker.source.proc").proc(vim.tbl_deep_extend("force", {
notify = false,
notify = not opts.live,
cmd = cmd,
args = args,
---@param item snacks.picker.finder.Item

View file

@ -31,6 +31,7 @@ function M.proc(opts)
end
end
end
local aborted = false
local stdout = assert(uv.new_pipe())
opts = vim.tbl_deep_extend("force", {}, opts or {}, {
@ -44,7 +45,7 @@ function M.proc(opts)
if not aborted and code ~= 0 and opts.notify ~= false then
local full = { opts.cmd or "" }
vim.list_extend(full, opts.args or {})
return Snacks.notify.error(("Command failed:\n- cmd: `%s`"):format(table.concat(full, " ")))
Snacks.notify.error(("Command failed:\n- cmd: `%s`"):format(table.concat(full, " ")))
end
stdout:close()
handle:close()
@ -55,9 +56,12 @@ function M.proc(opts)
end
local prev ---@type string?
local queue = require("snacks.picker.util.queue").new()
self:on("abort", function()
aborted = true
queue:clear()
cb = function() end
if not handle:is_closing() then
handle:kill("sigterm")
vim.defer_fn(function()
@ -97,9 +101,10 @@ function M.proc(opts)
end
end
local queue = require("snacks.picker.util.queue").new()
stdout:read_start(function(err, data)
if aborted then
return
end
assert(not err, err)
if M.USE_QUEUE then
queue:push(data)

View file

@ -58,9 +58,17 @@ function Async:init(fn)
return M.add(self)
end
function Async:aborted()
return self._aborted
end
function Async:_done()
if self._co == nil then
return
end
self:_emit("done")
self._fn = nil
M._threads[self._co] = nil
self._co = nil
self._on = {}
end

View file

@ -9,7 +9,7 @@ M.__index = M
function M.new()
local self = setmetatable({}, M)
self.first, self.last, self.queue = 0, -1, {}
self:clear()
return self
end
@ -26,6 +26,10 @@ function M:empty()
return self:size() == 0
end
function M:clear()
self.first, self.last, self.queue = 0, -1, {}
end
function M:pop()
if self:empty() then
return