diff --git a/CHANGELOG.md b/CHANGELOG.md index 838fffe..63d6626 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ CHANGELOG ========= +0.44.2 +------ +- Added `accept-or-print-query` action that acts like `accept` but prints the + current query when there's no match for the query + ```sh + # You can make CTRL-R paste the current query when there's no match + export FZF_CTRL_R_OPTS='--bind enter:accept-or-print-query' + ``` +- Bug fixes + 0.44.1 ------ - Fixed crash when preview window is hidden on `focus` event diff --git a/man/man1/fzf.1 b/man/man1/fzf.1 index 63cbd6a..0205d0a 100644 --- a/man/man1/fzf.1 +++ b/man/man1/fzf.1 @@ -1120,6 +1120,7 @@ A key or an event can be bound to one or more of the following actions. \fBabort\fR \fIctrl-c ctrl-g ctrl-q esc\fR \fBaccept\fR \fIenter double-click\fR \fBaccept-non-empty\fR (same as \fBaccept\fR except that it prevents fzf from exiting without selection) + \fBaccept-or-print-query\fR (same as \fBaccept\fR except that it prints the query when there's no match) \fBbackward-char\fR \fIctrl-b left\fR \fBbackward-delete-char\fR \fIctrl-h bspace\fR \fBbackward-delete-char/eof\fR (same as \fBbackward-delete-char\fR except aborts fzf if query is empty) diff --git a/src/options.go b/src/options.go index d2c2608..57f2f1e 100644 --- a/src/options.go +++ b/src/options.go @@ -1070,6 +1070,8 @@ func parseActionList(masked string, original string, prevActions []*action, putA appendAction(actAccept) case "accept-non-empty": appendAction(actAcceptNonEmpty) + case "accept-or-print-query": + appendAction(actAcceptOrPrintQuery) case "print-query": appendAction(actPrintQuery) case "refresh-preview": diff --git a/src/terminal.go b/src/terminal.go index e588187..4a4498b 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -343,6 +343,7 @@ const ( actAbort actAccept actAcceptNonEmpty + actAcceptOrPrintQuery actBackwardChar actBackwardDeleteChar actBackwardDeleteCharEOF @@ -3497,6 +3498,12 @@ func (t *Terminal) Loop() { if len(t.selected) > 0 || t.merger.Length() > 0 || !t.reading && t.count == 0 { req(reqClose) } + case actAcceptOrPrintQuery: + if len(t.selected) > 0 || t.merger.Length() > 0 { + req(reqClose) + } else { + req(reqPrintQuery) + } case actClearScreen: req(reqFullRedraw) case actClearQuery: diff --git a/test/test_go.rb b/test/test_go.rb index 30d5e7b..b69f9d9 100755 --- a/test/test_go.rb +++ b/test/test_go.rb @@ -1776,6 +1776,35 @@ class TestGoFZF < TestBase assert_equal %w[foo], readonce.lines(chomp: true) end + def test_accept_or_print_query_without_match + tmux.send_keys %(seq 1000 | #{fzf('--bind enter:accept-or-print-query')}), :Enter + tmux.until { |lines| assert_equal 1000, lines.match_count } + tmux.send_keys 99999 + tmux.until { |lines| assert_equal 0, lines.match_count } + tmux.send_keys :Enter + assert_equal %w[99999], readonce.lines(chomp: true) + end + + def test_accept_or_print_query_with_match + tmux.send_keys %(seq 1000 | #{fzf('--bind enter:accept-or-print-query')}), :Enter + tmux.until { |lines| assert_equal 1000, lines.match_count } + tmux.send_keys '^99$' + tmux.until { |lines| assert_equal 1, lines.match_count } + tmux.send_keys :Enter + assert_equal %w[99], readonce.lines(chomp: true) + end + + def test_accept_or_print_query_with_multi_selection + tmux.send_keys %(seq 1000 | #{fzf('--bind enter:accept-or-print-query --multi')}), :Enter + tmux.until { |lines| assert_equal 1000, lines.match_count } + tmux.send_keys :BTab, :BTab, :BTab + tmux.until { |lines| assert_equal 3, lines.select_count } + tmux.send_keys 99999 + tmux.until { |lines| assert_equal 0, lines.match_count } + tmux.send_keys :Enter + assert_equal %w[1 2 3], readonce.lines(chomp: true) + end + def test_preview_update_on_select tmux.send_keys %(seq 10 | fzf -m --preview 'echo {+}' --bind a:toggle-all), :Enter