mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-17 15:53:39 -05:00
@@ -65,8 +65,9 @@ usage: fzf [options]
|
|||||||
-e, --extended-exact Extended-search mode (exact match)
|
-e, --extended-exact Extended-search mode (exact match)
|
||||||
-i Case-insensitive match (default: smart-case match)
|
-i Case-insensitive match (default: smart-case match)
|
||||||
+i Case-sensitive match
|
+i Case-sensitive match
|
||||||
-n, --nth=[-]N[,..] Comma-separated list of field indexes for limiting
|
-n, --nth=N[,..] Comma-separated list of field index expressions
|
||||||
search scope (positive or negative integers)
|
for limiting search scope. Each can be a non-zero
|
||||||
|
integer or a range expression ([BEGIN]..[END])
|
||||||
-d, --delimiter=STR Field delimiter regex for --nth (default: AWK-style)
|
-d, --delimiter=STR Field delimiter regex for --nth (default: AWK-style)
|
||||||
|
|
||||||
Search result
|
Search result
|
||||||
|
|||||||
37
fzf
37
fzf
@@ -7,7 +7,7 @@
|
|||||||
# / __/ / /_/ __/
|
# / __/ / /_/ __/
|
||||||
# /_/ /___/_/ Fuzzy finder for your shell
|
# /_/ /___/_/ Fuzzy finder for your shell
|
||||||
#
|
#
|
||||||
# Version: 0.8.5 (Jun 12, 2014)
|
# Version: 0.8.5 (Jun 14, 2014)
|
||||||
#
|
#
|
||||||
# Author: Junegunn Choi
|
# Author: Junegunn Choi
|
||||||
# URL: https://github.com/junegunn/fzf
|
# URL: https://github.com/junegunn/fzf
|
||||||
@@ -133,10 +133,9 @@ class FZF
|
|||||||
when /^-f(.*)$/, /^--filter=(.*)$/
|
when /^-f(.*)$/, /^--filter=(.*)$/
|
||||||
@filter = $1
|
@filter = $1
|
||||||
when '-n', '--nth'
|
when '-n', '--nth'
|
||||||
usage 1, 'field number required' unless nth = argv.shift
|
usage 1, 'field expression required' unless nth = argv.shift
|
||||||
usage 1, 'invalid field number' if nth.to_i == 0
|
|
||||||
@nth = parse_nth nth
|
@nth = parse_nth nth
|
||||||
when /^-n([0-9,-]+)$/, /^--nth=([0-9,-]+)$/
|
when /^-n([0-9,-\.]+)$/, /^--nth=([0-9,-\.]+)$/
|
||||||
@nth = parse_nth $1
|
@nth = parse_nth $1
|
||||||
when '-d', '--delimiter'
|
when '-d', '--delimiter'
|
||||||
usage 1, 'delimiter required' unless delim = argv.shift
|
usage 1, 'delimiter required' unless delim = argv.shift
|
||||||
@@ -179,10 +178,20 @@ class FZF
|
|||||||
end
|
end
|
||||||
|
|
||||||
def parse_nth nth
|
def parse_nth nth
|
||||||
nth.split(',').map { |n|
|
nth.split(',').map { |expr|
|
||||||
ni = n.to_i
|
x = proc { usage 1, "invalid field expression: #{expr}" }
|
||||||
usage 1, "invalid field number: #{n}" if ni == 0
|
first, second = expr.split('..', 2)
|
||||||
ni
|
x.call if !first.empty? && first.to_i == 0 ||
|
||||||
|
second && !second.empty? && (second.to_i == 0 || second.include?('.'))
|
||||||
|
|
||||||
|
first = first.empty? ? 1 : first.to_i
|
||||||
|
second = case second
|
||||||
|
when nil then first
|
||||||
|
when '' then -1
|
||||||
|
else second.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
Range.new(*[first, second].map { |e| e > 0 ? e - 1 : e })
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -281,8 +290,9 @@ class FZF
|
|||||||
-e, --extended-exact Extended-search mode (exact match)
|
-e, --extended-exact Extended-search mode (exact match)
|
||||||
-i Case-insensitive match (default: smart-case match)
|
-i Case-insensitive match (default: smart-case match)
|
||||||
+i Case-sensitive match
|
+i Case-sensitive match
|
||||||
-n, --nth=[-]N[,..] Comma-separated list of field indexes for limiting
|
-n, --nth=N[,..] Comma-separated list of field index expressions
|
||||||
search scope (positive or negative integers)
|
for limiting search scope. Each can be a non-zero
|
||||||
|
integer or a range expression ([BEGIN]..[END])
|
||||||
-d, --delimiter=STR Field delimiter regex for --nth (default: AWK-style)
|
-d, --delimiter=STR Field delimiter regex for --nth (default: AWK-style)
|
||||||
|
|
||||||
Search result
|
Search result
|
||||||
@@ -1011,7 +1021,7 @@ class FZF
|
|||||||
end
|
end
|
||||||
|
|
||||||
def initialize nth, delim
|
def initialize nth, delim
|
||||||
@nth = nth && nth.map { |n| n > 0 ? n - 1 : n }
|
@nth = nth
|
||||||
@delim = delim
|
@delim = delim
|
||||||
@tokens_cache = {}
|
@tokens_cache = {}
|
||||||
end
|
end
|
||||||
@@ -1033,8 +1043,9 @@ class FZF
|
|||||||
prefix_length, tokens = tokenize str
|
prefix_length, tokens = tokenize str
|
||||||
|
|
||||||
@nth.each do |n|
|
@nth.each do |n|
|
||||||
if (token = tokens[n]) && (md = token.match(pat) rescue nil)
|
if (range = tokens[n]) && (token = range.join) &&
|
||||||
prefix_length += (tokens[0...n] || []).join.length
|
(md = token.sub(/\s+$/, '').match(pat) rescue nil)
|
||||||
|
prefix_length += (tokens[0...(n.begin)] || []).join.length
|
||||||
offset = md.offset(0).map { |o| o + prefix_length }
|
offset = md.offset(0).map { |o| o + prefix_length }
|
||||||
return MatchData.new(offset)
|
return MatchData.new(offset)
|
||||||
end
|
end
|
||||||
|
|||||||
6
install
6
install
@@ -140,7 +140,7 @@ if [ -z "$(set -o | grep '^vi.*on')" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# CTRL-R - Paste the selected command from history into the command line
|
# CTRL-R - Paste the selected command from history into the command line
|
||||||
bind '"\C-r": " \C-e\C-u$(HISTTIMEFORMAT= history | fzf +s | sed \"s/ *[0-9]* *//\")\e\C-e\er"'
|
bind '"\C-r": " \C-e\C-u$(HISTTIMEFORMAT= history | fzf +s +m -n..,1,2.. | sed \"s/ *[0-9]* *//\")\e\C-e\er"'
|
||||||
|
|
||||||
# ALT-C - cd into the selected directory
|
# ALT-C - cd into the selected directory
|
||||||
bind '"\ec": " \C-e\C-u$(__fcd)\e\C-e\er\C-m"'
|
bind '"\ec": " \C-e\C-u$(__fcd)\e\C-e\er\C-m"'
|
||||||
@@ -157,7 +157,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# CTRL-R - Paste the selected command from history into the command line
|
# CTRL-R - Paste the selected command from history into the command line
|
||||||
bind '"\C-r": "\eddi$(HISTTIMEFORMAT= history | fzf +s | sed \"s/ *[0-9]* *//\")\C-x\C-e\e$a\C-x\C-r"'
|
bind '"\C-r": "\eddi$(HISTTIMEFORMAT= history | fzf +s +m -n..,1,2.. | sed \"s/ *[0-9]* *//\")\C-x\C-e\e$a\C-x\C-r"'
|
||||||
|
|
||||||
# ALT-C - cd into the selected directory
|
# ALT-C - cd into the selected directory
|
||||||
bind '"\ec": "\eddi$(__fcd)\C-x\C-e\C-x\C-r\C-m"'
|
bind '"\ec": "\eddi$(__fcd)\C-x\C-e\C-x\C-r\C-m"'
|
||||||
@@ -216,7 +216,7 @@ bindkey '\ec' fzf-cd-widget
|
|||||||
|
|
||||||
# CTRL-R - Paste the selected command from history into the command line
|
# CTRL-R - Paste the selected command from history into the command line
|
||||||
fzf-history-widget() {
|
fzf-history-widget() {
|
||||||
LBUFFER=$(fc -l 1 | fzf +s | sed "s/ *[0-9*]* *//")
|
LBUFFER=$(fc -l 1 | fzf +s +m -n..,1,2.. | sed "s/ *[0-9*]* *//")
|
||||||
zle redisplay
|
zle redisplay
|
||||||
}
|
}
|
||||||
zle -N fzf-history-widget
|
zle -N fzf-history-widget
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal true, fzf.select1
|
assert_equal true, fzf.select1
|
||||||
assert_equal true, fzf.exit0
|
assert_equal true, fzf.exit0
|
||||||
assert_equal true, fzf.reverse
|
assert_equal true, fzf.reverse
|
||||||
assert_equal [3, -1, 2], fzf.nth
|
assert_equal [2..2, -1..-1, 1..1], fzf.nth
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_option_parser
|
def test_option_parser
|
||||||
@@ -80,7 +80,7 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal true, fzf.exit0
|
assert_equal true, fzf.exit0
|
||||||
assert_equal 'howdy', fzf.filter
|
assert_equal 'howdy', fzf.filter
|
||||||
assert_equal :exact, fzf.extended
|
assert_equal :exact, fzf.extended
|
||||||
assert_equal [1], fzf.nth
|
assert_equal [0..0], fzf.nth
|
||||||
assert_equal true, fzf.reverse
|
assert_equal true, fzf.reverse
|
||||||
|
|
||||||
# Long opts (left-to-right)
|
# Long opts (left-to-right)
|
||||||
@@ -101,7 +101,7 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal false, fzf.select1
|
assert_equal false, fzf.select1
|
||||||
assert_equal false, fzf.exit0
|
assert_equal false, fzf.exit0
|
||||||
assert_equal nil, fzf.extended
|
assert_equal nil, fzf.extended
|
||||||
assert_equal [-2], fzf.nth
|
assert_equal [-2..-2], fzf.nth
|
||||||
assert_equal false, fzf.reverse
|
assert_equal false, fzf.reverse
|
||||||
|
|
||||||
# Short opts
|
# Short opts
|
||||||
@@ -114,7 +114,7 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal 'hello', fzf.query.get
|
assert_equal 'hello', fzf.query.get
|
||||||
assert_equal 'howdy', fzf.filter
|
assert_equal 'howdy', fzf.filter
|
||||||
assert_equal :fuzzy, fzf.extended
|
assert_equal :fuzzy, fzf.extended
|
||||||
assert_equal [3], fzf.nth
|
assert_equal [2..2], fzf.nth
|
||||||
assert_equal true, fzf.select1
|
assert_equal true, fzf.select1
|
||||||
assert_equal true, fzf.exit0
|
assert_equal true, fzf.exit0
|
||||||
|
|
||||||
@@ -134,23 +134,28 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal false, fzf.exit0
|
assert_equal false, fzf.exit0
|
||||||
assert_equal 'world', fzf.filter
|
assert_equal 'world', fzf.filter
|
||||||
assert_equal nil, fzf.extended
|
assert_equal nil, fzf.extended
|
||||||
assert_equal [4, 5], fzf.nth
|
assert_equal [3..3, 4..4], fzf.nth
|
||||||
rescue SystemExit => e
|
rescue SystemExit => e
|
||||||
assert false, "Exited"
|
assert false, "Exited"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_invalid_option
|
def test_invalid_option
|
||||||
[%w[--unknown], %w[yo dawg]].each do |argv|
|
[
|
||||||
|
%w[--unknown],
|
||||||
|
%w[yo dawg],
|
||||||
|
%w[--nth=0],
|
||||||
|
%w[-n 0],
|
||||||
|
%w[-n 1..2..3],
|
||||||
|
%w[-n 1....],
|
||||||
|
%w[-n ....3],
|
||||||
|
%w[-n 1....3],
|
||||||
|
%w[-n 1..0],
|
||||||
|
%w[--nth ..0],
|
||||||
|
].each do |argv|
|
||||||
assert_raises(SystemExit) do
|
assert_raises(SystemExit) do
|
||||||
fzf = FZF.new argv
|
fzf = FZF.new argv
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
assert_raises(SystemExit) do
|
|
||||||
fzf = FZF.new %w[--nth=0]
|
|
||||||
end
|
|
||||||
assert_raises(SystemExit) do
|
|
||||||
fzf = FZF.new %w[-n 0]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# FIXME Only on 1.9 or above
|
# FIXME Only on 1.9 or above
|
||||||
@@ -487,43 +492,67 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
[list[0], [[2, 5]]],
|
[list[0], [[2, 5]]],
|
||||||
[list[1], [[9, 17]]]], matcher.match(list, 'is', '', '')
|
[list[1], [[9, 17]]]], matcher.match(list, 'is', '', '')
|
||||||
|
|
||||||
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [2]
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [1..1]
|
||||||
assert_equal [[list[1], [[8, 9]]]], matcher.match(list, 'f', '', '')
|
assert_equal [[list[1], [[8, 9]]]], matcher.match(list, 'f', '', '')
|
||||||
assert_equal [[list[0], [[8, 9]]]], matcher.match(list, 's', '', '')
|
assert_equal [[list[0], [[8, 9]]]], matcher.match(list, 's', '', '')
|
||||||
|
|
||||||
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [3]
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [2..2]
|
||||||
assert_equal [[list[0], [[19, 20]]]], matcher.match(list, 'r', '', '')
|
assert_equal [[list[0], [[19, 20]]]], matcher.match(list, 'r', '', '')
|
||||||
|
|
||||||
# Comma-separated
|
# Comma-separated
|
||||||
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [3, 1]
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [2..2, 0..0]
|
||||||
assert_equal [[list[0], [[19, 20]]], [list[1], [[3, 4]]]], matcher.match(list, 'r', '', '')
|
assert_equal [[list[0], [[19, 20]]], [list[1], [[3, 4]]]], matcher.match(list, 'r', '', '')
|
||||||
|
|
||||||
# Ordered
|
# Ordered
|
||||||
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [1, 3]
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [0..0, 2..2]
|
||||||
assert_equal [[list[0], [[3, 4]]], [list[1], [[3, 4]]]], matcher.match(list, 'r', '', '')
|
assert_equal [[list[0], [[3, 4]]], [list[1], [[3, 4]]]], matcher.match(list, 'r', '', '')
|
||||||
|
|
||||||
regex = FZF.build_delim_regex "\t"
|
regex = FZF.build_delim_regex "\t"
|
||||||
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [1], regex
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [0..0], regex
|
||||||
assert_equal [[list[0], [[3, 10]]]], matcher.match(list, 're', '', '')
|
assert_equal [[list[0], [[3, 10]]]], matcher.match(list, 're', '', '')
|
||||||
|
|
||||||
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [2], regex
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [1..1], regex
|
||||||
assert_equal [], matcher.match(list, 'r', '', '')
|
assert_equal [], matcher.match(list, 'r', '', '')
|
||||||
assert_equal [[list[1], [[9, 17]]]], matcher.match(list, 'is', '', '')
|
assert_equal [[list[1], [[9, 17]]]], matcher.match(list, 'is', '', '')
|
||||||
|
|
||||||
# Negative indexing
|
# Negative indexing
|
||||||
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [-1], regex
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [-1..-1], regex
|
||||||
assert_equal [[list[0], [[3, 6]]]], matcher.match(list, 'rt', '', '')
|
assert_equal [[list[0], [[3, 6]]]], matcher.match(list, 'rt', '', '')
|
||||||
assert_equal [[list[0], [[2, 5]]], [list[1], [[9, 17]]]], matcher.match(list, 'is', '', '')
|
assert_equal [[list[0], [[2, 5]]], [list[1], [[9, 17]]]], matcher.match(list, 'is', '', '')
|
||||||
|
|
||||||
# Regex delimiter
|
# Regex delimiter
|
||||||
regex = FZF.build_delim_regex "[ \t]+"
|
regex = FZF.build_delim_regex "[ \t]+"
|
||||||
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [1], regex
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [0..0], regex
|
||||||
assert_equal [list[1]], matcher.match(list, 'f', '', '').map(&:first)
|
assert_equal [list[1]], matcher.match(list, 'f', '', '').map(&:first)
|
||||||
|
|
||||||
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [2], regex
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [1..1], regex
|
||||||
assert_equal [[list[0], [[1, 2]]], [list[1], [[8, 9]]]], matcher.match(list, 'f', '', '')
|
assert_equal [[list[0], [[1, 2]]], [list[1], [[8, 9]]]], matcher.match(list, 'f', '', '')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_nth_match_range
|
||||||
|
list = [
|
||||||
|
' first second third',
|
||||||
|
'fourth fifth sixth',
|
||||||
|
]
|
||||||
|
|
||||||
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [1..2]
|
||||||
|
assert_equal [[list[0], [[8, 20]]]], matcher.match(list, 'sr', '', '')
|
||||||
|
assert_equal [], matcher.match(list, 'fo', '', '')
|
||||||
|
|
||||||
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [1..-1, 0..0]
|
||||||
|
assert_equal [[list[0], [[8, 20]]]], matcher.match(list, 'sr', '', '')
|
||||||
|
assert_equal [[list[1], [[0, 2]]]], matcher.match(list, 'fo', '', '')
|
||||||
|
|
||||||
|
matcher = FZF::ExtendedFuzzyMatcher.new Regexp::IGNORECASE, :fuzzy, [0..0, 1..2]
|
||||||
|
assert_equal [], matcher.match(list, '^t', '', '')
|
||||||
|
|
||||||
|
matcher = FZF::ExtendedFuzzyMatcher.new Regexp::IGNORECASE, :fuzzy, [0..1, 2..2]
|
||||||
|
assert_equal [[list[0], [[16, 17]]]], matcher.match(list, '^t', '', '')
|
||||||
|
|
||||||
|
matcher = FZF::ExtendedFuzzyMatcher.new Regexp::IGNORECASE, :fuzzy, [1..-1]
|
||||||
|
assert_equal [[list[0], [[8, 9]]]], matcher.match(list, '^s', '', '')
|
||||||
|
end
|
||||||
|
|
||||||
def stream_for str
|
def stream_for str
|
||||||
StringIO.new(str).tap do |sio|
|
StringIO.new(str).tap do |sio|
|
||||||
sio.instance_eval do
|
sio.instance_eval do
|
||||||
|
|||||||
Reference in New Issue
Block a user