@@ -362,23 +362,29 @@ func (dv *DiffView) renderUnified() string {
fullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth)
printedLines := -dv.yOffset
-
- write := func(s string) {
- if printedLines >= 0 {
- b.WriteString(s)
- }
+ shouldWrite := func() bool { return printedLines >= 0 }
+
+ getContent := func(in string, ls LineStyle) (content string, leadingEllipsis bool) {
+ content = strings.TrimSuffix(in, "\n")
+ content = dv.hightlightCode(content, ls.Code.GetBackground())
+ content = ansi.GraphemeWidth.Cut(content, dv.xOffset, len(content))
+ content = ansi.Truncate(content, dv.codeWidth, "…")
+ leadingEllipsis = dv.xOffset > 0 && strings.TrimSpace(content) != ""
+ return
}
outer:
for i, h := range dv.unified.Hunks {
- ls := dv.style.DividerLine
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
- write(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.DividerLine
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
+ b.WriteString(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
+ }
+ content := ansi.Truncate(dv.hunkLineFor(h), dv.fullCodeWidth, "…")
+ b.WriteString(ls.Code.Width(dv.fullCodeWidth).Render(content))
+ b.WriteString("\n")
}
- content := ansi.Truncate(dv.hunkLineFor(h), dv.fullCodeWidth, "…")
- write(ls.Code.Width(dv.fullCodeWidth).Render(content))
- write("\n")
printedLines++
beforeLine := h.FromLine
@@ -390,80 +396,82 @@ outer:
isLastHunk := i+1 == len(dv.unified.Hunks)
isLastLine := j+1 == len(h.Lines)
if hasReachedHeight && (!isLastHunk || !isLastLine) {
- ls := dv.lineStyleForType(l.Kind)
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
- write(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
+ if shouldWrite() {
+ ls := dv.lineStyleForType(l.Kind)
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
+ b.WriteString(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
+ }
+ b.WriteString(fullContentStyle.Render(
+ ls.Code.Width(dv.fullCodeWidth).Render(" …"),
+ ))
+ b.WriteRune('\n')
}
- write(fullContentStyle.Render(
- ls.Code.Width(dv.fullCodeWidth).Render(" …"),
- ))
- write("\n")
break outer
}
- getContent := func(ls LineStyle) string {
- content := strings.TrimSuffix(l.Content, "\n")
- content = dv.hightlightCode(content, ls.Code.GetBackground())
- content = ansi.GraphemeWidth.Cut(content, dv.xOffset, len(content))
- content = ansi.Truncate(content, dv.codeWidth, "…")
- return content
- }
-
- leadingEllipsis := dv.xOffset > 0 && strings.TrimSpace(content) != ""
-
switch l.Kind {
case udiff.Equal:
- ls := dv.style.EqualLine
- content := getContent(ls)
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
- write(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.EqualLine
+ content, leadingEllipsis := getContent(l.Content, ls)
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
+ b.WriteString(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
+ }
+ b.WriteString(fullContentStyle.Render(
+ ls.Code.Width(dv.fullCodeWidth).Render(ternary(leadingEllipsis, " …", " ") + content),
+ ))
}
- write(fullContentStyle.Render(
- ls.Code.Width(dv.fullCodeWidth).Render(ternary(leadingEllipsis, " …", " ") + content),
- ))
beforeLine++
afterLine++
case udiff.Insert:
- ls := dv.style.InsertLine
- content := getContent(ls)
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
- write(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.InsertLine
+ content, leadingEllipsis := getContent(l.Content, ls)
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
+ b.WriteString(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
+ }
+ b.WriteString(fullContentStyle.Render(
+ ls.Symbol.Render(ternary(leadingEllipsis, "+…", "+ ")) +
+ ls.Code.Width(dv.codeWidth).Render(content),
+ ))
}
- write(fullContentStyle.Render(
- ls.Symbol.Render(ternary(leadingEllipsis, "+…", "+ ")) +
- ls.Code.Width(dv.codeWidth).Render(content),
- ))
afterLine++
case udiff.Delete:
- ls := dv.style.DeleteLine
- content := getContent(ls)
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
- write(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.DeleteLine
+ content, leadingEllipsis := getContent(l.Content, ls)
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
+ b.WriteString(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
+ }
+ b.WriteString(fullContentStyle.Render(
+ ls.Symbol.Render(ternary(leadingEllipsis, "-…", "- ")) +
+ ls.Code.Width(dv.codeWidth).Render(content),
+ ))
}
- write(fullContentStyle.Render(
- ls.Symbol.Render(ternary(leadingEllipsis, "-…", "- ")) +
- ls.Code.Width(dv.codeWidth).Render(content),
- ))
beforeLine++
}
- write("\n")
+ if shouldWrite() {
+ b.WriteRune('\n')
+ }
printedLines++
}
}
for printedLines < dv.height {
- ls := dv.style.MissingLine
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
- write(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.MissingLine
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
+ b.WriteString(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
+ }
+ b.WriteString(ls.Code.Width(dv.fullCodeWidth).Render(" "))
+ b.WriteRune('\n')
}
- write(ls.Code.Width(dv.fullCodeWidth).Render(" "))
- write("\n")
printedLines++
}
@@ -477,26 +485,32 @@ func (dv *DiffView) renderSplit() string {
beforeFullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth)
afterFullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth + btoi(dv.extraColOnAfter))
printedLines := -dv.yOffset
-
- write := func(s string) {
- if printedLines >= 0 {
- b.WriteString(s)
- }
+ shouldWrite := func() bool { return printedLines >= 0 }
+
+ getContent := func(in string, ls LineStyle) (content string, leadingEllipsis bool) {
+ content = strings.TrimSuffix(in, "\n")
+ content = dv.hightlightCode(content, ls.Code.GetBackground())
+ content = ansi.GraphemeWidth.Cut(content, dv.xOffset, len(content))
+ content = ansi.Truncate(content, dv.codeWidth, "…")
+ leadingEllipsis = dv.xOffset > 0 && strings.TrimSpace(content) != ""
+ return
}
outer:
for i, h := range dv.splitHunks {
- ls := dv.style.DividerLine
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
- }
- content := ansi.Truncate(dv.hunkLineFor(dv.unified.Hunks[i]), dv.fullCodeWidth, "…")
- write(ls.Code.Width(dv.fullCodeWidth).Render(content))
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.DividerLine
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
+ }
+ content := ansi.Truncate(dv.hunkLineFor(dv.unified.Hunks[i]), dv.fullCodeWidth, "…")
+ b.WriteString(ls.Code.Width(dv.fullCodeWidth).Render(content))
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
+ }
+ b.WriteString(ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "))
+ b.WriteRune('\n')
}
- write(ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "))
- write("\n")
printedLines++
beforeLine := h.fromLine
@@ -508,126 +522,129 @@ outer:
isLastHunk := i+1 == len(dv.unified.Hunks)
isLastLine := j+1 == len(h.lines)
if hasReachedHeight && (!isLastHunk || !isLastLine) {
- ls := dv.style.MissingLine
- if l.before != nil {
- ls = dv.lineStyleForType(l.before.Kind)
- }
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.MissingLine
+ if l.before != nil {
+ ls = dv.lineStyleForType(l.before.Kind)
+ }
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
+ }
+ b.WriteString(beforeFullContentStyle.Render(
+ ls.Code.Width(dv.fullCodeWidth).Render(" …"),
+ ))
+ ls = dv.style.MissingLine
+ if l.after != nil {
+ ls = dv.lineStyleForType(l.after.Kind)
+ }
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
+ }
+ b.WriteString(afterFullContentStyle.Render(
+ ls.Code.Width(dv.fullCodeWidth).Render(" …"),
+ ))
+ b.WriteRune('\n')
}
- write(beforeFullContentStyle.Render(
- ls.Code.Width(dv.fullCodeWidth).Render(" …"),
- ))
- ls = dv.style.MissingLine
- if l.after != nil {
- ls = dv.lineStyleForType(l.after.Kind)
- }
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
- }
- write(afterFullContentStyle.Render(
- ls.Code.Width(dv.fullCodeWidth).Render(" …"),
- ))
- write("\n")
break outer
}
- getContent := func(content string, ls LineStyle) string {
- content = strings.TrimSuffix(content, "\n")
- content = dv.hightlightCode(content, ls.Code.GetBackground())
- content = ansi.GraphemeWidth.Cut(content, dv.xOffset, len(content))
- content = ansi.Truncate(content, dv.codeWidth, "…")
- return content
- }
- getLeadingEllipsis := func(content string) bool {
- return dv.xOffset > 0 && strings.TrimSpace(content) != ""
- }
-
switch {
case l.before == nil:
- ls := dv.style.MissingLine
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.MissingLine
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
+ }
+ b.WriteString(beforeFullContentStyle.Render(
+ ls.Code.Width(dv.fullCodeWidth).Render(" "),
+ ))
}
- write(beforeFullContentStyle.Render(
- ls.Code.Width(dv.fullCodeWidth).Render(" "),
- ))
case l.before.Kind == udiff.Equal:
- ls := dv.style.EqualLine
- content := getContent(l.before.Content, ls)
- leadingEllipsis := getLeadingEllipsis(content)
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.EqualLine
+ content, leadingEllipsis := getContent(l.before.Content, ls)
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
+ }
+ b.WriteString(beforeFullContentStyle.Render(
+ ls.Code.Width(dv.fullCodeWidth).Render(ternary(leadingEllipsis, " …", " ") + content),
+ ))
}
- write(beforeFullContentStyle.Render(
- ls.Code.Width(dv.fullCodeWidth).Render(ternary(leadingEllipsis, " …", " ") + content),
- ))
beforeLine++
case l.before.Kind == udiff.Delete:
- ls := dv.style.DeleteLine
- content := getContent(l.before.Content, ls)
- leadingEllipsis := getLeadingEllipsis(content)
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.DeleteLine
+ content, leadingEllipsis := getContent(l.before.Content, ls)
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
+ }
+ b.WriteString(beforeFullContentStyle.Render(
+ ls.Symbol.Render(ternary(leadingEllipsis, "-…", "- ")) +
+ ls.Code.Width(dv.codeWidth).Render(content),
+ ))
}
- write(beforeFullContentStyle.Render(
- ls.Symbol.Render(ternary(leadingEllipsis, "-…", "- ")) +
- ls.Code.Width(dv.codeWidth).Render(content),
- ))
beforeLine++
}
switch {
case l.after == nil:
- ls := dv.style.MissingLine
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.MissingLine
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
+ }
+ b.WriteString(afterFullContentStyle.Render(
+ ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "),
+ ))
}
- write(afterFullContentStyle.Render(
- ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "),
- ))
case l.after.Kind == udiff.Equal:
- ls := dv.style.EqualLine
- content := getContent(l.after.Content, ls)
- leadingEllipsis := getLeadingEllipsis(content)
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.EqualLine
+ content, leadingEllipsis := getContent(l.after.Content, ls)
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
+ }
+ b.WriteString(afterFullContentStyle.Render(
+ ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(ternary(leadingEllipsis, " …", " ") + content),
+ ))
}
- write(afterFullContentStyle.Render(
- ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(ternary(leadingEllipsis, " …", " ") + content),
- ))
afterLine++
case l.after.Kind == udiff.Insert:
- ls := dv.style.InsertLine
- content := getContent(l.after.Content, ls)
- leadingEllipsis := getLeadingEllipsis(content)
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.InsertLine
+ content, leadingEllipsis := getContent(l.after.Content, ls)
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
+ }
+ b.WriteString(afterFullContentStyle.Render(
+ ls.Symbol.Render(ternary(leadingEllipsis, "+…", "+ ")) +
+ ls.Code.Width(dv.codeWidth+btoi(dv.extraColOnAfter)).Render(content),
+ ))
}
- write(afterFullContentStyle.Render(
- ls.Symbol.Render(ternary(leadingEllipsis, "+…", "+ ")) +
- ls.Code.Width(dv.codeWidth+btoi(dv.extraColOnAfter)).Render(content),
- ))
afterLine++
}
- write("\n")
+ if shouldWrite() {
+ b.WriteRune('\n')
+ }
printedLines++
}
}
for printedLines < dv.height {
- ls := dv.style.MissingLine
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
- }
- write(ls.Code.Width(dv.fullCodeWidth).Render(" "))
- if dv.lineNumbers {
- write(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
+ if shouldWrite() {
+ ls := dv.style.MissingLine
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
+ }
+ b.WriteString(ls.Code.Width(dv.fullCodeWidth).Render(" "))
+ if dv.lineNumbers {
+ b.WriteString(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
+ }
+ b.WriteString(ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "))
+ b.WriteRune('\n')
}
- write(ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "))
- write("\n")
printedLines++
}