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
dcb4694e
Commit
dcb4694e
authored
11 years ago
by
Junegunn Choi
Browse files
Options
Downloads
Patches
Plain Diff
Reimplement mouse input without using Curses.getch
parent
2fb8ae01
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
README.md
+4
-0
4 additions, 0 deletions
README.md
fzf
+98
-8
98 additions, 8 deletions
fzf
test/test_fzf.rb
+22
-3
22 additions, 3 deletions
test/test_fzf.rb
with
124 additions
and
11 deletions
README.md
+
4
−
0
View file @
dcb4694e
...
...
@@ -58,6 +58,7 @@ usage: fzf [options]
-i Case-insensitive match (default: smart-case match)
+i Case-sensitive match
+c, --no-color Disable colors
--no-mouse Disable mouse
Environment variables
FZF_DEFAULT_COMMAND Default command to use when input is tty
...
...
@@ -101,6 +102,9 @@ The following readline key bindings should also work as expected.
If you enable multi-select mode with
`-m`
option, you can select multiple items
with TAB or Shift-TAB key.
You can also use mouse. Double-click on an item to select it or shift-click to
select multiple items. Use mouse wheel to move the cursor up and down.
### Extended-search mode
With
`-x`
or
`--extended`
option, fzf will start in "extended-search mode".
...
...
This diff is collapsed.
Click to expand it.
fzf
+
98
−
8
View file @
dcb4694e
...
...
@@ -50,7 +50,7 @@ end
class
FZF
C
=
Curses
attr_reader
:rxflag
,
:sort
,
:color
,
:multi
,
:query
,
:filter
,
:extended
attr_reader
:rxflag
,
:sort
,
:color
,
:mouse
,
:multi
,
:query
,
:filter
,
:extended
class
AtomicVar
def
initialize
value
...
...
@@ -78,6 +78,7 @@ class FZF
@sort
=
ENV
.
fetch
(
'FZF_DEFAULT_SORT'
,
1000
).
to_i
@color
=
true
@multi
=
false
@mouse
=
true
@extended
=
nil
@filter
=
nil
...
...
@@ -100,6 +101,7 @@ class FZF
when
'+i'
then
@rxflag
=
0
when
'-c'
,
'--color'
then
@color
=
true
when
'+c'
,
'--no-color'
then
@color
=
false
when
'--no-mouse'
then
@mouse
=
false
when
'+s'
,
'--no-sort'
then
@sort
=
nil
when
'-q'
,
'--query'
usage
1
,
'query string required'
unless
query
=
argv
.
shift
...
...
@@ -204,6 +206,7 @@ class FZF
-i Case-insensitive match (default: smart-case match)
+i Case-sensitive match
+c, --no-color Disable colors
--no-mouse Disable mouse
Environment variables
FZF_DEFAULT_COMMAND Default command to use when input is tty
...
...
@@ -506,6 +509,7 @@ class FZF
def
init_screen
C
.
init_screen
C
.
mousemask
C
::
ALL_MOUSE_EVENTS
if
@mouse
C
.
start_color
dbg
=
if
C
.
respond_to?
(
:use_default_colors
)
...
...
@@ -744,6 +748,29 @@ class FZF
end
end
def
read_nb
chars
=
1
,
default
=
nil
@tty
.
read_nonblock
(
chars
).
ord
rescue
default
end
def
get_mouse
case
ord
=
read_nb
when
32
,
36
,
# mouse-down / shift-mouse-down
35
,
39
# mouse-up / shift-mouse-up
x
=
read_nb
-
33
y
=
read_nb
-
33
{
:event
=>
(
ord
%
2
==
0
?
:click
:
:release
),
:x
=>
x
,
:y
=>
y
,
:shift
=>
ord
>=
36
}
when
96
,
100
,
# scroll-up / shift-scroll-up
97
,
101
# scroll-down / shift-scroll-down
read_nb
(
2
)
{
:event
=>
:scroll
,
:diff
=>
(
ord
%
2
==
0
?
-
1
:
1
),
:shift
=>
ord
>=
100
}
else
# e.g. 40, 43, 104, 105
read_nb
(
2
)
nil
end
end
def
get_input
actions
@tty
||=
IO
.
open
(
IO
.
sysopen
(
'/dev/tty'
),
'r'
)
...
...
@@ -776,15 +803,16 @@ class FZF
end
ord
=
case
ord
=
(
@tty
.
read_nonblock
(
1
).
ord
rescue
:esc
)
case
ord
=
read_nb
(
1
,
:esc
)
when
91
case
(
@tty
.
read_nonblock
(
1
).
ord
rescue
nil
)
case
read_nb
(
1
,
nil
)
when
68
then
ctrl
(
:b
)
when
67
then
ctrl
(
:f
)
when
66
then
ctrl
(
:j
)
when
65
then
ctrl
(
:k
)
when
90
then
:stab
else
next
when
77
get_mouse
end
when
'b'
,
98
then
:alt_b
when
'f'
,
102
then
:alt_f
...
...
@@ -792,6 +820,8 @@ class FZF
else
next
end
if
ord
==
27
return
ord
if
ord
.
nil?
||
ord
.
is_a?
(
Hash
)
if
actions
.
has_key?
(
ord
)
if
str
.
empty?
return
ord
...
...
@@ -808,6 +838,32 @@ class FZF
end
end
class
MouseEvent
DOUBLE_CLICK_INTERVAL
=
0.5
attr_reader
:v
def
initialize
v
=
nil
@c
=
0
@v
=
v
@t
=
Time
.
at
0
end
def
v
=
v
@c
=
(
@v
==
v
&&
within?
)
?
@c
+
1
:
0
@v
=
v
@t
=
Time
.
now
end
def
double?
v
@c
==
1
&&
@v
==
v
&&
within?
end
def
within?
(
Time
.
now
-
@t
)
<
DOUBLE_CLICK_INTERVAL
end
end
def
start_loop
got
=
nil
begin
...
...
@@ -841,7 +897,11 @@ class FZF
else
@selects
[
sel
]
=
1
end
vselect
{
|
v
|
v
+
(
o
==
:stab
?
1
:
-
1
)
}
vselect
{
|
v
|
v
+
case
o
when
:stab
then
1
when
:sclick
then
0
else
-
1
end
}
end
},
ctrl
(
:b
)
=>
proc
{
cursor
=
[
0
,
cursor
-
1
].
max
;
nil
},
...
...
@@ -860,14 +920,44 @@ class FZF
actions
[
ctrl
(
:q
)]
=
actions
[
ctrl
(
:g
)]
=
actions
[
ctrl
(
:c
)]
=
actions
[
:esc
]
emit
(
:key
)
{
[
@query
.
get
,
cursor
]
}
unless
@query
.
empty?
mouse
=
MouseEvent
.
new
while
true
@cursor_x
.
set
cursor
render
{
print_input
}
if
key
=
get_input
(
actions
)
upd
=
actions
.
fetch
(
key
,
proc
{
|
str
|
input
.
insert
cursor
,
str
cursor
+=
str
.
length
upd
=
actions
.
fetch
(
key
,
proc
{
|
val
|
case
val
when
String
input
.
insert
cursor
,
val
cursor
+=
val
.
length
when
Hash
event
=
val
[
:event
]
case
event
when
:click
,
:release
x
,
y
,
shift
=
val
.
values_at
:x
,
:y
,
:shift
if
y
==
cursor_y
cursor
=
[
0
,
[
input
.
length
,
x
-
2
].
min
].
max
elsif
x
>
1
&&
y
<=
max_items
tv
=
max_items
-
y
-
1
case
event
when
:click
vselect
{
|
_
|
tv
}
actions
[
ctrl
(
:i
)].
call
(
:sclick
)
if
shift
mouse
.
v
=
tv
when
:release
if
!
shift
&&
mouse
.
double?
(
tv
)
actions
[
ctrl
(
:m
)].
call
end
end
end
when
:scroll
diff
,
shift
=
val
.
values_at
:diff
,
:shift
actions
[
ctrl
(
:i
)].
call
(
:sclick
)
if
shift
actions
[
ctrl
(
diff
>
0
?
:j
:
:k
)].
call
end
end
}).
call
(
key
)
# Dispatch key event
...
...
This diff is collapsed.
Click to expand it.
test/test_fzf.rb
+
22
−
3
View file @
dcb4694e
...
...
@@ -7,7 +7,6 @@ ENV['FZF_EXECUTABLE'] = '0'
load
'fzf'
class
TestFZF
<
MiniTest
::
Unit
::
TestCase
def
setup
ENV
.
delete
'FZF_DEFAULT_SORT'
ENV
.
delete
'FZF_DEFAULT_OPTS'
...
...
@@ -20,6 +19,7 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal
false
,
fzf
.
multi
assert_equal
true
,
fzf
.
color
assert_equal
nil
,
fzf
.
rxflag
assert_equal
true
,
fzf
.
mouse
end
def
test_environment_variables
...
...
@@ -28,7 +28,7 @@ class TestFZF < MiniTest::Unit::TestCase
fzf
=
FZF
.
new
[]
assert_equal
20000
,
fzf
.
sort
ENV
[
'FZF_DEFAULT_OPTS'
]
=
'-x -m -s 10000 -q " hello world " +c -f "goodbye world"'
ENV
[
'FZF_DEFAULT_OPTS'
]
=
'-x -m -s 10000 -q " hello world " +c
--no-mouse
-f "goodbye world"'
fzf
=
FZF
.
new
[]
assert_equal
10000
,
fzf
.
sort
assert_equal
' hello world '
,
...
...
@@ -38,15 +38,17 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal
:fuzzy
,
fzf
.
extended
assert_equal
true
,
fzf
.
multi
assert_equal
false
,
fzf
.
color
assert_equal
false
,
fzf
.
mouse
end
def
test_option_parser
# Long opts
fzf
=
FZF
.
new
%w[--sort=2000 --no-color --multi +i --query hello
--filter=howdy --extended-exact]
--filter=howdy --extended-exact
--no-mouse
]
assert_equal
2000
,
fzf
.
sort
assert_equal
true
,
fzf
.
multi
assert_equal
false
,
fzf
.
color
assert_equal
false
,
fzf
.
mouse
assert_equal
0
,
fzf
.
rxflag
assert_equal
'hello'
,
fzf
.
query
.
get
assert_equal
'howdy'
,
fzf
.
filter
...
...
@@ -58,6 +60,7 @@ class TestFZF < MiniTest::Unit::TestCase
assert_equal
nil
,
fzf
.
sort
assert_equal
false
,
fzf
.
multi
assert_equal
true
,
fzf
.
color
assert_equal
true
,
fzf
.
mouse
assert_equal
1
,
fzf
.
rxflag
assert_equal
'b'
,
fzf
.
filter
assert_equal
'hello'
,
fzf
.
query
.
get
...
...
@@ -448,5 +451,21 @@ class TestFZF < MiniTest::Unit::TestCase
tokens
=
fzf
.
format
line
,
80
,
offsets
assert_equal
[],
tokens
end
def
test_mouse_event
interval
=
FZF
::
MouseEvent
::
DOUBLE_CLICK_INTERVAL
me
=
FZF
::
MouseEvent
.
new
nil
me
.
v
=
10
assert_equal
false
,
me
.
double?
(
10
)
assert_equal
false
,
me
.
double?
(
20
)
me
.
v
=
20
assert_equal
false
,
me
.
double?
(
10
)
assert_equal
false
,
me
.
double?
(
20
)
me
.
v
=
20
assert_equal
false
,
me
.
double?
(
10
)
assert_equal
true
,
me
.
double?
(
20
)
sleep
interval
assert_equal
false
,
me
.
double?
(
20
)
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