summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md8
-rw-r--r--man/man1/fzf.12
-rw-r--r--src/actiontype_string.go187
-rw-r--r--src/options.go6
-rw-r--r--src/terminal.go14
-rwxr-xr-xtest/test_go.rb19
6 files changed, 142 insertions, 94 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index df2db318..51e9a603 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,14 @@
CHANGELOG
=========
+0.51.0
+------
+- Added `change-multi` action for dynamically changing `--multi` option
+ - `change-multi` - enable multi-select mode with no limit
+ - `change-multi(NUM)` - enable multi-select mode with a limit
+ - `change-multi(0)` - disable multi-select mode
+- Bug fixes and improvements
+
0.50.0
------
- Search performance optimization. You can observe 50%+ improvement in some scenarios.
diff --git a/man/man1/fzf.1 b/man/man1/fzf.1
index 0d131c7a..458c6a5f 100644
--- a/man/man1/fzf.1
+++ b/man/man1/fzf.1
@@ -1282,6 +1282,8 @@ A key or an event can be bound to one or more of the following actions.
\fBcancel\fR (clear query string if not empty, abort fzf otherwise)
\fBchange-border-label(...)\fR (change \fB--border-label\fR to the given string)
\fBchange-header(...)\fR (change header to the given string; doesn't affect \fB--header-lines\fR)
+ \fBchange-multi\fR (enable multi-select mode with no limit)
+ \fBchange-multi(...)\fR (enable multi-select mode with a limit or disable it with 0)
\fBchange-preview(...)\fR (change \fB--preview\fR option)
\fBchange-preview-label(...)\fR (change \fB--preview-label\fR to the given string)
\fBchange-preview-window(...)\fR (change \fB--preview-window\fR option; rotate through the multiple option sets separated by '|')
diff --git a/src/actiontype_string.go b/src/actiontype_string.go
index 341c4bd4..a9d931d7 100644
--- a/src/actiontype_string.go
+++ b/src/actiontype_string.go
@@ -26,102 +26,103 @@ func _() {
_ = x[actCancel-15]
_ = x[actChangeBorderLabel-16]
_ = x[actChangeHeader-17]
- _ = x[actChangePreviewLabel-18]
- _ = x[actChangePrompt-19]
- _ = x[actChangeQuery-20]
- _ = x[actClearScreen-21]
- _ = x[actClearQuery-22]
- _ = x[actClearSelection-23]
- _ = x[actClose-24]
- _ = x[actDeleteChar-25]
- _ = x[actDeleteCharEof-26]
- _ = x[actEndOfLine-27]
- _ = x[actForwardChar-28]
- _ = x[actForwardWord-29]
- _ = x[actKillLine-30]
- _ = x[actKillWord-31]
- _ = x[actUnixLineDiscard-32]
- _ = x[actUnixWordRubout-33]
- _ = x[actYank-34]
- _ = x[actBackwardKillWord-35]
- _ = x[actSelectAll-36]
- _ = x[actDeselectAll-37]
- _ = x[actToggle-38]
- _ = x[actToggleSearch-39]
- _ = x[actToggleAll-40]
- _ = x[actToggleDown-41]
- _ = x[actToggleUp-42]
- _ = x[actToggleIn-43]
- _ = x[actToggleOut-44]
- _ = x[actToggleTrack-45]
- _ = x[actToggleTrackCurrent-46]
- _ = x[actToggleHeader-47]
- _ = x[actTrackCurrent-48]
- _ = x[actUntrackCurrent-49]
- _ = x[actDown-50]
- _ = x[actUp-51]
- _ = x[actPageUp-52]
- _ = x[actPageDown-53]
- _ = x[actPosition-54]
- _ = x[actHalfPageUp-55]
- _ = x[actHalfPageDown-56]
- _ = x[actOffsetUp-57]
- _ = x[actOffsetDown-58]
- _ = x[actJump-59]
- _ = x[actJumpAccept-60]
- _ = x[actPrintQuery-61]
- _ = x[actRefreshPreview-62]
- _ = x[actReplaceQuery-63]
- _ = x[actToggleSort-64]
- _ = x[actShowPreview-65]
- _ = x[actHidePreview-66]
- _ = x[actTogglePreview-67]
- _ = x[actTogglePreviewWrap-68]
- _ = x[actTransform-69]
- _ = x[actTransformBorderLabel-70]
- _ = x[actTransformHeader-71]
- _ = x[actTransformPreviewLabel-72]
- _ = x[actTransformPrompt-73]
- _ = x[actTransformQuery-74]
- _ = x[actPreview-75]
- _ = x[actChangePreview-76]
- _ = x[actChangePreviewWindow-77]
- _ = x[actPreviewTop-78]
- _ = x[actPreviewBottom-79]
- _ = x[actPreviewUp-80]
- _ = x[actPreviewDown-81]
- _ = x[actPreviewPageUp-82]
- _ = x[actPreviewPageDown-83]
- _ = x[actPreviewHalfPageUp-84]
- _ = x[actPreviewHalfPageDown-85]
- _ = x[actPrevHistory-86]
- _ = x[actPrevSelected-87]
- _ = x[actPut-88]
- _ = x[actNextHistory-89]
- _ = x[actNextSelected-90]
- _ = x[actExecute-91]
- _ = x[actExecuteSilent-92]
- _ = x[actExecuteMulti-93]
- _ = x[actSigStop-94]
- _ = x[actFirst-95]
- _ = x[actLast-96]
- _ = x[actReload-97]
- _ = x[actReloadSync-98]
- _ = x[actDisableSearch-99]
- _ = x[actEnableSearch-100]
- _ = x[actSelect-101]
- _ = x[actDeselect-102]
- _ = x[actUnbind-103]
- _ = x[actRebind-104]
- _ = x[actBecome-105]
- _ = x[actResponse-106]
- _ = x[actShowHeader-107]
- _ = x[actHideHeader-108]
+ _ = x[actChangeMulti-18]
+ _ = x[actChangePreviewLabel-19]
+ _ = x[actChangePrompt-20]
+ _ = x[actChangeQuery-21]
+ _ = x[actClearScreen-22]
+ _ = x[actClearQuery-23]
+ _ = x[actClearSelection-24]
+ _ = x[actClose-25]
+ _ = x[actDeleteChar-26]
+ _ = x[actDeleteCharEof-27]
+ _ = x[actEndOfLine-28]
+ _ = x[actForwardChar-29]
+ _ = x[actForwardWord-30]
+ _ = x[actKillLine-31]
+ _ = x[actKillWord-32]
+ _ = x[actUnixLineDiscard-33]
+ _ = x[actUnixWordRubout-34]
+ _ = x[actYank-35]
+ _ = x[actBackwardKillWord-36]
+ _ = x[actSelectAll-37]
+ _ = x[actDeselectAll-38]
+ _ = x[actToggle-39]
+ _ = x[actToggleSearch-40]
+ _ = x[actToggleAll-41]
+ _ = x[actToggleDown-42]
+ _ = x[actToggleUp-43]
+ _ = x[actToggleIn-44]
+ _ = x[actToggleOut-45]
+ _ = x[actToggleTrack-46]
+ _ = x[actToggleTrackCurrent-47]
+ _ = x[actToggleHeader-48]
+ _ = x[actTrackCurrent-49]
+ _ = x[actUntrackCurrent-50]
+ _ = x[actDown-51]
+ _ = x[actUp-52]
+ _ = x[actPageUp-53]
+ _ = x[actPageDown-54]
+ _ = x[actPosition-55]
+ _ = x[actHalfPageUp-56]
+ _ = x[actHalfPageDown-57]
+ _ = x[actOffsetUp-58]
+ _ = x[actOffsetDown-59]
+ _ = x[actJump-60]
+ _ = x[actJumpAccept-61]
+ _ = x[actPrintQuery-62]
+ _ = x[actRefreshPreview-63]
+ _ = x[actReplaceQuery-64]
+ _ = x[actToggleSort-65]
+ _ = x[actShowPreview-66]
+ _ = x[actHidePreview-67]
+ _ = x[actTogglePreview-68]
+ _ = x[actTogglePreviewWrap-69]
+ _ = x[actTransform-70]
+ _ = x[actTransformBorderLabel-71]
+ _ = x[actTransformHeader-72]
+ _ = x[actTransformPreviewLabel-73]
+ _ = x[actTransformPrompt-74]
+ _ = x[actTransformQuery-75]
+ _ = x[actPreview-76]
+ _ = x[actChangePreview-77]
+ _ = x[actChangePreviewWindow-78]
+ _ = x[actPreviewTop-79]
+ _ = x[actPreviewBottom-80]
+ _ = x[actPreviewUp-81]
+ _ = x[actPreviewDown-82]
+ _ = x[actPreviewPageUp-83]
+ _ = x[actPreviewPageDown-84]
+ _ = x[actPreviewHalfPageUp-85]
+ _ = x[actPreviewHalfPageDown-86]
+ _ = x[actPrevHistory-87]
+ _ = x[actPrevSelected-88]
+ _ = x[actPut-89]
+ _ = x[actNextHistory-90]
+ _ = x[actNextSelected-91]
+ _ = x[actExecute-92]
+ _ = x[actExecuteSilent-93]
+ _ = x[actExecuteMulti-94]
+ _ = x[actSigStop-95]
+ _ = x[actFirst-96]
+ _ = x[actLast-97]
+ _ = x[actReload-98]
+ _ = x[actReloadSync-99]
+ _ = x[actDisableSearch-100]
+ _ = x[actEnableSearch-101]
+ _ = x[actSelect-102]
+ _ = x[actDeselect-103]
+ _ = x[actUnbind-104]
+ _ = x[actRebind-105]
+ _ = x[actBecome-106]
+ _ = x[actResponse-107]
+ _ = x[actShowHeader-108]
+ _ = x[actHideHeader-109]
}
-const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeHeaderactChangePreviewLabelactChangePromptactChangeQueryactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformHeaderactTransformPreviewLabelactTransformPromptactTransformQueryactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactBecomeactResponseactShowHeaderactHideHeader"
+const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeHeaderactChangeMultiactChangePreviewLabelactChangePromptactChangeQueryactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformHeaderactTransformPreviewLabelactTransformPromptactTransformQueryactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactBecomeactResponseactShowHeaderactHideHeader"
-var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 42, 50, 68, 76, 85, 102, 123, 138, 159, 183, 198, 207, 227, 242, 263, 278, 292, 306, 319, 336, 344, 357, 373, 385, 399, 413, 424, 435, 453, 470, 477, 496, 508, 522, 531, 546, 558, 571, 582, 593, 605, 619, 640, 655, 670, 687, 694, 699, 708, 719, 730, 743, 758, 769, 782, 789, 802, 815, 832, 847, 860, 874, 888, 904, 924, 936, 959, 977, 1001, 1019, 1036, 1046, 1062, 1084, 1097, 1113, 1125, 1139, 1155, 1173, 1193, 1215, 1229, 1244, 1250, 1264, 1279, 1289, 1305, 1320, 1330, 1338, 1345, 1354, 1367, 1383, 1398, 1407, 1418, 1427, 1436, 1445, 1456, 1469, 1482}
+var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 42, 50, 68, 76, 85, 102, 123, 138, 159, 183, 198, 207, 227, 242, 256, 277, 292, 306, 320, 333, 350, 358, 371, 387, 399, 413, 427, 438, 449, 467, 484, 491, 510, 522, 536, 545, 560, 572, 585, 596, 607, 619, 633, 654, 669, 684, 701, 708, 713, 722, 733, 744, 757, 772, 783, 796, 803, 816, 829, 846, 861, 874, 888, 902, 918, 938, 950, 973, 991, 1015, 1033, 1050, 1060, 1076, 1098, 1111, 1127, 1139, 1153, 1169, 1187, 1207, 1229, 1243, 1258, 1264, 1278, 1293, 1303, 1319, 1334, 1344, 1352, 1359, 1368, 1381, 1397, 1412, 1421, 1432, 1441, 1450, 1459, 1470, 1483, 1496}
func (i actionType) String() string {
if i < 0 || i >= actionType(len(_actionType_index)-1) {
diff --git a/src/options.go b/src/options.go
index 4ba8538f..c8a3fa15 100644
--- a/src/options.go
+++ b/src/options.go
@@ -1055,7 +1055,7 @@ const (
func init() {
executeRegexp = regexp.MustCompile(
- `(?si)[:+](become|execute(?:-multi|-silent)?|reload(?:-sync)?|preview|(?:change|transform)-(?:header|query|prompt|border-label|preview-label)|transform|change-preview-window|change-preview|(?:re|un)bind|pos|put)`)
+ `(?si)[:+](become|execute(?:-multi|-silent)?|reload(?:-sync)?|preview|(?:change|transform)-(?:header|query|prompt|border-label|preview-label)|transform|change-(?:preview-window|preview|multi)|(?:re|un)bind|pos|put)`)
splitRegexp = regexp.MustCompile("[,:]+")
actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+")
}
@@ -1306,6 +1306,8 @@ func parseActionList(masked string, original string, prevActions []*action, putA
if t == actIgnore {
if specIndex == 0 && specLower == "" {
actions = append(prevActions, actions...)
+ } else if specLower == "change-multi" {
+ appendAction(actChangeMulti)
} else {
exit("unknown action: " + spec)
}
@@ -1407,6 +1409,8 @@ func isExecuteAction(str string) actionType {
return actChangePrompt
case "change-query":
return actChangeQuery
+ case "change-multi":
+ return actChangeMulti
case "pos":
return actPosition
case "execute":
diff --git a/src/terminal.go b/src/terminal.go
index b885ce25..25f30150 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -367,6 +367,7 @@ const (
actCancel
actChangeBorderLabel
actChangeHeader
+ actChangeMulti
actChangePreviewLabel
actChangePrompt
actChangeQuery
@@ -3489,6 +3490,19 @@ func (t *Terminal) Loop() {
}
case actPrintQuery:
req(reqPrintQuery)
+ case actChangeMulti:
+ multi := t.multi
+ if a.a == "" {
+ multi = maxMulti
+ } else if n, e := strconv.Atoi(a.a); e == nil && n >= 0 {
+ multi = n
+ }
+ if t.multi > 0 && multi != t.multi {
+ t.selected = make(map[int32]selectedItem)
+ t.version++
+ }
+ t.multi = multi
+ req(reqList, reqInfo)
case actChangeQuery:
t.input = []rune(a.a)
t.cx = len(t.input)
diff --git a/test/test_go.rb b/test/test_go.rb
index ba067997..b08ac72b 100755
--- a/test/test_go.rb
+++ b/test/test_go.rb
@@ -425,6 +425,25 @@ class TestGoFZF < TestBase
end
end
+ def test_multi_action
+ tmux.send_keys "seq 10 | #{FZF} --bind 'a:change-multi,b:change-multi(3),c:change-multi(xxx),d:change-multi(0)'", :Enter
+ tmux.until { |lines| assert_equal 10, lines.item_count }
+ tmux.until { |lines| assert lines[-2]&.start_with?(' 10/10 ') }
+ tmux.send_keys 'a'
+ tmux.until { |lines| assert lines[-2]&.start_with?(' 10/10 (0)') }
+ tmux.send_keys 'b'
+ tmux.until { |lines| assert lines[-2]&.start_with?(' 10/10 (0/3)') }
+ tmux.send_keys :BTab
+ tmux.until { |lines| assert lines[-2]&.start_with?(' 10/10 (1/3)') }
+ tmux.send_keys 'c'
+ tmux.send_keys :BTab
+ tmux.until { |lines| assert lines[-2]&.start_with?(' 10/10 (2/3)') }
+ tmux.send_keys 'd'
+ tmux.until do |lines|
+ assert lines[-2]&.start_with?(' 10/10 ') && !lines[-2]&.include?('(')
+ end
+ end
+
def test_with_nth
[true, false].each do |multi|
tmux.send_keys "(echo ' 1st 2nd 3rd/';