@@ -39,6 +39,7 @@ type DiffView struct {
3939 highlight bool
4040 height int
4141 width int
42+ xOffset int
4243 style Style
4344
4445 isComputed bool
@@ -130,6 +131,12 @@ func (dv *DiffView) Width(width int) *DiffView {
130131 return dv
131132}
132133
134+// XOffset sets the horizontal offset for the DiffView.
135+func (dv *DiffView) XOffset(xOffset int) *DiffView {
136+ dv.xOffset = xOffset
137+ return dv
138+}
139+
133140// String returns the string representation of the DiffView.
134141func (dv *DiffView) String() string {
135142 if err := dv.computeDiff(); err != nil {
@@ -323,8 +330,11 @@ outer:
323330 }
324331
325332 content := strings.TrimSuffix(l.Content, "\n")
333+ content = ansi.GraphemeWidth.Cut(content, dv.xOffset, len(content))
326334 content = ansi.Truncate(content, dv.codeWidth, "…")
327335
336+ leadingEllipsis := dv.xOffset > 0 && strings.TrimSpace(content) != ""
337+
328338 switch l.Kind {
329339 case udiff.Equal:
330340 if dv.lineNumbers {
@@ -332,7 +342,7 @@ outer:
332342 b.WriteString(dv.style.EqualLine.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
333343 }
334344 b.WriteString(fullContentStyle.Render(
335− dv.style.EqualLine.Code.Width(dv.fullCodeWidth).Render(" " + content),
345+ dv.style.EqualLine.Code.Width(dv.fullCodeWidth).Render(ternary(leadingEllipsis, " …", " ") + content),
336346 ))
337347 beforeLine++
338348 afterLine++
@@ -342,7 +352,7 @@ outer:
342352 b.WriteString(dv.style.InsertLine.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
343353 }
344354 b.WriteString(fullContentStyle.Render(
345− dv.style.InsertLine.Symbol.Render("+ ") +
355+ dv.style.InsertLine.Symbol.Render(ternary(leadingEllipsis, "+…", "+ ")) +
346356 dv.style.InsertLine.Code.Width(dv.codeWidth).Render(content),
347357 ))
348358 afterLine++
@@ -352,7 +362,7 @@ outer:
352362 b.WriteString(dv.style.DeleteLine.LineNumber.Render(pad(" ", dv.afterNumDigits)))
353363 }
354364 b.WriteString(fullContentStyle.Render(
355− dv.style.DeleteLine.Symbol.Render("- ") +
365+ dv.style.DeleteLine.Symbol.Render(ternary(leadingEllipsis, "-…", "- ")) +
356366 dv.style.DeleteLine.Code.Width(dv.codeWidth).Render(content),
357367 ))
358368 beforeLine++
@@ -427,13 +437,18 @@ outer:
427437 var afterContent string
428438 if l.before != nil {
429439 beforeContent = strings.TrimSuffix(l.before.Content, "\n")
440+ beforeContent = ansi.GraphemeWidth.Cut(beforeContent, dv.xOffset, len(beforeContent))
430441 beforeContent = ansi.Truncate(beforeContent, dv.codeWidth, "…")
431442 }
432443 if l.after != nil {
433444 afterContent = strings.TrimSuffix(l.after.Content, "\n")
445+ afterContent = ansi.GraphemeWidth.Cut(afterContent, dv.xOffset, len(afterContent))
434446 afterContent = ansi.Truncate(afterContent, dv.codeWidth+btoi(dv.extraColOnAfter), "…")
435447 }
436448
449+ leadingBeforeEllipsis := dv.xOffset > 0 && strings.TrimSpace(beforeContent) != ""
450+ leadingAfterEllipsis := dv.xOffset > 0 && strings.TrimSpace(afterContent) != ""
451+
437452 switch {
438453 case l.before == nil:
439454 if dv.lineNumbers {
@@ -447,7 +462,7 @@ outer:
447462 b.WriteString(dv.style.EqualLine.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
448463 }
449464 b.WriteString(beforeFullContentStyle.Render(
450− dv.style.EqualLine.Code.Width(dv.fullCodeWidth).Render(" " + beforeContent),
465+ dv.style.EqualLine.Code.Width(dv.fullCodeWidth).Render(ternary(leadingBeforeEllipsis, " …", " ") + beforeContent),
451466 ))
452467 beforeLine++
453468 case l.before.Kind == udiff.Delete:
@@ -455,7 +470,7 @@ outer:
455470 b.WriteString(dv.style.DeleteLine.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
456471 }
457472 b.WriteString(beforeFullContentStyle.Render(
458− dv.style.DeleteLine.Symbol.Render("- ") +
473+ dv.style.DeleteLine.Symbol.Render(ternary(leadingBeforeEllipsis, "-…", "- ")) +
459474 dv.style.DeleteLine.Code.Width(dv.codeWidth).Render(beforeContent),
460475 ))
461476 beforeLine++
@@ -474,7 +489,7 @@ outer:
474489 b.WriteString(dv.style.EqualLine.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
475490 }
476491 b.WriteString(afterFullContentStyle.Render(
477− dv.style.EqualLine.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" " + afterContent),
492+ dv.style.EqualLine.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(ternary(leadingAfterEllipsis, " …", " ") + afterContent),
478493 ))
479494 afterLine++
480495 case l.after.Kind == udiff.Insert:
@@ -482,7 +497,7 @@ outer:
482497 b.WriteString(dv.style.InsertLine.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
483498 }
484499 b.WriteString(afterFullContentStyle.Render(
485− dv.style.InsertLine.Symbol.Render("+ ") +
500+ dv.style.InsertLine.Symbol.Render(ternary(leadingAfterEllipsis, "+…", "+ ")) +
486501 dv.style.InsertLine.Code.Width(dv.codeWidth+btoi(dv.extraColOnAfter)).Render(afterContent),
487502 ))
488503 afterLine++