Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package fzf for openSUSE:Factory checked in 
at 2025-07-07 14:46:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/fzf (Old)
 and      /work/SRC/openSUSE:Factory/.fzf.new.1903 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "fzf"

Mon Jul  7 14:46:12 2025 rev:71 rq:1290911 version:0.64.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/fzf/fzf.changes  2025-06-30 13:06:10.061113404 
+0200
+++ /work/SRC/openSUSE:Factory/.fzf.new.1903/fzf.changes        2025-07-07 
14:46:14.599633731 +0200
@@ -1,0 +2,15 @@
+Sun Jul  6 18:43:48 UTC 2025 - Avindra Goolcharan <avin...@opensuse.org>
+
+- Update to version 0.64.0:
+  * Added `multi` event that is triggered when the multi-
+    selection has changed.
+  * Halfwidth and fullwidth alphanumeric and punctuation
+    characters are now internally normalized to their ASCII
+    equivalents to allow matching with ASCII queries.
+  * Renamed `clear-selection` action to `clear-multi` for consistency.
+  * Fixed a bug that could cause fzf to abort due to incorrect
+    update ordering.
+  * Fixed a bug where some multi-selections were lost when using
+    `exclude` or `change-nth`.
+
+-------------------------------------------------------------------

Old:
----
  fzf-0.63.0.tar.gz

New:
----
  fzf-0.64.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ fzf.spec ++++++
--- /var/tmp/diff_new_pack.038DoF/_old  2025-07-07 14:46:15.495671140 +0200
+++ /var/tmp/diff_new_pack.038DoF/_new  2025-07-07 14:46:15.495671140 +0200
@@ -19,7 +19,7 @@
 
 %global _lto_cflags %{nil}
 Name:           fzf
-Version:        0.63.0
+Version:        0.64.0
 Release:        0
 Summary:        A command-line fuzzy finder
 License:        MIT

++++++ fzf-0.63.0.tar.gz -> fzf-0.64.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/.tool-versions 
new/fzf-0.64.0/.tool-versions
--- old/fzf-0.63.0/.tool-versions       2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/.tool-versions       2025-07-06 15:11:36.000000000 +0200
@@ -1,2 +1,2 @@
-golang 1.20.13
+golang 1.20.14
 ruby 3.4.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/CHANGELOG.md new/fzf-0.64.0/CHANGELOG.md
--- old/fzf-0.63.0/CHANGELOG.md 2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/CHANGELOG.md 2025-07-06 15:11:36.000000000 +0200
@@ -1,6 +1,24 @@
 CHANGELOG
 =========
 
+0.64.0
+------
+- Added `multi` event that is triggered when the multi-selection has changed.
+  ```sh
+  fzf --multi \
+      --bind 'ctrl-a:select-all,ctrl-d:deselect-all' \
+      --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
+  ```
+- Renamed `clear-selection` action to `clear-multi` for consistency.
+    - `clear-selection` remains supported as an alias for backward 
compatibility.
+- Bug fixes
+    - Fixed a bug that could cause fzf to abort due to incorrect update 
ordering.
+    - Fixed a bug where some multi-selections were lost when using `exclude` 
or `change-nth`.
+
 0.63.0
 ------
 _Release highlights: https://junegunn.github.io/fzf/releases/0.63.0/_
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/LICENSE new/fzf-0.64.0/LICENSE
--- old/fzf-0.63.0/LICENSE      2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/LICENSE      2025-07-06 15:11:36.000000000 +0200
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2013-2024 Junegunn Choi
+Copyright (c) 2013-2025 Junegunn Choi
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/README-VIM.md new/fzf-0.64.0/README-VIM.md
--- old/fzf-0.63.0/README-VIM.md        2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/README-VIM.md        2025-07-06 15:11:36.000000000 +0200
@@ -493,4 +493,4 @@
 
 The MIT License (MIT)
 
-Copyright (c) 2013-2024 Junegunn Choi
+Copyright (c) 2013-2025 Junegunn Choi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/README.md new/fzf-0.64.0/README.md
--- old/fzf-0.63.0/README.md    2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/README.md    2025-07-06 15:11:36.000000000 +0200
@@ -981,7 +981,7 @@
 
 The MIT License (MIT)
 
-Copyright (c) 2013-2024 Junegunn Choi
+Copyright (c) 2013-2025 Junegunn Choi
 
 Sponsors :heart:
 ----------------
@@ -990,7 +990,7 @@
 
 If you'd like to sponsor this project, please visit 
https://github.com/sponsors/junegunn.
 
-<!-- sponsors --><a href="https://github.com/miyanokomiya";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;miyanokomiya.png" width="60px" alt="User 
avatar: miyanokomiya" /></a><a href="https://github.com/jonhoo";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;jonhoo.png" width="60px" alt="User 
avatar: Jon Gjengset" /></a><a href="https://github.com/AceofSpades5757";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;AceofSpades5757.png" width="60px" 
alt="User avatar: Kyle L. Davis" /></a><a 
href="https://github.com/Frederick888";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;Frederick888.png" width="60px" alt="User 
avatar: Frederick Zhang" /></a><a href="https://github.com/moritzdietz";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;moritzdietz.png" width="60px" alt="User 
avatar: Moritz Dietz" /></a><a href="https://github.com/mikker";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;mikker.png" width="60px" alt="User 
avatar: Mikkel Malmberg" /></a><a href="https://github.com/pldubouilh";><img 
src="https:&#x2F;&
 #x2F;github.com&#x2F;pldubouilh.png" width="60px" alt="User avatar: Pierre 
Dubouilh" /></a><a href="https://github.com/trantor";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;trantor.png" width="60px" alt="User 
avatar: Fulvio Scapin" /></a><a href="https://github.com/rcorre";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;rcorre.png" width="60px" alt="User 
avatar: Ryan Roden-Corrent" /></a><a href="https://github.com/blissdev";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;blissdev.png" width="60px" alt="User 
avatar: Jordan Arentsen" /></a><a href="https://github.com/aexvir";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;aexvir.png" width="60px" alt="User 
avatar: Alex Viscreanu" /></a><a href="https://github.com/dbalatero";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;dbalatero.png" width="60px" alt="User 
avatar: David Balatero" /></a><a href="https://github.com/moobar";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;moobar.png" width="60px" alt="User 
avatar: " /></a><a href="https://github.com/benela
 n"><img src="https:&#x2F;&#x2F;github.com&#x2F;benelan.png" width="60px" 
