Skip to content

Commit 36c8813

Browse files
committed
refactor(renderer): More ergonomic rendering API.
1 parent e48f04d commit 36c8813

File tree

5 files changed

+158
-300
lines changed

5 files changed

+158
-300
lines changed

lua/diffview/hl.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,11 @@ function M.get_file_icon(name, ext, render_data, line_idx, offset)
339339
end
340340

341341
if icon then
342-
if hl then
342+
if hl and render_data then
343343
render_data:add_hl(hl, line_idx, offset, offset + string.len(icon) + 1)
344344
end
345345

346-
return icon .. " "
346+
return icon .. " ", hl
347347
end
348348

349349
return ""

lua/diffview/renderer.lua

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ M.last_draw_time = 0
3131
---@field parent RenderComponent
3232
---@field lines string[]
3333
---@field hl renderer.HlList
34+
---@field line_buffer string
3435
---@field components RenderComponent[]
3536
---@field lstart integer 0 indexed, Inclusive
3637
---@field lend integer Exclusive
@@ -44,6 +45,7 @@ function RenderComponent:init(name)
4445
self.name = name or RenderComponent.next_uid()
4546
self.lines = {}
4647
self.hl = {}
48+
self.line_buffer = ""
4749
self.components = {}
4850
self.lstart = -1
4951
self.lend = -1
@@ -132,9 +134,16 @@ function RenderComponent:remove_component(component)
132134
return false
133135
end
134136

