on main help sign in
refactor(diffview): cache num digits on a struct variable
commit864735a540a0fb141dc6f67a8eff44a4df2488aa authorAndrey Nering <andreynering@users.noreply.github.com> dateMon 9 Jun 2025, 16:50 (1 year ago) parenteb50c92
1 file changed+28−27
internal/exp/diffview/diffview.go+28−27
internal/exp/diffview/diffview.go+28−27
@@ -45,8 +45,10 @@ type DiffView struct {
4545
4646 splitHunks []splitHunk
4747
48− codeWidth int
49− fullCodeWidth int // with leading symbols
48+ codeWidth int
49+ fullCodeWidth int // with leading symbols
50+ beforeNumDigits int
51+ afterNumDigits int
5052}
5153
5254// New creates a new DiffView with default settings.
@@ -130,6 +132,7 @@ func (dv *DiffView) String() string {
130132 return err.Error()
131133 }
132134 dv.convertDiffToSplit()
135+ dv.detectNumDigits()
133136 dv.detectCodeWidth()
134137
135138 switch dv.layout {
@@ -144,14 +147,12 @@ func (dv *DiffView) String() string {
144147
145148// renderUnified renders the unified diff view as a string.
146149func (dv *DiffView) renderUnified() string {
147− beforeNumDigits, afterNumDigits := dv.lineNumberDigits()
148−
149150 var b strings.Builder
150151
151152 for _, h := range dv.unified.Hunks {
152153 if dv.lineNumbers {
153− b.WriteString(dv.style.DividerLine.LineNumber.Render(pad("…", beforeNumDigits)))
154− b.WriteString(dv.style.DividerLine.LineNumber.Render(pad("…", afterNumDigits)))
154+ b.WriteString(dv.style.DividerLine.LineNumber.Render(pad("…", dv.beforeNumDigits)))
155+ b.WriteString(dv.style.DividerLine.LineNumber.Render(pad("…", dv.afterNumDigits)))
155156 }
156157 b.WriteString(dv.style.DividerLine.Code.Width(dv.fullCodeWidth).Render(dv.hunkLineFor(h)))
157158 b.WriteRune('\n')
@@ -165,24 +166,24 @@ func (dv *DiffView) renderUnified() string {
165166 switch l.Kind {
166167 case udiff.Equal:
167168 if dv.lineNumbers {
168− b.WriteString(dv.style.EqualLine.LineNumber.Render(pad(beforeLine, beforeNumDigits)))
169− b.WriteString(dv.style.EqualLine.LineNumber.Render(pad(afterLine, afterNumDigits)))
169+ b.WriteString(dv.style.EqualLine.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
170+ b.WriteString(dv.style.EqualLine.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
170171 }
171172 b.WriteString(dv.style.EqualLine.Code.Width(dv.fullCodeWidth).Render(" " + content))
172173 beforeLine++
173174 afterLine++
174175 case udiff.Insert:
175176 if dv.lineNumbers {
176− b.WriteString(dv.style.InsertLine.LineNumber.Render(pad(" ", beforeNumDigits)))
177− b.WriteString(dv.style.InsertLine.LineNumber.Render(pad(afterLine, afterNumDigits)))
177+ b.WriteString(dv.style.InsertLine.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
178+ b.WriteString(dv.style.InsertLine.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
178179 }
179180 b.WriteString(dv.style.InsertLine.Symbol.Render("+ "))
180181 b.WriteString(dv.style.InsertLine.Code.Width(dv.codeWidth).Render(content))
181182 afterLine++
182183 case udiff.Delete:
183184 if dv.lineNumbers {
184− b.WriteString(dv.style.DeleteLine.LineNumber.Render(pad(beforeLine, beforeNumDigits)))
185− b.WriteString(dv.style.DeleteLine.LineNumber.Render(pad(" ", afterNumDigits)))
185+ b.WriteString(dv.style.DeleteLine.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
186+ b.WriteString(dv.style.DeleteLine.LineNumber.Render(pad(" ", dv.afterNumDigits)))
186187 }
187188 b.WriteString(dv.style.DeleteLine.Symbol.Render("- "))
188189 b.WriteString(dv.style.DeleteLine.Code.Width(dv.codeWidth).Render(content))
@@ -197,17 +198,15 @@ func (dv *DiffView) renderUnified() string {
197198
198199// renderSplit renders the split (side-by-side) diff view as a string.
199200func (dv *DiffView) renderSplit() string {
200− beforeNumDigits, afterNumDigits := dv.lineNumberDigits()
201−
202201 var b strings.Builder
203202
204203 for i, h := range dv.splitHunks {
205204 if dv.lineNumbers {
206− b.WriteString(dv.style.DividerLine.LineNumber.Render(pad("…", beforeNumDigits)))
205+ b.WriteString(dv.style.DividerLine.LineNumber.Render(pad("…", dv.beforeNumDigits)))
207206 }
208207 b.WriteString(dv.style.DividerLine.Code.Width(dv.fullCodeWidth).Render(dv.hunkLineFor(dv.unified.Hunks[i])))
209208 if dv.lineNumbers {
210− b.WriteString(dv.style.DividerLine.LineNumber.Render(pad("…", afterNumDigits)))
209+ b.WriteString(dv.style.DividerLine.LineNumber.Render(pad("…", dv.afterNumDigits)))
211210 }
212211 b.WriteString(dv.style.DividerLine.Code.Width(dv.fullCodeWidth).Render(" "))
213212 b.WriteRune('\n')
@@ -228,18 +227,18 @@ func (dv *DiffView) renderSplit() string {
228227 switch {
229228 case l.before == nil:
230229 if dv.lineNumbers {
231− b.WriteString(dv.style.MissingLine.LineNumber.Render(pad(" ", beforeNumDigits)))
230+ b.WriteString(dv.style.MissingLine.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
232231 }
233232 b.WriteString(dv.style.MissingLine.Code.Width(dv.fullCodeWidth).Render(" "))
234233 case l.before.Kind == udiff.Equal:
235234 if dv.lineNumbers {
236− b.WriteString(dv.style.EqualLine.LineNumber.Render(pad(beforeLine, beforeNumDigits)))
235+ b.WriteString(dv.style.EqualLine.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
237236 }
238237 b.WriteString(dv.style.EqualLine.Code.Width(dv.fullCodeWidth).Render(" " + beforeContent))
239238 beforeLine++
240239 case l.before.Kind == udiff.Delete:
241240 if dv.lineNumbers {
242− b.WriteString(dv.style.DeleteLine.LineNumber.Render(pad(beforeLine, beforeNumDigits)))
241+ b.WriteString(dv.style.DeleteLine.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
243242 }
244243 b.WriteString(dv.style.DeleteLine.Symbol.Render("- "))
245244 b.WriteString(dv.style.DeleteLine.Code.Width(dv.codeWidth).Render(beforeContent))
@@ -249,18 +248,18 @@ func (dv *DiffView) renderSplit() string {
249248 switch {
250249 case l.after == nil:
251250 if dv.lineNumbers {
252− b.WriteString(dv.style.MissingLine.LineNumber.Render(pad(" ", afterNumDigits)))
251+ b.WriteString(dv.style.MissingLine.LineNumber.Render(pad(" ", dv.afterNumDigits)))
253252 }
254253 b.WriteString(dv.style.MissingLine.Code.Width(dv.fullCodeWidth).Render(" "))
255254 case l.after.Kind == udiff.Equal:
256255 if dv.lineNumbers {
257− b.WriteString(dv.style.EqualLine.LineNumber.Render(pad(afterLine, afterNumDigits)))
256+ b.WriteString(dv.style.EqualLine.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
258257 }
259258 b.WriteString(dv.style.EqualLine.Code.Width(dv.fullCodeWidth).Render(" " + afterContent))
260259 afterLine++
261260 case l.after.Kind == udiff.Insert:
262261 if dv.lineNumbers {
263− b.WriteString(dv.style.InsertLine.LineNumber.Render(pad(afterLine, afterNumDigits)))
262+ b.WriteString(dv.style.InsertLine.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
264263 }
265264 b.WriteString(dv.style.InsertLine.Symbol.Render("+ "))
266265 b.WriteString(dv.style.InsertLine.Code.Width(dv.codeWidth).Render(afterContent))
@@ -293,14 +292,16 @@ func (dv *DiffView) computeDiff() error {
293292 return dv.err
294293}
295294
296−// lineNumberDigits calculates the maximum number of digits needed for before and
295+// detectNumDigits calculates the maximum number of digits needed for before and
297296// after line numbers.
298−func (dv *DiffView) lineNumberDigits() (maxBefore, maxAfter int) {
297+func (dv *DiffView) detectNumDigits() {
298+ dv.beforeNumDigits = 0
299+ dv.afterNumDigits = 0
300+
299301 for _, h := range dv.unified.Hunks {
300− maxBefore = max(maxBefore, len(strconv.Itoa(h.FromLine+len(h.Lines))))
301− maxAfter = max(maxAfter, len(strconv.Itoa(h.ToLine+len(h.Lines))))
302+ dv.beforeNumDigits = max(dv.beforeNumDigits, len(strconv.Itoa(h.FromLine+len(h.Lines))))
303+ dv.afterNumDigits = max(dv.afterNumDigits, len(strconv.Itoa(h.ToLine+len(h.Lines))))
302304 }
303− return
304305}
305306
306307func (dv *DiffView) hunkLineFor(h *udiff.Hunk) string {