You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
1.5 KiB
Go

package multilinediff
import (
"fmt"
"strings"
"github.com/google/go-cmp/cmp"
)
type diffType int
const (
diffTypeEqual diffType = iota
diffTypeChange
diffTypeAdd
)
type diffLine struct {
diff diffType
old string
new string
}
func (l diffLine) toLine(length int) string {
line := ""
switch l.diff {
case diffTypeChange:
line += "- "
case diffTypeAdd:
line += "+ "
default:
line += " "
}
line += l.old
for i := 0; i < length-len(l.old); i++ {
line += " "
}
line += " "
line += l.new
return line
}
type Reporter struct {
LineSep string
path cmp.Path
lines []diffLine
diffCount int
}
func (r *Reporter) PushStep(ps cmp.PathStep) {
r.path = append(r.path, ps)
}
func (r *Reporter) Report(rs cmp.Result) {
line := diffLine{}
vOld, vNew := r.path.Last().Values()
if !rs.Equal() {
r.diffCount++
if vOld.IsValid() {
line.diff = diffTypeChange
line.old = fmt.Sprintf("%+v", vOld)
}
if vNew.IsValid() {
if line.diff == diffTypeEqual {
line.diff = diffTypeAdd
}
line.new = fmt.Sprintf("%+v", vNew)
}
} else {
line.old = fmt.Sprintf("%+v", vOld)
line.new = fmt.Sprintf("%+v", vOld)
}
r.lines = append(r.lines, line)
}
func (r *Reporter) PopStep() {
r.path = r.path[:len(r.path)-1]
}
func (r *Reporter) String() string {
maxLen := 0
for _, l := range r.lines {
if len(l.old) > maxLen {
maxLen = len(l.old)
}
}
diffLines := []string{}
for _, l := range r.lines {
diffLines = append(diffLines, l.toLine(maxLen))
}
return strings.Join(diffLines, r.LineSep)
}