alt="User avatar: Ben Elan" /></a><a href="https://github.com/pawelduda";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;pawelduda.png" width="60px" alt="User 
avatar: Paweł Duda" /></a><a href="https://github.com/pyrho";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;pyrho.png" width="60px" alt="User 
avatar: Damien Rajon" /></a><a href="https://github.com/ArtBIT";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;ArtBIT.png" width="60px" alt="User 
avatar: ArtBIT" /></a><a href="https://github.com/da-moon";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;da-moon.png" width="60px" alt="User 
avatar: " /></a><a href="https://github.com/hovissimo";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;hovissimo.png" width="60px" alt="User 
avatar: Hovis" /></a><a href="https://github.com/dariusjonda";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;dariusjonda.png" width="60px" alt="User 
avatar: Darius Jonda" /></a><a href="https://github.com/cristian
 d391"><img src="https:&#x2F;&#x2F;github.com&#x2F;cristiand391.png" 
width="60px" alt="User avatar: Cristian Dominguez" /></a><a 
href="https://github.com/eliangcs";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;eliangcs.png" width="60px" alt="User 
avatar: Chang-Hung Liang" /></a><a href="https://github.com/asphaltbuffet";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;asphaltbuffet.png" width="60px" 
alt="User avatar: Ben Lechlitner" /></a><a href="https://github.com/kg8m";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;kg8m.png" width="60px" alt="User avatar: 
Takumi KAGIYAMA" /></a><a href="https://github.com/polm";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;polm.png" width="60px" alt="User avatar: 
Paul OLeary McCann" /></a><a href="https://github.com/rbeeger";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;rbeeger.png" width="60px" alt="User 
avatar: Robert Beeger" /></a><a href="https://github.com/scalisi";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;scalisi.png" width="60px" alt="User 
avatar: Josh
  Scalisi" /></a><a href="https://github.com/alecbcs";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;alecbcs.png" width="60px" alt="User 
avatar: Alec Scott" /></a><a href="https://github.com/artursapek";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;artursapek.png" width="60px" alt="User 
avatar: Artur Sapek" /></a><a href="https://github.com/ramnes";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;ramnes.png" width="60px" alt="User 
avatar: Guillaume Gelin" /></a><a href="https://github.com/jyc";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;jyc.png" width="60px" alt="User avatar: 
" /></a><a href="https://github.com/roblevy";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;roblevy.png" width="60px" alt="User 
avatar: Rob Levy" /></a><a href="https://github.com/glozow";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;glozow.png" width="60px" alt="User 
avatar: Gloria Zhao" /></a><a href="https://github.com/toupeira";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;toupeira.png" width="60px" alt="User 
avatar: Markus 
 Koller" /></a><a href="https://github.com/rkpatel33";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;rkpatel33.png" width="60px" alt="User 
avatar: " /></a><a href="https://github.com/jamesob";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;jamesob.png" width="60px" alt="User 
avatar: jamesob" /></a><a href="https://github.com/jlebray";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;jlebray.png" width="60px" alt="User 
avatar: Johan Le Bray" /></a><a href="https://github.com/panosl1";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;panosl1.png" width="60px" alt="User 
avatar: Panos Lampropoulos" /></a><a href="https://github.com/bespinian";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;bespinian.png" width="60px" alt="User 
avatar: bespinian" /></a><a href="https://github.com/scosu";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;scosu.png" width="60px" alt="User 
avatar: Markus Schneider-Pargmann" /></a><a 
href="https://github.com/smithbm2316";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;smithbm2316.png" width="
 60px" alt="User avatar: Ben Smith" /></a><a 
href="https://github.com/charlieegan3";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;charlieegan3.png" width="60px" alt="User 
avatar: Charlie Egan" /></a><a href="https://github.com/thobbs";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;thobbs.png" width="60px" alt="User 
avatar: Tyler Hobbs" /></a><a href="https://github.com/neilparikh";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;neilparikh.png" width="60px" alt="User 
avatar: Neil Parikh" /></a><a href="https://github.com/shkm";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;shkm.png" width="60px" alt="User avatar: 
Jamie Schembri" /></a><a href="https://github.com/BasedScience";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;BasedScience.png" width="60px" alt="User 
avatar: dockien" /></a><a href="https://github.com/RussellGilmore";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;RussellGilmore.png" width="60px" 
alt="User avatar: Russell Gilmore" /></a><a 
href="https://github.com/meribold";><img src="https:&#
 x2F;&#x2F;github.com&#x2F;meribold.png" width="60px" alt="User avatar: Lukas 
Waymann" /></a><a href="https://github.com/terminaldweller";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;terminaldweller.png" width="60px" 
alt="User avatar: Farzad Sadeghi" /></a><a 
href="https://github.com/jaydee-coder";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;jaydee-coder.png" width="60px" alt="User 
avatar: " /></a><a href="https://github.com/brpaz";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;brpaz.png" width="60px" alt="User 
avatar: Bruno Paz" /></a><a href="https://github.com/timobenn";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;timobenn.png" width="60px" alt="User 
avatar: Timothy Bennett" /></a><a href="https://github.com/danhorner";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;danhorner.png" width="60px" alt="User 
avatar: Daniel Horner" /></a><a href="https://github.com/syeo66";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;syeo66.png" width="60px" alt="User 
avatar: Red Ochsenbein" /></a><a href="https:/
 /github.com/nekhaevskiy"><img 
src="https:&#x2F;&#x2F;github.com&#x2F;nekhaevskiy.png" width="60px" alt="User 
avatar: Yury" /></a><a href="https://github.com/lajarre";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;lajarre.png" width="60px" alt="User 
avatar: " /></a><a href="https://github.com/vidhatre";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;vidhatre.png" width="60px" alt="User 
avatar: Vidhatre Gathey" /></a><a href="https://github.com/NightsPaladin";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;NightsPaladin.png" width="60px" 
alt="User avatar: Chris G." /></a><a href="https://github.com/lzell";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;lzell.png" width="60px" alt="User 
avatar: Lou Zell" /></a><a href="https://github.com/yolabingo";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;yolabingo.png" width="60px" alt="User 
avatar: Todd Jacobsen" /></a><a href="https://github.com/3ximus";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;3ximus.png" width="60px" alt="User 
avatar: Fabio" /></a><a href="
 https://github.com/bladeacer";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;bladeacer.png" width="60px" alt="User 
avatar: " /></a><a href="https://github.com/tylerdak";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;tylerdak.png" width="60px" alt="User 
avatar: Tyler Dakin" /></a><!-- sponsors -->
+<!-- sponsors --><a href="https://github.com/miyanokomiya";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;miyanokomiya.png" width="60px" alt="User 
avatar: miyanokomiya" /></a><a href="https://github.com/jonhoo";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;jonhoo.png" width="60px" alt="User 
avatar: Jon Gjengset" /></a><a href="https://github.com/AceofSpades5757";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;AceofSpades5757.png" width="60px" 
alt="User avatar: Kyle L. Davis" /></a><a 
href="https://github.com/Frederick888";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;Frederick888.png" width="60px" alt="User 
avatar: Frederick Zhang" /></a><a href="https://github.com/moritzdietz";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;moritzdietz.png" width="60px" alt="User 
avatar: Moritz Dietz" /></a><a href="https://github.com/pldubouilh";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;pldubouilh.png" width="60px" alt="User 
avatar: Pierre Dubouilh" /></a><a href="https://github.com/trantor";><img 
src="https:&#
 x2F;&#x2F;github.com&#x2F;trantor.png" width="60px" alt="User avatar: Fulvio 
