Fix prefix/suffix/equal matcher to trim whitespaces

- Prefix matcher will trim leading whitespaces only when the pattern
  doesn't start with a whitespace
- Suffix matcher will trim trailing whitespaces only when the pattern
  doesn't end with a whitespace
- Equal matcher will trim leading whitespaces only when the pattern
  doesn't start with a whitespace, and trim trailing whitespaces only
  when the pattern doesn't end with a whitespace

Previously, only suffix matcher would trim whitespaces unconditionally.

Fix #1894
pull/1903/head
Junegunn Choi 4 years ago
parent b2c0413a98
commit 4c9cab3f8a
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627

@ -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

@ -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)
}
}

@ -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) {

@ -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-- {

Loading…
Cancel
Save