From 28ede9f8e074b109bffb806c95186b1a450cbdfa Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Tue, 3 Sep 2024 08:52:33 -0400 Subject: [PATCH] feat!(border): left/right borders may now be set without top/bottom If the top and bottom borders are missing the left and right borders will now render. If the text value rendered is one line, this will essentially work akin to inline mode. --- borders.go | 87 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/borders.go b/borders.go index 5d730b4c..8d071a5b 100644 --- a/borders.go +++ b/borders.go @@ -11,14 +11,17 @@ import ( // Border contains a series of values which comprise the various parts of a // border. type Border struct { - Top string - Bottom string - Left string - Right string - TopLeft string - TopRight string - BottomLeft string - BottomRight string + // Values for all borders. + Top string + Bottom string + Left string + Right string + TopLeft string + TopRight string + BottomLeft string + BottomRight string + + // Values for table borders. MiddleLeft string MiddleRight string Middle string @@ -235,17 +238,26 @@ func (s Style) applyBorder(str string) string { border = s.getBorderStyle() + hasBorderTopLeft = border.TopLeft != "" + hasBorderTop = border.Top != "" + hasBorderTopRight = border.TopRight != "" + hasBorderRight = border.Right != "" + hasBorderBottomRight = border.BottomRight != "" + hasBorderBottom = border.Bottom != "" + hasBorderBottomLeft = border.BottomLeft != "" + hasBorderLeft = border.Left != "" + // Determine if a border was set. Borders also contain a middle section // for tables, but those don't apply here, so we explicitly check for // the relevant parts of borders only. - hasBorder = border.Top != "" || - border.Bottom != "" || - border.Left != "" || - border.Right != "" || - border.TopLeft != "" || - border.TopRight != "" || - border.BottomLeft != "" || - border.BottomRight != "" + hasBorder = hasBorderTop || + hasBorderBottom || + hasBorderLeft || + hasBorderRight || + hasBorderTopLeft || + hasBorderTopRight || + hasBorderBottomLeft || + hasBorderBottomRight hasTop = s.getAsBool(borderTopKey, false) hasRight = s.getAsBool(borderRightKey, false) @@ -277,6 +289,39 @@ func (s Style) applyBorder(str string) string { return str } + // But should we really render the top border? + if !topSet && !hasBorderTop && !hasBorderTopLeft && !hasBorderTopRight { + hasTop = false + } + + // And should we render the bottom border? + if !bottomSet && !hasBorderBottom && !hasBorderBottomLeft && !hasBorderBottomRight { + hasBottom = false + } + + // Don't render horizontal borders if the top and bottom won't be rendered + // and the border edge isn't set. + // + // For example, we wouldn't render a left border in the following case + // because setting the right border only nullifies other borders: + // + // Style(). + // BorderStyle(NormalBorder()). + // BorderRight(true) + // + // We also wouldn't render the left border in the following case, where the + // top and bottom borders are missing and the left border doesn't have + // a value set: + // + // Style(). + // BorderStyle(Border{Right: "│"}) + if !hasBorderLeft && !hasTop && !hasBottom { + hasLeft = false + } + if !hasBorderRight && !hasTop && !hasBottom { + hasRight = false + } + lines, width := getLines(str) if hasLeft { @@ -290,8 +335,8 @@ func (s Style) applyBorder(str string) string { border.Right = " " } - // If corners should be rendered but are set with the empty string, fill them - // with a single space. + // If corners should be rendered but are set with the empty string, fill + // them with a single space. if hasTop && hasLeft && border.TopLeft == "" { border.TopLeft = " " } @@ -338,7 +383,7 @@ func (s Style) applyBorder(str string) string { var out strings.Builder - // Render top + // Render top. This includes the top left and right corners. if hasTop { top := renderHorizontalEdge(border.TopLeft, border.Top, border.TopRight, width) top = s.styleBorder(top, topFG, topBG) @@ -352,7 +397,7 @@ func (s Style) applyBorder(str string) string { rightRunes := []rune(border.Right) rightIndex := 0 - // Render sides + // Render sides. This never includes any corners. for i, l := range lines { if hasLeft { r := string(leftRunes[leftIndex]) @@ -376,7 +421,7 @@ func (s Style) applyBorder(str string) string { } } - // Render bottom + // Render bottom. This includes the bottom left and right corners. if hasBottom { bottom := renderHorizontalEdge(border.BottomLeft, border.Bottom, border.BottomRight, width) bottom = s.styleBorder(bottom, bottomFG, bottomBG)