split.go

 1package diffview
 2
 3import (
 4	"slices"
 5
 6	"github.com/aymanbagabas/go-udiff"
 7	"github.com/charmbracelet/x/exp/slice"
 8)
 9
10type splitHunk struct {
11	fromLine int
12	toLine   int
13	lines    []*splitLine
14}
15
16type splitLine struct {
17	before *udiff.Line
18	after  *udiff.Line
19}
20
21func hunkToSplit(h *udiff.Hunk) (sh splitHunk) {
22	lines := slices.Clone(h.Lines)
23	sh = splitHunk{
24		fromLine: h.FromLine,
25		toLine:   h.ToLine,
26		lines:    make([]*splitLine, 0, len(lines)),
27	}
28
29	for {
30		var ul udiff.Line
31		var ok bool
32		ul, lines, ok = slice.Shift(lines)
33		if !ok {
34			break
35		}
36
37		var sl splitLine
38
39		switch ul.Kind {
40
41		// For equal lines, add as is
42		case udiff.Equal:
43			sl.before = &ul
44			sl.after = &ul
45
46		// For inserted lines, set after and keep before as nil
47		case udiff.Insert:
48			sl.before = nil
49			sl.after = &ul
50
51		// For deleted lines, set before and loop over the next lines
52		// searching for the equivalent after line.
53		case udiff.Delete:
54			sl.before = &ul
55
56		inner:
57			for i, l := range lines {
58				switch l.Kind {
59				case udiff.Insert:
60					var ll udiff.Line
61					ll, lines, _ = slice.DeleteAt(lines, i)
62					sl.after = &ll
63					break inner
64				case udiff.Equal:
65					break inner
66				}
67			}
68		}
69
70		sh.lines = append(sh.lines, &sl)
71	}
72
73	return
74}