From 9bbbd1b1c8cfea4ed9ee7189db14f19454870021 Mon Sep 17 00:00:00 2001 From: Oscar Wallberg Date: Sat, 9 May 2026 00:25:10 +0200 Subject: [PATCH] feat(git): highlight only fatal/error lines in failure dump --- lua/git/cmd.lua | 31 ++++++++++++++++++++++++++++--- test/git/cmd_test.lua | 37 +++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/lua/git/cmd.lua b/lua/git/cmd.lua index e803b0b..f4d4d77 100644 --- a/lua/git/cmd.lua +++ b/lua/git/cmd.lua @@ -321,6 +321,32 @@ local function clean_progress_line(line) return "" end +---@param lines string[] +---@param fallback string +---@return [string, string?][] +local function format_error_dump(lines, fallback) + if #lines == 0 then + return { { fallback, "ErrorMsg" } } + end + local chunks = {} + local matched = false + for i, line in ipairs(lines) do + if i > 1 then + table.insert(chunks, { "\n" }) + end + if line:match("^fatal:") or line:match("^error:") then + table.insert(chunks, { line, "ErrorMsg" }) + matched = true + else + table.insert(chunks, { line }) + end + end + if not matched then + return { { table.concat(lines, "\n"), "ErrorMsg" } } + end + return chunks +end + ---@param r ow.Git.Repo ---@param args string[] local function run_streaming(r, args) @@ -387,9 +413,8 @@ local function run_streaming(r, args) ) else emit_progress(("exit %d"):format(code), "failed") - local body = #accum > 0 and table.concat(accum, "\n") - or ("%s failed: exit %d"):format(title, code) - vim.api.nvim_echo({ { body, "ErrorMsg" } }, true, {}) + local fallback = ("%s failed: exit %d"):format(title, code) + vim.api.nvim_echo(format_error_dump(accum, fallback), true, {}) end end diff --git a/test/git/cmd_test.lua b/test/git/cmd_test.lua index b83c8d0..df69f72 100644 --- a/test/git/cmd_test.lua +++ b/test/git/cmd_test.lua @@ -550,7 +550,7 @@ t.test( ) t.test( - "streaming :G fetch (no bang) on failure dumps output to :messages with ErrorMsg", + "streaming :G fetch (no bang) on failure highlights only fatal/error lines", function() make_repo({ a = "x" }) with_echo_stub(function(calls) @@ -558,24 +558,33 @@ t.test( t.wait_for(function() return has_status(calls, "failed") end, "failed progress notification", 5000) - local body = "" + ---@type table? + local dump for _, c in ipairs(calls) do - if - c.history == true - and c.chunks[1] - and c.chunks[1][2] == "ErrorMsg" - then - body = c.chunks[1][1] + if c.history == true then + dump = c.chunks break end end - t.truthy(body ~= "", "expected ErrorMsg history dump") - local lower = string.lower(body) + t.truthy(dump, "expected history dump") + ---@cast dump -nil + local fatal_chunks_red, plain_continuation = 0, false + for _, chunk in ipairs(dump) do + local text, hl = chunk[1], chunk[2] + if text:match("^fatal:") and hl == "ErrorMsg" then + fatal_chunks_red = fatal_chunks_red + 1 + end + if text:match("Please make sure") and hl ~= "ErrorMsg" then + plain_continuation = true + end + end t.truthy( - lower:match("repository") - or lower:match("remote") - or lower:match("fatal"), - "expected error mention in dump, got: " .. body + fatal_chunks_red >= 1, + "expected at least one fatal: line highlighted as ErrorMsg" + ) + t.truthy( + plain_continuation, + "expected continuation line to be plain" ) end) end