Scapin" /></a><a href="https://github.com/rcorre";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;rcorre.png" width="60px" alt="User 
avatar: Ryan Roden-Corrent" /></a><a href="https://github.com/blissdev";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;blissdev.png" width="60px" alt="User 
avatar: Jordan Arentsen" /></a><a href="https://github.com/aexvir";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;aexvir.png" width="60px" alt="User 
avatar: Alex Viscreanu" /></a><a href="https://github.com/dbalatero";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;dbalatero.png" width="60px" alt="User 
avatar: David Balatero" /></a><a href="https://github.com/moobar";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;moobar.png" width="60px" alt="User 
avatar: " /></a><a href="https://github.com/benelan";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;benelan.png" width="60px" alt="User 
avatar: Ben Elan" /></a><a href="https://github.com/pawelduda";>
 <img src="https:&#x2F;&#x2F;github.com&#x2F;pawelduda.png" width="60px" 
alt="User avatar: Paweł Duda" /></a><a href="https://github.com/pyrho";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;pyrho.png" width="60px" alt="User 
avatar: Damien Rajon" /></a><a href="https://github.com/ArtBIT";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;ArtBIT.png" width="60px" alt="User 
avatar: ArtBIT" /></a><a href="https://github.com/da-moon";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;da-moon.png" width="60px" alt="User 
avatar: " /></a><a href="https://github.com/hovissimo";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;hovissimo.png" width="60px" alt="User 
avatar: Hovis" /></a><a href="https://github.com/dariusjonda";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;dariusjonda.png" width="60px" alt="User 
avatar: Darius Jonda" /></a><a href="https://github.com/cristiand391";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;cristiand391.png" width="60px" alt="User 
avatar: Cristian Dominguez" /></a><a href="https://gith
 ub.com/eliangcs"><img src="https:&#x2F;&#x2F;github.com&#x2F;eliangcs.png" 
width="60px" alt="User avatar: Chang-Hung Liang" /></a><a 
href="https://github.com/asphaltbuffet";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;asphaltbuffet.png" width="60px" 
alt="User avatar: Ben Lechlitner" /></a><a href="https://github.com/kg8m";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;kg8m.png" width="60px" alt="User avatar: 
Takumi KAGIYAMA" /></a><a href="https://github.com/polm";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;polm.png" width="60px" alt="User avatar: 
Paul OLeary McCann" /></a><a href="https://github.com/rbeeger";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;rbeeger.png" width="60px" alt="User 
avatar: Robert Beeger" /></a><a href="https://github.com/scalisi";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;scalisi.png" width="60px" alt="User 
avatar: Josh Scalisi" /></a><a href="https://github.com/alecbcs";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;alecbcs.png" width="60px" alt="User 
avatar: Alec 
 Scott" /></a><a href="https://github.com/artursapek";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;artursapek.png" width="60px" alt="User 
avatar: Artur Sapek" /></a><a href="https://github.com/ramnes";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;ramnes.png" width="60px" alt="User 
avatar: Guillaume Gelin" /></a><a href="https://github.com/jyc";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;jyc.png" width="60px" alt="User avatar: 
" /></a><a href="https://github.com/roblevy";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;roblevy.png" width="60px" alt="User 
avatar: Rob Levy" /></a><a href="https://github.com/glozow";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;glozow.png" width="60px" alt="User 
avatar: Gloria Zhao" /></a><a href="https://github.com/toupeira";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;toupeira.png" width="60px" alt="User 
avatar: Markus Koller" /></a><a href="https://github.com/rkpatel33";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;rkpatel33.png" width="60px" alt="User 
avatar: " /
 ></a><a href="https://github.com/jamesob";><img 
 >src="https:&#x2F;&#x2F;github.com&#x2F;jamesob.png" width="60px" alt="User 
 >avatar: jamesob" /></a><a href="https://github.com/jlebray";><img 
 >src="https:&#x2F;&#x2F;github.com&#x2F;jlebray.png" width="60px" alt="User 
 >avatar: Johan Le Bray" /></a><a href="https://github.com/panosl1";><img 
 >src="https:&#x2F;&#x2F;github.com&#x2F;panosl1.png" width="60px" alt="User 
 >avatar: Panos Lampropoulos" /></a><a href="https://github.com/bespinian";><img 
 >src="https:&#x2F;&#x2F;github.com&#x2F;bespinian.png" width="60px" alt="User 
 >avatar: bespinian" /></a><a href="https://github.com/scosu";><img 
 >src="https:&#x2F;&#x2F;github.com&#x2F;scosu.png" width="60px" alt="User 
 >avatar: Markus Schneider-Pargmann" /></a><a 
 >href="https://github.com/smithbm2316";><img 
 >src="https:&#x2F;&#x2F;github.com&#x2F;smithbm2316.png" width="60px" 
 >alt="User avatar: Ben Smith" /></a><a 
 >href="https://github.com/charlieegan3";><img 
 >src="https:&#x2F;&#x2F;github.com&#x2F;charlieegan3.png" w
 idth="60px" alt="User avatar: Charlie Egan" /></a><a 
href="https://github.com/thobbs";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;thobbs.png" width="60px" alt="User 
avatar: Tyler Hobbs" /></a><a href="https://github.com/neilparikh";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;neilparikh.png" width="60px" alt="User 
avatar: Neil Parikh" /></a><a href="https://github.com/shkm";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;shkm.png" width="60px" alt="User avatar: 
Jamie Schembri" /></a><a href="https://github.com/BasedScience";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;BasedScience.png" width="60px" alt="User 
avatar: dockien" /></a><a href="https://github.com/RussellGilmore";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;RussellGilmore.png" width="60px" 
alt="User avatar: Russell Gilmore" /></a><a 
href="https://github.com/meribold";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;meribold.png" width="60px" alt="User 
avatar: Lukas Waymann" /></a><a href="https://github.com/terminaldweller";><img 
src=
 "https:&#x2F;&#x2F;github.com&#x2F;terminaldweller.png" width="60px" alt="User 
