Compare commits

..

2 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] 336cfdef02 Fix nushell contamination in install loop 2026-05-28 00:34:17 +00:00
copilot-swe-agent[bot] eee9672eb0 Initial plan 2026-05-28 00:32:09 +00:00
16 changed files with 63 additions and 209 deletions
-12
View File
@@ -1,18 +1,6 @@
CHANGELOG CHANGELOG
========= =========
0.74.0 (WIP)
------------
- Added `result-final` event, a variant of `result` that is not triggered while the input stream is still open (#4835)
- Use it for one-shot, per-query actions that would otherwise re-fire on every intermediate snapshot during loading
```sh
# 'result' fires per intermediate snapshot (header keeps updating during load);
# 'result-final' fires once after the stream closes (footer shows the final count)
(seq 100; sleep 1; seq 100) | fzf --query 1 \
--bind 'result:transform-header(echo result: $FZF_MATCH_COUNT),result-final:transform-footer(echo final: $FZF_MATCH_COUNT)'
```
- Bound `alt-left` to `backward-word` and `alt-right` to `forward-word` by default (#4833)
0.73.1 0.73.1
------ ------
- Bug fixes - Bug fixes
+1 -11
View File
@@ -1,15 +1,5 @@
FROM rubylang/ruby:3.4.1-noble FROM rubylang/ruby:3.4.1-noble
RUN apt-get update && apt-get install -y git make golang zsh fish tmux RUN apt-get update -y && apt install -y git make golang zsh fish tmux
# https://www.nushell.sh/book/installation.html
RUN <<EOF
set -ex
apt-get install -y wget gnupg
wget -qO- https://apt.fury.io/nushell/gpg.key | gpg --dearmor -o /etc/apt/keyrings/fury-nushell.gpg
echo "deb [signed-by=/etc/apt/keyrings/fury-nushell.gpg] https://apt.fury.io/nushell/ /" | tee /etc/apt/sources.list.d/fury-nushell.list
apt-get update
apt-get install -y nushell
EOF
RUN gem install --no-document -v 5.22.3 minitest RUN gem install --no-document -v 5.22.3 minitest
RUN echo '. /usr/share/bash-completion/completions/git' >> ~/.bashrc RUN echo '. /usr/share/bash-completion/completions/git' >> ~/.bashrc
RUN echo '. ~/.bashrc' >> ~/.bash_profile RUN echo '. ~/.bashrc' >> ~/.bash_profile
+3 -3
View File
@@ -227,13 +227,13 @@ fi
for s in $shells; do for s in $shells; do
bin=$s bin=$s
[[ $s == nushell ]] && bin=nu [[ "$s" = nushell ]] && bin=nu
if ! command -v "$bin" > /dev/null; then if ! command -v "$bin" > /dev/null; then
shells=${shells/$s/} shells=${shells/$s/}
fi fi
done done
if [[ -z ${shells// /} ]]; then if [[ ${#shells} -lt 3 ]]; then
echo "No shell configuration to be updated." echo "No shell configuration to be updated."
exit 0 exit 0
fi fi
@@ -442,7 +442,7 @@ if [[ $shells =~ fish ]]; then
fi fi
fi fi
if [[ $shells =~ nushell ]]; then if [[ "$shells" =~ nushell ]]; then
if [[ $key_bindings -eq 1 || $auto_completion -eq 1 ]]; then if [[ $key_bindings -eq 1 || $auto_completion -eq 1 ]]; then
echo "Setting up Nushell integration ..." echo "Setting up Nushell integration ..."
nushell_autoload_dir=$(nu -c '$nu.user-autoload-dirs | first') nushell_autoload_dir=$(nu -c '$nu.user-autoload-dirs | first')
+3 -17
View File
@@ -226,7 +226,7 @@ Enable processing of ANSI color codes
Synchronous search for multi-staged filtering. If specified, fzf will launch Synchronous search for multi-staged filtering. If specified, fzf will launch
the finder only after the input stream is complete and the initial filtering the finder only after the input stream is complete and the initial filtering
and the associated actions (bound to any of \fBstart\fR, \fBload\fR, and the associated actions (bound to any of \fBstart\fR, \fBload\fR,
\fBresult\fR, \fBresult\-final\fR, or \fBfocus\fR) are complete. \fBresult\fR, or \fBfocus\fR) are complete.
.RS .RS
e.g. \fB# Avoid rendering both fzf instances at the same time e.g. \fB# Avoid rendering both fzf instances at the same time
@@ -1855,20 +1855,6 @@ e.g.
# * Note that you can't use 'change' event in this case because the second position may not be available # * Note that you can't use 'change' event in this case because the second position may not be available
fzf \-\-sync \-\-bind 'result:transform:[[ \-z {q} ]] && echo "pos(2)"'\fR fzf \-\-sync \-\-bind 'result:transform:[[ \-z {q} ]] && echo "pos(2)"'\fR
.RE .RE
\fIresult\-final\fR
.RS
Same as \fIresult\fR, but suppressed while the input stream is still open. Use
this when you want a one-shot action per query instead of one per intermediate
snapshot during loading.
e.g.
\fB# 'result' fires per intermediate snapshot (header keeps updating during load);
# 'result-final' fires once after the stream closes (footer shows the final count)
(seq 100; sleep 1; seq 100) | fzf \-\-query 1 \\
\-\-bind 'result:transform\-header(echo result: $FZF_MATCH_COUNT),result\-final:transform\-footer(echo final: $FZF_MATCH_COUNT)'\fR
.RE
\fIchange\fR \fIchange\fR
.RS .RS
Triggered whenever the query string is changed Triggered whenever the query string is changed
@@ -2012,7 +1998,7 @@ A key or an event can be bound to one or more of the following actions.
\fBbackward\-kill\-subword\fR \fBbackward\-kill\-subword\fR
\fBbackward\-kill\-word\fR \fIalt\-bs\fR \fBbackward\-kill\-word\fR \fIalt\-bs\fR
\fBbackward\-subword\fR \fBbackward\-subword\fR
\fBbackward\-word\fR \fIalt\-b shift\-left alt\-left\fR \fBbackward\-word\fR \fIalt\-b shift\-left\fR
\fBbecome(...)\fR (replace fzf process with the specified command; see below for the details) \fBbecome(...)\fR (replace fzf process with the specified command; see below for the details)
\fBbeginning\-of\-line\fR \fIctrl\-a home\fR \fBbeginning\-of\-line\fR \fIctrl\-a home\fR
\fBbell\fR (ring the terminal bell) \fBbell\fR (ring the terminal bell)
@@ -2059,7 +2045,7 @@ A key or an event can be bound to one or more of the following actions.
\fBfirst\fR (move to the first match; same as \fBpos(1)\fR) \fBfirst\fR (move to the first match; same as \fBpos(1)\fR)
\fBforward\-char\fR \fIctrl\-f right\fR \fBforward\-char\fR \fIctrl\-f right\fR
\fBforward\-subword\fR \fBforward\-subword\fR
\fBforward\-word\fR \fIalt\-f shift\-right alt\-right\fR \fBforward\-word\fR \fIalt\-f shift\-right\fR
\fBignore\fR \fBignore\fR
\fBjump\fR (EasyMotion-like 2-keystroke movement) \fBjump\fR (EasyMotion-like 2-keystroke movement)
\fBkill\-line\fR \fBkill\-line\fR
+1 -1
View File
@@ -152,7 +152,7 @@ function fzf_key_bindings
# Enable syntax highlighting colors on fish v4.3.3 and newer # Enable syntax highlighting colors on fish v4.3.3 and newer
if string match -qr -- '^\\d\\d+|^4\\.[4-9]|^4\\.3\\.[3-9]' $version if string match -qr -- '^\\d\\d+|^4\\.[4-9]|^4\\.3\\.[3-9]' $version
set -a -- FZF_DEFAULT_OPTS '--ansi' set -a -- FZF_DEFAULT_OPTS '--ansi'
set -a -- FZF_DEFAULT_COMMAND '--color=always --show-time=(set_color $fish_color_comment 2>/dev/null; or set_color normal)"%F %a %T%t%s%t"(set_color normal)' set -a -- FZF_DEFAULT_COMMAND '--color=always --show-time=(set_color $fish_color_comment)"%F %a %T%t%s%t"(set_color $fish_color_normal)'
else else
set -a -- FZF_DEFAULT_COMMAND '--show-time="%F %a %T%t%s%t"' set -a -- FZF_DEFAULT_COMMAND '--show-time="%F %a %T%t%s%t"'
end end
+1 -7
View File
@@ -110,14 +110,8 @@ fzf-cd-widget() {
zle redisplay zle redisplay
return 0 return 0
fi fi
# Use subshell expansion to get the absolute PWD of the target dir.
# This allows the recorded shell history to be reused even from a different
# working directory.
# If failed, fallback to the unexpanded path to surface the error to the user.
# NOTE: Don't use the `:a` modifier as it resolves symlinks like `pwd -P`.
dir=$(builtin cd >/dev/null -- "${dir}" && echo "${PWD}" || echo "${dir}")
zle push-line # Clear buffer. Auto-restored on next prompt. zle push-line # Clear buffer. Auto-restored on next prompt.
BUFFER="builtin cd -- ${(q)dir}" BUFFER="builtin cd -- ${(q)dir:a}"
zle accept-line zle accept-line
local ret=$? local ret=$?
unset dir # ensure this doesn't end up appearing in prompt expansion unset dir # ensure this doesn't end up appearing in prompt expansion
+5 -5
View File
@@ -10,6 +10,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"unicode"
"github.com/junegunn/fzf/src/algo" "github.com/junegunn/fzf/src/algo"
"github.com/junegunn/fzf/src/tui" "github.com/junegunn/fzf/src/tui"
@@ -1063,8 +1064,6 @@ func parseKeyChords(str string, message string) (map[tui.Event]string, []tui.Eve
add(tui.Focus) add(tui.Focus)
case "result": case "result":
add(tui.Result) add(tui.Result)
case "result-final":
add(tui.ResultFinal)
case "resize": case "resize":
add(tui.Resize) add(tui.Resize)
case "one": case "one":
@@ -1735,10 +1734,10 @@ Loop:
return masked return masked
} }
func parseSingleActionList(str string, putAllowed bool) ([]*action, error) { func parseSingleActionList(str string) ([]*action, error) {
// We prepend a colon to satisfy argActionRegexp and remove it later // We prepend a colon to satisfy argActionRegexp and remove it later
masked := maskActionContents(":" + str)[1:] masked := maskActionContents(":" + str)[1:]
return parseActionList(masked, str, []*action{}, putAllowed) return parseActionList(masked, str, []*action{}, false)
} }
func parseActionList(masked string, original string, prevActions []*action, putAllowed bool) ([]*action, error) { func parseActionList(masked string, original string, prevActions []*action, putAllowed bool) ([]*action, error) {
@@ -2044,7 +2043,8 @@ func parseKeymap(keymap map[tui.Event][]*action, str string) error {
} }
key = firstKey(keys) key = firstKey(keys)
} }
keymap[key], err = parseActionList(pair[1], origPairStr[len(pair[0])+1:], keymap[key], key.Printable()) putAllowed := key.Type == tui.Rune && unicode.IsGraphic(key.Char)
keymap[key], err = parseActionList(pair[1], origPairStr[len(pair[0])+1:], keymap[key], putAllowed)
if err != nil { if err != nil {
return err return err
} }
+2 -2
View File
@@ -572,7 +572,7 @@ func TestValidateSign(t *testing.T) {
} }
func TestParseSingleActionList(t *testing.T) { func TestParseSingleActionList(t *testing.T) {
actions, _ := parseSingleActionList("Execute@foo+bar,baz@+up+up+reload:down+down", false) actions, _ := parseSingleActionList("Execute@foo+bar,baz@+up+up+reload:down+down")
if len(actions) != 4 { if len(actions) != 4 {
t.Errorf("Invalid number of actions parsed:%d", len(actions)) t.Errorf("Invalid number of actions parsed:%d", len(actions))
} }
@@ -588,7 +588,7 @@ func TestParseSingleActionList(t *testing.T) {
} }
func TestParseSingleActionListError(t *testing.T) { func TestParseSingleActionListError(t *testing.T) {
_, err := parseSingleActionList("change-query(foobar)baz", false) _, err := parseSingleActionList("change-query(foobar)baz")
if err == nil { if err == nil {
t.Errorf("Failed to detect error") t.Errorf("Failed to detect error")
} }
+1 -4
View File
@@ -198,10 +198,7 @@ func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, t
start := 0 start := 0
ansiToColorPair := func(ansi ansiOffset, base tui.ColorPair) tui.ColorPair { ansiToColorPair := func(ansi ansiOffset, base tui.ColorPair) tui.ColorPair {
if !theme.Colored { if !theme.Colored {
// Ignore ANSI colors but keep the attributes. Retain the base return tui.NewColorPair(-1, -1, ansi.color.attr).MergeAttr(base)
// colors (e.g. an overridden input-bg or list-bg) instead of
// resetting to the terminal default.
return tui.NewColorPair(base.Fg(), base.Bg(), ansi.color.attr).MergeAttr(base)
} }
// fd --color always | fzf --ansi --delimiter / --nth -1 --color fg:dim:strip,nth:regular // fd --color always | fzf --ansi --delimiter / --nth -1 --color fg:dim:strip,nth:regular
if base.ShouldStripColors() { if base.ShouldStripColors() {
+1 -1
View File
@@ -240,7 +240,7 @@ Loop:
} }
body = body[:contentLength] body = body[:contentLength]
actions, err := parseSingleActionList(strings.Trim(string(body), "\r\n"), false) actions, err := parseSingleActionList(strings.Trim(string(body), "\r\n"))
if err != nil { if err != nil {
return bad(err.Error()) return bad(err.Error())
} }
+4 -20
View File
@@ -871,10 +871,8 @@ func defaultKeymap() map[tui.Event][]*action {
addEvent(tui.AltKey('b'), actBackwardWord) addEvent(tui.AltKey('b'), actBackwardWord)
add(tui.ShiftLeft, actBackwardWord) add(tui.ShiftLeft, actBackwardWord)
add(tui.AltLeft, actBackwardWord)
addEvent(tui.AltKey('f'), actForwardWord) addEvent(tui.AltKey('f'), actForwardWord)
add(tui.ShiftRight, actForwardWord) add(tui.ShiftRight, actForwardWord)
add(tui.AltRight, actForwardWord)
addEvent(tui.AltKey('d'), actKillWord) addEvent(tui.AltKey('d'), actKillWord)
add(tui.AltBackspace, actBackwardKillWord) add(tui.AltBackspace, actBackwardKillWord)
@@ -1154,7 +1152,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
bgSemaphore: make(chan struct{}, maxBgProcesses), bgSemaphore: make(chan struct{}, maxBgProcesses),
bgSemaphores: make(map[action]chan struct{}), bgSemaphores: make(map[action]chan struct{}),
keyChan: make(chan tui.Event), keyChan: make(chan tui.Event),
eventChan: make(chan tui.Event, 7), // start | (load + result + result-final + zero|one) | (focus) | (resize) eventChan: make(chan tui.Event, 6), // start | (load + result + zero|one) | (focus) | (resize)
timerChan: make(chan tui.Event), // unbuffered: every() ticks coalesce when main loop is busy timerChan: make(chan tui.Event), // unbuffered: every() ticks coalesce when main loop is busy
tui: renderer, tui: renderer,
ttyDefault: opts.TtyDefault, ttyDefault: opts.TtyDefault,
@@ -1347,9 +1345,6 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
} }
_, t.hasStartActions = t.keymap[tui.Start.AsEvent()] _, t.hasStartActions = t.keymap[tui.Start.AsEvent()]
_, t.hasResultActions = t.keymap[tui.Result.AsEvent()] _, t.hasResultActions = t.keymap[tui.Result.AsEvent()]
if _, prs := t.keymap[tui.ResultFinal.AsEvent()]; prs {
t.hasResultActions = true
}
_, t.hasFocusActions = t.keymap[tui.Focus.AsEvent()] _, t.hasFocusActions = t.keymap[tui.Focus.AsEvent()]
_, t.hasLoadActions = t.keymap[tui.Load.AsEvent()] _, t.hasLoadActions = t.keymap[tui.Load.AsEvent()]
@@ -2027,18 +2022,8 @@ func (t *Terminal) UpdateList(result MatchResult) {
} }
} }
if t.hasResultActions { if t.hasResultActions {
result := tui.Result.AsEvent() t.pendingReqList = true
if _, prs := t.keymap[result]; prs { t.eventChan <- tui.Result.AsEvent()
t.pendingReqList = true
t.eventChan <- result
}
if !t.reading {
resultFinal := tui.ResultFinal.AsEvent()
if _, prs := t.keymap[resultFinal]; prs {
t.pendingReqList = true
t.eventChan <- resultFinal
}
}
} }
updateList := !t.trackBlocked && !t.pendingReqList updateList := !t.trackBlocked && !t.pendingReqList
updatePrompt := trackWasBlocked && !t.trackBlocked updatePrompt := trackWasBlocked && !t.trackBlocked
@@ -6988,8 +6973,7 @@ func (t *Terminal) Loop() error {
}) })
case actTransform, actBgTransform: case actTransform, actBgTransform:
capture(false, func(body string) { capture(false, func(body string) {
// Allow 'put' if the triggering key is a printable character if actions, err := parseSingleActionList(strings.Trim(body, "\r\n")); err == nil {
if actions, err := parseSingleActionList(strings.Trim(body, "\r\n"), event.Printable()); err == nil {
// NOTE: We're not properly passing the return value here // NOTE: We're not properly passing the return value here
doActions(actions) doActions(actions)
} }
+2 -3
View File
@@ -164,12 +164,11 @@ func _() {
_ = x[ClickFooter-153] _ = x[ClickFooter-153]
_ = x[Multi-154] _ = x[Multi-154]
_ = x[Every-155] _ = x[Every-155]
_ = x[ResultFinal-156]
} }
const _EventType_name = "RuneCtrlACtrlBCtrlCCtrlDCtrlECtrlFCtrlGCtrlHTabCtrlJCtrlKCtrlLEnterCtrlNCtrlOCtrlPCtrlQCtrlRCtrlSCtrlTCtrlUCtrlVCtrlWCtrlXCtrlYCtrlZEscCtrlSpaceCtrlBackSlashCtrlRightBracketCtrlCaretCtrlSlashShiftTabBackspaceDeletePageUpPageDownUpDownLeftRightHomeEndInsertShiftUpShiftDownShiftLeftShiftRightShiftDeleteShiftHomeShiftEndShiftPageUpShiftPageDownF1F2F3F4F5F6F7F8F9F10F11F12AltBackspaceAltUpAltDownAltLeftAltRightAltDeleteAltHomeAltEndAltPageUpAltPageDownAltShiftUpAltShiftDownAltShiftLeftAltShiftRightAltShiftDeleteAltShiftHomeAltShiftEndAltShiftPageUpAltShiftPageDownCtrlUpCtrlDownCtrlLeftCtrlRightCtrlHomeCtrlEndCtrlBackspaceCtrlDeleteCtrlPageUpCtrlPageDownAltCtrlAltCtrlAltUpCtrlAltDownCtrlAltLeftCtrlAltRightCtrlAltHomeCtrlAltEndCtrlAltBackspaceCtrlAltDeleteCtrlAltPageUpCtrlAltPageDownCtrlShiftUpCtrlShiftDownCtrlShiftLeftCtrlShiftRightCtrlShiftHomeCtrlShiftEndCtrlShiftDeleteCtrlShiftPageUpCtrlShiftPageDownCtrlAltShiftUpCtrlAltShiftDownCtrlAltShiftLeftCtrlAltShiftRightCtrlAltShiftHomeCtrlAltShiftEndCtrlAltShiftDeleteCtrlAltShiftPageUpCtrlAltShiftPageDownMouseDoubleClickLeftClickRightClickSLeftClickSRightClickScrollUpScrollDownSScrollUpSScrollDownPreviewScrollUpPreviewScrollDownInvalidFatalBracketedPasteBeginBracketedPasteEndResizeChangeBackwardEOFStartLoadFocusOneZeroResultJumpJumpCancelClickHeaderClickFooterMultiEveryResultFinal" const _EventType_name = "RuneCtrlACtrlBCtrlCCtrlDCtrlECtrlFCtrlGCtrlHTabCtrlJCtrlKCtrlLEnterCtrlNCtrlOCtrlPCtrlQCtrlRCtrlSCtrlTCtrlUCtrlVCtrlWCtrlXCtrlYCtrlZEscCtrlSpaceCtrlBackSlashCtrlRightBracketCtrlCaretCtrlSlashShiftTabBackspaceDeletePageUpPageDownUpDownLeftRightHomeEndInsertShiftUpShiftDownShiftLeftShiftRightShiftDeleteShiftHomeShiftEndShiftPageUpShiftPageDownF1F2F3F4F5F6F7F8F9F10F11F12AltBackspaceAltUpAltDownAltLeftAltRightAltDeleteAltHomeAltEndAltPageUpAltPageDownAltShiftUpAltShiftDownAltShiftLeftAltShiftRightAltShiftDeleteAltShiftHomeAltShiftEndAltShiftPageUpAltShiftPageDownCtrlUpCtrlDownCtrlLeftCtrlRightCtrlHomeCtrlEndCtrlBackspaceCtrlDeleteCtrlPageUpCtrlPageDownAltCtrlAltCtrlAltUpCtrlAltDownCtrlAltLeftCtrlAltRightCtrlAltHomeCtrlAltEndCtrlAltBackspaceCtrlAltDeleteCtrlAltPageUpCtrlAltPageDownCtrlShiftUpCtrlShiftDownCtrlShiftLeftCtrlShiftRightCtrlShiftHomeCtrlShiftEndCtrlShiftDeleteCtrlShiftPageUpCtrlShiftPageDownCtrlAltShiftUpCtrlAltShiftDownCtrlAltShiftLeftCtrlAltShiftRightCtrlAltShiftHomeCtrlAltShiftEndCtrlAltShiftDeleteCtrlAltShiftPageUpCtrlAltShiftPageDownMouseDoubleClickLeftClickRightClickSLeftClickSRightClickScrollUpScrollDownSScrollUpSScrollDownPreviewScrollUpPreviewScrollDownInvalidFatalBracketedPasteBeginBracketedPasteEndResizeChangeBackwardEOFStartLoadFocusOneZeroResultJumpJumpCancelClickHeaderClickFooterMultiEvery"
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, 157, 173, 182, 191, 199, 208, 214, 220, 228, 230, 234, 238, 243, 247, 250, 256, 263, 272, 281, 291, 302, 311, 319, 330, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 364, 367, 370, 382, 387, 394, 401, 409, 418, 425, 431, 440, 451, 461, 473, 485, 498, 512, 524, 535, 549, 565, 571, 579, 587, 596, 604, 611, 624, 634, 644, 656, 659, 666, 675, 686, 697, 709, 720, 730, 746, 759, 772, 787, 798, 811, 824, 838, 851, 863, 878, 893, 910, 924, 940, 956, 973, 989, 1004, 1022, 1040, 1060, 1065, 1076, 1085, 1095, 1105, 1116, 1124, 1134, 1143, 1154, 1169, 1186, 1193, 1198, 1217, 1234, 1240, 1246, 1257, 1262, 1266, 1271, 1274, 1278, 1284, 1288, 1298, 1309, 1320, 1325, 1330, 1341} 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, 157, 173, 182, 191, 199, 208, 214, 220, 228, 230, 234, 238, 243, 247, 250, 256, 263, 272, 281, 291, 302, 311, 319, 330, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 364, 367, 370, 382, 387, 394, 401, 409, 418, 425, 431, 440, 451, 461, 473, 485, 498, 512, 524, 535, 549, 565, 571, 579, 587, 596, 604, 611, 624, 634, 644, 656, 659, 666, 675, 686, 697, 709, 720, 730, 746, 759, 772, 787, 798, 811, 824, 838, 851, 863, 878, 893, 910, 924, 940, 956, 973, 989, 1004, 1022, 1040, 1060, 1065, 1076, 1085, 1095, 1105, 1116, 1124, 1134, 1143, 1154, 1169, 1186, 1193, 1198, 1217, 1234, 1240, 1246, 1257, 1262, 1266, 1271, 1274, 1278, 1284, 1288, 1298, 1309, 1320, 1325, 1330}
func (i EventType) String() string { func (i EventType) String() string {
if i < 0 || i >= EventType(len(_EventType_index)-1) { if i < 0 || i >= EventType(len(_EventType_index)-1) {
+38 -51
View File
@@ -4,7 +4,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"unicode"
"github.com/junegunn/fzf/src/util" "github.com/junegunn/fzf/src/util"
"github.com/rivo/uniseg" "github.com/rivo/uniseg"
@@ -234,7 +233,6 @@ const (
ClickFooter ClickFooter
Multi Multi
Every Every
ResultFinal
) )
func (t EventType) AsEvent() Event { func (t EventType) AsEvent() Event {
@@ -254,12 +252,6 @@ func (e Event) Comparable() Event {
return Event{e.Type, e.Char, nil} return Event{e.Type, e.Char, nil}
} }
// Printable returns true if the event is a printable character that can be
// inserted into the query (e.g. via the 'put' action).
func (e Event) Printable() bool {
return e.Type == Rune && unicode.IsGraphic(e.Char)
}
func (e Event) KeyName() string { func (e Event) KeyName() string {
if me := e.MouseEvent; me != nil { if me := e.MouseEvent; me != nil {
return me.Name() return me.Name()
@@ -1003,56 +995,51 @@ func init() {
undefined := ColorAttr{colUndefined, AttrUndefined} undefined := ColorAttr{colUndefined, AttrUndefined}
NoColorTheme = &ColorTheme{ NoColorTheme = &ColorTheme{
Colored: false, Colored: false,
// Root colors. Everything else is left undefined so that overriding a Input: defaultColor,
// root (e.g. --color bw,bg:blue) propagates to the derived colors, Fg: defaultColor,
// just like in the colored base themes. Bg: defaultColor,
Input: defaultColor, ListFg: defaultColor,
Fg: defaultColor, ListBg: defaultColor,
Bg: defaultColor,
DarkBg: defaultColor,
Prompt: defaultColor,
Match: defaultColor,
Spinner: defaultColor,
Info: defaultColor,
Pointer: defaultColor,
Marker: defaultColor,
Header: defaultColor,
Footer: defaultColor,
BorderLabel: defaultColor,
// Derived colors. Left undefined so they inherit from a root.
ListFg: undefined,
ListBg: undefined,
AltBg: undefined, AltBg: undefined,
SelectedFg: undefined, SelectedFg: defaultColor,
SelectedBg: undefined, SelectedBg: defaultColor,
SelectedMatch: undefined, SelectedMatch: defaultColor,
DarkBg: defaultColor,
Prompt: defaultColor,
Match: defaultColor,
Current: undefined, Current: undefined,
CurrentMatch: undefined, CurrentMatch: undefined,
Spinner: defaultColor,
Info: defaultColor,
Pointer: defaultColor,
Marker: defaultColor,
Header: defaultColor,
Border: undefined, Border: undefined,
BorderLabel: defaultColor,
Ghost: undefined, Ghost: undefined,
Disabled: undefined, Disabled: defaultColor,
PreviewFg: undefined, PreviewFg: defaultColor,
PreviewBg: undefined, PreviewBg: defaultColor,
Gutter: undefined, Gutter: undefined,
AltGutter: undefined, AltGutter: undefined,
PreviewBorder: undefined, PreviewBorder: defaultColor,
PreviewScrollbar: undefined, PreviewScrollbar: defaultColor,
PreviewLabel: undefined, PreviewLabel: defaultColor,
ListLabel: undefined, ListLabel: defaultColor,
ListBorder: undefined, ListBorder: defaultColor,
Separator: undefined, Separator: defaultColor,
Scrollbar: undefined, Scrollbar: defaultColor,
InputBg: undefined, InputBg: defaultColor,
InputBorder: undefined, InputBorder: defaultColor,
InputLabel: undefined, InputLabel: defaultColor,
HeaderBg: undefined, HeaderBg: defaultColor,
HeaderBorder: undefined, HeaderBorder: defaultColor,
HeaderLabel: undefined, HeaderLabel: defaultColor,
FooterBg: undefined, FooterBg: defaultColor,
FooterBorder: undefined, FooterBorder: defaultColor,
FooterLabel: undefined, FooterLabel: defaultColor,
GapLine: undefined, GapLine: defaultColor,
Nth: undefined, Nth: undefined,
Nomatch: undefined, Nomatch: undefined,
} }
+1 -2
View File
@@ -136,7 +136,6 @@ class Tmux
rescue Minitest::Assertion rescue Minitest::Assertion
retries += 1 retries += 1
raise if retries > 5 raise if retries > 5
retry retry
end end
send_keys 'clear', :Enter send_keys 'clear', :Enter
@@ -296,7 +295,7 @@ class Tmux
if @shell == :nushell if @shell == :nushell
message = "Prepare[#{tries}]" message = "Prepare[#{tries}]"
send_keys 'C-u', 'C-l' send_keys 'C-u', 'C-l'
sleep(0.2) sleep 0.2
send_keys ' ', 'C-u', :Enter, message send_keys ' ', 'C-u', :Enter, message
self.until { |lines| lines[-1] == message } self.until { |lines| lines[-1] == message }
else else
-29
View File
@@ -971,24 +971,6 @@ class TestCore < TestInteractive
tmux.until { |lines| assert_includes lines[1], ' aabravo/aabravo' } tmux.until { |lines| assert_includes lines[1], ' aabravo/aabravo' }
end end
def test_transform_put
tmux.send_keys %(seq 1000 | #{FZF} --bind 'a:transform:echo put'), :Enter
tmux.until { |lines| assert_equal 1000, lines.match_count }
tmux.send_keys :a
tmux.until { |lines| assert_equal '> a', lines.last }
tmux.send_keys :b
tmux.until { |lines| assert_equal '> ab', lines.last }
end
# The async callback runs in a later iteration, but 'put' must still insert
# the key that triggered the bg-transform (snapshot of the scheduling event).
def test_bg_transform_put
tmux.send_keys %(seq 1000 | #{FZF} --bind 'a:bg-transform:sleep 0.5; echo put'), :Enter
tmux.until { |lines| assert_equal 1000, lines.match_count }
tmux.send_keys 'ab'
tmux.until { |lines| assert_equal '> ba', lines.last }
end
def test_accept_non_empty def test_accept_non_empty
tmux.send_keys %(seq 1000 | #{fzf('--print-query --bind enter:accept-non-empty')}), :Enter tmux.send_keys %(seq 1000 | #{fzf('--print-query --bind enter:accept-non-empty')}), :Enter
tmux.until { |lines| assert_equal 1000, lines.match_count } tmux.until { |lines| assert_equal 1000, lines.match_count }
@@ -1405,17 +1387,6 @@ class TestCore < TestInteractive
tmux.until { |lines| assert_includes lines, '> 1' } tmux.until { |lines| assert_includes lines, '> 1' }
end end
def test_result_final_event
tmux.send_keys %[(seq 100; sleep 1; seq 100) | #{FZF} \\
--query 1 \\
--bind 'result:transform-header(echo "R=$FZF_MATCH_COUNT")' \\
--bind 'result-final:transform-footer(echo "F=$FZF_MATCH_COUNT")'], :Enter
tmux.until { |lines| assert lines.any_include?('R=20') }
tmux.until { |lines| refute lines.any_include?('F=20') }
tmux.until { |lines| assert lines.any_include?('R=40') }
tmux.until { |lines| assert lines.any_include?('F=40') }
end
def test_every_event def test_every_event
tmux.send_keys %(seq 100 | fzf --bind 'every(0.2):transform-prompt(cat #{tempname})'), :Enter tmux.send_keys %(seq 100 | fzf --bind 'every(0.2):transform-prompt(cat #{tempname})'), :Enter
tmux.until { |lines| assert_equal 100, lines.match_count } tmux.until { |lines| assert_equal 100, lines.match_count }
-41
View File
@@ -100,47 +100,6 @@ module TestShell
tmux.until { |lines| assert_equal '/tmp', lines[-1] } tmux.until { |lines| assert_equal '/tmp', lines[-1] }
end end
def test_alt_c_symlink
base = '/tmp/fzf-test-alt-c-symlink'
FileUtils.rm_rf(base)
FileUtils.mkdir_p("#{base}/real/subdir")
FileUtils.ln_s("#{base}/real", "#{base}/link")
tmux.prepare
tmux.send_keys "cd #{base}/link", :Enter
tmux.prepare
tmux.send_keys :Escape, :c
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
tmux.send_keys 'subdir'
tmux.until { |lines| assert_equal 1, lines.match_count }
tmux.send_keys :Enter
tmux.prepare
tmux.send_keys :pwd, :Enter
tmux.until { |lines| assert_equal "#{base}/link/subdir", lines[-1] }
ensure
FileUtils.rm_rf(base)
end
def test_alt_c_absolute_cmd
base = '/tmp/fzf-test-alt-c-absolute'
FileUtils.rm_rf(base)
FileUtils.mkdir_p(base)
set_var('FZF_ALT_C_COMMAND', "echo #{base}")
tmux.prepare
tmux.send_keys 'cd /tmp', :Enter
tmux.prepare
tmux.send_keys :Escape, :c
tmux.until { |lines| assert_equal 1, lines.match_count }
tmux.send_keys :Enter
tmux.prepare
tmux.send_keys :pwd, :Enter
tmux.until { |lines| assert_equal base, lines[-1] }
ensure
FileUtils.rm_rf(base)
end
def test_ctrl_r def test_ctrl_r
tmux.prepare tmux.prepare
tmux.send_keys 'echo 1st', :Enter tmux.send_keys 'echo 1st', :Enter