Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions doc/diffview.txt
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,15 @@ file_panel *diffview-config-file_panel*
contain a single directory. Default: `true`
• {folder_statuses} ("never"|"only_folded"|"always")
Show folder statuses. Default: `"only_folded"`
• {folder_count_style} ("grouped"|"simple"|"none")
How to display file counts on collapsed folders.
`"grouped"` shows per-status counts (e.g. "2M 1D"),
`"simple"` shows a plain total (e.g. "3"),
`"none"` hides the count entirely.
Default: `"grouped"`
• {folder_trailing_slash} (boolean)
Append "/" to folder names in the file tree.
Default: `true`

{win_config} (table|function)
See |diffview-config-win_config|.
Expand Down Expand Up @@ -815,6 +824,12 @@ file_history_panel *diffview-config-file_history_pa
"5, 3", `"bar"` shows e.g. "| 8 +++++---". Default:
`"number"`

{subject_highlight} ("ref_aware"|"plain")
How to highlight commit subjects. `"ref_aware"` uses
different colours for pushed vs unpushed commits.
`"plain"` uses a single colour for all.
Default: `"ref_aware"`

{commit_format} (string[])
Ordered list of components to show for each commit entry.
Available components: `"status"`, `"files"`, `"stats"`,
Expand Down
3 changes: 3 additions & 0 deletions doc/diffview_defaults.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ DEFAULT CONFIG *diffview.defaults*
tree_options = { -- Only applies when listing_style is 'tree'
flatten_dirs = true, -- Flatten dirs that only contain one single dir
folder_statuses = "only_folded", -- One of 'never', 'only_folded' or 'always'.
folder_count_style = "grouped", -- "grouped" (e.g. "2M 1D"), "simple" (e.g. "3"), or "none".
folder_trailing_slash = true, -- Append "/" to folder names in the file tree.
},
win_config = { -- See |diffview-config-win_config|
position = "left",
Expand All @@ -102,6 +104,7 @@ DEFAULT CONFIG *diffview.defaults*
},
file_history_panel = {
stat_style = "number", -- "number" (e.g. "5, 3"), "bar" (e.g. "| 8 +++++---"), or "both".
subject_highlight = "ref_aware", -- "ref_aware" (colour by pushed/unpushed) or "plain".
-- Ordered list of components to show for each commit entry.
-- Available: "status", "files", "stats", "hash", "reflog", "ref", "subject", "author", "date"
commit_format = { "status", "files", "stats", "hash", "reflog", "ref", "subject", "author", "date" },
Expand Down
5 changes: 4 additions & 1 deletion lua/diffview/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ M.defaults = {
sort_file = nil, -- Custom file comparator: function(a_name, b_name, a_data, b_data) -> boolean
tree_options = {
flatten_dirs = true,
folder_statuses = "only_folded"
folder_statuses = "only_folded",
folder_count_style = "grouped", -- "grouped" (e.g. "2M 1D"), "simple" (e.g. "3"), or "none".
folder_trailing_slash = true, -- Append "/" to folder names in the file tree.
Comment thread
dlyongemallo marked this conversation as resolved.
},
win_config = {
position = "left",
Expand All @@ -166,6 +168,7 @@ M.defaults = {
},
file_history_panel = {
stat_style = "number", -- "number" (e.g. "5, 3"), "bar" (e.g. "| 8 +++++---"), or "both".
subject_highlight = "ref_aware", -- "ref_aware" (colour by pushed/unpushed) or "plain".
-- Ordered list of components to show for each commit entry.
-- Available: "status", "files", "stats", "hash", "reflog", "ref", "subject", "author", "date"
commit_format = { "status", "files", "stats", "hash", "reflog", "ref", "subject", "author", "date" },
Expand Down
2 changes: 2 additions & 0 deletions lua/diffview/scene/views/diff/file_panel.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ local M = {}
---@class TreeOptions
---@field flatten_dirs boolean
---@field folder_statuses "never"|"only_folded"|"always"
---@field folder_count_style "grouped"|"simple"|"none"
---@field folder_trailing_slash boolean

---@class FilePanel : Panel
---@field adapter VCSAdapter
Expand Down
78 changes: 56 additions & 22 deletions lua/diffview/scene/views/diff/render.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,47 @@ local utils = require("diffview.utils")

local pl = utils.path

---Format a folder name, optionally appending a trailing slash.
---@param name string
---@param tree_options table
---@return string
local function format_folder_name(name, tree_options)
return name .. (tree_options.folder_trailing_slash and "/" or "")
end

---Render the file count annotation for a collapsed folder.
---@param comp table RenderComponent-like object supporting add_text().
---@param node table Tree node whose leaves() will be counted.
---@param tree_options table Config tree_options table.
local function render_folder_count(comp, node, tree_options)
if tree_options.folder_count_style == "none" then return end

if tree_options.folder_count_style == "grouped" then
local leaves = node:leaves()
local status_counts = {}
for _, leaf in ipairs(leaves) do
local s = leaf.data.status or "?"
status_counts[s] = (status_counts[s] or 0) + 1
end

-- Sort status letters for consistent display order.
local statuses = vim.tbl_keys(status_counts)
table.sort(statuses)

comp:add_text(" (", "DiffviewDim1")
for i, s in ipairs(statuses) do
if i > 1 then
comp:add_text(" ", "DiffviewDim1")
end
comp:add_text(tostring(status_counts[s]) .. hl.get_status_icon(s), hl.get_git_hl(s))
end
comp:add_text(")", "DiffviewDim1")
else
local file_count = #node:leaves()
comp:add_text(" (" .. file_count .. ")", "DiffviewDim1")
end
end

---@param conf DiffviewConfig
---@param panel FilePanel
---@param comp RenderComponent
Expand Down Expand Up @@ -161,28 +202,11 @@ local function render_file_tree_recurse(conf, panel, depth, comp)
"DiffviewFolderSign"
)

dir:add_text(ctx.name .. "/", "DiffviewFolderName")
-- Show file count grouped by status when folder is collapsed.
local tree_options = conf.file_panel.tree_options
dir:add_text(format_folder_name(ctx.name, tree_options), "DiffviewFolderName")
-- Show file count when folder is collapsed.
Comment thread
dlyongemallo marked this conversation as resolved.
if ctx.collapsed and ctx._node then
local leaves = ctx._node:leaves()
local status_counts = {}
for _, node in ipairs(leaves) do
local s = node.data.status or "?"
status_counts[s] = (status_counts[s] or 0) + 1
end

-- Sort status letters for consistent display order.
local statuses = vim.tbl_keys(status_counts)
table.sort(statuses)

dir:add_text(" (", "DiffviewDim1")
for i, s in ipairs(statuses) do
if i > 1 then
dir:add_text(" ", "DiffviewDim1")
end
dir:add_text(tostring(status_counts[s]) .. hl.get_status_icon(s), hl.get_git_hl(s))
end
dir:add_text(")", "DiffviewDim1")
render_folder_count(dir, ctx._node, tree_options)
end
dir:ln()

Expand Down Expand Up @@ -214,7 +238,7 @@ local function render_files(conf, panel, listing_style, comp)
end

---@param panel FilePanel
return function(panel)
local function render_panel(panel)
if not panel.render_data then
return
end
Expand Down Expand Up @@ -314,3 +338,13 @@ return function(panel)
end
end
end

return setmetatable({
-- Exposed for testing only.
_test = {
format_folder_name = format_folder_name,
render_folder_count = render_folder_count,
},
}, {
__call = function(_, panel) render_panel(panel) end,
})
13 changes: 11 additions & 2 deletions lua/diffview/scene/views/file_history/render.lua
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,12 @@ local formatters = {
local subject_hl
if ctx.panel.cur_item[1] == entry then
subject_hl = "DiffviewFilePanelSelected"
elseif entry.has_remote_ref then
elseif ctx.conf.file_history_panel.subject_highlight == "ref_aware" and entry.has_remote_ref then
subject_hl = "DiffviewCommitRemoteRef"
else
elseif ctx.conf.file_history_panel.subject_highlight == "ref_aware" then
subject_hl = "DiffviewCommitLocalOnly"
else
Comment thread
dlyongemallo marked this conversation as resolved.
subject_hl = "DiffviewFilePanelFileName"
end

comp:add_text(" " .. subject, subject_hl)
Expand Down Expand Up @@ -422,4 +424,11 @@ return {
clear_cache = function(panel)
cache[panel] = nil
end,
-- Exposed for testing only.
_test = {
render_stat_bar = render_stat_bar,
render_file_stats = render_file_stats,
formatters = formatters,
MAX_BAR_WIDTH = MAX_BAR_WIDTH,
},
}
65 changes: 65 additions & 0 deletions lua/diffview/tests/functional/file_history_render_spec.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
local helpers = require("diffview.tests.helpers")
local config = require("diffview.config")
local render = require("diffview.scene.views.file_history.render")

local eq = helpers.eq

local formatters = render._test.formatters

-- ---------------------------------------------------------------------------
-- Mock RenderComponent
-- ---------------------------------------------------------------------------
Expand Down Expand Up @@ -340,6 +343,68 @@ describe("file_history_render", function()
end)
end)

-- -----------------------------------------------------------------------
-- subject_highlight
-- -----------------------------------------------------------------------

describe("subject_highlight", function()
---Call the real formatters.subject and return the highlight group it used.
---@param entry table
---@param is_selected boolean
---@return string
local function render_subject_hl(entry, is_selected)
entry.commit = entry.commit or { subject = "test" }
local comp = make_comp()
local ctx = {
conf = config.get_config(),
panel = { cur_item = { is_selected and entry or {} } },
}
formatters.subject(comp, entry, ctx)
-- The subject is rendered as a single segment; return its hl group.
return comp.lines[1][1].hl
end

it("uses DiffviewFilePanelFileName for 'plain' mode", function()
local conf = config.get_config()
conf.file_history_panel.subject_highlight = "plain"
config.setup(conf)

local entry = { has_remote_ref = true }
eq("DiffviewFilePanelFileName", render_subject_hl(entry, false))
end)

it("uses DiffviewCommitRemoteRef for 'ref_aware' with remote ref", function()
local conf = config.get_config()
conf.file_history_panel.subject_highlight = "ref_aware"
config.setup(conf)

local entry = { has_remote_ref = true }
eq("DiffviewCommitRemoteRef", render_subject_hl(entry, false))
end)

it("uses DiffviewCommitLocalOnly for 'ref_aware' without remote ref", function()
local conf = config.get_config()
conf.file_history_panel.subject_highlight = "ref_aware"
config.setup(conf)

local entry = { has_remote_ref = false }
eq("DiffviewCommitLocalOnly", render_subject_hl(entry, false))
end)

it("uses DiffviewFilePanelSelected when entry is selected", function()
local conf = config.get_config()
conf.file_history_panel.subject_highlight = "ref_aware"
config.setup(conf)

local entry = { has_remote_ref = true }
eq("DiffviewFilePanelSelected", render_subject_hl(entry, true))
end)

it("defaults to 'ref_aware'", function()
eq("ref_aware", config.get_config().file_history_panel.subject_highlight)
end)
end)

-- -----------------------------------------------------------------------
-- date_format config default
-- -----------------------------------------------------------------------
Expand Down
46 changes: 46 additions & 0 deletions lua/diffview/tests/functional/panel_render_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ local config = require("diffview.config")
local Node = require("diffview.ui.models.file_tree.node").Node
local FileTree = require("diffview.ui.models.file_tree.file_tree").FileTree
local FileDict = require("diffview.vcs.file_dict").FileDict
local panel_render = require("diffview.scene.views.diff.render")

local eq = helpers.eq

local format_folder_name = panel_render._test.format_folder_name
local render_folder_count = panel_render._test.render_folder_count

-- ---------------------------------------------------------------------------
-- Mock RenderComponent (same pattern as file_history_render_spec.lua)
-- ---------------------------------------------------------------------------
Expand Down Expand Up @@ -248,6 +252,22 @@ describe("panel_render", function()
eq(")", dim_segs[#dim_segs])
end)

it("hides count entirely when folder_count_style is 'none'", function()
local conf = config.get_config()
conf.file_panel.tree_options.folder_count_style = "none"
config.setup(conf)

local dir_node = Node("src", { name = "src", path = "src", kind = "working", collapsed = true, status = "M" })
dir_node:add_child(Node("a.lua", { path = "src/a.lua", status = "M" }))
dir_node:add_child(Node("b.lua", { path = "src/b.lua", status = "A" }))

-- Call the real render_folder_count; it should produce no output.
local comp = make_comp()
render_folder_count(comp, dir_node, config.get_config().file_panel.tree_options)
eq(0, #comp:segments_by_hl("DiffviewDim1"))
eq("", comp:flat_text())
end)

it("does not show count when directory is expanded", function()
-- When collapsed is false, the count section is skipped.
local dir_node = Node("src", { name = "src", path = "src", kind = "working", collapsed = false, status = "M" })
Expand All @@ -269,6 +289,32 @@ describe("panel_render", function()
end)
end)

-- -----------------------------------------------------------------------
-- folder_trailing_slash
-- -----------------------------------------------------------------------

describe("folder_trailing_slash option", function()
it("appends trailing slash when enabled", function()
local conf = config.get_config()
conf.file_panel.tree_options.folder_trailing_slash = true
config.setup(conf)

eq("src/", format_folder_name("src", config.get_config().file_panel.tree_options))
end)

it("omits trailing slash when disabled", function()
local conf = config.get_config()
conf.file_panel.tree_options.folder_trailing_slash = false
config.setup(conf)

eq("src", format_folder_name("src", config.get_config().file_panel.tree_options))
end)

it("defaults to true", function()
eq(true, config.get_config().file_panel.tree_options.folder_trailing_slash)
end)
end)

-- -----------------------------------------------------------------------
-- Loading indicator (commit 5f1603a)
-- -----------------------------------------------------------------------
Expand Down
Loading