avatar: Farzad Sadeghi" /></a><a href="https://github.com/jaydee-coder";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;jaydee-coder.png" width="60px" alt="User 
avatar: " /></a><a href="https://github.com/brpaz";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;brpaz.png" width="60px" alt="User 
avatar: Bruno Paz" /></a><a href="https://github.com/timobenn";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;timobenn.png" width="60px" alt="User 
avatar: Timothy Bennett" /></a><a href="https://github.com/danhorner";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;danhorner.png" width="60px" alt="User 
avatar: Daniel Horner" /></a><a href="https://github.com/syeo66";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;syeo66.png" width="60px" alt="User 
avatar: Red Ochsenbein" /></a><a href="https://github.com/nekhaevskiy";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;nekhaevskiy.png" width="60px" alt="User 
avatar: Yury" /></a><a href="https://
 github.com/lajarre"><img src="https:&#x2F;&#x2F;github.com&#x2F;lajarre.png" 
width="60px" alt="User avatar: " /></a><a 
href="https://github.com/vidhatre";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;vidhatre.png" width="60px" alt="User 
avatar: Vidhatre Gathey" /></a><a href="https://github.com/NightsPaladin";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;NightsPaladin.png" width="60px" 
alt="User avatar: Chris G." /></a><a href="https://github.com/lzell";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;lzell.png" width="60px" alt="User 
avatar: Lou Zell" /></a><a href="https://github.com/3ximus";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;3ximus.png" width="60px" alt="User 
avatar: Fabio" /></a><a href="https://github.com/bladeacer";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;bladeacer.png" width="60px" alt="User 
avatar: " /></a><a href="https://github.com/tylerdak";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;tylerdak.png" width="60px" alt="User 
avatar: Tyler Dakin" /></a><a href="https://githu
 b.com/justinlubin"><img 
src="https:&#x2F;&#x2F;github.com&#x2F;justinlubin.png" width="60px" alt="User 
avatar: Justin Lubin" /></a><a href="https://github.com/gpoma";><img 
src="https:&#x2F;&#x2F;github.com&#x2F;gpoma.png" width="60px" alt="User 
avatar: Gabriel" /></a><!-- sponsors -->
 
 ---
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/doc/fzf.txt new/fzf-0.64.0/doc/fzf.txt
--- old/fzf-0.63.0/doc/fzf.txt  2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/doc/fzf.txt  2025-07-06 15:11:36.000000000 +0200
@@ -503,7 +503,7 @@
 
 The MIT License (MIT)
 
-Copyright (c) 2013-2024 Junegunn Choi
+Copyright (c) 2013-2025 Junegunn Choi
 
 ==============================================================================
 vim:tw=78:sw=2:ts=2:ft=help:norl:nowrap:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/install new/fzf-0.64.0/install
--- old/fzf-0.63.0/install      2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/install      2025-07-06 15:11:36.000000000 +0200
@@ -2,7 +2,7 @@
 
 set -u
 
-version=0.63.0
+version=0.64.0
 auto_completion=
 key_bindings=
 update_config=2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/install.ps1 new/fzf-0.64.0/install.ps1
--- old/fzf-0.63.0/install.ps1  2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/install.ps1  2025-07-06 15:11:36.000000000 +0200
@@ -1,4 +1,4 @@
-$version="0.63.0"
+$version="0.64.0"
 
 $fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/main.go new/fzf-0.64.0/main.go
--- old/fzf-0.63.0/main.go      2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/main.go      2025-07-06 15:11:36.000000000 +0200
@@ -11,7 +11,7 @@
        "github.com/junegunn/fzf/src/protector"
 )
 
-var version = "0.63"
+var version = "0.64"
 var revision = "devel"
 
 //go:embed shell/key-bindings.bash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/man/man1/fzf-tmux.1 
new/fzf-0.64.0/man/man1/fzf-tmux.1
--- old/fzf-0.63.0/man/man1/fzf-tmux.1  2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/man/man1/fzf-tmux.1  2025-07-06 15:11:36.000000000 +0200
@@ -1,7 +1,7 @@
 .ig
 The MIT License (MIT)
 
-Copyright (c) 2013-2024 Junegunn Choi
+Copyright (c) 2013-2025 Junegunn Choi
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -21,7 +21,7 @@
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 ..
-.TH fzf\-tmux 1 "Jun 2025" "fzf 0.63.0" "fzf\-tmux - open fzf in tmux split 
pane"
+.TH fzf\-tmux 1 "Jul 2025" "fzf 0.64.0" "fzf\-tmux - open fzf in tmux split 
pane"
 
 .SH NAME
 fzf\-tmux - open fzf in tmux split pane
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/man/man1/fzf.1 
new/fzf-0.64.0/man/man1/fzf.1
--- old/fzf-0.63.0/man/man1/fzf.1       2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/man/man1/fzf.1       2025-07-06 15:11:36.000000000 +0200
@@ -1,7 +1,7 @@
 .ig
 The MIT License (MIT)
 
-Copyright (c) 2013-2024 Junegunn Choi
+Copyright (c) 2013-2025 Junegunn Choi
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -21,7 +21,7 @@
 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 @@
      # 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,13 +1715,13 @@
     \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
     \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)
+    \fBdeselect\-all\fR                 (deselect all matches; to also clear 
non-matched selections, use \fBclear\-multi\fR)
     \fBdisable\-search\fR               (disable search functionality)
     \fBdown\fR                         \fIctrl\-j  ctrl\-n  down\fR
     \fBenable\-search\fR                (enable search functionality)
@@ -1938,6 +1942,17 @@
                     echo "change\-header:Invalid selection"'
     \fR
 
+A common mistake when writing a \fBtransform\fR action is not escaping
+placeholder expressions when passing them back to fzf. In the following
+example, if you don't escape \fB{}\fR, fzf will immediately replace it with the
+single-quoted string of the current item. This causes single quotes to appear
+in the header and footer, and the script will break if any item contains
+double-quote characters.
+
+    \fBfzf \-\-bind 'focus:transform:[[ $FZF_ACTION =~ up ]] &&
+                echo "change\-header()+transform\-footer:echo \\{}" ||
+                echo "change\-footer()+transform\-header:echo \\{}"'\fR
+
 .SS TRANSFORM IN THE BACKGROUND
 
 Transform actions are synchronous, meaning fzf becomes unresponsive while the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/plugin/fzf.vim 
