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
This commit is contained in:
Junegunn Choi
2017-12-02 02:27:02 +09:00
parent 338a73d764
commit 5a7b41a2cf
4 changed files with 44 additions and 0 deletions

View File

@@ -492,6 +492,7 @@ triggered whenever the query string is changed.
\fBACTION: DEFAULT BINDINGS (NOTES): \fBACTION: DEFAULT BINDINGS (NOTES):
\fBabort\fR \fIctrl-c ctrl-g ctrl-q esc\fR \fBabort\fR \fIctrl-c ctrl-g ctrl-q esc\fR
\fBaccept\fR \fIenter double-click\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-char\fR \fIctrl-b left\fR
\fBbackward-delete-char\fR \fIctrl-h bspace\fR \fBbackward-delete-char\fR \fIctrl-h bspace\fR
\fBbackward-kill-word\fR \fIalt-bs\fR \fBbackward-kill-word\fR \fIalt-bs\fR

View File

@@ -662,6 +662,8 @@ func parseKeymap(keymap map[int][]action, str string) {
appendAction(actAbort) appendAction(actAbort)
case "accept": case "accept":
appendAction(actAccept) appendAction(actAccept)
case "accept-non-empty":
appendAction(actAcceptNonEmpty)
case "print-query": case "print-query":
appendAction(actPrintQuery) appendAction(actPrintQuery)
case "replace-query": case "replace-query":

View File

@@ -170,6 +170,7 @@ const (
actBeginningOfLine actBeginningOfLine
actAbort actAbort
actAccept actAccept
actAcceptNonEmpty
actBackwardChar actBackwardChar
actBackwardDeleteChar actBackwardDeleteChar
actBackwardWord actBackwardWord
@@ -1656,6 +1657,10 @@ func (t *Terminal) Loop() {
req(reqList) req(reqList)
case actAccept: case actAccept:
req(reqClose) req(reqClose)
case actAcceptNonEmpty:
if len(t.selected) > 0 || t.merger.Length() > 0 || !t.reading && t.count == 0 {
req(reqClose)
}
case actClearScreen: case actClearScreen:
req(reqRedraw) req(reqRedraw)
case actTop: case actTop:

View File

@@ -1378,6 +1378,42 @@ class TestGoFZF < TestBase
tmux.send_keys :Enter tmux.send_keys :Enter
end 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 def test_preview_update_on_select
tmux.send_keys(%(seq 10 | fzf -m --preview 'echo {+}' --bind a:toggle-all), tmux.send_keys(%(seq 10 | fzf -m --preview 'echo {+}' --bind a:toggle-all),
:Enter) :Enter)