diff --git a/src/algo/algo.go b/src/algo/algo.go index a627514..b3f29e6 100644 --- a/src/algo/algo.go +++ b/src/algo/algo.go @@ -773,12 +773,17 @@ func PrefixMatch(caseSensitive bool, normalize bool, forward bool, text *util.Ch return Result{0, 0, 0}, nil } - if text.Length() < len(pattern) { + trimmedLen := 0 + if !unicode.IsSpace(pattern[0]) { + trimmedLen = text.LeadingWhitespaces() + } + + if text.Length()-trimmedLen < len(pattern) { return Result{-1, -1, 0}, nil } for index, r := range pattern { - char := text.Get(index) + char := text.Get(trimmedLen + index) if !caseSensitive { char = unicode.ToLower(char) } @@ -790,14 +795,17 @@ func PrefixMatch(caseSensitive bool, normalize bool, forward bool, text *util.Ch } } lenPattern := len(pattern) - score, _ := calculateScore(caseSensitive, normalize, text, pattern, 0, lenPattern, false) - return Result{0, lenPattern, score}, nil + score, _ := calculateScore(caseSensitive, normalize, text, pattern, trimmedLen, trimmedLen+lenPattern, false) + return Result{trimmedLen, trimmedLen + lenPattern, score}, nil } // SuffixMatch performs suffix-match func SuffixMatch(caseSensitive bool, normalize bool, forward bool, text *util.Chars, pattern []rune, withPos bool, slab *util.Slab) (Result, *[]int) { lenRunes := text.Length() - trimmedLen := lenRunes - text.TrailingWhitespaces() + trimmedLen := lenRunes + if len(pattern) == 0 || !unicode.IsSpace(pattern[len(pattern)-1]) { + trimmedLen -= text.TrailingWhitespaces() + } if len(pattern) == 0 { return Result{trimmedLen, trimmedLen, 0}, nil } @@ -828,14 +836,30 @@ func SuffixMatch(caseSensitive bool, normalize bool, forward bool, text *util.Ch // EqualMatch performs equal-match func EqualMatch(caseSensitive bool, normalize bool, forward bool, text *util.Chars, pattern []rune, withPos bool, slab *util.Slab) (Result, *[]int) { lenPattern := len(pattern) - if text.Length() != lenPattern { + if lenPattern == 0 { + return Result{-1, -1, 0}, nil + } + + // Strip leading whitespaces + trimmedLen := 0 + if !unicode.IsSpace(pattern[0]) { + trimmedLen = text.LeadingWhitespaces() + } + + // Strip trailing whitespaces + trimmedEndLen := 0 + if !unicode.IsSpace(pattern[lenPattern-1]) { + trimmedEndLen = text.TrailingWhitespaces() + } + + if text.Length()-trimmedLen-trimmedEndLen != lenPattern { return Result{-1, -1, 0}, nil } match := true if normalize { runes := text.ToRunes() for idx, pchar := range pattern { - char := runes[idx] + char := runes[trimmedLen+idx] if !caseSensitive { char = unicode.To(unicode.LowerCase, char) } @@ -845,14 +869,15 @@ func EqualMatch(caseSensitive bool, normalize bool, forward bool, text *util.Cha } } } else { - runesStr := text.ToString() + runes := text.ToRunes() + runesStr := string(runes[trimmedLen : len(runes)-trimmedEndLen]) if !caseSensitive { runesStr = strings.ToLower(runesStr) } match = runesStr == string(pattern) } if match { - return Result{0, lenPattern, (scoreMatch+bonusBoundary)*lenPattern + + return Result{trimmedLen, trimmedLen + lenPattern, (scoreMatch+bonusBoundary)*lenPattern + (bonusFirstCharMultiplier-1)*bonusBoundary}, nil } return Result{-1, -1, 0}, nil diff --git a/src/algo/algo_test.go b/src/algo/algo_test.go index 610c30e..d8f40cd 100644 --- a/src/algo/algo_test.go +++ b/src/algo/algo_test.go @@ -136,6 +136,10 @@ func TestPrefixMatch(t *testing.T) { assertMatch(t, PrefixMatch, false, dir, "fooBarbaz", "Foo", 0, 3, score) assertMatch(t, PrefixMatch, false, dir, "foOBarBaZ", "foo", 0, 3, score) assertMatch(t, PrefixMatch, false, dir, "f-oBarbaz", "f-o", 0, 3, score) + + assertMatch(t, PrefixMatch, false, dir, " fooBar", "foo", 1, 4, score) + assertMatch(t, PrefixMatch, false, dir, " fooBar", " fo", 0, 3, score) + assertMatch(t, PrefixMatch, false, dir, " fo", "foo", -1, -1, 0) } } @@ -148,6 +152,13 @@ func TestSuffixMatch(t *testing.T) { scoreMatch*3+bonusConsecutive*2) assertMatch(t, SuffixMatch, false, dir, "fooBarBaZ", "baz", 6, 9, (scoreMatch+bonusCamel123)*3+bonusCamel123*(bonusFirstCharMultiplier-1)) + + // Strip trailing white space from the string + assertMatch(t, SuffixMatch, false, dir, "fooBarbaz ", "baz", 6, 9, + scoreMatch*3+bonusConsecutive*2) + // Only when the pattern doesn't end with a space + assertMatch(t, SuffixMatch, false, dir, "fooBarbaz ", "baz ", 6, 10, + scoreMatch*4+bonusConsecutive*2+bonusNonWord) } } diff --git a/src/pattern_test.go b/src/pattern_test.go index bfadf5d..5a62295 100644 --- a/src/pattern_test.go +++ b/src/pattern_test.go @@ -98,6 +98,9 @@ func TestEqual(t *testing.T) { } match("ABC", -1, -1) match("AbC", 0, 3) + match("AbC ", 0, 3) + match(" AbC ", 1, 4) + match(" AbC", 2, 5) } func TestCaseSensitivity(t *testing.T) { diff --git a/src/util/chars.go b/src/util/chars.go index a57ba4b..41de924 100644 --- a/src/util/chars.go +++ b/src/util/chars.go @@ -130,6 +130,18 @@ func (chars *Chars) TrimLength() uint16 { return chars.trimLength } +func (chars *Chars) LeadingWhitespaces() int { + whitespaces := 0 + for i := 0; i < chars.Length(); i++ { + char := chars.Get(i) + if !unicode.IsSpace(char) { + break + } + whitespaces++ + } + return whitespaces +} + func (chars *Chars) TrailingWhitespaces() int { whitespaces := 0 for i := chars.Length() - 1; i >= 0; i-- {