From 6c7ef7e27a797acd68f6bffcb90d58f03dd8431d Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Wed, 26 Jun 2024 18:31:31 +0200 Subject: [PATCH] refactor: logging --- lua/lazy/core/plugin.lua | 2 +- lua/lazy/manage/init.lua | 2 +- lua/lazy/manage/runner.lua | 2 +- lua/lazy/manage/task/git.lua | 27 +++++++---- lua/lazy/manage/task/init.lua | 82 ++++++++++++++++++++++----------- lua/lazy/manage/task/plugin.lua | 7 +-- lua/lazy/pkg/rockspec.lua | 6 +-- lua/lazy/view/colors.lua | 5 +- lua/lazy/view/render.lua | 68 +++++++++++++++------------ lua/lazy/view/sections.lua | 9 ++-- 10 files changed, 130 insertions(+), 80 deletions(-) diff --git a/lua/lazy/core/plugin.lua b/lua/lazy/core/plugin.lua index a806b0a..a3cb497 100644 --- a/lua/lazy/core/plugin.lua +++ b/lua/lazy/core/plugin.lua @@ -403,7 +403,7 @@ end ---@param plugin LazyPlugin function M.has_errors(plugin) for _, task in ipairs(plugin._.tasks or {}) do - if task.error then + if task:has_errors() then return true end end diff --git a/lua/lazy/manage/init.lua b/lua/lazy/manage/init.lua index 9737538..e0b2233 100644 --- a/lua/lazy/manage/init.lua +++ b/lua/lazy/manage/init.lua @@ -232,7 +232,7 @@ function M.clear(plugins) if plugin._.tasks then ---@param task LazyTask plugin._.tasks = vim.tbl_filter(function(task) - return task:is_running() or task.error + return task:is_running() or task:has_errors() end, plugin._.tasks) end end diff --git a/lua/lazy/manage/runner.lua b/lua/lazy/manage/runner.lua index 31b194b..e517ddc 100644 --- a/lua/lazy/manage/runner.lua +++ b/lua/lazy/manage/runner.lua @@ -96,7 +96,7 @@ function Runner:_start() wait_step = s.step elseif not running then local plugin = self:plugin(name) - if s.task and s.task.error then + if s.task and s.task:has_errors() then active = active - 1 elseif s.step == #self._pipeline then s.task = nil diff --git a/lua/lazy/manage/task/git.lua b/lua/lazy/manage/task/git.lua index 56d2b73..4bd7134 100644 --- a/lua/lazy/manage/task/git.lua +++ b/lua/lazy/manage/task/git.lua @@ -18,6 +18,7 @@ M.log = { local stat = vim.uv.fs_stat(plugin.dir .. "/.git") return not (stat and stat.type == "directory") end, + ---@async ---@param opts {args?: string[], updated?:boolean, check?:boolean} run = function(self, opts) local args = { @@ -68,6 +69,7 @@ M.clone = { skip = function(plugin) return plugin._.installed or plugin._.is_local end, + ---@async run = function(self) local args = { "clone", @@ -129,6 +131,7 @@ M.branch = { local branch = assert(Git.get_branch(plugin)) return Git.get_commit(plugin.dir, branch, true) end, + ---@async run = function(self) local args = { "remote", @@ -154,14 +157,17 @@ M.origin = { local origin = Git.get_origin(plugin.dir) return origin == plugin.url end, + ---@async ---@param opts {check?:boolean} run = function(self, opts) if opts.check then local origin = Git.get_origin(self.plugin.dir) - self.error = "Origin has changed:\n" - self.error = self.error .. " * old: " .. origin .. "\n" - self.error = self.error .. " * new: " .. self.plugin.url .. "\n" - self.error = self.error .. "Please run update to fix" + self:error({ + "Origin has changed:", + " * old: " .. origin, + " * new: " .. self.plugin.url, + "Please run update to fix", + }) return end require("lazy.manage.task.fs").clean.run(self, opts) @@ -173,6 +179,7 @@ M.status = { skip = function(plugin) return not plugin._.installed or plugin._.is_local end, + ---@async run = function(self) self:spawn("git", { args = { "ls-files", "-d", "-m" }, @@ -180,6 +187,7 @@ M.status = { on_exit = function(ok, output) if ok then local lines = vim.split(output, "\n") + ---@type string[] lines = vim.tbl_filter(function(line) -- Fix doc/tags being marked as modified if line:gsub("[\\/]", "/") == "doc/tags" then @@ -190,12 +198,13 @@ M.status = { return line ~= "" end, lines) if #lines > 0 then - self.error = "You have local changes in `" .. self.plugin.dir .. "`:\n" + local msg = { "You have local changes in `" .. self.plugin.dir .. "`:" } for _, line in ipairs(lines) do - self.error = self.error .. " * " .. line .. "\n" + msg[#msg + 1] = " * " .. line end - self.error = self.error .. "Please remove them to update.\n" - self.error = self.error .. "You can also press `x` to remove the plugin and then `I` to install it again." + msg[#msg + 1] = "Please remove them to update." + msg[#msg + 1] = "You can also press `x` to remove the plugin and then `I` to install it again." + self:error(msg) end end end, @@ -209,6 +218,7 @@ M.fetch = { return not plugin._.installed or plugin._.is_local end, + ---@async run = function(self) local args = { "fetch", @@ -236,6 +246,7 @@ M.checkout = { return not plugin._.installed or plugin._.is_local end, + ---@async ---@param opts {lockfile?:boolean} run = function(self, opts) local info = assert(Git.info(self.plugin.dir)) diff --git a/lua/lazy/manage/task/init.lua b/lua/lazy/manage/task/init.lua index 98c7636..496dac9 100644 --- a/lua/lazy/manage/task/init.lua +++ b/lua/lazy/manage/task/init.lua @@ -3,21 +3,23 @@ local Process = require("lazy.manage.process") ---@class LazyTaskDef ---@field skip? fun(plugin:LazyPlugin, opts?:TaskOptions):any? ----@field run fun(task:LazyTask, opts:TaskOptions) +---@field run async fun(task:LazyTask, opts:TaskOptions) ---@alias LazyTaskFn async fun(task:LazyTask, opts:TaskOptions) +---@class LazyMsg +---@field msg string +---@field level? number + ---@class LazyTask ---@field plugin LazyPlugin ---@field name string ----@field output string ----@field status string ----@field error? string ----@field warn? string +---@field private _log LazyMsg[] ---@field private _started? number ---@field private _ended? number ---@field private _opts TaskOptions ---@field private _running Async +---@field private _level number local Task = {} ---@class TaskOptions: {[string]:any} @@ -30,10 +32,10 @@ local Task = {} function Task.new(plugin, name, task, opts) local self = setmetatable({}, { __index = Task }) self._opts = opts or {} + self._log = {} + self._level = vim.log.levels.TRACE self.plugin = plugin self.name = name - self.output = "" - self.status = "" ---@param other LazyTask plugin._.tasks = vim.tbl_filter(function(other) return other.name ~= name or other:is_running() @@ -43,6 +45,31 @@ function Task.new(plugin, name, task, opts) return self end +---@param level? number +---@return LazyMsg[] +function Task:get_log(level) + level = level or vim.log.levels.DEBUG + return vim.tbl_filter(function(msg) + return msg.level >= level + end, self._log) +end + +---@param level? number +function Task:output(level) + return table.concat( + ---@param m LazyMsg + vim.tbl_map(function(m) + return m.msg + end, self:get_log(level)), + "\n" + ) +end + +function Task:status() + local ret = self._log[#self._log] + return ret and ret.msg or "" +end + function Task:has_started() return self._started ~= nil end @@ -55,6 +82,14 @@ function Task:is_running() return not self:has_ended() end +function Task:has_errors() + return self._level >= vim.log.levels.ERROR +end + +function Task:has_warnings() + return self._level >= vim.log.levels.WARN +end + ---@private ---@param task LazyTaskFn function Task:_start(task) @@ -70,36 +105,33 @@ function Task:_start(task) self:_done() end, on_error = function(err) - self:notify_error(err) + self:error(err) end, on_yield = function(res) - self:notify(res) + self:log(res) end, }) end ---@param msg string|string[] ----@param severity? vim.diagnostic.Severity -function Task:notify(msg, severity) - local var = severity == vim.diagnostic.severity.ERROR and "error" - or severity == vim.diagnostic.severity.WARN and "warn" - or "output" +---@param level? number +function Task:log(msg, level) + level = level or vim.log.levels.DEBUG + self._level = math.max(self._level or 0, level or 0) msg = type(msg) == "table" and table.concat(msg, "\n") or msg ---@cast msg string - ---@diagnostic disable-next-line: no-unknown - self[var] = self[var] and (self[var] .. "\n" .. msg) or msg - self.status = msg + table.insert(self._log, { msg = msg, level = level }) vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false }) end ---@param msg string|string[] -function Task:notify_error(msg) - self:notify(msg, vim.diagnostic.severity.ERROR) +function Task:error(msg) + self:log(msg, vim.log.levels.ERROR) end ---@param msg string|string[] -function Task:notify_warn(msg) - self:notify(msg, vim.diagnostic.severity.WARN) +function Task:warn(msg) + self:log(msg, vim.log.levels.WARN) end ---@private @@ -141,20 +173,16 @@ function Task:spawn(cmd, opts) local on_exit = opts.on_exit function opts.on_line(line) - self.status = line + self:log(line, vim.log.levels.TRACE) if on_line then pcall(on_line, line) end - vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false }) end local running = true ---@param output string function opts.on_exit(ok, output) - self.output = self.output .. output - if not ok then - self.error = self.error and (self.error .. "\n" .. output) or output - end + self:log(output, ok and vim.log.levels.DEBUG or vim.log.levels.ERROR) if on_exit then pcall(on_exit, ok, output) end diff --git a/lua/lazy/manage/task/plugin.lua b/lua/lazy/manage/task/plugin.lua index ddf53a1..fd6c12b 100644 --- a/lua/lazy/manage/task/plugin.lua +++ b/lua/lazy/manage/task/plugin.lua @@ -1,4 +1,3 @@ -local Config = require("lazy.core.config") local Loader = require("lazy.core.loader") local Rocks = require("lazy.pkg.rockspec") local Util = require("lazy.util") @@ -21,9 +20,10 @@ local B = {} ---@param build string function B.cmd(task, build) local cmd = vim.api.nvim_parse_cmd(build:sub(2), {}) --[[@as vim.api.keyset.cmd]] - task.output = vim.api.nvim_cmd(cmd, { output = true }) + task:log(vim.api.nvim_cmd(cmd, { output = true })) end +---@async ---@param task LazyTask ---@param build string function B.shell(task, build) @@ -44,6 +44,7 @@ M.build = { end return not ((plugin._.dirty or plugin._.build) and (plugin.build or get_build_file(plugin))) end, + ---@async run = function(self) vim.cmd([[silent! runtime plugin/rplugin.vim]]) @@ -92,7 +93,7 @@ M.docs = { run = function(self) local docs = self.plugin.dir .. "/doc/" if Util.file_exists(docs) then - self.output = vim.api.nvim_cmd({ cmd = "helptags", args = { docs } }, { output = true }) + self:log(vim.api.nvim_cmd({ cmd = "helptags", args = { docs } }, { output = true })) end end, } diff --git a/lua/lazy/pkg/rockspec.lua b/lua/lazy/pkg/rockspec.lua index 2eca5bd..04ff937 100644 --- a/lua/lazy/pkg/rockspec.lua +++ b/lua/lazy/pkg/rockspec.lua @@ -106,15 +106,15 @@ function M.build(task) if not M.check({ error = function(msg) - task:notify_error(msg:gsub("[{}]", "`")) + task:error(msg:gsub("[{}]", "`")) end, warn = function(msg) - task:notify_warn(msg) + task:warn(msg) end, ok = function(msg) end, }) then - task:notify_warn({ + task:log({ "", "This plugin requires `luarocks`. Try one of the following:", " - fix your `luarocks` installation", diff --git a/lua/lazy/view/colors.lua b/lua/lazy/view/colors.lua index e55c56b..c1dbe50 100644 --- a/lua/lazy/view/colors.lua +++ b/lua/lazy/view/colors.lua @@ -30,8 +30,9 @@ M.colors = { Button = "CursorLine", ButtonActive = "Visual", TaskOutput = "MsgArea", -- task output - TaskError = "ErrorMsg", -- task errors - TaskWarning = "WarningMsg", -- task errors + Error = "DiagnosticError", -- task errors + Warning = "DiagnosticWarn", -- task errors + Info = "DiagnosticInfo", -- task errors Dir = "@markup.link", -- directory Url = "@markup.link", -- url Bold = { bold = true }, diff --git a/lua/lazy/view/render.lua b/lua/lazy/view/render.lua index a2c33c1..00ebd8f 100644 --- a/lua/lazy/view/render.lua +++ b/lua/lazy/view/render.lua @@ -354,6 +354,31 @@ end ---@param plugin LazyPlugin function M:diagnostics(plugin) + local skip = false + for _, task in ipairs(plugin._.tasks or {}) do + if task:is_running() then + self:diagnostic({ + severity = vim.diagnostic.severity.WARN, + message = task.name .. (task:status() and (": " .. task:status()) or ""), + }) + skip = true + elseif task:has_errors() then + self:diagnostic({ + message = task.name .. " failed", + severity = vim.diagnostic.severity.ERROR, + }) + skip = true + elseif task:has_warnings() then + self:diagnostic({ + message = task.name .. " warning", + severity = vim.diagnostic.severity.WARN, + }) + skip = true + end + end + if skip then + return + end if plugin._.updated then if plugin._.updated.from == plugin._.updated.to then self:diagnostic({ @@ -383,24 +408,6 @@ function M:diagnostics(plugin) }) end end - for _, task in ipairs(plugin._.tasks or {}) do - if task:is_running() then - self:diagnostic({ - severity = vim.diagnostic.severity.WARN, - message = task.name .. (task.status == "" and "" or (": " .. task.status)), - }) - elseif task.error then - self:diagnostic({ - message = task.name .. " failed", - severity = vim.diagnostic.severity.ERROR, - }) - elseif task.warn then - self:diagnostic({ - message = task.name .. " warning", - severity = vim.diagnostic.severity.WARN, - }) - end - end end ---@param plugin LazyPlugin @@ -463,24 +470,27 @@ function M:tasks(plugin) self:append(" " .. math.floor((task:time()) * 100) / 100 .. "ms", "Bold") self:nl() end - if task.error then - self:markdown(task.error, "LazyTaskError", { indent = 6 }) - end - if task.warn then - self:markdown(task.warn, "LazyTaskWarning", { indent = 6 }) - end - if not task.error and not task.warn and task.name == "log" then + + if not task:has_warnings() and task.name == "log" then self:log(task) - end - if (self.view:is_selected(plugin) or (task.error or task.warn)) and task.output ~= task.error then - self:markdown(vim.trim(task.output), "LazyTaskOutput", { indent = 6 }) + else + local hls = { + [vim.log.levels.ERROR] = "LazyError", + [vim.log.levels.WARN] = "LazyWarning", + [vim.log.levels.INFO] = "LazyInfo", + } + for _, msg in ipairs(task:get_log()) do + if task:has_warnings() or self.view:is_selected(plugin) then + self:markdown(msg.msg, hls[msg.level] or "LazyTaskOutput", { indent = 6 }) + end + end end end end ---@param task LazyTask function M:log(task) - local log = vim.trim(task.output) + local log = vim.trim(task:output()) if log ~= "" then local lines = vim.split(log, "\n") for _, line in ipairs(lines) do diff --git a/lua/lazy/view/sections.lua b/lua/lazy/view/sections.lua index 5dfb57e..e2892a2 100644 --- a/lua/lazy/view/sections.lua +++ b/lua/lazy/view/sections.lua @@ -17,7 +17,7 @@ return { { filter = function(plugin) return has_task(plugin, function(task) - return task.error ~= nil + return task:has_errors() end) end, title = "Failed", @@ -39,8 +39,7 @@ return { if task.name ~= "log" then return end - local lines = vim.split(task.output, "\n") - for _, line in ipairs(lines) do + for _, line in ipairs(vim.split(task:output(), "\n")) do if line:find("^%w+ %S+!:") then return true end @@ -71,7 +70,7 @@ return { { filter = function(plugin) return has_task(plugin, function(task) - return task.name == "log" and vim.trim(task.output) ~= "" + return task.name == "log" and vim.trim(task:output()) ~= "" end) end, title = "Log", @@ -89,7 +88,7 @@ return { title = "Not Installed", }, { - filter = function (plugin) + filter = function(plugin) return plugin._.outdated end, title = "Outdated",