summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2014-03-04 21:29:45 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2014-03-04 21:29:45 +0900
commit2dbca00bfb8e9f0d63514bd389f09a28bbf6e149 (patch)
tree0ed23a790e0544a68de21288216aad0451972aa5
parentb22fd6de6db852f9cbecc5f1e173f701876fccdc (diff)
Implement --extended-exact option (#24)
-rw-r--r--README.md4
-rwxr-xr-xfzf42
-rw-r--r--test/test_fzf.rb31
3 files changed, 59 insertions, 18 deletions
diff --git a/README.md b/README.md
index b0c8203c..baa73f2c 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,7 @@ usage: fzf [options]
Options
-m, --multi Enable multi-select
-x, --extended Extended-search mode
+ -e, --extended-exact Extended-search mode (exact match)
-q, --query=STR Initial query
-f, --filter=STR Filter mode. Do not start interactive finder.
-s, --sort=MAX Maximum number of matched items to sort (default: 1000)
@@ -120,6 +121,9 @@ such as: `^music .mp3$ sbtrkt !rmx`
| `'wild` | Items that include `wild` | exact-match (quoted) |
| `!'fire` | Items that do not include `fire` | inverse-exact-match |
+If you don't need fuzzy matching and do not wish to "quote" every word, start
+fzf with `-e` or `--extended-exact` option.
+
Useful examples
---------------
diff --git a/fzf b/fzf
index 84c1f117..180a53df 100755
--- a/fzf
+++ b/fzf
@@ -7,7 +7,7 @@
# / __/ / /_/ __/
# /_/ /___/_/ Fuzzy finder for your shell
#
-# Version: 0.7.3 (February 20, 2014)
+# Version: 0.7.3 (March 4, 2014)
#
# Author: Junegunn Choi
# URL: https://github.com/junegunn/fzf
@@ -78,7 +78,7 @@ class FZF
@sort = ENV.fetch('FZF_DEFAULT_SORT', 1000).to_i
@color = true
@multi = false
- @extended = false
+ @extended = nil
@mouse = true
@filter = nil
@@ -95,8 +95,8 @@ class FZF
when '-h', '--help' then usage 0
when '-m', '--multi' then @multi = true
when '+m', '--no-multi' then @multi = false
- when '-x', '--extended' then @extended = true
- when '+x', '--no-extended' then @extended = false
+ when '-x', '--extended' then @extended = :fuzzy
+ when '+x', '--no-extended' then @extended = nil
when '-i' then @rxflag = Regexp::IGNORECASE
when '+i' then @rxflag = 0
when '-c', '--color' then @color = true
@@ -119,6 +119,8 @@ class FZF
@sort = sort.to_i
when /^-s([0-9]+)$/, /^--sort=([0-9]+)$/
@sort = $1.to_i
+ when '-e', '--extended-exact' then @extended = :exact
+ when '+e', '--no-extended-exact' then @extended = nil
else
usage 1, "illegal option: #{o}"
end
@@ -162,14 +164,21 @@ class FZF
end
def filter_list list
- matcher = (@extended ? ExtendedFuzzyMatcher : FuzzyMatcher).new @rxflag
- matches = matcher.match(list, @filter, '', '')
+ matches = get_matcher.match(list, @filter, '', '')
if @sort && matches.length <= @sort
matches = sort_by_rank(matches)
end
matches.each { |m| puts m.first }
end
+ def get_matcher
+ if @extended
+ ExtendedFuzzyMatcher.new @rxflag, @extended
+ else
+ FuzzyMatcher.new @rxflag
+ end
+ end
+
def version
File.open(__FILE__, 'r') do |f|
f.each_line do |line|
@@ -188,6 +197,7 @@ class FZF
Options
-m, --multi Enable multi-select
-x, --extended Extended-search mode
+ -e, --extended-exact Extended-search mode (exact match)
-q, --query=STR Initial query
-f, --filter=STR Filter mode. Do not start interactive finder.
-s, --sort=MAX Maximum number of matched items to sort (default: 1000)
@@ -582,7 +592,7 @@ class FZF
end
def start_search
- matcher = (@extended ? ExtendedFuzzyMatcher : FuzzyMatcher).new @rxflag
+ matcher = get_matcher
searcher = Thread.new {
lists = []
events = {}
@@ -952,9 +962,10 @@ class FZF
end
class ExtendedFuzzyMatcher < FuzzyMatcher
- def initialize rxflag
- super
+ def initialize rxflag, mode = :fuzzy
+ super rxflag
@regexps = {}
+ @mode = mode
end
def empty? q
@@ -977,8 +988,11 @@ class FZF
when /^\^(.*)\$$/
Regexp.new('^' << sanitize(Regexp.escape($1)) << '$', rxflag_for(w))
when /^'/
- w.length > 1 ?
- Regexp.new(sanitize(Regexp.escape(w[1..-1])), rxflag_for(w)) : nil
+ if @mode == :fuzzy && w.length > 1
+ exact_regex w[1..-1]
+ elsif @mode == :exact
+ exact_regex w
+ end
when /^\^/
w.length > 1 ?
Regexp.new('^' << sanitize(Regexp.escape(w[1..-1])), rxflag_for(w)) : nil
@@ -986,11 +1000,15 @@ class FZF
w.length > 1 ?
Regexp.new(sanitize(Regexp.escape(w[0..-2])) << '$', rxflag_for(w)) : nil
else
- fuzzy_regex w
+ @mode == :fuzzy ? fuzzy_regex(w) : exact_regex(w)
end, invert ]
}.select { |pair| pair.first }
end
+ def exact_regex w
+ Regexp.new(sanitize(Regexp.escape(w)), rxflag_for(w))
+ end
+
def match list, q, prefix, suffix
regexps = parse q
# Look for prefix cache
diff --git a/test/test_fzf.rb b/test/test_fzf.rb
index 4be0846f..d1006659 100644
--- a/test/test_fzf.rb
+++ b/test/test_fzf.rb
@@ -36,7 +36,7 @@ class TestFZF < MiniTest::Unit::TestCase
fzf.query.get
assert_equal 'goodbye world',
fzf.filter
- assert_equal true, fzf.extended
+ assert_equal :fuzzy, fzf.extended
assert_equal true, fzf.multi
assert_equal false, fzf.color
assert_equal false, fzf.mouse
@@ -45,7 +45,7 @@ class TestFZF < MiniTest::Unit::TestCase
def test_option_parser
# Long opts
fzf = FZF.new %w[--sort=2000 --no-color --multi +i --query hello
- --filter=howdy --extended --no-mouse]
+ --filter=howdy --extended-exact --no-mouse]
assert_equal 2000, fzf.sort
assert_equal true, fzf.multi
assert_equal false, fzf.color
@@ -53,7 +53,7 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal 0, fzf.rxflag
assert_equal 'hello', fzf.query.get
assert_equal 'howdy', fzf.filter
- assert_equal true, fzf.extended
+ assert_equal :exact, fzf.extended
fzf = FZF.new %w[--sort=2000 --no-color --multi +i --query hello
--filter a --filter b
@@ -65,7 +65,7 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal 1, fzf.rxflag
assert_equal 'b', fzf.filter
assert_equal 'hello', fzf.query.get
- assert_equal false, fzf.extended
+ assert_equal nil, fzf.extended
# Short opts
fzf = FZF.new %w[-s 2000 +c -m +i -qhello -x -fhowdy]
@@ -75,7 +75,7 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal 0, fzf.rxflag
assert_equal 'hello', fzf.query.get
assert_equal 'howdy', fzf.filter
- assert_equal true, fzf.extended
+ assert_equal :fuzzy, fzf.extended
# Left-to-right
fzf = FZF.new %w[-s 2000 +c -m +i -qhello -x -fgoodbye
@@ -86,7 +86,7 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal 1, fzf.rxflag
assert_equal 'world', fzf.query.get
assert_equal 'world', fzf.filter
- assert_equal false, fzf.extended
+ assert_equal nil, fzf.extended
fzf = FZF.new %w[--query hello +s -s 2000 --query=world]
assert_equal 2000, fzf.sort
@@ -378,6 +378,25 @@ class TestFZF < MiniTest::Unit::TestCase
FZF.new([]).sort_by_rank(xmatcher.match(list, '01 __', '', '')))
end
+ def test_extended_exact_mode
+ exact = FZF::ExtendedFuzzyMatcher.new Regexp::IGNORECASE, :exact
+ fuzzy = FZF::ExtendedFuzzyMatcher.new Regexp::IGNORECASE, :fuzzy
+ list = %w[
+ extended-exact-mode-not-fuzzy
+ extended'-fuzzy-mode
+ ]
+ assert_equal 2, fuzzy.match(list, 'extended', '', '').length
+ assert_equal 2, fuzzy.match(list, 'mode extended', '', '').length
+ assert_equal 2, fuzzy.match(list, 'xtndd', '', '').length
+ assert_equal 2, fuzzy.match(list, "'-fuzzy", '', '').length
+
+ assert_equal 2, exact.match(list, 'extended', '', '').length
+ assert_equal 2, exact.match(list, 'mode extended', '', '').length
+ assert_equal 0, exact.match(list, 'xtndd', '', '').length
+ assert_equal 1, exact.match(list, "'-fuzzy", '', '').length
+ assert_equal 2, exact.match(list, "-fuzzy", '', '').length
+ end
+
if RUBY_PLATFORM =~ /darwin/
NFD = '한글'
def test_nfc