Apply facing-line rule to input border as well

Visible input border suppressed separator even when it draws no line
toward list section (bottom in default layout, top in reverse, vertical).
Suppress only when input border has a line on the list side; otherwise
fall through to adjacent section check.

Also requires header window to have content before treating it as the
facing section; hasHeaderWindow returns true with empty header when
input border is visible.
This commit is contained in:
Junegunn Choi
2026-07-18 01:05:47 +09:00
parent 083045ad53
commit c434be7bf5
3 changed files with 21 additions and 4 deletions
+4
View File
@@ -10,6 +10,10 @@ CHANGELOG
# Separator shown; no border separates the input section from the list section
fzf --style full --input-border none --header foo --no-header-border
# Conversely, separator is now shown when the input border does not draw
# a line facing the list section
fzf --input-border bottom
```
- Rendering improvements
- Each frame is now wrapped in synchronized update mode (mode 2026) to reduce flickering on supported terminals
+8 -1
View File
@@ -3699,7 +3699,14 @@ func (opts *Options) noSeparatorLine() bool {
// NOTE: This does not know that the default separator can be suppressed at
// runtime (see Terminal.separatorLength), so the minimum heights derived
// from it can be one line taller than strictly necessary.
sep := opts.Separator == nil && !opts.InputBorderShape.Visible() || opts.Separator != nil && len(*opts.Separator) > 0
//
// Whether the input border draws a line on the side facing the list
// section; BorderLine always resolves to that side (see NewTerminal)
shape := opts.InputBorderShape
facingLine := shape == tui.BorderLine ||
opts.Layout == layoutReverse && shape.HasBottom() ||
opts.Layout != layoutReverse && shape.HasTop()
sep := opts.Separator == nil && !facingLine || opts.Separator != nil && len(*opts.Separator) > 0
return noSeparatorLine(opts.InfoStyle, sep)
}
+9 -3
View File
@@ -1714,7 +1714,9 @@ func (t *Terminal) separatorLength() int {
// The default horizontal separator is redundant if the input section is
// already visually separated from the list section by a border line
func (t *Terminal) separatedByBorder() bool {
if t.inputBorderShape.Visible() {
// The input border itself draws a line on the side facing the list section
if t.layout == layoutReverse && t.inputBorderShape.HasBottom() ||
t.layout != layoutReverse && t.inputBorderShape.HasTop() {
return true
}
for po := &t.previewOpts; po != nil; po = po.alternative {
@@ -1727,7 +1729,7 @@ func (t *Terminal) separatedByBorder() bool {
}
hasHeaderLinesWindow, headerLinesShape := t.determineHeaderLinesShape()
hasHeaderWindow := t.hasHeaderWindow()
if !hasHeaderWindow && !hasHeaderLinesWindow {
if !t.inputBorderShape.Visible() && !hasHeaderWindow && !hasHeaderLinesWindow {
// No separate window is created for the input section in this case
// (see hasInputWindow in resizeWindows), i.e. the input section is
// embedded in the list window and no border separates the two
@@ -1736,7 +1738,11 @@ func (t *Terminal) separatedByBorder() bool {
// The input section has its own window. Determine which section it is
// facing, and check if the border of that section draws a line toward it.
if hasHeaderWindow && !t.headerFirst && t.headerBorderShape != tui.BorderInline {
// NOTE: hasHeaderWindow can be true with no header content when the input
// border is visible (see Terminal.hasHeaderWindow). An empty header window
// takes no space, so it cannot be the facing section.
hasHeaderSection := hasHeaderWindow && len(t.header0)+t.headerLines > 0
if hasHeaderSection && !t.headerFirst && t.headerBorderShape != tui.BorderInline {
// Header section; an inline header is not a separate section, it is
// drawn inside the list border, so it falls through to the branches
// below