mirror of https://github.com/folke/lazy.nvim.git
feat: added `opts.headless` to control ansi output when running headless
This commit is contained in:
parent
93b3a77286
commit
a0a51c06c2
|
@ -130,6 +130,17 @@ M.defaults = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
-- Output options for headless mode
|
||||||
|
headless = {
|
||||||
|
-- show the output from process commands like git
|
||||||
|
process = true,
|
||||||
|
-- show log messages
|
||||||
|
log = true,
|
||||||
|
-- show task start/end
|
||||||
|
task = true,
|
||||||
|
-- use ansi colors
|
||||||
|
colors = true,
|
||||||
|
},
|
||||||
diff = {
|
diff = {
|
||||||
-- diff command <d> can be one of:
|
-- diff command <d> can be one of:
|
||||||
-- * browser: opens the github compare view. Note that this is always mapped to <K> as well,
|
-- * browser: opens the github compare view. Note that this is always mapped to <K> as well,
|
||||||
|
|
|
@ -48,6 +48,7 @@ local uv = vim.uv
|
||||||
---@field cwd? string
|
---@field cwd? string
|
||||||
---@field on_line? fun(string)
|
---@field on_line? fun(string)
|
||||||
---@field on_exit? fun(ok:boolean, output:string)
|
---@field on_exit? fun(ok:boolean, output:string)
|
||||||
|
---@field on_data? fun(string)
|
||||||
---@field timeout? number
|
---@field timeout? number
|
||||||
---@field env? table<string,string>
|
---@field env? table<string,string>
|
||||||
|
|
||||||
|
@ -145,6 +146,11 @@ function M.spawn(cmd, opts)
|
||||||
assert(not err, err)
|
assert(not err, err)
|
||||||
|
|
||||||
if data then
|
if data then
|
||||||
|
if opts.on_data then
|
||||||
|
vim.schedule(function()
|
||||||
|
opts.on_data(data)
|
||||||
|
end)
|
||||||
|
end
|
||||||
output = output .. data:gsub("\r\n", "\n")
|
output = output .. data:gsub("\r\n", "\n")
|
||||||
local lines = vim.split(vim.trim(output:gsub("\r$", "")):gsub("[^\n\r]+\r", ""), "\n")
|
local lines = vim.split(vim.trim(output:gsub("\r$", "")):gsub("[^\n\r]+\r", ""), "\n")
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
local Async = require("lazy.async")
|
local Async = require("lazy.async")
|
||||||
|
local Config = require("lazy.core.config")
|
||||||
local Process = require("lazy.manage.process")
|
local Process = require("lazy.manage.process")
|
||||||
|
local Terminal = require("lazy.terminal")
|
||||||
|
|
||||||
|
local colors = Config.options.headless.colors
|
||||||
|
|
||||||
---@class LazyTaskDef
|
---@class LazyTaskDef
|
||||||
---@field skip? fun(plugin:LazyPlugin, opts?:TaskOptions):any?
|
---@field skip? fun(plugin:LazyPlugin, opts?:TaskOptions):any?
|
||||||
|
@ -96,6 +100,10 @@ function Task:_start(task)
|
||||||
assert(not self:has_started(), "task already started")
|
assert(not self:has_started(), "task already started")
|
||||||
assert(not self:has_ended(), "task already done")
|
assert(not self:has_ended(), "task already done")
|
||||||
|
|
||||||
|
if Config.headless() and Config.options.headless.task then
|
||||||
|
self:log("Running task " .. self.name, vim.log.levels.INFO)
|
||||||
|
end
|
||||||
|
|
||||||
self._started = vim.uv.hrtime()
|
self._started = vim.uv.hrtime()
|
||||||
---@async
|
---@async
|
||||||
self._running = Async.run(function()
|
self._running = Async.run(function()
|
||||||
|
@ -122,6 +130,27 @@ function Task:log(msg, level)
|
||||||
---@cast msg string
|
---@cast msg string
|
||||||
table.insert(self._log, { msg = msg, level = level })
|
table.insert(self._log, { msg = msg, level = level })
|
||||||
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
|
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
|
||||||
|
if Config.headless() then
|
||||||
|
self:headless()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Task:headless()
|
||||||
|
if not Config.options.headless.log then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local msg = self._log[#self._log]
|
||||||
|
if not msg or msg.level == vim.log.levels.TRACE then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local map = {
|
||||||
|
[vim.log.levels.ERROR] = Terminal.red,
|
||||||
|
[vim.log.levels.WARN] = Terminal.yellow,
|
||||||
|
[vim.log.levels.INFO] = Terminal.blue,
|
||||||
|
}
|
||||||
|
local color = Config.options.headless.colors and map[msg.level]
|
||||||
|
io.write(Terminal.prefix(color and color(msg.msg) or msg.msg, self:prefix()))
|
||||||
|
io.write("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param msg string|string[]
|
---@param msg string|string[]
|
||||||
|
@ -143,6 +172,10 @@ function Task:_done()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Config.headless() and Config.options.headless.task then
|
||||||
|
local ms = math.floor(self:time() + 0.5)
|
||||||
|
self:log("Finished task " .. self.name .. " in " .. ms .. "ms", vim.log.levels.INFO)
|
||||||
|
end
|
||||||
self._ended = vim.uv.hrtime()
|
self._ended = vim.uv.hrtime()
|
||||||
if self._opts.on_done then
|
if self._opts.on_done then
|
||||||
self._opts.on_done(self)
|
self._opts.on_done(self)
|
||||||
|
@ -172,8 +205,12 @@ function Task:spawn(cmd, opts)
|
||||||
local on_line = opts.on_line
|
local on_line = opts.on_line
|
||||||
local on_exit = opts.on_exit
|
local on_exit = opts.on_exit
|
||||||
|
|
||||||
|
local headless = Config.headless() and Config.options.headless.process
|
||||||
|
|
||||||
function opts.on_line(line)
|
function opts.on_line(line)
|
||||||
self:log(line, vim.log.levels.TRACE)
|
if not headless then
|
||||||
|
return self:log(line, vim.log.levels.TRACE)
|
||||||
|
end
|
||||||
if on_line then
|
if on_line then
|
||||||
pcall(on_line, line)
|
pcall(on_line, line)
|
||||||
end
|
end
|
||||||
|
@ -182,18 +219,36 @@ function Task:spawn(cmd, opts)
|
||||||
local running = true
|
local running = true
|
||||||
---@param output string
|
---@param output string
|
||||||
function opts.on_exit(ok, output)
|
function opts.on_exit(ok, output)
|
||||||
self:log(vim.trim(output), ok and vim.log.levels.DEBUG or vim.log.levels.ERROR)
|
if not headless then
|
||||||
|
self:log(vim.trim(output), ok and vim.log.levels.DEBUG or vim.log.levels.ERROR)
|
||||||
|
end
|
||||||
if on_exit then
|
if on_exit then
|
||||||
pcall(on_exit, ok, output)
|
pcall(on_exit, ok, output)
|
||||||
end
|
end
|
||||||
running = false
|
running = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if headless then
|
||||||
|
opts.on_data = function(data)
|
||||||
|
-- prefix with plugin name
|
||||||
|
local prefix = self:prefix()
|
||||||
|
io.write(Terminal.prefix(data, prefix))
|
||||||
|
end
|
||||||
|
end
|
||||||
Process.spawn(cmd, opts)
|
Process.spawn(cmd, opts)
|
||||||
while running do
|
while running do
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Task:prefix()
|
||||||
|
local plugin = "[" .. self.plugin.name .. "] "
|
||||||
|
local task = string.rep(" ", 20 - #(self.name .. self.plugin.name)) .. self.name
|
||||||
|
|
||||||
|
return colors and Terminal.magenta(plugin) .. Terminal.cyan(task) .. Terminal.bright_black(" | ")
|
||||||
|
or plugin .. " " .. task .. " | "
|
||||||
|
end
|
||||||
|
|
||||||
function Task:wait()
|
function Task:wait()
|
||||||
while self:is_running() do
|
while self:is_running() do
|
||||||
vim.wait(10)
|
vim.wait(10)
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
---@class Ansi: table<string, fun(string):string>
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
M.colors = {
|
||||||
|
reset = "\27[0m",
|
||||||
|
black = "\27[30m",
|
||||||
|
red = "\27[31m",
|
||||||
|
green = "\27[32m",
|
||||||
|
yellow = "\27[33m",
|
||||||
|
blue = "\27[34m",
|
||||||
|
magenta = "\27[35m",
|
||||||
|
cyan = "\27[36m",
|
||||||
|
white = "\27[37m",
|
||||||
|
bright_black = "\27[90m",
|
||||||
|
bright_red = "\27[91m",
|
||||||
|
bright_green = "\27[92m",
|
||||||
|
bright_yellow = "\27[93m",
|
||||||
|
bright_blue = "\27[94m",
|
||||||
|
bright_magenta = "\27[95m",
|
||||||
|
bright_cyan = "\27[96m",
|
||||||
|
bright_white = "\27[97m",
|
||||||
|
}
|
||||||
|
|
||||||
|
function M.color(text, color)
|
||||||
|
return M.colors[color] .. text .. M.colors.reset
|
||||||
|
end
|
||||||
|
|
||||||
|
-- stylua: ignore start
|
||||||
|
function M.black(text) return M.color(text, "black") end
|
||||||
|
function M.red(text) return M.color(text, "red") end
|
||||||
|
function M.green(text) return M.color(text, "green") end
|
||||||
|
function M.yellow(text) return M.color(text, "yellow") end
|
||||||
|
function M.blue(text) return M.color(text, "blue") end
|
||||||
|
function M.magenta(text) return M.color(text, "magenta") end
|
||||||
|
function M.cyan(text) return M.color(text, "cyan") end
|
||||||
|
function M.white(text) return M.color(text, "white") end
|
||||||
|
function M.bright_black(text) return M.color(text, "bright_black") end
|
||||||
|
function M.bright_red(text) return M.color(text, "bright_red") end
|
||||||
|
function M.bright_green(text) return M.color(text, "bright_green") end
|
||||||
|
function M.bright_yellow(text) return M.color(text, "bright_yellow") end
|
||||||
|
function M.bright_blue(text) return M.color(text, "bright_blue") end
|
||||||
|
function M.bright_magenta(text) return M.color(text, "bright_magenta") end
|
||||||
|
function M.bright_cyan(text) return M.color(text, "bright_cyan") end
|
||||||
|
function M.bright_white(text) return M.color(text, "bright_white") end
|
||||||
|
-- stylua: ignore end
|
||||||
|
|
||||||
|
---@param data string
|
||||||
|
---@param prefix string
|
||||||
|
function M.prefix(data, prefix)
|
||||||
|
-- Normalize Windows-style newlines to simple newlines
|
||||||
|
data = data:gsub("\r\n", "\n")
|
||||||
|
|
||||||
|
-- Handle prefix for the first line, if data starts immediately
|
||||||
|
data = prefix .. data
|
||||||
|
|
||||||
|
-- Prefix new lines ensuring not to double prefix if a line starts with \r
|
||||||
|
data = data:gsub("(\n)([^\r])", "%1" .. prefix .. "%2")
|
||||||
|
|
||||||
|
-- Handle carriage returns properly to avoid double prefixing
|
||||||
|
-- Replace any \r not followed by \n with \r, then add a prefix only if the following character isn't the start of our prefix
|
||||||
|
data = data:gsub("\r([^\n])", function(nextChar)
|
||||||
|
if nextChar:sub(1, #prefix) == prefix then
|
||||||
|
return "\r" .. nextChar
|
||||||
|
else
|
||||||
|
return "\r" .. prefix .. nextChar
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
|
@ -6,22 +6,22 @@ for _, name in ipairs({ "config", "data", "state", "cache" }) do
|
||||||
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
|
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
|
||||||
end
|
end
|
||||||
|
|
||||||
-- -- Bootstrap lazy.nvim
|
|
||||||
-- local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
|
|
||||||
-- if not (vim.uv or vim.loop).fs_stat(lazypath) then
|
|
||||||
-- local lazyrepo = "https://github.com/folke/lazy.nvim.git"
|
|
||||||
-- vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
|
|
||||||
-- end
|
|
||||||
-- vim.opt.rtp:prepend(lazypath)
|
|
||||||
vim.opt.rtp:prepend(".")
|
vim.opt.rtp:prepend(".")
|
||||||
|
|
||||||
vim.o.loadplugins = true -- enable since nvim -l disables plugins
|
vim.o.loadplugins = true -- enable since nvim -l disables plugins
|
||||||
|
|
||||||
-- Setup lazy.nvim
|
-- Setup lazy.nvim
|
||||||
require("lazy").setup({
|
require("lazy").setup({
|
||||||
"lunarmodules/busted", -- add busted
|
spec = {
|
||||||
|
"lunarmodules/busted", -- add busted
|
||||||
|
},
|
||||||
|
rocks = { hererocks = true },
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local Config = require("lazy.core.config")
|
||||||
|
-- disable termnial output for the tests
|
||||||
|
Config.options.headless = {}
|
||||||
|
|
||||||
-- run busted
|
-- run busted
|
||||||
return pcall(require("busted.runner"), {
|
return pcall(require("busted.runner"), {
|
||||||
standalone = false,
|
standalone = false,
|
||||||
|
|
Loading…
Reference in New Issue