From 3961136a13e9429df6220fdefbca75deb65d01a3 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 4 Feb 2025 14:26:33 -0500 Subject: [PATCH 1/3] fix(viewport): handle nil LeftGutterFunc (#723) Since LeftGutterFunc is public, it can be nil if viewport is instantiated without using `viewport.New()`. This commit adds nil checks to handle this case. --- viewport/viewport.go | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/viewport/viewport.go b/viewport/viewport.go index 8ac13ea9..4f13c168 100644 --- a/viewport/viewport.go +++ b/viewport/viewport.go @@ -243,7 +243,11 @@ func (m Model) calculateLine(yoffset int) (total, idx int) { return len(m.lines), yoffset } maxWidth := m.maxWidth() - gutterSize := lipgloss.Width(m.LeftGutterFunc(GutterContext{})) + + var gutterSize int + if m.LeftGutterFunc != nil { + gutterSize = lipgloss.Width(m.LeftGutterFunc(GutterContext{})) + } for i, line := range m.lines { adjust := max(1, ansi.StringWidth(line)/(maxWidth-gutterSize)) if yoffset >= total && yoffset < total+adjust { @@ -281,9 +285,13 @@ func (m Model) maxXOffset() int { } func (m Model) maxWidth() int { + var gutterSize int + if m.LeftGutterFunc != nil { + gutterSize = lipgloss.Width(m.LeftGutterFunc(GutterContext{})) + } return m.Width() - m.Style.GetHorizontalFrameSize() - - lipgloss.Width(m.LeftGutterFunc(GutterContext{})) + gutterSize } func (m Model) maxHeight() int { @@ -361,11 +369,14 @@ func (m Model) softWrap(lines []string, maxWidth int) []string { idx := 0 for ansi.StringWidth(line) >= idx { truncatedLine := ansi.Cut(line, idx, maxWidth+idx) - wrappedLines = append(wrappedLines, m.LeftGutterFunc(GutterContext{ - Index: i + m.YOffset, - TotalLines: m.TotalLineCount(), - Soft: idx > 0, - })+truncatedLine) + if m.LeftGutterFunc != nil { + truncatedLine = m.LeftGutterFunc(GutterContext{ + Index: i + m.YOffset, + TotalLines: m.TotalLineCount(), + Soft: idx > 0, + }) + truncatedLine + } + wrappedLines = append(wrappedLines, truncatedLine) idx += maxWidth } } @@ -375,10 +386,13 @@ func (m Model) softWrap(lines []string, maxWidth int) []string { func (m Model) prependColumn(lines []string) []string { result := make([]string, len(lines)) for i, line := range lines { - result[i] = m.LeftGutterFunc(GutterContext{ - Index: i + m.YOffset, - TotalLines: m.TotalLineCount(), - }) + line + if m.LeftGutterFunc != nil { + line = m.LeftGutterFunc(GutterContext{ + Index: i + m.YOffset, + TotalLines: m.TotalLineCount(), + }) + line + } + result[i] = line } return result } From a7783a1a588bad3dede298cb8a683063de4e9773 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 4 Feb 2025 14:45:04 -0500 Subject: [PATCH 2/3] chore: go mod tidy --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index 07c14970..d70371df 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,6 @@ github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= 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.20250203222705-2e91ec2235cd h1:u+kqgSbIL4pnP7huv4kaYUCmuN2L4yyDvdH81QJ4FZ0= -github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.2.0.20250203222705-2e91ec2235cd/go.mod h1:zaWGYfO6cBtu4dRgGbVN7yMYUz3j9sVIzHy2gn0jdo8= github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.2.0.20250204175057-2a96bc438da6 h1:KbLqbYgHC5JZWks50WjBJr92Hs+GpiauwZaDObw9vxE= github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.2.0.20250204175057-2a96bc438da6/go.mod h1:zaWGYfO6cBtu4dRgGbVN7yMYUz3j9sVIzHy2gn0jdo8= github.com/charmbracelet/colorprofile v0.2.0 h1:iiIQlp3LSvoJPtR11KoDfIf9wqWm2mn/iU420rHOZ/A= From 64c16e990e33dcbb046a589257a36133be8e6989 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Wed, 5 Feb 2025 10:00:01 -0300 Subject: [PATCH 3/3] feat(v2)!: update to go 1.22 (#724) * feat(v2)!: update to go 1.22 * fix: ci * fix: more --- .github/workflows/build.yml | 2 +- .github/workflows/coverage.yml | 2 +- filepicker/filepicker.go | 7 ------- go.mod | 2 +- go.sum | 4 ++++ list/list.go | 7 ------- list/list_test.go | 4 ++-- paginator/paginator.go | 7 ------- progress/progress.go | 14 -------------- table/table.go | 16 ---------------- textarea/textarea.go | 14 -------------- textinput/textinput.go | 14 -------------- viewport/viewport.go | 23 +++-------------------- 13 files changed, 12 insertions(+), 104 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f804b0cd..e9fea580 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ jobs: test: strategy: matrix: - go-version: [~1.18, ^1] + go-version: [~1.22, ^1] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} env: diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 7998ddf7..40a4bf1c 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -5,7 +5,7 @@ jobs: coverage: strategy: matrix: - go-version: [^1.18] + go-version: [^1.22] os: [ubuntu-latest] runs-on: ${{ matrix.os }} env: diff --git a/filepicker/filepicker.go b/filepicker/filepicker.go index 86aaad01..89b31b75 100644 --- a/filepicker/filepicker.go +++ b/filepicker/filepicker.go @@ -511,10 +511,3 @@ func (m Model) canSelect(file string) bool { } return false } - -func max(a, b int) int { - if a > b { - return a - } - return b -} diff --git a/go.mod b/go.mod index aa3c9a0b..33ffc312 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/charmbracelet/bubbles/v2 -go 1.18 +go 1.22 require ( github.com/MakeNowJust/heredoc v1.0.0 diff --git a/go.sum b/go.sum index d70371df..d3275821 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6 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.20250204175057-2a96bc438da6 h1:KbLqbYgHC5JZWks50WjBJr92Hs+GpiauwZaDObw9vxE= @@ -32,11 +33,13 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ 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= @@ -45,6 +48,7 @@ github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8 github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= diff --git a/list/list.go b/list/list.go index 50681b17..8f0a5979 100644 --- a/list/list.go +++ b/list/list.go @@ -1323,10 +1323,3 @@ func countEnabledBindings(groups [][]key.Binding) (agg int) { } return agg } - -func max(a, b int) int { - if a > b { - return a - } - return b -} diff --git a/list/list_test.go b/list/list_test.go index d1d8524b..90c5008b 100644 --- a/list/list_test.go +++ b/list/list_test.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "reflect" + "slices" "strings" "testing" @@ -82,8 +83,7 @@ func TestSetFilterText(t *testing.T) { list.SetFilterState(Unfiltered) expected := tc - // TODO: replace with slices.Equal() when project move to go1.18 or later - if !reflect.DeepEqual(list.VisibleItems(), expected) { + if !slices.Equal(list.VisibleItems(), expected) { t.Fatalf("Error: expected view to contain only %s", expected) } diff --git a/paginator/paginator.go b/paginator/paginator.go index 1fea948b..7abe3269 100644 --- a/paginator/paginator.go +++ b/paginator/paginator.go @@ -198,10 +198,3 @@ func (m Model) dotsView() string { func (m Model) arabicView() string { return fmt.Sprintf(m.ArabicFormat, m.Page+1, m.TotalPages) } - -func min(a, b int) int { - if a < b { - return a - } - return b -} diff --git a/progress/progress.go b/progress/progress.go index 10aa9f05..fadc42cf 100644 --- a/progress/progress.go +++ b/progress/progress.go @@ -345,22 +345,8 @@ func (m *Model) setRamp(colorA, colorB string, scaled bool) { m.rampColorB = b } -func max(a, b int) int { - if a > b { - return a - } - return b -} - // IsAnimating returns false if the progress bar reached equilibrium and is no longer animating. func (m *Model) IsAnimating() bool { dist := math.Abs(m.percentShown - m.targetPercent) return !(dist < 0.001 && m.velocity < 0.01) } - -func min(a, b int) int { - if a < b { - return a - } - return b -} diff --git a/table/table.go b/table/table.go index 1ef645f0..f1b49b2d 100644 --- a/table/table.go +++ b/table/table.go @@ -437,22 +437,6 @@ func (m *Model) renderRow(r int) string { return row } -func max(a, b int) int { - if a > b { - return a - } - - return b -} - -func min(a, b int) int { - if a < b { - return a - } - - return b -} - func clamp(v, low, high int) int { return min(max(v, low), high) } diff --git a/textarea/textarea.go b/textarea/textarea.go index 39e5fed4..b054dee2 100644 --- a/textarea/textarea.go +++ b/textarea/textarea.go @@ -1645,20 +1645,6 @@ func clamp(v, low, high int) int { return min(high, max(low, v)) } -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - func abs(n int) int { if n < 0 { return -n diff --git a/textinput/textinput.go b/textinput/textinput.go index 92c468ac..907288b2 100644 --- a/textinput/textinput.go +++ b/textinput/textinput.go @@ -761,20 +761,6 @@ func clamp(v, low, high int) int { return min(high, max(low, v)) } -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - func (m Model) completionView(offset int) string { var ( value = m.value diff --git a/viewport/viewport.go b/viewport/viewport.go index 4f13c168..57638f15 100644 --- a/viewport/viewport.go +++ b/viewport/viewport.go @@ -701,27 +701,10 @@ func clamp(v, low, high int) int { return min(high, max(low, v)) } -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - func maxLineWidth(lines []string) int { - maxlen := 0 + result := 0 for _, line := range lines { - llen := ansi.StringWidth(line) - if llen > maxlen { - maxlen = llen - } + result = max(result, ansi.StringWidth(line)) } - return maxlen + return result }