Skip to content

Commit

Permalink
add undercurl support
Browse files Browse the repository at this point in the history
  • Loading branch information
topi314 committed Nov 26, 2024
1 parent 8f4aab7 commit 031fa0f
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ssh_example_ed25519*
.idea/
32 changes: 32 additions & 0 deletions get.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,30 @@ func (s Style) GetUnderline() bool {
return s.getAsBool(underlineKey, false)
}

// GetDoubleUnderline returns the style's double underline value. If no value is set false is
// returned.
func (s Style) GetDoubleUnderline() bool {
return s.getAsBool(doubleUnderlineKey, false)
}

// GetCurlyUnderline returns the style's curly underline value. If no value is set false is
// returned.
func (s Style) GetCurlyUnderline() bool {
return s.getAsBool(curlyUnderlineKey, false)
}

// GetDottedUnderline returns the style's dotted underline value. If no value is set false is
// returned.
func (s Style) GetDottedUnderline() bool {
return s.getAsBool(dottedUnderlineKey, false)
}

// GetDashedUnderline returns the style's dashed underline value. If no value is set false is
// returned.
func (s Style) GetDashedUnderline() bool {
return s.getAsBool(dashedUnderlineKey, false)
}

// GetStrikethrough returns the style's strikethrough value. If no value is set false
// is returned.
func (s Style) GetStrikethrough() bool {
Expand Down Expand Up @@ -60,6 +84,12 @@ func (s Style) GetBackground() color.Color {
return s.getAsColor(backgroundKey)
}

// 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)
}

