From 18e3b38c69da2828efac6adc2ea3a5e85f70e571 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Sun, 11 Dec 2022 00:59:34 +0900 Subject: [PATCH] Add 'next-selected' and 'prev-selected' actions Close #2749 --- CHANGELOG.md | 12 +++++++++++- man/man1/fzf.1 | 2 ++ src/options.go | 4 ++++ src/terminal.go | 18 ++++++++++++++++++ test/test_go.rb | 19 +++++++++++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b56575f..123e9a10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,18 @@ CHANGELOG ========= -0.35.2 +0.36.0 ------ +- Added `next-selected` and `prev-selected` actions to move between selected + items + ```sh + # `next-selected` will move the pointer to the next selected item below the current line + # `prev-selected` will move the pointer to the previous selected item above the current line + seq 10 | fzf --multi --bind ctrl-n:next-selected,ctrl-p:prev-selected + + # Both actions respect --layout option + seq 10 | fzf --multi --bind ctrl-n:next-selected,ctrl-p:prev-selected --layout reverse + ``` - `double-click` will behave the same as `enter` unless otherwise specified, so you don't have to repeat the same action twice in `--bind` in most cases. ```sh diff --git a/man/man1/fzf.1 b/man/man1/fzf.1 index b4d5f8aa..03ac6551 100644 --- a/man/man1/fzf.1 +++ b/man/man1/fzf.1 @@ -974,11 +974,13 @@ A key or an event can be bound to one or more of the following actions. \fBkill-word\fR \fIalt-d\fR \fBlast\fR (move to the last match) \fBnext-history\fR (\fIctrl-n\fR on \fB--history\fR) + \fBnext-selected\fR (move to the next selected item) \fBpage-down\fR \fIpgdn\fR \fBpage-up\fR \fIpgup\fR \fBhalf-page-down\fR \fBhalf-page-up\fR \fBprev-history\fR (\fIctrl-p\fR on \fB--history\fR) + \fBprev-selected\fR (move to the previous selected item) \fBpreview(...)\fR (see below for the details) \fBpreview-down\fR \fIshift-down\fR \fBpreview-up\fR \fIshift-up\fR diff --git a/src/options.go b/src/options.go index eceeffa2..4728adff 100644 --- a/src/options.go +++ b/src/options.go @@ -1064,6 +1064,10 @@ func parseKeymap(keymap map[tui.Event][]*action, str string) { appendAction(actPrevHistory) case "next-history": appendAction(actNextHistory) + case "prev-selected": + appendAction(actPrevSelected) + case "next-selected": + appendAction(actNextSelected) case "toggle-preview": appendAction(actTogglePreview) case "toggle-preview-wrap": diff --git a/src/terminal.go b/src/terminal.go index a5d54694..2bb785c1 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -316,7 +316,9 @@ const ( actPreviewHalfPageUp actPreviewHalfPageDown actPrevHistory + actPrevSelected actNextHistory + actNextSelected actExecute actExecuteSilent actExecuteMulti // Deprecated @@ -3016,6 +3018,22 @@ func (t *Terminal) Loop() { scrollPreviewTo(t.evaluateScrollOffset()) } } + case actNextSelected, actPrevSelected: + if len(t.selected) > 0 { + total := t.merger.Length() + for i := 1; i < total; i++ { + y := (t.cy + i) % total + if t.layout == layoutDefault && a.t == actNextSelected || + t.layout != layoutDefault && a.t == actPrevSelected { + y = (t.cy - i + total) % total + } + if _, found := t.selected[t.merger.Get(y).item.Index()]; found { + t.vset(y) + req(reqList) + break + } + } + } } return true } diff --git a/test/test_go.rb b/test/test_go.rb index b7ae1511..2312848b 100755 --- a/test/test_go.rb +++ b/test/test_go.rb @@ -2408,6 +2408,25 @@ class TestGoFZF < TestBase tmux.send_keys 'seq 100 | fzf -q55 --no-separator', :Enter tmux.until { assert(_1[-2] == ' 1/100') } end + + def test_prev_next_selected + tmux.send_keys 'seq 10 | fzf --multi --bind ctrl-n:next-selected,ctrl-p:prev-selected', :Enter + tmux.until { |lines| assert_equal 10, lines.item_count } + tmux.send_keys :BTab, :BTab, :Up, :BTab + tmux.until { |lines| assert_equal 3, lines.select_count } + tmux.send_keys 'C-n' + tmux.until { |lines| assert_includes lines, '>>4' } + tmux.send_keys 'C-n' + tmux.until { |lines| assert_includes lines, '>>2' } + tmux.send_keys 'C-n' + tmux.until { |lines| assert_includes lines, '>>1' } + tmux.send_keys 'C-n' + tmux.until { |lines| assert_includes lines, '>>4' } + tmux.send_keys 'C-p' + tmux.until { |lines| assert_includes lines, '>>1' } + tmux.send_keys 'C-p' + tmux.until { |lines| assert_includes lines, '>>2' } + end end module TestShell