on main help sign in
fix(diffview): add fixes + more extensive testing for height handling
21ca2aeAndrey Nering
internal/exp/diffview/Taskfile.yaml+20
@@ -40,3 +40,23 @@ tasks:
40 - for: sources
40 - for: sources
41 cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
41 cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
42 silent: true
42 silent: true
43+
44+ test:print:height:unified:
45+ desc: Print golden files for debugging
46+ method: none
47+ sources:
48+ - ./testdata/TestDiffViewHeight/Unified/LightMode/*.golden
49+ cmds:
50+ - for: sources
51+ cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
52+ silent: true
53+
54+ test:print:height:split:
55+ desc: Print golden files for debugging
56+ method: none
57+ sources:
58+ - ./testdata/TestDiffViewHeight/Split/LightMode/*.golden
59+ cmds:
60+ - for: sources
61+ cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
62+ silent: true
internal/exp/diffview/diffview.go+34
@@ -149,6 +149,9 @@ func (dv *DiffView) String() string {
149 if dv.width > 0 {
149 if dv.width > 0 {
150 style = style.MaxWidth(dv.width)
150 style = style.MaxWidth(dv.width)
151 }
151 }
152+ if dv.height > 0 {
153+ style = style.MaxHeight(dv.height)
154+ }
152
155
153 switch dv.layout {
156 switch dv.layout {
154 case layoutUnified:
157 case layoutUnified:
@@ -287,6 +290,7 @@ func (dv *DiffView) renderUnified() string {
287 var b strings.Builder
290 var b strings.Builder
288
291
289 fullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth)
292 fullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth)
293+ printedLines := 0
290
294
291 for _, h := range dv.unified.Hunks {
295 for _, h := range dv.unified.Hunks {
292 if dv.lineNumbers {
296 if dv.lineNumbers {
@@ -296,6 +300,7 @@ func (dv *DiffView) renderUnified() string {
296 content := ansi.Truncate(dv.hunkLineFor(h), dv.fullCodeWidth, "…")
300 content := ansi.Truncate(dv.hunkLineFor(h), dv.fullCodeWidth, "…")
297 b.WriteString(dv.style.DividerLine.Code.Width(dv.fullCodeWidth).Render(content))
301 b.WriteString(dv.style.DividerLine.Code.Width(dv.fullCodeWidth).Render(content))
298 b.WriteRune('\n')
302 b.WriteRune('\n')
303+ printedLines++
299
304
300 beforeLine := h.FromLine
305 beforeLine := h.FromLine
301 afterLine := h.ToLine
306 afterLine := h.ToLine
@@ -337,7 +342,19 @@ func (dv *DiffView) renderUnified() string {
337 beforeLine++
342 beforeLine++
338 }
343 }
339 b.WriteRune('\n')
344 b.WriteRune('\n')
345+
346+ printedLines++
347+ }
348+ }
349+
350+ for printedLines < dv.height {
351+ if dv.lineNumbers {
352+ b.WriteString(dv.style.MissingLine.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
353+ b.WriteString(dv.style.MissingLine.LineNumber.Render(pad(" ", dv.afterNumDigits)))
340 }
354 }
355+ b.WriteString(dv.style.MissingLine.Code.Width(dv.fullCodeWidth).Render(" "))
356+ b.WriteRune('\n')
357+ printedLines++
341 }
358 }
342
359
343 return b.String()
360 return b.String()
@@ -349,6 +366,7 @@ func (dv *DiffView) renderSplit() string {
349
366
350 beforeFullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth)
367 beforeFullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth)
351 afterFullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth + btoi(dv.extraColOnAfter))
368 afterFullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth + btoi(dv.extraColOnAfter))
369+ printedLines := 0
352
370
353 for i, h := range dv.splitHunks {
371 for i, h := range dv.splitHunks {
354 if dv.lineNumbers {
372 if dv.lineNumbers {
@@ -361,6 +379,7 @@ func (dv *DiffView) renderSplit() string {
361 }
379 }
362 b.WriteString(dv.style.DividerLine.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "))
380 b.WriteString(dv.style.DividerLine.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "))
363 b.WriteRune('\n')
381 b.WriteRune('\n')
382+ printedLines++
364
383
365 beforeLine := h.fromLine
384 beforeLine := h.fromLine
366 afterLine := h.toLine
385 afterLine := h.toLine
@@ -432,9 +451,24 @@ func (dv *DiffView) renderSplit() string {
432 }
451 }
433
452
434 b.WriteRune('\n')
453 b.WriteRune('\n')
454+
455+ printedLines++
435 }
456 }
436 }
457 }
437
458
459+ for printedLines < dv.height {
460+ if dv.lineNumbers {
461+ b.WriteString(dv.style.MissingLine.LineNumber.Render(pad("…", dv.beforeNumDigits)))
462+ }
463+ b.WriteString(dv.style.MissingLine.Code.Width(dv.fullCodeWidth).Render(" "))
464+ if dv.lineNumbers {
465+ b.WriteString(dv.style.MissingLine.LineNumber.Render(pad("…", dv.afterNumDigits)))
466+ }
467+ b.WriteString(dv.style.MissingLine.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "))
468+ b.WriteRune('\n')
469+ printedLines++
470+ }
471+
438 return b.String()
472 return b.String()
439}
473}
440
474
internal/exp/diffview/diffview_test.go+34
@@ -167,6 +167,32 @@ func TestDiffViewWidth(t *testing.T) {
167 }
167 }
168}
168}
169
169
170+func TestDiffViewHeight(t *testing.T) {
171+ for layoutName, layoutFunc := range LayoutFuncs {
172+ t.Run(layoutName, func(t *testing.T) {
173+ for themeName, themeFunc := range ThemeFuncs {
174+ t.Run(themeName, func(t *testing.T) {
175+ for height := 1; height <= 20; height++ {
176+ t.Run(fmt.Sprintf("HeightOf%03d", height), func(t *testing.T) {
177+ dv := diffview.New().
178+ Before("main.go", TestMultipleHunksBefore).
179+ After("main.go", TestMultipleHunksAfter).
180+ Height(height)
181+ dv = layoutFunc(dv)
182+ dv = themeFunc(dv)
183+
184+ output := dv.String()
185+ golden.RequireEqual(t, []byte(output))
186+
187+ assertHeight(t, height, output)
188+ })
189+ }
190+ })
191+ }
192+ })
193+ }
194+}
195+
170func assertLineWidth(t *testing.T, expected int, output string) {
196func assertLineWidth(t *testing.T, expected int, output string) {
171 var lineWidth int
197 var lineWidth int
172 for line := range strings.SplitSeq(output, "\n") {
198 for line := range strings.SplitSeq(output, "\n") {
@@ -176,3 +202,11 @@ func assertLineWidth(t *testing.T, expected int, output string) {
176 t.Errorf("expected output width to be == %d, got %d", expected, lineWidth)
202 t.Errorf("expected output width to be == %d, got %d", expected, lineWidth)
177 }
203 }
178}
204}
205+
206+func assertHeight(t *testing.T, expected int, output string) {
207+ output = strings.TrimSuffix(output, "\n")
208+ lines := strings.Count(output, "\n") + 1
209+ if lines != expected {
210+ t.Errorf("expected output height to be == %d, got %d", expected, lines)
211+ }
212+}