Add change-prompt action

Close #2270
pull/2281/head
Junegunn Choi 4 years ago
parent d2af3ff98d
commit 6d647e13ff
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627

@ -1,6 +1,14 @@
CHANGELOG CHANGELOG
========= =========
0.24.4
------
- Added `change-prompt` action
```sh
fzf --prompt 'foo> ' --bind $'a:change-prompt:\x1b[31mbar> '
```
- Bug fixes and improvements
0.24.3 0.24.3
------ ------
- Added `--padding` option - Added `--padding` option

@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
.. ..
.TH fzf-tmux 1 "Nov 2020" "fzf 0.24.3" "fzf-tmux - open fzf in tmux split pane" .TH fzf-tmux 1 "Dec 2020" "fzf 0.24.3" "fzf-tmux - open fzf in tmux split pane"
.SH NAME .SH NAME
fzf-tmux - open fzf in tmux split pane fzf-tmux - open fzf in tmux split pane

@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
.. ..
.TH fzf 1 "Nov 2020" "fzf 0.24.4" "fzf - a command-line fuzzy finder" .TH fzf 1 "Dec 2020" "fzf 0.24.4" "fzf - a command-line fuzzy finder"
.SH NAME .SH NAME
fzf - a command-line fuzzy finder fzf - a command-line fuzzy finder
@ -761,6 +761,7 @@ A key or an event can be bound to one or more of the following actions.
\fBbackward-word\fR \fIalt-b shift-left\fR \fBbackward-word\fR \fIalt-b shift-left\fR
\fBbeginning-of-line\fR \fIctrl-a home\fR \fBbeginning-of-line\fR \fIctrl-a home\fR
\fBcancel\fR (clear query string if not empty, abort fzf otherwise) \fBcancel\fR (clear query string if not empty, abort fzf otherwise)
\fBchange-prompt(...)\fR (change prompt to the given string)
\fBclear-screen\fR \fIctrl-l\fR \fBclear-screen\fR \fIctrl-l\fR
\fBclear-selection\fR (clear multi-selection) \fBclear-selection\fR (clear multi-selection)
\fBclear-query\fR (clear query string) \fBclear-query\fR (clear query string)
@ -816,42 +817,51 @@ A key or an event can be bound to one or more of the following actions.
Multiple actions can be chained using \fB+\fR separator. Multiple actions can be chained using \fB+\fR separator.
e.g. e.g.
\fBfzf --bind 'ctrl-a:select-all+accept'\fR \fBfzf --multi --bind 'ctrl-a:select-all+accept'\fR
\fBfzf --multi --bind 'ctrl-a:select-all' --bind 'ctrl-a:+accept'\fR
.SS COMMAND EXECUTION .SS ACTION ARGUMENT
With \fBexecute(...)\fR action, you can execute arbitrary commands without An action denoted with \fB(...)\fR suffix takes an argument.
leaving fzf. For example, you can turn fzf into a simple file browser by
binding \fBenter\fR key to \fBless\fR command like follows.
\fBfzf --bind "enter:execute(less {})"\fR e.g.
\fBfzf --bind 'ctrl-a:change-prompt(NewPrompt> )'\fR
You can use the same placeholder expressions as in \fB--preview\fR. \fBfzf --bind 'ctrl-v:preview(cat {})' --preview-window hidden\fR
If the command contains parentheses, fzf may fail to parse the expression. In If the argument contains parentheses, fzf may fail to parse the expression. In
that case, you can use any of the following alternative notations to avoid that case, you can use any of the following alternative notations to avoid
parse errors. parse errors.
\fBexecute[...]\fR \fBaction-name[...]\fR
\fBexecute~...~\fR \fBaction-name~...~\fR
\fBexecute!...!\fR \fBaction-name!...!\fR
\fBexecute@...@\fR \fBaction-name@...@\fR
\fBexecute#...#\fR \fBaction-name#...#\fR
\fBexecute$...$\fR \fBaction-name$...$\fR
\fBexecute%...%\fR \fBaction-name%...%\fR
\fBexecute^...^\fR \fBaction-name^...^\fR
\fBexecute&...&\fR \fBaction-name&...&\fR
\fBexecute*...*\fR \fBaction-name*...*\fR
\fBexecute;...;\fR \fBaction-name;...;\fR
\fBexecute/.../\fR \fBaction-name/.../\fR
\fBexecute|...|\fR \fBaction-name|...|\fR
\fBexecute:...\fR \fBaction-name:...\fR
.RS .RS
The last one is the special form that frees you from parse errors as it does The last one 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 not expect the closing character. The catch is that it should be the last one
in the comma-separated list of key-action pairs. in the comma-separated list of key-action pairs.
.RE .RE
.SS COMMAND EXECUTION
With \fBexecute(...)\fR action, you can execute arbitrary commands without
leaving fzf. For example, you can turn fzf into a simple file browser by
binding \fBenter\fR key to \fBless\fR command like follows.
\fBfzf --bind "enter:execute(less {})"\fR
You can use the same placeholder expressions as in \fB--preview\fR.
fzf switches to the alternate screen when executing a command. However, if the fzf switches to the alternate screen when executing a command. However, if the
command is expected to complete quickly, and you are not interested in its command is expected to complete quickly, and you are not interested in its
output, you might want to use \fBexecute-silent\fR instead, which silently output, you might want to use \fBexecute-silent\fR instead, which silently

