Compare commits

..

6 Commits

Author SHA1 Message Date
Junegunn Choi 6fefe02546 0.72.0
CodeQL / Analyze (go) (push) Waiting to run
build / build (push) Waiting to run
Test fzf on macOS / build (push) Waiting to run
2026-04-26 18:04:37 +09:00
Junegunn Choi f783582561 Rename internal variables to match user-facing names 2026-04-26 14:47:57 +09:00
Junegunn Choi af42fde089 Fix rubocop errors 2026-04-26 14:47:06 +09:00
Junegunn Choi 27dab2422e Change the example command in the 0.72.0 changelog
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
2026-04-21 18:48:00 +09:00
Junegunn Choi 56be41218c Redraw when change-footer changes line count
Mirror of the earlier change-header fix. The inline footer slot's row
budget depends on footer content length, but resizeIfNeeded() tolerates
a shorter-than-wanted inline window, so extra lines get clipped. Drive
a redraw on length change to re-run the layout.
2026-04-21 18:41:48 +09:00
Junegunn Choi 7782da6c00 Add dashed border style
New --border=dashed / --list-border=dashed / --header-border=dashed etc.
Uses U+2576 (╶) for horizontal edges and U+2506 (┆) for verticals, with
rounded corners (╭╮╰╯) and sharp T-junction mids (├┤). Terminal cells
are taller than wide (~2:1), so horizontals use a sparse stub per cell
while verticals need more dashes per cell to look evenly dashed.
Works with inline sections.
2026-04-20 22:23:41 +09:00
12 changed files with 106 additions and 56 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
go-version: "1.23" go-version: "1.23"
- name: Setup Ruby - name: Setup Ruby
uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1 uses: ruby/setup-ruby@3ff19f5e2baf30647122352b96108b1fbe250c64 # v1
with: with:
ruby-version: 3.4.6 ruby-version: 3.4.6
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
go-version: "1.23" go-version: "1.23"
- name: Setup Ruby - name: Setup Ruby
uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1 uses: ruby/setup-ruby@3ff19f5e2baf30647122352b96108b1fbe250c64 # v1
with: with:
ruby-version: 3.0.0 ruby-version: 3.0.0
+8 -3
View File
@@ -3,19 +3,24 @@ CHANGELOG
0.72.0 0.72.0
------ ------
_Release highlights: https://junegunn.github.io/fzf/releases/0.72.0/_
- `--header-border`, `--header-lines-border`, and `--footer-border` now accept a new `inline` style that embeds the section inside the list frame, separated from the list content by a horizontal line. When the list border has side segments, the separator joins them as T-junctions. - `--header-border`, `--header-lines-border`, and `--footer-border` now accept a new `inline` style that embeds the section inside the list frame, separated from the list content by a horizontal line. When the list border has side segments, the separator joins them as T-junctions.
- Requires a `--list-border` shape that has both top and bottom segments (`rounded`, `sharp`, `bold`, `double`, `block`, `thinblock`, or `horizontal`); falls back to `line` otherwise. `horizontal` has no side borders, so the separator is drawn without T-junction endpoints. - Requires a `--list-border` shape that has both top and bottom segments (`rounded`, `sharp`, `bold`, `double`, `block`, `thinblock`, or `horizontal`); falls back to `line` otherwise. `horizontal` has no side borders, so the separator is drawn without T-junction endpoints.
- Sections stack. Example combining all three: - Sections stack. Example combining all three:
```sh ```sh
ps -ef | fzf --reverse --style full:double \ ps -ef | fzf --reverse --style full \
--header 'Select a process' --header-lines 1 \ --header 'Select a process' --header-lines 1 \
--bind 'load:transform-footer:echo $FZF_TOTAL_COUNT processes' \ --bind 'load:transform-footer:echo $FZF_TOTAL_COUNT processes' \
--header-border=inline --header-lines-border=inline \ --header-border dashed --header-first \
--footer-border=inline --header-lines-border inline --footer-border inline
``` ```
- `--header-label` and `--footer-label` render on their respective separator row. - `--header-label` and `--footer-label` render on their respective separator row.
- The separator inherits `--color list-border` when the section's own border color is not explicitly set. - The separator inherits `--color list-border` when the section's own border color is not explicitly set.
- `inline` takes precedence over `--header-first`: the inline section stays inside the list frame. `--header-border=inline` requires `--header-lines-border` to be `inline` or unset. - `inline` takes precedence over `--header-first`: the inline section stays inside the list frame. `--header-border=inline` requires `--header-lines-border` to be `inline` or unset.
- New `dashed` border style with dashed edges (`` / ``) and rounded corners.
- `--border=dashed`, `--list-border=dashed`, etc.
- Works with inline sections (T-junctions render correctly).
- [vim] Move and resize popup window when detecting `VimResized` event (#4778) (@Vulcalien) - [vim] Move and resize popup window when detecting `VimResized` event (#4778) (@Vulcalien)
- Bug fixes - Bug fixes
- Fixed gutter display in `--style=minimal` - Fixed gutter display in `--style=minimal`
+1 -1
View File
@@ -2,7 +2,7 @@
set -u set -u
version=0.71.0 version=0.72.0
auto_completion= auto_completion=
key_bindings= key_bindings=
update_config=2 update_config=2
+1 -1
View File
@@ -1,4 +1,4 @@
$version="0.71.0" $version="0.72.0"
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition $fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"github.com/junegunn/fzf/src/protector" "github.com/junegunn/fzf/src/protector"
) )
var version = "0.71" var version = "0.72"
var revision = "devel" var revision = "devel"
//go:embed shell/key-bindings.bash //go:embed shell/key-bindings.bash
+1 -1
View File
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
.. ..
.TH fzf\-tmux 1 "Apr 2026" "fzf 0.71.0" "fzf\-tmux - open fzf in tmux split pane" .TH fzf\-tmux 1 "Apr 2026" "fzf 0.72.0" "fzf\-tmux - open fzf in tmux split pane"
.SH NAME .SH NAME
fzf\-tmux - open fzf in tmux split pane fzf\-tmux - open fzf in tmux split pane
+6 -2
View File
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
.. ..
.TH fzf 1 "Apr 2026" "fzf 0.71.0" "fzf - a command-line fuzzy finder" .TH fzf 1 "Apr 2026" "fzf 0.72.0" "fzf - a command-line fuzzy finder"
.SH NAME .SH NAME
fzf - a command-line fuzzy finder fzf - a command-line fuzzy finder
@@ -517,6 +517,8 @@ Draw border around the finder
.br .br
.BR double " Border with double lines" .BR double " Border with double lines"
.br .br
.BR dashed " Border with dashed lines and rounded corners"
.br
.BR block " Border using block elements; suitable when using different background colors" .BR block " Border using block elements; suitable when using different background colors"
.br .br
.BR thinblock " Border using legacy computing symbols; may not be displayed on some terminals" .BR thinblock " Border using legacy computing symbols; may not be displayed on some terminals"
@@ -955,6 +957,8 @@ Should be used with one of the following \fB\-\-preview\-window\fR options.
.br .br
.B * border\-double .B * border\-double
.br .br
.B * border\-dashed
.br
.B * border\-block .B * border\-block
.br .br
.B * border\-thinblock .B * border\-thinblock
@@ -1104,7 +1108,7 @@ separator line between the header window and the list section. \fBinline\fR
style embeds the header inside the list border frame, joined to the list style embeds the header inside the list border frame, joined to the list
section by a horizontal separator; it requires a \fB\-\-list\-border\fR section by a horizontal separator; it requires a \fB\-\-list\-border\fR
shape that has both top and bottom segments (rounded / sharp / bold / shape that has both top and bottom segments (rounded / sharp / bold /
double / block / thinblock / horizontal) and falls back to \fBline\fR double / dashed / block / thinblock / horizontal) and falls back to \fBline\fR
otherwise. When the list border also has side segments, the separator otherwise. When the list border also has side segments, the separator
joins them with T-junctions; \fBhorizontal\fR has no side borders, so the joins them with T-junctions; \fBhorizontal\fR has no side borders, so the
separator is drawn without T-junction endpoints. Takes precedence over separator is drawn without T-junction endpoints. Takes precedence over
+12 -8
View File
@@ -85,7 +85,7 @@ Usage: fzf [options]
--margin=MARGIN Screen margin (TRBL | TB,RL | T,RL,B | T,R,B,L) --margin=MARGIN Screen margin (TRBL | TB,RL | T,RL,B | T,R,B,L)
--padding=PADDING Padding inside border (TRBL | TB,RL | T,RL,B | T,R,B,L) --padding=PADDING Padding inside border (TRBL | TB,RL | T,RL,B | T,R,B,L)
--border[=STYLE] Draw border around the finder --border[=STYLE] Draw border around the finder
[rounded|sharp|bold|block|thinblock|double|horizontal|vertical| [rounded|sharp|bold|block|thinblock|double|dashed|horizontal|vertical|
top|bottom|left|right|line|none] (default: rounded) top|bottom|left|right|line|none] (default: rounded)
--border-label=LABEL Label to print on the border --border-label=LABEL Label to print on the border
--border-label-pos=COL Position of the border label --border-label-pos=COL Position of the border label
@@ -128,7 +128,7 @@ Usage: fzf [options]
(each for list section and preview window) (each for list section and preview window)
--no-scrollbar Hide scrollbar --no-scrollbar Hide scrollbar
--list-border[=STYLE] Draw border around the list section --list-border[=STYLE] Draw border around the list section
[rounded|sharp|bold|block|thinblock|double|horizontal|vertical| [rounded|sharp|bold|block|thinblock|double|dashed|horizontal|vertical|
top|bottom|left|right|none] (default: rounded) top|bottom|left|right|none] (default: rounded)
--list-label=LABEL Label to print on the list border --list-label=LABEL Label to print on the list border
--list-label-pos=COL Position of the list label --list-label-pos=COL Position of the list label
@@ -148,7 +148,7 @@ Usage: fzf [options]
--ghost=TEXT Ghost text to display when the input is empty --ghost=TEXT Ghost text to display when the input is empty
--filepath-word Make word-wise movements respect path separators --filepath-word Make word-wise movements respect path separators
--input-border[=STYLE] Draw border around the input section --input-border[=STYLE] Draw border around the input section
[rounded|sharp|bold|block|thinblock|double|horizontal|vertical| [rounded|sharp|bold|block|thinblock|double|dashed|horizontal|vertical|
top|bottom|left|right|line|none] (default: rounded) top|bottom|left|right|line|none] (default: rounded)
--input-label=LABEL Label to print on the input border --input-label=LABEL Label to print on the input border
--input-label-pos=COL Position of the input label --input-label-pos=COL Position of the input label
@@ -165,7 +165,7 @@ Usage: fzf [options]
[,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES] [,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES]
[,default][,<SIZE_THRESHOLD(ALTERNATIVE_LAYOUT)] [,default][,<SIZE_THRESHOLD(ALTERNATIVE_LAYOUT)]
--preview-border[=STYLE] Short for --preview-window=border-STYLE --preview-border[=STYLE] Short for --preview-window=border-STYLE
[rounded|sharp|bold|block|thinblock|double|horizontal|vertical| [rounded|sharp|bold|block|thinblock|double|dashed|horizontal|vertical|
top|bottom|left|right|line|none] (default: rounded) top|bottom|left|right|line|none] (default: rounded)
--preview-label=LABEL --preview-label=LABEL
--preview-label-pos=N Same as --border-label and --border-label-pos, --preview-label-pos=N Same as --border-label and --border-label-pos,
@@ -177,7 +177,7 @@ Usage: fzf [options]
--header-lines=N The first N lines of the input are treated as header --header-lines=N The first N lines of the input are treated as header
--header-first Print header before the prompt line --header-first Print header before the prompt line
--header-border[=STYLE] Draw border around the header section --header-border[=STYLE] Draw border around the header section
[rounded|sharp|bold|block|thinblock|double|horizontal|vertical| [rounded|sharp|bold|block|thinblock|double|dashed|horizontal|vertical|
top|bottom|left|right|line|inline|none] (default: rounded) top|bottom|left|right|line|inline|none] (default: rounded)
--header-lines-border[=STYLE] --header-lines-border[=STYLE]
Display header from --header-lines with a separate border. Display header from --header-lines with a separate border.
@@ -192,7 +192,7 @@ Usage: fzf [options]
FOOTER FOOTER
--footer=STR String to print as footer --footer=STR String to print as footer
--footer-border[=STYLE] Draw border around the footer section --footer-border[=STYLE] Draw border around the footer section
[rounded|sharp|bold|block|thinblock|double|horizontal|vertical| [rounded|sharp|bold|block|thinblock|double|dashed|horizontal|vertical|
top|bottom|left|right|line|inline|none] (default: line) top|bottom|left|right|line|inline|none] (default: line)
--footer-label=LABEL Label to print on the footer border --footer-label=LABEL Label to print on the footer border
--footer-label-pos=COL Position of the footer label --footer-label-pos=COL Position of the footer label
@@ -968,6 +968,8 @@ func parseBorder(str string, optional bool) (tui.BorderShape, error) {
return tui.BorderThinBlock, nil return tui.BorderThinBlock, nil
case "double": case "double":
return tui.BorderDouble, nil return tui.BorderDouble, nil
case "dashed":
return tui.BorderDashed, nil
case "horizontal": case "horizontal":
return tui.BorderHorizontal, nil return tui.BorderHorizontal, nil
case "vertical": case "vertical":
@@ -986,7 +988,7 @@ func parseBorder(str string, optional bool) (tui.BorderShape, error) {
if optional && str == "" { if optional && str == "" {
return defaultBorderShape, nil return defaultBorderShape, nil
} }
return tui.BorderNone, errors.New("invalid border style (expected: rounded|sharp|bold|block|thinblock|double|horizontal|vertical|top|bottom|left|right|line|inline|none)") return tui.BorderNone, errors.New("invalid border style (expected: rounded|sharp|bold|block|thinblock|double|dashed|horizontal|vertical|top|bottom|left|right|line|inline|none)")
} }
func parseKeyChords(str string, message string) (map[tui.Event]string, []tui.Event, error) { func parseKeyChords(str string, message string) (map[tui.Event]string, []tui.Event, error) {
@@ -1570,7 +1572,7 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, *tui
case "info": case "info":
mergeAttr(&theme.Info) mergeAttr(&theme.Info)
case "pointer": case "pointer":
mergeAttr(&theme.Cursor) mergeAttr(&theme.Pointer)
case "marker": case "marker":
mergeAttr(&theme.Marker) mergeAttr(&theme.Marker)
case "header", "header-fg": case "header", "header-fg":
@@ -2341,6 +2343,8 @@ func parsePreviewWindowImpl(opts *previewOpts, input string) error {
opts.border = tui.BorderThinBlock opts.border = tui.BorderThinBlock
case "border-double": case "border-double":
opts.border = tui.BorderDouble opts.border = tui.BorderDouble
case "border-dashed":
opts.border = tui.BorderDashed
case "noborder", "border-none": case "noborder", "border-none":
opts.border = tui.BorderNone opts.border = tui.BorderNone
case "border-horizontal": case "border-horizontal":
+18 -11
View File
@@ -1816,14 +1816,16 @@ func (t *Terminal) changeHeader(header string) bool {
return needFullRedraw return needFullRedraw
} }
func (t *Terminal) changeFooter(footer string) { func (t *Terminal) changeFooter(footer string) bool {
var lines []string var lines []string
if len(footer) > 0 { if len(footer) > 0 {
lines = strings.Split(strings.TrimSuffix(footer, "\n"), "\n") lines = strings.Split(strings.TrimSuffix(footer, "\n"), "\n")
} }
needFullRedraw := len(t.footer) != len(lines)
t.footer = lines t.footer = lines
t.clickFooterLine = 0 t.clickFooterLine = 0
t.clickFooterColumn = 0 t.clickFooterColumn = 0
return needFullRedraw
} }
// UpdateHeader updates the header // UpdateHeader updates the header
@@ -2155,7 +2157,7 @@ func (t *Terminal) adjustMarginAndPadding() (int, int, [4]int, [4]int) {
if idx == 3 { if idx == 3 {
extraMargin[idx] += 1 + bw extraMargin[idx] += 1 + bw
} }
case tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderBlock, tui.BorderThinBlock, tui.BorderDouble: case tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderBlock, tui.BorderThinBlock, tui.BorderDouble, tui.BorderDashed:
extraMargin[idx] += 1 + bw*(idx%2) extraMargin[idx] += 1 + bw*(idx%2)
} }
marginInt[idx] = sizeSpecToInt(idx, sizeSpec) + extraMargin[idx] marginInt[idx] = sizeSpecToInt(idx, sizeSpec) + extraMargin[idx]
@@ -3017,7 +3019,7 @@ func (t *Terminal) printLabel(window tui.Window, render labelPrinter, opts label
return return
} }
switch borderShape { switch borderShape {
case tui.BorderHorizontal, tui.BorderTop, tui.BorderBottom, tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderBlock, tui.BorderThinBlock, tui.BorderDouble: case tui.BorderHorizontal, tui.BorderTop, tui.BorderBottom, tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderBlock, tui.BorderThinBlock, tui.BorderDouble, tui.BorderDashed:
if redrawBorder { if redrawBorder {
window.DrawHBorder() window.DrawHBorder()
} }
@@ -3602,18 +3604,18 @@ func (t *Terminal) renderEmptyLine(line int, barRange [2]int) {
func (t *Terminal) gutter(current bool, alt bool) { func (t *Terminal) gutter(current bool, alt bool) {
var color tui.ColorPair var color tui.ColorPair
if current { if current {
color = tui.ColCurrentCursorEmpty color = tui.ColCurrentPointerEmpty
} else if !t.raw && t.gutterReverse || t.raw && t.gutterRawReverse { } else if !t.raw && t.gutterReverse || t.raw && t.gutterRawReverse {
if alt { if alt {
color = tui.ColAltCursorEmpty color = tui.ColAltPointerEmpty
} else { } else {
color = tui.ColCursorEmpty color = tui.ColPointerEmpty
} }
} else { } else {
if alt { if alt {
color = tui.ColAltCursorEmptyChar color = tui.ColAltPointerEmptyChar
} else { } else {
color = tui.ColCursorEmptyChar color = tui.ColPointerEmptyChar
} }
} }
gutter := t.pointerEmpty gutter := t.pointerEmpty
@@ -3801,7 +3803,7 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
if len(label) == 0 { if len(label) == 0 {
t.gutter(true, false) t.gutter(true, false)
} else { } else {
t.window.CPrint(tui.ColCurrentCursor, label) t.window.CPrint(tui.ColCurrentPointer, label)
} }
if w-t.markerLen < 0 { if w-t.markerLen < 0 {
return indentSize return indentSize
@@ -3830,7 +3832,7 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
if len(label) == 0 { if len(label) == 0 {
t.gutter(false, index%2 == 1) t.gutter(false, index%2 == 1)
} else { } else {
t.window.CPrint(tui.ColCursor, label) t.window.CPrint(tui.ColPointer, label)
} }
if w-t.markerLen < 0 { if w-t.markerLen < 0 {
return indentSize return indentSize
@@ -6796,7 +6798,12 @@ func (t *Terminal) Loop() error {
}) })
case actChangeFooter, actTransformFooter, actBgTransformFooter: case actChangeFooter, actTransformFooter, actBgTransformFooter:
capture(false, func(footer string) { capture(false, func(footer string) {
t.changeFooter(footer) if t.changeFooter(footer) && t.footerBorderShape == tui.BorderInline {
// resizeIfNeeded() tolerates a shorter-than-wanted inline
// window, so a length change can leave the inline slot
// stale. Force a redraw to re-run the layout.
req(reqRedraw)
}
req(reqFooter) req(reqFooter)
}) })
case actChangeHeaderLabel, actTransformHeaderLabel, actBgTransformHeaderLabel: case actChangeHeaderLabel, actTransformHeaderLabel, actBgTransformHeaderLabel:
+40 -22
View File
@@ -506,7 +506,7 @@ type ColorTheme struct {
CurrentMatch ColorAttr CurrentMatch ColorAttr
Spinner ColorAttr Spinner ColorAttr
Info ColorAttr Info ColorAttr
Cursor ColorAttr Pointer ColorAttr
Marker ColorAttr Marker ColorAttr
Header ColorAttr Header ColorAttr
HeaderBg ColorAttr HeaderBg ColorAttr
@@ -596,6 +596,7 @@ const (
BorderLeft BorderLeft
BorderRight BorderRight
BorderInline BorderInline
BorderDashed
) )
func (s BorderShape) HasLeft() bool { func (s BorderShape) HasLeft() bool {
@@ -759,6 +760,23 @@ func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle {
leftMid: '╠', leftMid: '╠',
rightMid: '╣', rightMid: '╣',
} }
case BorderDashed:
// Terminal cells are taller than wide (~2:1), so horizontals can use a
// sparse stub per cell while verticals need more dashes per cell to look
// evenly dashed. Rounded corners and sharp T-junction mids.
return BorderStyle{
shape: shape,
top: '╶',
bottom: '╶',
left: '┆',
right: '┆',
topLeft: '╭',
topRight: '╮',
bottomLeft: '╰',
bottomRight: '╯',
leftMid: '├',
rightMid: '┤',
}
} }
return BorderStyle{ return BorderStyle{
shape: shape, shape: shape,
@@ -930,18 +948,18 @@ var (
ColDisabled ColorPair ColDisabled ColorPair
ColGhost ColorPair ColGhost ColorPair
ColMatch ColorPair ColMatch ColorPair
ColCursor ColorPair ColPointer ColorPair
ColCursorEmpty ColorPair ColPointerEmpty ColorPair
ColCursorEmptyChar ColorPair ColPointerEmptyChar ColorPair
ColAltCursorEmpty ColorPair ColAltPointerEmpty ColorPair
ColAltCursorEmptyChar ColorPair ColAltPointerEmptyChar ColorPair
ColMarker ColorPair ColMarker ColorPair
ColSelected ColorPair ColSelected ColorPair
ColSelectedMatch ColorPair ColSelectedMatch ColorPair
ColCurrent ColorPair ColCurrent ColorPair
ColCurrentMatch ColorPair ColCurrentMatch ColorPair
ColCurrentCursor ColorPair ColCurrentPointer ColorPair
ColCurrentCursorEmpty ColorPair ColCurrentPointerEmpty ColorPair
ColCurrentMarker ColorPair ColCurrentMarker ColorPair
ColCurrentSelectedEmpty ColorPair ColCurrentSelectedEmpty ColorPair
ColSpinner ColorPair ColSpinner ColorPair
@@ -990,7 +1008,7 @@ func init() {
CurrentMatch: undefined, CurrentMatch: undefined,
Spinner: defaultColor, Spinner: defaultColor,
Info: defaultColor, Info: defaultColor,
Cursor: defaultColor, Pointer: defaultColor,
Marker: defaultColor, Marker: defaultColor,
Header: defaultColor, Header: defaultColor,
Border: undefined, Border: undefined,
@@ -1040,7 +1058,7 @@ func init() {
CurrentMatch: undefined, CurrentMatch: undefined,
Spinner: undefined, Spinner: undefined,
Info: undefined, Info: undefined,
Cursor: undefined, Pointer: undefined,
Marker: undefined, Marker: undefined,
Header: undefined, Header: undefined,
Footer: undefined, Footer: undefined,
@@ -1091,7 +1109,7 @@ func init() {
CurrentMatch: ColorAttr{colBrightGreen, AttrUndefined}, CurrentMatch: ColorAttr{colBrightGreen, AttrUndefined},
Spinner: ColorAttr{colGreen, AttrUndefined}, Spinner: ColorAttr{colGreen, AttrUndefined},
Info: ColorAttr{colYellow, AttrUndefined}, Info: ColorAttr{colYellow, AttrUndefined},
Cursor: ColorAttr{colRed, AttrUndefined}, Pointer: ColorAttr{colRed, AttrUndefined},
Marker: ColorAttr{colMagenta, AttrUndefined}, Marker: ColorAttr{colMagenta, AttrUndefined},
Header: ColorAttr{colCyan, AttrUndefined}, Header: ColorAttr{colCyan, AttrUndefined},
Footer: ColorAttr{colCyan, AttrUndefined}, Footer: ColorAttr{colCyan, AttrUndefined},
@@ -1142,7 +1160,7 @@ func init() {
CurrentMatch: ColorAttr{151, AttrUndefined}, CurrentMatch: ColorAttr{151, AttrUndefined},
Spinner: ColorAttr{148, AttrUndefined}, Spinner: ColorAttr{148, AttrUndefined},
Info: ColorAttr{144, AttrUndefined}, Info: ColorAttr{144, AttrUndefined},
Cursor: ColorAttr{161, AttrUndefined}, Pointer: ColorAttr{161, AttrUndefined},
Marker: ColorAttr{168, AttrUndefined}, Marker: ColorAttr{168, AttrUndefined},
Header: ColorAttr{109, AttrUndefined}, Header: ColorAttr{109, AttrUndefined},
Footer: ColorAttr{109, AttrUndefined}, Footer: ColorAttr{109, AttrUndefined},
@@ -1193,7 +1211,7 @@ func init() {
CurrentMatch: ColorAttr{23, AttrUndefined}, CurrentMatch: ColorAttr{23, AttrUndefined},
Spinner: ColorAttr{65, AttrUndefined}, Spinner: ColorAttr{65, AttrUndefined},
Info: ColorAttr{101, AttrUndefined}, Info: ColorAttr{101, AttrUndefined},
Cursor: ColorAttr{161, AttrUndefined}, Pointer: ColorAttr{161, AttrUndefined},
Marker: ColorAttr{168, AttrUndefined}, Marker: ColorAttr{168, AttrUndefined},
Header: ColorAttr{31, AttrUndefined}, Header: ColorAttr{31, AttrUndefined},
Footer: ColorAttr{31, AttrUndefined}, Footer: ColorAttr{31, AttrUndefined},
@@ -1244,7 +1262,7 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, boldify bool, forceBlac
theme.CurrentMatch = boldify(theme.CurrentMatch) theme.CurrentMatch = boldify(theme.CurrentMatch)
theme.Prompt = boldify(theme.Prompt) theme.Prompt = boldify(theme.Prompt)
theme.Input = boldify(theme.Input) theme.Input = boldify(theme.Input)
theme.Cursor = boldify(theme.Cursor) theme.Pointer = boldify(theme.Pointer)
theme.Spinner = boldify(theme.Spinner) theme.Spinner = boldify(theme.Spinner)
} }
@@ -1288,7 +1306,7 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, boldify bool, forceBlac
theme.CurrentMatch = o(baseTheme.CurrentMatch, currentMatch) theme.CurrentMatch = o(baseTheme.CurrentMatch, currentMatch)
theme.Spinner = o(baseTheme.Spinner, theme.Spinner) theme.Spinner = o(baseTheme.Spinner, theme.Spinner)
theme.Info = o(baseTheme.Info, theme.Info) theme.Info = o(baseTheme.Info, theme.Info)
theme.Cursor = o(baseTheme.Cursor, theme.Cursor) theme.Pointer = o(baseTheme.Pointer, theme.Pointer)
theme.Marker = o(baseTheme.Marker, theme.Marker) theme.Marker = o(baseTheme.Marker, theme.Marker)
theme.Header = o(baseTheme.Header, theme.Header) theme.Header = o(baseTheme.Header, theme.Header)
theme.Footer = o(baseTheme.Footer, theme.Footer) theme.Footer = o(baseTheme.Footer, theme.Footer)
@@ -1404,11 +1422,11 @@ func initPalette(theme *ColorTheme) {
ColDisabled = pair(theme.Disabled, theme.InputBg) ColDisabled = pair(theme.Disabled, theme.InputBg)
ColMatch = pair(theme.Match, theme.ListBg) ColMatch = pair(theme.Match, theme.ListBg)
ColSelectedMatch = pair(theme.SelectedMatch, theme.SelectedBg) ColSelectedMatch = pair(theme.SelectedMatch, theme.SelectedBg)
ColCursor = pair(theme.Cursor, theme.Gutter) ColPointer = pair(theme.Pointer, theme.Gutter)
ColCursorEmpty = pair(blank, theme.Gutter) ColPointerEmpty = pair(blank, theme.Gutter)
ColCursorEmptyChar = pair(theme.Gutter, theme.ListBg) ColPointerEmptyChar = pair(theme.Gutter, theme.ListBg)
ColAltCursorEmpty = pair(blank, theme.AltGutter) ColAltPointerEmpty = pair(blank, theme.AltGutter)
ColAltCursorEmptyChar = pair(theme.AltGutter, theme.ListBg) ColAltPointerEmptyChar = pair(theme.AltGutter, theme.ListBg)
if theme.SelectedBg.Color != theme.ListBg.Color { if theme.SelectedBg.Color != theme.ListBg.Color {
ColMarker = pair(theme.Marker, theme.SelectedBg) ColMarker = pair(theme.Marker, theme.SelectedBg)
} else { } else {
@@ -1416,8 +1434,8 @@ func initPalette(theme *ColorTheme) {
} }
ColCurrent = pair(theme.Current, theme.DarkBg) ColCurrent = pair(theme.Current, theme.DarkBg)
ColCurrentMatch = pair(theme.CurrentMatch, theme.DarkBg) ColCurrentMatch = pair(theme.CurrentMatch, theme.DarkBg)
ColCurrentCursor = pair(theme.Cursor, theme.DarkBg) ColCurrentPointer = pair(theme.Pointer, theme.DarkBg)
ColCurrentCursorEmpty = pair(blank, theme.DarkBg) ColCurrentPointerEmpty = pair(blank, theme.DarkBg)
ColCurrentMarker = pair(theme.Marker, theme.DarkBg) ColCurrentMarker = pair(theme.Marker, theme.DarkBg)
ColCurrentSelectedEmpty = pair(blank, theme.DarkBg) ColCurrentSelectedEmpty = pair(blank, theme.DarkBg)
ColSpinner = pair(theme.Spinner, theme.InputBg) ColSpinner = pair(theme.Spinner, theme.InputBg)
+16 -4
View File
@@ -1497,7 +1497,7 @@ class TestLayout < TestInteractive
tmux.send_keys %(seq 5 | #{FZF} --style full --header foo --header-first --header-border inline), :Enter tmux.send_keys %(seq 5 | #{FZF} --style full --header foo --header-first --header-border inline), :Enter
tmux.until do |lines| tmux.until do |lines|
foo_idx = lines.index { |l| l.match?(/\A│\s+foo\s+│\z/) } foo_idx = lines.index { |l| l.match?(/\A│\s+foo\s+│\z/) }
input_idx = lines.index { |l| l.match?(/\A│\s+>\s+\d+\/\d+\s+│\z/) } input_idx = lines.index { |l| l.match?(%r{\A│\s+>\s+\d+/\d+\s+│\z}) }
foo_idx && input_idx && foo_idx < input_idx foo_idx && input_idx && foo_idx < input_idx
end end
end end
@@ -1510,7 +1510,7 @@ class TestLayout < TestInteractive
tmux.until do |lines| tmux.until do |lines|
one_idx = lines.index { |l| l.match?(/\A│\s+1\s+│\z/) } one_idx = lines.index { |l| l.match?(/\A│\s+1\s+│\z/) }
foo_idx = lines.index { |l| l.match?(/\A│\s+foo\s+│\z/) } foo_idx = lines.index { |l| l.match?(/\A│\s+foo\s+│\z/) }
input_idx = lines.index { |l| l.match?(/\A│\s+>\s+\d+\/\d+\s+│\z/) } input_idx = lines.index { |l| l.match?(%r{\A│\s+>\s+\d+/\d+\s+│\z}) }
one_idx && foo_idx && input_idx && one_idx < input_idx && input_idx < foo_idx one_idx && foo_idx && input_idx && one_idx < input_idx && input_idx < foo_idx
end end
end end
@@ -1522,7 +1522,7 @@ class TestLayout < TestInteractive
tmux.send_keys %(seq 5 | #{FZF} --style full --header-lines 1 --header-first --header-lines-border inline), :Enter tmux.send_keys %(seq 5 | #{FZF} --style full --header-lines 1 --header-first --header-lines-border inline), :Enter
tmux.until do |lines| tmux.until do |lines|
one_idx = lines.index { |l| l.match?(/\A│\s+1\s+│\z/) } one_idx = lines.index { |l| l.match?(/\A│\s+1\s+│\z/) }
input_idx = lines.index { |l| l.match?(/\A│\s+>\s+\d+\/\d+\s+│\z/) } input_idx = lines.index { |l| l.match?(%r{\A│\s+>\s+\d+/\d+\s+│\z}) }
one_idx && input_idx && one_idx < input_idx one_idx && input_idx && one_idx < input_idx
end end
end end
@@ -1534,12 +1534,24 @@ class TestLayout < TestInteractive
def test_inline_change_header_grows_slot def test_inline_change_header_grows_slot
tmux.send_keys %(seq 5 | #{FZF} --style full --header-lines 1 --header-border inline --bind space:change-header:tada), :Enter tmux.send_keys %(seq 5 | #{FZF} --style full --header-lines 1 --header-border inline --bind space:change-header:tada), :Enter
tmux.until { |lines| lines.any_include?(/\A│\s+1\s+│\z/) } tmux.until { |lines| lines.any_include?(/\A│\s+1\s+│\z/) }
tmux.send_keys ' ' tmux.send_keys :Space
tmux.until do |lines| tmux.until do |lines|
lines.any_include?(/\A│\s+1\s+│\z/) && lines.any_include?(/\A│\s+tada\s+│\z/) lines.any_include?(/\A│\s+1\s+│\z/) && lines.any_include?(/\A│\s+tada\s+│\z/)
end end
end end
# Regression: with --footer-border=inline, change-footer that grows the
# footer line count left the inline slot sized for the old length, so
# extra lines were clipped.
def test_inline_change_footer_grows_slot
tmux.send_keys %(seq 5 | #{FZF} --style full --footer-border inline --footer one --bind $'space:change-footer:one\\ntwo'), :Enter
tmux.until { |lines| lines.any_include?(/\A│\s+one\s+│\z/) }
tmux.send_keys :Space
tmux.until do |lines|
lines.any_include?(/\A│\s+one\s+│\z/) && lines.any_include?(/\A│\s+two\s+│\z/)
end
end
# Invalid inline combinations must be rejected at startup. # Invalid inline combinations must be rejected at startup.
def test_inline_rejected_on_unsupported_options def test_inline_rejected_on_unsupported_options
[ [