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"
- name: Setup Ruby
uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1
uses: ruby/setup-ruby@3ff19f5e2baf30647122352b96108b1fbe250c64 # v1
with:
ruby-version: 3.4.6
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
go-version: "1.23"
- name: Setup Ruby
uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1
uses: ruby/setup-ruby@3ff19f5e2baf30647122352b96108b1fbe250c64 # v1
with:
ruby-version: 3.0.0
+8 -3
View File
@@ -3,19 +3,24 @@ CHANGELOG
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.
- 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:
```sh
ps -ef | fzf --reverse --style full:double \
ps -ef | fzf --reverse --style full \
--header 'Select a process' --header-lines 1 \
--bind 'load:transform-footer:echo $FZF_TOTAL_COUNT processes' \
--header-border=inline --header-lines-border=inline \
--footer-border=inline
--header-border dashed --header-first \
--header-lines-border inline --footer-border inline
```
- `--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.
- `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)
- Bug fixes
- Fixed gutter display in `--style=minimal`
+1 -1
View File
@@ -2,7 +2,7 @@
set -u
version=0.71.0
version=0.72.0
auto_completion=
key_bindings=
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
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"github.com/junegunn/fzf/src/protector"
)
var version = "0.71"
var version = "0.72"
var revision = "devel"
//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
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
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
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
fzf - a command-line fuzzy finder
@@ -517,6 +517,8 @@ Draw border around the finder
.br
.BR double " Border with double lines"
.br
.BR dashed " Border with dashed lines and rounded corners"
.br
.BR block " Border using block elements; suitable when using different background colors"
.br
.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
.B * border\-double
.br
.B * border\-dashed
.br
.B * border\-block
.br
.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
section by a horizontal separator; it requires a \fB\-\-list\-border\fR
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
joins them with T-junctions; \fBhorizontal\fR has no side borders, so the
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)
--padding=PADDING Padding inside border (TRBL | TB,RL | T,RL,B | T,R,B,L)
--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)
--border-label=LABEL Label to print on the border
--border-label-pos=COL Position of the border label
@@ -128,7 +128,7 @@ Usage: fzf [options]
(each for list section and preview window)
--no-scrollbar Hide scrollbar
--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)
--list-label=LABEL Label to print on the list border
--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
--filepath-word Make word-wise movements respect path separators
--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)
--input-label=LABEL Label to print on the input border
--input-label-pos=COL Position of the input label
@@ -165,7 +165,7 @@ Usage: fzf [options]
[,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES]
[,default][,<SIZE_THRESHOLD(ALTERNATIVE_LAYOUT)]
--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)
--preview-label=LABEL
--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-first Print header before the prompt line
--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)
--header-lines-border[=STYLE]
Display header from --header-lines with a separate border.
@@ -192,7 +192,7 @@ Usage: fzf [options]
FOOTER
--footer=STR String to print as footer
--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)
--footer-label=LABEL Label to print on the footer border
--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
case "double":
return tui.BorderDouble, nil
case "dashed":
return tui.BorderDashed, nil
case "horizontal":
return tui.BorderHorizontal, nil
case "vertical":
@@ -986,7 +988,7 @@ func parseBorder(str string, optional bool) (tui.BorderShape, error) {
if optional && str == "" {
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) {
@@ -1570,7 +1572,7 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, *tui
case "info":
mergeAttr(&theme.Info)
case "pointer":
mergeAttr(&theme.Cursor)
mergeAttr(&theme.Pointer)
case "marker":
mergeAttr(&theme.Marker)
case "header", "header-fg":
@@ -2341,6 +2343,8 @@ func parsePreviewWindowImpl(opts *previewOpts, input string) error {
opts.border = tui.BorderThinBlock
case "border-double":
opts.border = tui.BorderDouble
case "border-dashed":
opts.border = tui.BorderDashed
case "noborder", "border-none":
opts.border = tui.BorderNone
case "border-horizontal":
+18 -11
View File
@@ -1816,14 +1816,16 @@ func (t *Terminal) changeHeader(header string) bool {
return needFullRedraw
}
func (t *Terminal) changeFooter(footer string) {
func (t *Terminal) changeFooter(footer string) bool {
var lines []string
if len(footer) > 0 {
lines = strings.Split(strings.TrimSuffix(footer, "\n"), "\n")
}
needFullRedraw := len(t.footer) != len(lines)
t.footer = lines
t.clickFooterLine = 0
t.clickFooterColumn = 0
return needFullRedraw
}
// UpdateHeader updates the header
@@ -2155,7 +2157,7 @@ func (t *Terminal) adjustMarginAndPadding() (int, int, [4]int, [4]int) {
if idx == 3 {
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)
}
marginInt[idx] = sizeSpecToInt(idx, sizeSpec) + extraMargin[idx]
@@ -3017,7 +3019,7 @@ func (t *Terminal) printLabel(window tui.Window, render labelPrinter, opts label
return
}
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 {
window.DrawHBorder()
}
@@ -3602,18 +3604,18 @@ func (t *Terminal) renderEmptyLine(line int, barRange [2]int) {
func (t *Terminal) gutter(current bool, alt bool) {
var color tui.ColorPair
if current {
color = tui.ColCurrentCursorEmpty
color = tui.ColCurrentPointerEmpty
} else if !t.raw && t.gutterReverse || t.raw && t.gutterRawReverse {
if alt {
color = tui.ColAltCursorEmpty
color = tui.ColAltPointerEmpty
} else {
color = tui.ColCursorEmpty
color = tui.ColPointerEmpty
}
} else {
if alt {
color = tui.ColAltCursorEmptyChar
color = tui.ColAltPointerEmptyChar
} else {
color = tui.ColCursorEmptyChar
color = tui.ColPointerEmptyChar
}
}
gutter := t.pointerEmpty
@@ -3801,7 +3803,7 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
if len(label) == 0 {
t.gutter(true, false)
} else {
t.window.CPrint(tui.ColCurrentCursor, label)
t.window.CPrint(tui.ColCurrentPointer, label)
}
if w-t.markerLen < 0 {
return indentSize
@@ -3830,7 +3832,7 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
if len(label) == 0 {
t.gutter(false, index%2 == 1)
} else {
t.window.CPrint(tui.ColCursor, label)
t.window.CPrint(tui.ColPointer, label)
}
if w-t.markerLen < 0 {
return indentSize
@@ -6796,7 +6798,12 @@ func (t *Terminal) Loop() error {
})
case actChangeFooter, actTransformFooter, actBgTransformFooter:
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)
})
case actChangeHeaderLabel, actTransformHeaderLabel, actBgTransformHeaderLabel:
+40 -22
View File
@@ -506,7 +506,7 @@ type ColorTheme struct {
CurrentMatch ColorAttr
Spinner ColorAttr
Info ColorAttr
Cursor ColorAttr
Pointer ColorAttr
Marker ColorAttr
Header ColorAttr
HeaderBg ColorAttr
@@ -596,6 +596,7 @@ const (
BorderLeft
BorderRight
BorderInline
BorderDashed
)
func (s BorderShape) HasLeft() bool {
@@ -759,6 +760,23 @@ func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle {
leftMid: '╠',
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{
shape: shape,
@@ -930,18 +948,18 @@ var (
ColDisabled ColorPair
ColGhost ColorPair
ColMatch ColorPair
ColCursor ColorPair
ColCursorEmpty ColorPair
ColCursorEmptyChar ColorPair
ColAltCursorEmpty ColorPair
ColAltCursorEmptyChar ColorPair
ColPointer ColorPair
ColPointerEmpty ColorPair
ColPointerEmptyChar ColorPair
ColAltPointerEmpty ColorPair
ColAltPointerEmptyChar ColorPair
ColMarker ColorPair
ColSelected ColorPair
ColSelectedMatch ColorPair
ColCurrent ColorPair
ColCurrentMatch ColorPair
ColCurrentCursor ColorPair
ColCurrentCursorEmpty ColorPair
ColCurrentPointer ColorPair
ColCurrentPointerEmpty ColorPair
ColCurrentMarker ColorPair
ColCurrentSelectedEmpty ColorPair
ColSpinner ColorPair
@@ -990,7 +1008,7 @@ func init() {
CurrentMatch: undefined,
Spinner: defaultColor,
Info: defaultColor,
Cursor: defaultColor,
Pointer: defaultColor,
Marker: defaultColor,
Header: defaultColor,
Border: undefined,
@@ -1040,7 +1058,7 @@ func init() {
CurrentMatch: undefined,
Spinner: undefined,
Info: undefined,
Cursor: undefined,
Pointer: undefined,
Marker: undefined,
Header: undefined,
Footer: undefined,
@@ -1091,7 +1109,7 @@ func init() {
CurrentMatch: ColorAttr{colBrightGreen, AttrUndefined},
Spinner: ColorAttr{colGreen, AttrUndefined},
Info: ColorAttr{colYellow, AttrUndefined},
Cursor: ColorAttr{colRed, AttrUndefined},
Pointer: ColorAttr{colRed, AttrUndefined},
Marker: ColorAttr{colMagenta, AttrUndefined},
Header: ColorAttr{colCyan, AttrUndefined},
Footer: ColorAttr{colCyan, AttrUndefined},
@@ -1142,7 +1160,7 @@ func init() {
CurrentMatch: ColorAttr{151, AttrUndefined},
Spinner: ColorAttr{148, AttrUndefined},
Info: ColorAttr{144, AttrUndefined},
Cursor: ColorAttr{161, AttrUndefined},
Pointer: ColorAttr{161, AttrUndefined},
Marker: ColorAttr{168, AttrUndefined},
Header: ColorAttr{109, AttrUndefined},
Footer: ColorAttr{109, AttrUndefined},
@@ -1193,7 +1211,7 @@ func init() {
CurrentMatch: ColorAttr{23, AttrUndefined},
Spinner: ColorAttr{65, AttrUndefined},
Info: ColorAttr{101, AttrUndefined},
Cursor: ColorAttr{161, AttrUndefined},
Pointer: ColorAttr{161, AttrUndefined},
Marker: ColorAttr{168, AttrUndefined},
Header: 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.Prompt = boldify(theme.Prompt)
theme.Input = boldify(theme.Input)
theme.Cursor = boldify(theme.Cursor)
theme.Pointer = boldify(theme.Pointer)
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.Spinner = o(baseTheme.Spinner, theme.Spinner)
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.Header = o(baseTheme.Header, theme.Header)
theme.Footer = o(baseTheme.Footer, theme.Footer)
@@ -1404,11 +1422,11 @@ func initPalette(theme *ColorTheme) {
ColDisabled = pair(theme.Disabled, theme.InputBg)
ColMatch = pair(theme.Match, theme.ListBg)
ColSelectedMatch = pair(theme.SelectedMatch, theme.SelectedBg)
ColCursor = pair(theme.Cursor, theme.Gutter)
ColCursorEmpty = pair(blank, theme.Gutter)
ColCursorEmptyChar = pair(theme.Gutter, theme.ListBg)
ColAltCursorEmpty = pair(blank, theme.AltGutter)
ColAltCursorEmptyChar = pair(theme.AltGutter, theme.ListBg)
ColPointer = pair(theme.Pointer, theme.Gutter)
ColPointerEmpty = pair(blank, theme.Gutter)
ColPointerEmptyChar = pair(theme.Gutter, theme.ListBg)
ColAltPointerEmpty = pair(blank, theme.AltGutter)
ColAltPointerEmptyChar = pair(theme.AltGutter, theme.ListBg)
if theme.SelectedBg.Color != theme.ListBg.Color {
ColMarker = pair(theme.Marker, theme.SelectedBg)
} else {
@@ -1416,8 +1434,8 @@ func initPalette(theme *ColorTheme) {
}
ColCurrent = pair(theme.Current, theme.DarkBg)
ColCurrentMatch = pair(theme.CurrentMatch, theme.DarkBg)
ColCurrentCursor = pair(theme.Cursor, theme.DarkBg)
ColCurrentCursorEmpty = pair(blank, theme.DarkBg)
ColCurrentPointer = pair(theme.Pointer, theme.DarkBg)
ColCurrentPointerEmpty = pair(blank, theme.DarkBg)
ColCurrentMarker = pair(theme.Marker, theme.DarkBg)
ColCurrentSelectedEmpty = pair(blank, theme.DarkBg)
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.until do |lines|
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
end
end
@@ -1510,7 +1510,7 @@ class TestLayout < TestInteractive
tmux.until do |lines|
one_idx = lines.index { |l| l.match?(/\A│\s+1\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
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.until do |lines|
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
end
end
@@ -1534,12 +1534,24 @@ class TestLayout < TestInteractive
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.until { |lines| lines.any_include?(/\A│\s+1\s+│\z/) }
tmux.send_keys ' '
tmux.send_keys :Space
tmux.until do |lines|
lines.any_include?(/\A│\s+1\s+│\z/) && lines.any_include?(/\A│\s+tada\s+│\z/)
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.
def test_inline_rejected_on_unsupported_options
[