@ -735,7 +735,7 @@ func init() {
// Backreferences are not supported. // Backreferences are not supported.
// "~!@#$%^&*;/|".each_char.map { |c| Regexp.escape(c) }.map { |c| "#{c}[^#{c}]*#{c}" }.join('|') // "~!@#$%^&*;/|".each_char.map { |c| Regexp.escape(c) }.map { |c| "#{c}[^#{c}]*#{c}" }.join('|')
executeRegexp = regexp.MustCompile( executeRegexp = regexp.MustCompile(
`(?si)[:+](execute(?:-multi|-silent)?|reload|preview):.+|[:+](execute(?:-multi|-silent)?|reload|preview)(\([^)]*\)|\[[^\]]*\]|~[^~]*~|![^!]*!|@[^@]*@|\#[^\#]*\#|\$[^\$]*\$|%[^%]*%|\^[^\^]*\^|&[^&]*&|\*[^\*]*\*|;[^;]*;|/[^/]*/|\|[^\|]*\|)`) `(?si)[:+](execute(?:-multi|-silent)?|reload|preview|change-prompt):.+|[:+](execute(?:-multi|-silent)?|reload|preview|change-prompt)(\([^)]*\)|\[[^\]]*\]|~[^~]*~|![^!]*!|@[^@]*@|\#[^\#]*\#|\$[^\$]*\$|%[^%]*%|\^[^\^]*\^|&[^&]*&|\*[^\*]*\*|;[^;]*;|/[^/]*/|\|[^\|]*\|)`)
} }
func parseKeymap(keymap map[int][]action, str string) { func parseKeymap(keymap map[int][]action, str string) {
@ -749,6 +749,8 @@ func parseKeymap(keymap map[int][]action, str string) {
prefix = symbol + "reload" prefix = symbol + "reload"
} else if strings.HasPrefix(src[1:], "preview") { } else if strings.HasPrefix(src[1:], "preview") {
prefix = symbol + "preview" prefix = symbol + "preview"
} else if strings.HasPrefix(src[1:], "change-prompt") {
prefix = symbol + "change-prompt"
} else if src[len(prefix)] == '-' { } else if src[len(prefix)] == '-' {
c := src[len(prefix)+1] c := src[len(prefix)+1]
if c == 's' || c == 'S' { if c == 's' || c == 'S' {
@ -922,6 +924,8 @@ func parseKeymap(keymap map[int][]action, str string) {
offset = len("reload") offset = len("reload")
case actPreview: case actPreview:
offset = len("preview") offset = len("preview")
case actChangePrompt:
offset = len("change-prompt")
case actExecuteSilent: case actExecuteSilent:
offset = len("execute-silent") offset = len("execute-silent")
case actExecuteMulti: case actExecuteMulti:
@ -961,6 +965,8 @@ func isExecuteAction(str string) actionType {
return actReload return actReload
case "preview": case "preview":
return actPreview return actPreview
case "change-prompt":
return actChangePrompt
case "execute": case "execute":
return actExecute return actExecute
case "execute-silent": case "execute-silent":

@ -214,6 +214,7 @@ const (
actBackwardDeleteCharEOF actBackwardDeleteCharEOF
actBackwardWord actBackwardWord
actCancel actCancel
actChangePrompt
actClearScreen actClearScreen
actClearQuery actClearQuery
actClearSelection actClearSelection
@ -2223,6 +2224,9 @@ func (t *Terminal) Loop() {
} }
case actPrintQuery: case actPrintQuery:
req(reqPrintQuery) req(reqPrintQuery)
case actChangePrompt:
t.prompt, t.promptLen = t.parsePrompt(a.a)
req(reqPrompt)
case actPreview: case actPreview:
togglePreview(true) togglePreview(true)
refreshPreview(a.a) refreshPreview(a.a)

@ -1823,6 +1823,15 @@ class TestGoFZF < TestBase
tmux.until { |lines| lines.item_count == 100 } tmux.until { |lines| lines.item_count == 100 }
tmux.until { |lines| lines[1]&.include?('[200]') } tmux.until { |lines| lines[1]&.include?('[200]') }
end end
def test_change_prompt
tmux.send_keys "#{FZF} --bind 'a:change-prompt(a> ),b:change-prompt:b> ' --query foo", :Enter
tmux.until { |lines| assert_equal '> foo', lines[-1] }
tmux.send_keys 'a'
tmux.until { |lines| assert_equal 'a> foo', lines[-1] }
tmux.send_keys 'b'
tmux.until { |lines| assert_equal 'c> foo', lines[-1] }
end
end end
module TestShell module TestShell

Loading…
Cancel
Save