mirror of
https://github.com/junegunn/fzf.git
synced 2026-04-26 09:26:00 +08:00
Use bottom char for thinblock inline separator above list
For border styles where the top and bottom horizontals differ (thinblock and block), the inline separator now picks the char based on position: separators above the list content use the `bottom` char so the thin line hugs the list from above, matching how the list frame's top edge sits against the first row. Separators below list content continue to use the `top` char. Rounded / sharp / bold / double / horizontal / line are unaffected because their top and bottom chars are identical.
This commit is contained in:
+17
-4
@@ -2739,7 +2739,9 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
}
|
||||
cursor += s.contentLines
|
||||
sepRow := cursor - t.wborder.Top()
|
||||
t.wborder.DrawHSeparator(sepRow, s.windowType)
|
||||
// Separator sits above list content; hug the list below by using the
|
||||
// bottom char (matters for thinblock/block where top and bottom differ).
|
||||
t.wborder.DrawHSeparator(sepRow, s.windowType, true)
|
||||
recordSep(s.role, sepRow)
|
||||
cursor++
|
||||
}
|
||||
@@ -2756,7 +2758,8 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
t.footerWindow = win
|
||||
}
|
||||
sepRow := top - 1 - t.wborder.Top()
|
||||
t.wborder.DrawHSeparator(sepRow, s.windowType)
|
||||
// Separator sits below list content; hug the list above with the top char.
|
||||
t.wborder.DrawHSeparator(sepRow, s.windowType, false)
|
||||
recordSep(s.role, sepRow)
|
||||
cursor = top - 2
|
||||
}
|
||||
@@ -2937,6 +2940,16 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// isInlineSepAboveList reports whether the recorded wborder-relative separator row sits
|
||||
// above the list content window, so DrawHSeparator should use the bottom horizontal char
|
||||
// to visually hug the list from above.
|
||||
func (t *Terminal) isInlineSepAboveList(sepRow int) bool {
|
||||
if t.wborder == nil || t.window == nil {
|
||||
return false
|
||||
}
|
||||
return t.wborder.Top()+sepRow < t.window.Top()
|
||||
}
|
||||
|
||||
func (t *Terminal) printInlineLabel(window tui.Window, row int, render labelPrinter, opts labelOpts, length int) {
|
||||
if window == nil || render == nil || window.Height() == 0 {
|
||||
return
|
||||
@@ -6123,13 +6136,13 @@ func (t *Terminal) Loop() error {
|
||||
case reqRedrawHeaderLabel:
|
||||
t.printLabel(t.headerBorder, t.headerLabel, t.headerLabelOpts, t.headerLabelLen, t.headerBorderShape, true)
|
||||
if t.wborder != nil && t.inlineHeaderSepRow >= 0 {
|
||||
t.wborder.DrawHSeparator(t.inlineHeaderSepRow, tui.WindowHeader)
|
||||
t.wborder.DrawHSeparator(t.inlineHeaderSepRow, tui.WindowHeader, t.isInlineSepAboveList(t.inlineHeaderSepRow))
|
||||
t.printInlineLabel(t.wborder, t.inlineHeaderSepRow, t.headerLabel, t.headerLabelOpts, t.headerLabelLen)
|
||||
}
|
||||
case reqRedrawFooterLabel:
|
||||
t.printLabel(t.footerBorder, t.footerLabel, t.footerLabelOpts, t.footerLabelLen, t.footerBorderShape, true)
|
||||
if t.wborder != nil && t.inlineFooterSepRow >= 0 {
|
||||
t.wborder.DrawHSeparator(t.inlineFooterSepRow, tui.WindowFooter)
|
||||
t.wborder.DrawHSeparator(t.inlineFooterSepRow, tui.WindowFooter, t.isInlineSepAboveList(t.inlineFooterSepRow))
|
||||
t.printInlineLabel(t.wborder, t.inlineFooterSepRow, t.footerLabel, t.footerLabelOpts, t.footerLabelLen)
|
||||
}
|
||||
case reqRedrawListLabel:
|
||||
|
||||
+8
-4
@@ -1122,7 +1122,7 @@ func (w *LightWindow) DrawHBorder() {
|
||||
w.drawBorder(true)
|
||||
}
|
||||
|
||||
func (w *LightWindow) DrawHSeparator(row int, windowType WindowType) {
|
||||
func (w *LightWindow) DrawHSeparator(row int, windowType WindowType, useBottom bool) {
|
||||
if w.height == 0 {
|
||||
return
|
||||
}
|
||||
@@ -1147,13 +1147,17 @@ func (w *LightWindow) DrawHSeparator(row int, windowType WindowType) {
|
||||
// Section color for the horizontal; list-border color (w.windowType) for the T-junctions.
|
||||
lineColor := colorFor(windowType)
|
||||
junctionColor := colorFor(w.windowType)
|
||||
hw := runeWidth(w.border.top)
|
||||
lineChar := w.border.top
|
||||
if useBottom {
|
||||
lineChar = w.border.bottom
|
||||
}
|
||||
hw := runeWidth(lineChar)
|
||||
w.Move(row, 0)
|
||||
if !w.border.shape.HasLeft() && !w.border.shape.HasRight() {
|
||||
// No verticals to join, so draw a continuous horizontal across the full width.
|
||||
full := max(0, w.width/hw)
|
||||
rem := w.width - full*hw
|
||||
w.CPrint(lineColor, repeat(w.border.top, full)+repeat(' ', rem))
|
||||
w.CPrint(lineColor, repeat(lineChar, full)+repeat(' ', rem))
|
||||
return
|
||||
}
|
||||
lw := runeWidth(w.border.leftMid)
|
||||
@@ -1161,7 +1165,7 @@ func (w *LightWindow) DrawHSeparator(row int, windowType WindowType) {
|
||||
inner := max(0, (w.width-lw-rw)/hw)
|
||||
rem := (w.width - lw - rw) - inner*hw
|
||||
w.CPrint(junctionColor, string(w.border.leftMid))
|
||||
w.CPrint(lineColor, repeat(w.border.top, inner)+repeat(' ', rem))
|
||||
w.CPrint(lineColor, repeat(lineChar, inner)+repeat(' ', rem))
|
||||
w.CPrint(junctionColor, string(w.border.rightMid))
|
||||
}
|
||||
|
||||
|
||||
+8
-4
@@ -1017,7 +1017,7 @@ func (w *TcellWindow) DrawHBorder() {
|
||||
w.drawBorder(true)
|
||||
}
|
||||
|
||||
func (w *TcellWindow) DrawHSeparator(row int, windowType WindowType) {
|
||||
func (w *TcellWindow) DrawHSeparator(row int, windowType WindowType, useBottom bool) {
|
||||
if w.height == 0 {
|
||||
return
|
||||
}
|
||||
@@ -1049,15 +1049,19 @@ func (w *TcellWindow) DrawHSeparator(row int, windowType WindowType) {
|
||||
// so the outer frame's verticals stay visually continuous.
|
||||
lineStyle := styleFor(windowType)
|
||||
junctionStyle := styleFor(w.windowType)
|
||||
lineChar := w.borderStyle.top
|
||||
if useBottom {
|
||||
lineChar = w.borderStyle.bottom
|
||||
}
|
||||
y := w.top + row
|
||||
left := w.left
|
||||
right := left + w.width
|
||||
hw := runeWidth(w.borderStyle.top)
|
||||
hw := runeWidth(lineChar)
|
||||
hasVert := shape.HasLeft() || shape.HasRight()
|
||||
if !hasVert {
|
||||
// No verticals to join, so draw a continuous horizontal across the full width.
|
||||
for x := left; x <= right-hw; x += hw {
|
||||
_screen.SetContent(x, y, w.borderStyle.top, nil, lineStyle)
|
||||
_screen.SetContent(x, y, lineChar, nil, lineStyle)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1065,7 +1069,7 @@ func (w *TcellWindow) DrawHSeparator(row int, windowType WindowType) {
|
||||
rightMidW := runeWidth(w.borderStyle.rightMid)
|
||||
max := right - leftMidW - rightMidW
|
||||
for x := left + leftMidW; x <= max; x += hw {
|
||||
_screen.SetContent(x, y, w.borderStyle.top, nil, lineStyle)
|
||||
_screen.SetContent(x, y, lineChar, nil, lineStyle)
|
||||
}
|
||||
_screen.SetContent(left, y, w.borderStyle.leftMid, nil, junctionStyle)
|
||||
_screen.SetContent(right-rightMidW, y, w.borderStyle.rightMid, nil, junctionStyle)
|
||||
|
||||
+6
-1
@@ -830,7 +830,12 @@ type Window interface {
|
||||
|
||||
DrawBorder()
|
||||
DrawHBorder()
|
||||
DrawHSeparator(row int, windowType WindowType)
|
||||
// DrawHSeparator draws an inline horizontal separator at `row` (relative to the
|
||||
// window's top) using the color for `windowType`. When useBottom is true, the
|
||||
// `bottom` horizontal char is used instead of `top` — for thinblock/block styles
|
||||
// where the two characters differ, this keeps the thin line visually bonded to
|
||||
// the list content that sits on the opposite side of the separator.
|
||||
DrawHSeparator(row int, windowType WindowType, useBottom bool)
|
||||
Refresh()
|
||||
FinishFill()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user