mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2025-01-23 15:18:29 +00:00
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} {}')
This commit is contained in:
parent
4dbe45640a
commit
36d2bb332b
18
CHANGELOG.md
18
CHANGELOG.md
@ -31,7 +31,23 @@ CHANGELOG
|
|||||||
# Both actions respect --layout option
|
# Both actions respect --layout option
|
||||||
seq 10 | fzf --multi --bind ctrl-n:next-selected,ctrl-p:prev-selected --layout reverse
|
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
|
- `put` action can optionally take an argument string
|
||||||
```sh
|
```sh
|
||||||
# a will put 'alpha' on the prompt, ctrl-b will put 'bravo'
|
# a will put 'alpha' on the prompt, ctrl-b will put 'bravo'
|
||||||
|
@ -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-search\fR (toggle search functionality)
|
||||||
\fBtoggle-sort\fR
|
\fBtoggle-sort\fR
|
||||||
\fBtoggle+up\fR \fIbtab (shift-tab)\fR
|
\fBtoggle+up\fR \fIbtab (shift-tab)\fR
|
||||||
|
\fBtransform-query(...)\fR (transform query string using an external command)
|
||||||
\fBunbind(...)\fR (unbind bindings)
|
\fBunbind(...)\fR (unbind bindings)
|
||||||
\fBunix-line-discard\fR \fIctrl-u\fR
|
\fBunix-line-discard\fR \fIctrl-u\fR
|
||||||
\fBunix-word-rubout\fR \fIctrl-w\fR
|
\fBunix-word-rubout\fR \fIctrl-w\fR
|
||||||
|
@ -890,7 +890,7 @@ const (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
executeRegexp = regexp.MustCompile(
|
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("[,:]+")
|
splitRegexp = regexp.MustCompile("[,:]+")
|
||||||
actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+")
|
actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+")
|
||||||
}
|
}
|
||||||
@ -1207,6 +1207,8 @@ func isExecuteAction(str string) actionType {
|
|||||||
return actExecuteMulti
|
return actExecuteMulti
|
||||||
case "put":
|
case "put":
|
||||||
return actPut
|
return actPut
|
||||||
|
case "transform-query":
|
||||||
|
return actTransformQuery
|
||||||
}
|
}
|
||||||
return actIgnore
|
return actIgnore
|
||||||
}
|
}
|
||||||
|
@ -308,6 +308,7 @@ const (
|
|||||||
actToggleSort
|
actToggleSort
|
||||||
actTogglePreview
|
actTogglePreview
|
||||||
actTogglePreviewWrap
|
actTogglePreviewWrap
|
||||||
|
actTransformQuery
|
||||||
actPreview
|
actPreview
|
||||||
actChangePreview
|
actChangePreview
|
||||||
actChangePreviewWindow
|
actChangePreviewWindow
|
||||||
@ -2014,10 +2015,11 @@ func (t *Terminal) redraw(clear bool) {
|
|||||||
t.printAll()
|
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)
|
valid, list := t.buildPlusList(template, forcePlus)
|
||||||
if !valid {
|
if !valid {
|
||||||
return
|
return line
|
||||||
}
|
}
|
||||||
command := t.replacePlaceholder(template, forcePlus, string(t.input), list)
|
command := t.replacePlaceholder(template, forcePlus, string(t.input), list)
|
||||||
cmd := util.ExecCommand(command, false)
|
cmd := util.ExecCommand(command, false)
|
||||||
@ -2033,11 +2035,21 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
|
|||||||
t.refresh()
|
t.refresh()
|
||||||
} else {
|
} else {
|
||||||
t.tui.Pause(false)
|
t.tui.Pause(false)
|
||||||
|
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()
|
cmd.Run()
|
||||||
|
}
|
||||||
t.tui.Resume(false, false)
|
t.tui.Resume(false, false)
|
||||||
}
|
}
|
||||||
t.executing.Set(false)
|
t.executing.Set(false)
|
||||||
cleanTemporaryFiles()
|
cleanTemporaryFiles()
|
||||||
|
return line
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) hasPreviewer() bool {
|
func (t *Terminal) hasPreviewer() bool {
|
||||||
@ -2610,9 +2622,9 @@ func (t *Terminal) Loop() {
|
|||||||
switch a.t {
|
switch a.t {
|
||||||
case actIgnore:
|
case actIgnore:
|
||||||
case actExecute, actExecuteSilent:
|
case actExecute, actExecuteSilent:
|
||||||
t.executeCommand(a.a, false, a.t == actExecuteSilent)
|
t.executeCommand(a.a, false, a.t == actExecuteSilent, false)
|
||||||
case actExecuteMulti:
|
case actExecuteMulti:
|
||||||
t.executeCommand(a.a, true, false)
|
t.executeCommand(a.a, true, false, false)
|
||||||
case actInvalid:
|
case actInvalid:
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
return false
|
return false
|
||||||
@ -2635,6 +2647,10 @@ func (t *Terminal) Loop() {
|
|||||||
t.previewed.version = 0
|
t.previewed.version = 0
|
||||||
req(reqPreviewRefresh)
|
req(reqPreviewRefresh)
|
||||||
}
|
}
|
||||||
|
case actTransformQuery:
|
||||||
|
query := t.executeCommand(a.a, false, true, true)
|
||||||
|
t.input = []rune(query)
|
||||||
|
t.cx = len(t.input)
|
||||||
case actToggleSort:
|
case actToggleSort:
|
||||||
t.sort = !t.sort
|
t.sort = !t.sort
|
||||||
changed = true
|
changed = true
|
||||||
|
@ -1797,6 +1797,15 @@ class TestGoFZF < TestBase
|
|||||||
tmux.until { |lines| assert_equal '> foobarbaz', lines.last }
|
tmux.until { |lines| assert_equal '> foobarbaz', lines.last }
|
||||||
end
|
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
|
def test_clear_selection
|
||||||
tmux.send_keys %(seq 100 | #{FZF} --multi --bind space:clear-selection), :Enter
|
tmux.send_keys %(seq 100 | #{FZF} --multi --bind space:clear-selection), :Enter
|
||||||
tmux.until { |lines| assert_equal 100, lines.match_count }
|
tmux.until { |lines| assert_equal 100, lines.match_count }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user