Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion get.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,19 @@ func (s Style) GetItalic() bool {
// GetUnderline returns the style's underline value. If no value is set false is
// returned.
func (s Style) GetUnderline() bool {
return s.getAsBool(underlineKey, false)
return s.ul != NoUnderline
}

// GetUnderlineStyle returns the style's underline style. If no value is set
// NoUnderline is returned.
func (s Style) GetUnderlineStyle() Underline {
return s.ul
}

// GetUnderlineColor returns the style's underline color. If no value is set
// NoColor{} is returned.
func (s Style) GetUnderlineColor() color.Color {
return s.getAsColor(underlineColorKey)
}

// GetStrikethrough returns the style's strikethrough value. If no value is set false
Expand Down
26 changes: 25 additions & 1 deletion set.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ func (s *Style) set(key propKey, value interface{}) {
s.fgColor = colorOrNil(value)
case backgroundKey:
s.bgColor = colorOrNil(value)
case underlineColorKey:
s.ulColor = colorOrNil(value)
case underlineKey:
s.ul = value.(Underline)
case widthKey:
s.width = max(0, value.(int))
case heightKey:
Expand Down Expand Up @@ -95,6 +99,10 @@ func (s *Style) setFrom(key propKey, i Style) {
s.set(foregroundKey, i.fgColor)
case backgroundKey:
s.set(backgroundKey, i.bgColor)
case underlineColorKey:
s.set(underlineColorKey, i.ulColor)
case underlineKey:
s.set(underlineKey, i.ul)
case widthKey:
s.set(widthKey, i.width)
case heightKey:
Expand Down Expand Up @@ -177,7 +185,23 @@ func (s Style) Italic(v bool) Style {
// whitespace like margins and padding. To change this behavior set
// [Style.UnderlineSpaces].
func (s Style) Underline(v bool) Style {
s.set(underlineKey, v)
if v {
return s.UnderlineStyle(SingleUnderline)
}
return s.UnderlineStyle(NoUnderline)
}

// UnderlineStyle sets the underline style. This can be used to set the underline
// to be a single, double, curly, dotted, or dashed line.
func (s Style) UnderlineStyle(u Underline) Style {
s.set(underlineKey, u)
return s
}

// UnderlineColor sets the color of the underline. By default, the underline
// will be the same color as the foreground.
func (s Style) UnderlineColor(c color.Color) Style {
s.set(underlineColorKey, c)
return s
}

Expand Down
39 changes: 36 additions & 3 deletions style.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const (
// Boolean props come first.
boldKey propKey = 1 << iota
italicKey
underlineKey
strikethroughKey
reverseKey
blinkKey
Expand All @@ -29,8 +28,10 @@ const (
colorWhitespaceKey

// Non-boolean props.
underlineKey
foregroundKey
backgroundKey
underlineColorKey
widthKey
heightKey
alignHorizontalKey
Expand Down Expand Up @@ -96,6 +97,24 @@ func (p props) has(k propKey) bool {
return p&props(k) != 0
}

// Underline is the style of the underline.
type Underline uint8

const (
// NoUnderline is no underline.
NoUnderline = Underline(ansi.NoUnderlineStyle)
// SingleUnderline is a single underline. This is the default when underline is enabled.
SingleUnderline = Underline(ansi.SingleUnderlineStyle)
// DoubleUnderline is a double underline.
DoubleUnderline = Underline(ansi.DoubleUnderlineStyle)
// CurlyUnderline is a curly underline.
CurlyUnderline = Underline(ansi.CurlyUnderlineStyle)
// DottedUnderline is a dotted underline.
DottedUnderline = Underline(ansi.DottedUnderlineStyle)
// DashedUnderline is a dashed underline.
DashedUnderline = Underline(ansi.DashedUnderlineStyle)
)

// NewStyle returns a new, empty Style. While it's syntactic sugar for the
// [Style]{} primitive, it's recommended to use this function for creating styles
// in case the underlying implementation changes.
Expand All @@ -114,6 +133,9 @@ type Style struct {
// props that have values
fgColor color.Color
bgColor color.Color
ulColor color.Color

ul Underline

width int
height int
Expand Down Expand Up @@ -234,15 +256,16 @@ func (s Style) Render(strs ...string) string {

bold = s.getAsBool(boldKey, false)
italic = s.getAsBool(italicKey, false)
underline = s.getAsBool(underlineKey, false)
strikethrough = s.getAsBool(strikethroughKey, false)
reverse = s.getAsBool(reverseKey, false)
blink = s.getAsBool(blinkKey, false)
faint = s.getAsBool(faintKey, false)

fg = s.getAsColor(foregroundKey)
bg = s.getAsColor(backgroundKey)
ul = s.getAsColor(underlineColorKey)

underline = s.ul != NoUnderline
width = s.getAsInt(widthKey)
height = s.getAsInt(heightKey)
horizontalAlign = s.getAsPosition(alignHorizontalKey)
Expand Down Expand Up @@ -322,8 +345,18 @@ func (s Style) Render(strs ...string) string {
}
}

if ul != noColor {
te = te.UnderlineColor(ul)
if colorWhitespace {
teWhitespace = teWhitespace.UnderlineColor(ul)
}
if useSpaceStyler {
teSpace = teSpace.UnderlineColor(ul)
}
}

if underline {
te = te.Underline()
te = te.UnderlineStyle(ansi.UnderlineStyle(s.ul))
}
if strikethrough {
te = te.Strikethrough()
Expand Down
4 changes: 4 additions & 0 deletions style_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ func TestUnderline(t *testing.T) {
NewStyle().UnderlineSpaces(true),
"ab\x1b[4m \x1b[mc",
},
{
NewStyle().UnderlineStyle(CurlyUnderline),
"\x1b[4;4:3ma\x1b[m\x1b[4;4:3mb\x1b[m\x1b[4m \x1b[m\x1b[4;4:3mc\x1b[m",
},
}

for i, tc := range tt {
Expand Down
3 changes: 1 addition & 2 deletions unset.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ func (s Style) UnsetItalic() Style {

// UnsetUnderline removes the underline style rule, if set.
func (s Style) UnsetUnderline() Style {
s.unset(underlineKey)
return s
return s.Underline(false)
}

// UnsetStrikethrough removes the strikethrough style rule, if set.
Expand Down
Loading