// GetWidth returns the style's width setting. If no width is set 0 is
// returned.
func (s Style) GetWidth() int {
Expand Down Expand Up @@ -438,6 +468,8 @@ func (s Style) getAsColor(k propKey) color.Color {
c = s.fgColor
case backgroundKey:
c = s.bgColor
case underlineColorKey:
c = s.underlineColor
case marginBackgroundKey:
c = s.marginBgColor
case borderTopForegroundKey:
Expand Down
9 changes: 9 additions & 0 deletions hyperlink.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package lipgloss

import (
"github.com/charmbracelet/x/ansi"
)

func Hyperlink(uri string, name string, params ...string) string {
return ansi.SetHyperlink(uri, params...) + name + ansi.ResetHyperlink(params...) + ansi.ResetStyle
}
43 changes: 43 additions & 0 deletions set.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ func (s *Style) set(key propKey, value interface{}) {
s.fgColor = colorOrNil(value)
case backgroundKey:
s.bgColor = colorOrNil(value)
case underlineColorKey:
s.underlineColor = colorOrNil(value)
case widthKey:
s.width = max(0, value.(int))
case heightKey:
Expand Down Expand Up @@ -95,6 +97,8 @@ 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.underlineColor)
case widthKey:
s.set(widthKey, i.width)
case heightKey:
Expand Down Expand Up @@ -181,6 +185,38 @@ func (s Style) Underline(v bool) Style {
return s
}

// DoubleUnderline sets a double underline rule. By default, underlines will not
// be drawn on whitespace like margins and padding. To change this behavior set
// UnderlineSpaces.
func (s Style) DoubleUnderline(v bool) Style {
s.set(doubleUnderlineKey, v)
return s
}

// CurlyUnderline sets a curly underline rule. By default, underlines will not
// be drawn on whitespace like margins and padding. To change this behavior set
// UnderlineSpaces.
func (s Style) CurlyUnderline(v bool) Style {
s.set(curlyUnderlineKey, v)
return s
}

// DottedUnderline sets a dotted underline rule. By default, underlines will not
// be drawn on whitespace like margins and padding. To change this behavior set
// UnderlineSpaces.
func (s Style) DottedUnderline(v bool) Style {
s.set(dottedUnderlineKey, v)
return s
}

// DashedUnderline sets a dashed underline rule. By default, underlines will not
// be drawn on whitespace like margins and padding. To change this behavior set
// UnderlineSpaces.
func (s Style) DashedUnderline(v bool) Style {
s.set(dashedUnderlineKey, v)
return s
}

// Strikethrough sets a strikethrough rule. By default, strikes will not be
// drawn on whitespace like margins and padding. To change this behavior set
// StrikethroughSpaces.
Expand Down Expand Up @@ -225,6 +261,13 @@ func (s Style) Background(c color.Color) Style {
return s
}

// UnderlineColor sets an underline color rule. This can be used to change the
// underline color to a different color than the foreground color.
func (s Style) UnderlineColor(c color.Color) Style {
s.set(underlineColorKey, c)
return s
}

// Width sets the width of the block before applying margins. The width, if
// set, also determines where text will wrap.
func (s Style) Width(i int) Style {
Expand Down
81 changes: 64 additions & 17 deletions style.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const (
boldKey propKey = 1 << iota
italicKey
underlineKey
doubleUnderlineKey
curlyUnderlineKey
dottedUnderlineKey
dashedUnderlineKey
strikethroughKey
reverseKey
blinkKey
Expand All @@ -30,6 +34,7 @@ const (
// Non-boolean props.
foregroundKey
backgroundKey
underlineColorKey
widthKey
heightKey
alignHorizontalKey
Expand Down Expand Up @@ -111,8 +116,9 @@ type Style struct {
attrs int

// props that have values
fgColor color.Color
bgColor color.Color
fgColor color.Color
bgColor color.Color
underlineColor color.Color

width int
height int
Expand Down Expand Up @@ -231,16 +237,21 @@ func (s Style) Render(strs ...string) string {
teSpace ansi.Style
teWhitespace ansi.Style

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)
bold = s.getAsBool(boldKey, false)
italic = s.getAsBool(italicKey, false)
underline = s.getAsBool(underlineKey, false)
doubleUnderline = s.getAsBool(doubleUnderlineKey, false)
curlyUnderline = s.getAsBool(curlyUnderlineKey, false)
dottedUnderline = s.getAsBool(dottedUnderlineKey, false)
dashedUnderline = s.getAsBool(dashedUnderlineKey, 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)
underlineColor = s.getAsColor(underlineColorKey)

width = s.getAsInt(widthKey)
height = s.getAsInt(heightKey)
Expand All @@ -257,15 +268,19 @@ func (s Style) Render(strs ...string) string {
maxWidth = s.getAsInt(maxWidthKey)
maxHeight = s.getAsInt(maxHeightKey)

underlineSpaces = s.getAsBool(underlineSpacesKey, false) || (underline && s.getAsBool(underlineSpacesKey, true))
strikethroughSpaces = s.getAsBool(strikethroughSpacesKey, false) || (strikethrough && s.getAsBool(strikethroughSpacesKey, true))
underlineSpaces = s.getAsBool(underlineSpacesKey, false) || (underline && s.getAsBool(underlineSpacesKey, true))
doubleUnderlineSpaces = s.getAsBool(underlineSpacesKey, false) || (doubleUnderline && s.getAsBool(underlineSpacesKey, true))
curlyUnderlineSpaces = s.getAsBool(underlineSpacesKey, false) || (curlyUnderline && s.getAsBool(underlineSpacesKey, true))
dottedUnderlineSpaces = s.getAsBool(underlineSpacesKey, false) || (dottedUnderline && s.getAsBool(underlineSpacesKey, true))
dashedUnderlineSpaces = s.getAsBool(underlineSpacesKey, false) || (dashedUnderline && s.getAsBool(underlineSpacesKey, true))
strikethroughSpaces = s.getAsBool(strikethroughSpacesKey, false) || (strikethrough && s.getAsBool(strikethroughSpacesKey, true))

// Do we need to style whitespace (padding and space outside
// paragraphs) separately?
styleWhitespace = reverse

// Do we need to style spaces separately?
useSpaceStyler = (underline && !underlineSpaces) || (strikethrough && !strikethroughSpaces) || underlineSpaces || strikethroughSpaces
useSpaceStyler = ((underline || doubleUnderline || curlyUnderline || dottedUnderline || dashedUnderline) && !underlineSpaces) || (strikethrough && !strikethroughSpaces) || underline || doubleUnderline || curlyUnderline || dottedUnderline || dashedUnderline || strikethroughSpaces

transform = s.getAsTransform(transformKey)
)
Expand All @@ -287,6 +302,19 @@ func (s Style) Render(strs ...string) string {
if underline {
te = te.Underline()
}
if doubleUnderline {
te = te.DoubleUnderline()
}
if curlyUnderline {
te = te.CurlyUnderline()
}
if dottedUnderline {
te = te.DottedUnderline()
}
if dashedUnderline {
te = te.DashedUnderline()
}

if reverse {
teWhitespace = teWhitespace.Reverse()
te = te.Reverse()
Expand Down Expand Up @@ -318,16 +346,35 @@ func (s Style) Render(strs ...string) string {
}
}

if underline {
te = te.Underline()
if underlineColor != noColor {
te = te.UnderlineColor(underlineColor)
if colorWhitespace {
teWhitespace = teWhitespace.UnderlineColor(underlineColor)
}
if useSpaceStyler {
teSpace = teSpace.UnderlineColor(underlineColor)
}
}

if strikethrough {
te = te.Strikethrough()
}

if underlineSpaces {
teSpace = teSpace.Underline()
}
if doubleUnderlineSpaces {
teSpace = teSpace.DoubleUnderline()
}
if curlyUnderlineSpaces {
teSpace = teSpace.CurlyUnderline()
}
if dottedUnderlineSpaces {
teSpace = teSpace.DottedUnderline()
}
if dashedUnderlineSpaces {
teSpace = teSpace.DashedUnderline()
}
if strikethroughSpaces {
teSpace = teSpace.Strikethrough()
}
Expand Down
30 changes: 30 additions & 0 deletions unset.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,36 @@ func (s Style) UnsetUnderline() Style {
return s
}

// UnsetDoubleUnderline removes the double underline style rule, if set.
func (s Style) UnsetDoubleUnderline() Style {
s.unset(doubleUnderlineKey)
return s
}

// UnsetCurlyUnderline removes the curly underline style rule, if set.
func (s Style) UnsetCurlyUnderline() Style {
s.unset(curlyUnderlineKey)
return s
}

// UnsetDottedUnderline removes the dotted underline style rule, if set.
func (s Style) UnsetDottedUnderline() Style {
s.unset(dottedUnderlineKey)
return s
}

// UnsetDashedUnderline removes the dashed underline style rule, if set.
func (s Style) UnsetDashedUnderline() Style {
s.unset(dashedUnderlineKey)
return s
}

// UnsetUnderlineColor removes the underline color style rule, if set.
func (s Style) UnsetUnderlineColor() Style {
s.unset(underlineColorKey)
return s
}

// UnsetStrikethrough removes the strikethrough style rule, if set.
func (s Style) UnsetStrikethrough() Style {
s.unset(strikethroughKey)
Expand Down

0 comments on commit 031fa0f

Please sign in to comment.