mirror of
https://github.com/folke/snacks.nvim
synced 2025-08-04 10:49:08 +00:00
refactor: move all dashboard tracing to debug
This commit is contained in:
parent
9c0d2e2e93
commit
143c244346
2 changed files with 79 additions and 55 deletions
|
@ -201,39 +201,20 @@ local D = {}
|
|||
function M.open(opts)
|
||||
local self = setmetatable({}, { __index = D })
|
||||
self.opts = Snacks.config.get("dashboard", defaults, opts) --[[@as snacks.dashboard.Opts]]
|
||||
self:trace("buf/win")
|
||||
self.buf = self.opts.buf or vim.api.nvim_create_buf(false, true)
|
||||
self.win = self.opts.win or Snacks.win({ style = "dashboard", buf = self.buf, enter = true }).win --[[@as number]]
|
||||
self:trace() -- buf/win
|
||||
self:trace("dashboard")
|
||||
self:trace("init")
|
||||
self:init()
|
||||
self:trace() -- init
|
||||
self:update()
|
||||
self:trace() -- dashboard
|
||||
if self.opts.debug then
|
||||
Snacks.debug.stats({ min = 0.2 })
|
||||
end
|
||||
self:fire("Opened")
|
||||
return self
|
||||
end
|
||||
|
||||
---@param name? string
|
||||
function D:trace(name)
|
||||
return self.opts.debug and Snacks.debug.trace(name)
|
||||
return self.opts.debug and Snacks.debug.trace(name and ("dashboard:" .. name) or nil)
|
||||
end
|
||||
|
||||
function D:init()
|
||||
if self.opts.debug then -- track initial load of icon provider
|
||||
local icon = M.icon
|
||||
M.icon = function(...)
|
||||
self:trace("icon-provider")
|
||||
local ret = icon(...)
|
||||
self:trace()
|
||||
M.icon = icon
|
||||
return ret
|
||||
end
|
||||
end
|
||||
vim.api.nvim_win_set_buf(self.win, self.buf)
|
||||
vim.o.ei = "all"
|
||||
Snacks.util.wo(self.win, Snacks.config.styles.dashboard.wo)
|
||||
|
@ -469,7 +450,7 @@ function D:resolve(item, results, parent)
|
|||
table.insert(results, { title = item.title, icon = item.icon, pane = item.pane })
|
||||
end
|
||||
if item.section then -- add section items
|
||||
self:trace(item.section)
|
||||
self:trace("resolve." .. item.section)
|
||||
local items = M.sections[item.section](item) ---@type snacks.dashboard.Section?
|
||||
self:resolve(items, results, item)
|
||||
self:trace()
|
||||
|
@ -505,9 +486,7 @@ function D:padding(item)
|
|||
end
|
||||
|
||||
function D:fire(event)
|
||||
self:trace(event)
|
||||
vim.api.nvim_exec_autocmds("User", { pattern = "SnacksDashboard" .. event, modeline = false })
|
||||
self:trace()
|
||||
end
|
||||
|
||||
function D:on(event, cb)
|
||||
|
@ -549,7 +528,6 @@ end
|
|||
|
||||
-- Layout in panes
|
||||
function D:layout()
|
||||
self:trace("layout")
|
||||
local max_panes =
|
||||
math.max(1, math.floor((self._size.width + self.opts.pane_gap) / (self.opts.width + self.opts.pane_gap)))
|
||||
self.panes = {} ---@type snacks.dashboard.Item[][]
|
||||
|
@ -562,17 +540,14 @@ function D:layout()
|
|||
for p = 1, math.max(unpack(vim.tbl_keys(self.panes))) or 1 do
|
||||
self.panes[p] = self.panes[p] or {}
|
||||
end
|
||||
self:trace()
|
||||
end
|
||||
|
||||
-- Format and render the dashboard
|
||||
function D:render()
|
||||
self:trace("render")
|
||||
-- horizontal position
|
||||
self.col = self.opts.col
|
||||
or math.floor(self._size.width - (self.opts.width * #self.panes + self.opts.pane_gap * (#self.panes - 1))) / 2
|
||||
|
||||
self:trace("format")
|
||||
self.lines = {} ---@type string[]
|
||||
local extmarks = {} ---@type {row:number, col:number, opts:vim.api.keyset.set_extmark}[]
|
||||
for p, pane in ipairs(self.panes) do
|
||||
|
@ -605,7 +580,6 @@ function D:render()
|
|||
end
|
||||
end
|
||||
end
|
||||
self:trace() -- format
|
||||
|
||||
-- vertical position
|
||||
self.row = self.opts.row or math.max(math.floor((self._size.height - #self.lines) / 2), 0)
|
||||
|
@ -623,7 +597,11 @@ function D:render()
|
|||
end
|
||||
end
|
||||
|
||||
self:trace("lines/extmarks")
|
||||
self:render_buf(extmarks)
|
||||
end
|
||||
|
||||
---@param extmarks {row:number, col:number, opts:vim.api.keyset.set_extmark}[]
|
||||
function D:render_buf(extmarks)
|
||||
-- set lines
|
||||
vim.bo[self.buf].modifiable = true
|
||||
vim.api.nvim_buf_set_lines(self.buf, 0, -1, false, self.lines)
|
||||
|
@ -634,12 +612,9 @@ function D:render()
|
|||
for _, extmark in ipairs(extmarks) do
|
||||
vim.api.nvim_buf_set_extmark(self.buf, M.ns, extmark.row + self.row, extmark.col, extmark.opts)
|
||||
end
|
||||
self:trace() -- lines/extmarks
|
||||
self:trace() -- render
|
||||
end
|
||||
|
||||
function D:keys()
|
||||
self:trace("keys")
|
||||
local autokeys = self.opts.autokeys:gsub("[hjklq]", "")
|
||||
for _, item in ipairs(self.items) do
|
||||
if item.key and not item.autokey then
|
||||
|
@ -656,18 +631,13 @@ function D:keys()
|
|||
end, { buffer = self.buf, nowait = not item.autokey, desc = "Dashboard action" })
|
||||
end
|
||||
end
|
||||
self:trace()
|
||||
end
|
||||
|
||||
function D:update()
|
||||
self:trace("update")
|
||||
|
||||
self:fire("UpdatePre")
|
||||
self._size = self:size()
|
||||
|
||||
self:trace("items")
|
||||
self.items = self:resolve(self.opts.sections)
|
||||
self:trace() -- items
|
||||
|
||||
self:layout()
|
||||
self:keys()
|
||||
|
@ -701,7 +671,6 @@ function D:update()
|
|||
end,
|
||||
})
|
||||
self:fire("UpdatePost")
|
||||
self:trace() -- update
|
||||
end
|
||||
|
||||
-- Get an icon
|
||||
|
@ -1050,6 +1019,11 @@ function M.setup()
|
|||
end
|
||||
M.status.opened = true
|
||||
|
||||
if Snacks.config.dashboard.debug then
|
||||
Snacks.debug.tracemod("dashboard", M)
|
||||
Snacks.debug.tracemod("dashboard", D, ":")
|
||||
end
|
||||
|
||||
local options = { showtabline = vim.o.showtabline, laststatus = vim.o.laststatus }
|
||||
vim.o.showtabline, vim.o.laststatus = 0, 0
|
||||
M.open({ buf = buf, win = wins[1] }):on("Closed", function()
|
||||
|
@ -1059,6 +1033,10 @@ function M.setup()
|
|||
end
|
||||
end
|
||||
end)
|
||||
|
||||
if Snacks.config.dashboard.debug then
|
||||
Snacks.debug.stats({ min = 0.2 })
|
||||
end
|
||||
end
|
||||
|
||||
function M.health()
|
||||
|
|
|
@ -94,9 +94,10 @@ function M.log(...)
|
|||
end
|
||||
|
||||
---@alias snacks.debug.Trace {name: string, time: number, [number]:snacks.debug.Trace}
|
||||
---@alias snacks.debug.Stat {name:string, time:number, count?:number, depth?:number}
|
||||
|
||||
---@type snacks.debug.Trace[]
|
||||
M._traces = { { name = "snacks" } }
|
||||
M._traces = { { name = "__TOP__", time = 0 } }
|
||||
|
||||
---@param name string?
|
||||
function M.trace(name)
|
||||
|
@ -112,25 +113,70 @@ function M.trace(name)
|
|||
end
|
||||
end
|
||||
|
||||
---@param opts? {min?: number}
|
||||
function M.stats(opts)
|
||||
opts = opts or {}
|
||||
local lines = {}
|
||||
---@param stat snacks.debug.Trace
|
||||
---@param level number
|
||||
local function collect(stat, level)
|
||||
for _, entry in ipairs(stat) do
|
||||
local ms = math.floor(entry.time / 1e4) / 1e2
|
||||
if ms >= (opts.min or 0) then
|
||||
table.insert(lines, ("%s- `%s`: **%.2f**ms"):format((" "):rep(level), entry.name, entry.time / 1e6))
|
||||
if entry[1] then
|
||||
collect(entry, level + 1)
|
||||
end
|
||||
---@param modname string
|
||||
---@param mod? table
|
||||
---@param suffix? string
|
||||
function M.tracemod(modname, mod, suffix)
|
||||
mod = mod or require(modname)
|
||||
suffix = suffix or "."
|
||||
for k, v in pairs(mod) do
|
||||
if type(v) == "function" and k ~= "trace" then
|
||||
mod[k] = function(...)
|
||||
M.trace(modname .. suffix .. k)
|
||||
local ok, ret = pcall(v, ...)
|
||||
M.trace()
|
||||
return ok == false and error(ret) or ret
|
||||
end
|
||||
end
|
||||
end
|
||||
collect(M._traces[1], 0)
|
||||
Snacks.notify.warn(lines, { title = "Traces" })
|
||||
end
|
||||
|
||||
---@param opts? {min?: number, show?:boolean}
|
||||
---@return {summary:table<string, snacks.debug.Stat>, trace:snacks.debug.Stat[], traces:snacks.debug.Trace[]}
|
||||
function M.stats(opts)
|
||||
opts = opts or {}
|
||||
local stack, lines, trace = {}, {}, {} ---@type string[], string[], snacks.debug.Stat[]
|
||||
local summary = {} ---@type table<string, snacks.debug.Stat>
|
||||
---@param stat snacks.debug.Trace
|
||||
local function collect(stat)
|
||||
if #stack > 0 then
|
||||
local recursive = vim.list_contains(stack, stat.name)
|
||||
summary[stat.name] = summary[stat.name] or { time = 0, count = 0, name = stat.name }
|
||||
summary[stat.name].time = summary[stat.name].time + (recursive and 0 or stat.time)
|
||||
summary[stat.name].count = summary[stat.name].count + 1
|
||||
table.insert(trace, { name = stat.name, time = stat.time or 0, depth = #stack - 1 })
|
||||
end
|
||||
table.insert(stack, stat.name)
|
||||
for _, entry in ipairs(stat) do
|
||||
collect(entry)
|
||||
end
|
||||
table.remove(stack)
|
||||
end
|
||||
collect(M._traces[1])
|
||||
|
||||
---@param entries snacks.debug.Stat[]
|
||||
local function add(entries)
|
||||
for _, stat in ipairs(entries) do
|
||||
local ms = math.floor(stat.time / 1e4) / 1e2
|
||||
if ms >= (opts.min or 0) then
|
||||
local line = ("%s- `%s`: **%.2f**ms"):format((" "):rep(stat.depth or 0), stat.name, ms)
|
||||
table.insert(lines, line .. (stat.count and (" ([%d])"):format(stat.count) or ""))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if opts.show ~= false then
|
||||
lines[#lines + 1] = "# Summary"
|
||||
summary = vim.tbl_values(summary)
|
||||
table.sort(summary, function(a, b)
|
||||
return a.time > b.time
|
||||
end)
|
||||
add(summary)
|
||||
lines[#lines + 1] = "\n# Trace"
|
||||
add(trace)
|
||||
Snacks.notify.warn(lines, { title = "Traces" })
|
||||
end
|
||||
return { summary = summary, trace = trace, tree = M._traces }
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue