From 5a7b41a2cf1271537c9831b0fddd38dbe58eb60d Mon Sep 17 00:00:00 2001 From: Junegunn Choi <junegunn.c@gmail.com> Date: Sat, 2 Dec 2017 02:27:02 +0900 Subject: [PATCH] Add accept-non-empty action 'accept-non-empty' is similar to 'accept' (which is bound to 'enter' and 'double-click' by default) but it prevents fzf from exiting without any selection. Close #1162 --- man/man1/fzf.1 | 1 + src/options.go | 2 ++ src/terminal.go | 5 +++++ test/test_go.rb | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+) diff --git a/man/man1/fzf.1 b/man/man1/fzf.1 index 301e2099..60012501 100644 --- a/man/man1/fzf.1 +++ b/man/man1/fzf.1 @@ -492,6 +492,7 @@ triggered whenever the query string is changed. \fBACTION: DEFAULT BINDINGS (NOTES): \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) \fBbackward-char\fR \fIctrl-b left\fR \fBbackward-delete-char\fR \fIctrl-h bspace\fR \fBbackward-kill-word\fR \fIalt-bs\fR diff --git a/src/options.go b/src/options.go index 730c1167..160fdd01 100644 --- a/src/options.go +++ b/src/options.go @@ -662,6 +662,8 @@ func parseKeymap(keymap map[int][]action, str string) { appendAction(actAbort) case "accept": appendAction(actAccept) + case "accept-non-empty": + appendAction(actAcceptNonEmpty) case "print-query": appendAction(actPrintQuery) case "replace-query": diff --git a/src/terminal.go b/src/terminal.go index 82f0ac9f..6881cdb5 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -170,6 +170,7 @@ const ( actBeginningOfLine actAbort actAccept + actAcceptNonEmpty actBackwardChar actBackwardDeleteChar actBackwardWord @@ -1656,6 +1657,10 @@ func (t *Terminal) Loop() { req(reqList) case actAccept: req(reqClose) + case actAcceptNonEmpty: + if len(t.selected) > 0 || t.merger.Length() > 0 || !t.reading && t.count == 0 { + req(reqClose) + } case actClearScreen: req(reqRedraw) case actTop: diff --git a/test/test_go.rb b/test/test_go.rb index eca458ca..03fee238 100644 --- a/test/test_go.rb +++ b/test/test_go.rb @@ -1378,6 +1378,42 @@ class TestGoFZF < TestBase tmux.send_keys :Enter end + def test_accept_non_empty + tmux.send_keys %(seq 1000 | #{fzf '--print-query --bind enter:accept-non-empty'}), :Enter + tmux.until { |lines| lines.match_count == 1000 } + tmux.send_keys 'foo' + tmux.until { |lines| lines[-2].include? '0/1000' } + # fzf doesn't exit since there's no selection + tmux.send_keys :Enter + tmux.until { |lines| lines[-2].include? '0/1000' } + tmux.send_keys 'C-u' + tmux.until { |lines| lines[-2].include? '1000/1000' } + tmux.send_keys '999' + tmux.until { |lines| lines[-2].include? '1/1000' } + tmux.send_keys :Enter + assert_equal %w[999 999], readonce.split($INPUT_RECORD_SEPARATOR) + end + + def test_accept_non_empty_with_multi_selection + tmux.send_keys %(seq 1000 | #{fzf '-m --print-query --bind enter:accept-non-empty'}), :Enter + tmux.until { |lines| lines.match_count == 1000 } + tmux.send_keys :Tab + tmux.until { |lines| lines[-2].include? '1000/1000 (1)' } + tmux.send_keys 'foo' + tmux.until { |lines| lines[-2].include? '0/1000' } + # fzf will exit in this case even though there's no match for the current query + tmux.send_keys :Enter + assert_equal %w[foo 1], readonce.split($INPUT_RECORD_SEPARATOR) + end + + def test_accept_non_empty_with_empty_list + tmux.send_keys %(: | #{fzf '-q foo --print-query --bind enter:accept-non-empty'}), :Enter + tmux.until { |lines| lines[-2].strip == '0/0' } + tmux.send_keys :Enter + # fzf will exit anyway since input list is empty + assert_equal %w[foo], readonce.split($INPUT_RECORD_SEPARATOR) + end + def test_preview_update_on_select tmux.send_keys(%(seq 10 | fzf -m --preview 'echo {+}' --bind a:toggle-all), :Enter) -- GitLab