From e1e171a3c458b8bc7dc347cbbd89be30f490ffb8 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Sat, 1 Feb 2025 11:12:59 +0900 Subject: [PATCH] Add toggle-bind --- CHANGELOG.md | 1 + man/man1/fzf.1 | 1 + src/actiontype_string.go | 13 +++++++------ src/options.go | 6 ++++-- src/terminal.go | 11 +++++++++++ test/test_core.rb | 8 ++++++-- 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4250b42..e2a14101 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ CHANGELOG # Press CTRL-Y to copy the current line to the clipboard and ring the bell fzf --bind 'ctrl-y:execute-silent(echo -n {} | pbcopy)+bell' ``` +- Added `toggle-bind` action - Bug fixes and improvements - Fixed fish script to support fish 3.1.2 or later (@bitraid) diff --git a/man/man1/fzf.1 b/man/man1/fzf.1 index 3a8a107f..0b3cabfc 100644 --- a/man/man1/fzf.1 +++ b/man/man1/fzf.1 @@ -1643,6 +1643,7 @@ A key or an event can be bound to one or more of the following actions. \fBtoggle\-all\fR (toggle all matches) \fBtoggle\-in\fR (\fB\-\-layout=reverse*\fR ? \fBtoggle+up\fR : \fBtoggle+down\fR) \fBtoggle\-out\fR (\fB\-\-layout=reverse*\fR ? \fBtoggle+down\fR : \fBtoggle+up\fR) + \fBtoggle\-bind\fR \fBtoggle\-header\fR \fBtoggle\-hscroll\fR \fBtoggle\-multi\-line\fR diff --git a/src/actiontype_string.go b/src/actiontype_string.go index b37446c5..123c0651 100644 --- a/src/actiontype_string.go +++ b/src/actiontype_string.go @@ -130,15 +130,16 @@ func _() { _ = x[actDeselect-119] _ = x[actUnbind-120] _ = x[actRebind-121] - _ = x[actBecome-122] - _ = x[actShowHeader-123] - _ = x[actHideHeader-124] - _ = x[actBell-125] + _ = x[actToggleBind-122] + _ = x[actBecome-123] + _ = x[actShowHeader-124] + _ = x[actHideHeader-125] + _ = x[actBell-126] } -const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeListLabelactChangeInputLabelactChangeHeaderactChangeHeaderLabelactChangeMultiactChangePreviewLabelactChangePromptactChangeQueryactChangeNthactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleMultiLineactToggleHscrollactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformListLabelactTransformInputLabelactTransformHeaderactTransformHeaderLabelactTransformNthactTransformPreviewLabelactTransformPromptactTransformQueryactTransformSearchactSearchactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactBecomeactShowHeaderactHideHeaderactBell" +const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeListLabelactChangeInputLabelactChangeHeaderactChangeHeaderLabelactChangeMultiactChangePreviewLabelactChangePromptactChangeQueryactChangeNthactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleMultiLineactToggleHscrollactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformListLabelactTransformInputLabelactTransformHeaderactTransformHeaderLabelactTransformNthactTransformPreviewLabelactTransformPromptactTransformQueryactTransformSearchactSearchactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactToggleBindactBecomeactShowHeaderactHideHeaderactBell" -var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 42, 50, 68, 76, 85, 102, 123, 138, 159, 183, 198, 207, 227, 245, 264, 279, 299, 313, 334, 349, 363, 375, 389, 402, 419, 427, 440, 456, 468, 476, 490, 504, 515, 526, 544, 561, 568, 587, 599, 613, 622, 637, 649, 662, 673, 684, 696, 710, 731, 746, 759, 777, 793, 808, 825, 832, 837, 846, 857, 868, 881, 896, 907, 920, 935, 942, 955, 968, 985, 1000, 1013, 1027, 1041, 1057, 1077, 1089, 1112, 1133, 1155, 1173, 1196, 1211, 1235, 1253, 1270, 1288, 1297, 1307, 1323, 1345, 1358, 1374, 1386, 1400, 1416, 1434, 1454, 1476, 1490, 1505, 1513, 1519, 1533, 1548, 1558, 1574, 1589, 1599, 1607, 1614, 1623, 1636, 1652, 1667, 1676, 1687, 1696, 1705, 1714, 1727, 1740, 1747} +var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 42, 50, 68, 76, 85, 102, 123, 138, 159, 183, 198, 207, 227, 245, 264, 279, 299, 313, 334, 349, 363, 375, 389, 402, 419, 427, 440, 456, 468, 476, 490, 504, 515, 526, 544, 561, 568, 587, 599, 613, 622, 637, 649, 662, 673, 684, 696, 710, 731, 746, 759, 777, 793, 808, 825, 832, 837, 846, 857, 868, 881, 896, 907, 920, 935, 942, 955, 968, 985, 1000, 1013, 1027, 1041, 1057, 1077, 1089, 1112, 1133, 1155, 1173, 1196, 1211, 1235, 1253, 1270, 1288, 1297, 1307, 1323, 1345, 1358, 1374, 1386, 1400, 1416, 1434, 1454, 1476, 1490, 1505, 1513, 1519, 1533, 1548, 1558, 1574, 1589, 1599, 1607, 1614, 1623, 1636, 1652, 1667, 1676, 1687, 1696, 1705, 1718, 1727, 1740, 1753, 1760} 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 fec9596c..a22916e3 100644 --- a/src/options.go +++ b/src/options.go @@ -1336,7 +1336,7 @@ const ( func init() { executeRegexp = regexp.MustCompile( - `(?si)[:+](become|execute(?:-multi|-silent)?|reload(?:-sync)?|preview|(?:change|transform)-(?:query|prompt|(?:border|list|preview|input|header)-label|header|search|nth)|transform|change-(?:preview-window|preview|multi)|(?:re|un)bind|pos|put|print|search)`) + `(?si)[:+](become|execute(?:-multi|-silent)?|reload(?:-sync)?|preview|(?:change|transform)-(?:query|prompt|(?:border|list|preview|input|header)-label|header|search|nth)|transform|change-(?:preview-window|preview|multi)|(?:re|un|toggle-)bind|pos|put|print|search)`) splitRegexp = regexp.MustCompile("[,:]+") actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+") } @@ -1620,7 +1620,7 @@ func parseActionList(masked string, original string, prevActions []*action, putA actions = append(actions, &action{t: t, a: actionArg}) } switch t { - case actUnbind, actRebind: + case actUnbind, actRebind, actToggleBind: if _, err := parseKeyChordsImpl(actionArg, spec[0:offset]+" target required"); err != nil { return nil, err } @@ -1705,6 +1705,8 @@ func isExecuteAction(str string) actionType { return actUnbind case "rebind": return actRebind + case "toggle-bind": + return actToggleBind case "preview": return actPreview case "change-header": diff --git a/src/terminal.go b/src/terminal.go index d75f8a6d..d6e7eadc 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -569,6 +569,7 @@ const ( actDeselect actUnbind actRebind + actToggleBind actBecome actShowHeader actHideHeader @@ -5761,6 +5762,16 @@ func (t *Terminal) Loop() error { } } } + case actToggleBind: + if keys, err := parseKeyChords(a.a, "PANIC"); err == nil { + for key := range keys { + if _, bound := t.keymap[key]; bound { + delete(t.keymap, key) + } else if originalAction, found := t.keymapOrg[key]; found { + t.keymap[key] = originalAction + } + } + } case actChangePreview: if t.previewOpts.command != a.a { t.previewOpts.command = a.a diff --git a/test/test_core.rb b/test/test_core.rb index 5e47ef9d..893d040b 100644 --- a/test/test_core.rb +++ b/test/test_core.rb @@ -1174,8 +1174,8 @@ class TestCore < TestInteractive tmux.until { |lines| assert_equal 2, lines.select_count } end - def test_unbind_rebind - tmux.send_keys "seq 100 | #{FZF} --bind 'c:clear-query,d:unbind(c,d),e:rebind(c,d)'", :Enter + def test_unbind_rebind_toggle_bind + tmux.send_keys "seq 100 | #{FZF} --bind 'c:clear-query,d:unbind(c,d),e:rebind(c,d),f:toggle-bind(c)'", :Enter tmux.until { |lines| assert_equal 100, lines.match_count } tmux.send_keys 'ab' tmux.until { |lines| assert_equal '> ab', lines[-1] } @@ -1185,6 +1185,10 @@ class TestCore < TestInteractive tmux.until { |lines| assert_equal '> abcd', lines[-1] } tmux.send_keys 'ecabddc' tmux.until { |lines| assert_equal '> abdc', lines[-1] } + tmux.send_keys 'fcabfc' + tmux.until { |lines| assert_equal '> abc', lines[-1] } + tmux.send_keys 'fc' + tmux.until { |lines| assert_equal '>', lines[-1] } end def test_scroll_off