diff --git a/borders.go b/borders.go index deb6b35a..a5e668d0 100644 --- a/borders.go +++ b/borders.go @@ -228,11 +228,6 @@ func HiddenBorder() Border { func (s Style) applyBorder(str string) string { var ( - topSet = s.isSet(borderTopKey) - rightSet = s.isSet(borderRightKey) - bottomSet = s.isSet(borderBottomKey) - leftSet = s.isSet(borderLeftKey) - border = s.getBorderStyle() hasTop = s.getAsBool(borderTopKey, false) hasRight = s.getAsBool(borderRightKey, false) @@ -252,7 +247,7 @@ func (s Style) applyBorder(str string) string { // If a border is set and no sides have been specifically turned on or off // render borders on all sides. - if border != noBorder && !(topSet || rightSet || bottomSet || leftSet) { + if s.implicitBorders() { hasTop = true hasRight = true hasBottom = true diff --git a/borders_test.go b/borders_test.go new file mode 100644 index 00000000..44b95d0c --- /dev/null +++ b/borders_test.go @@ -0,0 +1,96 @@ +package lipgloss + +import "testing" + +func TestStyle_GetBorderSizes(t *testing.T) { + tests := []struct { + name string + style Style + wantX int + wantY int + }{ + { + name: "Default style", + style: NewStyle(), + wantX: 0, + wantY: 0, + }, + { + name: "Border(NormalBorder())", + style: NewStyle().Border(NormalBorder()), + wantX: 2, + wantY: 2, + }, + { + name: "Border(NormalBorder(), true)", + style: NewStyle().Border(NormalBorder(), true), + wantX: 2, + wantY: 2, + }, + { + name: "Border(NormalBorder(), true, false)", + style: NewStyle().Border(NormalBorder(), true, false), + wantX: 0, + wantY: 2, + }, + { + name: "Border(NormalBorder(), true, true, false)", + style: NewStyle().Border(NormalBorder(), true, true, false), + wantX: 2, + wantY: 1, + }, + { + name: "Border(NormalBorder(), true, true, false, false)", + style: NewStyle().Border(NormalBorder(), true, true, false, false), + wantX: 1, + wantY: 1, + }, + { + name: "BorderTop(true).BorderStyle(NormalBorder())", + style: NewStyle().BorderTop(true).BorderStyle(NormalBorder()), + wantX: 0, + wantY: 1, + }, + { + name: "BorderStyle(NormalBorder())", + style: NewStyle().BorderStyle(NormalBorder()), + wantX: 2, + wantY: 2, + }, + { + name: "Custom BorderStyle", + style: NewStyle().BorderStyle(Border{Left: "123456789"}), + wantX: 1, // left and right borders are laid out vertically, one rune per row + wantY: 0, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotX := tt.style.GetHorizontalBorderSize() + if gotX != tt.wantX { + t.Errorf("Style.GetHorizontalBorderSize() got %d, want %d", gotX, tt.wantX) + } + + gotY := tt.style.GetVerticalBorderSize() + if gotY != tt.wantY { + t.Errorf("Style.GetVerticalBorderSize() got %d, want %d", gotY, tt.wantY) + } + + gotX = tt.style.GetHorizontalFrameSize() + if gotX != tt.wantX { + t.Errorf("Style.GetHorizontalFrameSize() got %d, want %d", gotX, tt.wantX) + } + + gotY = tt.style.GetVerticalFrameSize() + if gotY != tt.wantY { + t.Errorf("Style.GetVerticalFrameSize() got %d, want %d", gotY, tt.wantY) + } + + gotX, gotY = tt.style.GetFrameSize() + if gotX != tt.wantX || gotY != tt.wantY { + t.Errorf("Style.GetFrameSize() got (%d, %d), want (%d, %d)", gotX, gotY, tt.wantX, tt.wantY) + } + }) + } +} diff --git a/get.go b/get.go index 9c2f06fe..422b4ce9 100644 --- a/get.go +++ b/get.go @@ -300,7 +300,7 @@ func (s Style) GetBorderTopWidth() int { // runes of varying widths, the widest rune is returned. If no border exists on // the top edge, 0 is returned. func (s Style) GetBorderTopSize() int { - if !s.getAsBool(borderTopKey, false) { + if !s.getAsBool(borderTopKey, false) && !s.implicitBorders() { return 0 } return s.getBorderStyle().GetTopSize() @@ -310,7 +310,7 @@ func (s Style) GetBorderTopSize() int { // runes of varying widths, the widest rune is returned. If no border exists on // the left edge, 0 is returned. func (s Style) GetBorderLeftSize() int { - if !s.getAsBool(borderLeftKey, false) { + if !s.getAsBool(borderLeftKey, false) && !s.implicitBorders() { return 0 } return s.getBorderStyle().GetLeftSize() @@ -320,7 +320,7 @@ func (s Style) GetBorderLeftSize() int { // contain runes of varying widths, the widest rune is returned. If no border // exists on the left edge, 0 is returned. func (s Style) GetBorderBottomSize() int { - if !s.getAsBool(borderBottomKey, false) { + if !s.getAsBool(borderBottomKey, false) && !s.implicitBorders() { return 0 } return s.getBorderStyle().GetBottomSize() @@ -330,7 +330,7 @@ func (s Style) GetBorderBottomSize() int { // contain runes of varying widths, the widest rune is returned. If no border // exists on the right edge, 0 is returned. func (s Style) GetBorderRightSize() int { - if !s.getAsBool(borderRightKey, false) { + if !s.getAsBool(borderRightKey, false) && !s.implicitBorders() { return 0 } return s.getBorderStyle().GetRightSize() @@ -519,6 +519,20 @@ func (s Style) getBorderStyle() Border { return s.borderStyle } +// Returns whether or not the style has implicit borders. This happens when +// a border style has been set but no border sides have been explicitly turned +// on or off. +func (s Style) implicitBorders() bool { + var ( + borderStyle = s.getBorderStyle() + topSet = s.isSet(borderTopKey) + rightSet = s.isSet(borderRightKey) + bottomSet = s.isSet(borderBottomKey) + leftSet = s.isSet(borderLeftKey) + ) + return borderStyle != noBorder && !(topSet || rightSet || bottomSet || leftSet) +} + func (s Style) getAsTransform(propKey) func(string) string { if !s.isSet(transformKey) { return nil