mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2025-01-09 17:53:56 +00:00
parent
ab9fbf1967
commit
22d3929ae3
53
README.md
53
README.md
@ -50,23 +50,31 @@ Usage
|
|||||||
```
|
```
|
||||||
usage: fzf [options]
|
usage: fzf [options]
|
||||||
|
|
||||||
Options
|
Search
|
||||||
-m, --multi Enable multi-select
|
|
||||||
-x, --extended Extended-search mode
|
-x, --extended Extended-search mode
|
||||||
-e, --extended-exact Extended-search mode (exact match)
|
-e, --extended-exact Extended-search mode (exact match)
|
||||||
-q, --query=STR Initial query
|
-i Case-insensitive match (default: smart-case match)
|
||||||
-f, --filter=STR Filter mode. Do not start interactive finder.
|
+i Case-sensitive match
|
||||||
-n, --nth=[-]N[,..] Comma-separated list of field indexes for limiting
|
-n, --nth=[-]N[,..] Comma-separated list of field indexes for limiting
|
||||||
search scope (positive or negative integers)
|
search scope (positive or negative integers)
|
||||||
-d, --delimiter=STR Field delimiter regex for --nth (default: AWK-style)
|
-d, --delimiter=STR Field delimiter regex for --nth (default: AWK-style)
|
||||||
|
|
||||||
|
Search result
|
||||||
-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
|
Interface
|
||||||
|
-m, --multi Enable multi-select with tab/shift-tab
|
||||||
|
--no-mouse Disable mouse
|
||||||
+c, --no-color Disable colors
|
+c, --no-color Disable colors
|
||||||
+2, --no-256 Disable 256-color
|
+2, --no-256 Disable 256-color
|
||||||
--black Use black background
|
--black Use black background
|
||||||
--no-mouse Disable mouse
|
|
||||||
|
Scripting
|
||||||
|
-q, --query=STR Start the finder with the given query
|
||||||
|
-1, --select-1 (with --query) Automatically select the only match
|
||||||
|
-0, --exit-0 (with --query) Exit when there's no match
|
||||||
|
-f, --filter=STR Filter mode. Do not start interactive finder.
|
||||||
|
|
||||||
Environment variables
|
Environment variables
|
||||||
FZF_DEFAULT_COMMAND Default command to use when input is tty
|
FZF_DEFAULT_COMMAND Default command to use when input is tty
|
||||||
@ -137,10 +145,12 @@ Useful examples
|
|||||||
---------------
|
---------------
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# vimf - Open selected file in Vim
|
# fe [FUZZY PATTERN] - Open the selected file with the default editor
|
||||||
vimf() {
|
# - Bypass fuzzy finder if there's only one match (--select-1)
|
||||||
|
# - Exit if there's no match (--exit-0)
|
||||||
|
fe() {
|
||||||
local file
|
local file
|
||||||
file=$(fzf --query="$1") && vim "$file"
|
file=$(fzf --query="$1" --select-1 --exit-0) && ${EDITOR:-vim} "$file"
|
||||||
}
|
}
|
||||||
|
|
||||||
# fd - cd to selected directory
|
# fd - cd to selected directory
|
||||||
@ -193,29 +203,6 @@ ftags() {
|
|||||||
) && $EDITOR $(cut -f3 <<< "$line") -c "set nocst" \
|
) && $EDITOR $(cut -f3 <<< "$line") -c "set nocst" \
|
||||||
-c "silent tag $(cut -f2 <<< "$line")"
|
-c "silent tag $(cut -f2 <<< "$line")"
|
||||||
}
|
}
|
||||||
|
|
||||||
# fq1 [QUERY]
|
|
||||||
# - Immediately select the file when there's only one match.
|
|
||||||
# If not, start the fuzzy finder as usual.
|
|
||||||
fq1() {
|
|
||||||
local lines
|
|
||||||
lines=$(fzf --filter="$1" --no-sort)
|
|
||||||
if [ -z "$lines" ]; then
|
|
||||||
return 1
|
|
||||||
elif [ $(wc -l <<< "$lines") -eq 1 ]; then
|
|
||||||
echo "$lines"
|
|
||||||
else
|
|
||||||
echo "$lines" | fzf --query="$1"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# fe [QUERY]
|
|
||||||
# - Open the selected file with the default editor
|
|
||||||
# (Bypass fuzzy finder when there's only one match)
|
|
||||||
fe() {
|
|
||||||
local file
|
|
||||||
file=$(fq1 "$1") && ${EDITOR:-vim} "$file"
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Key bindings for command line
|
Key bindings for command line
|
||||||
|
106
fzf
106
fzf
@ -51,7 +51,7 @@ end
|
|||||||
class FZF
|
class FZF
|
||||||
C = Curses
|
C = Curses
|
||||||
attr_reader :rxflag, :sort, :nth, :color, :black, :ansi256,
|
attr_reader :rxflag, :sort, :nth, :color, :black, :ansi256,
|
||||||
:mouse, :multi, :query, :filter, :extended
|
:mouse, :multi, :query, :select1, :exit0, :filter, :extended
|
||||||
|
|
||||||
class AtomicVar
|
class AtomicVar
|
||||||
def initialize value
|
def initialize value
|
||||||
@ -83,6 +83,8 @@ class FZF
|
|||||||
@multi = false
|
@multi = false
|
||||||
@mouse = true
|
@mouse = true
|
||||||
@extended = nil
|
@extended = nil
|
||||||
|
@select1 = false
|
||||||
|
@exit0 = false
|
||||||
@filter = nil
|
@filter = nil
|
||||||
@nth = nil
|
@nth = nil
|
||||||
@delim = nil
|
@delim = nil
|
||||||
@ -113,6 +115,10 @@ class FZF
|
|||||||
when '--mouse' then @mouse = true
|
when '--mouse' then @mouse = true
|
||||||
when '--no-mouse' then @mouse = false
|
when '--no-mouse' then @mouse = false
|
||||||
when '+s', '--no-sort' then @sort = nil
|
when '+s', '--no-sort' then @sort = nil
|
||||||
|
when '-1', '--select-1' then @select1 = true
|
||||||
|
when '+1', '--no-select-1' then @select1 = false
|
||||||
|
when '-0', '--exit-0' then @exit0 = true
|
||||||
|
when '+0', '--no-exit-0' then @exit0 = false
|
||||||
when '-q', '--query'
|
when '-q', '--query'
|
||||||
usage 1, 'query string required' unless query = argv.shift
|
usage 1, 'query string required' unless query = argv.shift
|
||||||
@query = AtomicVar.new query.dup
|
@query = AtomicVar.new query.dup
|
||||||
@ -184,41 +190,60 @@ class FZF
|
|||||||
|
|
||||||
def start
|
def start
|
||||||
if @filter
|
if @filter
|
||||||
start_reader(false).join
|
start_reader.join
|
||||||
filter_list @new
|
filter_list @new
|
||||||
else
|
else
|
||||||
@stdout = $stdout.clone
|
start_reader
|
||||||
$stdout.reopen($stderr)
|
emit(:key) { q = @query.get; [q, q.length] } unless @query.empty?
|
||||||
|
if !@query.empty? && (@select1 || @exit0)
|
||||||
|
start_search do |loaded, matches|
|
||||||
|
len = matches.length
|
||||||
|
if loaded
|
||||||
|
if @select1 && len == 1
|
||||||
|
puts matches.first.first
|
||||||
|
exit 0
|
||||||
|
elsif @exit0 && len == 0
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
start_reader true
|
if loaded || len > 1
|
||||||
init_screen
|
start_renderer
|
||||||
start_renderer
|
Thread.new { start_loop }
|
||||||
start_search
|
end
|
||||||
start_loop
|
end
|
||||||
|
|
||||||
|
sleep
|
||||||
|
else
|
||||||
|
start_search
|
||||||
|
start_renderer
|
||||||
|
start_loop
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_list list
|
def filter_list list
|
||||||
matches = get_matcher.match(list, @filter, '', '')
|
matches = matcher.match(list, @filter, '', '')
|
||||||
if @sort && matches.length <= @sort
|
if @sort && matches.length <= @sort
|
||||||
matches = sort_by_rank(matches)
|
matches = sort_by_rank(matches)
|
||||||
end
|
end
|
||||||
matches.each { |m| puts m.first }
|
matches.each { |m| puts m.first }
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_matcher
|
def matcher
|
||||||
if @extended
|
@matcher ||=
|
||||||
ExtendedFuzzyMatcher.new @rxflag, @extended, @nth, @delim
|
if @extended
|
||||||
else
|
ExtendedFuzzyMatcher.new @rxflag, @extended, @nth, @delim
|
||||||
FuzzyMatcher.new @rxflag, @nth, @delim
|
else
|
||||||
end
|
FuzzyMatcher.new @rxflag, @nth, @delim
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def version
|
def version
|
||||||
File.open(__FILE__, 'r') do |f|
|
File.open(__FILE__, 'r') do |f|
|
||||||
f.each_line do |line|
|
f.each_line do |line|
|
||||||
if line =~ /Version: (.*)/
|
if line =~ /Version: (.*)/
|
||||||
$stdout.puts "fzf " << $1
|
$stdout.puts 'fzf ' << $1
|
||||||
exit
|
exit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -229,23 +254,31 @@ class FZF
|
|||||||
$stderr.puts message if message
|
$stderr.puts message if message
|
||||||
$stderr.puts %[usage: fzf [options]
|
$stderr.puts %[usage: fzf [options]
|
||||||
|
|
||||||
Options
|
Search
|
||||||
-m, --multi Enable multi-select
|
|
||||||
-x, --extended Extended-search mode
|
-x, --extended Extended-search mode
|
||||||
-e, --extended-exact Extended-search mode (exact match)
|
-e, --extended-exact Extended-search mode (exact match)
|
||||||
-q, --query=STR Initial query
|
-i Case-insensitive match (default: smart-case match)
|
||||||
-f, --filter=STR Filter mode. Do not start interactive finder.
|
+i Case-sensitive match
|
||||||
-n, --nth=[-]N[,..] Comma-separated list of field indexes for limiting
|
-n, --nth=[-]N[,..] Comma-separated list of field indexes for limiting
|
||||||
search scope (positive or negative integers)
|
search scope (positive or negative integers)
|
||||||
-d, --delimiter=STR Field delimiter regex for --nth (default: AWK-style)
|
-d, --delimiter=STR Field delimiter regex for --nth (default: AWK-style)
|
||||||
|
|
||||||
|
Search result
|
||||||
-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
|
Interface
|
||||||
|
-m, --multi Enable multi-select with tab/shift-tab
|
||||||
|
--no-mouse Disable mouse
|
||||||
+c, --no-color Disable colors
|
+c, --no-color Disable colors
|
||||||
+2, --no-256 Disable 256-color
|
+2, --no-256 Disable 256-color
|
||||||
--black Use black background
|
--black Use black background
|
||||||
--no-mouse Disable mouse
|
|
||||||
|
Scripting
|
||||||
|
-q, --query=STR Start the finder with the given query
|
||||||
|
-1, --select-1 (with --query) Automatically select the only match
|
||||||
|
-0, --exit-0 (with --query) Exit when there's no match
|
||||||
|
-f, --filter=STR Filter mode. Do not start interactive finder.
|
||||||
|
|
||||||
Environment variables
|
Environment variables
|
||||||
FZF_DEFAULT_COMMAND Default command to use when input is tty
|
FZF_DEFAULT_COMMAND Default command to use when input is tty
|
||||||
@ -547,6 +580,9 @@ class FZF
|
|||||||
end
|
end
|
||||||
|
|
||||||
def init_screen
|
def init_screen
|
||||||
|
@stdout = $stdout.clone
|
||||||
|
$stdout.reopen($stderr)
|
||||||
|
|
||||||
C.init_screen
|
C.init_screen
|
||||||
C.mousemask C::ALL_MOUSE_EVENTS if @mouse
|
C.mousemask C::ALL_MOUSE_EVENTS if @mouse
|
||||||
C.start_color
|
C.start_color
|
||||||
@ -604,7 +640,7 @@ class FZF
|
|||||||
C.refresh
|
C.refresh
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_reader curses
|
def start_reader
|
||||||
stream =
|
stream =
|
||||||
if @source.tty?
|
if @source.tty?
|
||||||
if default_command = ENV['FZF_DEFAULT_COMMAND']
|
if default_command = ENV['FZF_DEFAULT_COMMAND']
|
||||||
@ -623,13 +659,12 @@ class FZF
|
|||||||
emit(:new) { @new << line.chomp }
|
emit(:new) { @new << line.chomp }
|
||||||
end
|
end
|
||||||
emit(:loaded) { true }
|
emit(:loaded) { true }
|
||||||
@spinner.clear if curses
|
@spinner.clear if @spinner
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_search
|
def start_search &callback
|
||||||
matcher = get_matcher
|
Thread.new do
|
||||||
searcher = Thread.new {
|
|
||||||
lists = []
|
lists = []
|
||||||
events = {}
|
events = {}
|
||||||
fcache = {}
|
fcache = {}
|
||||||
@ -668,7 +703,7 @@ class FZF
|
|||||||
progress = 0
|
progress = 0
|
||||||
started_at = Time.now
|
started_at = Time.now
|
||||||
|
|
||||||
if new_search && !lists.empty?
|
if updated = new_search && !lists.empty?
|
||||||
q, cx = events.delete(:key) || [q, 0]
|
q, cx = events.delete(:key) || [q, 0]
|
||||||
empty = matcher.empty?(q)
|
empty = matcher.empty?(q)
|
||||||
unless matches = fcache[q]
|
unless matches = fcache[q]
|
||||||
@ -699,6 +734,10 @@ class FZF
|
|||||||
@matches.set matches
|
@matches.set matches
|
||||||
end#new_search
|
end#new_search
|
||||||
|
|
||||||
|
callback = nil if callback &&
|
||||||
|
(updated || events[:loaded]) &&
|
||||||
|
callback.call(events[:loaded], matches)
|
||||||
|
|
||||||
# This small delay reduces the number of partial lists
|
# This small delay reduces the number of partial lists
|
||||||
sleep((delay = [20, delay + 5].min) * 0.01) unless user_input
|
sleep((delay = [20, delay + 5].min) * 0.01) unless user_input
|
||||||
|
|
||||||
@ -707,7 +746,7 @@ class FZF
|
|||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
@main.raise e
|
@main.raise e
|
||||||
end
|
end
|
||||||
}
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def pick
|
def pick
|
||||||
@ -751,6 +790,8 @@ class FZF
|
|||||||
end
|
end
|
||||||
|
|
||||||
def start_renderer
|
def start_renderer
|
||||||
|
init_screen
|
||||||
|
|
||||||
Thread.new do
|
Thread.new do
|
||||||
begin
|
begin
|
||||||
while blk = @queue.shift
|
while blk = @queue.shift
|
||||||
@ -1030,7 +1071,6 @@ class FZF
|
|||||||
actions[127] = actions[ctrl(:h)]
|
actions[127] = actions[ctrl(:h)]
|
||||||
actions[ctrl(:q)] = actions[ctrl(:g)] = actions[ctrl(:c)] = actions[:esc]
|
actions[ctrl(:q)] = actions[ctrl(:g)] = actions[ctrl(:c)] = actions[:esc]
|
||||||
|
|
||||||
emit(:key) { [@query.get, cursor] } unless @query.empty?
|
|
||||||
while true
|
while true
|
||||||
@cursor_x.set cursor
|
@cursor_x.set cursor
|
||||||
render { print_input }
|
render { print_input }
|
||||||
@ -1093,7 +1133,7 @@ class FZF
|
|||||||
if (token = tokens[n]) && (md = token.match(pat) rescue nil)
|
if (token = tokens[n]) && (md = token.match(pat) rescue nil)
|
||||||
prefix_length += (tokens[0...n] || []).join.length
|
prefix_length += (tokens[0...n] || []).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
|
||||||
end
|
end
|
||||||
nil
|
nil
|
||||||
|
101
test/test_fzf.rb
101
test/test_fzf.rb
@ -1,6 +1,9 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
|
||||||
|
require 'curses'
|
||||||
|
require 'timeout'
|
||||||
|
require 'stringio'
|
||||||
require 'minitest/autorun'
|
require 'minitest/autorun'
|
||||||
$LOAD_PATH.unshift File.expand_path('../..', __FILE__)
|
$LOAD_PATH.unshift File.expand_path('../..', __FILE__)
|
||||||
ENV['FZF_EXECUTABLE'] = '0'
|
ENV['FZF_EXECUTABLE'] = '0'
|
||||||
@ -20,6 +23,15 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal true, fzf.color
|
assert_equal true, fzf.color
|
||||||
assert_equal nil, fzf.rxflag
|
assert_equal nil, fzf.rxflag
|
||||||
assert_equal true, fzf.mouse
|
assert_equal true, fzf.mouse
|
||||||
|
assert_equal nil, fzf.nth
|
||||||
|
assert_equal true, fzf.color
|
||||||
|
assert_equal false, fzf.black
|
||||||
|
assert_equal true, fzf.ansi256
|
||||||
|
assert_equal '', fzf.query.get
|
||||||
|
assert_equal false, fzf.select1
|
||||||
|
assert_equal false, fzf.exit0
|
||||||
|
assert_equal nil, fzf.filter
|
||||||
|
assert_equal nil, fzf.extended
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_environment_variables
|
def test_environment_variables
|
||||||
@ -30,7 +42,8 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal nil, fzf.nth
|
assert_equal nil, fzf.nth
|
||||||
|
|
||||||
ENV['FZF_DEFAULT_OPTS'] =
|
ENV['FZF_DEFAULT_OPTS'] =
|
||||||
'-x -m -s 10000 -q " hello world " +c +2 --no-mouse -f "goodbye world" --black --nth=3,-1,2'
|
'-x -m -s 10000 -q " hello world " +c +2 --select-1 -0 ' +
|
||||||
|
'--no-mouse -f "goodbye world" --black --nth=3,-1,2'
|
||||||
fzf = FZF.new []
|
fzf = FZF.new []
|
||||||
assert_equal 10000, fzf.sort
|
assert_equal 10000, fzf.sort
|
||||||
assert_equal ' hello world ',
|
assert_equal ' hello world ',
|
||||||
@ -43,13 +56,16 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal false, fzf.ansi256
|
assert_equal false, fzf.ansi256
|
||||||
assert_equal true, fzf.black
|
assert_equal true, fzf.black
|
||||||
assert_equal false, fzf.mouse
|
assert_equal false, fzf.mouse
|
||||||
|
assert_equal true, fzf.select1
|
||||||
|
assert_equal true, fzf.exit0
|
||||||
assert_equal [3, -1, 2], fzf.nth
|
assert_equal [3, -1, 2], fzf.nth
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_option_parser
|
def test_option_parser
|
||||||
# Long opts
|
# Long opts
|
||||||
fzf = FZF.new %w[--sort=2000 --no-color --multi +i --query hello
|
fzf = FZF.new %w[--sort=2000 --no-color --multi +i --query hello --select-1
|
||||||
--filter=howdy --extended-exact --no-mouse --no-256 --nth=1]
|
--exit-0 --filter=howdy --extended-exact
|
||||||
|
--no-mouse --no-256 --nth=1]
|
||||||
assert_equal 2000, fzf.sort
|
assert_equal 2000, fzf.sort
|
||||||
assert_equal true, fzf.multi
|
assert_equal true, fzf.multi
|
||||||
assert_equal false, fzf.color
|
assert_equal false, fzf.color
|
||||||
@ -58,12 +74,16 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal false, fzf.mouse
|
assert_equal false, fzf.mouse
|
||||||
assert_equal 0, fzf.rxflag
|
assert_equal 0, fzf.rxflag
|
||||||
assert_equal 'hello', fzf.query.get
|
assert_equal 'hello', fzf.query.get
|
||||||
|
assert_equal true, fzf.select1
|
||||||
|
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 [1], fzf.nth
|
||||||
|
|
||||||
fzf = FZF.new %w[--sort=2000 --no-color --multi +i --query hello
|
# Long opts (left-to-right)
|
||||||
--filter a --filter b --no-256 --black --nth -2
|
fzf = FZF.new %w[--sort=2000 --no-color --multi +i --query=hello
|
||||||
|
--filter a --filter b --no-256 --black --nth -1 --nth -2
|
||||||
|
--select-1 --exit-0 --no-select-1 --no-exit-0
|
||||||
--no-sort -i --color --no-multi --256]
|
--no-sort -i --color --no-multi --256]
|
||||||
assert_equal nil, fzf.sort
|
assert_equal nil, fzf.sort
|
||||||
assert_equal false, fzf.multi
|
assert_equal false, fzf.multi
|
||||||
@ -74,11 +94,13 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal 1, fzf.rxflag
|
assert_equal 1, fzf.rxflag
|
||||||
assert_equal 'b', fzf.filter
|
assert_equal 'b', fzf.filter
|
||||||
assert_equal 'hello', fzf.query.get
|
assert_equal 'hello', fzf.query.get
|
||||||
|
assert_equal false, fzf.select1
|
||||||
|
assert_equal false, fzf.exit0
|
||||||
assert_equal nil, fzf.extended
|
assert_equal nil, fzf.extended
|
||||||
assert_equal [-2], fzf.nth
|
assert_equal [-2], fzf.nth
|
||||||
|
|
||||||
# Short opts
|
# Short opts
|
||||||
fzf = FZF.new %w[-s 2000 +c -m +i -qhello -x -fhowdy +2 -n3]
|
fzf = FZF.new %w[-s2000 +c -m +i -qhello -x -fhowdy +2 -n3 -1 -0]
|
||||||
assert_equal 2000, fzf.sort
|
assert_equal 2000, fzf.sort
|
||||||
assert_equal true, fzf.multi
|
assert_equal true, fzf.multi
|
||||||
assert_equal false, fzf.color
|
assert_equal false, fzf.color
|
||||||
@ -88,10 +110,14 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
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 [3], fzf.nth
|
||||||
|
assert_equal true, fzf.select1
|
||||||
|
assert_equal true, fzf.exit0
|
||||||
|
|
||||||
# Left-to-right
|
# Left-to-right
|
||||||
fzf = FZF.new %w[-s 2000 +c -m +i -qhello -x -fgoodbye +2 -n3 -n4,5
|
fzf = FZF.new %w[-s 2000 +c -m +i -qhello -x -fgoodbye +2 -n3 -n4,5
|
||||||
-s 3000 -c +m -i -q world +x -fworld -2 --black --no-black]
|
-s 3000 -c +m -i -q world +x -fworld -2 --black --no-black
|
||||||
|
-1 -0 +1 +0
|
||||||
|
]
|
||||||
assert_equal 3000, fzf.sort
|
assert_equal 3000, fzf.sort
|
||||||
assert_equal false, fzf.multi
|
assert_equal false, fzf.multi
|
||||||
assert_equal true, fzf.color
|
assert_equal true, fzf.color
|
||||||
@ -99,13 +125,11 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
assert_equal false, fzf.black
|
assert_equal false, fzf.black
|
||||||
assert_equal 1, fzf.rxflag
|
assert_equal 1, fzf.rxflag
|
||||||
assert_equal 'world', fzf.query.get
|
assert_equal 'world', fzf.query.get
|
||||||
|
assert_equal false, fzf.select1
|
||||||
|
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 [4, 5], fzf.nth
|
||||||
|
|
||||||
fzf = FZF.new %w[--query hello +s -s 2000 --query=world]
|
|
||||||
assert_equal 2000, fzf.sort
|
|
||||||
assert_equal 'world', fzf.query.get
|
|
||||||
rescue SystemExit => e
|
rescue SystemExit => e
|
||||||
assert false, "Exited"
|
assert false, "Exited"
|
||||||
end
|
end
|
||||||
@ -538,5 +562,60 @@ class TestFZF < MiniTest::Unit::TestCase
|
|||||||
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [2], regex
|
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE, [2], 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 stream_for str
|
||||||
|
StringIO.new(str).tap do |sio|
|
||||||
|
sio.instance_eval do
|
||||||
|
alias org_gets gets
|
||||||
|
|
||||||
|
def gets
|
||||||
|
org_gets.tap { |e| sleep 0.5 unless e.nil? }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_select_1
|
||||||
|
stream = stream_for "Hello\nWorld"
|
||||||
|
output = StringIO.new
|
||||||
|
|
||||||
|
begin
|
||||||
|
$stdout = output
|
||||||
|
FZF.new(%w[--query=ol --select-1], stream).start
|
||||||
|
rescue SystemExit => e
|
||||||
|
assert_equal 0, e.status
|
||||||
|
assert_equal 'World', output.string.chomp
|
||||||
|
ensure
|
||||||
|
$stdout = STDOUT
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_select_1_ambiguity
|
||||||
|
stream = stream_for "Hello\nWorld"
|
||||||
|
begin
|
||||||
|
Timeout::timeout(3) do
|
||||||
|
FZF.new(%w[--query=o --select-1], stream).start
|
||||||
|
end
|
||||||
|
flunk 'Should not reach here'
|
||||||
|
rescue Exception => e
|
||||||
|
Curses.close_screen
|
||||||
|
assert_instance_of Timeout::Error, e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_exit_0
|
||||||
|
stream = stream_for "Hello\nWorld"
|
||||||
|
output = StringIO.new
|
||||||
|
|
||||||
|
begin
|
||||||
|
$stdout = output
|
||||||
|
FZF.new(%w[--query=zz --exit-0], stream).start
|
||||||
|
rescue SystemExit => e
|
||||||
|
assert_equal 1, e.status
|
||||||
|
assert_equal '', output.string
|
||||||
|
ensure
|
||||||
|
$stdout = STDOUT
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user