mirror of
https://github.com/junegunn/fzf.git
synced 2025-08-15 04:05:48 -07:00
Implement smart-case match (#12)
This commit is contained in:
@@ -57,6 +57,7 @@ usage: fzf [options]
|
|||||||
-q, --query=STR Initial query
|
-q, --query=STR Initial query
|
||||||
-s, --sort=MAX Maximum number of matched items to sort. Default: 1000
|
-s, --sort=MAX Maximum number of matched items to sort. Default: 1000
|
||||||
+s, --no-sort Do not sort the result. Keep the sequence unchanged.
|
+s, --no-sort Do not sort the result. Keep the sequence unchanged.
|
||||||
|
-i Case-insensitive match (default: smart-case match)
|
||||||
+i Case-sensitive match
|
+i Case-sensitive match
|
||||||
+c, --no-color Disable colors
|
+c, --no-color Disable colors
|
||||||
```
|
```
|
||||||
|
20
fzf
20
fzf
@@ -67,7 +67,7 @@ class FZF
|
|||||||
end
|
end
|
||||||
|
|
||||||
def initialize argv, source = $stdin
|
def initialize argv, source = $stdin
|
||||||
@rxflag = Regexp::IGNORECASE
|
@rxflag = nil
|
||||||
@sort = ENV.fetch('FZF_DEFAULT_SORT', 1000).to_i
|
@sort = ENV.fetch('FZF_DEFAULT_SORT', 1000).to_i
|
||||||
@color = true
|
@color = true
|
||||||
@multi = false
|
@multi = false
|
||||||
@@ -79,6 +79,7 @@ class FZF
|
|||||||
when '-h', '--help' then usage 0
|
when '-h', '--help' then usage 0
|
||||||
when '-m', '--multi' then @multi = true
|
when '-m', '--multi' then @multi = true
|
||||||
when '-x', '--extended' then @xmode = true
|
when '-x', '--extended' then @xmode = true
|
||||||
|
when '-i' then @rxflag = Regexp::IGNORECASE
|
||||||
when '+i' then @rxflag = 0
|
when '+i' then @rxflag = 0
|
||||||
when '+s', '--no-sort' then @sort = nil
|
when '+s', '--no-sort' then @sort = nil
|
||||||
when '+c', '--no-color' then @color = false
|
when '+c', '--no-color' then @color = false
|
||||||
@@ -136,6 +137,7 @@ class FZF
|
|||||||
-q, --query=STR Initial query
|
-q, --query=STR Initial query
|
||||||
-s, --sort=MAX Maximum number of matched items to sort. Default: 1000
|
-s, --sort=MAX Maximum number of matched items to sort. Default: 1000
|
||||||
+s, --no-sort Do not sort the result. Keep the sequence unchanged.
|
+s, --no-sort Do not sort the result. Keep the sequence unchanged.
|
||||||
|
-i Case-insensitive match (default: smart-case match)
|
||||||
+i Case-sensitive match
|
+i Case-sensitive match
|
||||||
+c, --no-color Disable colors]
|
+c, --no-color Disable colors]
|
||||||
exit x
|
exit x
|
||||||
@@ -770,14 +772,18 @@ class FZF
|
|||||||
q.empty?
|
q.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def rxflag_for q
|
||||||
|
@rxflag || (q =~ /[A-Z]/ ? 0 : Regexp::IGNORECASE)
|
||||||
|
end
|
||||||
|
|
||||||
def fuzzy_regex q
|
def fuzzy_regex q
|
||||||
@regexp[q] ||= begin
|
@regexp[q] ||= begin
|
||||||
q = q.downcase if @rxflag != 0
|
q = q.downcase if @rxflag == Regexp::IGNORECASE
|
||||||
Regexp.new(query_chars(q).inject('') { |sum, e|
|
Regexp.new(query_chars(q).inject('') { |sum, e|
|
||||||
e = Regexp.escape e
|
e = Regexp.escape e
|
||||||
sum << (e.length > 1 ? "(?:#{e}).*?" : # FIXME: not equivalent
|
sum << (e.length > 1 ? "(?:#{e}).*?" : # FIXME: not equivalent
|
||||||
"#{e}[^#{e}]*?")
|
"#{e}[^#{e}]*?")
|
||||||
}, @rxflag)
|
}, rxflag_for(q))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -830,16 +836,16 @@ class FZF
|
|||||||
when ''
|
when ''
|
||||||
nil
|
nil
|
||||||
when /^\^(.*)\$$/
|
when /^\^(.*)\$$/
|
||||||
Regexp.new('^' << sanitize(Regexp.escape($1)) << '$', rxflag)
|
Regexp.new('^' << sanitize(Regexp.escape($1)) << '$', rxflag_for(w))
|
||||||
when /^'/
|
when /^'/
|
||||||
w.length > 1 ?
|
w.length > 1 ?
|
||||||
Regexp.new(sanitize(Regexp.escape(w[1..-1])), rxflag) : nil
|
Regexp.new(sanitize(Regexp.escape(w[1..-1])), rxflag_for(w)) : nil
|
||||||
when /^\^/
|
when /^\^/
|
||||||
w.length > 1 ?
|
w.length > 1 ?
|
||||||
Regexp.new('^' << sanitize(Regexp.escape(w[1..-1])), rxflag) : nil
|
Regexp.new('^' << sanitize(Regexp.escape(w[1..-1])), rxflag_for(w)) : nil
|
||||||
when /\$$/
|
when /\$$/
|
||||||
w.length > 1 ?
|
w.length > 1 ?
|
||||||
Regexp.new(sanitize(Regexp.escape(w[0..-2])) << '$', rxflag) : nil
|
Regexp.new(sanitize(Regexp.escape(w[0..-2])) << '$', rxflag_for(w)) : nil
|
||||||
else
|
else
|
||||||
fuzzy_regex w
|
fuzzy_regex w
|
||||||
end, invert ]
|
end, invert ]
|
||||||
|
@@ -12,7 +12,7 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal 1000, fzf.sort
|
assert_equal 1000, fzf.sort
|
||||||
assert_equal false, fzf.multi
|
assert_equal false, fzf.multi
|
||||||
assert_equal true, fzf.color
|
assert_equal true, fzf.color
|
||||||
assert_equal Regexp::IGNORECASE, fzf.rxflag
|
assert_equal nil, fzf.rxflag
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ENV['FZF_DEFAULT_SORT'] = '1500'
|
ENV['FZF_DEFAULT_SORT'] = '1500'
|
||||||
@@ -152,15 +152,59 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
# TODO : partial_cache
|
# TODO : partial_cache
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_fuzzy_matcher_rxflag
|
||||||
|
assert_equal nil, FZF::FuzzyMatcher.new(nil).rxflag
|
||||||
|
assert_equal 0, FZF::FuzzyMatcher.new(0).rxflag
|
||||||
|
assert_equal 1, FZF::FuzzyMatcher.new(1).rxflag
|
||||||
|
|
||||||
|
assert_equal 1, FZF::FuzzyMatcher.new(nil).rxflag_for('abc')
|
||||||
|
assert_equal 0, FZF::FuzzyMatcher.new(nil).rxflag_for('Abc')
|
||||||
|
assert_equal 0, FZF::FuzzyMatcher.new(0).rxflag_for('abc')
|
||||||
|
assert_equal 0, FZF::FuzzyMatcher.new(0).rxflag_for('Abc')
|
||||||
|
assert_equal 1, FZF::FuzzyMatcher.new(1).rxflag_for('abc')
|
||||||
|
assert_equal 1, FZF::FuzzyMatcher.new(1).rxflag_for('Abc')
|
||||||
|
end
|
||||||
|
|
||||||
def test_fuzzy_matcher_case_sensitive
|
def test_fuzzy_matcher_case_sensitive
|
||||||
|
# Smart-case match (Uppercase found)
|
||||||
|
assert_equal [['Fruit', [[0, 5]]]],
|
||||||
|
FZF::FuzzyMatcher.new(nil).match(%w[Fruit Grapefruit], 'Fruit', '', '').sort
|
||||||
|
|
||||||
|
# Smart-case match (Uppercase not-found)
|
||||||
|
assert_equal [["Fruit", [[0, 5]]], ["Grapefruit", [[5, 10]]]],
|
||||||
|
FZF::FuzzyMatcher.new(nil).match(%w[Fruit Grapefruit], 'fruit', '', '').sort
|
||||||
|
|
||||||
|
# Case-sensitive match (-i)
|
||||||
assert_equal [['Fruit', [[0, 5]]]],
|
assert_equal [['Fruit', [[0, 5]]]],
|
||||||
FZF::FuzzyMatcher.new(0).match(%w[Fruit Grapefruit], 'Fruit', '', '').sort
|
FZF::FuzzyMatcher.new(0).match(%w[Fruit Grapefruit], 'Fruit', '', '').sort
|
||||||
|
|
||||||
|
# Case-insensitive match (+i)
|
||||||
assert_equal [["Fruit", [[0, 5]]], ["Grapefruit", [[5, 10]]]],
|
assert_equal [["Fruit", [[0, 5]]], ["Grapefruit", [[5, 10]]]],
|
||||||
FZF::FuzzyMatcher.new(Regexp::IGNORECASE).
|
FZF::FuzzyMatcher.new(Regexp::IGNORECASE).
|
||||||
match(%w[Fruit Grapefruit], 'Fruit', '', '').sort
|
match(%w[Fruit Grapefruit], 'Fruit', '', '').sort
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_extended_fuzzy_matcher_case_sensitive
|
||||||
|
%w['Fruit Fruit$].each do |q|
|
||||||
|
# Smart-case match (Uppercase found)
|
||||||
|
assert_equal [['Fruit', [[0, 5]]]],
|
||||||
|
FZF::ExtendedFuzzyMatcher.new(nil).match(%w[Fruit Grapefruit], q, '', '').sort
|
||||||
|
|
||||||
|
# Smart-case match (Uppercase not-found)
|
||||||
|
assert_equal [["Fruit", [[0, 5]]], ["Grapefruit", [[5, 10]]]],
|
||||||
|
FZF::ExtendedFuzzyMatcher.new(nil).match(%w[Fruit Grapefruit], q.downcase, '', '').sort
|
||||||
|
|
||||||
|
# Case-sensitive match (-i)
|
||||||
|
assert_equal [['Fruit', [[0, 5]]]],
|
||||||
|
FZF::ExtendedFuzzyMatcher.new(0).match(%w[Fruit Grapefruit], q, '', '').sort
|
||||||
|
|
||||||
|
# Case-insensitive match (+i)
|
||||||
|
assert_equal [["Fruit", [[0, 5]]], ["Grapefruit", [[5, 10]]]],
|
||||||
|
FZF::ExtendedFuzzyMatcher.new(Regexp::IGNORECASE).
|
||||||
|
match(%w[Fruit Grapefruit], q, '', '').sort
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_extended_fuzzy_matcher
|
def test_extended_fuzzy_matcher
|
||||||
matcher = FZF::ExtendedFuzzyMatcher.new Regexp::IGNORECASE
|
matcher = FZF::ExtendedFuzzyMatcher.new Regexp::IGNORECASE
|
||||||
list = %w[
|
list = %w[
|
||||||
|
Reference in New Issue
Block a user