From 2e3a42396e9952e9b3de4ac9eda4d81134ef9af3 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Thu, 12 Dec 2024 10:51:23 -0500 Subject: [PATCH] chore(progress)!: migrate progress to lipgloss (#676) * chore(progress)!: migrate progress to lipgloss This removes the dependency on termenv and replaces it with lipgloss. This change also removes the WithColorProfile option, as it is no longer needed. The new API uses `color.Color` types for colors, which are more flexible and allow for more advanced color manipulation. * Update progress/progress_test.go Co-authored-by: Christian Rocha * Update progress/progress_test.go Co-authored-by: Christian Rocha * chore: go mod tidy --------- Co-authored-by: Christian Rocha --- go.mod | 5 +---- go.sum | 11 ++-------- progress/progress.go | 45 ++++++++++++--------------------------- progress/progress_test.go | 12 +++++------ 4 files changed, 22 insertions(+), 51 deletions(-) diff --git a/go.mod b/go.mod index 6c74148..15668ce 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 - github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.2.0.20241121171714-fbd5423ea935 + github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.2.0.20241126192050-a8ed96118b08 github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss/v2 v2.0.0-alpha.2.0.20241121164047-8448a9be4804 github.com/charmbracelet/x/ansi v0.5.1 @@ -13,13 +13,11 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/lucasb-eyer/go-colorful v1.2.0 github.com/mattn/go-runewidth v0.0.16 - github.com/muesli/termenv v0.15.2 github.com/rivo/uniseg v0.4.7 github.com/sahilm/fuzzy v0.1.1 ) require ( - github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-udiff v0.2.0 // indirect github.com/charmbracelet/colorprofile v0.1.8 // indirect github.com/charmbracelet/x/cellbuf v0.0.6 // indirect @@ -28,7 +26,6 @@ require ( github.com/charmbracelet/x/wcwidth v0.0.0-20241113152101-0af7d04e9f32 // indirect github.com/charmbracelet/x/windows v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect golang.org/x/sync v0.9.0 // indirect diff --git a/go.sum b/go.sum index dfc4079..2c3c84b 100644 --- a/go.sum +++ b/go.sum @@ -2,12 +2,10 @@ github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= -github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= -github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.2.0.20241121171714-fbd5423ea935 h1:S+hhEwWnJxDeZMtHqIHgGVilNWsez3xmFOpwSc9GbcE= -github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.2.0.20241121171714-fbd5423ea935/go.mod h1:BbC4R+6e9TLjbskxrjISt/DDCn4OiB6v+ArqfYiPyyg= +github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.2.0.20241126192050-a8ed96118b08 h1:8hwULvCHjF6JjaeosebMGbB06oCv46d4s+Lbs5ytAT4= +github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.2.0.20241126192050-a8ed96118b08/go.mod h1:BbC4R+6e9TLjbskxrjISt/DDCn4OiB6v+ArqfYiPyyg= github.com/charmbracelet/colorprofile v0.1.8 h1:PywDeXsiAzlPtkiiKgMEVLvb6nlEuKrMj9+FJBtj4jU= github.com/charmbracelet/colorprofile v0.1.8/go.mod h1:+jpmObxZl1Dab3H3IMVIPSZTsKcFpjJUv97G0dLqM60= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= @@ -34,14 +32,10 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= -github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= -github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -52,7 +46,6 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJu golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= diff --git a/progress/progress.go b/progress/progress.go index b4c9129..b596c30 100644 --- a/progress/progress.go +++ b/progress/progress.go @@ -2,6 +2,7 @@ package progress import ( "fmt" + "image/color" "math" "strings" "sync/atomic" @@ -12,7 +13,6 @@ import ( "github.com/charmbracelet/lipgloss/v2" "github.com/charmbracelet/x/ansi" "github.com/lucasb-eyer/go-colorful" - "github.com/muesli/termenv" ) // Internal ID management. Used during animating to assure that frame messages @@ -65,7 +65,7 @@ func WithScaledGradient(colorA, colorB string) Option { } // WithSolidFill sets the progress to use a solid fill with the given color. -func WithSolidFill(color string) Option { +func WithSolidFill(color color.Color) Option { return func(m *Model) { m.FullColor = color m.useRamp = false @@ -108,13 +108,6 @@ func WithSpringOptions(frequency, damping float64) Option { } } -// WithColorProfile sets the color profile to use for the progress bar. -func WithColorProfile(p termenv.Profile) Option { - return func(m *Model) { - m.colorProfile = p - } -} - // FrameMsg indicates that an animation step should occur. type FrameMsg struct { id int @@ -135,11 +128,11 @@ type Model struct { // "Filled" sections of the progress bar. Full rune - FullColor string + FullColor color.Color // "Empty" sections of the progress bar. Empty rune - EmptyColor string + EmptyColor color.Color // Settings for rendering the numeric percentage. ShowPercentage bool @@ -162,9 +155,6 @@ type Model struct { // of the progress bar. When false, the width of the gradient will be set // to the full width of the progress bar. scaleRamp bool - - // Color profile for the progress bar. - colorProfile termenv.Profile } // New returns a model with default values. @@ -173,12 +163,11 @@ func New(opts ...Option) Model { id: nextID(), width: defaultWidth, Full: '█', - FullColor: "#7571F9", + FullColor: lipgloss.Color("#7571F9"), Empty: '░', - EmptyColor: "#606060", + EmptyColor: lipgloss.Color("#606060"), ShowPercentage: true, PercentFormat: " %3.0f%%", - colorProfile: termenv.ColorProfile(), } for _, opt := range opts { @@ -316,23 +305,21 @@ func (m Model) barView(b *strings.Builder, percent float64, textWidth int) { } else { p = float64(i) / float64(tw-1) } - c := m.rampColorA.BlendLuv(m.rampColorB, p).Hex() - b.WriteString(termenv. - String(string(m.Full)). - Foreground(m.color(c)). - String(), - ) + c := m.rampColorA.BlendLuv(m.rampColorB, p) + b.WriteString(lipgloss.NewStyle().Foreground(c).Render(string(m.Full))) } } else { // Solid fill - s := termenv.String(string(m.Full)).Foreground(m.color(m.FullColor)).String() - b.WriteString(strings.Repeat(s, fw)) + b.WriteString(lipgloss.NewStyle(). + Foreground(m.FullColor). + Render(strings.Repeat(string(m.Full), fw))) } // Empty fill - e := termenv.String(string(m.Empty)).Foreground(m.color(m.EmptyColor)).String() n := max(0, tw-fw) - b.WriteString(strings.Repeat(e, n)) + b.WriteString(lipgloss.NewStyle(). + Foreground(m.EmptyColor). + Render(strings.Repeat(string(m.Empty), n))) } func (m Model) percentageView(percent float64) string { @@ -358,10 +345,6 @@ func (m *Model) setRamp(colorA, colorB string, scaled bool) { m.rampColorB = b } -func (m Model) color(c string) termenv.Color { - return m.colorProfile.Color(c) -} - func max(a, b int) int { if a > b { return a diff --git a/progress/progress_test.go b/progress/progress_test.go index a4ba720..08bd52b 100644 --- a/progress/progress_test.go +++ b/progress/progress_test.go @@ -4,15 +4,14 @@ import ( "strings" "testing" - "github.com/muesli/termenv" + "github.com/charmbracelet/lipgloss/v2" ) const ( - AnsiReset = "\x1b[0m" + AnsiReset = "\x1b[m" ) func TestGradient(t *testing.T) { - colA := "#FF0000" colB := "#00FF00" @@ -21,7 +20,7 @@ func TestGradient(t *testing.T) { for _, scale := range []bool{false, true} { opts := []Option{ - WithColorProfile(termenv.TrueColor), WithoutPercentage(), + WithoutPercentage(), } if scale { descr = "progress bar with scaled gradient" @@ -36,10 +35,10 @@ func TestGradient(t *testing.T) { // build the expected colors by colorizing an empty string and then cutting off the following reset sequence sb := strings.Builder{} - sb.WriteString(termenv.String("").Foreground(p.color(colA)).String()) + sb.WriteString(lipgloss.NewStyle().Foreground(lipgloss.Color(colA)).String()) expFirst := strings.Split(sb.String(), AnsiReset)[0] sb.Reset() - sb.WriteString(termenv.String("").Foreground(p.color(colB)).String()) + sb.WriteString(lipgloss.NewStyle().Foreground(lipgloss.Color(colB)).String()) expLast := strings.Split(sb.String(), AnsiReset)[0] for _, width := range []int{3, 5, 50} { @@ -62,5 +61,4 @@ func TestGradient(t *testing.T) { } }) } - }