@@ -1,6 +1,7 @@
11package diffview
22
33import (
4+ "fmt"
45 "os"
56 "strconv"
67 "strings"
@@ -125,22 +126,34 @@ func (dv *DiffView) String() string {
125126 }
126127 dv.detectWidth()
127128
128− lineNumberWidth := func(start, num int) int {
129− return len(strconv.Itoa(start + num))
130− }
129+ codeWidth := dv.width - leadingSymbolsSize
130+ beforeNumDigits, afterNumDigits := dv.lineNumberDigits()
131131
132132 var b strings.Builder
133133
134− for _, h := range dv.unified.Hunks {
134+ for i, h := range dv.unified.Hunks {
135+ beforeShownLines, afterShownLines := dv.hunkShownLines(i)
136+
137+ if dv.lineNumbers {
138+ b.WriteString(dv.style.DividerLine.LineNumber.Render(pad("…", beforeNumDigits)))
139+ b.WriteString(dv.style.DividerLine.LineNumber.Render(pad("…", afterNumDigits)))
140+ }
141+ b.WriteString(dv.style.DividerLine.Code.Width(codeWidth + leadingSymbolsSize).Render(
142+ fmt.Sprintf(
143+ " @@ -%d,%d +%d,%d @@",
144+ h.FromLine,
145+ beforeShownLines,
146+ h.ToLine,
147+ afterShownLines,
148+ ),
149+ ))
150+ b.WriteRune('\n')
151+
135152 beforeLine := h.FromLine
136153 afterLine := h.ToLine
137154
138− beforeNumDigits := lineNumberWidth(h.FromLine, len(h.Lines))
139− afterNumDigits := lineNumberWidth(h.ToLine, len(h.Lines))
140−
141155 for _, l := range h.Lines {
142156 content := strings.TrimSuffix(l.Content, "\n")
143− codeWidth := dv.width - leadingSymbolsSize
144157
145158 switch l.Kind {
146159 case udiff.Equal:
@@ -194,6 +207,33 @@ func (dv *DiffView) computeDiff() error {
194207 return dv.err
195208}
196209
210+// lineNumberDigits calculates the maximum number of digits needed for before and
211+// after line numbers.
212+func (dv *DiffView) lineNumberDigits() (maxBefore, maxAfter int) {
213+ for _, h := range dv.unified.Hunks {
214+ maxBefore = max(maxBefore, len(strconv.Itoa(h.FromLine+len(h.Lines))))
215+ maxAfter = max(maxAfter, len(strconv.Itoa(h.ToLine+len(h.Lines))))
216+ }
217+ return
218+}
219+
220+// hunkShownLines calculates the number of lines shown in a hunk for both before
221+// and after versions.
222+func (dv *DiffView) hunkShownLines(i int) (before, after int) {
223+ for _, l := range dv.unified.Hunks[i].Lines {
224+ switch l.Kind {
225+ case udiff.Equal:
226+ before++
227+ after++
228+ case udiff.Insert:
229+ after++
230+ case udiff.Delete:
231+ before++
232+ }
233+ }
234+ return
235+}
236+
197237func (dv *DiffView) detectWidth() {
198238 if dv.width > 0 {
199239 return