Skip to content

Commit

Permalink
feat: make Lipgloss Style thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
muesli committed Feb 28, 2023
1 parent a74950e commit 40bcc0e
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 107 deletions.
18 changes: 18 additions & 0 deletions get.go
Expand Up @@ -397,11 +397,17 @@ func (s Style) GetFrameSize() (x, y int) {

// Returns whether or not the given property is set.
func (s Style) isSet(k propKey) bool {
s.mtx.RLock()
defer s.mtx.RUnlock()

_, exists := s.rules[k]
return exists
}

func (s Style) getAsBool(k propKey, defaultVal bool) bool {
s.mtx.RLock()
defer s.mtx.RUnlock()

v, ok := s.rules[k]
if !ok {
return defaultVal
Expand All @@ -413,6 +419,9 @@ func (s Style) getAsBool(k propKey, defaultVal bool) bool {
}

func (s Style) getAsColor(k propKey) TerminalColor {
s.mtx.RLock()
defer s.mtx.RUnlock()

v, ok := s.rules[k]
if !ok {
return noColor
Expand All @@ -424,6 +433,9 @@ func (s Style) getAsColor(k propKey) TerminalColor {
}

func (s Style) getAsInt(k propKey) int {
s.mtx.RLock()
defer s.mtx.RUnlock()

v, ok := s.rules[k]
if !ok {
return 0
Expand All @@ -435,6 +447,9 @@ func (s Style) getAsInt(k propKey) int {
}

func (s Style) getAsPosition(k propKey) Position {
s.mtx.RLock()
defer s.mtx.RUnlock()

v, ok := s.rules[k]
if !ok {
return Position(0)
Expand All @@ -446,6 +461,9 @@ func (s Style) getAsPosition(k propKey) Position {
}

func (s Style) getBorderStyle() Border {
s.mtx.RLock()
defer s.mtx.RUnlock()

v, ok := s.rules[borderStyleKey]
if !ok {
return noBorder
Expand Down
3 changes: 3 additions & 0 deletions set.go
Expand Up @@ -10,6 +10,9 @@ func (s *Style) init() {

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

s.init()

switch v := value.(type) {
Expand Down
25 changes: 23 additions & 2 deletions style.go
Expand Up @@ -2,6 +2,7 @@ package lipgloss

import (
"strings"
"sync"
"unicode"

"github.com/muesli/reflow/truncate"
Expand Down Expand Up @@ -98,17 +99,22 @@ func NewStyle(opts ...StyleOption) Style {
// in case the underlying implementation changes. It takes an optional string
// value to be set as the underlying string value for this style.
func (r *Renderer) NewStyle(opts ...StyleOption) Style {
s := Style{r: r}
s := Style{
mtx: &sync.RWMutex{},
r: r,
}
for _, opt := range opts {
opt(&s)
}
return s
}

// Style contains a set of rules that comprise a style as a whole.
// It is safe for concurrent use by multiple goroutines.
type Style struct {
mtx *sync.RWMutex
r *Renderer
rules map[propKey]interface{}
rules rules
value string
}

Expand All @@ -124,12 +130,18 @@ func joinString(strs ...string) string {
// as when using fmt.Sprintf. You can also simply define a style and render out
// strings directly with Style.Render.
func (s Style) SetString(strs ...string) Style {
s.mtx.Lock()
defer s.mtx.Unlock()

s.value = joinString(strs...)
return s
}

// Value returns the raw, unformatted, underlying string value for this style.
func (s Style) Value() string {
s.mtx.RLock()
defer s.mtx.RUnlock()

return s.value
}

Expand All @@ -142,6 +154,9 @@ func (s Style) String() string {

// Copy returns a copy of this style, including any underlying string values.
func (s Style) Copy() Style {
s.mtx.RLock()
defer s.mtx.RUnlock()

o := NewStyle()
o.init()
for k, v := range s.rules {
Expand All @@ -158,6 +173,9 @@ func (s Style) Copy() Style {
//
// Margins, padding, and underlying string values are not inherited.
func (s Style) Inherit(i Style) Style {
i.mtx.RLock()
defer i.mtx.RUnlock()

s.init()

for k, v := range i.rules {
Expand Down Expand Up @@ -185,6 +203,9 @@ func (s Style) Inherit(i Style) Style {

// Render applies the defined style formatting to a given string.
func (s Style) Render(strs ...string) string {
s.mtx.RLock()
defer s.mtx.RUnlock()

if s.r == nil {
s.r = DefaultRenderer()
}
Expand Down

0 comments on commit 40bcc0e

Please sign in to comment.