Skip to content

Commit f932f2c

Browse files
committed
myers: create package
Part of #18.
1 parent 7cc3ed0 commit f932f2c

File tree

6 files changed

+34
-30
lines changed

6 files changed

+34
-30
lines changed

cmd/pkg-diff-example/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"os"
1212

1313
"github.com/pkg/diff"
14+
"github.com/pkg/diff/myers"
1415
)
1516

1617
var (
@@ -73,7 +74,7 @@ func main() {
7374
ctx, cancel = context.WithTimeout(ctx, *timeout)
7475
defer cancel()
7576
}
76-
e := diff.Myers(ctx, ab)
77+
e := myers.Diff(ctx, ab)
7778
e = diff.EditScriptWithContextSize(e, *unified) // limit amount of output context
7879
opts := []diff.WriteOpt{
7980
diff.Names(aName, bName),

diff.go

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
11
package diff
22

33
import (
4-
"fmt"
54
"io"
65

7-
"github.com/pkg/diff/edit"
6+
"github.com/pkg/diff/myers"
87
)
98

10-
// A Pair is two things that can be diffed using the Myers diff algorithm.
11-
// A is the initial state; B is the final state.
12-
type Pair interface {
13-
// LenA returns the number of initial elements.
14-
LenA() int
15-
// LenA returns the number of final elements.
16-
LenB() int
17-
// Equal reports whether the ai'th element of A is equal to the bi'th element of B.
18-
Equal(ai, bi int) bool
19-
}
20-
219
// A WriterTo type supports writing a diff, element by element.
2210
// A is the initial state; B is the final state.
2311
type WriterTo interface {
@@ -29,7 +17,7 @@ type WriterTo interface {
2917

3018
// PairWriterTo is the union of Pair and WriterTo.
3119
type PairWriterTo interface {
32-
Pair
20+
myers.Pair
3321
WriterTo
3422
}
3523

@@ -49,12 +37,6 @@ type PairWriterTo interface {
4937
// If you have paid the O(n) cost to intern all strings involved in both A and B,
5038
// then string comparisons are reduced to cheap pointer comparisons.
5139

52-
func rangeString(r edit.Range) string {
53-
// This output is helpful when hacking on a Myers diff.
54-
// In other contexts it is usually more natural to group LowA, HighA and LowB, HighB.
55-
return fmt.Sprintf("(%d, %d) -- %s %d --> (%d, %d)", r.LowA, r.LowB, r.Op(), r.Len(), r.HighA, r.HighB)
56-
}
57-
5840
// TODO: consider adding an "it just works" test helper that accepts two slices (via interface{}),
5941
// diffs them using Strings or Bytes or Slices (using reflect.DeepEqual) as appropriate,
6042
// and calls t.Errorf with a generated diff if they're not equal.

example_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"os"
66

77
"github.com/pkg/diff"
8+
"github.com/pkg/diff/myers"
89
)
910

1011
// TODO: use a less heavyweight output format for Example_testHelper
@@ -13,7 +14,7 @@ func Example_testHelper() {
1314
want := []int{1, 2, 3, 4, 5}
1415
got := []int{1, 2, 4, 5}
1516
ab := diff.Slices(want, got, nil)
16-
e := diff.Myers(context.Background(), ab)
17+
e := myers.Diff(context.Background(), ab)
1718
if e.IsIdentity() {
1819
return
1920
}
@@ -32,7 +33,7 @@ func Example_strings() {
3233
a := []string{"a", "b", "c"}
3334
b := []string{"a", "c", "d"}
3435
ab := diff.Strings(a, b)
35-
e := diff.Myers(context.Background(), ab)
36+
e := myers.Diff(context.Background(), ab)
3637
diff.WriteUnified(e, os.Stdout, ab)
3738
// Output:
3839
// --- a
@@ -48,7 +49,7 @@ func Example_Names() {
4849
a := []string{"a", "b", "c"}
4950
b := []string{"a", "c", "d"}
5051
ab := diff.Strings(a, b)
51-
e := diff.Myers(context.Background(), ab)
52+
e := myers.Diff(context.Background(), ab)
5253
diff.WriteUnified(e, os.Stdout, ab, diff.Names("before", "after"))
5354
// Output:
5455
// --- before

myers.go renamed to myers/myers.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
package diff
1+
// Package myers implements the Myers diff algorithm.
2+
package myers
23

34
import (
45
"context"
@@ -7,9 +8,20 @@ import (
78
"github.com/pkg/diff/edit"
89
)
910

10-
// Myers calculates an edit.Script (diff) for ab using the Myers diff algorithm.
11+
// A Pair is two things that can be diffed using the Myers diff algorithm.
12+
// A is the initial state; B is the final state.
13+
type Pair interface {
14+
// LenA returns the number of initial elements.
15+
LenA() int
16+
// LenB returns the number of final elements.
17+
LenB() int
18+
// Equal reports whether the aᵢ'th element of A is equal to the bᵢ'th element of B.
19+
Equal(ai, bi int) bool
20+
}
21+
22+
// Diff calculates an edit.Script for ab using the Myers diff algorithm.
1123
// Because diff calculation can be expensive, Myers supports cancellation via ctx.
12-
func Myers(ctx context.Context, ab Pair) edit.Script {
24+
func Diff(ctx context.Context, ab Pair) edit.Script {
1325
aLen := ab.LenA()
1426
bLen := ab.LenB()
1527
if aLen == 0 {
@@ -153,3 +165,9 @@ func combineRanges(s, t edit.Range) (u edit.Range, ok bool) {
153165
}
154166
return s, true
155167
}
168+
169+
func rangeString(r edit.Range) string {
170+
// This output is helpful when hacking on a Myers diff.
171+
// In other contexts it is usually more natural to group LowA, HighA and LowB, HighB.
172+
return fmt.Sprintf("(%d, %d) -- %s %d --> (%d, %d)", r.LowA, r.LowB, r.Op(), r.Len(), r.HighA, r.HighB)
173+
}

myers_test.go renamed to myers/myers_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
package diff
1+
package myers_test
22

33
import (
44
"context"
55
"reflect"
66
"testing"
77

88
"github.com/pkg/diff/edit"
9+
"github.com/pkg/diff/myers"
910
)
1011

1112
func TestMyers(t *testing.T) {
@@ -49,7 +50,7 @@ func TestMyers(t *testing.T) {
4950
for _, test := range tests {
5051
t.Run(test.name, func(t *testing.T) {
5152
ab := &diffByByte{a: test.a, b: test.b}
52-
got := Myers(context.Background(), ab)
53+
got := myers.Diff(context.Background(), ab)
5354
want := edit.Script{Ranges: test.want}
5455

5556
if !reflect.DeepEqual(got, want) {

unified_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88

99
"github.com/pkg/diff"
10+
"github.com/pkg/diff/myers"
1011
"github.com/sergi/go-diff/diffmatchpatch"
1112
)
1213

@@ -80,7 +81,7 @@ func TestGolden(t *testing.T) {
8081
// TODO: supply an edit.Script to the tests instead doing a Myers diff here.
8182
// Doing it as I have done, the lazy way, mixes concerns: diff algorithm vs unification algorithm
8283
// vs unified diff formatting.
83-
e := diff.Myers(context.Background(), ab)
84+
e := myers.Diff(context.Background(), ab)
8485
e = diff.EditScriptWithContextSize(e, 3)
8586
buf := new(bytes.Buffer)
8687
diff.WriteUnified(e, buf, ab, test.opts...)

0 commit comments

Comments
 (0)