summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2022-12-28 00:05:31 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2022-12-28 00:05:31 +0900
commit36d2bb332b87900e8178f2ec54d2cfda07f075db (patch)
tree1a5573e489b3b962920ae91ea5df374b0d1e204b
parent4dbe45640a46a67e2c46fcd0f6257e078b6817c1 (diff)
downloadfzf-36d2bb332b87900e8178f2ec54d2cfda07f075db.tar.gz
Add transform-query(...) action
Test case authored by @SpicyLemon Close #1930 Close #2465 Close #2559 Close #2509 (e.g. fzf --bind 'space:transform-query:printf %s%s {q} {}')
-rw-r--r--CHANGELOG.md18
-rw-r--r--man/man1/fzf.11
-rw-r--r--src/options.go4
-rw-r--r--src/terminal.go26
-rwxr-xr-xtest/test_go.rb9
5 files changed, 51 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0ae8edaa..3608f4e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,7 +31,23 @@ CHANGELOG
# Both actions respect --layout option
seq 10 | fzf --multi --bind ctrl-n:next-selected,ctrl-p:prev-selected --layout reverse
```
-- Added `change-query(...)` action
+- Added `change-query(...)` action that simply changes the query string to the
+ given static string. This can be useful when used with `--listen`.
+ ```sh
+ curl localhost:6266 -d "change-query:$(date)"
+ ```
+- Added `transform-query(...)` action for transforming the query string using
+ an external command
+ ```sh
+ # Press space to convert the query to uppercase letters
+ fzf --bind 'space:transform-query(tr [:lower:] [:upper:] <<< {q})'
+
+ # Bind it to 'change' event for automatic conversion
+ fzf --bind 'change:transform-query(tr [:lower:] [:upper:] <<< {q})'
+
+ # Can only type numbers
+ fzf --bind 'change:transform-query(sed 's/[^0-9]//g' <<< {q})'
+ ```
- `put` action can optionally take an argument string
```sh
# a will put 'alpha' on the prompt, ctrl-b will put 'bravo'
diff --git a/man/man1/fzf.1 b/man/man1/fzf.1
index b6488bdb..f5e01b6e 100644
--- a/man/man1/fzf.1
+++ b/man/man1/fzf.1
@@ -1023,6 +1023,7 @@ A key or an event can be bound to one or more of the following actions.
\fBtoggle-search\fR (toggle search functionality)
\fBtoggle-sort\fR
\fBtoggle+up\fR \fIbtab (shift-tab)\fR
+ \fBtransform-query(...)\fR (transform query string using an external command)
\fBunbind(...)\fR (unbind bindings)
\fBunix-line-discard\fR \fIctrl-u\fR
\fBunix-word-rubout\fR \fIctrl-w\fR
diff --git a/src/options.go b/src/options.go
index f25b6e73..1288fbe4 100644
--- a/src/options.go
+++ b/src/options.go
@@ -890,7 +890,7 @@ const (
func init() {
executeRegexp = regexp.MustCompile(
- `(?si)[:+](execute(?:-multi|-silent)?|reload|preview|change-query|change-prompt|change-preview-window|change-preview|(?:re|un)bind|pos|put)`)
+ `(?si)[:+](execute(?:-multi|-silent)?|reload|preview|change-query|change-prompt|change-preview-window|change-preview|(?:re|un)bind|pos|put|transform-query)`)
splitRegexp = regexp.MustCompile("[,:]+")
actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+")
}
@@ -1207,6 +1207,8 @@ func isExecuteAction(str string) actionType {
return actExecuteMulti
case "put":
return actPut
+ case "transform-query":
+ return actTransformQuery
}
return actIgnore
}
diff --git a/src/terminal.go b/src/terminal.go
index 68a099cf..2d18f791 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -308,6 +308,7 @@ const (
actToggleSort
actTogglePreview
actTogglePreviewWrap
+ actTransformQuery
actPreview
actChangePreview
actChangePreviewWindow
@@ -2014,10 +2015,11 @@ func (t *Terminal) redraw(clear bool) {
t.printAll()
}
-func (t *Terminal) executeCommand(template string, forcePlus bool, background bool) {
+func (t *Terminal) executeCommand(template string, forcePlus bool, background bool, captureFirstLine bool) string {
+ line := ""
valid, list := t.buildPlusList(template, forcePlus)
if !valid {
- return
+ return line
}
command := t.replacePlaceholder(template, forcePlus, string(t.input), list)
cmd := util.ExecCommand(command, false)
@@ -2033,11 +2035,21 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
t.refresh()
} else {
t.tui.Pause(false)
- cmd.Run()
+ if captureFirstLine {
+ out, _ := cmd.StdoutPipe()
+ reader := bufio.NewReader(out)
+ cmd.Start()
+ line, _ = reader.ReadString('\n')
+ line = strings.TrimRight(line, "\r\n")
+ cmd.Wait()
+ } else {
+ cmd.Run()
+ }
t.tui.Resume(false, false)
}
t.executing.Set(false)
cleanTemporaryFiles()
+ return line
}
func (t *Terminal) hasPreviewer() bool {
@@ -2610,9 +2622,9 @@ func (t *Terminal) Loop() {
switch a.t {
case actIgnore:
case actExecute, actExecuteSilent:
- t.executeCommand(a.a, false, a.t == actExecuteSilent)
+ t.executeCommand(a.a, false, a.t == actExecuteSilent, false)
case actExecuteMulti:
- t.executeCommand(a.a, true, false)
+ t.executeCommand(a.a, true, false, false)
case actInvalid:
t.mutex.Unlock()
return false
@@ -2635,6 +2647,10 @@ func (t *Terminal) Loop() {
t.previewed.version = 0
req(reqPreviewRefresh)
}
+ case actTransformQuery:
+ query := t.executeCommand(a.a, false, true, true)
+ t.input = []rune(query)
+ t.cx = len(t.input)
case actToggleSort:
t.sort = !t.sort
changed = true
diff --git a/test/test_go.rb b/test/test_go.rb
index 4b2856eb..a4d2e2a8 100755
--- a/test/test_go.rb
+++ b/test/test_go.rb
@@ -1797,6 +1797,15 @@ class TestGoFZF < TestBase
tmux.until { |lines| assert_equal '> foobarbaz', lines.last }
end
+ def test_transform_query
+ tmux.send_keys %{#{FZF} --bind 'ctrl-r:transform-query(rev <<< {q}),ctrl-u:transform-query: tr "[:lower:]" "[:upper:]" <<< {q}' --query bar}, :Enter
+ tmux.until { |lines| assert_equal '> bar', lines[-1] }
+ tmux.send_keys 'C-r'
+ tmux.until { |lines| assert_equal '> rab', lines[-1] }
+ tmux.send_keys 'C-u'
+ tmux.until { |lines| assert_equal '> RAB', lines[-1] }
+ end
+
def test_clear_selection
tmux.send_keys %(seq 100 | #{FZF} --multi --bind space:clear-selection), :Enter
tmux.until { |lines| assert_equal 100, lines.match_count }