mirror of
https://github.com/junegunn/fzf.git
synced 2026-11-04 14:05:55 +00:00
Compare commits
7
Commits
nth-cycling
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99bfd5aa0f | ||
|
|
26ff936df0 | ||
|
|
b412a45053 | ||
|
|
ac28b8c3ba | ||
|
|
2adb741c33 | ||
|
|
a38ab117c5 | ||
|
|
903a4da7ab |
No files matched your search
+11
-1
@@ -1,8 +1,14 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
0.74.6
|
||||
0.75.0
|
||||
------
|
||||
- Added `{change,transform,bg-transform}-info-command` actions (#4951) (@casperdcl)
|
||||
```sh
|
||||
seq 100 | fzf --info-command 'echo "mode: A | $FZF_INFO"' \
|
||||
--bind 'ctrl-a:change-info-command:echo "mode: A | $FZF_INFO"' \
|
||||
--bind 'ctrl-b:change-info-command:echo "mode: B | $FZF_INFO"'
|
||||
```
|
||||
- Fixed `--with-shell` on Windows not detecting cmd, PowerShell, and pwsh, which made fzf quote commands and entries for a POSIX shell (#4936) (@vimkim)
|
||||
- e.g. With `--with-shell "cmd.exe /d /c"`, `--preview '"C:\Program Files\nu\bin\nu.exe" --version'` failed
|
||||
- `transform-nth` and `transform-with-nth` (and their `bg-` variants) no longer split the output at `|`
|
||||
@@ -26,6 +32,10 @@ CHANGELOG
|
||||
```
|
||||
- nushell
|
||||
- The completion integration now requires nushell 0.116.1 or above, where an interactive completer can take the terminal through the `@interactive` attribute (#4934) (@sim590)
|
||||
- Fixed `--no-sort` being ignored in filter mode with `--sync`, `--tac`, or `--bench` (#4940) (@NavpreetSSidhu)
|
||||
- Vim plugin: Fixed garbage text on screen in Neovim with `set title` when the fzf command contains ANSI escape sequences (#4941)
|
||||
- Fixed `--walker=follow` skipping a symlink in one `--walker-root` when its target is an ancestor of another root (#4944) (@mabunemeh)
|
||||
- Fixed O(n^2) action parsing in `--listen`. A single ~1 MB request could block the server for ~30 s (@zachariah-mithani, AploSec)
|
||||
|
||||
0.74.5
|
||||
------
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
|
||||
<kbd align="center">
|
||||
<br/>
|
||||
<a href="https://commitgoods.com/collections/fzf"><img src="https://junegunn.github.io/fzf/images/fzf-mugs.jpg" width="80%" alt="fzf merch"></a>
|
||||
<a href="https://commitgoods.com/collections/fzf?utm_source=github&utm_medium=referral"><img src="https://junegunn.github.io/fzf/images/fzf-mugs.jpg" width="80%" alt="fzf merch"></a>
|
||||
<br/>
|
||||
<br/>
|
||||
Show your love for fzf -- T-shirts, mugs, and stickers now available!
|
||||
<br/>
|
||||
<br/>
|
||||
<a href="https://commitgoods.com/collections/fzf">commitgoods.com/collections/fzf</a>
|
||||
<a href="https://commitgoods.com/collections/fzf?utm_source=github&utm_medium=referral"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cdn.shopify.com/s/files/1/0101/8752/files/commitgoods-badge-stacked-navy-dark.svg"><img src="https://cdn.shopify.com/s/files/1/0101/8752/files/commitgoods-badge-stacked-navy.svg" height="28" alt="Official merch on commitgoods.com"></picture></a>
|
||||
<br/>
|
||||
<br/>
|
||||
</kbd>
|
||||
@@ -1150,7 +1150,7 @@ Copyright (c) 2013-2026 Junegunn Choi
|
||||
Goods
|
||||
-----
|
||||
|
||||
Grab fzf T-shirts, mugs, and stickers here: https://commitgoods.com/collections/fzf
|
||||
Grab fzf T-shirts, mugs, and stickers here: [commitgoods.com/collections/fzf](https://commitgoods.com/collections/fzf?utm_source=github&utm_medium=referral)
|
||||
|
||||
Sponsors :heart:
|
||||
----------------
|
||||
|
||||
@@ -2056,6 +2056,7 @@ A key or an event can be bound to one or more of the following actions.
|
||||
\fBchange\-header(...)\fR (change header to the given string; doesn't affect \fB\-\-header\-lines\fR)
|
||||
\fBchange\-header\-lines(N)\fR (change the number of \fB\-\-header\-lines\fR)
|
||||
\fBchange\-header\-label(...)\fR (change \fB\-\-header\-label\fR to the given string)
|
||||
\fBchange\-info\-command(...)\fR (change \fB\-\-info\-command\fR option)
|
||||
\fBchange\-input\-label(...)\fR (change \fB\-\-input\-label\fR to the given string)
|
||||
\fBchange\-list\-label(...)\fR (change \fB\-\-list\-label\fR to the given string)
|
||||
\fBchange\-multi\fR (enable multi-select mode with no limit)
|
||||
@@ -2164,6 +2165,7 @@ A key or an event can be bound to one or more of the following actions.
|
||||
\fBtransform\-header(...)\fR (transform header using an external command)
|
||||
\fBtransform\-header\-lines(...)\fR (transform the number of \fB\-\-header\-lines\fR using an external command)
|
||||
\fBtransform\-header\-label(...)\fR (transform header label using an external command)
|
||||
\fBtransform\-info\-command(...)\fR (transform \fB\-\-info\-command\fR using an external command)
|
||||
\fBtransform\-input\-label(...)\fR (transform input label using an external command)
|
||||
\fBtransform\-list\-label(...)\fR (transform list label using an external command)
|
||||
\fBtransform\-nth(...)\fR (transform nth using an external command; see CHANGE NTH AND WITH\-NTH)
|
||||
|
||||
@@ -1104,6 +1104,12 @@ function! s:execute_term(dict, command, temps) abort
|
||||
let fzf.temps.batchfile = s:fzf_tempname().'.bat'
|
||||
call s:writefile(s:wrap_cmds(a:command), fzf.temps.batchfile)
|
||||
let command = fzf.temps.batchfile
|
||||
elseif has('nvim') && &title && a:command =~ '[[:cntrl:]]'
|
||||
" Neovim puts the command in the buffer name, which can end up raw in
|
||||
" the terminal title (#4941)
|
||||
let fzf.temps.shellscript = s:fzf_tempname()
|
||||
call s:writefile([a:command], fzf.temps.shellscript)
|
||||
let command = 'sh '.fzf#shellescape(fzf.temps.shellscript)
|
||||
else
|
||||
let command = a:command
|
||||
endif
|
||||
|
||||
+161
-157
@@ -34,168 +34,172 @@ func _() {
|
||||
_ = x[actChangeFooter-23]
|
||||
_ = x[actChangeHeaderLabel-24]
|
||||
_ = x[actChangeFooterLabel-25]
|
||||
_ = x[actChangeInputLabel-26]
|
||||
_ = x[actChangeListLabel-27]
|
||||
_ = x[actChangeMulti-28]
|
||||
_ = x[actChangeNth-29]
|
||||
_ = x[actChangeWithNth-30]
|
||||
_ = x[actChangePointer-31]
|
||||
_ = x[actChangePreview-32]
|
||||
_ = x[actChangePreviewLabel-33]
|
||||
_ = x[actChangePreviewWindow-34]
|
||||
_ = x[actChangePrompt-35]
|
||||
_ = x[actChangeQuery-36]
|
||||
_ = x[actClearScreen-37]
|
||||
_ = x[actClearQuery-38]
|
||||
_ = x[actClearSelection-39]
|
||||
_ = x[actClose-40]
|
||||
_ = x[actDeleteChar-41]
|
||||
_ = x[actDeleteCharEof-42]
|
||||
_ = x[actEndOfLine-43]
|
||||
_ = x[actFatal-44]
|
||||
_ = x[actForwardChar-45]
|
||||
_ = x[actForwardWord-46]
|
||||
_ = x[actForwardSubWord-47]
|
||||
_ = x[actKillLine-48]
|
||||
_ = x[actKillWord-49]
|
||||
_ = x[actKillSubWord-50]
|
||||
_ = x[actUnixLineDiscard-51]
|
||||
_ = x[actUnixWordRubout-52]
|
||||
_ = x[actYank-53]
|
||||
_ = x[actBackwardKillWord-54]
|
||||
_ = x[actBackwardKillSubWord-55]
|
||||
_ = x[actSelectAll-56]
|
||||
_ = x[actDeselectAll-57]
|
||||
_ = x[actToggle-58]
|
||||
_ = x[actToggleSearch-59]
|
||||
_ = x[actToggleAll-60]
|
||||
_ = x[actToggleDown-61]
|
||||
_ = x[actToggleUp-62]
|
||||
_ = x[actToggleIn-63]
|
||||
_ = x[actToggleOut-64]
|
||||
_ = x[actToggleTrack-65]
|
||||
_ = x[actToggleTrackCurrent-66]
|
||||
_ = x[actToggleHeader-67]
|
||||
_ = x[actToggleWrap-68]
|
||||
_ = x[actToggleWrapWord-69]
|
||||
_ = x[actToggleMultiLine-70]
|
||||
_ = x[actToggleHscroll-71]
|
||||
_ = x[actToggleRaw-72]
|
||||
_ = x[actEnableRaw-73]
|
||||
_ = x[actDisableRaw-74]
|
||||
_ = x[actTrackCurrent-75]
|
||||
_ = x[actToggleInput-76]
|
||||
_ = x[actHideInput-77]
|
||||
_ = x[actShowInput-78]
|
||||
_ = x[actUntrackCurrent-79]
|
||||
_ = x[actDown-80]
|
||||
_ = x[actDownMatch-81]
|
||||
_ = x[actUp-82]
|
||||
_ = x[actUpMatch-83]
|
||||
_ = x[actPageUp-84]
|
||||
_ = x[actPageDown-85]
|
||||
_ = x[actPosition-86]
|
||||
_ = x[actHalfPageUp-87]
|
||||
_ = x[actHalfPageDown-88]
|
||||
_ = x[actOffsetUp-89]
|
||||
_ = x[actOffsetDown-90]
|
||||
_ = x[actOffsetMiddle-91]
|
||||
_ = x[actJump-92]
|
||||
_ = x[actJumpAccept-93]
|
||||
_ = x[actPrintQuery-94]
|
||||
_ = x[actRefreshPreview-95]
|
||||
_ = x[actReplaceQuery-96]
|
||||
_ = x[actToggleSort-97]
|
||||
_ = x[actShowPreview-98]
|
||||
_ = x[actHidePreview-99]
|
||||
_ = x[actTogglePreview-100]
|
||||
_ = x[actTogglePreviewWrap-101]
|
||||
_ = x[actTogglePreviewWrapWord-102]
|
||||
_ = x[actTransform-103]
|
||||
_ = x[actTransformBorderLabel-104]
|
||||
_ = x[actTransformGhost-105]
|
||||
_ = x[actTransformHeader-106]
|
||||
_ = x[actTransformHeaderLines-107]
|
||||
_ = x[actTransformFooter-108]
|
||||
_ = x[actTransformHeaderLabel-109]
|
||||
_ = x[actTransformFooterLabel-110]
|
||||
_ = x[actTransformInputLabel-111]
|
||||
_ = x[actTransformListLabel-112]
|
||||
_ = x[actTransformNth-113]
|
||||
_ = x[actTransformWithNth-114]
|
||||
_ = x[actTransformPointer-115]
|
||||
_ = x[actTransformPreviewLabel-116]
|
||||
_ = x[actTransformPrompt-117]
|
||||
_ = x[actTransformQuery-118]
|
||||
_ = x[actTransformSearch-119]
|
||||
_ = x[actTrigger-120]
|
||||
_ = x[actBgTransform-121]
|
||||
_ = x[actBgTransformBorderLabel-122]
|
||||
_ = x[actBgTransformGhost-123]
|
||||
_ = x[actBgTransformHeader-124]
|
||||
_ = x[actBgTransformHeaderLines-125]
|
||||
_ = x[actBgTransformFooter-126]
|
||||
_ = x[actBgTransformHeaderLabel-127]
|
||||
_ = x[actBgTransformFooterLabel-128]
|
||||
_ = x[actBgTransformInputLabel-129]
|
||||
_ = x[actBgTransformListLabel-130]
|
||||
_ = x[actBgTransformNth-131]
|
||||
_ = x[actBgTransformWithNth-132]
|
||||
_ = x[actBgTransformPointer-133]
|
||||
_ = x[actBgTransformPreviewLabel-134]
|
||||
_ = x[actBgTransformPrompt-135]
|
||||
_ = x[actBgTransformQuery-136]
|
||||
_ = x[actBgTransformSearch-137]
|
||||
_ = x[actBgCancel-138]
|
||||
_ = x[actSearch-139]
|
||||
_ = x[actPreview-140]
|
||||
_ = x[actPreviewTop-141]
|
||||
_ = x[actPreviewBottom-142]
|
||||
_ = x[actPreviewUp-143]
|
||||
_ = x[actPreviewDown-144]
|
||||
_ = x[actPreviewPageUp-145]
|
||||
_ = x[actPreviewPageDown-146]
|
||||
_ = x[actPreviewHalfPageUp-147]
|
||||
_ = x[actPreviewHalfPageDown-148]
|
||||
_ = x[actPrevHistory-149]
|
||||
_ = x[actPrevSelected-150]
|
||||
_ = x[actPrint-151]
|
||||
_ = x[actPut-152]
|
||||
_ = x[actNextHistory-153]
|
||||
_ = x[actNextSelected-154]
|
||||
_ = x[actExecute-155]
|
||||
_ = x[actExecuteSilent-156]
|
||||
_ = x[actExecuteMulti-157]
|
||||
_ = x[actSigStop-158]
|
||||
_ = x[actBest-159]
|
||||
_ = x[actFirst-160]
|
||||
_ = x[actLast-161]
|
||||
_ = x[actReload-162]
|
||||
_ = x[actReloadSync-163]
|
||||
_ = x[actDisableSearch-164]
|
||||
_ = x[actEnableSearch-165]
|
||||
_ = x[actSelect-166]
|
||||
_ = x[actDeselect-167]
|
||||
_ = x[actUnbind-168]
|
||||
_ = x[actRebind-169]
|
||||
_ = x[actToggleBind-170]
|
||||
_ = x[actBecome-171]
|
||||
_ = x[actShowHeader-172]
|
||||
_ = x[actHideHeader-173]
|
||||
_ = x[actBell-174]
|
||||
_ = x[actExclude-175]
|
||||
_ = x[actExcludeMulti-176]
|
||||
_ = x[actAsync-177]
|
||||
_ = x[actWait-178]
|
||||
_ = x[actChangeInfoCommand-26]
|
||||
_ = x[actChangeInputLabel-27]
|
||||
_ = x[actChangeListLabel-28]
|
||||
_ = x[actChangeMulti-29]
|
||||
_ = x[actChangeNth-30]
|
||||
_ = x[actChangeWithNth-31]
|
||||
_ = x[actChangePointer-32]
|
||||
_ = x[actChangePreview-33]
|
||||
_ = x[actChangePreviewLabel-34]
|
||||
_ = x[actChangePreviewWindow-35]
|
||||
_ = x[actChangePrompt-36]
|
||||
_ = x[actChangeQuery-37]
|
||||
_ = x[actClearScreen-38]
|
||||
_ = x[actClearQuery-39]
|
||||
_ = x[actClearSelection-40]
|
||||
_ = x[actClose-41]
|
||||
_ = x[actDeleteChar-42]
|
||||
_ = x[actDeleteCharEof-43]
|
||||
_ = x[actEndOfLine-44]
|
||||
_ = x[actFatal-45]
|
||||
_ = x[actForwardChar-46]
|
||||
_ = x[actForwardWord-47]
|
||||
_ = x[actForwardSubWord-48]
|
||||
_ = x[actKillLine-49]
|
||||
_ = x[actKillWord-50]
|
||||
_ = x[actKillSubWord-51]
|
||||
_ = x[actUnixLineDiscard-52]
|
||||
_ = x[actUnixWordRubout-53]
|
||||
_ = x[actYank-54]
|
||||
_ = x[actBackwardKillWord-55]
|
||||
_ = x[actBackwardKillSubWord-56]
|
||||
_ = x[actSelectAll-57]
|
||||
_ = x[actDeselectAll-58]
|
||||
_ = x[actToggle-59]
|
||||
_ = x[actToggleSearch-60]
|
||||
_ = x[actToggleAll-61]
|
||||
_ = x[actToggleDown-62]
|
||||
_ = x[actToggleUp-63]
|
||||
_ = x[actToggleIn-64]
|
||||
_ = x[actToggleOut-65]
|
||||
_ = x[actToggleTrack-66]
|
||||
_ = x[actToggleTrackCurrent-67]
|
||||
_ = x[actToggleHeader-68]
|
||||
_ = x[actToggleWrap-69]
|
||||
_ = x[actToggleWrapWord-70]
|
||||
_ = x[actToggleMultiLine-71]
|
||||
_ = x[actToggleHscroll-72]
|
||||
_ = x[actToggleRaw-73]
|
||||
_ = x[actEnableRaw-74]
|
||||
_ = x[actDisableRaw-75]
|
||||
_ = x[actTrackCurrent-76]
|
||||
_ = x[actToggleInput-77]
|
||||
_ = x[actHideInput-78]
|
||||
_ = x[actShowInput-79]
|
||||
_ = x[actUntrackCurrent-80]
|
||||
_ = x[actDown-81]
|
||||
_ = x[actDownMatch-82]
|
||||
_ = x[actUp-83]
|
||||
_ = x[actUpMatch-84]
|
||||
_ = x[actPageUp-85]
|
||||
_ = x[actPageDown-86]
|
||||
_ = x[actPosition-87]
|
||||
_ = x[actHalfPageUp-88]
|
||||
_ = x[actHalfPageDown-89]
|
||||
_ = x[actOffsetUp-90]
|
||||
_ = x[actOffsetDown-91]
|
||||
_ = x[actOffsetMiddle-92]
|
||||
_ = x[actJump-93]
|
||||
_ = x[actJumpAccept-94]
|
||||
_ = x[actPrintQuery-95]
|
||||
_ = x[actRefreshPreview-96]
|
||||
_ = x[actReplaceQuery-97]
|
||||
_ = x[actToggleSort-98]
|
||||
_ = x[actShowPreview-99]
|
||||
_ = x[actHidePreview-100]
|
||||
_ = x[actTogglePreview-101]
|
||||
_ = x[actTogglePreviewWrap-102]
|
||||
_ = x[actTogglePreviewWrapWord-103]
|
||||
_ = x[actTransform-104]
|
||||
_ = x[actTransformBorderLabel-105]
|
||||
_ = x[actTransformGhost-106]
|
||||
_ = x[actTransformHeader-107]
|
||||
_ = x[actTransformHeaderLines-108]
|
||||
_ = x[actTransformFooter-109]
|
||||
_ = x[actTransformHeaderLabel-110]
|
||||
_ = x[actTransformFooterLabel-111]
|
||||
_ = x[actTransformInfoCommand-112]
|
||||
_ = x[actTransformInputLabel-113]
|
||||
_ = x[actTransformListLabel-114]
|
||||
_ = x[actTransformNth-115]
|
||||
_ = x[actTransformWithNth-116]
|
||||
_ = x[actTransformPointer-117]
|
||||
_ = x[actTransformPreviewLabel-118]
|
||||
_ = x[actTransformPrompt-119]
|
||||
_ = x[actTransformQuery-120]
|
||||
_ = x[actTransformSearch-121]
|
||||
_ = x[actTrigger-122]
|
||||
_ = x[actBgTransform-123]
|
||||
_ = x[actBgTransformBorderLabel-124]
|
||||
_ = x[actBgTransformGhost-125]
|
||||
_ = x[actBgTransformHeader-126]
|
||||
_ = x[actBgTransformHeaderLines-127]
|
||||
_ = x[actBgTransformFooter-128]
|
||||
_ = x[actBgTransformHeaderLabel-129]
|
||||
_ = x[actBgTransformFooterLabel-130]
|
||||
_ = x[actBgTransformInfoCommand-131]
|
||||
_ = x[actBgTransformInputLabel-132]
|
||||
_ = x[actBgTransformListLabel-133]
|
||||
_ = x[actBgTransformNth-134]
|
||||
_ = x[actBgTransformWithNth-135]
|
||||
_ = x[actBgTransformPointer-136]
|
||||
_ = x[actBgTransformPreviewLabel-137]
|
||||
_ = x[actBgTransformPrompt-138]
|
||||
_ = x[actBgTransformQuery-139]
|
||||
_ = x[actBgTransformSearch-140]
|
||||
_ = x[actBgCancel-141]
|
||||
_ = x[actSearch-142]
|
||||
_ = x[actPreview-143]
|
||||
_ = x[actPreviewTop-144]
|
||||
_ = x[actPreviewBottom-145]
|
||||
_ = x[actPreviewUp-146]
|
||||
_ = x[actPreviewDown-147]
|
||||
_ = x[actPreviewPageUp-148]
|
||||
_ = x[actPreviewPageDown-149]
|
||||
_ = x[actPreviewHalfPageUp-150]
|
||||
_ = x[actPreviewHalfPageDown-151]
|
||||
_ = x[actPrevHistory-152]
|
||||
_ = x[actPrevSelected-153]
|
||||
_ = x[actPrint-154]
|
||||
_ = x[actPut-155]
|
||||
_ = x[actNextHistory-156]
|
||||
_ = x[actNextSelected-157]
|
||||
_ = x[actExecute-158]
|
||||
_ = x[actExecuteSilent-159]
|
||||
_ = x[actExecuteMulti-160]
|
||||
_ = x[actSigStop-161]
|
||||
_ = x[actBest-162]
|
||||
_ = x[actFirst-163]
|
||||
_ = x[actLast-164]
|
||||
_ = x[actReload-165]
|
||||
_ = x[actReloadSync-166]
|
||||
_ = x[actDisableSearch-167]
|
||||
_ = x[actEnableSearch-168]
|
||||
_ = x[actSelect-169]
|
||||
_ = x[actDeselect-170]
|
||||
_ = x[actUnbind-171]
|
||||
_ = x[actRebind-172]
|
||||
_ = x[actToggleBind-173]
|
||||
_ = x[actBecome-174]
|
||||
_ = x[actShowHeader-175]
|
||||
_ = x[actHideHeader-176]
|
||||
_ = x[actBell-177]
|
||||
_ = x[actExclude-178]
|
||||
_ = x[actExcludeMulti-179]
|
||||
_ = x[actAsync-180]
|
||||
_ = x[actWait-181]
|
||||
}
|
||||
|
||||
const _actionType_name = "actIgnoreactStartactClickactInvalidactBracketedPasteBeginactBracketedPasteEndactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactBackwardSubWordactCancelactChangeBorderLabelactChangeGhostactChangeHeaderactChangeHeaderLinesactChangeFooteractChangeHeaderLabelactChangeFooterLabelactChangeInputLabelactChangeListLabelactChangeMultiactChangeNthactChangeWithNthactChangePointeractChangePreviewactChangePreviewLabelactChangePreviewWindowactChangePromptactChangeQueryactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactForwardSubWordactKillLineactKillWordactKillSubWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactBackwardKillSubWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleWrapWordactToggleMultiLineactToggleHscrollactToggleRawactEnableRawactDisableRawactTrackCurrentactToggleInputactHideInputactShowInputactUntrackCurrentactDownactDownMatchactUpactUpMatchactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTogglePreviewWrapWordactTransformactTransformBorderLabelactTransformGhostactTransformHeaderactTransformHeaderLinesactTransformFooteractTransformHeaderLabelactTransformFooterLabelactTransformInputLabelactTransformListLabelactTransformNthactTransformWithNthactTransformPointeractTransformPreviewLabelactTransformPromptactTransformQueryactTransformSearchactTriggeractBgTransformactBgTransformBorderLabelactBgTransformGhostactBgTransformHeaderactBgTransformHeaderLinesactBgTransformFooteractBgTransformHeaderLabelactBgTransformFooterLabelactBgTransformInputLabelactBgTransformListLabelactBgTransformNthactBgTransformWithNthactBgTransformPointeractBgTransformPreviewLabelactBgTransformPromptactBgTransformQueryactBgTransformSearchactBgCancelactSearchactPreviewactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactBestactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactToggleBindactBecomeactShowHeaderactHideHeaderactBellactExcludeactExcludeMultiactAsyncactWait"
|
||||
const _actionType_name = "actIgnoreactStartactClickactInvalidactBracketedPasteBeginactBracketedPasteEndactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactBackwardSubWordactCancelactChangeBorderLabelactChangeGhostactChangeHeaderactChangeHeaderLinesactChangeFooteractChangeHeaderLabelactChangeFooterLabelactChangeInfoCommandactChangeInputLabelactChangeListLabelactChangeMultiactChangeNthactChangeWithNthactChangePointeractChangePreviewactChangePreviewLabelactChangePreviewWindowactChangePromptactChangeQueryactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactForwardSubWordactKillLineactKillWordactKillSubWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactBackwardKillSubWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleWrapWordactToggleMultiLineactToggleHscrollactToggleRawactEnableRawactDisableRawactTrackCurrentactToggleInputactHideInputactShowInputactUntrackCurrentactDownactDownMatchactUpactUpMatchactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTogglePreviewWrapWordactTransformactTransformBorderLabelactTransformGhostactTransformHeaderactTransformHeaderLinesactTransformFooteractTransformHeaderLabelactTransformFooterLabelactTransformInfoCommandactTransformInputLabelactTransformListLabelactTransformNthactTransformWithNthactTransformPointeractTransformPreviewLabelactTransformPromptactTransformQueryactTransformSearchactTriggeractBgTransformactBgTransformBorderLabelactBgTransformGhostactBgTransformHeaderactBgTransformHeaderLinesactBgTransformFooteractBgTransformHeaderLabelactBgTransformFooterLabelactBgTransformInfoCommandactBgTransformInputLabelactBgTransformListLabelactBgTransformNthactBgTransformWithNthactBgTransformPointeractBgTransformPreviewLabelactBgTransformPromptactBgTransformQueryactBgTransformSearchactBgCancelactSearchactPreviewactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactBestactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactToggleBindactBecomeactShowHeaderactHideHeaderactBellactExcludeactExcludeMultiactAsyncactWait"
|
||||
|
||||
var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 57, 77, 84, 92, 110, 118, 127, 144, 165, 180, 201, 225, 240, 258, 267, 287, 301, 316, 336, 351, 371, 391, 410, 428, 442, 454, 470, 486, 502, 523, 545, 560, 574, 588, 601, 618, 626, 639, 655, 667, 675, 689, 703, 720, 731, 742, 756, 774, 791, 798, 817, 839, 851, 865, 874, 889, 901, 914, 925, 936, 948, 962, 983, 998, 1011, 1028, 1046, 1062, 1074, 1086, 1099, 1114, 1128, 1140, 1152, 1169, 1176, 1188, 1193, 1203, 1212, 1223, 1234, 1247, 1262, 1273, 1286, 1301, 1308, 1321, 1334, 1351, 1366, 1379, 1393, 1407, 1423, 1443, 1467, 1479, 1502, 1519, 1537, 1560, 1578, 1601, 1624, 1646, 1667, 1682, 1701, 1720, 1744, 1762, 1779, 1797, 1807, 1821, 1846, 1865, 1885, 1910, 1930, 1955, 1980, 2004, 2027, 2044, 2065, 2086, 2112, 2132, 2151, 2171, 2182, 2191, 2201, 2214, 2230, 2242, 2256, 2272, 2290, 2310, 2332, 2346, 2361, 2369, 2375, 2389, 2404, 2414, 2430, 2445, 2455, 2462, 2470, 2477, 2486, 2499, 2515, 2530, 2539, 2550, 2559, 2568, 2581, 2590, 2603, 2616, 2623, 2633, 2648, 2656, 2663}
|
||||
var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 57, 77, 84, 92, 110, 118, 127, 144, 165, 180, 201, 225, 240, 258, 267, 287, 301, 316, 336, 351, 371, 391, 411, 430, 448, 462, 474, 490, 506, 522, 543, 565, 580, 594, 608, 621, 638, 646, 659, 675, 687, 695, 709, 723, 740, 751, 762, 776, 794, 811, 818, 837, 859, 871, 885, 894, 909, 921, 934, 945, 956, 968, 982, 1003, 1018, 1031, 1048, 1066, 1082, 1094, 1106, 1119, 1134, 1148, 1160, 1172, 1189, 1196, 1208, 1213, 1223, 1232, 1243, 1254, 1267, 1282, 1293, 1306, 1321, 1328, 1341, 1354, 1371, 1386, 1399, 1413, 1427, 1443, 1463, 1487, 1499, 1522, 1539, 1557, 1580, 1598, 1621, 1644, 1667, 1689, 1710, 1725, 1744, 1763, 1787, 1805, 1822, 1840, 1850, 1864, 1889, 1908, 1928, 1953, 1973, 1998, 2023, 2048, 2072, 2095, 2112, 2133, 2154, 2180, 2200, 2219, 2239, 2250, 2259, 2269, 2282, 2298, 2310, 2324, 2340, 2358, 2378, 2400, 2414, 2429, 2437, 2443, 2457, 2472, 2482, 2498, 2513, 2523, 2530, 2538, 2545, 2554, 2567, 2583, 2598, 2607, 2618, 2627, 2636, 2649, 2658, 2671, 2684, 2691, 2701, 2716, 2724, 2731}
|
||||
|
||||
func (i actionType) String() string {
|
||||
if i < 0 || i >= actionType(len(_actionType_index)-1) {
|
||||
idx := int(i) - 0
|
||||
if i < 0 || idx >= len(_actionType_index)-1 {
|
||||
return "actionType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _actionType_name[_actionType_index[i]:_actionType_index[i+1]]
|
||||
return _actionType_name[_actionType_index[idx]:_actionType_index[idx+1]]
|
||||
}
|
||||
@@ -264,7 +264,6 @@ func Run(opts *Options) (int, error) {
|
||||
}
|
||||
|
||||
pattern := patternBuilder([]rune(*opts.Filter))
|
||||
matcher.sort = pattern.sortable
|
||||
|
||||
transformer := buildItemTransformer(opts)
|
||||
|
||||
|
||||
+14
-7
@@ -1672,21 +1672,21 @@ const (
|
||||
|
||||
func init() {
|
||||
argActionRegexp = regexp.MustCompile(
|
||||
`(?si)[:+](become|execute(?:-multi|-silent)?|reload(?:-sync)?|preview|(?:change|bg-transform|transform)-(?:query|prompt|(?:border|list|preview|input|header|footer)-label|header-lines|header|footer|search|with-nth|nth|pointer|ghost)|bg-transform|transform|change-(?:preview-window|preview|multi)|(?:re|un|toggle-)bind|pos|put|print|search|trigger)`)
|
||||
`(?si)[:+](become|execute(?:-multi|-silent)?|reload(?:-sync)?|preview|(?:change|bg-transform|transform)-(?:query|prompt|(?:border|list|preview|input|header|footer)-label|header-lines|header|footer|search|with-nth|nth|pointer|ghost|info-command)|bg-transform|transform|change-(?:preview-window|preview|multi)|(?:re|un|toggle-)bind|pos|put|print|search|trigger)`)
|
||||
splitRegexp = regexp.MustCompile("[,:]+")
|
||||
actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+")
|
||||
}
|
||||
|
||||
func maskActionContents(action string) string {
|
||||
masked := ""
|
||||
var sb strings.Builder
|
||||
Loop:
|
||||
for len(action) > 0 {
|
||||
loc := argActionRegexp.FindStringIndex(action)
|
||||
if loc == nil {
|
||||
masked += action
|
||||
sb.WriteString(action)
|
||||
break
|
||||
}
|
||||
masked += action[:loc[1]]
|
||||
sb.WriteString(action[:loc[1]])
|
||||
action = action[loc[1]:]
|
||||
if len(action) == 0 {
|
||||
break
|
||||
@@ -1695,7 +1695,7 @@ Loop:
|
||||
var ce string
|
||||
switch action[0] {
|
||||
case ':':
|
||||
masked += strings.Repeat(" ", len(action))
|
||||
sb.WriteString(strings.Repeat(" ", len(action)))
|
||||
break Loop
|
||||
case '(':
|
||||
ce = ")"
|
||||
@@ -1716,7 +1716,7 @@ Loop:
|
||||
// @$ or @+
|
||||
loc = regexp.MustCompile(fmt.Sprintf(`(?s)^%s.*?(%s[+,]|%s$)`, cs, ce, ce)).FindStringIndex(action)
|
||||
if loc == nil {
|
||||
masked += action
|
||||
sb.WriteString(action)
|
||||
break
|
||||
}
|
||||
// Keep + or , at the end
|
||||
@@ -1724,9 +1724,10 @@ Loop:
|
||||
if lastChar == '+' || lastChar == ',' {
|
||||
loc[1]--
|
||||
}
|
||||
masked += strings.Repeat(" ", loc[1])
|
||||
sb.WriteString(strings.Repeat(" ", loc[1]))
|
||||
action = action[loc[1]:]
|
||||
}
|
||||
masked := sb.String()
|
||||
masked = strings.ReplaceAll(masked, ",,,", string([]rune{',', escapedComma, ','}))
|
||||
masked = strings.ReplaceAll(masked, ",:,", string([]rune{',', escapedColon, ','}))
|
||||
masked = strings.ReplaceAll(masked, "::", string([]rune{escapedColon, ':'}))
|
||||
@@ -2100,6 +2101,8 @@ func isExecuteAction(str string) actionType {
|
||||
return actChangeHeaderLabel
|
||||
case "change-footer-label":
|
||||
return actChangeFooterLabel
|
||||
case "change-info-command":
|
||||
return actChangeInfoCommand
|
||||
case "change-ghost":
|
||||
return actChangeGhost
|
||||
case "change-pointer":
|
||||
@@ -2144,6 +2147,8 @@ func isExecuteAction(str string) actionType {
|
||||
return actTransformHeaderLabel
|
||||
case "transform-footer-label":
|
||||
return actTransformFooterLabel
|
||||
case "transform-info-command":
|
||||
return actTransformInfoCommand
|
||||
case "transform-footer":
|
||||
return actTransformFooter
|
||||
case "transform-header":
|
||||
@@ -2178,6 +2183,8 @@ func isExecuteAction(str string) actionType {
|
||||
return actBgTransformHeaderLabel
|
||||
case "bg-transform-footer-label":
|
||||
return actBgTransformFooterLabel
|
||||
case "bg-transform-info-command":
|
||||
return actBgTransformInfoCommand
|
||||
case "bg-transform-footer":
|
||||
return actBgTransformFooter
|
||||
case "bg-transform-header":
|
||||
|
||||
+20
-22
@@ -275,22 +275,12 @@ func (r *Reader) readFiles(roots []string, opts walkerOpts, ignores []string) bo
|
||||
Sort: fastwalk.SortFilesFirst,
|
||||
}
|
||||
|
||||
// When following symlinks, precompute the absolute real paths of walker
|
||||
// roots so we can skip symlinks that point to an ancestor. fastwalk's
|
||||
// built-in loop detection (shouldTraverse) catches loops on the second
|
||||
// pass, but a single pass through a symlink like z: -> / already
|
||||
// traverses the entire root filesystem, causing severe resource
|
||||
// exhaustion. Skipping ancestor symlinks prevents this entirely.
|
||||
var absRoots []string
|
||||
if opts.follow {
|
||||
for _, root := range roots {
|
||||
if real, err := filepath.EvalSymlinks(root); err == nil {
|
||||
if abs, err := filepath.Abs(real); err == nil {
|
||||
absRoots = append(absRoots, filepath.Clean(abs))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// When following symlinks, skip targets that point to an ancestor of the
|
||||
// current walker root. fastwalk's built-in loop detection (shouldTraverse)
|
||||
// catches loops on the second pass, but a single pass through a symlink
|
||||
// like z: -> / already traverses the entire root filesystem, causing
|
||||
// severe resource exhaustion. Skipping ancestor symlinks prevents this.
|
||||
var absRoot string
|
||||
|
||||
ignoresBase := []string{}
|
||||
ignoresFull := []string{}
|
||||
@@ -326,19 +316,17 @@ func (r *Reader) readFiles(roots []string, opts walkerOpts, ignores []string) bo
|
||||
return filepath.SkipDir
|
||||
}
|
||||
// Skip symlinks whose target is an ancestor of (or equal to)
|
||||
// any walker root. Following such symlinks would traverse a
|
||||
// the current walker root. Following such symlinks would traverse a
|
||||
// superset of the tree we're already walking.
|
||||
if isDirSymlink && len(absRoots) > 0 {
|
||||
if isDirSymlink && absRoot != "" {
|
||||
if target, err := filepath.EvalSymlinks(path); err == nil {
|
||||
if abs, err := filepath.Abs(target); err == nil {
|
||||
abs = filepath.Clean(abs)
|
||||
if abs == string(os.PathSeparator) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
for _, absRoot := range absRoots {
|
||||
if absRoot == abs || strings.HasPrefix(absRoot, abs+string(os.PathSeparator)) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if absRoot == abs || strings.HasPrefix(absRoot, abs+string(os.PathSeparator)) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -377,6 +365,16 @@ func (r *Reader) readFiles(roots []string, opts walkerOpts, ignores []string) bo
|
||||
}
|
||||
noerr := true
|
||||
for _, root := range roots {
|
||||
// Compare against this root only. Safe to update here because
|
||||
// fastwalk.Walk returns after all its workers finish.
|
||||
absRoot = ""
|
||||
if opts.follow {
|
||||
if real, err := filepath.EvalSymlinks(root); err == nil {
|
||||
if abs, err := filepath.Abs(real); err == nil {
|
||||
absRoot = filepath.Clean(abs)
|
||||
}
|
||||
}
|
||||
}
|
||||
noerr = noerr && (fastwalk.Walk(&conf, root, fn) == nil)
|
||||
}
|
||||
return noerr
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package fzf
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -66,3 +70,70 @@ func TestReadFromCommand(t *testing.T) {
|
||||
t.Error("EvtReadFin should be set")
|
||||
}
|
||||
}
|
||||
|
||||
func walkFiles(t *testing.T, roots ...string) []string {
|
||||
t.Helper()
|
||||
var mu sync.Mutex
|
||||
files := []string{}
|
||||
reader := NewReader(func(data []byte) bool {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
files = append(files, filepath.FromSlash(string(data)))
|
||||
return true
|
||||
}, util.NewEventBox(), nil, false, false)
|
||||
if !reader.readFiles(roots, walkerOpts{file: true, follow: true}, nil) {
|
||||
t.Fatal("file walk failed")
|
||||
}
|
||||
slices.Sort(files)
|
||||
return files
|
||||
}
|
||||
|
||||
func TestReadFilesSymlinkAcrossRoots(t *testing.T) {
|
||||
base := t.TempDir()
|
||||
app := filepath.Join(base, "app")
|
||||
shared := filepath.Join(base, "shared")
|
||||
frontend := filepath.Join(shared, "frontend")
|
||||
os.MkdirAll(app, 0755)
|
||||
os.MkdirAll(frontend, 0755)
|
||||
os.WriteFile(filepath.Join(shared, "docs.txt"), nil, 0644)
|
||||
os.WriteFile(filepath.Join(frontend, "index.js"), nil, 0644)
|
||||
if err := os.Symlink(filepath.Join("..", "shared"), filepath.Join(app, "shared")); err != nil {
|
||||
t.Skipf("cannot create symlink: %v", err)
|
||||
}
|
||||
|
||||
viaApp := []string{
|
||||
filepath.Join(app, "shared", "docs.txt"),
|
||||
filepath.Join(app, "shared", "frontend", "index.js"),
|
||||
}
|
||||
both := append(slices.Clone(viaApp), filepath.Join(frontend, "index.js"))
|
||||
slices.Sort(both)
|
||||
for _, tc := range []struct {
|
||||
roots []string
|
||||
want []string
|
||||
}{
|
||||
{[]string{app}, viaApp},
|
||||
{[]string{app, frontend}, both},
|
||||
{[]string{frontend, app}, both},
|
||||
} {
|
||||
if files := walkFiles(t, tc.roots...); !slices.Equal(files, tc.want) {
|
||||
t.Errorf("roots = %v, files = %v, want %v", tc.roots, files, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadFilesSkipsAncestorSymlinks(t *testing.T) {
|
||||
base := t.TempDir()
|
||||
project := filepath.Join(base, "project")
|
||||
os.Mkdir(project, 0755)
|
||||
file := filepath.Join(project, "file.txt")
|
||||
os.WriteFile(file, nil, 0644)
|
||||
os.WriteFile(filepath.Join(base, "outside.txt"), nil, 0644)
|
||||
for name, target := range map[string]string{"parent": "..", "self": "."} {
|
||||
if err := os.Symlink(target, filepath.Join(project, name)); err != nil {
|
||||
t.Skipf("cannot create symlink: %v", err)
|
||||
}
|
||||
}
|
||||
if files := walkFiles(t, project); !slices.Equal(files, []string{file}) {
|
||||
t.Errorf("files = %v, want [%s]", files, file)
|
||||
}
|
||||
}
|
||||
@@ -589,6 +589,7 @@ const (
|
||||
actChangeFooter
|
||||
actChangeHeaderLabel
|
||||
actChangeFooterLabel
|
||||
actChangeInfoCommand
|
||||
actChangeInputLabel
|
||||
actChangeListLabel
|
||||
actChangeMulti
|
||||
@@ -676,6 +677,7 @@ const (
|
||||
actTransformFooter
|
||||
actTransformHeaderLabel
|
||||
actTransformFooterLabel
|
||||
actTransformInfoCommand
|
||||
actTransformInputLabel
|
||||
actTransformListLabel
|
||||
actTransformNth
|
||||
@@ -696,6 +698,7 @@ const (
|
||||
actBgTransformFooter
|
||||
actBgTransformHeaderLabel
|
||||
actBgTransformFooterLabel
|
||||
actBgTransformInfoCommand
|
||||
actBgTransformInputLabel
|
||||
actBgTransformListLabel
|
||||
actBgTransformNth
|
||||
@@ -764,6 +767,7 @@ func processExecution(action actionType) bool {
|
||||
actTransformFooter,
|
||||
actTransformHeaderLabel,
|
||||
actTransformFooterLabel,
|
||||
actTransformInfoCommand,
|
||||
actTransformInputLabel,
|
||||
actTransformListLabel,
|
||||
actTransformNth,
|
||||
@@ -781,6 +785,7 @@ func processExecution(action actionType) bool {
|
||||
actBgTransformFooter,
|
||||
actBgTransformHeaderLabel,
|
||||
actBgTransformFooterLabel,
|
||||
actBgTransformInfoCommand,
|
||||
actBgTransformInputLabel,
|
||||
actBgTransformListLabel,
|
||||
actBgTransformNth,
|
||||
@@ -792,6 +797,7 @@ func processExecution(action actionType) bool {
|
||||
actBgTransformSearch,
|
||||
actPreview,
|
||||
actChangePreview,
|
||||
actChangeInfoCommand,
|
||||
actRefreshPreview,
|
||||
actExecute,
|
||||
actExecuteSilent,
|
||||
@@ -7447,6 +7453,13 @@ func (t *Terminal) Loop() error {
|
||||
t.footerLabel, t.footerLabelLen = t.ansiLabelPrinter(label, &tui.ColFooterLabel, false)
|
||||
req(reqRedrawFooterLabel)
|
||||
})
|
||||
case actChangeInfoCommand, actTransformInfoCommand, actBgTransformInfoCommand:
|
||||
capture(true, func(command string) {
|
||||
if t.infoCommand != command {
|
||||
t.infoCommand = command
|
||||
req(reqInfo)
|
||||
}
|
||||
})
|
||||
case actChangeInputLabel, actTransformInputLabel, actBgTransformInputLabel:
|
||||
capture(true, func(label string) {
|
||||
t.inputLabelOpts.label = label
|
||||
|
||||
@@ -1826,6 +1826,36 @@ class TestCore < TestInteractive
|
||||
tmux.until { assert_match(/^ 2 xx/, it[-2]) }
|
||||
end
|
||||
|
||||
def test_change_info_command
|
||||
tmux.send_keys(%(seq 100 | #{FZF} --separator x --bind 'a:change-info-command(echo {}: $FZF_INFO)' --bind 'b:change-info-command()'), :Enter)
|
||||
tmux.until { assert_match(%r{^ 100/100 xx}, it[-2]) }
|
||||
tmux.send_keys :a
|
||||
tmux.until { assert_match(%r{^ 1: 100/100 xx}, it[-2]) }
|
||||
# Placeholders are evaluated on each update, not when the action runs
|
||||
tmux.send_keys :Up
|
||||
tmux.until { assert_match(%r{^ 2: 100/100 xx}, it[-2]) }
|
||||
tmux.send_keys :b
|
||||
tmux.until { assert_match(%r{^ 100/100 xx}, it[-2]) }
|
||||
end
|
||||
|
||||
def test_transform_info_command
|
||||
tmux.send_keys(%(seq 100 | #{FZF} --separator x --bind 'a:transform-info-command(echo "echo {}: \\$FZF_POS")'), :Enter)
|
||||
tmux.until { assert_match(%r{^ 100/100 xx}, it[-2]) }
|
||||
tmux.send_keys :a
|
||||
tmux.until { assert_match(%r{^ 1: 1 xx}, it[-2]) }
|
||||
tmux.send_keys :Up
|
||||
tmux.until { assert_match(%r{^ 1: 2 xx}, it[-2]) }
|
||||
end
|
||||
|
||||
def test_bg_transform_info_command
|
||||
tmux.send_keys(%(seq 100 | #{FZF} --separator x --bind 'a:bg-transform-info-command(sleep 0.5; echo "echo {}: \\$FZF_POS")'), :Enter)
|
||||
tmux.until { assert_match(%r{^ 100/100 xx}, it[-2]) }
|
||||
tmux.send_keys :a
|
||||
tmux.until { assert_match(%r{^ 1: 1 xx}, it[-2]) }
|
||||
tmux.send_keys :Up
|
||||
tmux.until { assert_match(%r{^ 1: 2 xx}, it[-2]) }
|
||||
end
|
||||
|
||||
def test_prev_next_selected
|
||||
tmux.send_keys 'seq 10 | fzf --multi --bind ctrl-n:next-selected,ctrl-p:prev-selected', :Enter
|
||||
tmux.until { |lines| assert_equal 10, lines.match_count }
|
||||
|
||||
@@ -25,6 +25,15 @@ class TestFilter < TestBase
|
||||
assert_equal 1, `echo Foo bar | #{FZF} -x -f "foo Fbar" | wc -l`.to_i
|
||||
end
|
||||
|
||||
def test_filter_no_sort
|
||||
input = "printf 'abz\\nab\\nzab\\n'"
|
||||
['', '--sync'].each do |opts|
|
||||
assert_equal %w[ab abz zab], `#{input} | #{FZF} -f ab #{opts}`.lines(chomp: true)
|
||||
assert_equal %w[abz ab zab], `#{input} | #{FZF} -f ab --no-sort #{opts}`.lines(chomp: true)
|
||||
assert_equal %w[zab ab abz], `#{input} | #{FZF} -f ab --no-sort --tac #{opts}`.lines(chomp: true)
|
||||
end
|
||||
end
|
||||
|
||||
def test_filter_exitstatus
|
||||
# filter / streaming filter
|
||||
['', '--no-sort'].each do |opts|
|
||||
|
||||
Reference in new issue
Block a user