Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
F
fzf
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to JiHu GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
KMSCAKKSCFKA AKFACAMADCAS
fzf
Commits
52b74abb
Commit
52b74abb
authored
11 years ago
by
Junegunn Choi
Browse files
Options
Downloads
Plain Diff
Merge pull request #32 from junegunn/nth
Add --nth and --delimiter option
parents
cf8dbf80
ec4b8a59
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
README.md
+10
-0
10 additions, 0 deletions
README.md
fzf
+75
-9
75 additions, 9 deletions
fzf
test/test_fzf.rb
+59
-5
59 additions, 5 deletions
test/test_fzf.rb
with
144 additions
and
14 deletions
README.md
+
10
−
0
View file @
52b74abb
...
...
@@ -53,6 +53,8 @@ usage: fzf [options]
-e, --extended-exact Extended-search mode (exact match)
-q, --query=STR Initial query
-f, --filter=STR Filter mode. Do not start interactive finder.
-n, --nth=[-]N Match only in the N-th token of the item
-d, --delimiter=STR Field delimiter regex for --nth (default: AWK-style)
-s, --sort=MAX Maximum number of matched items to sort (default: 1000)
+s, --no-sort Do not sort the result. Keep the sequence unchanged.
-i Case-insensitive match (default: smart-case match)
...
...
@@ -177,6 +179,14 @@ fco() {
git checkout
$(
echo
"
$commit
"
|
sed
"s/ .*//"
)
}
# ftags - search ctags
ftags
()
{
local
line
[
-e
tags
]
&&
line
=
$(
grep
-v
"^!"
tags |
cut
-f1-3
|
cut
-c1-80
| fzf
--nth
=
1
)
&&
$EDITOR
$(
cut
-f2
<<<
"
$line
"
)
}
# fq1 [QUERY]
# - Immediately select the file when there's only one match.
# If not, start the fuzzy finder as usual.
...
...
This diff is collapsed.
Click to expand it.
fzf
+
75
−
9
View file @
52b74abb
...
...
@@ -7,7 +7,7 @@
# / __/ / /_/ __/
# /_/ /___/_/ Fuzzy finder for your shell
#
# Version: 0.8.2 (March
15
, 2014)
# Version: 0.8.2 (March
30
, 2014)
#
# Author: Junegunn Choi
# URL: https://github.com/junegunn/fzf
...
...
@@ -50,7 +50,8 @@ end
class
FZF
C
=
Curses
attr_reader
:rxflag
,
:sort
,
:color
,
:black
,
:ansi256
,
:mouse
,
:multi
,
:query
,
:filter
,
:extended
attr_reader
:rxflag
,
:sort
,
:nth
,
:color
,
:black
,
:ansi256
,
:mouse
,
:multi
,
:query
,
:filter
,
:extended
class
AtomicVar
def
initialize
value
...
...
@@ -83,6 +84,8 @@ class FZF
@mouse
=
true
@extended
=
nil
@filter
=
nil
@nth
=
nil
@delim
=
nil
argv
=
if
opts
=
ENV
[
'FZF_DEFAULT_OPTS'
]
...
...
@@ -120,6 +123,17 @@ class FZF
@filter
=
query
when
/^-f(.*)$/
,
/^--filter=(.*)$/
@filter
=
$1
when
'-n'
,
'--nth'
usage
1
,
'field number required'
unless
nth
=
argv
.
shift
usage
1
,
'invalid field number'
if
nth
.
to_i
==
0
@nth
=
nth
.
to_i
when
/^-n(-?[1-9][0-9]*)$/
,
/^--nth=(-?[1-9][0-9]*)$/
@nth
=
$1
.
to_i
when
'-d'
,
'--delimiter'
usage
1
,
'delimiter required'
unless
delim
=
argv
.
shift
@delim
=
FZF
.
build_delim_regex
delim
when
/^-d(.+)$/
,
/^--delimiter=(.+)$/
@delim
=
FZF
.
build_delim_regex
$1
when
'-s'
,
'--sort'
usage
1
,
'sort size required'
unless
sort
=
argv
.
shift
usage
1
,
'invalid sort size'
unless
sort
=~
/^[0-9]+$/
...
...
@@ -155,6 +169,11 @@ class FZF
end
end
def
FZF
.
build_delim_regex
delim
Regexp
.
compile
(
delim
)
rescue
(
delim
=
Regexp
.
escape
(
delim
))
Regexp
.
compile
"(?:.*?
#{
delim
}
)|(?:.+?$)"
end
def
start
if
@filter
start_reader
(
false
).
join
...
...
@@ -181,9 +200,9 @@ class FZF
def
get_matcher
if
@extended
ExtendedFuzzyMatcher
.
new
@rxflag
,
@extended
ExtendedFuzzyMatcher
.
new
@rxflag
,
@extended
,
@nth
,
@delim
else
FuzzyMatcher
.
new
@rxflag
FuzzyMatcher
.
new
@rxflag
,
@nth
,
@delim
end
end
...
...
@@ -208,6 +227,8 @@ class FZF
-e, --extended-exact Extended-search mode (exact match)
-q, --query=STR Initial query
-f, --filter=STR Filter mode. Do not start interactive finder.
-n, --nth=[-]N Match only in the N-th token of the item
-d, --delimiter=STR Field delimiter regex for --nth (default: AWK-style)
-s, --sort=MAX Maximum number of matched items to sort (default: 1000)
+s, --no-sort Do not sort the result. Keep the sequence unchanged.
-i Case-insensitive match (default: smart-case match)
...
...
@@ -1026,10 +1047,55 @@ class FZF
end
end
class
Matcher
class
MatchData
def
initialize
n
@n
=
n
end
def
offset
_
@n
end
end
def
initialize
nth
,
delim
@nth
=
nth
&&
(
nth
>
0
?
nth
-
1
:
nth
)
@delim
=
delim
@tokens_cache
=
{}
end
def
tokenize
str
@tokens_cache
[
str
]
||=
unless
@delim
# AWK default
prefix_length
=
str
[
/^\s+/
].
length
rescue
0
[
prefix_length
,
(
str
.
strip
.
scan
(
/\S+\s*/
)
rescue
[])]
else
prefix_length
=
0
[
prefix_length
,
(
str
.
scan
(
@delim
)
rescue
[])]
end
end
def
do_match
str
,
pat
if
@nth
prefix_length
,
tokens
=
tokenize
str
if
(
token
=
tokens
[
@nth
])
&&
(
md
=
token
.
match
(
pat
)
rescue
nil
)
prefix_length
+=
(
tokens
[
0
...
@nth
]
||
[]).
join
.
length
offset
=
md
.
offset
(
0
).
map
{
|
o
|
o
+
prefix_length
}
MatchData
.
new
offset
end
else
str
.
match
(
pat
)
rescue
nil
end
end
end
class
FuzzyMatcher
<
Matcher
attr_reader
:caches
,
:rxflag
def
initialize
rxflag
def
initialize
rxflag
,
nth
=
nil
,
delim
=
nil
super
nth
,
delim
@caches
=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
{}
}
@regexp
=
{}
@rxflag
=
rxflag
...
...
@@ -1073,15 +1139,15 @@ class FZF
cache
[
q
]
||=
(
partial_cache
?
partial_cache
.
map
{
|
e
|
e
.
first
}
:
list
).
map
{
|
line
|
# Ignore errors: e.g. invalid byte sequence in UTF-8
md
=
line
.
match
(
regexp
)
rescue
nil
md
=
do_
match
(
line
,
regexp
)
md
&&
[
line
,
[
md
.
offset
(
0
)]]
}.
compact
end
end
class
ExtendedFuzzyMatcher
<
FuzzyMatcher
def
initialize
rxflag
,
mode
=
:fuzzy
super
rxflag
def
initialize
rxflag
,
mode
=
:fuzzy
,
nth
=
nil
,
delim
=
nil
super
rxflag
,
nth
,
delim
@regexps
=
{}
@mode
=
mode
end
...
...
@@ -1143,7 +1209,7 @@ class FZF
offsets
=
[]
regexps
.
all?
{
|
pair
|
regexp
,
invert
=
pair
md
=
line
.
match
(
regexp
)
rescue
nil
md
=
do_
match
(
line
,
regexp
)
if
md
&&
!
invert
offsets
<<
md
.
offset
(
0
)
elsif
!
md
&&
invert
...
...
This diff is collapsed.
Click to expand it.
test/test_fzf.rb
+
59
−
5
View file @
52b74abb
...
...
@@ -27,8 +27,10 @@ class TestFZF < MiniTest::Unit::TestCase
ENV
[
'FZF_DEFAULT_SORT'
]
=
'20000'
fzf
=
FZF
.
new
[]
assert_equal
20000
,
fzf
.
sort
assert_equal
nil
,
fzf
.
nth
ENV
[
'FZF_DEFAULT_OPTS'
]
=
'-x -m -s 10000 -q " hello world " +c +2 --no-mouse -f "goodbye world" --black'
ENV
[
'FZF_DEFAULT_OPTS'
]
=
'-x -m -s 10000 -q " hello world " +c +2 --no-mouse -f "goodbye world" --black --nth=3'
fzf
=
FZF
.
new
[]
assert_equal
10000
,
fzf
.
sort
assert_equal
' hello world '
,
...
...
@@ -41,12 +43,13 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal
false
,
fzf
.
ansi256
assert_equal
true
,
fzf
.
black
assert_equal
false
,
fzf
.
mouse
assert_equal
3
,
fzf
.
nth
end
def
test_option_parser
# Long opts
fzf
=
FZF
.
new
%w[--sort=2000 --no-color --multi +i --query hello
--filter=howdy --extended-exact --no-mouse --no-256]
--filter=howdy --extended-exact --no-mouse --no-256
--nth=1
]
assert_equal
2000
,
fzf
.
sort
assert_equal
true
,
fzf
.
multi
assert_equal
false
,
fzf
.
color
...
...
@@ -57,9 +60,10 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal
'hello'
,
fzf
.
query
.
get
assert_equal
'howdy'
,
fzf
.
filter
assert_equal
:exact
,
fzf
.
extended
assert_equal
1
,
fzf
.
nth
fzf
=
FZF
.
new
%w[--sort=2000 --no-color --multi +i --query hello
--filter a --filter b --no-256 --black
--filter a --filter b --no-256 --black
--nth 2
--no-sort -i --color --no-multi --256]
assert_equal
nil
,
fzf
.
sort
assert_equal
false
,
fzf
.
multi
...
...
@@ -71,9 +75,10 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal
'b'
,
fzf
.
filter
assert_equal
'hello'
,
fzf
.
query
.
get
assert_equal
nil
,
fzf
.
extended
assert_equal
2
,
fzf
.
nth
# Short opts
fzf
=
FZF
.
new
%w[-s 2000 +c -m +i -qhello -x -fhowdy +2]
fzf
=
FZF
.
new
%w[-s 2000 +c -m +i -qhello -x -fhowdy +2
-n3
]
assert_equal
2000
,
fzf
.
sort
assert_equal
true
,
fzf
.
multi
assert_equal
false
,
fzf
.
color
...
...
@@ -82,9 +87,10 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal
'hello'
,
fzf
.
query
.
get
assert_equal
'howdy'
,
fzf
.
filter
assert_equal
:fuzzy
,
fzf
.
extended
assert_equal
3
,
fzf
.
nth
# Left-to-right
fzf
=
FZF
.
new
%w[-s 2000 +c -m +i -qhello -x -fgoodbye +2
fzf
=
FZF
.
new
%w[-s 2000 +c -m +i -qhello -x -fgoodbye +2
-n3 -n4
-s 3000 -c +m -i -q world +x -fworld -2 --black --no-black]
assert_equal
3000
,
fzf
.
sort
assert_equal
false
,
fzf
.
multi
...
...
@@ -95,6 +101,7 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal
'world'
,
fzf
.
query
.
get
assert_equal
'world'
,
fzf
.
filter
assert_equal
nil
,
fzf
.
extended
assert_equal
4
,
fzf
.
nth
fzf
=
FZF
.
new
%w[--query hello +s -s 2000 --query=world]
assert_equal
2000
,
fzf
.
sort
...
...
@@ -109,6 +116,12 @@ class TestFZF < MiniTest::Unit::TestCase
fzf
=
FZF
.
new
argv
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
# FIXME Only on 1.9 or above
...
...
@@ -476,5 +489,46 @@ class TestFZF < MiniTest::Unit::TestCase
sleep
interval
assert_equal
false
,
me
.
double?
(
20
)
end
def
test_nth_match
list
=
[
' first second third'
,
'fourth fifth sixth'
,
]
matcher
=
FZF
::
FuzzyMatcher
.
new
Regexp
::
IGNORECASE
assert_equal
list
,
matcher
.
match
(
list
,
'f'
,
''
,
''
).
map
(
&
:first
)
assert_equal
[
[
list
[
0
],
[[
2
,
5
]]],
[
list
[
1
],
[[
9
,
17
]]]],
matcher
.
match
(
list
,
'is'
,
''
,
''
)
matcher
=
FZF
::
FuzzyMatcher
.
new
Regexp
::
IGNORECASE
,
2
assert_equal
[[
list
[
1
],
[[
8
,
9
]]]],
matcher
.
match
(
list
,
'f'
,
''
,
''
)
assert_equal
[[
list
[
0
],
[[
8
,
9
]]]],
matcher
.
match
(
list
,
's'
,
''
,
''
)
matcher
=
FZF
::
FuzzyMatcher
.
new
Regexp
::
IGNORECASE
,
3
assert_equal
[[
list
[
0
],
[[
19
,
20
]]]],
matcher
.
match
(
list
,
'r'
,
''
,
''
)
regex
=
FZF
.
build_delim_regex
"
\t
"
matcher
=
FZF
::
FuzzyMatcher
.
new
Regexp
::
IGNORECASE
,
1
,
regex
assert_equal
[[
list
[
0
],
[[
3
,
10
]]]],
matcher
.
match
(
list
,
're'
,
''
,
''
)
matcher
=
FZF
::
FuzzyMatcher
.
new
Regexp
::
IGNORECASE
,
2
,
regex
assert_equal
[],
matcher
.
match
(
list
,
'r'
,
''
,
''
)
assert_equal
[[
list
[
1
],
[[
9
,
17
]]]],
matcher
.
match
(
list
,
'is'
,
''
,
''
)
# Negative indexing
matcher
=
FZF
::
FuzzyMatcher
.
new
Regexp
::
IGNORECASE
,
-
1
,
regex
assert_equal
[[
list
[
0
],
[[
3
,
6
]]]],
matcher
.
match
(
list
,
'rt'
,
''
,
''
)
assert_equal
[[
list
[
0
],
[[
2
,
5
]]],
[
list
[
1
],
[[
9
,
17
]]]],
matcher
.
match
(
list
,
'is'
,
''
,
''
)
# Regex delimiter
regex
=
FZF
.
build_delim_regex
"[
\t
]+"
matcher
=
FZF
::
FuzzyMatcher
.
new
Regexp
::
IGNORECASE
,
1
,
regex
assert_equal
[
list
[
1
]],
matcher
.
match
(
list
,
'f'
,
''
,
''
).
map
(
&
:first
)
matcher
=
FZF
::
FuzzyMatcher
.
new
Regexp
::
IGNORECASE
,
2
,
regex
assert_equal
[[
list
[
0
],
[[
1
,
2
]]],
[
list
[
1
],
[[
8
,
9
]]]],
matcher
.
match
(
list
,
'f'
,
''
,
''
)
end
end
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment