diff --git a/src/pattern.go b/src/pattern.go index 8cb2098..47cabf7 100644 --- a/src/pattern.go +++ b/src/pattern.go @@ -10,12 +10,12 @@ import ( // fuzzy // 'exact -// ^exact-prefix -// exact-suffix$ -// !not-fuzzy -// !'not-exact -// !^not-exact-prefix -// !not-exact-suffix$ +// ^prefix-exact +// suffix-exact$ +// !inverse-exact +// !'inverse-fuzzy +// !^inverse-prefix-exact +// !inverse-suffix-exact$ type termType int @@ -32,7 +32,6 @@ type term struct { inv bool text []rune caseSensitive bool - origText []rune } type termSet []term @@ -101,7 +100,7 @@ func BuildPattern(fuzzy bool, fuzzyAlgo algo.Algo, extended bool, caseMode Case, for idx, term := range termSet { // If the query contains inverse search terms or OR operators, // we cannot cache the search scope - if !cacheable || idx > 0 || term.inv || !fuzzy && term.typ != termExact { + if !cacheable || idx > 0 || term.inv || fuzzy && term.typ != termFuzzy || !fuzzy && term.typ != termExact { cacheable = false break Loop } @@ -153,7 +152,6 @@ func parseTerms(fuzzy bool, caseMode Case, normalize bool, str string) []termSet if !caseSensitive { text = lowerText } - origText := []rune(text) if !fuzzy { typ = termExact } @@ -204,8 +202,7 @@ func parseTerms(fuzzy bool, caseMode Case, normalize bool, str string) []termSet typ: typ, inv: inv, text: textRunes, - caseSensitive: caseSensitive, - origText: origText}) + caseSensitive: caseSensitive}) switchSet = true } } @@ -236,7 +233,7 @@ func (p *Pattern) CacheKey() string { cacheableTerms := []string{} for _, termSet := range p.termSets { if len(termSet) == 1 && !termSet[0].inv && (p.fuzzy || termSet[0].typ == termExact) { - cacheableTerms = append(cacheableTerms, string(termSet[0].origText)) + cacheableTerms = append(cacheableTerms, string(termSet[0].text)) } } return strings.Join(cacheableTerms, " ") diff --git a/src/pattern_test.go b/src/pattern_test.go index 81d158a..9d56ff9 100644 --- a/src/pattern_test.go +++ b/src/pattern_test.go @@ -33,19 +33,11 @@ func TestParseTermsExtended(t *testing.T) { terms[8][3].typ != termExact || !terms[8][3].inv { t.Errorf("%s", terms) } - for idx, termSet := range terms[:8] { + for _, termSet := range terms[:8] { term := termSet[0] if len(term.text) != 3 { t.Errorf("%s", term) } - if idx > 0 && len(term.origText) != 4+idx/5 { - t.Errorf("%s", term) - } - } - for _, term := range terms[8] { - if len(term.origText) != 4 { - t.Errorf("%s", term) - } } } @@ -167,6 +159,7 @@ func TestOrigTextAndTransformed(t *testing.T) { func TestCacheKey(t *testing.T) { test := func(extended bool, patStr string, expected string, cacheable bool) { + clearPatternCache() pat := BuildPattern(true, algo.FuzzyMatchV2, extended, CaseSmart, false, true, true, []Range{}, Delimiter{}, []rune(patStr)) if pat.CacheKey() != expected { t.Errorf("Expected: %s, actual: %s", expected, pat.CacheKey()) @@ -188,19 +181,24 @@ func TestCacheKey(t *testing.T) { } func TestCacheable(t *testing.T) { - test := func(fuzzy bool, str string, cacheable bool) { + test := func(fuzzy bool, str string, expected string, cacheable bool) { clearPatternCache() pat := BuildPattern(fuzzy, algo.FuzzyMatchV2, true, CaseSmart, true, true, true, []Range{}, Delimiter{}, []rune(str)) + if pat.CacheKey() != expected { + t.Errorf("Expected: %s, actual: %s", expected, pat.CacheKey()) + } if cacheable != pat.cacheable { t.Errorf("Invalid Pattern.cacheable for \"%s\": %v (expected: %v)", str, pat.cacheable, cacheable) } + clearPatternCache() } - test(true, "foo bar", true) - test(true, "foo 'bar", true) - test(true, "foo !bar", false) + test(true, "foo bar", "foo bar", true) + test(true, "foo 'bar", "foo bar", false) + test(true, "foo !bar", "foo", false) - test(false, "foo bar", true) - test(false, "foo '", true) - test(false, "foo 'bar", false) - test(false, "foo !bar", false) + test(false, "foo bar", "foo bar", true) + test(false, "foo 'bar", "foo", false) + test(false, "foo '", "foo", true) + test(false, "foo 'bar", "foo", false) + test(false, "foo !bar", "foo", false) } diff --git a/test/test_go.rb b/test/test_go.rb index b75b150..f001ec6 100644 --- a/test/test_go.rb +++ b/test/test_go.rb @@ -719,6 +719,38 @@ class TestGoFZF < TestBase tmux.send_keys :Enter end + def test_invalid_cache_query_type + command = %[(echo 'foo\\$bar'; echo 'barfoo'; echo 'foo^bar'; echo \\"foo'1-2\\"; seq 100) | #{fzf}] + + # Suffix match + tmux.send_keys command, :Enter + tmux.until { |lines| lines.match_count == 104 } + tmux.send_keys 'foo$' + tmux.until { |lines| lines.match_count == 1 } + tmux.send_keys 'bar' + tmux.until { |lines| lines.match_count == 1 } + tmux.send_keys :Enter + + # Prefix match + tmux.prepare + tmux.send_keys command, :Enter + tmux.until { |lines| lines.match_count == 104 } + tmux.send_keys '^bar' + tmux.until { |lines| lines.match_count == 1 } + tmux.send_keys 'C-a', 'foo' + tmux.until { |lines| lines.match_count == 1 } + tmux.send_keys :Enter + + # Exact match + tmux.prepare + tmux.send_keys command, :Enter + tmux.until { |lines| lines.match_count == 104 } + tmux.send_keys "'12" + tmux.until { |lines| lines.match_count == 1 } + tmux.send_keys 'C-a', 'foo' + tmux.until { |lines| lines.match_count == 1 } + end + def test_smart_case_for_each_term assert_equal 1, `echo Foo bar | #{FZF} -x -f "foo Fbar" | wc -l`.to_i end