mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2025-02-01 19:48:31 +00:00
parent
0237bf09bf
commit
7220d8233e
47
ADVANCED.md
47
ADVANCED.md
@ -1,8 +1,8 @@
|
||||
Advanced fzf examples
|
||||
======================
|
||||
|
||||
* *Last update: 2024/06/24*
|
||||
* *Requires fzf 0.54.0 or later*
|
||||
* *Last update: 2025/01/26*
|
||||
* *Requires fzf 0.59.0 or later*
|
||||
|
||||
---
|
||||
|
||||
@ -22,6 +22,7 @@ Advanced fzf examples
|
||||
* [Switching to fzf-only search mode](#switching-to-fzf-only-search-mode)
|
||||
* [Switching between Ripgrep mode and fzf mode](#switching-between-ripgrep-mode-and-fzf-mode)
|
||||
* [Switching between Ripgrep mode and fzf mode using a single key binding](#switching-between-ripgrep-mode-and-fzf-mode-using-a-single-key-binding)
|
||||
* [Controlling Ripgrap search and fzf search simultaneously](#controlling-ripgrap-search-and-fzf-search-simultaneously)
|
||||
* [Log tailing](#log-tailing)
|
||||
* [Key bindings for git objects](#key-bindings-for-git-objects)
|
||||
* [Files listed in `git status`](#files-listed-in-git-status)
|
||||
@ -500,6 +501,48 @@ fzf --ansi --disabled --query "$INITIAL_QUERY" \
|
||||
--bind 'enter:become(vim {1} +{2})'
|
||||
```
|
||||
|
||||
### Controlling Ripgrap search and fzf search simultaneously
|
||||
|
||||
fzf 0.59.0 added `search` action that allows you to trigger an fzf search
|
||||
with an arbitrary query string. This means fzf is no longer restricted to the
|
||||
exact query entered in the prompt.
|
||||
|
||||
In the example below, `transform` action is used to conditionally trigger
|
||||
either `reload` for ripgrep or `search` for fzf. The first word of the query
|
||||
initiates the Ripgrep process to generate the initial results, while the
|
||||
remainder of the query is passed to fzf for secondary filtering.
|
||||
|
||||
```sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Switch between Ripgrep mode and fzf filtering mode (CTRL-T)
|
||||
RG_PREFIX="rg --column --line-number --no-heading --color=always --smart-case "
|
||||
INITIAL_QUERY="${*:-}"
|
||||
TRANSFORMER='
|
||||
words=($FZF_QUERY)
|
||||
|
||||
# If $FZF_QUERY contains multiple words, drop the first word,
|
||||
# and trigger fzf search with the rest
|
||||
if [[ ${#words[@]} -gt 1 ]]; then
|
||||
echo "search:${FZF_QUERY#* }"
|
||||
|
||||
# Otherwise, if the query does not end with a space,
|
||||
# restart ripgrep and reload the list
|
||||
elif ! [[ $FZF_QUERY =~ \ $ ]]; then
|
||||
echo "reload:sleep 0.1; $RG_PREFIX \"${words[0]}\" || true"
|
||||
fi
|
||||
'
|
||||
fzf --ansi --disabled --query "$INITIAL_QUERY" \
|
||||
--with-shell 'bash -c' \
|
||||
--bind "start:transform:$TRANSFORMER" \
|
||||
--bind "change:transform:$TRANSFORMER" \
|
||||
--color "hl:-1:underline,hl+:-1:underline:reverse" \
|
||||
--delimiter : \
|
||||
--preview 'bat --color=always {1} --highlight-line {2}' \
|
||||
--preview-window 'up,60%,border-bottom,+{2}+3/3,~3' \
|
||||
--bind 'enter:become(vim {1} +{2})'
|
||||
```
|
||||
|
||||
Log tailing
|
||||
-----------
|
||||
|
||||
|
21
CHANGELOG.md
21
CHANGELOG.md
@ -14,6 +14,27 @@ CHANGELOG
|
||||
--bind 'ctrl-r:reload(ps -ef)' --header 'Press CTRL-R to reload' \
|
||||
--header-lines-border bottom --no-list-border
|
||||
```
|
||||
- Added `search(...)` and `transform-search(...)` action to trigger an fzf search with an arbitrary query string. This can be used to extend the search syntax of fzf. In the following example, fzf will use the first word of the query to trigger ripgrep search, and use the rest of the query to perform fzf search within the result.
|
||||
```sh
|
||||
TRANSFORMER='
|
||||
words=($FZF_QUERY)
|
||||
|
||||
# If $FZF_QUERY contains multiple words, drop the first word,
|
||||
# and trigger fzf search with the rest
|
||||
if [[ ${#words[@]} -gt 1 ]]; then
|
||||
echo "search:${FZF_QUERY#* }"
|
||||
|
||||
# Otherwise, if the query does not end with a space,
|
||||
# restart ripgrep and reload the list
|
||||
elif ! [[ $FZF_QUERY =~ \ $ ]]; then
|
||||
echo "reload:rg --column --color=always --smart-case \"${words[0]}\""
|
||||
fi
|
||||
'
|
||||
fzf --ansi --disabled \
|
||||
--with-shell 'bash -c' \
|
||||
--bind "start:transform:$TRANSFORMER" \
|
||||
--bind "change:transform:$TRANSFORMER"
|
||||
```
|
||||
- Added `bell` action to ring the terminal bell
|
||||
```sh
|
||||
# Press CTRL-Y to copy the current line to the clipboard and ring the bell
|
||||
|
@ -94,8 +94,8 @@ more weight to the chronological ordering. This also sets
|
||||
.RS
|
||||
fzf chooses \fBpath\fR scheme when the input is a TTY device, where fzf would
|
||||
start its built-in walker or run \fB$FZF_DEFAULT_COMMAND\fR, and there is no
|
||||
\fBreload\fR action bound to \fBstart\fR event. Otherwise, it chooses
|
||||
\fBdefault\fR scheme.
|
||||
\fBreload\fR or \fBtransform\fR action bound to \fBstart\fR event. Otherwise,
|
||||
it chooses \fBdefault\fR scheme.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
@ -1609,6 +1609,7 @@ A key or an event can be bound to one or more of the following actions.
|
||||
\fBreload(...)\fR (see below for the details)
|
||||
\fBreload\-sync(...)\fR (see below for the details)
|
||||
\fBreplace\-query\fR (replace query string with the current selection)
|
||||
\fBsearch(...)\fR (trigger fzf search with the given string)
|
||||
\fBselect\fR
|
||||
\fBselect\-all\fR (select all matches)
|
||||
\fBshow\-header\fR
|
||||
@ -1639,6 +1640,7 @@ A key or an event can be bound to one or more of the following actions.
|
||||
\fBtransform\-preview\-label(...)\fR (transform preview label using an external command)
|
||||
\fBtransform\-prompt(...)\fR (transform prompt string using an external command)
|
||||
\fBtransform\-query(...)\fR (transform query string using an external command)
|
||||
\fBtransform\-search(...)\fR (trigger fzf search with the output of an external command)
|
||||
\fBunbind(...)\fR (unbind bindings)
|
||||
\fBunix\-line\-discard\fR \fIctrl\-u\fR
|
||||
\fBunix\-word\-rubout\fR \fIctrl\-w\fR
|
||||
|
@ -96,45 +96,48 @@ func _() {
|
||||
_ = x[actTransformPreviewLabel-85]
|
||||
_ = x[actTransformPrompt-86]
|
||||
_ = x[actTransformQuery-87]
|
||||
_ = x[actPreview-88]
|
||||
_ = x[actChangePreview-89]
|
||||
_ = x[actChangePreviewWindow-90]
|
||||
_ = x[actPreviewTop-91]
|
||||
_ = x[actPreviewBottom-92]
|
||||
_ = x[actPreviewUp-93]
|
||||
_ = x[actPreviewDown-94]
|
||||
_ = x[actPreviewPageUp-95]
|
||||
_ = x[actPreviewPageDown-96]
|
||||
_ = x[actPreviewHalfPageUp-97]
|
||||
_ = x[actPreviewHalfPageDown-98]
|
||||
_ = x[actPrevHistory-99]
|
||||
_ = x[actPrevSelected-100]
|
||||
_ = x[actPrint-101]
|
||||
_ = x[actPut-102]
|
||||
_ = x[actNextHistory-103]
|
||||
_ = x[actNextSelected-104]
|
||||
_ = x[actExecute-105]
|
||||
_ = x[actExecuteSilent-106]
|
||||
_ = x[actExecuteMulti-107]
|
||||
_ = x[actSigStop-108]
|
||||
_ = x[actFirst-109]
|
||||
_ = x[actLast-110]
|
||||
_ = x[actReload-111]
|
||||
_ = x[actReloadSync-112]
|
||||
_ = x[actDisableSearch-113]
|
||||
_ = x[actEnableSearch-114]
|
||||
_ = x[actSelect-115]
|
||||
_ = x[actDeselect-116]
|
||||
_ = x[actUnbind-117]
|
||||
_ = x[actRebind-118]
|
||||
_ = x[actBecome-119]
|
||||
_ = x[actShowHeader-120]
|
||||
_ = x[actHideHeader-121]
|
||||
_ = x[actTransformSearch-88]
|
||||
_ = x[actSearch-89]
|
||||
_ = x[actPreview-90]
|
||||
_ = x[actChangePreview-91]
|
||||
_ = x[actChangePreviewWindow-92]
|
||||
_ = x[actPreviewTop-93]
|
||||
_ = x[actPreviewBottom-94]
|
||||
_ = x[actPreviewUp-95]
|
||||
_ = x[actPreviewDown-96]
|
||||
_ = x[actPreviewPageUp-97]
|
||||
_ = x[actPreviewPageDown-98]
|
||||
_ = x[actPreviewHalfPageUp-99]
|
||||
_ = x[actPreviewHalfPageDown-100]
|
||||
_ = x[actPrevHistory-101]
|
||||
_ = x[actPrevSelected-102]
|
||||
_ = x[actPrint-103]
|
||||
_ = x[actPut-104]
|
||||
_ = x[actNextHistory-105]
|
||||
_ = x[actNextSelected-106]
|
||||
_ = x[actExecute-107]
|
||||
_ = x[actExecuteSilent-108]
|
||||
_ = x[actExecuteMulti-109]
|
||||
_ = x[actSigStop-110]
|
||||
_ = x[actFirst-111]
|
||||
_ = x[actLast-112]
|
||||
_ = x[actReload-113]
|
||||
_ = x[actReloadSync-114]
|
||||
_ = x[actDisableSearch-115]
|
||||
_ = x[actEnableSearch-116]
|
||||
_ = x[actSelect-117]
|
||||
_ = x[actDeselect-118]
|
||||
_ = x[actUnbind-119]
|
||||
_ = x[actRebind-120]
|
||||
_ = x[actBecome-121]
|
||||
_ = x[actShowHeader-122]
|
||||
_ = x[actHideHeader-123]
|
||||
_ = x[actBell-124]
|
||||
}
|
||||
|
||||
const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeListLabelactChangeInputLabelactChangeHeaderactChangeHeaderLabelactChangeMultiactChangePreviewLabelactChangePromptactChangeQueryactChangeNthactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleMultiLineactToggleHscrollactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformListLabelactTransformInputLabelactTransformHeaderactTransformHeaderLabelactTransformPreviewLabelactTransformPromptactTransformQueryactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactBecomeactShowHeaderactHideHeader"
|
||||
const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeListLabelactChangeInputLabelactChangeHeaderactChangeHeaderLabelactChangeMultiactChangePreviewLabelactChangePromptactChangeQueryactChangeNthactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleMultiLineactToggleHscrollactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformListLabelactTransformInputLabelactTransformHeaderactTransformHeaderLabelactTransformPreviewLabelactTransformPromptactTransformQueryactTransformSearchactSearchactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactBecomeactShowHeaderactHideHeaderactBell"
|
||||
|
||||
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, 1220, 1238, 1255, 1265, 1281, 1303, 1316, 1332, 1344, 1358, 1374, 1392, 1412, 1434, 1448, 1463, 1471, 1477, 1491, 1506, 1516, 1532, 1547, 1557, 1565, 1572, 1581, 1594, 1610, 1625, 1634, 1645, 1654, 1663, 1672, 1685, 1698}
|
||||
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, 1220, 1238, 1255, 1273, 1282, 1292, 1308, 1330, 1343, 1359, 1371, 1385, 1401, 1419, 1439, 1461, 1475, 1490, 1498, 1504, 1518, 1533, 1543, 1559, 1574, 1584, 1592, 1599, 1608, 1621, 1637, 1652, 1661, 1672, 1681, 1690, 1699, 1712, 1725, 1732}
|
||||
|
||||
func (i actionType) String() string {
|
||||
if i < 0 || i >= actionType(len(_actionType_index)-1) {
|
||||
|
@ -1332,7 +1332,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)|transform|change-(?:preview-window|preview|multi|nth)|(?:re|un)bind|pos|put|print)`)
|
||||
`(?si)[:+](become|execute(?:-multi|-silent)?|reload(?:-sync)?|preview|(?:change|transform)-(?:query|prompt|(?:border|list|preview|input|header)-label|header|search)|transform|change-(?:preview-window|preview|multi|nth)|(?:re|un)bind|pos|put|print|search)`)
|
||||
splitRegexp = regexp.MustCompile("[,:]+")
|
||||
actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+")
|
||||
}
|
||||
@ -1744,6 +1744,10 @@ func isExecuteAction(str string) actionType {
|
||||
return actTransformPrompt
|
||||
case "transform-query":
|
||||
return actTransformQuery
|
||||
case "transform-search":
|
||||
return actTransformSearch
|
||||
case "search":
|
||||
return actSearch
|
||||
}
|
||||
return actIgnore
|
||||
}
|
||||
@ -3252,7 +3256,7 @@ func ParseOptions(useDefaults bool, args []string) (*Options, error) {
|
||||
// 1. explicitly set --scheme=default,
|
||||
// 2. or replace $FZF_DEFAULT_COMMAND with an equivalent 'start:reload'
|
||||
// binding, which is the new preferred way.
|
||||
if !opts.hasReloadOnStart() && util.IsTty(os.Stdin) {
|
||||
if !opts.hasReloadOrTransformOnStart() && util.IsTty(os.Stdin) {
|
||||
opts.Scheme = "path"
|
||||
}
|
||||
_, opts.Criteria, _ = parseScheme(opts.Scheme)
|
||||
@ -3267,10 +3271,10 @@ func ParseOptions(useDefaults bool, args []string) (*Options, error) {
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func (opts *Options) hasReloadOnStart() bool {
|
||||
func (opts *Options) hasReloadOrTransformOnStart() bool {
|
||||
if actions, prs := opts.Keymap[tui.Start.AsEvent()]; prs {
|
||||
for _, action := range actions {
|
||||
if action.t == actReload || action.t == actReloadSync {
|
||||
if action.t == actReload || action.t == actReloadSync || action.t == actTransform {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -277,6 +277,7 @@ type Terminal struct {
|
||||
xoffset int
|
||||
yanked []rune
|
||||
input []rune
|
||||
inputOverride *[]rune
|
||||
multi int
|
||||
multiLine bool
|
||||
sort bool
|
||||
@ -533,6 +534,8 @@ const (
|
||||
actTransformPreviewLabel
|
||||
actTransformPrompt
|
||||
actTransformQuery
|
||||
actTransformSearch
|
||||
actSearch
|
||||
actPreview
|
||||
actChangePreview
|
||||
actChangePreviewWindow
|
||||
@ -1354,7 +1357,13 @@ func (t *Terminal) getScrollbar() (int, int) {
|
||||
func (t *Terminal) Input() (bool, []rune) {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
return t.paused, copySlice(t.input)
|
||||
paused := t.paused
|
||||
src := t.input
|
||||
if t.inputOverride != nil {
|
||||
paused = false
|
||||
src = *t.inputOverride
|
||||
}
|
||||
return paused, copySlice(src)
|
||||
}
|
||||
|
||||
// UpdateCount updates the count information
|
||||
@ -3837,6 +3846,14 @@ func (t *Terminal) fullRedraw() {
|
||||
t.printAll()
|
||||
}
|
||||
|
||||
func (t *Terminal) captureLine(template string) string {
|
||||
return t.executeCommand(template, false, true, true, true, "")
|
||||
}
|
||||
|
||||
func (t *Terminal) captureLines(template string) string {
|
||||
return t.executeCommand(template, false, true, true, false, "")
|
||||
}
|
||||
|
||||
func (t *Terminal) executeCommand(template string, forcePlus bool, background bool, capture bool, firstLineOnly bool, info string) string {
|
||||
line := ""
|
||||
valid, list := t.buildPlusList(template, forcePlus)
|
||||
@ -4751,12 +4768,12 @@ func (t *Terminal) Loop() error {
|
||||
req(reqPreviewRefresh)
|
||||
}
|
||||
case actTransformPrompt:
|
||||
prompt := t.executeCommand(a.a, false, true, true, true, "")
|
||||
prompt := t.captureLine(a.a)
|
||||
t.promptString = prompt
|
||||
t.prompt, t.promptLen = t.parsePrompt(prompt)
|
||||
req(reqPrompt)
|
||||
case actTransformQuery:
|
||||
query := t.executeCommand(a.a, false, true, true, true, "")
|
||||
query := t.captureLine(a.a)
|
||||
t.input = []rune(query)
|
||||
t.cx = len(t.input)
|
||||
case actToggleSort:
|
||||
@ -4840,7 +4857,7 @@ func (t *Terminal) Loop() error {
|
||||
case actChangeHeader, actTransformHeader:
|
||||
header := a.a
|
||||
if a.t == actTransformHeader {
|
||||
header = t.executeCommand(a.a, false, true, true, false, "")
|
||||
header = t.captureLines(a.a)
|
||||
}
|
||||
if t.changeHeader(header) {
|
||||
req(reqHeader, reqList, reqPrompt, reqInfo)
|
||||
@ -4878,40 +4895,40 @@ func (t *Terminal) Loop() error {
|
||||
req(reqRedrawPreviewLabel)
|
||||
}
|
||||
case actTransform:
|
||||
body := t.executeCommand(a.a, false, true, true, false, "")
|
||||
body := t.captureLines(a.a)
|
||||
if actions, err := parseSingleActionList(strings.Trim(body, "\r\n")); err == nil {
|
||||
return doActions(actions)
|
||||
}
|
||||
case actTransformHeaderLabel:
|
||||
label := t.executeCommand(a.a, false, true, true, true, "")
|
||||
label := t.captureLine(a.a)
|
||||
t.headerLabelOpts.label = label
|
||||
if t.headerBorder != nil {
|
||||
t.headerLabel, t.headerLabelLen = t.ansiLabelPrinter(label, &tui.ColHeaderLabel, false)
|
||||
req(reqRedrawHeaderLabel)
|
||||
}
|
||||
case actTransformInputLabel:
|
||||
label := t.executeCommand(a.a, false, true, true, true, "")
|
||||
label := t.captureLine(a.a)
|
||||
t.inputLabelOpts.label = label
|
||||
if t.inputBorder != nil {
|
||||
t.inputLabel, t.inputLabelLen = t.ansiLabelPrinter(label, &tui.ColInputLabel, false)
|
||||
req(reqRedrawInputLabel)
|
||||
}
|
||||
case actTransformListLabel:
|
||||
label := t.executeCommand(a.a, false, true, true, true, "")
|
||||
label := t.captureLine(a.a)
|
||||
t.listLabelOpts.label = label
|
||||
if t.wborder != nil {
|
||||
t.listLabel, t.listLabelLen = t.ansiLabelPrinter(label, &tui.ColListLabel, false)
|
||||
req(reqRedrawListLabel)
|
||||
}
|
||||
case actTransformBorderLabel:
|
||||
label := t.executeCommand(a.a, false, true, true, true, "")
|
||||
label := t.captureLine(a.a)
|
||||
t.borderLabelOpts.label = label
|
||||
if t.border != nil {
|
||||
t.borderLabel, t.borderLabelLen = t.ansiLabelPrinter(label, &tui.ColBorderLabel, false)
|
||||
req(reqRedrawBorderLabel)
|
||||
}
|
||||
case actTransformPreviewLabel:
|
||||
label := t.executeCommand(a.a, false, true, true, true, "")
|
||||
label := t.captureLine(a.a)
|
||||
t.previewLabelOpts.label = label
|
||||
if t.pborder != nil {
|
||||
t.previewLabel, t.previewLabelLen = t.ansiLabelPrinter(label, &tui.ColPreviewLabel, false)
|
||||
@ -5309,6 +5326,14 @@ func (t *Terminal) Loop() error {
|
||||
t.track = trackDisabled
|
||||
}
|
||||
req(reqInfo)
|
||||
case actSearch:
|
||||
override := []rune(a.a)
|
||||
t.inputOverride = &override
|
||||
changed = true
|
||||
case actTransformSearch:
|
||||
override := []rune(t.captureLine(a.a))
|
||||
t.inputOverride = &override
|
||||
changed = true
|
||||
case actEnableSearch:
|
||||
t.paused = false
|
||||
changed = true
|
||||
@ -5734,6 +5759,9 @@ func (t *Terminal) Loop() error {
|
||||
}
|
||||
t.truncateQuery()
|
||||
queryChanged = string(previousInput) != string(t.input)
|
||||
if queryChanged {
|
||||
t.inputOverride = nil
|
||||
}
|
||||
changed = changed || queryChanged
|
||||
if onChanges, prs := t.keymap[tui.Change.AsEvent()]; queryChanged && prs && !doActions(onChanges) {
|
||||
continue
|
||||
|
@ -1069,6 +1069,24 @@ class TestCore < TestInteractive
|
||||
tmux.until { |lines| assert_equal 'up', lines[-1] }
|
||||
end
|
||||
|
||||
def test_search
|
||||
tmux.send_keys %(seq 100 | #{FZF} --query 0 --bind space:search:1), :Enter
|
||||
tmux.until { |lines| assert_equal 10, lines.match_count }
|
||||
tmux.send_keys :Space
|
||||
tmux.until { |lines| assert_equal 20, lines.match_count }
|
||||
tmux.send_keys '0'
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
end
|
||||
|
||||
def test_transform_search
|
||||
tmux.send_keys %(seq 1000 | #{FZF} --bind 'change:transform-search:echo {q}{q}'), :Enter
|
||||
tmux.until { |lines| assert_equal 1000, lines.match_count }
|
||||
tmux.send_keys '1'
|
||||
tmux.until { |lines| assert_equal 28, lines.match_count }
|
||||
tmux.send_keys :BSpace, '0'
|
||||
tmux.until { |lines| assert_equal 10, lines.match_count }
|
||||
end
|
||||
|
||||
def test_clear_selection
|
||||
tmux.send_keys %(seq 100 | #{FZF} --multi --bind space:clear-selection), :Enter
|
||||
tmux.until { |lines| assert_equal 100, lines.match_count }
|
||||
|
Loading…
x
Reference in New Issue
Block a user