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
a89d8995
Commit
a89d8995
authored
9 years ago
by
Junegunn Choi
Browse files
Options
Downloads
Patches
Plain Diff
Add execute-multi action
Close #413
parent
dbc854d5
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
man/man1/fzf.1
+7
-0
7 additions, 0 deletions
man/man1/fzf.1
src/options.go
+24
-8
24 additions, 8 deletions
src/options.go
src/terminal.go
+28
-9
28 additions, 9 deletions
src/terminal.go
test/test_go.rb
+18
-0
18 additions, 0 deletions
test/test_go.rb
with
77 additions
and
17 deletions
man/man1/fzf.1
+
7
−
0
View file @
a89d8995
...
...
@@ -223,6 +223,7 @@ e.g. \fBfzf --bind=ctrl-j:accept,ctrl-k:kill-line\fR
\fBdown\fR \fIctrl-j ctrl-n down\fR
\fBend-of-line\fR \fIctrl-e end\fR
\fBexecute(...)\fR (see below for the details)
\fBexecute-multi(...)\fR (see below for the details)
\fBforward-char\fR \fIctrl-f right\fR
\fBforward-word\fR \fIalt-f shift-right\fR
\fBignore\fR
...
...
@@ -276,6 +277,12 @@ This is the special form that frees you from parse errors as it does not expect
the closing character. The catch is that it should be the last one in the
comma-separated list.
.RE
\fBexecute-multi(...)\fR is an alternative action that executes the command
with the selected entries when multi-select is enabled (\fB--multi\fR). With
this action, \fB{}\fR is replaced with the double-quoted strings of the
selected entries separated by spaces.
.RE
.TP
.BI "--history=" "HISTORY_FILE"
...
...
This diff is collapsed.
Click to expand it.
src/options.go
+
24
−
8
View file @
a89d8995
...
...
@@ -466,10 +466,13 @@ func parseKeymap(keymap map[int]actionType, execmap map[int]string, toggleSort b
// Backreferences are not supported.
// "~!@#$%^&*;/|".each_char.map { |c| Regexp.escape(c) }.map { |c| "#{c}[^#{c}]*#{c}" }.join('|')
executeRegexp
=
regexp
.
MustCompile
(
"(?s):execute:.*|:execute(
\\
([^)]*
\\
)|
\\
[[^
\\
]]*
\\
]|~[^~]*~|![^!]*!|@[^@]*@|
\\
#[^
\\
#]*
\\
#|
\\
$[^
\\
$]*
\\
$|%[^%]*%|
\\
^[^
\\
^]*
\\
^|&[^&]*&|
\\
*[^
\\
*]*
\\
*|;[^;]*;|/[^/]*/|
\\
|[^
\\
|]*
\\
|)"
)
"(?s):execute
(-multi)?
:.*|:execute(
-multi)?(
\\
([^)]*
\\
)|
\\
[[^
\\
]]*
\\
]|~[^~]*~|![^!]*!|@[^@]*@|
\\
#[^
\\
#]*
\\
#|
\\
$[^
\\
$]*
\\
$|%[^%]*%|
\\
^[^
\\
^]*
\\
^|&[^&]*&|
\\
*[^
\\
*]*
\\
*|;[^;]*;|/[^/]*/|
\\
|[^
\\
|]*
\\
|)"
)
}
masked
:=
executeRegexp
.
ReplaceAllStringFunc
(
str
,
func
(
src
string
)
string
{
return
":execute("
+
strings
.
Repeat
(
" "
,
len
(
src
)
-
10
)
+
")"
if
strings
.
HasPrefix
(
src
,
":execute-multi"
)
{
return
":execute-multi("
+
strings
.
Repeat
(
" "
,
len
(
src
)
-
len
(
":execute-multi()"
))
+
")"
}
return
":execute("
+
strings
.
Repeat
(
" "
,
len
(
src
)
-
len
(
":execute()"
))
+
")"
})
masked
=
strings
.
Replace
(
masked
,
"::"
,
string
([]
rune
{
escapedColon
,
':'
}),
-
1
)
masked
=
strings
.
Replace
(
masked
,
",:"
,
string
([]
rune
{
escapedComma
,
':'
}),
-
1
)
...
...
@@ -565,11 +568,18 @@ func parseKeymap(keymap map[int]actionType, execmap map[int]string, toggleSort b
toggleSort
=
true
default
:
if
isExecuteAction
(
actLower
)
{
keymap
[
key
]
=
actExecute
if
act
[
7
]
==
':'
{
execmap
[
key
]
=
act
[
8
:
]
var
offset
int
if
strings
.
HasPrefix
(
actLower
,
"execute-multi"
)
{
keymap
[
key
]
=
actExecuteMulti
offset
=
len
(
"execute-multi"
)
}
else
{
keymap
[
key
]
=
actExecute
offset
=
len
(
"execute"
)
}
if
act
[
offset
]
==
':'
{
execmap
[
key
]
=
act
[
offset
+
1
:
]
}
else
{
execmap
[
key
]
=
act
[
8
:
len
(
act
)
-
1
]
execmap
[
key
]
=
act
[
offset
+
1
:
len
(
act
)
-
1
]
}
}
else
{
errorExit
(
"unknown action: "
+
act
)
...
...
@@ -580,10 +590,16 @@ func parseKeymap(keymap map[int]actionType, execmap map[int]string, toggleSort b
}
func
isExecuteAction
(
str
string
)
bool
{
if
!
strings
.
HasPrefix
(
str
,
"execute"
)
||
len
(
str
)
<
9
{
if
!
strings
.
HasPrefix
(
str
,
"execute"
)
||
len
(
str
)
<
len
(
"execute()"
)
{
return
false
}
b
:=
str
[
7
]
b
:=
str
[
len
(
"execute"
)]
if
strings
.
HasPrefix
(
str
,
"execute-multi"
)
{
if
len
(
str
)
<
len
(
"execute-multi()"
)
{
return
false
}
b
=
str
[
len
(
"execute-multi"
)]
}
e
:=
str
[
len
(
str
)
-
1
]
if
b
==
':'
||
b
==
'('
&&
e
==
')'
||
b
==
'['
&&
e
==
']'
||
b
==
e
&&
strings
.
ContainsAny
(
string
(
b
),
"~!@#$%^&*;/|"
)
{
...
...
This diff is collapsed.
Click to expand it.
src/terminal.go
+
28
−
9
View file @
a89d8995
...
...
@@ -132,6 +132,7 @@ const (
actPreviousHistory
actNextHistory
actExecute
actExecuteMulti
)
func
defaultKeymap
()
map
[
int
]
actionType
{
...
...
@@ -305,18 +306,22 @@ func (t *Terminal) output() bool {
found
=
true
}
}
else
{
sels
:=
make
([]
selectedItem
,
0
,
len
(
t
.
selected
))
for
_
,
sel
:=
range
t
.
selected
{
sels
=
append
(
sels
,
sel
)
}
sort
.
Sort
(
byTimeOrder
(
sels
))
for
_
,
sel
:=
range
sels
{
for
_
,
sel
:=
range
t
.
sortSelected
()
{
fmt
.
Println
(
*
sel
.
text
)
}
}
return
found
}
func
(
t
*
Terminal
)
sortSelected
()
[]
selectedItem
{
sels
:=
make
([]
selectedItem
,
0
,
len
(
t
.
selected
))
for
_
,
sel
:=
range
t
.
selected
{
sels
=
append
(
sels
,
sel
)
}
sort
.
Sort
(
byTimeOrder
(
sels
))
return
sels
}
func
runeWidth
(
r
rune
,
prefixWidth
int
)
int
{
if
r
==
'\t'
{
return
8
-
prefixWidth
%
8
...
...
@@ -698,8 +703,12 @@ func keyMatch(key int, event C.Event) bool {
return
event
.
Type
==
key
||
event
.
Type
==
C
.
Rune
&&
int
(
event
.
Char
)
==
key
-
C
.
AltZ
}
func
executeCommand
(
template
string
,
current
string
)
{
command
:=
strings
.
Replace
(
template
,
"{}"
,
fmt
.
Sprintf
(
"%q"
,
current
),
-
1
)
func
quoteEntry
(
entry
string
)
string
{
return
fmt
.
Sprintf
(
"%q"
,
entry
)
}
func
executeCommand
(
template
string
,
replacement
string
)
{
command
:=
strings
.
Replace
(
template
,
"{}"
,
replacement
,
-
1
)
cmd
:=
exec
.
Command
(
"sh"
,
"-c"
,
command
)
cmd
.
Stdin
=
os
.
Stdin
cmd
.
Stdout
=
os
.
Stdout
...
...
@@ -858,7 +867,17 @@ func (t *Terminal) Loop() {
case
actExecute
:
if
t
.
cy
>=
0
&&
t
.
cy
<
t
.
merger
.
Length
()
{
item
:=
t
.
merger
.
Get
(
t
.
cy
)
executeCommand
(
t
.
execmap
[
mapkey
],
item
.
AsString
(
t
.
ansi
))
executeCommand
(
t
.
execmap
[
mapkey
],
quoteEntry
(
item
.
AsString
(
t
.
ansi
)))
}
case
actExecuteMulti
:
if
len
(
t
.
selected
)
>
0
{
sels
:=
make
([]
string
,
len
(
t
.
selected
))
for
i
,
sel
:=
range
t
.
sortSelected
()
{
sels
[
i
]
=
quoteEntry
(
*
sel
.
text
)
}
executeCommand
(
t
.
execmap
[
mapkey
],
strings
.
Join
(
sels
,
" "
))
}
else
{
return
doAction
(
actExecute
,
mapkey
)
}
case
actInvalid
:
t
.
mutex
.
Unlock
()
...
...
This diff is collapsed.
Click to expand it.
test/test_go.rb
+
18
−
0
View file @
a89d8995
...
...
@@ -713,6 +713,24 @@ class TestGoFZF < TestBase
File
.
unlink
output
rescue
nil
end
def
test_execute_multi
output
=
'/tmp/fzf-test-execute-multi'
opts
=
%[--multi --bind
\\
"alt-a:execute-multi(echo '[{}], @{}@' >>
#{
output
}
)
\\
"]
tmux
.
send_keys
"seq 100 |
#{
fzf
opts
}
"
,
:Enter
tmux
.
until
{
|
lines
|
lines
[
-
2
].
include?
'100/100'
}
tmux
.
send_keys
:Escape
,
:a
tmux
.
send_keys
:BTab
,
:BTab
,
:BTab
tmux
.
send_keys
:Escape
,
:a
tmux
.
send_keys
:Tab
,
:Tab
tmux
.
send_keys
:Escape
,
:a
tmux
.
send_keys
:Enter
readonce
assert_equal
[
'["1"], @"1"@'
,
'["1" "2" "3"], @"1" "2" "3"@'
,
'["1" "2" "4"], @"1" "2" "4"@'
],
File
.
readlines
(
output
).
map
(
&
:chomp
)
ensure
File
.
unlink
output
rescue
nil
end
def
test_cycle
tmux
.
send_keys
"seq 8 |
#{
fzf
:cycle
}
"
,
:Enter
tmux
.
until
{
|
lines
|
lines
[
-
2
].
include?
'8/8'
}
...
...
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