summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2025-07-06 10:05:25 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2025-07-06 10:05:25 +0900
commit6e3c830cd26194775ad18d565b1d96df8ae945f0 (patch)
tree7a944edfca478188bc8f967270fb7e0016651316
parentd7db7fc13275ed55b6d3d79b18f95d5b83b7a015 (diff)
downloadfzf-6e3c830cd26194775ad18d565b1d96df8ae945f0.tar.gz
Add 'multi' event triggered on multi-selection changes
-rw-r--r--CHANGELOG.md7
-rw-r--r--man/man1/fzf.18
-rw-r--r--src/options.go4
-rw-r--r--src/terminal.go4
-rw-r--r--src/tui/tui.go1
-rw-r--r--test/test_core.rb11
6 files changed, 31 insertions, 4 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8f1213f8..4727de6f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,13 +1,18 @@
CHANGELOG
=========
-0.63.1
+0.64.0
------
+- Added `multi` event that is triggered when the multi-selection has changed.
+ ```sh
+ fzf --multi --bind 'multi:transform-footer:(( FZF_SELECT_COUNT )) && echo "Selected: $FZF_SELECT_COUNT item(s)"'
+ ```
- [Halfwidth and fullwidth alphanumeric and punctuation characters](https://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms_(Unicode_block)) are now internally normalized to their ASCII equivalents to allow matching with ASCII queries.
```sh
echo ABC| fzf -q abc
```
- Fixed a bug which caused fzf to abort due to incorrect update ordering.
+- Renamed `clear-selection` action to `clear-multi` for consistency.
0.63.0
------
diff --git a/man/man1/fzf.1 b/man/man1/fzf.1
index 0802127e..fdbca13a 100644
--- a/man/man1/fzf.1
+++ b/man/man1/fzf.1
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
..
-.TH fzf 1 "Jun 2025" "fzf 0.63.0" "fzf - a command-line fuzzy finder"
+.TH fzf 1 "Jul 2025" "fzf 0.64.0" "fzf - a command-line fuzzy finder"
.SH NAME
fzf - a command-line fuzzy finder
@@ -1609,6 +1609,10 @@ e.g.
# Beware not to introduce an infinite loop
seq 10 | fzf \-\-bind 'focus:up' \-\-cycle\fR
.RE
+\fImulti\fR
+.RS
+Triggered when the multi\-selection has changed.
+.RE
\fIone\fR
.RS
@@ -1711,7 +1715,7 @@ A key or an event can be bound to one or more of the following actions.
\fBchange\-prompt(...)\fR (change prompt to the given string)
\fBchange\-query(...)\fR (change query string to the given string)
\fBclear\-screen\fR \fIctrl\-l\fR
- \fBclear\-selection\fR (clear multi\-selection)
+ \fBclear\-multi\fR (clear multi\-selection)
\fBclose\fR (close preview window if open, abort fzf otherwise)
\fBclear\-query\fR (clear query string)
\fBdelete\-char\fR \fIdel\fR
diff --git a/src/options.go b/src/options.go
index c724f2eb..5cb9f14a 100644
--- a/src/options.go
+++ b/src/options.go
@@ -1008,6 +1008,8 @@ func parseKeyChordsImpl(str string, message string) (map[tui.Event]string, error
add(tui.JumpCancel)
case "click-header":
add(tui.ClickHeader)
+ case "multi":
+ add(tui.Multi)
case "alt-enter", "alt-return":
chords[tui.CtrlAltKey('m')] = key
case "alt-space":
@@ -1561,7 +1563,7 @@ func parseActionList(masked string, original string, prevActions []*action, putA
appendAction(actCancel)
case "clear-query":
appendAction(actClearQuery)
- case "clear-selection":
+ case "clear-multi", "clear-selection":
appendAction(actClearSelection)
case "forward-char":
appendAction(actForwardChar)
diff --git a/src/terminal.go b/src/terminal.go
index 8b5529fe..634d7859 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -5399,6 +5399,7 @@ func (t *Terminal) Loop() error {
}
previousInput := t.input
previousCx := t.cx
+ previousVersion := t.version
t.lastKey = event.KeyName()
updatePreviewWindow := func(forcePreview bool) {
t.resizeWindows(forcePreview, false)
@@ -6656,6 +6657,9 @@ func (t *Terminal) Loop() error {
if onEOFs, prs := t.keymap[tui.BackwardEOF.AsEvent()]; beof && prs && !doActions(onEOFs) {
continue
}
+ if onMultis, prs := t.keymap[tui.Multi.AsEvent()]; t.version != previousVersion && prs && !doActions(onMultis) {
+ continue
+ }
} else {
jumpEvent := tui.JumpCancel
if event.Type == tui.Rune {
diff --git a/src/tui/tui.go b/src/tui/tui.go
index c899ee78..02b9b093 100644
--- a/src/tui/tui.go
+++ b/src/tui/tui.go
@@ -132,6 +132,7 @@ const (
Jump
JumpCancel
ClickHeader
+ Multi
)
func (t EventType) AsEvent() Event {
diff --git a/test/test_core.rb b/test/test_core.rb
index b19b1dc5..08d6c05b 100644
--- a/test/test_core.rb
+++ b/test/test_core.rb
@@ -1988,4 +1988,15 @@ class TestCore < TestInteractive
tmux.until { assert it.any_include?('boom') }
tmux.until { assert it.any_include?('bam') }
end
+
+ def test_multi_event
+ tmux.send_keys %(seq 100 | #{FZF} --multi --bind 'multi:transform-footer:(( FZF_SELECT_COUNT )) && echo "Selected $FZF_SELECT_COUNT item(s)"'), :Enter
+ tmux.until { assert_equal 100, it.match_count }
+ tmux.send_keys :Tab
+ tmux.until { assert_equal 1, it.select_count }
+ tmux.until { assert it.any_include?('Selected 1 item(s)') }
+ tmux.send_keys :Tab
+ tmux.until { assert_equal 0, it.select_count }
+ tmux.until { refute it.any_include?('Selected') }
+ end
end