135-
---@param line string
136-
function RenderComponent:add_line(line)
137-
self.lines[#self.lines + 1] = line
137+
---@param line string?
138+
---@param hl_group string?
139+
function RenderComponent:add_line(line, hl_group)
140+
if line and hl_group then
141+
local first = #self.line_buffer
142+
self:add_hl(hl_group, #self.lines, first, first + #line)
143+
end
144+
145+
self.lines[#self.lines + 1] = self.line_buffer .. (line or "")
146+
self.line_buffer = ""
138147
end
139148

140149
---@param group string
@@ -150,6 +159,23 @@ function RenderComponent:add_hl(group, line_idx, first, last)
150159
}
151160
end
152161

162+
---@param text string
163+
---@param hl_group string?
164+
function RenderComponent:add_text(text, hl_group)
165+
if hl_group then
166+
local first = #self.line_buffer
167+
self:add_hl(hl_group, #self.lines, first, first + #text)
168+
end
169+
170+
self.line_buffer = self.line_buffer .. text
171+
end
172+
173+
---Finalize current line
174+
function RenderComponent:ln()
175+
self.lines[#self.lines + 1] = self.line_buffer
176+
self.line_buffer = ""
177+
end
178+
153179
function RenderComponent:clear()
154180
self.lines = {}
155181
self.hl = {}

lua/diffview/scene/views/diff/render.lua

Lines changed: 54 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -8,57 +8,40 @@ local utils = require("diffview.utils")
88
local function render_file(comp, show_path, depth)
99
---@type table
1010
local file = comp.context
11-
local offset = 0
1211

13-
comp:add_hl(hl.get_git_hl(file.status), 0, 0, 1)
14-
local s = file.status .. " "
12+
comp:add_text(file.status .. " ", hl.get_git_hl(file.status))
13+
1514
if depth then
16-
s = s .. string.rep(" ", depth * 2 + 2)
15+
comp:add_text(string.rep(" ", depth * 2 + 2))
1716
end
1817

19-
offset = #s
20-
local icon = hl.get_file_icon(file.basename, file.extension, comp, 0, offset)
21-
22-
offset = offset + #icon
23-
comp:add_hl("DiffviewFilePanelFileName", 0, offset, offset + #file.basename)
24-
s = s .. icon .. file.basename
18+
local icon, icon_hl = hl.get_file_icon(file.basename, file.extension)
19+
comp:add_text(icon, icon_hl)
20+
comp:add_text(file.basename, "DiffviewFilePanelFileName")
2521

2622
if file.stats then
27-
offset = #s + 1
28-
2923
if file.stats.additions then
30-
comp:add_hl("DiffviewFilePanelInsertions", 0, offset, offset + string.len(file.stats.additions))
31-
offset = offset + string.len(file.stats.additions) + 2
32-
comp:add_hl("DiffviewFilePanelDeletions", 0, offset, offset + string.len(file.stats.deletions))
33-
s = s .. " " .. file.stats.additions .. ", " .. file.stats.deletions
24+
comp:add_text(" " .. file.stats.additions, "DiffviewFilePanelInsertions")
25+
comp:add_text(", ")
26+
comp:add_text(tostring(file.stats.deletions), "DiffviewFilePanelDeletions")
3427
elseif file.stats.conflicts then
35-
local conflicts
36-
37-
if file.stats.conflicts == 0 then
38-
conflicts = config.get_config().signs.done
39-
comp:add_hl("DiffviewFilePanelInsertions", 0, offset, offset + string.len(conflicts))
40-
else
41-
conflicts = tostring(file.stats.conflicts)
42-
comp:add_hl("DiffviewFilePanelConflicts", 0, offset, offset + string.len(conflicts))
43-
end
44-
45-
s = s .. " " .. conflicts
28+
local has_conflicts = file.stats.conflicts > 0
29+
comp:add_text(
30+
" " .. (has_conflicts and file.stats.conflicts or config.get_config().signs.done),
31+
has_conflicts and "DiffviewFilePanelConflicts" or "DiffviewFilePanelInsertions"
32+
)
4633
end
4734
end
4835

4936
if file.kind == "conflicting" and not (file.stats and file.stats.conflicts) then
50-
offset = #s + 1
51-
comp:add_hl("DiffviewFilePanelConflicts", 0, offset, offset + 1)
52-
s = s .. " !"
37+
comp:add_text(" !", "DiffviewFilePanelConflicts")
5338
end
5439

5540
if show_path then
56-
offset = #s + 1
57-
comp:add_hl("DiffviewFilePanelPath", 0, offset, offset + #file.parent_path)
58-
s = s .. " " .. file.parent_path
41+
comp:add_text(" " .. file.parent_path, "DiffviewFilePanelPath")
5942
end
6043

61-
comp:add_line(s)
44+
comp:ln()
6245
end
6346

6447
---@param comp RenderComponent
@@ -73,48 +56,45 @@ end
7356
---@return string
7457
local function get_dir_status_text(ctx, tree_options)
7558
local folder_statuses = tree_options.folder_statuses
59+
7660
if folder_statuses == "always" or (folder_statuses == "only_folded" and ctx.collapsed) then
7761
return ctx.status
7862
end
63+
7964
return " "
8065
end
8166

8267
---@param depth integer
8368
---@param comp RenderComponent
8469
local function render_file_tree_recurse(depth, comp)
8570
local conf = config.get_config()
86-
local offset, s
8771

8872
if comp.name == "file" then
8973
render_file(comp, false, depth)
9074
return
9175
end
92-
if comp.name ~= "wrapper" then
93-
return
94-
end
76+
if comp.name ~= "wrapper" then return end
9577

9678
local dir = comp.components[1]
9779
---@type table
9880
local ctx = dir.context
9981

100-
dir:add_hl(hl.get_git_hl(ctx.status), 0, 0, 1)
101-
s = get_dir_status_text(ctx, conf.file_panel.tree_options) .. " "
102-
103-
s = s .. string.rep(" ", depth * 2)
104-
offset = #s
82+
dir:add_text(
83+
get_dir_status_text(ctx, conf.file_panel.tree_options) .. " ",
84+
hl.get_git_hl(ctx.status)
85+
)
86+
dir:add_text(string.rep(" ", depth * 2))
87+
dir:add_text(ctx.collapsed and conf.signs.fold_closed or conf.signs.fold_open, "DiffviewNonText")
10588

106-
local fold = ctx.collapsed and conf.signs.fold_closed or conf.signs.fold_open
107-
local icon = ""
10889
if conf.use_icons then
109-
icon = " " .. (ctx.collapsed and conf.icons.folder_closed or conf.icons.folder_open)
90+
dir:add_text(
91+
" " .. (ctx.collapsed and conf.icons.folder_closed or conf.icons.folder_open) .. " ",
92+
"DiffviewFolderSign"
93+
)
11094
end
111-
dir:add_hl("DiffviewNonText", 0, offset, offset + #fold)
112-
dir:add_hl("DiffviewFolderSign", 0, offset + #fold + 1, offset + #fold + 1 + #icon)
113-
s = string.format("%s%s%s ", s, fold, icon)
11495

115-
offset = #s
116-
dir:add_hl("DiffviewFolderName", 0, offset, offset + #ctx.name)
117-
dir:add_line(s .. ctx.name)
96+
dir:add_text(ctx.name, "DiffviewFolderName")
97+
dir:ln()
11898

11999
if not ctx.collapsed then
120100
for i = 2, #comp.components do
@@ -154,51 +134,37 @@ return function(panel)
154134

155135
---@type RenderComponent
156136
local comp = panel.components.path.comp
157-
local line_idx = 0
158-
local s = utils.path:shorten(utils.path:vim_fnamemodify(panel.adapter.ctx.toplevel, ":~"), width - 6)
159-
comp:add_hl("DiffviewFilePanelRootPath", line_idx, 0, #s)
160-
comp:add_line(s)
161137

162-
local change_count
138+
comp:add_line(
139+
utils.path:shorten(utils.path:vim_fnamemodify(panel.adapter.ctx.toplevel, ":~"), width - 6),
140+
"DiffviewFilePanelRootPath"
141+
)
163142

164143
if #panel.files.conflicting > 0 then
165144
comp = panel.components.conflicting.title.comp
166-
line_idx = 0
167-
s = "Conflicts"
168-
comp:add_hl("DiffviewFilePanelTitle", line_idx, 0, #s)
169-
change_count = "(" .. #panel.files.conflicting .. ")"
170-
comp:add_hl("DiffviewFilePanelCounter", line_idx, #s + 1, #s + 1 + string.len(change_count))
171-
s = s .. " " .. change_count
172-
comp:add_line(s)
145+
comp:add_text("Conflicts ", "DiffviewFilePanelTitle")
146+
comp:add_text("(" .. #panel.files.conflicting .. ")", "DiffviewFilePanelCounter")
147+
comp:ln()
173148

174149
render_files(panel.listing_style, panel.components.conflicting.files.comp)
175150
end
176151

177152
comp = panel.components.working.title.comp
178-
line_idx = 0
179-
if #panel.files.conflicting > 0 then
180-
comp:add_line("")
181-
line_idx = 1
182-
end
183-
s = "Changes"
184-
comp:add_hl("DiffviewFilePanelTitle", line_idx, 0, #s)
185-
change_count = "(" .. #panel.files.working .. ")"
186-
comp:add_hl("DiffviewFilePanelCounter", line_idx, #s + 1, #s + 1 + string.len(change_count))
187-
s = s .. " " .. change_count
188-
comp:add_line(s)
153+
154+
if #panel.files.conflicting > 0 then comp:add_line() end
155+
156+
comp:add_text("Changes ", "DiffviewFilePanelTitle")
157+
comp:add_text("(" .. #panel.files.working .. ")", "DiffviewFilePanelCounter")
158+
comp:ln()
189159

190160
render_files(panel.listing_style, panel.components.working.files.comp)
191161

192162
if #panel.files.staged > 0 then
193163
comp = panel.components.staged.title.comp
194-
comp:add_line("")
195-
line_idx = 1
196-
s = "Staged changes"
197-
comp:add_hl("DiffviewFilePanelTitle", line_idx, 0, #s)
198-
change_count = "(" .. #panel.files.staged .. ")"
199-
comp:add_hl("DiffviewFilePanelCounter", line_idx, #s + 1, #s + 1 + string.len(change_count))
200-
s = s .. " " .. change_count
201-
comp:add_line(s)
164+
comp:add_line()
165+
comp:add_text("Staged changes ", "DiffviewFilePanelTitle")
166+
comp:add_text("(" .. #panel.files.staged .. ")", "DiffviewFilePanelCounter")
167+
comp:ln()
202168

203169
render_files(panel.listing_style, panel.components.staged.files.comp)
204170
end
@@ -207,25 +173,15 @@ return function(panel)
207173
local extra_info = utils.vec_join({ panel.rev_pretty_name }, panel.path_args or {})
208174

209175
comp = panel.components.info.title.comp
210-
line_idx = 0
211-
comp:add_line("")
212-
line_idx = line_idx + 1
213-
214-
s = "Showing changes for:"
215-
comp:add_hl("DiffviewFilePanelTitle", line_idx, 0, #s)
216-
comp:add_line(s)
176+
comp:add_line()
177+
comp:add_line("Showing changes for:", "DiffviewFilePanelTitle")
217178

218179
comp = panel.components.info.entries.comp
219-
line_idx = 0
180+
220181
for _, arg in ipairs(extra_info) do
221182
local relpath = utils.path:relative(arg, panel.adapter.ctx.toplevel)
222-
if relpath == "" then
223-
relpath = "."
224-
end
225-
s = utils.path:shorten(relpath, width - 5)
226-
comp:add_hl("DiffviewFilePanelPath", line_idx, 0, #s)
227-
comp:add_line(s)
228-
line_idx = line_idx + 1
183+
if relpath == "" then relpath = "." end
184+
comp:add_line(utils.path:shorten(relpath, width - 5), "DiffviewFilePanelPath")
229185
end
230186
end
231187
end

0 commit comments

Comments
 (0)