Add select and deselect actions

Close #2358
This commit is contained in:
Junegunn Choi 2021-02-25 21:14:15 +09:00
parent 806a47a7cc
commit 76bbf57b3d
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627
5 changed files with 60 additions and 0 deletions

View File

@ -1,6 +1,12 @@
CHANGELOG
=========
0.25.2
------
- Added `select` and `deselect` action for unconditinoally selecting or
deselecting a single item in `--multi` mode. Complements `toggle` action.
- Built with Go 1.16
0.25.1
------
- Added `close` action

View File

@ -784,6 +784,7 @@ A key or an event can be bound to one or more of the following actions.
\fBclear-query\fR (clear query string)
\fBdelete-char\fR \fIdel\fR
\fBdelete-char/eof\fR \fIctrl-d\fR (same as \fBdelete-char\fR except aborts fzf if query is empty)
\fBdeselect\fR
\fBdeselect-all\fR (deselect all matches)
\fBdisable-search\fR (disable search functionality)
\fBdown\fR \fIctrl-j ctrl-n down\fR
@ -819,6 +820,7 @@ A key or an event can be bound to one or more of the following actions.
\fBrefresh-preview\fR
\fBreload(...)\fR (see below for the details)
\fBreplace-query\fR (replace query string with the current selection)
\fBselect\fR
\fBselect-all\fR (select all matches)
\fBtoggle\fR (\fIright-click\fR)
\fBtoggle-all\fR (toggle all matches)

View File

@ -839,6 +839,8 @@ func parseKeymap(keymap map[tui.Event][]action, str string) {
appendAction(actDeleteChar)
case "delete-char/eof":
appendAction(actDeleteCharEOF)
case "deselect":
appendAction(actDeselect)
case "end-of-line":
appendAction(actEndOfLine)
case "cancel":
@ -879,6 +881,8 @@ func parseKeymap(keymap map[tui.Event][]action, str string) {
appendAction(actToggleAll)
case "toggle-search":
appendAction(actToggleSearch)
case "select":
appendAction(actSelect)
case "select-all":
appendAction(actSelectAll)
case "deselect-all":

View File

@ -276,6 +276,8 @@ const (
actReload
actDisableSearch
actEnableSearch
actSelect
actDeselect
)
type placeholderFlags struct {
@ -1785,11 +1787,26 @@ func (t *Terminal) selectItem(item *Item) bool {
return true
}
func (t *Terminal) selectItemChanged(item *Item) bool {
if _, found := t.selected[item.Index()]; found {
return false
}
return t.selectItem(item)
}
func (t *Terminal) deselectItem(item *Item) {
delete(t.selected, item.Index())
t.version++
}
func (t *Terminal) deselectItemChanged(item *Item) bool {
if _, found := t.selected[item.Index()]; found {
t.deselectItem(item)
return true
}
return false
}
func (t *Terminal) toggleItem(item *Item) bool {
if _, found := t.selected[item.Index()]; !found {
return t.selectItem(item)
@ -2341,6 +2358,16 @@ func (t *Terminal) Loop() {
} else {
req(reqQuit)
}
case actSelect:
current := t.currentItem()
if t.multi > 0 && current != nil && t.selectItemChanged(current) {
req(reqList, reqInfo)
}
case actDeselect:
current := t.currentItem()
if t.multi > 0 && current != nil && t.deselectItemChanged(current) {
req(reqList, reqInfo)
}
case actToggle:
if t.multi > 0 && t.merger.Length() > 0 && toggle() {
req(reqList)

View File

@ -1890,6 +1890,27 @@ class TestGoFZF < TestBase
tmux.send_keys 'C-l', 'closed'
tmux.until { |lines| assert_includes lines[0], 'closed' }
end
def test_select_deselect
tmux.send_keys "seq 3 | #{FZF} --multi --bind up:deselect+up,down:select+down", :Enter
tmux.until { |lines| assert_equal 3, lines.match_count }
tmux.send_keys :Tab
tmux.until { |lines| assert_equal 1, lines.select_count }
tmux.send_keys :Up
tmux.until { |lines| assert_equal 0, lines.select_count }
tmux.send_keys :Down, :Down
tmux.until { |lines| assert_equal 2, lines.select_count }
tmux.send_keys :Tab
tmux.until { |lines| assert_equal 1, lines.select_count }
tmux.send_keys :Down, :Down
tmux.until { |lines| assert_equal 2, lines.select_count }
tmux.send_keys :Up
tmux.until { |lines| assert_equal 1, lines.select_count }
tmux.send_keys :Down
tmux.until { |lines| assert_equal 1, lines.select_count }
tmux.send_keys :Down
tmux.until { |lines| assert_equal 2, lines.select_count }
end
end
module TestShell