diff --git a/README.md b/README.md index df057d2..71fc40b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# pretty-diff-reporter -Pretty reporter for cmp.Diff with colourized output support +# multilinediff +Pretty multiline diff tool and library with a custom reporter for cmp.Diff. diff --git a/cmd/experiment/main.go b/cmd/experiment/main.go new file mode 100644 index 0000000..bde3026 --- /dev/null +++ b/cmd/experiment/main.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" + + "github.com/RageCage64/multilinediff" +) + +func main() { + a := `a +b +c +diff` + b := `a +b +c +f +f +f` + + fmt.Println(multilinediff.MultilineDiff(a, b, "\n")) +} diff --git a/cmd/mld/main.go b/cmd/mld/main.go new file mode 100644 index 0000000..e64ea4a --- /dev/null +++ b/cmd/mld/main.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("not ready yet") +} diff --git a/go.mod b/go.mod index 9253c9e..a714b38 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/RageCage64/pretty-diff-reporter +module github.com/RageCage64/multilinediff go 1.18 diff --git a/multilinediff.go b/multilinediff.go new file mode 100644 index 0000000..b1fabcd --- /dev/null +++ b/multilinediff.go @@ -0,0 +1,22 @@ +package multilinediff + +import ( + "strings" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" +) + +func MultilineDiff(a, b, lineSep string) string { + reporter := Reporter{ + LineSep: lineSep, + } + cmp.Diff( + a, b, + cmpopts.AcyclicTransformer("multiline", func(s string) []string { + return strings.Split(s, lineSep) + }), + cmp.Reporter(&reporter), + ) + return reporter.String() +} diff --git a/reporter.go b/reporter.go index 2638542..2cfe812 100644 --- a/reporter.go +++ b/reporter.go @@ -1,4 +1,4 @@ -package prettyreporter +package multilinediff import ( "fmt" @@ -7,10 +7,50 @@ import ( "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 - old []string - new []string + lines []diffLine diffCount int } @@ -19,19 +59,25 @@ func (r *Reporter) PushStep(ps cmp.PathStep) { } func (r *Reporter) Report(rs cmp.Result) { + line := diffLine{} vOld, vNew := r.path.Last().Values() if !rs.Equal() { r.diffCount++ if vOld.IsValid() { - r.old = append(r.old, fmt.Sprintf("%+v", vOld)) + line.diff = diffTypeChange + line.old = fmt.Sprintf("%+v", vOld) } if vNew.IsValid() { - r.new = append(r.new, fmt.Sprintf("%+v", vNew)) + if line.diff == diffTypeEqual { + line.diff = diffTypeAdd + } + line.new = fmt.Sprintf("%+v", vNew) } } else { - r.old = append(r.old, "") - r.new = append(r.new, fmt.Sprintf("%+v", vOld)) + line.old = fmt.Sprintf("%+v", vOld) + line.new = fmt.Sprintf("%+v", vOld) } + r.lines = append(r.lines, line) } func (r *Reporter) PopStep() { @@ -39,16 +85,17 @@ func (r *Reporter) PopStep() { } func (r *Reporter) String() string { - - return strings.Join(r.lines, "\n") -} - -func maxLen(strs []string) int { - max := 0 - for _, s := range strs { - if len(s) > max { - max = len(s) + maxLen := 0 + for _, l := range r.lines { + if len(l.old) > maxLen { + maxLen = len(l.old) } } - return max + + diffLines := []string{} + for _, l := range r.lines { + diffLines = append(diffLines, l.toLine(maxLen)) + } + + return strings.Join(diffLines, r.LineSep) }