Skip to content

Commit

Permalink
feat!: make transform an interface type
Browse files Browse the repository at this point in the history
This change introduces a new `Transform` type with a canonical implementation
`TransformFunc` that can be used to transform a string at render time. This
change also updates the `Style` type to use the new `Transform` type instead of
a function type.

We need this to support complex transforms and to be able to compare styles
using the `==` operator.
  • Loading branch information
aymanbagabas committed Oct 31, 2024
1 parent 0208749 commit 1b669f5
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 17 deletions.
4 changes: 2 additions & 2 deletions get.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ func (s Style) GetFrameSize() (x, y int) {

// GetTransform returns the transform set on the style. If no transform is set
// nil is returned.
func (s Style) GetTransform() func(string) string {
func (s Style) GetTransform() Transform {
return s.getAsTransform(transformKey)
}

Expand Down Expand Up @@ -520,7 +520,7 @@ func (s Style) getBorderStyle() Border {
return s.borderStyle
}

func (s Style) getAsTransform(propKey) func(string) string {
func (s Style) getAsTransform(propKey) Transform {
if !s.isSet(transformKey) {
return nil
}
Expand Down
14 changes: 7 additions & 7 deletions list/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ func TestEnumeratorsTransform(t *testing.T) {
}{
"alphabet lower": {
enumeration: list.Alphabet,
style: lipgloss.NewStyle().PaddingRight(1).Transform(strings.ToLower),
style: lipgloss.NewStyle().PaddingRight(1).Transform(lipgloss.TransformFunc(strings.ToLower)),
expected: `
a. Foo
b. Bar
Expand All @@ -315,9 +315,9 @@ c. Baz
},
"arabic)": {
enumeration: list.Arabic,
style: lipgloss.NewStyle().PaddingRight(1).Transform(func(s string) string {
style: lipgloss.NewStyle().PaddingRight(1).Transform(lipgloss.TransformFunc(func(s string) string {
return strings.Replace(s, ".", ")", 1)
}),
})),
expected: `
1) Foo
2) Bar
Expand All @@ -326,9 +326,9 @@ c. Baz
},
"roman within ()": {
enumeration: list.Roman,
style: lipgloss.NewStyle().Transform(func(s string) string {
style: lipgloss.NewStyle().Transform(lipgloss.TransformFunc(func(s string) string {
return "(" + strings.Replace(strings.ToLower(s), ".", "", 1) + ") "
}),
})),
expected: `
(i) Foo
(ii) Bar
Expand All @@ -337,9 +337,9 @@ c. Baz
},
"bullet is dash": {
enumeration: list.Bullet,
style: lipgloss.NewStyle().Transform(func(s string) string {
style: lipgloss.NewStyle().Transform(lipgloss.TransformFunc(func(s string) string {
return "- " // this is better done by replacing the enumerator.
}),
})),
expected: `
- Foo
- Bar
Expand Down
28 changes: 23 additions & 5 deletions set.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package lipgloss

import "image/color"
import (
"image/color"
)

// Set a value on the underlying rules map.
func (s *Style) set(key propKey, value interface{}) {
Expand Down Expand Up @@ -66,7 +68,7 @@ func (s *Style) set(key propKey, value interface{}) {
// that negative value can be no less than -1).
s.tabWidth = value.(int)
case transformKey:
s.transform = value.(func(string) string)
s.transform = value.(Transform)
default:
if v, ok := value.(bool); ok { //nolint:nestif
if v {
Expand Down Expand Up @@ -675,15 +677,31 @@ func (s Style) StrikethroughSpaces(v bool) Style {
return s
}

// Transform is a method for setting a function that will be applied to the
// string at render time.
type Transform interface {
Transform(string) string
}

// TransformFunc is a function that can be used to transform a string at render
// time.
type TransformFunc func(string) string

// Transform applies a given function to a string at render time, allowing for
// the string being rendered to be manipuated.
func (t TransformFunc) Transform(s string) string {
return t(s)
}

// Transform applies a given function to a string at render time, allowing for
// the string being rendered to be manipuated.
//
// Example:
//
// s := NewStyle().Transform(strings.ToUpper)
// s := NewStyle().Transform(lipgloss.TransformFunc(strings.ToUpper))
// fmt.Println(s.Render("raow!") // "RAOW!"
func (s Style) Transform(fn func(string) string) Style {
s.set(transformKey, fn)
func (s Style) Transform(t Transform) Style {
s.set(transformKey, t)
return s
}

Expand Down
4 changes: 2 additions & 2 deletions style.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ type Style struct {
maxHeight int
tabWidth int

transform func(string) string
transform Transform
}

// joinString joins a list of strings into a single string separated with a
Expand Down Expand Up @@ -271,7 +271,7 @@ func (s Style) Render(strs ...string) string {
)

if transform != nil {
str = transform(str)
str = transform.Transform(str)
}

if s.props == 0 {
Expand Down
2 changes: 1 addition & 1 deletion style_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ func TestStringTransform(t *testing.T) {
"犬 yzal eht revo depmuj 狐 nworb kciuq ehT",
},
} {
res := NewStyle().Bold(true).Transform(tc.fn).Render(tc.input)
res := NewStyle().Bold(true).Transform(TransformFunc(tc.fn)).Render(tc.input)
expected := "\x1b[1m" + tc.expected + "\x1b[m"
if res != expected {
t.Errorf("Test #%d:\nExpected: %q\nGot: %q", i+1, expected, res)
Expand Down

0 comments on commit 1b669f5

Please sign in to comment.