new/fzf-0.64.0/plugin/fzf.vim
--- old/fzf-0.63.0/plugin/fzf.vim       2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/plugin/fzf.vim       2025-07-06 15:11:36.000000000 +0200
@@ -1,4 +1,4 @@
-" Copyright (c) 2013-2024 Junegunn Choi
+" Copyright (c) 2013-2025 Junegunn Choi
 "
 " MIT License
 "
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/src/LICENSE new/fzf-0.64.0/src/LICENSE
--- old/fzf-0.63.0/src/LICENSE  2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/src/LICENSE  2025-07-06 15:11:36.000000000 +0200
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2013-2024 Junegunn Choi
+Copyright (c) 2013-2025 Junegunn Choi
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/src/algo/algo.go 
new/fzf-0.64.0/src/algo/algo.go
--- old/fzf-0.63.0/src/algo/algo.go     2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/src/algo/algo.go     2025-07-06 15:11:36.000000000 +0200
@@ -303,7 +303,7 @@
 }
 
 func normalizeRune(r rune) rune {
-       if r < 0x00C0 || r > 0x2184 {
+       if r < 0x00C0 || r > 0xFF61 {
                return r
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/src/algo/normalize.go 
new/fzf-0.64.0/src/algo/normalize.go
--- old/fzf-0.63.0/src/algo/normalize.go        2025-06-27 18:11:00.000000000 
+0200
+++ new/fzf-0.64.0/src/algo/normalize.go        2025-07-06 15:11:36.000000000 
+0200
@@ -473,6 +473,103 @@
        'ử': 'u',
        'ữ': 'u',
        'ự': 'u',
+
+       // 
https://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms_(Unicode_block)
+       0xFF01: '!',  // Fullwidth exclamation
+       0xFF02: '"',  // Fullwidth quotation mark
+       0xFF03: '#',  // Fullwidth number sign
+       0xFF04: '$',  // Fullwidth dollar sign
+       0xFF05: '%',  // Fullwidth percent
+       0xFF06: '&',  // Fullwidth ampersand
+       0xFF07: '\'', // Fullwidth apostrophe
+       0xFF08: '(',  // Fullwidth left parenthesis
+       0xFF09: ')',  // Fullwidth right parenthesis
+       0xFF0A: '*',  // Fullwidth asterisk
+       0xFF0B: '+',  // Fullwidth plus
+       0xFF0C: ',',  // Fullwidth comma
+       0xFF0D: '-',  // Fullwidth hyphen-minus
+       0xFF0E: '.',  // Fullwidth period
+       0xFF0F: '/',  // Fullwidth slash
+       0xFF10: '0',
+       0xFF11: '1',
+       0xFF12: '2',
+       0xFF13: '3',
+       0xFF14: '4',
+       0xFF15: '5',
+       0xFF16: '6',
+       0xFF17: '7',
+       0xFF18: '8',
+       0xFF19: '9',
+       0xFF1A: ':', // Fullwidth colon
+       0xFF1B: ';', // Fullwidth semicolon
+       0xFF1C: '<', // Fullwidth less-than
+       0xFF1D: '=', // Fullwidth equal
+       0xFF1E: '>', // Fullwidth greater-than
+       0xFF1F: '?', // Fullwidth question mark
+       0xFF20: '@', // Fullwidth at sign
+       0xFF21: 'A',
+       0xFF22: 'B',
+       0xFF23: 'C',
+       0xFF24: 'D',
+       0xFF25: 'E',
+       0xFF26: 'F',
+       0xFF27: 'G',
+       0xFF28: 'H',
+       0xFF29: 'I',
+       0xFF2A: 'J',
+       0xFF2B: 'K',
+       0xFF2C: 'L',
+       0xFF2D: 'M',
+       0xFF2E: 'N',
+       0xFF2F: 'O',
+       0xFF30: 'P',
+       0xFF31: 'Q',
+       0xFF32: 'R',
+       0xFF33: 'S',
+       0xFF34: 'T',
+       0xFF35: 'U',
+       0xFF36: 'V',
+       0xFF37: 'W',
+       0xFF38: 'X',
+       0xFF39: 'Y',
+       0xFF3A: 'Z',
+       0xFF3B: '[',  // Fullwidth left bracket
+       0xFF3C: '\\', // Fullwidth backslash
+       0xFF3D: ']',  // Fullwidth right bracket
+       0xFF3E: '^',  // Fullwidth circumflex
+       0xFF3F: '_',  // Fullwidth underscore
+       0xFF40: '`',  // Fullwidth grave accent
+       0xFF41: 'a',
+       0xFF42: 'b',
+       0xFF43: 'c',
+       0xFF44: 'd',
+       0xFF45: 'e',
+       0xFF46: 'f',
+       0xFF47: 'g',
+       0xFF48: 'h',
+       0xFF49: 'i',
+       0xFF4A: 'j',
+       0xFF4B: 'k',
+       0xFF4C: 'l',
+       0xFF4D: 'm',
+       0xFF4E: 'n',
+       0xFF4F: 'o',
+       0xFF50: 'p',
+       0xFF51: 'q',
+       0xFF52: 'r',
+       0xFF53: 's',
+       0xFF54: 't',
+       0xFF55: 'u',
+       0xFF56: 'v',
+       0xFF57: 'w',
+       0xFF58: 'x',
+       0xFF59: 'y',
+       0xFF5A: 'z',
+       0xFF5B: '{', // Fullwidth left brace
+       0xFF5C: '|', // Fullwidth vertical bar
+       0xFF5D: '}', // Fullwidth right brace
+       0xFF5E: '~', // Fullwidth tilde
+       0xFF61: '.', // Halfwidth ideographic full stop
 }
 
 // NormalizeRunes normalizes latin script letters
@@ -480,7 +577,7 @@
        ret := make([]rune, len(runes))
        copy(ret, runes)
        for idx, r := range runes {
-               if r < 0x00C0 || r > 0x2184 {
+               if r < 0x00C0 || r > 0xFF61 {
                        continue
                }
                n := normalized[r]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/src/chunklist.go 
new/fzf-0.64.0/src/chunklist.go
--- old/fzf-0.63.0/src/chunklist.go     2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/src/chunklist.go     2025-07-06 15:11:36.000000000 +0200
@@ -41,6 +41,13 @@
        return c.count == chunkSize
 }
 
+func (c *Chunk) lastIndex(minValue int32) int32 {
+       if c.count == 0 {
+               return minValue
+       }
+       return c.items[c.count-1].Index() + 1 // Exclusive
+}
+
 func (cl *ChunkList) lastChunk() *Chunk {
        return cl.chunks[len(cl.chunks)-1]
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/src/matcher.go 
new/fzf-0.64.0/src/matcher.go
--- old/fzf-0.63.0/src/matcher.go       2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/src/matcher.go       2025-07-06 15:11:36.000000000 +0200
@@ -165,6 +165,7 @@
        }
 
        minIndex := request.chunks[0].items[0].Index()
+       maxIndex := request.chunks[numChunks-1].lastIndex(minIndex)
        cancelled := util.NewAtomicBool(false)
 
        slices := m.sliceChunks(request.chunks)
@@ -236,7 +237,7 @@
                partialResult := <-resultChan
                partialResults[partialResult.index] = partialResult.matches
        }
-       return NewMerger(pattern, partialResults, m.sort && 
request.pattern.sortable, m.tac, request.revision, minIndex), false
+       return NewMerger(pattern, partialResults, m.sort && 
request.pattern.sortable, m.tac, request.revision, minIndex, maxIndex), false
 }
 
 // Reset is called to interrupt/signal the ongoing search
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/src/merger.go new/fzf-0.64.0/src/merger.go
--- old/fzf-0.63.0/src/merger.go        2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/src/merger.go        2025-07-06 15:11:36.000000000 +0200
@@ -4,7 +4,7 @@
 
 // EmptyMerger is a Merger with no data
 func EmptyMerger(revision revision) *Merger {
-       return NewMerger(nil, [][]Result{}, false, false, revision, 0)
+       return NewMerger(nil, [][]Result{}, false, false, revision, 0, 0)
 }
 
 // Merger holds a set of locally sorted lists of items and provides the view of
@@ -22,14 +22,16 @@
        pass     bool
        revision revision
        minIndex int32
+       maxIndex int32
 }
 
 // PassMerger returns a new Merger that simply returns the items in the
 // original order
 func PassMerger(chunks *[]*Chunk, tac bool, revision revision) *Merger {
-       var minIndex int32
+       var minIndex, maxIndex int32
        if len(*chunks) > 0 {
                minIndex = (*chunks)[0].items[0].Index()
+               maxIndex = (*chunks)[len(*chunks)-1].lastIndex(minIndex)
        }
        mg := Merger{
                pattern:  nil,
@@ -38,7 +40,8 @@
                count:    0,
                pass:     true,
                revision: revision,
-               minIndex: minIndex}
+               minIndex: minIndex,
+               maxIndex: maxIndex}
 
        for _, chunk := range *mg.chunks {
                mg.count += chunk.count
@@ -47,7 +50,7 @@
 }
 
 // NewMerger returns a new Merger
