From 66ceb352aaf89aa5517b34df9dc694dc5346465b Mon Sep 17 00:00:00 2001 From: Oscar Wallberg Date: Thu, 7 May 2026 00:10:01 +0200 Subject: [PATCH] feat(nvim-tree): aggregate child git status onto directory nodes --- lua/git/repo.lua | 1 + lua/git/status.lua | 23 +++++++++++++++++++++++ plugins/nvim-tree.lua | 16 +++++++++++++--- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/lua/git/repo.lua b/lua/git/repo.lua index af3a396..5080b57 100644 --- a/lua/git/repo.lua +++ b/lua/git/repo.lua @@ -47,6 +47,7 @@ local STATUS_CMD = { "--porcelain=v1", "--branch", "--ignored", + "--untracked-files=all", } ---@private diff --git a/lua/git/status.lua b/lua/git/status.lua index 9cd0d54..46e7089 100644 --- a/lua/git/status.lua +++ b/lua/git/status.lua @@ -45,6 +45,29 @@ function Status:by_kind(kind) return out end +---@param prefix string +---@return ow.Git.Status.Entry[] +function Status:aggregate_at(prefix) + local match = (prefix == "" or prefix == ".") and "" or prefix .. "/" + local seen = {} + local out = {} + for path, list in pairs(self.entries) do + if path == prefix or vim.startswith(path, match) then + for _, e in ipairs(list) do + local key = e.char .. "\0" .. e.hl + if not seen[key] then + seen[key] = true + table.insert(out, e) + end + end + end + end + table.sort(out, function(a, b) + return a.char < b.char + end) + return out +end + ---@param x string ---@return string char, string hl local function staged_attrs(x) diff --git a/plugins/nvim-tree.lua b/plugins/nvim-tree.lua index 3b17f12..408bf67 100644 --- a/plugins/nvim-tree.lua +++ b/plugins/nvim-tree.lua @@ -57,7 +57,14 @@ local function entries_for(node) return end local rel = vim.fs.relpath(r.worktree, node.absolute_path) - return rel and r.status.entries[rel] + if not rel then + return + end + if node.type == "directory" then + local list = r.status:aggregate_at(rel) + return #list > 0 and list or nil + end + return r.status.entries[rel] end ---@param node Node @@ -83,11 +90,14 @@ function GitDecorator.highlight_group(_, node) if not list then return end + local hl for _, entry in ipairs(list) do - if entry.kind == "ignored" then - return entry.hl + if entry.kind ~= "ignored" then + return end + hl = hl or entry.hl end + return hl end local signs = require("lsp.diagnostic").signs