Skip to content

Commit

Permalink
Merge pull request #24 from youta-t/feature/#20/text-matcher
Browse files Browse the repository at this point in the history
add Text matcher
  • Loading branch information
youta-t committed Feb 23, 2024
2 parents bf20759 + fa73f18 commit e7c23a8
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 0 deletions.
88 changes: 88 additions & 0 deletions general.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"reflect"
"strings"

"github.com/sergi/go-diff/diffmatchpatch"
"github.com/youta-t/its/itskit"
"github.com/youta-t/its/itskit/itsio"
)
Expand Down Expand Up @@ -561,3 +562,90 @@ func Pointer[T any](m Matcher[T]) Matcher[*T] {
m: m,
}
}

type textMatcher struct {
label itskit.Label
want string
}

func (tm textMatcher) Match(got string) itskit.Match {
dmp := diffmatchpatch.New()
var diff []diffmatchpatch.Diff
{
a, b, dmpStrings := dmp.DiffLinesToChars(tm.want, got)
diff = dmp.DiffMain(a, b, false)
diff = dmp.DiffCharsToLines(diff, dmpStrings)
diff = dmp.DiffCleanupSemantic(diff)
}

message := new(strings.Builder)
message.WriteString(tm.label.String())
message.WriteString("\n")

unmatch := 0
for _, d := range diff {
header := " | "
switch d.Type {
case diffmatchpatch.DiffDelete:
unmatch += 1
header = " - | "
case diffmatchpatch.DiffInsert:
unmatch += 1
header = " + | "
default:
}

lines := strings.SplitAfter(d.Text, "\n")
if len(lines) == 1 {
if len(d.Text) == 0 {
continue
}
message.WriteString(header)
message.WriteString(d.Text)
message.WriteString("\n")
continue
}
for _, l := range lines[:len(lines)-1] {
if l == "\n" {
message.WriteString(header[:len(header)-1])
message.WriteString("\n")
continue
}
message.WriteString(header)
message.WriteString(l)
}
}

return itskit.NewMatch(
unmatch == 0,
message.String(),
)
}

func (tm textMatcher) Write(w itsio.Writer) error {
if err := tm.label.Write(w); err != nil {
return err
}
in := w.Indent()
if err := in.WriteStringln(tm.want); err != nil {
return err
}
return nil
}

func (tm textMatcher) String() string {
return itskit.MatcherToString(tm)
}

// Text returns a matcher for a long text.
//
// When it get unmatch, it shows diff of text.
func Text(want string) Matcher[string] {
cancel := itskit.SkipStack()
defer cancel()

return textMatcher{
label: itskit.NewLabelWithLocation("(+ = got, - = want)"),
want: want,
}
}
64 changes: 64 additions & 0 deletions general_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,3 +449,67 @@ func ExamplePointer() {
// ✘ /* got */ nil is not nil, --- @ ./general_test.go:444
// ✘ /* got */ ?? == /* want */ 42 --- @ ./general_test.go:444
}

func ExampleText_multibytes() {
// "風景" (純銀もざいく; 山村暮鳥): https://www.aozora.gr.jp/cards/000136/files/52348_42039.html
its.Text(`
いちめんのなのはな
いちめんのなのはな
いちめんのなのはな
いちめんのなのはな
いちめんのなのはな
いちめんのなのはな
いちめんのなのはな
かすかなるむぎぶえ
いちめんのなのはな
`).Match(`
いちめんのなのはな
いちめんのなのはな
いちめんのなのはな
いちめんのなのはな
いちめんのなのはな
いちめんのなのはな
いちめんのなのはな
ひばりのおしやべり
いちめんのなのはな
`).OrError(t)
// Output:
// ✘ (+ = got, - = want) --- @ ./general_test.go:455
// |
// | いちめんのなのはな
// | いちめんのなのはな
// | いちめんのなのはな
// | いちめんのなのはな
// | いちめんのなのはな
// | いちめんのなのはな
// | いちめんのなのはな
// - | かすかなるむぎぶえ
// + | ひばりのおしやべり
// | いちめんのなのはな
}

func ExampleText_ascii() {
// London Bridge Is Falling Down
its.Text(`
Build it up with bricks and mortar,
Bricks and mortar, bricks and mortar,
Build it up with bricks and mortar,
My fair lady.
`).Match(`
Build it up with iron and steel,
Iron and steel, iron and steel,
Build it up with iron and steel,
My fair lady.
`).OrError(t)
// Output:
//
// ✘ (+ = got, - = want) --- @ ./general_test.go:493
// |
// - | Build it up with bricks and mortar,
// + | Build it up with iron and steel,
// - | Bricks and mortar, bricks and mortar,
// + | Iron and steel, iron and steel,
// - | Build it up with bricks and mortar,
// + | Build it up with iron and steel,
// | My fair lady.
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ module github.com/youta-t/its
go 1.21

require golang.org/x/mod v0.14.0

require github.com/sergi/go-diff v1.3.1
18 changes: 18 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,20 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

0 comments on commit e7c23a8

Please sign in to comment.