From fb21995413acdc040d929c2efa16321b985c2a89 Mon Sep 17 00:00:00 2001 From: Patrick Gundlach Date: Fri, 7 Mar 2025 10:05:57 +0100 Subject: [PATCH] x/text: bidi incorrect brackets matching Brackets are now ordered correctly in the bidi algorithm. While parsing the input, the pairValues slice is created with correct bracket data. The algorithm in matchOpener from brackets.go checks if the opening and closing values are equal. Therefore the unicode value of the closing bracket needs to be changed to the opening bracket. --- unicode/bidi/bidi.go | 16 ++++++++-------- unicode/bidi/bidi_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/unicode/bidi/bidi.go b/unicode/bidi/bidi.go index fd057601..8d68f98e 100644 --- a/unicode/bidi/bidi.go +++ b/unicode/bidi/bidi.go @@ -109,17 +109,17 @@ func (p *Paragraph) prepareInput() (n int, err error) { return bytecount, nil } p.types = append(p.types, cls) - if props.IsOpeningBracket() { + + switch { + case !props.IsBracket(): + p.pairTypes = append(p.pairTypes, bpNone) + p.pairValues = append(p.pairValues, 0) + case props.IsOpeningBracket(): p.pairTypes = append(p.pairTypes, bpOpen) p.pairValues = append(p.pairValues, r) - } else if props.IsBracket() { - // this must be a closing bracket, - // since IsOpeningBracket is not true + default: p.pairTypes = append(p.pairTypes, bpClose) - p.pairValues = append(p.pairValues, r) - } else { - p.pairTypes = append(p.pairTypes, bpNone) - p.pairValues = append(p.pairValues, 0) + p.pairValues = append(p.pairValues, props.reverseBracket(r)) } } return bytecount, nil diff --git a/unicode/bidi/bidi_test.go b/unicode/bidi/bidi_test.go index 88572f56..8f0f2142 100644 --- a/unicode/bidi/bidi_test.go +++ b/unicode/bidi/bidi_test.go @@ -345,3 +345,35 @@ func TestAppendReverse(t *testing.T) { } } + +func TestBracket(t *testing.T) { + str := `ع a (b)` + p := Paragraph{} + p.SetString(str, DefaultDirection(LeftToRight)) + order, err := p.Order() + if err != nil { + log.Fatal(err) + } + + expectedRuns := []runInformation{ + {"ع ", RightToLeft, 0, 1}, + {"a (b)", LeftToRight, 2, 6}, + } + + if nr, want := order.NumRuns(), len(expectedRuns); nr != want { + t.Errorf("order.NumRuns() = %d; want %d", nr, want) + } + + for i, want := range expectedRuns { + r := order.Run(i) + if got := r.String(); got != want.str { + t.Errorf("Run(%d) = %q; want %q", i, got, want.str) + } + if s, e := r.Pos(); s != want.start || e != want.end { + t.Errorf("Run(%d).start = %d, .end = %d; want start = %d, end = %d", i, s, e, want.start, want.end) + } + if d := r.Direction(); d != want.dir { + t.Errorf("Run(%d).Direction = %d; want %d", i, d, want.dir) + } + } +}