Skip to content

Commit

Permalink
refactor: replace props map with struct fields
Browse files Browse the repository at this point in the history
Use an int to store property existence and style struct fields to store
the actual values for each non-bool property.

Fixes: #139
Fixes: #141
  • Loading branch information
aymanbagabas committed Mar 28, 2024
1 parent f16ea2b commit 8c95fd7
Show file tree
Hide file tree
Showing 5 changed files with 395 additions and 159 deletions.
102 changes: 71 additions & 31 deletions get.go
Expand Up @@ -416,74 +416,114 @@ func (s Style) GetTransform() func(string) string {

// Returns whether or not the given property is set.
func (s Style) isSet(k propKey) bool {
_, exists := s.rules[k]
return exists
return s.props.has(k)
}

func (s Style) getAsBool(k propKey, defaultVal bool) bool {
v, ok := s.rules[k]
if !ok {
if !s.isSet(k) {
return defaultVal
}
if b, ok := v.(bool); ok {
return b
}
return defaultVal
return s.attrs&int(k) != 0
}

func (s Style) getAsColor(k propKey) TerminalColor {
v, ok := s.rules[k]
if !ok {
if !s.isSet(k) {
return noColor
}
if c, ok := v.(TerminalColor); ok {

var c TerminalColor
switch k {

Check failure on line 435 in get.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type lipgloss.propKey: lipgloss.boldKey, lipgloss.italicKey, lipgloss.underlineKey, lipgloss.strikethroughKey, lipgloss.reverseKey, lipgloss.blinkKey, lipgloss.faintKey, lipgloss.underlineSpacesKey, lipgloss.strikethroughSpacesKey, lipgloss.colorWhitespaceKey, lipgloss.widthKey, lipgloss.heightKey, lipgloss.alignHorizontalKey, lipgloss.alignVerticalKey, lipgloss.paddingTopKey, lipgloss.paddingRightKey, lipgloss.paddingBottomKey, lipgloss.paddingLeftKey, lipgloss.marginTopKey, lipgloss.marginRightKey, lipgloss.marginBottomKey, lipgloss.marginLeftKey, lipgloss.borderStyleKey, lipgloss.borderTopKey, lipgloss.borderRightKey, lipgloss.borderBottomKey, lipgloss.borderLeftKey, lipgloss.inlineKey, lipgloss.maxWidthKey, lipgloss.maxHeightKey, lipgloss.tabWidthKey, lipgloss.transformKey (exhaustive)

Check failure on line 435 in get.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type lipgloss.propKey: lipgloss.boldKey, lipgloss.italicKey, lipgloss.underlineKey, lipgloss.strikethroughKey, lipgloss.reverseKey, lipgloss.blinkKey, lipgloss.faintKey, lipgloss.underlineSpacesKey, lipgloss.strikethroughSpacesKey, lipgloss.colorWhitespaceKey, lipgloss.widthKey, lipgloss.heightKey, lipgloss.alignHorizontalKey, lipgloss.alignVerticalKey, lipgloss.paddingTopKey, lipgloss.paddingRightKey, lipgloss.paddingBottomKey, lipgloss.paddingLeftKey, lipgloss.marginTopKey, lipgloss.marginRightKey, lipgloss.marginBottomKey, lipgloss.marginLeftKey, lipgloss.borderStyleKey, lipgloss.borderTopKey, lipgloss.borderRightKey, lipgloss.borderBottomKey, lipgloss.borderLeftKey, lipgloss.inlineKey, lipgloss.maxWidthKey, lipgloss.maxHeightKey, lipgloss.tabWidthKey, lipgloss.transformKey (exhaustive)
case foregroundKey:
c = s.fgColor
case backgroundKey:
c = s.bgColor
case marginBackgroundKey:
c = s.marginBgColor
case borderTopForegroundKey:
c = s.borderTopFgColor
case borderRightForegroundKey:
c = s.borderRightFgColor
case borderBottomForegroundKey:
c = s.borderBottomFgColor
case borderLeftForegroundKey:
c = s.borderLeftFgColor
case borderTopBackgroundKey:
c = s.borderTopBgColor
case borderRightBackgroundKey:
c = s.borderRightBgColor
case borderBottomBackgroundKey:
c = s.borderBottomBgColor
case borderLeftBackgroundKey:
c = s.borderLeftBgColor
}

if c != nil {
return c
}

return noColor
}

func (s Style) getAsInt(k propKey) int {
v, ok := s.rules[k]
if !ok {
if !s.isSet(k) {
return 0
}
if i, ok := v.(int); ok {
return i
switch k {

Check failure on line 471 in get.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type lipgloss.propKey: lipgloss.boldKey, lipgloss.italicKey, lipgloss.underlineKey, lipgloss.strikethroughKey, lipgloss.reverseKey, lipgloss.blinkKey, lipgloss.faintKey, lipgloss.underlineSpacesKey, lipgloss.strikethroughSpacesKey, lipgloss.colorWhitespaceKey, lipgloss.foregroundKey, lipgloss.backgroundKey, lipgloss.alignHorizontalKey, lipgloss.alignVerticalKey, lipgloss.marginBackgroundKey, lipgloss.borderStyleKey, lipgloss.borderTopKey, lipgloss.borderRightKey, lipgloss.borderBottomKey, lipgloss.borderLeftKey, lipgloss.borderTopForegroundKey, lipgloss.borderRightForegroundKey, lipgloss.borderBottomForegroundKey, lipgloss.borderLeftForegroundKey, lipgloss.borderTopBackgroundKey, lipgloss.borderRightBackgroundKey, lipgloss.borderBottomBackgroundKey, lipgloss.borderLeftBackgroundKey, lipgloss.inlineKey, lipgloss.transformKey (exhaustive)

Check failure on line 471 in get.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type lipgloss.propKey: lipgloss.boldKey, lipgloss.italicKey, lipgloss.underlineKey, lipgloss.strikethroughKey, lipgloss.reverseKey, lipgloss.blinkKey, lipgloss.faintKey, lipgloss.underlineSpacesKey, lipgloss.strikethroughSpacesKey, lipgloss.colorWhitespaceKey, lipgloss.foregroundKey, lipgloss.backgroundKey, lipgloss.alignHorizontalKey, lipgloss.alignVerticalKey, lipgloss.marginBackgroundKey, lipgloss.borderStyleKey, lipgloss.borderTopKey, lipgloss.borderRightKey, lipgloss.borderBottomKey, lipgloss.borderLeftKey, lipgloss.borderTopForegroundKey, lipgloss.borderRightForegroundKey, lipgloss.borderBottomForegroundKey, lipgloss.borderLeftForegroundKey, lipgloss.borderTopBackgroundKey, lipgloss.borderRightBackgroundKey, lipgloss.borderBottomBackgroundKey, lipgloss.borderLeftBackgroundKey, lipgloss.inlineKey, lipgloss.transformKey (exhaustive)
case widthKey:
return s.width
case heightKey:
return s.height
case paddingTopKey:
return s.paddingTop
case paddingRightKey:
return s.paddingRight
case paddingBottomKey:
return s.paddingBottom
case paddingLeftKey:
return s.paddingLeft
case marginTopKey:
return s.marginTop
case marginRightKey:
return s.marginRight
case marginBottomKey:
return s.marginBottom
case marginLeftKey:
return s.marginLeft
case maxWidthKey:
return s.maxWidth
case maxHeightKey:
return s.maxHeight
case tabWidthKey:
return s.tabWidth
}
return 0
}

func (s Style) getAsPosition(k propKey) Position {
v, ok := s.rules[k]
if !ok {
if !s.isSet(k) {
return Position(0)
}
if p, ok := v.(Position); ok {
return p
switch k {

Check failure on line 506 in get.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type lipgloss.propKey: lipgloss.boldKey, lipgloss.italicKey, lipgloss.underlineKey, lipgloss.strikethroughKey, lipgloss.reverseKey, lipgloss.blinkKey, lipgloss.faintKey, lipgloss.underlineSpacesKey, lipgloss.strikethroughSpacesKey, lipgloss.colorWhitespaceKey, lipgloss.foregroundKey, lipgloss.backgroundKey, lipgloss.widthKey, lipgloss.heightKey, lipgloss.paddingTopKey, lipgloss.paddingRightKey, lipgloss.paddingBottomKey, lipgloss.paddingLeftKey, lipgloss.marginTopKey, lipgloss.marginRightKey, lipgloss.marginBottomKey, lipgloss.marginLeftKey, lipgloss.marginBackgroundKey, lipgloss.borderStyleKey, lipgloss.borderTopKey, lipgloss.borderRightKey, lipgloss.borderBottomKey, lipgloss.borderLeftKey, lipgloss.borderTopForegroundKey, lipgloss.borderRightForegroundKey, lipgloss.borderBottomForegroundKey, lipgloss.borderLeftForegroundKey, lipgloss.borderTopBackgroundKey, lipgloss.borderRightBackgroundKey, lipgloss.borderBottomBackgroundKey, lipgloss.borderLeftBackgroundKey, lipgloss.inlineKey, lipgloss.maxWidthKey, lipgloss.maxHeightKey, lipgloss.tabWidthKey, lipgloss.transformKey (exhaustive)

Check failure on line 506 in get.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type lipgloss.propKey: lipgloss.boldKey, lipgloss.italicKey, lipgloss.underlineKey, lipgloss.strikethroughKey, lipgloss.reverseKey, lipgloss.blinkKey, lipgloss.faintKey, lipgloss.underlineSpacesKey, lipgloss.strikethroughSpacesKey, lipgloss.colorWhitespaceKey, lipgloss.foregroundKey, lipgloss.backgroundKey, lipgloss.widthKey, lipgloss.heightKey, lipgloss.paddingTopKey, lipgloss.paddingRightKey, lipgloss.paddingBottomKey, lipgloss.paddingLeftKey, lipgloss.marginTopKey, lipgloss.marginRightKey, lipgloss.marginBottomKey, lipgloss.marginLeftKey, lipgloss.marginBackgroundKey, lipgloss.borderStyleKey, lipgloss.borderTopKey, lipgloss.borderRightKey, lipgloss.borderBottomKey, lipgloss.borderLeftKey, lipgloss.borderTopForegroundKey, lipgloss.borderRightForegroundKey, lipgloss.borderBottomForegroundKey, lipgloss.borderLeftForegroundKey, lipgloss.borderTopBackgroundKey, lipgloss.borderRightBackgroundKey, lipgloss.borderBottomBackgroundKey, lipgloss.borderLeftBackgroundKey, lipgloss.inlineKey, lipgloss.maxWidthKey, lipgloss.maxHeightKey, lipgloss.tabWidthKey, lipgloss.transformKey (exhaustive)
case alignHorizontalKey:
return s.alignHorizontal
case alignVerticalKey:
return s.alignVertical
}
return Position(0)
}

func (s Style) getBorderStyle() Border {
v, ok := s.rules[borderStyleKey]
if !ok {
if !s.isSet(borderStyleKey) {
return noBorder
}
if b, ok := v.(Border); ok {
return b
}
return noBorder
return s.borderStyle
}

func (s Style) getAsTransform(k propKey) func(string) string {

Check warning on line 522 in get.go

View workflow job for this annotation

GitHub Actions / lint

unused-parameter: parameter 'k' seems to be unused, consider removing or renaming it as _ (revive)
v, ok := s.rules[k]
if !ok {
if !s.isSet(transformKey) {
return nil
}
if fn, ok := v.(func(string) string); ok {
return fn
}
return nil
return s.transform
}

// Split a string into lines, additionally returning the size of the widest
Expand Down
171 changes: 150 additions & 21 deletions set.go
@@ -1,34 +1,163 @@
package lipgloss

// This could (should) probably just be moved into NewStyle(). We've broken it
// out, so we can call it in a lazy way.
func (s *Style) init() {
if s.rules == nil {
s.rules = make(rules)
}
}

// Set a value on the underlying rules map.
func (s *Style) set(key propKey, value interface{}) {
s.init()

switch v := value.(type) {
case int:
// We don't allow negative integers on any of our other values, so just keep
// them at zero or above. We could use uints instead, but the
// conversions are a little tedious, so we're sticking with ints for
// sake of usability.
switch key {

Check failure on line 9 in set.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type lipgloss.propKey: lipgloss.boldKey, lipgloss.italicKey, lipgloss.underlineKey, lipgloss.strikethroughKey, lipgloss.reverseKey, lipgloss.blinkKey, lipgloss.faintKey, lipgloss.underlineSpacesKey, lipgloss.strikethroughSpacesKey, lipgloss.colorWhitespaceKey, lipgloss.borderTopKey, lipgloss.borderRightKey, lipgloss.borderBottomKey, lipgloss.borderLeftKey, lipgloss.inlineKey (exhaustive)

Check failure on line 9 in set.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type lipgloss.propKey: lipgloss.boldKey, lipgloss.italicKey, lipgloss.underlineKey, lipgloss.strikethroughKey, lipgloss.reverseKey, lipgloss.blinkKey, lipgloss.faintKey, lipgloss.underlineSpacesKey, lipgloss.strikethroughSpacesKey, lipgloss.colorWhitespaceKey, lipgloss.borderTopKey, lipgloss.borderRightKey, lipgloss.borderBottomKey, lipgloss.borderLeftKey, lipgloss.inlineKey (exhaustive)
case foregroundKey:
s.fgColor = colorOrNil(value)
case backgroundKey:
s.bgColor = colorOrNil(value)
case widthKey:
s.width = max(0, value.(int))
case heightKey:
s.height = max(0, value.(int))
case alignHorizontalKey:
s.alignHorizontal = value.(Position)
case alignVerticalKey:
s.alignVertical = value.(Position)
case paddingTopKey:
s.paddingTop = max(0, value.(int))
case paddingRightKey:
s.paddingRight = max(0, value.(int))
case paddingBottomKey:
s.paddingBottom = max(0, value.(int))
case paddingLeftKey:
s.paddingLeft = max(0, value.(int))
case marginTopKey:
s.marginTop = max(0, value.(int))
case marginRightKey:
s.marginRight = max(0, value.(int))
case marginBottomKey:
s.marginBottom = max(0, value.(int))
case marginLeftKey:
s.marginLeft = max(0, value.(int))
case marginBackgroundKey:
s.marginBgColor = colorOrNil(value)
case borderStyleKey:
s.borderStyle = value.(Border)
case borderTopForegroundKey:
s.borderTopFgColor = colorOrNil(value)
case borderRightForegroundKey:
s.borderRightFgColor = colorOrNil(value)
case borderBottomForegroundKey:
s.borderBottomFgColor = colorOrNil(value)
case borderLeftForegroundKey:
s.borderLeftFgColor = colorOrNil(value)
case borderTopBackgroundKey:
s.borderTopBgColor = colorOrNil(value)
case borderRightBackgroundKey:
s.borderRightBgColor = colorOrNil(value)
case borderBottomBackgroundKey:
s.borderBottomBgColor = colorOrNil(value)
case borderLeftBackgroundKey:
s.borderLeftBgColor = colorOrNil(value)
case maxWidthKey:
s.maxWidth = max(0, value.(int))
case maxHeightKey:
s.maxHeight = max(0, value.(int))
case tabWidthKey:
// TabWidth is the only property that may have a negative value (and
// that negative value can be no less than -1).
if key == tabWidthKey {
s.rules[key] = v
break
s.tabWidth = value.(int)
case transformKey:
s.transform = value.(func(string) string)
default:
if v, ok := value.(bool); ok {

Check failure on line 69 in set.go

View workflow job for this annotation

GitHub Actions / lint-soft

`if ok` has complex nested blocks (complexity: 5) (nestif)

Check failure on line 69 in set.go

View workflow job for this annotation

GitHub Actions / lint-soft

`if ok` has complex nested blocks (complexity: 5) (nestif)
if v {
s.attrs |= int(key)
} else {
s.attrs &^= int(key)
}
} else if attrs, ok := value.(int); ok {
// bool attrs
if attrs&int(key) != 0 {
s.attrs |= int(key)
} else {
s.attrs &^= int(key)
}
}
}

// We don't allow negative integers on any of our other values, so just keep
// them at zero or above. We could use uints instead, but the
// conversions are a little tedious, so we're sticking with ints for
// sake of usability.
s.rules[key] = max(0, v)
// Set the prop on
s.props = s.props.set(key)
}

// setFrom sets the property from another style.
func (s *Style) setFrom(key propKey, i Style) {
switch key {

Check failure on line 91 in set.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type lipgloss.propKey: lipgloss.boldKey, lipgloss.italicKey, lipgloss.underlineKey, lipgloss.strikethroughKey, lipgloss.reverseKey, lipgloss.blinkKey, lipgloss.faintKey, lipgloss.underlineSpacesKey, lipgloss.strikethroughSpacesKey, lipgloss.colorWhitespaceKey, lipgloss.borderTopKey, lipgloss.borderRightKey, lipgloss.borderBottomKey, lipgloss.borderLeftKey, lipgloss.inlineKey (exhaustive)

Check failure on line 91 in set.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type lipgloss.propKey: lipgloss.boldKey, lipgloss.italicKey, lipgloss.underlineKey, lipgloss.strikethroughKey, lipgloss.reverseKey, lipgloss.blinkKey, lipgloss.faintKey, lipgloss.underlineSpacesKey, lipgloss.strikethroughSpacesKey, lipgloss.colorWhitespaceKey, lipgloss.borderTopKey, lipgloss.borderRightKey, lipgloss.borderBottomKey, lipgloss.borderLeftKey, lipgloss.inlineKey (exhaustive)
case foregroundKey:
s.set(foregroundKey, i.fgColor)
case backgroundKey:
s.set(backgroundKey, i.bgColor)
case widthKey:
s.set(widthKey, i.width)
case heightKey:
s.set(heightKey, i.height)
case alignHorizontalKey:
s.set(alignHorizontalKey, i.alignHorizontal)
case alignVerticalKey:
s.set(alignVerticalKey, i.alignVertical)
case paddingTopKey:
s.set(paddingTopKey, i.paddingTop)
case paddingRightKey:
s.set(paddingRightKey, i.paddingRight)
case paddingBottomKey:
s.set(paddingBottomKey, i.paddingBottom)
case paddingLeftKey:
s.set(paddingLeftKey, i.paddingLeft)
case marginTopKey:
s.set(marginTopKey, i.marginTop)
case marginRightKey:
s.set(marginRightKey, i.marginRight)
case marginBottomKey:
s.set(marginBottomKey, i.marginBottom)
case marginLeftKey:
s.set(marginLeftKey, i.marginLeft)
case marginBackgroundKey:
s.set(marginBackgroundKey, i.marginBgColor)
case borderStyleKey:
s.set(borderStyleKey, i.borderStyle)
case borderTopForegroundKey:
s.set(borderTopForegroundKey, i.borderTopFgColor)
case borderRightForegroundKey:
s.set(borderRightForegroundKey, i.borderRightFgColor)
case borderBottomForegroundKey:
s.set(borderBottomForegroundKey, i.borderBottomFgColor)
case borderLeftForegroundKey:
s.set(borderLeftForegroundKey, i.borderLeftFgColor)
case borderTopBackgroundKey:
s.set(borderTopBackgroundKey, i.borderTopBgColor)
case borderRightBackgroundKey:
s.set(borderRightBackgroundKey, i.borderRightBgColor)
case borderBottomBackgroundKey:
s.set(borderBottomBackgroundKey, i.borderBottomBgColor)
case borderLeftBackgroundKey:
s.set(borderLeftBackgroundKey, i.borderLeftBgColor)
case maxWidthKey:
s.set(maxWidthKey, i.maxWidth)
case maxHeightKey:
s.set(maxHeightKey, i.maxHeight)
case tabWidthKey:
s.set(tabWidthKey, i.tabWidth)
case transformKey:
s.set(transformKey, i.transform)
default:
s.rules[key] = v
if i.props.has(key) {
// Set attributes for set bool properties
s.set(key, i.attrs)
}
}
}

func colorOrNil(c interface{}) TerminalColor {
if c, ok := c.(TerminalColor); ok {
return c
}
return nil
}

// Bold sets a bold formatting rule.
Expand Down

0 comments on commit 8c95fd7

Please sign in to comment.