-func NewMerger(pattern *Pattern, lists [][]Result, sorted bool, tac bool, 
revision revision, minIndex int32) *Merger {
+func NewMerger(pattern *Pattern, lists [][]Result, sorted bool, tac bool, 
revision revision, minIndex int32, maxIndex int32) *Merger {
        mg := Merger{
                pattern:  pattern,
                lists:    lists,
@@ -59,7 +62,8 @@
                final:    false,
                count:    0,
                revision: revision,
-               minIndex: minIndex}
+               minIndex: minIndex,
+               maxIndex: maxIndex}
 
        for _, list := range mg.lists {
                mg.count += len(list)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/src/merger_test.go 
new/fzf-0.64.0/src/merger_test.go
--- old/fzf-0.63.0/src/merger_test.go   2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/src/merger_test.go   2025-07-06 15:11:36.000000000 +0200
@@ -58,7 +58,7 @@
        cnt := len(items)
 
        // Not sorted: same order
-       mg := NewMerger(nil, lists, false, false, revision{}, 0)
+       mg := NewMerger(nil, lists, false, false, revision{}, 0, 0)
        assert(t, cnt == mg.Length(), "Invalid Length")
        for i := 0; i < cnt; i++ {
                assert(t, items[i] == mg.Get(i), "Invalid Get")
@@ -70,7 +70,7 @@
        cnt := len(items)
 
        // Sorted sorted order
-       mg := NewMerger(nil, lists, true, false, revision{}, 0)
+       mg := NewMerger(nil, lists, true, false, revision{}, 0, 0)
        assert(t, cnt == mg.Length(), "Invalid Length")
        sort.Sort(ByRelevance(items))
        for i := 0; i < cnt; i++ {
@@ -80,7 +80,7 @@
        }
 
        // Inverse order
-       mg2 := NewMerger(nil, lists, true, false, revision{}, 0)
+       mg2 := NewMerger(nil, lists, true, false, revision{}, 0, 0)
        for i := cnt - 1; i >= 0; i-- {
                if items[i] != mg2.Get(i) {
                        t.Error("Not sorted", items[i], mg2.Get(i))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/src/options.go 
new/fzf-0.64.0/src/options.go
--- old/fzf-0.63.0/src/options.go       2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/src/options.go       2025-07-06 15:11:36.000000000 +0200
@@ -1008,6 +1008,8 @@
                        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 @@
                        appendAction(actCancel)
                case "clear-query":
                        appendAction(actClearQuery)
-               case "clear-selection":
+               case "clear-multi", "clear-selection":
                        appendAction(actClearSelection)
                case "forward-char":
                        appendAction(actForwardChar)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/src/terminal.go 
new/fzf-0.64.0/src/terminal.go
--- old/fzf-0.63.0/src/terminal.go      2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/src/terminal.go      2025-07-06 15:11:36.000000000 +0200
@@ -450,31 +450,35 @@
        return a[i].at.Before(a[j].at)
 }
 
+// EventTypes are listed in the order of their priority.
 const (
-       reqPrompt util.EventType = iota
+       reqResize util.EventType = iota
+       reqReinit
+       reqFullRedraw
+       reqRedraw
+
+       reqJump
+       reqPrompt
        reqInfo
        reqHeader
        reqFooter
        reqList
-       reqJump
-       reqActivate
-       reqReinit
-       reqFullRedraw
-       reqResize
-       reqRedraw
        reqRedrawInputLabel
        reqRedrawHeaderLabel
        reqRedrawFooterLabel
        reqRedrawListLabel
        reqRedrawBorderLabel
        reqRedrawPreviewLabel
-       reqClose
-       reqPrintQuery
+
        reqPreviewReady
        reqPreviewEnqueue
        reqPreviewDisplay
        reqPreviewRefresh
        reqPreviewDelayed
+
+       reqActivate
+       reqClose
+       reqPrintQuery
        reqBecome
        reqQuit
        reqFatal
@@ -1624,14 +1628,12 @@
        return needFullRedraw
 }
 
-func (t *Terminal) changeFooter(footer string) bool {
+func (t *Terminal) changeFooter(footer string) {
        var lines []string
        if len(footer) > 0 {
                lines = strings.Split(strings.TrimSuffix(footer, "\n"), "\n")
        }
-       needFullRedraw := len(t.footer) != len(lines)
        t.footer = lines
-       return needFullRedraw
 }
 
 // UpdateHeader updates the header
@@ -1678,12 +1680,12 @@
                        // Trimmed by --tail: filter selection by index
                        filtered := make(map[int32]selectedItem)
                        minIndex := merger.minIndex
-                       maxIndex := minIndex + int32(merger.Length())
+                       maxIndex := merger.maxIndex
                        for k, v := range t.selected {
                                var included bool
                                if maxIndex > minIndex {
                                        included = k >= minIndex && k < maxIndex
-                               } else { // int32 overflow [==>   <==]
+                               } else if maxIndex < minIndex { // int32 
overflow [==>   <==]
                                        included = k >= minIndex || k < maxIndex
                                }
                                if included {
@@ -2889,19 +2891,29 @@
                return true
        }
 
+       // Check footer window
+       if len(t.footer) > 0 && (t.footerWindow == nil || 
t.footerWindow.Height() != len(t.footer)) ||
+               len(t.footer) == 0 && t.footerWindow != nil {
+               t.printAll()
+               return true
+       }
+
        // Check if the header borders are used and header has changed
        allHeaderLines := t.visibleHeaderLines()
        primaryHeaderLines := allHeaderLines
-       if t.hasHeaderLinesWindow() {
+       needHeaderWindow := t.hasHeaderWindow()
+       needHeaderLinesWindow := t.hasHeaderLinesWindow()
+       if needHeaderLinesWindow {
                primaryHeaderLines -= t.headerLines
        }
        // FIXME: Full redraw is triggered if there are too many lines in the 
header
        // so that the header window cannot display all of them.
-       needHeaderLinesWindow := t.hasHeaderLinesWindow()
-       if (t.headerBorderShape.Visible() || needHeaderLinesWindow) &&
-               (t.headerWindow == nil && primaryHeaderLines > 0 || 
t.headerWindow != nil && primaryHeaderLines != t.headerWindow.Height()) ||
-               needHeaderLinesWindow && (t.headerLinesWindow == nil || 
t.headerLinesWindow != nil && t.headerLines != t.headerLinesWindow.Height()) ||
-               !needHeaderLinesWindow && t.headerLinesWindow != nil {
+       if (needHeaderWindow && t.headerWindow == nil) ||
+               (!needHeaderWindow && t.headerWindow != nil) ||
+               (needHeaderWindow && t.headerWindow != nil && 
primaryHeaderLines != t.headerWindow.Height()) ||
+               (needHeaderLinesWindow && t.headerLinesWindow == nil) ||
+               (!needHeaderLinesWindow && t.headerLinesWindow != nil) ||
+               (needHeaderLinesWindow && t.headerLinesWindow != nil && 
t.headerLines != t.headerLinesWindow.Height()) {
                t.printAll()
                return true
        }
@@ -5116,6 +5128,8 @@
                                t.uiMutex.Lock()
                                t.mutex.Lock()
                                info := false
+                               header := false
+                               footer := false
                                for _, key := range keys {
                                        req := util.EventType(key)
                                        value := (*events)[req]
@@ -5153,13 +5167,9 @@
                                                }
                                                t.printList()
                                        case reqHeader:
-                                               if !t.resizeIfNeeded() {
-                                                       t.printHeader()
-                                               }
+                                               header = true
                                        case reqFooter:
-                                               if !t.resizeIfNeeded() {
-                                                       t.printFooter()
-                                               }
+                                               footer = true
                                        case reqActivate:
                                                t.suppress = false
                                                if t.hasPreviewer() {
@@ -5177,10 +5187,10 @@
                                                t.printLabel(t.border, 
t.borderLabel, t.borderLabelOpts, t.borderLabelLen, t.borderShape, true)
                                        case reqRedrawPreviewLabel:
                                                t.printLabel(t.pborder, 
t.previewLabel, t.previewLabelOpts, t.previewLabelLen, 
t.activePreviewOpts.Border(), true)
-                                       case reqReinit:
-                                               t.tui.Resume(t.fullscreen, true)
-                                               t.fullRedraw()
-                                       case reqResize, reqFullRedraw, 
reqRedraw:
+                                       case reqReinit, reqResize, 
reqFullRedraw, reqRedraw:
+                                               if req == reqReinit {
+                                                       
t.tui.Resume(t.fullscreen, true)
+                                               }
                                                if req == reqResize {
                                                        t.termSize = 
t.tui.Size()
                                                }
@@ -5243,8 +5253,16 @@
                                                return
                                        }
                                }
-                               if info && !t.resizeIfNeeded() {
-                                       t.printInfo()
+                               if (info || header || footer) && 
!t.resizeIfNeeded() {
+                                       if info {
+                                               t.printInfo()
+                                       }
+                                       if header {
+                                               t.printHeader()
+                                       }
+                                       if footer {
+                                               t.printFooter()
+                                       }
                                }
                                t.flush()
                                t.mutex.Unlock()
@@ -5384,6 +5402,7 @@
                }
                previousInput := t.input
                previousCx := t.cx
+               previousVersion := t.version
                t.lastKey = event.KeyName()
                updatePreviewWindow := func(forcePreview bool) {
                        t.resizeWindows(forcePreview, false)
@@ -5670,24 +5689,17 @@
                                t.cx = len(t.input)
                        case actChangeHeader, actTransformHeader, 
actBgTransformHeader:
                                capture(false, func(header string) {
+                                       // When a dedicated header window is 
not used, we may need to
+                                       // update other elements as well.
                                        if t.changeHeader(header) {
-                                               if t.headerWindow != nil {
-                                                       // Need to resize 
header window
-                                                       req(reqRedraw)
-                                               } else {
-                                                       req(reqHeader, reqList, 
reqPrompt, reqInfo)
-                                               }
-                                       } else {
-                                               req(reqHeader)
+                                               req(reqList, reqPrompt, reqInfo)
                                        }
+                                       req(reqHeader)
                                })
                        case actChangeFooter, actTransformFooter, 
actBgTransformFooter:
                                capture(false, func(footer string) {
-                                       if t.changeFooter(footer) {
-                                               req(reqRedraw)
-                                       } else {
-                                               req(reqFooter)
-                                       }
+                                       t.changeFooter(footer)
+                                       req(reqFooter)
                                })
                        case actChangeHeaderLabel, actTransformHeaderLabel, 
actBgTransformHeaderLabel:
                                capture(true, func(label string) {
@@ -6648,6 +6660,9 @@
                        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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/src/tui/eventtype_string.go 
new/fzf-0.64.0/src/tui/eventtype_string.go
--- old/fzf-0.63.0/src/tui/eventtype_string.go  2025-06-27 18:11:00.000000000 
+0200
+++ new/fzf-0.64.0/src/tui/eventtype_string.go  2025-07-06 15:11:36.000000000 
+0200
@@ -110,11 +110,12 @@
        _ = x[Jump-99]
        _ = x[JumpCancel-100]
        _ = x[ClickHeader-101]
+       _ = x[Multi-102]
 }
 
-const _EventType_name = 
"RuneCtrlACtrlBCtrlCCtrlDCtrlECtrlFCtrlGCtrlHTabCtrlJCtrlKCtrlLEnterCtrlNCtrlOCtrlPCtrlQCtrlRCtrlSCtrlTCtrlUCtrlVCtrlWCtrlXCtrlYCtrlZEscCtrlSpaceCtrlDeleteCtrlBackSlashCtrlRightBracketCtrlCaretCtrlSlashShiftTabBackspaceDeletePageUpPageDownUpDownLeftRightHomeEndInsertShiftUpShiftDownShiftLeftShiftRightShiftDeleteF1F2F3F4F5F6F7F8F9F10F11F12AltBackspaceAltUpAltDownAltLeftAltRightAltShiftUpAltShiftDownAltShiftLeftAltShiftRightAltCtrlAltInvalidFatalBracketedPasteBeginBracketedPasteEndMouseDoubleClickLeftClickRightClickSLeftClickSRightClickScrollUpScrollDownSScrollUpSScrollDownPreviewScrollUpPreviewScrollDownResizeChangeBackwardEOFStartLoadFocusOneZeroResultJumpJumpCancelClickHeader"
+const _EventType_name = 
"RuneCtrlACtrlBCtrlCCtrlDCtrlECtrlFCtrlGCtrlHTabCtrlJCtrlKCtrlLEnterCtrlNCtrlOCtrlPCtrlQCtrlRCtrlSCtrlTCtrlUCtrlVCtrlWCtrlXCtrlYCtrlZEscCtrlSpaceCtrlDeleteCtrlBackSlashCtrlRightBracketCtrlCaretCtrlSlashShiftTabBackspaceDeletePageUpPageDownUpDownLeftRightHomeEndInsertShiftUpShiftDownShiftLeftShiftRightShiftDeleteF1F2F3F4F5F6F7F8F9F10F11F12AltBackspaceAltUpAltDownAltLeftAltRightAltShiftUpAltShiftDownAltShiftLeftAltShiftRightAltCtrlAltInvalidFatalBracketedPasteBeginBracketedPasteEndMouseDoubleClickLeftClickRightClickSLeftClickSRightClickScrollUpScrollDownSScrollUpSScrollDownPreviewScrollUpPreviewScrollDownResizeChangeBackwardEOFStartLoadFocusOneZeroResultJumpJumpCancelClickHeaderMulti"
 
-var _EventType_index = [...]uint16{0, 4, 9, 14, 19, 24, 29, 34, 39, 44, 47, 
52, 57, 62, 67, 72, 77, 82, 87, 92, 97, 102, 107, 112, 117, 122, 127, 132, 135, 
144, 154, 167, 183, 192, 201, 209, 218, 224, 230, 238, 240, 244, 248, 253, 257, 
260, 266, 273, 282, 291, 301, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 
333, 336, 339, 351, 356, 363, 370, 378, 388, 400, 412, 425, 428, 435, 442, 447, 
466, 483, 488, 499, 508, 518, 528, 539, 547, 557, 566, 577, 592, 609, 615, 621, 
632, 637, 641, 646, 649, 653, 659, 663, 673, 684}
+var _EventType_index = [...]uint16{0, 4, 9, 14, 19, 24, 29, 34, 39, 44, 47, 
52, 57, 62, 67, 72, 77, 82, 87, 92, 97, 102, 107, 112, 117, 122, 127, 132, 135, 
144, 154, 167, 183, 192, 201, 209, 218, 224, 230, 238, 240, 244, 248, 253, 257, 
260, 266, 273, 282, 291, 301, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 
333, 336, 339, 351, 356, 363, 370, 378, 388, 400, 412, 425, 428, 435, 442, 447, 
466, 483, 488, 499, 508, 518, 528, 539, 547, 557, 566, 577, 592, 609, 615, 621, 
632, 637, 641, 646, 649, 653, 659, 663, 673, 684, 689}
 
 func (i EventType) String() string {
        if i < 0 || i >= EventType(len(_EventType_index)-1) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/src/tui/tui.go 
new/fzf-0.64.0/src/tui/tui.go
--- old/fzf-0.63.0/src/tui/tui.go       2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/src/tui/tui.go       2025-07-06 15:11:36.000000000 +0200
@@ -132,6 +132,7 @@
        Jump
        JumpCancel
        ClickHeader
+       Multi
 )
 
 func (t EventType) AsEvent() Event {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fzf-0.63.0/test/test_core.rb 
new/fzf-0.64.0/test/test_core.rb
--- old/fzf-0.63.0/test/test_core.rb    2025-06-27 18:11:00.000000000 +0200
+++ new/fzf-0.64.0/test/test_core.rb    2025-07-06 15:11:36.000000000 +0200
@@ -1930,7 +1930,10 @@
 
   def test_change_header_on_header_window
     tmux.send_keys %(seq 100 | #{FZF} --list-border --input-border --bind 
'start:change-header(foo),space:change-header(bar)'), :Enter
-    tmux.until { |lines| assert lines.any_include?('foo') }
+    tmux.until do |lines|
+      assert lines.any_include?('100/100')
+      assert lines.any_include?('foo')
+    end
     tmux.send_keys :Space
     tmux.until { |lines| assert lines.any_include?('bar') }
   end
@@ -1981,4 +1984,55 @@
       refute lines.any_include?('[1]')
     end
   end
+
+  def test_render_order
+    tmux.send_keys %(seq 100 | #{FZF} --bind='focus:preview(echo 
boom)+change-footer(bam)'), :Enter
+    tmux.until { assert_equal 100, it.match_count }
+    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
+
+  def test_preserve_selection_on_revision_bump
+    tmux.send_keys %(seq 100 | #{FZF} --multi --sync --query "'1" --bind 
'a:select-all+change-header(pressed a),b:change-header(pressed 
b)+change-nth(1),c:exclude'), :Enter
+    tmux.until do
+      assert_equal 20, it.match_count
+      assert_equal 0, it.select_count
+    end
+    tmux.send_keys :a
+    tmux.until do
+      assert_equal 20, it.match_count
+      assert_equal 20, it.select_count
+      assert it.any_include?('pressed a')
+    end
+    tmux.send_keys :b
+    tmux.until do
+      assert_equal 20, it.match_count
+      assert_equal 20, it.select_count
+      refute it.any_include?('pressed a')
+      assert it.any_include?('pressed b')
+    end
+    tmux.send_keys :a
+    tmux.until do
+      assert_equal 20, it.match_count
+      assert_equal 20, it.select_count
+      assert it.any_include?('pressed a')
+      refute it.any_include?('pressed b')
+    end
+    tmux.send_keys :c
+    tmux.until do
+      assert_equal 19, it.match_count
+      assert_equal 19, it.select_count
+    end
+  end
 end

Reply via email to