From 2caa9d4bdf051e9255b15ef8d7223c991b7a6b8a Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Wed, 11 Sep 2024 17:05:46 -0400 Subject: [PATCH 01/26] chore(viewport): deprecate performance rendering stuff --- viewport/viewport.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/viewport/viewport.go b/viewport/viewport.go index e0a4cc3..1d2423a 100644 --- a/viewport/viewport.go +++ b/viewport/viewport.go @@ -50,6 +50,8 @@ type Model struct { // // This should only be used in program occupying the entire terminal, // which is usually via the alternate screen buffer. + // + // Deprecated: high performance rendering is now deprecated in Bubble Tea. HighPerformanceRendering bool initialized bool @@ -97,8 +99,7 @@ func (m Model) ScrollPercent() float64 { return math.Max(0.0, math.Min(1.0, v)) } -// SetContent set the pager's text content. For high performance rendering the -// Sync command should also be called. +// SetContent set the pager's text content. func (m *Model) SetContent(s string) { s = strings.ReplaceAll(s, "\r\n", "\n") // normalize line endings m.lines = strings.Split(s, "\n") @@ -126,6 +127,8 @@ func (m Model) visibleLines() (lines []string) { } // scrollArea returns the scrollable boundaries for high performance rendering. +// +// XXX: high performance rendering is deprecated in Bubble Tea. func (m Model) scrollArea() (top, bottom int) { top = max(0, m.YPosition) bottom = max(top, top+m.Height) @@ -189,6 +192,8 @@ func (m *Model) LineDown(n int) (lines []string) { m.SetYOffset(m.YOffset + n) // Gather lines to send off for performance scrolling. + // + // XXX: high performance rendering is deprecated in Bubble Tea. bottom := clamp(m.YOffset+m.Height, 0, len(m.lines)) top := clamp(m.YOffset+m.Height-n, 0, bottom) return m.lines[top:bottom] @@ -206,6 +211,8 @@ func (m *Model) LineUp(n int) (lines []string) { m.SetYOffset(m.YOffset - n) // Gather lines to send off for performance scrolling. + // + // XXX: high performance rendering is deprecated in Bubble Tea. top := max(0, m.YOffset) bottom := clamp(m.YOffset+n, 0, m.maxYOffset()) return m.lines[top:bottom] @@ -242,6 +249,8 @@ func (m *Model) GotoBottom() (lines []string) { // first render and after a window resize. // // For high performance rendering only. +// +// Deprecated: high performance rendering is deprecated in Bubble Tea. func Sync(m Model) tea.Cmd { if len(m.lines) == 0 { return nil @@ -261,6 +270,9 @@ func ViewDown(m Model, lines []string) tea.Cmd { return nil } top, bottom := m.scrollArea() + + // XXX: high performance rendering is deprecated in Bubble Tea. In a v2 we + // won't need to return a command here. return tea.ScrollDown(lines, top, bottom) } @@ -272,6 +284,9 @@ func ViewUp(m Model, lines []string) tea.Cmd { return nil } top, bottom := m.scrollArea() + + // XXX: high performance rendering is deprecated in Bubble Tea. In a v2 we + // won't need to return a command here. return tea.ScrollUp(lines, top, bottom) } From 64cc034014cdebfbf3514eea47a9575904e0a05b Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Wed, 11 Sep 2024 17:08:37 -0400 Subject: [PATCH 02/26] chore(lint): update deprecated directive --- .golangci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 92a9771..a096c2a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -15,7 +15,7 @@ issues: linters: enable: - bodyclose - - exportloopref + - copyloopvar - gofumpt - goimports - gosec @@ -28,6 +28,6 @@ linters: - unconvert - unparam - whitespace - # We're isabling predeclared because the linter is running a newer version + # We're disabling predeclared because the linter is running a newer version # of Go than then Go module. # - predeclared From 1797ac268d77f1273ba1bc6bd833f3327ce92c0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:04:14 -0300 Subject: [PATCH 03/26] feat(deps): bump github.com/charmbracelet/bubbletea from 1.1.0 to 1.1.1 (#611) Bumps [github.com/charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/charmbracelet/bubbletea/releases) - [Changelog](https://github.com/charmbracelet/bubbletea/blob/main/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/bubbletea/compare/v1.1.0...v1.1.1) --- updated-dependencies: - dependency-name: github.com/charmbracelet/bubbletea dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2815703..db9c9fb 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 v1.1.0 + github.com/charmbracelet/bubbletea v1.1.1 github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss v0.13.0 github.com/charmbracelet/x/ansi v0.2.3 diff --git a/go.sum b/go.sum index 9eb7dd6..78b8b2f 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE 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 v1.1.0 h1:FjAl9eAL3HBCHenhz/ZPjkKdScmaS5SK69JAK2YJK9c= -github.com/charmbracelet/bubbletea v1.1.0/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4= +github.com/charmbracelet/bubbletea v1.1.1 h1:KJ2/DnmpfqFtDNVTvYZ6zpPFL9iRCRr0qqKOCvppbPY= +github.com/charmbracelet/bubbletea v1.1.1/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= From c1199d7be61f7c9224759e9de6d3fc241b91d10c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:20:10 -0400 Subject: [PATCH 04/26] feat(deps): bump github.com/charmbracelet/x/ansi from 0.2.3 to 0.3.0 (#613) Bumps [github.com/charmbracelet/x/ansi](https://github.com/charmbracelet/x) from 0.2.3 to 0.3.0. - [Release notes](https://github.com/charmbracelet/x/releases) - [Commits](https://github.com/charmbracelet/x/compare/ansi/v0.2.3...ansi/v0.3.0) --- updated-dependencies: - dependency-name: github.com/charmbracelet/x/ansi dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index db9c9fb..c5d16c8 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/charmbracelet/bubbletea v1.1.1 github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss v0.13.0 - github.com/charmbracelet/x/ansi v0.2.3 + github.com/charmbracelet/x/ansi v0.3.0 github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b github.com/dustin/go-humanize v1.0.1 github.com/lucasb-eyer/go-colorful v1.2.0 diff --git a/go.sum b/go.sum index 78b8b2f..493b478 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= -github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY= -github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/ansi v0.3.0 h1:CCsscv7vKC/DNYUYFQNNIOWzrpTUbLXL3d4fdFIQ0WE= +github.com/charmbracelet/x/ansi v0.3.0/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q= github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= From 9589cbc16c537db95188cf65d64bf1825dba3d10 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Thu, 12 Sep 2024 13:33:07 -0400 Subject: [PATCH 05/26] fix: lint issues and disable predeclared linter (#614) --- .golangci.yml | 1 - filepicker/filepicker.go | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a096c2a..4e2ea02 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -20,7 +20,6 @@ linters: - goimports - gosec - nilerr - - predeclared - revive - rowserrcheck - sqlclosecheck diff --git a/filepicker/filepicker.go b/filepicker/filepicker.go index 9a1235a..2288a5d 100644 --- a/filepicker/filepicker.go +++ b/filepicker/filepicker.go @@ -377,7 +377,7 @@ func (m Model) View() string { var symlinkPath string info, _ := f.Info() isSymlink := info.Mode()&os.ModeSymlink != 0 - size := strings.Replace(humanize.Bytes(uint64(info.Size())), " ", "", 1) + size := strings.Replace(humanize.Bytes(uint64(info.Size())), " ", "", 1) //nolint:gosec name := f.Name() if isSymlink { From d3ac47df46a7801611741e2bde7ff3422e6a8d4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 13:15:01 -0400 Subject: [PATCH 06/26] feat(deps): bump github.com/charmbracelet/x/ansi from 0.3.0 to 0.3.1 (#615) Bumps [github.com/charmbracelet/x/ansi](https://github.com/charmbracelet/x) from 0.3.0 to 0.3.1. - [Release notes](https://github.com/charmbracelet/x/releases) - [Commits](https://github.com/charmbracelet/x/compare/ansi/v0.3.0...ansi/v0.3.1) --- updated-dependencies: - dependency-name: github.com/charmbracelet/x/ansi dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c5d16c8..6aec383 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/charmbracelet/bubbletea v1.1.1 github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss v0.13.0 - github.com/charmbracelet/x/ansi v0.3.0 + github.com/charmbracelet/x/ansi v0.3.1 github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b github.com/dustin/go-humanize v1.0.1 github.com/lucasb-eyer/go-colorful v1.2.0 diff --git a/go.sum b/go.sum index 493b478..cf3b383 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= -github.com/charmbracelet/x/ansi v0.3.0 h1:CCsscv7vKC/DNYUYFQNNIOWzrpTUbLXL3d4fdFIQ0WE= -github.com/charmbracelet/x/ansi v0.3.0/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/ansi v0.3.1 h1:CRO6lc/6HCx2/D6S/GZ87jDvRvk6GtPyFP+IljkNtqI= +github.com/charmbracelet/x/ansi v0.3.1/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q= github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= From ed14316c61e956ab460707a5db7775696fb477ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 13:53:19 -0400 Subject: [PATCH 07/26] feat(deps): bump github.com/charmbracelet/x/ansi from 0.3.1 to 0.3.2 (#618) Bumps [github.com/charmbracelet/x/ansi](https://github.com/charmbracelet/x) from 0.3.1 to 0.3.2. - [Release notes](https://github.com/charmbracelet/x/releases) - [Commits](https://github.com/charmbracelet/x/compare/ansi/v0.3.1...ansi/v0.3.2) --- updated-dependencies: - dependency-name: github.com/charmbracelet/x/ansi dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6aec383..1b53f26 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/charmbracelet/bubbletea v1.1.1 github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss v0.13.0 - github.com/charmbracelet/x/ansi v0.3.1 + github.com/charmbracelet/x/ansi v0.3.2 github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b github.com/dustin/go-humanize v1.0.1 github.com/lucasb-eyer/go-colorful v1.2.0 diff --git a/go.sum b/go.sum index cf3b383..fafd9e2 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= -github.com/charmbracelet/x/ansi v0.3.1 h1:CRO6lc/6HCx2/D6S/GZ87jDvRvk6GtPyFP+IljkNtqI= -github.com/charmbracelet/x/ansi v0.3.1/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/ansi v0.3.2 h1:wsEwgAN+C9U06l9dCVMX0/L3x7ptvY1qmjMwyfE6USY= +github.com/charmbracelet/x/ansi v0.3.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q= github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= From 4382fdf1c6cfe18d34615c1e8b94b068022a461a Mon Sep 17 00:00:00 2001 From: David Luevano Alvarado Date: Wed, 17 Jul 2024 04:29:41 -0600 Subject: [PATCH 08/26] feat(textinput): expose matched suggestions and index --- textinput/textinput.go | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/textinput/textinput.go b/textinput/textinput.go index 93bc150..cf944b8 100644 --- a/textinput/textinput.go +++ b/textinput/textinput.go @@ -813,16 +813,29 @@ func (m Model) completionView(offset int) string { return "" } -// AvailableSuggestions returns the list of available suggestions. -func (m *Model) AvailableSuggestions() []string { - suggestions := make([]string, len(m.suggestions)) - for i, s := range m.suggestions { +func (m *Model) getSuggestions(sugs [][]rune) []string { + suggestions := make([]string, len(sugs)) + for i, s := range sugs { suggestions[i] = string(s) } - return suggestions } +// AvailableSuggestions returns the list of available suggestions. +func (m *Model) AvailableSuggestions() []string { + return m.getSuggestions(m.suggestions) +} + +// MatchedSuggestions returns the list of matched suggestions. +func (m *Model) MatchedSuggestions() []string { + return m.getSuggestions(m.matchedSuggestions) +} + +// CurrentSuggestion returns the currently selected suggestion index. +func (m *Model) CurrentSuggestionIndex() int { + return m.currentSuggestionIndex +} + // CurrentSuggestion returns the currently selected suggestion. func (m *Model) CurrentSuggestion() string { if m.currentSuggestionIndex >= len(m.matchedSuggestions) { From 9a262e9b0fc34b27b4f7cf7e60e2c48a7c310696 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Mon, 7 Oct 2024 15:26:12 -0300 Subject: [PATCH 09/26] fix: use atomic for ids (#634) closes #622 Signed-off-by: Carlos Alexandro Becker Co-authored-by: Ville Valkonen --- filepicker/filepicker.go | 13 +++---------- progress/progress.go | 13 +++---------- spinner/spinner.go | 13 +++---------- stopwatch/stopwatch.go | 12 +++--------- timer/timer.go | 12 +++--------- 5 files changed, 15 insertions(+), 48 deletions(-) diff --git a/filepicker/filepicker.go b/filepicker/filepicker.go index 2288a5d..57fe02d 100644 --- a/filepicker/filepicker.go +++ b/filepicker/filepicker.go @@ -7,7 +7,7 @@ import ( "sort" "strconv" "strings" - "sync" + "sync/atomic" "github.com/charmbracelet/bubbles/key" tea "github.com/charmbracelet/bubbletea" @@ -15,17 +15,10 @@ import ( "github.com/dustin/go-humanize" ) -var ( - lastID int - idMtx sync.Mutex -) +var lastID int64 -// Return the next ID we should use on the Model. func nextID() int { - idMtx.Lock() - defer idMtx.Unlock() - lastID++ - return lastID + return int(atomic.AddInt64(&lastID, 1)) } // New returns a new filepicker model with default styling and key bindings. diff --git a/progress/progress.go b/progress/progress.go index defa981..cf3dbb4 100644 --- a/progress/progress.go +++ b/progress/progress.go @@ -4,7 +4,7 @@ import ( "fmt" "math" "strings" - "sync" + "sync/atomic" "time" tea "github.com/charmbracelet/bubbletea" @@ -17,17 +17,10 @@ import ( // Internal ID management. Used during animating to assure that frame messages // can only be received by progress components that sent them. -var ( - lastID int - idMtx sync.Mutex -) +var lastID int64 -// Return the next ID we should use on the model. func nextID() int { - idMtx.Lock() - defer idMtx.Unlock() - lastID++ - return lastID + return int(atomic.AddInt64(&lastID, 1)) } const ( diff --git a/spinner/spinner.go b/spinner/spinner.go index bb53597..7138af1 100644 --- a/spinner/spinner.go +++ b/spinner/spinner.go @@ -1,7 +1,7 @@ package spinner import ( - "sync" + "sync/atomic" "time" tea "github.com/charmbracelet/bubbletea" @@ -10,17 +10,10 @@ import ( // Internal ID management. Used during animating to ensure that frame messages // are received only by spinner components that sent them. -var ( - lastID int - idMtx sync.Mutex -) +var lastID int64 -// Return the next ID we should use on the Model. func nextID() int { - idMtx.Lock() - defer idMtx.Unlock() - lastID++ - return lastID + return int(atomic.AddInt64(&lastID, 1)) } // Spinner is a set of frames used in animating the spinner. diff --git a/stopwatch/stopwatch.go b/stopwatch/stopwatch.go index 6b298f7..bf4e39c 100644 --- a/stopwatch/stopwatch.go +++ b/stopwatch/stopwatch.go @@ -2,22 +2,16 @@ package stopwatch import ( - "sync" + "sync/atomic" "time" tea "github.com/charmbracelet/bubbletea" ) -var ( - lastID int - idMtx sync.Mutex -) +var lastID int64 func nextID() int { - idMtx.Lock() - defer idMtx.Unlock() - lastID++ - return lastID + return int(atomic.AddInt64(&lastID, 1)) } // TickMsg is a message that is sent on every timer tick. diff --git a/timer/timer.go b/timer/timer.go index eb085e0..076ee6f 100644 --- a/timer/timer.go +++ b/timer/timer.go @@ -2,22 +2,16 @@ package timer import ( - "sync" + "sync/atomic" "time" tea "github.com/charmbracelet/bubbletea" ) -var ( - lastID int - idMtx sync.Mutex -) +var lastID int64 func nextID() int { - idMtx.Lock() - defer idMtx.Unlock() - lastID++ - return lastID + return int(atomic.AddInt64(&lastID, 1)) } // Authors note with regard to start and stop commands: From cf3f46ab316fc263a88a0dfd368011f8868101f5 Mon Sep 17 00:00:00 2001 From: Aashutosh Date: Tue, 8 Oct 2024 00:11:58 +0545 Subject: [PATCH 10/26] docs(list): fix grammar in doc comment and README (#627) --- list/README.md | 2 +- list/defaultitem.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/list/README.md b/list/README.md index 60e802c..ad073ed 100644 --- a/list/README.md +++ b/list/README.md @@ -17,7 +17,7 @@ type Item interface { ``` ```go -// DefaultItem describes an items designed to work with DefaultDelegate. +// DefaultItem describes an item designed to work with DefaultDelegate. type DefaultItem interface { Item Title() string diff --git a/list/defaultitem.go b/list/defaultitem.go index 3f07cef..763dad1 100644 --- a/list/defaultitem.go +++ b/list/defaultitem.go @@ -61,7 +61,7 @@ func NewDefaultItemStyles() (s DefaultItemStyles) { return s } -// DefaultItem describes an items designed to work with DefaultDelegate. +// DefaultItem describes an item designed to work with DefaultDelegate. type DefaultItem interface { Item Title() string From 076b578512a8d2226f6d7c226533eeebab071bbb Mon Sep 17 00:00:00 2001 From: cui fliter Date: Tue, 8 Oct 2024 02:29:06 +0800 Subject: [PATCH 11/26] chore: Remove duplicate and redundant code (#626) Signed-off-by: cuishuang --- table/table.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/table/table.go b/table/table.go index 6103c83..73687b9 100644 --- a/table/table.go +++ b/table/table.go @@ -219,8 +219,6 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { m.MoveUp(m.viewport.Height / 2) case key.Matches(msg, m.KeyMap.HalfPageDown): m.MoveDown(m.viewport.Height / 2) - case key.Matches(msg, m.KeyMap.LineDown): - m.MoveDown(1) case key.Matches(msg, m.KeyMap.GotoTop): m.GotoTop() case key.Matches(msg, m.KeyMap.GotoBottom): From 171a9d61a0ce4fff88db8e16d03c3bac3f35f264 Mon Sep 17 00:00:00 2001 From: nobe4 Date: Thu, 10 Oct 2024 01:59:04 +0200 Subject: [PATCH 12/26] feat(list): implement GlobalIndex helper (#574) * feat(list): implement GlobalIndex helper This commit introduces a new `filteredItem` field called `index` which stores the index of the filtered item in the unfiltered list. This allows to get at runtime the unfiltered list index for the selected (and possibly filtered) item. This is the only solution I found to use `SetItem` with a filtered list. The name `GlobalIndex` might not be ideal, I'm happy to change it to something else. (`UnfilteredIndex`?) Fixes: #550 * docs(list): improve Index() documentation --- list/list.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/list/list.go b/list/list.go index 00d27a0..9ee1643 100644 --- a/list/list.go +++ b/list/list.go @@ -53,6 +53,7 @@ type ItemDelegate interface { } type filteredItem struct { + index int // index in the unfiltered list item Item // item matched matches []int // rune indices of matched items } @@ -484,12 +485,26 @@ func (m Model) MatchesForItem(index int) []int { return m.filteredItems[index].matches } -// Index returns the index of the currently selected item as it appears in the -// entire slice of items. +// Index returns the index of the currently selected item as it is stored in the +// filtered list of items. +// Using this value with SetItem() might be incorrect, consider using +// GlobalIndex() instead. func (m Model) Index() int { return m.Paginator.Page*m.Paginator.PerPage + m.cursor } +// GlobalIndex returns the index of the currently selected item as it is stored +// in the unfiltered list of items. This value can be used with SetItem(). +func (m Model) GlobalIndex() int { + index := m.Index() + + if m.filteredItems == nil || index >= len(m.filteredItems) { + return index + } + + return m.filteredItems[index].index +} + // Cursor returns the index of the cursor on the current page. func (m Model) Cursor() int { return m.cursor @@ -1256,6 +1271,7 @@ func filterItems(m Model) tea.Cmd { filterMatches := []filteredItem{} for _, r := range m.Filter(m.FilterInput.Value(), targets) { filterMatches = append(filterMatches, filteredItem{ + index: r.Index, item: items[r.Index], matches: r.MatchedIndexes, }) From 81d444a207009d0621988c9e08e827aa803ee04e Mon Sep 17 00:00:00 2001 From: David Luevano Alvarado Date: Sun, 14 Jul 2024 07:15:11 -0600 Subject: [PATCH 13/26] fix(help): wrong full help sep rendering --- help/help.go | 60 +++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/help/help.go b/help/help.go index f4e1c97..85afbee 100644 --- a/help/help.go +++ b/help/help.go @@ -124,28 +124,23 @@ func (m Model) ShortHelpView(bindings []key.Binding) string { continue } + // Sep var sep string if totalWidth > 0 && i < len(bindings) { sep = separator } + // Item str := sep + m.Styles.ShortKey.Inline(true).Render(kb.Help().Key) + " " + m.Styles.ShortDesc.Inline(true).Render(kb.Help().Desc) - w := lipgloss.Width(str) - // If adding this help item would go over the available width, stop - // drawing. - if m.Width > 0 && totalWidth+w > m.Width { - // Although if there's room for an ellipsis, print that. - tail := " " + m.Styles.Ellipsis.Inline(true).Render(m.Ellipsis) - tailWidth := lipgloss.Width(tail) - - if totalWidth+tailWidth < m.Width { + // Tail + if tail, ok := m.shouldAddItem(totalWidth, w); !ok { + if tail != "" { b.WriteString(tail) } - break } @@ -170,8 +165,7 @@ func (m Model) FullHelpView(groups [][]key.Binding) string { out []string totalWidth int - sep = m.Styles.FullSeparator.Render(m.FullSeparator) - sepWidth = lipgloss.Width(sep) + separator = m.Styles.FullSeparator.Inline(true).Render(m.FullSeparator) ) // Iterate over groups to build columns @@ -179,12 +173,17 @@ func (m Model) FullHelpView(groups [][]key.Binding) string { if group == nil || !shouldRenderColumn(group) { continue } - var ( + sep string keys []string descriptions []string ) + // Sep + if totalWidth > 0 && i < len(groups) { + sep = separator + } + // Separate keys and descriptions into different slices for _, kb := range group { if !kb.Enabled() { @@ -194,33 +193,42 @@ func (m Model) FullHelpView(groups [][]key.Binding) string { descriptions = append(descriptions, kb.Help().Desc) } + // Column col := lipgloss.JoinHorizontal(lipgloss.Top, + sep, m.Styles.FullKey.Render(strings.Join(keys, "\n")), - m.Styles.FullKey.Render(" "), + " ", m.Styles.FullDesc.Render(strings.Join(descriptions, "\n")), ) + w := lipgloss.Width(col) - // Column - totalWidth += lipgloss.Width(col) - if m.Width > 0 && totalWidth > m.Width { + // Tail + if tail, ok := m.shouldAddItem(totalWidth, w); !ok { + if tail != "" { + out = append(out, tail) + } break } + totalWidth += w out = append(out, col) - - // Separator - if i < len(group)-1 { - totalWidth += sepWidth - if m.Width > 0 && totalWidth > m.Width { - break - } - out = append(out, sep) - } } return lipgloss.JoinHorizontal(lipgloss.Top, out...) } +func (m Model) shouldAddItem(totalWidth, width int) (tail string, ok bool) { + // If there's room for an ellipsis, print that. + if m.Width > 0 && totalWidth+width > m.Width { + tail = " " + m.Styles.Ellipsis.Inline(true).Render(m.Ellipsis) + + if totalWidth+lipgloss.Width(tail) < m.Width { + return tail, false + } + } + return "", true +} + func shouldRenderColumn(b []key.Binding) (ok bool) { for _, v := range b { if v.Enabled() { From 60796500b2e255dcb9d68b916a6fc5aa49cf5b47 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Thu, 10 Oct 2024 15:29:23 -0400 Subject: [PATCH 14/26] chore(help): add full help test to support #554 --- go.mod | 2 +- go.sum | 4 +- help/help_test.go | 38 +++++++++++++++++++ .../TestFullHelp/full_help_20_width.golden | 1 + .../TestFullHelp/full_help_30_width.golden | 2 + .../TestFullHelp/full_help_40_width.golden | 3 ++ 6 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 help/help_test.go create mode 100644 help/testdata/TestFullHelp/full_help_20_width.golden create mode 100644 help/testdata/TestFullHelp/full_help_30_width.golden create mode 100644 help/testdata/TestFullHelp/full_help_40_width.golden diff --git a/go.mod b/go.mod index 1b53f26..95d6817 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss v0.13.0 github.com/charmbracelet/x/ansi v0.3.2 - github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b + github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 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 diff --git a/go.sum b/go.sum index fafd9e2..bbb72b1 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= github.com/charmbracelet/x/ansi v0.3.2 h1:wsEwgAN+C9U06l9dCVMX0/L3x7ptvY1qmjMwyfE6USY= github.com/charmbracelet/x/ansi v0.3.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= -github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q= -github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= +github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= diff --git a/help/help_test.go b/help/help_test.go new file mode 100644 index 0000000..79601d7 --- /dev/null +++ b/help/help_test.go @@ -0,0 +1,38 @@ +package help + +import ( + "fmt" + "testing" + + "github.com/charmbracelet/x/exp/golden" + + "github.com/charmbracelet/bubbles/key" +) + +func TestFullHelp(t *testing.T) { + m := New() + m.FullSeparator = " | " + k := key.WithKeys("x") + kb := [][]key.Binding{ + { + key.NewBinding(k, key.WithHelp("enter", "continue")), + }, + { + key.NewBinding(k, key.WithHelp("esc", "back")), + key.NewBinding(k, key.WithHelp("?", "help")), + }, + { + key.NewBinding(k, key.WithHelp("H", "home")), + key.NewBinding(k, key.WithHelp("ctrl+c", "quit")), + key.NewBinding(k, key.WithHelp("ctrl+l", "log")), + }, + } + + for _, w := range []int{20, 30, 40} { + t.Run(fmt.Sprintf("full help %d width", w), func(t *testing.T) { + m.Width = w + s := m.FullHelpView(kb) + golden.RequireEqual(t, []byte(s)) + }) + } +} diff --git a/help/testdata/TestFullHelp/full_help_20_width.golden b/help/testdata/TestFullHelp/full_help_20_width.golden new file mode 100644 index 0000000..e8c569b --- /dev/null +++ b/help/testdata/TestFullHelp/full_help_20_width.golden @@ -0,0 +1 @@ +enter continue … \ No newline at end of file diff --git a/help/testdata/TestFullHelp/full_help_30_width.golden b/help/testdata/TestFullHelp/full_help_30_width.golden new file mode 100644 index 0000000..1183a10 --- /dev/null +++ b/help/testdata/TestFullHelp/full_help_30_width.golden @@ -0,0 +1,2 @@ +enter continue | esc back … + ? help \ No newline at end of file diff --git a/help/testdata/TestFullHelp/full_help_40_width.golden b/help/testdata/TestFullHelp/full_help_40_width.golden new file mode 100644 index 0000000..e0227d0 --- /dev/null +++ b/help/testdata/TestFullHelp/full_help_40_width.golden @@ -0,0 +1,3 @@ +enter continue | esc back | H home + ? help ctrl+c quit + ctrl+l log \ No newline at end of file From 178590b4469b2386726cff8da7c479615a746a94 Mon Sep 17 00:00:00 2001 From: bashbunni <15822994+bashbunni@users.noreply.github.com> Date: Wed, 16 Oct 2024 09:57:39 -0700 Subject: [PATCH 15/26] docs: update contributing guidelines (#640) --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index f6e4d21..66abbd7 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,12 @@ following requirements: Thank you! +## Contributing + +See [contributing][contribute]. + +[contribute]: https://github.com/charmbracelet/bubbles/contribute + ## Feedback We’d love to hear your thoughts on this project. Feel free to drop us a note! From a9b780a96c9796826dcad68ea14f5050d613b1cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:28:20 +0000 Subject: [PATCH 16/26] feat(deps): bump github.com/charmbracelet/lipgloss from 0.13.0 to 0.13.1 Bumps [github.com/charmbracelet/lipgloss](https://github.com/charmbracelet/lipgloss) from 0.13.0 to 0.13.1. - [Release notes](https://github.com/charmbracelet/lipgloss/releases) - [Changelog](https://github.com/charmbracelet/lipgloss/blob/master/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/lipgloss/compare/v0.13.0...v0.13.1) --- updated-dependencies: - dependency-name: github.com/charmbracelet/lipgloss dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 95d6817..13ee214 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/atotto/clipboard v0.1.4 github.com/charmbracelet/bubbletea v1.1.1 github.com/charmbracelet/harmonica v0.2.0 - github.com/charmbracelet/lipgloss v0.13.0 + github.com/charmbracelet/lipgloss v0.13.1 github.com/charmbracelet/x/ansi v0.3.2 github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 github.com/dustin/go-humanize v1.0.1 diff --git a/go.sum b/go.sum index bbb72b1..8411f1e 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ github.com/charmbracelet/bubbletea v1.1.1 h1:KJ2/DnmpfqFtDNVTvYZ6zpPFL9iRCRr0qqK github.com/charmbracelet/bubbletea v1.1.1/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= -github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= -github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= +github.com/charmbracelet/lipgloss v0.13.1 h1:Oik/oqDTMVA01GetT4JdEC033dNzWoQHdWnHnQmXE2A= +github.com/charmbracelet/lipgloss v0.13.1/go.mod h1:zaYVJ2xKSKEnTEEbX6uAHabh2d975RJ+0yfkFpRBz5U= github.com/charmbracelet/x/ansi v0.3.2 h1:wsEwgAN+C9U06l9dCVMX0/L3x7ptvY1qmjMwyfE6USY= github.com/charmbracelet/x/ansi v0.3.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= From 358a6c58c88c1f9ecef350f1d5db775cdbdd7283 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Thu, 24 Oct 2024 12:09:01 -0400 Subject: [PATCH 17/26] chore(lint): fix and suppress all soft lint issues; update directives --- filepicker/filepicker.go | 2 +- list/defaultitem.go | 10 ++++++---- list/list.go | 12 ++++++------ list/style.go | 8 ++++---- paginator/paginator.go | 2 +- progress/progress.go | 2 +- spinner/spinner.go | 24 ++++++++++++------------ table/table.go | 6 +++--- textarea/textarea.go | 12 +++++++----- textinput/textinput.go | 4 ++-- viewport/viewport.go | 6 +++--- 11 files changed, 46 insertions(+), 42 deletions(-) diff --git a/filepicker/filepicker.go b/filepicker/filepicker.go index 57fe02d..113c6c9 100644 --- a/filepicker/filepicker.go +++ b/filepicker/filepicker.go @@ -379,7 +379,7 @@ func (m Model) View() string { disabled := !m.canSelect(name) && !f.IsDir() - if m.selected == i { + if m.selected == i { //nolint:nestif selected := "" if m.ShowPermissions { selected += " " + info.Mode().String() diff --git a/list/defaultitem.go b/list/defaultitem.go index 763dad1..4affe34 100644 --- a/list/defaultitem.go +++ b/list/defaultitem.go @@ -35,7 +35,7 @@ type DefaultItemStyles struct { func NewDefaultItemStyles() (s DefaultItemStyles) { s.NormalTitle = lipgloss.NewStyle(). Foreground(lipgloss.AdaptiveColor{Light: "#1a1a1a", Dark: "#dddddd"}). - Padding(0, 0, 0, 2) + Padding(0, 0, 0, 2) //nolint:mnd s.NormalDesc = s.NormalTitle. Foreground(lipgloss.AdaptiveColor{Light: "#A49FA5", Dark: "#777777"}) @@ -51,7 +51,7 @@ func NewDefaultItemStyles() (s DefaultItemStyles) { s.DimmedTitle = lipgloss.NewStyle(). Foreground(lipgloss.AdaptiveColor{Light: "#A49FA5", Dark: "#777777"}). - Padding(0, 0, 0, 2) + Padding(0, 0, 0, 2) //nolint:mnd s.DimmedDesc = s.DimmedTitle. Foreground(lipgloss.AdaptiveColor{Light: "#C2B8C2", Dark: "#4D4D4D"}) @@ -93,11 +93,13 @@ type DefaultDelegate struct { // NewDefaultDelegate creates a new delegate with default styles. func NewDefaultDelegate() DefaultDelegate { + const defaultHeight = 2 + const defaultSpacing = 1 return DefaultDelegate{ ShowDescription: true, Styles: NewDefaultItemStyles(), - height: 2, - spacing: 1, + height: defaultHeight, + spacing: defaultSpacing, } } diff --git a/list/list.go b/list/list.go index 9ee1643..6808142 100644 --- a/list/list.go +++ b/list/list.go @@ -273,7 +273,7 @@ func (m *Model) SetShowTitle(v bool) { // SetFilterText explicitly sets the filter text without relying on user input. // It also sets the filterState to a sane default of FilterApplied, but this -// can be changed with SetFilterState +// can be changed with SetFilterState. func (m *Model) SetFilterText(filter string) { m.filterState = Filtering m.FilterInput.SetValue(filter) @@ -289,7 +289,7 @@ func (m *Model) SetFilterText(filter string) { m.updateKeybindings() } -// Helper method for setting the filtering state manually +// Helper method for setting the filtering state manually. func (m *Model) SetFilterState(state FilterState) { m.Paginator.Page = 0 m.cursor = 0 @@ -722,7 +722,7 @@ func (m Model) itemsAsFilterItems() filteredItems { // Set keybindings according to the filter state. func (m *Model) updateKeybindings() { - switch m.filterState { + switch m.filterState { //nolint:exhaustive case Filtering: m.KeyMap.CursorUp.SetEnabled(false) m.KeyMap.CursorDown.SetEnabled(false) @@ -1153,7 +1153,7 @@ func (m Model) statusView() string { itemsDisplay := fmt.Sprintf("%d %s", visibleItems, itemName) - if m.filterState == Filtering { + if m.filterState == Filtering { //nolint:nestif // Filter results if visibleItems == 0 { status = m.Styles.StatusEmpty.Render("Nothing matched") @@ -1169,7 +1169,7 @@ func (m Model) statusView() string { if filtered { f := strings.TrimSpace(m.FilterInput.Value()) - f = ansi.Truncate(f, 10, "…") + f = ansi.Truncate(f, 10, "…") //nolint:mnd status += fmt.Sprintf("“%s” ", f) } @@ -1186,7 +1186,7 @@ func (m Model) statusView() string { } func (m Model) paginationView() string { - if m.Paginator.TotalPages < 2 { //nolint:gomnd + if m.Paginator.TotalPages < 2 { //nolint:mnd return "" } diff --git a/list/style.go b/list/style.go index e4451f8..e663c07 100644 --- a/list/style.go +++ b/list/style.go @@ -45,7 +45,7 @@ func DefaultStyles() (s Styles) { verySubduedColor := lipgloss.AdaptiveColor{Light: "#DDDADA", Dark: "#3C3C3C"} subduedColor := lipgloss.AdaptiveColor{Light: "#9B9B9B", Dark: "#5C5C5C"} - s.TitleBar = lipgloss.NewStyle().Padding(0, 0, 1, 2) + s.TitleBar = lipgloss.NewStyle().Padding(0, 0, 1, 2) //nolint:mnd s.Title = lipgloss.NewStyle(). Background(lipgloss.Color("62")). @@ -65,7 +65,7 @@ func DefaultStyles() (s Styles) { s.StatusBar = lipgloss.NewStyle(). Foreground(lipgloss.AdaptiveColor{Light: "#A49FA5", Dark: "#777777"}). - Padding(0, 0, 1, 2) + Padding(0, 0, 1, 2) //nolint:mnd s.StatusEmpty = lipgloss.NewStyle().Foreground(subduedColor) @@ -79,9 +79,9 @@ func DefaultStyles() (s Styles) { s.ArabicPagination = lipgloss.NewStyle().Foreground(subduedColor) - s.PaginationStyle = lipgloss.NewStyle().PaddingLeft(2) //nolint:gomnd + s.PaginationStyle = lipgloss.NewStyle().PaddingLeft(2) //nolint:mnd - s.HelpStyle = lipgloss.NewStyle().Padding(1, 0, 0, 2) + s.HelpStyle = lipgloss.NewStyle().Padding(1, 0, 0, 2) //nolint:mnd s.ActivePaginationDot = lipgloss.NewStyle(). Foreground(lipgloss.AdaptiveColor{Light: "#847A85", Dark: "#979797"}). diff --git a/paginator/paginator.go b/paginator/paginator.go index de05a85..961b4e5 100644 --- a/paginator/paginator.go +++ b/paginator/paginator.go @@ -189,7 +189,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { // View renders the pagination to a string. func (m Model) View() string { - switch m.Type { + switch m.Type { //nolint:exhaustive case Dots: return m.dotsView() default: diff --git a/progress/progress.go b/progress/progress.go index cf3dbb4..cfd18cb 100644 --- a/progress/progress.go +++ b/progress/progress.go @@ -335,7 +335,7 @@ func (m Model) percentageView(percent float64) string { return "" } percent = math.Max(0, math.Min(1, percent)) - percentage := fmt.Sprintf(m.PercentFormat, percent*100) //nolint:gomnd + percentage := fmt.Sprintf(m.PercentFormat, percent*100) //nolint:mnd percentage = m.PercentageStyle.Inline(true).Render(percentage) return percentage } diff --git a/spinner/spinner.go b/spinner/spinner.go index 7138af1..ac6e34a 100644 --- a/spinner/spinner.go +++ b/spinner/spinner.go @@ -26,39 +26,39 @@ type Spinner struct { var ( Line = Spinner{ Frames: []string{"|", "/", "-", "\\"}, - FPS: time.Second / 10, //nolint:gomnd + FPS: time.Second / 10, //nolint:mnd } Dot = Spinner{ Frames: []string{"⣾ ", "⣽ ", "⣻ ", "⢿ ", "⡿ ", "⣟ ", "⣯ ", "⣷ "}, - FPS: time.Second / 10, //nolint:gomnd + FPS: time.Second / 10, //nolint:mnd } MiniDot = Spinner{ Frames: []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}, - FPS: time.Second / 12, //nolint:gomnd + FPS: time.Second / 12, //nolint:mnd } Jump = Spinner{ Frames: []string{"⢄", "⢂", "⢁", "⡁", "⡈", "⡐", "⡠"}, - FPS: time.Second / 10, //nolint:gomnd + FPS: time.Second / 10, //nolint:mnd } Pulse = Spinner{ Frames: []string{"█", "▓", "▒", "░"}, - FPS: time.Second / 8, //nolint:gomnd + FPS: time.Second / 8, //nolint:mnd } Points = Spinner{ Frames: []string{"∙∙∙", "●∙∙", "∙●∙", "∙∙●"}, - FPS: time.Second / 7, //nolint:gomnd + FPS: time.Second / 7, //nolint:mnd } Globe = Spinner{ Frames: []string{"🌍", "🌎", "🌏"}, - FPS: time.Second / 4, //nolint:gomnd + FPS: time.Second / 4, //nolint:mnd } Moon = Spinner{ Frames: []string{"🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"}, - FPS: time.Second / 8, //nolint:gomnd + FPS: time.Second / 8, //nolint:mnd } Monkey = Spinner{ Frames: []string{"🙈", "🙉", "🙊"}, - FPS: time.Second / 3, //nolint:gomnd + FPS: time.Second / 3, //nolint:mnd } Meter = Spinner{ Frames: []string{ @@ -70,15 +70,15 @@ var ( "▰▱▱", "▱▱▱", }, - FPS: time.Second / 7, //nolint:gomnd + FPS: time.Second / 7, //nolint:mnd } Hamburger = Spinner{ Frames: []string{"☱", "☲", "☴", "☲"}, - FPS: time.Second / 3, //nolint:gomnd + FPS: time.Second / 3, //nolint:mnd } Ellipsis = Spinner{ Frames: []string{"", ".", "..", "..."}, - FPS: time.Second / 3, //nolint:gomnd + FPS: time.Second / 3, //nolint:mnd } ) diff --git a/table/table.go b/table/table.go index 73687b9..d68b626 100644 --- a/table/table.go +++ b/table/table.go @@ -133,7 +133,7 @@ type Option func(*Model) func New(opts ...Option) Model { m := Model{ cursor: 0, - viewport: viewport.New(0, 20), + viewport: viewport.New(0, 20), //nolint:mnd KeyMap: DefaultKeyMap(), Help: help.New(), @@ -216,9 +216,9 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { case key.Matches(msg, m.KeyMap.PageDown): m.MoveDown(m.viewport.Height) case key.Matches(msg, m.KeyMap.HalfPageUp): - m.MoveUp(m.viewport.Height / 2) + m.MoveUp(m.viewport.Height / 2) //nolint:mnd case key.Matches(msg, m.KeyMap.HalfPageDown): - m.MoveDown(m.viewport.Height / 2) + m.MoveDown(m.viewport.Height / 2) //nolint:mnd case key.Matches(msg, m.KeyMap.GotoTop): m.GotoTop() case key.Matches(msg, m.KeyMap.GotoBottom): diff --git a/textarea/textarea.go b/textarea/textarea.go index 153f39e..95c4351 100644 --- a/textarea/textarea.go +++ b/textarea/textarea.go @@ -492,7 +492,8 @@ func (m *Model) CursorDown() { // Move the cursor to the start of the next line so that we can get // the line information. We need to add 2 columns to account for the // trailing space wrapping. - m.col = min(li.StartColumn+li.Width+2, len(m.value[m.row])-1) + const trailingSpace = 2 + m.col = min(li.StartColumn+li.Width+trailingSpace, len(m.value[m.row])-1) } nli := m.LineInfo() @@ -526,7 +527,8 @@ func (m *Model) CursorUp() { // This can be done by moving the cursor to the start of the line and // then subtracting 2 to account for the trailing space we keep on // soft-wrapped lines. - m.col = li.StartColumn - 2 + const trailingSpace = 2 + m.col = li.StartColumn - trailingSpace } nli := m.LineInfo() @@ -1119,7 +1121,7 @@ func (m Model) View() string { displayLine++ var ln string - if m.ShowLineNumbers { + if m.ShowLineNumbers { //nolint:nestif if wl == 0 { if m.row == l { ln = style.Render(m.style.computedCursorLineNumber().Render(m.formatLineNumber(l + 1))) @@ -1198,7 +1200,7 @@ func (m Model) View() string { } // formatLineNumber formats the line number for display dynamically based on -// the maximum number of lines +// the maximum number of lines. func (m Model) formatLineNumber(x any) string { // XXX: ultimately we should use a max buffer height, which has yet to be // implemented. @@ -1407,7 +1409,7 @@ func wrap(runes []rune, width int) [][]rune { word = append(word, r) } - if spaces > 0 { + if spaces > 0 { //nolint:nestif if uniseg.StringWidth(string(lines[row]))+uniseg.StringWidth(string(word))+spaces > width { row++ lines = append(lines, []rune{}) diff --git a/textinput/textinput.go b/textinput/textinput.go index cf944b8..d1abf12 100644 --- a/textinput/textinput.go +++ b/textinput/textinput.go @@ -565,7 +565,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { // Let's remember where the position of the cursor currently is so that if // the cursor position changes, we can reset the blink. - oldPos := m.pos //nolint + oldPos := m.pos switch msg := msg.(type) { case tea.KeyMsg: @@ -658,7 +658,7 @@ func (m Model) View() string { pos := max(0, m.pos-m.offset) v := styleText(m.echoTransform(string(value[:pos]))) - if pos < len(value) { + if pos < len(value) { //nolint:nestif char := m.echoTransform(string(value[pos])) m.Cursor.SetChar(char) v += m.Cursor.View() // cursor and text under it diff --git a/viewport/viewport.go b/viewport/viewport.go index 1d2423a..f220d1e 100644 --- a/viewport/viewport.go +++ b/viewport/viewport.go @@ -168,7 +168,7 @@ func (m *Model) HalfViewDown() (lines []string) { return nil } - return m.LineDown(m.Height / 2) + return m.LineDown(m.Height / 2) //nolint:mnd } // HalfViewUp moves the view up by half the height of the viewport. @@ -177,7 +177,7 @@ func (m *Model) HalfViewUp() (lines []string) { return nil } - return m.LineUp(m.Height / 2) + return m.LineUp(m.Height / 2) //nolint:mnd } // LineDown moves the view down by the given number of lines. @@ -350,7 +350,7 @@ func (m Model) updateAsModel(msg tea.Msg) (Model, tea.Cmd) { if !m.MouseWheelEnabled || msg.Action != tea.MouseActionPress { break } - switch msg.Button { + switch msg.Button { //nolint:exhaustive case tea.MouseButtonWheelUp: lines := m.LineUp(m.MouseWheelDelta) if m.HighPerformanceRendering { From 6f3d765c591a6b957fd4e1b706eec7db8c38d6cc Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Thu, 24 Oct 2024 16:01:07 -0400 Subject: [PATCH 18/26] chore: bump bubbletea and ansi --- go.mod | 6 +++--- go.sum | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 13ee214..5dd4b8f 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,10 @@ go 1.18 require ( github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 - github.com/charmbracelet/bubbletea v1.1.1 + github.com/charmbracelet/bubbletea v1.1.2 github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss v0.13.1 - github.com/charmbracelet/x/ansi v0.3.2 + github.com/charmbracelet/x/ansi v0.4.0 github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 github.com/dustin/go-humanize v1.0.1 github.com/lucasb-eyer/go-colorful v1.2.0 @@ -29,6 +29,6 @@ require ( github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.24.0 // indirect + golang.org/x/sys v0.26.0 // indirect golang.org/x/text v0.3.8 // indirect ) diff --git a/go.sum b/go.sum index 8411f1e..0e2339c 100644 --- a/go.sum +++ b/go.sum @@ -8,12 +8,16 @@ github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWp github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/charmbracelet/bubbletea v1.1.1 h1:KJ2/DnmpfqFtDNVTvYZ6zpPFL9iRCRr0qqKOCvppbPY= github.com/charmbracelet/bubbletea v1.1.1/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4= +github.com/charmbracelet/bubbletea v1.1.2 h1:naQXF2laRxyLyil/i7fxdpiz1/k06IKquhm4vBfHsIc= +github.com/charmbracelet/bubbletea v1.1.2/go.mod h1:9HIU/hBV24qKjlehyj8z1r/tR9TYTQEag+cWZnuXo8E= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.13.1 h1:Oik/oqDTMVA01GetT4JdEC033dNzWoQHdWnHnQmXE2A= github.com/charmbracelet/lipgloss v0.13.1/go.mod h1:zaYVJ2xKSKEnTEEbX6uAHabh2d975RJ+0yfkFpRBz5U= github.com/charmbracelet/x/ansi v0.3.2 h1:wsEwgAN+C9U06l9dCVMX0/L3x7ptvY1qmjMwyfE6USY= github.com/charmbracelet/x/ansi v0.3.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/ansi v0.4.0 h1:NqwHA4B23VwsDn4H3VcNX1W1tOmgnvY1NDx5tOXdnOU= +github.com/charmbracelet/x/ansi v0.4.0/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= @@ -49,5 +53,7 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= From 8101a3462fd57e0fb9409da787e10aa50341f67a Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Mon, 28 Oct 2024 10:18:13 -0400 Subject: [PATCH 19/26] fix(ci): add lint and lint-sync workflows and update golangci.yml (#651) --- .github/workflows/lint-soft.yml | 28 --------------------- .github/workflows/lint-sync.yml | 14 +++++++++++ .github/workflows/lint.yml | 24 ++---------------- .golangci-soft.yml | 44 --------------------------------- .golangci.yml | 4 --- 5 files changed, 16 insertions(+), 98 deletions(-) delete mode 100644 .github/workflows/lint-soft.yml create mode 100644 .github/workflows/lint-sync.yml delete mode 100644 .golangci-soft.yml diff --git a/.github/workflows/lint-soft.yml b/.github/workflows/lint-soft.yml deleted file mode 100644 index 2eb2526..0000000 --- a/.github/workflows/lint-soft.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: lint-soft -on: - push: - pull_request: - -permissions: - contents: read - # Optional: allow read access to pull request. Use with `only-new-issues` option. - pull-requests: read - -jobs: - golangci: - name: lint-soft - runs-on: ubuntu-latest - steps: - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: ^1.18 - - - uses: actions/checkout@v4 - - name: golangci-lint - uses: golangci/golangci-lint-action@v6 - with: - # Optional: golangci-lint command line arguments. - args: --config .golangci-soft.yml --issues-exit-code=0 - # Optional: show only new issues if it's a pull request. The default value is `false`. - only-new-issues: true diff --git a/.github/workflows/lint-sync.yml b/.github/workflows/lint-sync.yml new file mode 100644 index 0000000..ecf8580 --- /dev/null +++ b/.github/workflows/lint-sync.yml @@ -0,0 +1,14 @@ +name: lint-sync +on: + schedule: + # every Sunday at midnight + - cron: "0 0 * * 0" + workflow_dispatch: # allows manual triggering + +permissions: + contents: write + pull-requests: write + +jobs: + lint: + uses: charmbracelet/meta/.github/workflows/lint-sync.yml@main diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 86612f0..a1d6d0e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -3,26 +3,6 @@ on: push: pull_request: -permissions: - contents: read - # Optional: allow read access to pull request. Use with `only-new-issues` option. - pull-requests: read - jobs: - golangci: - name: lint - runs-on: ubuntu-latest - steps: - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: ^1.18 - - - uses: actions/checkout@v4 - - name: golangci-lint - uses: golangci/golangci-lint-action@v6 - with: - # Optional: golangci-lint command line arguments. - #args: - # Optional: show only new issues if it's a pull request. The default value is `false`. - only-new-issues: true + lint: + uses: charmbracelet/meta/.github/workflows/lint.yml@main diff --git a/.golangci-soft.yml b/.golangci-soft.yml deleted file mode 100644 index d11d36b..0000000 --- a/.golangci-soft.yml +++ /dev/null @@ -1,44 +0,0 @@ -run: - tests: false - -issues: - include: - - EXC0001 - - EXC0005 - - EXC0011 - - EXC0012 - - EXC0013 - - max-issues-per-linter: 0 - max-same-issues: 0 - -linters: - enable: - # - dupl - - exhaustive - # - exhaustivestruct - - goconst - - godot - - godox - - mnd - - gomoddirectives - - goprintffuncname - # - lll - - misspell - - nakedret - - nestif - - noctx - - nolintlint - - prealloc - - wrapcheck - - # disable default linters, they are already enabled in .golangci.yml - disable: - - errcheck - - gosimple - - govet - - ineffassign - - staticcheck - - typecheck - - unused - - predeclared diff --git a/.golangci.yml b/.golangci.yml index 4e2ea02..d6789e0 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -15,7 +15,6 @@ issues: linters: enable: - bodyclose - - copyloopvar - gofumpt - goimports - gosec @@ -27,6 +26,3 @@ linters: - unconvert - unparam - whitespace - # We're disabling predeclared because the linter is running a newer version - # of Go than then Go module. - # - predeclared From db3514caa70d35517e566e6b15beaa2c8f3fdb8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 15:07:07 -0300 Subject: [PATCH 20/26] feat(deps): bump github.com/charmbracelet/lipgloss from 0.13.1 to 1.0.0 (#655) Bumps [github.com/charmbracelet/lipgloss](https://github.com/charmbracelet/lipgloss) from 0.13.1 to 1.0.0. - [Release notes](https://github.com/charmbracelet/lipgloss/releases) - [Changelog](https://github.com/charmbracelet/lipgloss/blob/master/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/lipgloss/compare/v0.13.1...v1.0.0) --- updated-dependencies: - dependency-name: github.com/charmbracelet/lipgloss dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 14 ++++---------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 5dd4b8f..575d4f5 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ require ( github.com/atotto/clipboard v0.1.4 github.com/charmbracelet/bubbletea v1.1.2 github.com/charmbracelet/harmonica v0.2.0 - github.com/charmbracelet/lipgloss v0.13.1 - github.com/charmbracelet/x/ansi v0.4.0 + github.com/charmbracelet/lipgloss v1.0.0 + github.com/charmbracelet/x/ansi v0.4.2 github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 github.com/dustin/go-humanize v1.0.1 github.com/lucasb-eyer/go-colorful v1.2.0 diff --git a/go.sum b/go.sum index 0e2339c..bd41a6f 100644 --- a/go.sum +++ b/go.sum @@ -6,18 +6,14 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE 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 v1.1.1 h1:KJ2/DnmpfqFtDNVTvYZ6zpPFL9iRCRr0qqKOCvppbPY= -github.com/charmbracelet/bubbletea v1.1.1/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4= github.com/charmbracelet/bubbletea v1.1.2 h1:naQXF2laRxyLyil/i7fxdpiz1/k06IKquhm4vBfHsIc= github.com/charmbracelet/bubbletea v1.1.2/go.mod h1:9HIU/hBV24qKjlehyj8z1r/tR9TYTQEag+cWZnuXo8E= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= -github.com/charmbracelet/lipgloss v0.13.1 h1:Oik/oqDTMVA01GetT4JdEC033dNzWoQHdWnHnQmXE2A= -github.com/charmbracelet/lipgloss v0.13.1/go.mod h1:zaYVJ2xKSKEnTEEbX6uAHabh2d975RJ+0yfkFpRBz5U= -github.com/charmbracelet/x/ansi v0.3.2 h1:wsEwgAN+C9U06l9dCVMX0/L3x7ptvY1qmjMwyfE6USY= -github.com/charmbracelet/x/ansi v0.3.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= -github.com/charmbracelet/x/ansi v0.4.0 h1:NqwHA4B23VwsDn4H3VcNX1W1tOmgnvY1NDx5tOXdnOU= -github.com/charmbracelet/x/ansi v0.4.0/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg= +github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo= +github.com/charmbracelet/x/ansi v0.4.2 h1:0JM6Aj/g/KC154/gOP4vfxun0ff6itogDYk41kof+qk= +github.com/charmbracelet/x/ansi v0.4.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= @@ -51,8 +47,6 @@ golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= From 20a65e5655524e2e713ebe07791fb39c1f220c15 Mon Sep 17 00:00:00 2001 From: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com> Date: Sun, 3 Nov 2024 00:03:06 +0000 Subject: [PATCH 21/26] chore(ci): sync golangci-lint config --- .golangci-soft.yml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .golangci-soft.yml diff --git a/.golangci-soft.yml b/.golangci-soft.yml new file mode 100644 index 0000000..d325d4f --- /dev/null +++ b/.golangci-soft.yml @@ -0,0 +1,40 @@ +run: + tests: false + issues-exit-code: 0 + +issues: + include: + - EXC0001 + - EXC0005 + - EXC0011 + - EXC0012 + - EXC0013 + + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + - exhaustive + - goconst + - godot + - godox + - mnd + - gomoddirectives + - goprintffuncname + - misspell + - nakedret + - nestif + - noctx + - nolintlint + - prealloc + - wrapcheck + + # disable default linters, they are already enabled in .golangci.yml + disable: + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - unused From 730f5a29e29b13ed9d4f9f67acb1722425708524 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Tue, 5 Nov 2024 22:03:46 -0500 Subject: [PATCH 22/26] fix: debounce stopwatch and timer This keeps them from ticking too fast. Fixes #661. --- stopwatch/stopwatch.go | 21 ++++++++++++++++----- timer/timer.go | 12 +++++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/stopwatch/stopwatch.go b/stopwatch/stopwatch.go index bf4e39c..e5d5f63 100644 --- a/stopwatch/stopwatch.go +++ b/stopwatch/stopwatch.go @@ -23,7 +23,8 @@ type TickMsg struct { // Note, however, that a stopwatch will reject ticks from other // stopwatches, so it's safe to flow all TickMsgs through all stopwatches // and have them still behave appropriately. - ID int + ID int + tag int } // StartStopMsg is sent when the stopwatch should start or stop. @@ -41,6 +42,7 @@ type ResetMsg struct { type Model struct { d time.Duration id int + tag int running bool // How long to wait before every tick. Defaults to 1 second. @@ -75,7 +77,7 @@ func (m Model) Init() tea.Cmd { func (m Model) Start() tea.Cmd { return tea.Batch(func() tea.Msg { return StartStopMsg{ID: m.id, running: true} - }, tick(m.id, m.Interval)) + }, tick(m.id, m.tag, m.Interval)) } // Stop stops the stopwatch. @@ -122,8 +124,17 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { if !m.running || msg.ID != m.id { break } + + // If a tag is set, and it's not the one we expect, reject the message. + // This prevents the stopwatch from receiving too many messages and + // thus ticking too fast. + if msg.tag > 0 && msg.tag != m.tag { + return m, nil + } + m.d += m.Interval - return m, tick(m.id, m.Interval) + m.tag++ + return m, tick(m.id, m.tag, m.Interval) } return m, nil @@ -139,8 +150,8 @@ func (m Model) View() string { return m.d.String() } -func tick(id int, d time.Duration) tea.Cmd { +func tick(id int, tag int, d time.Duration) tea.Cmd { return tea.Tick(d, func(_ time.Time) tea.Msg { - return TickMsg{ID: id} + return TickMsg{ID: id, tag: tag} }) } diff --git a/timer/timer.go b/timer/timer.go index 076ee6f..d0b6da6 100644 --- a/timer/timer.go +++ b/timer/timer.go @@ -61,6 +61,8 @@ type TickMsg struct { // Timeout returns whether or not this tick is a timeout tick. You can // alternatively listen for TimeoutMsg. Timeout bool + + tag int } // TimeoutMsg is a message that is sent once when the timer times out. @@ -80,6 +82,7 @@ type Model struct { Interval time.Duration id int + tag int running bool } @@ -137,6 +140,13 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { break } + // If a tag is set, and it's not the one we expect, reject the message. + // This prevents the ticker from receiving too many messages and + // thus ticking too fast. + if msg.tag > 0 && msg.tag != m.tag { + return m, nil + } + m.Timeout -= m.Interval return m, tea.Batch(m.tick(), m.timedout()) } @@ -166,7 +176,7 @@ func (m *Model) Toggle() tea.Cmd { func (m Model) tick() tea.Cmd { return tea.Tick(m.Interval, func(_ time.Time) tea.Msg { - return TickMsg{ID: m.id, Timeout: m.Timedout()} + return TickMsg{ID: m.id, tag: m.tag, Timeout: m.Timedout()} }) } From f439d83043fc1aa8a0903429d9901c302b28e654 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Thu, 14 Nov 2024 12:19:28 -0500 Subject: [PATCH 23/26] fix(textarea): max height should not determine max lines Fixes #671. --- textarea/textarea.go | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/textarea/textarea.go b/textarea/textarea.go index 95c4351..a3943a4 100644 --- a/textarea/textarea.go +++ b/textarea/textarea.go @@ -27,6 +27,9 @@ const ( defaultCharLimit = 400 defaultMaxHeight = 99 defaultMaxWidth = 500 + + // XXX: in v2, make max lines dynamic and default max lines configurable. + maxLines = 10000 ) // Internal messages for clipboard operations. @@ -290,13 +293,13 @@ func New() Model { style: &blurredStyle, FocusedStyle: focusedStyle, BlurredStyle: blurredStyle, - cache: memoization.NewMemoCache[line, [][]rune](defaultMaxHeight), + cache: memoization.NewMemoCache[line, [][]rune](maxLines), EndOfBufferCharacter: ' ', ShowLineNumbers: true, Cursor: cur, KeyMap: DefaultKeyMap, - value: make([][]rune, minHeight, defaultMaxHeight), + value: make([][]rune, minHeight, maxLines), focus: false, col: 0, row: 0, @@ -360,9 +363,8 @@ func (m *Model) insertRunesFromUserInput(runes []rune) { // whatnot. runes = m.san().Sanitize(runes) - var availSpace int if m.CharLimit > 0 { - availSpace = m.CharLimit - m.Length() + availSpace := m.CharLimit - m.Length() // If the char limit's been reached, cancel. if availSpace <= 0 { return @@ -393,9 +395,9 @@ func (m *Model) insertRunesFromUserInput(runes []rune) { lines = append(lines, runes[lstart:]) } - // Obey the maximum height limit. - if m.MaxHeight > 0 && len(m.value)+len(lines)-1 > m.MaxHeight { - allowedHeight := max(0, m.MaxHeight-len(m.value)+1) + // Obey the maximum line limit. + if maxLines > 0 && len(m.value)+len(lines)-1 > maxLines { + allowedHeight := max(0, maxLines-len(m.value)+1) lines = lines[:allowedHeight] } @@ -590,11 +592,7 @@ func (m *Model) Blur() { // Reset sets the input to its default state with no input. func (m *Model) Reset() { - startCap := m.MaxHeight - if startCap <= 0 { - startCap = defaultMaxHeight - } - m.value = make([][]rune, minHeight, startCap) + m.value = make([][]rune, minHeight, maxLines) m.col = 0 m.row = 0 m.viewport.GotoTop() From 398e92c5ae72b738cd6336a48c85bc21039b8cf8 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Fri, 15 Nov 2024 08:27:24 -0500 Subject: [PATCH 24/26] fix: remove default character limit --- textarea/textarea.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/textarea/textarea.go b/textarea/textarea.go index a3943a4..8a2071f 100644 --- a/textarea/textarea.go +++ b/textarea/textarea.go @@ -24,7 +24,7 @@ const ( minHeight = 1 defaultHeight = 6 defaultWidth = 40 - defaultCharLimit = 400 + defaultCharLimit = 0 // no limit defaultMaxHeight = 99 defaultMaxWidth = 500 From e5296a2b0fd6b4b7db8cb54cc15b99b681b7d949 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Fri, 15 Nov 2024 19:00:41 -0300 Subject: [PATCH 25/26] ci: fix goreleaser config (#668) Signed-off-by: Carlos Alexandro Becker --- .gitignore | 1 + .goreleaser.yml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index e43b0f9..1a07445 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .DS_Store +dist/ diff --git a/.goreleaser.yml b/.goreleaser.yml index c61970e..3353d02 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,5 +1,5 @@ +# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json +version: 2 includes: - from_url: url: charmbracelet/meta/main/goreleaser-lib.yaml -# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json - From 8624776d4572078ae6ff098d454c719047f9eb83 Mon Sep 17 00:00:00 2001 From: Mikael Fangel <34864484+MikaelFangel@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:40:33 +0100 Subject: [PATCH 26/26] fix(textinput): slicing outside cap (#532) * textinput: fix slicing outside cap * textinput: add test that makes slicing outside cap occur * chore: tidy with gofmt --------- Co-authored-by: bashbunni --- textinput/textinput.go | 4 +++- textinput/textinput_test.go | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/textinput/textinput.go b/textinput/textinput.go index d1abf12..66e4518 100644 --- a/textinput/textinput.go +++ b/textinput/textinput.go @@ -700,10 +700,12 @@ func (m Model) View() string { func (m Model) placeholderView() string { var ( v string - p = []rune(m.Placeholder) style = m.PlaceholderStyle.Inline(true).Render ) + p := make([]rune, m.Width+1) + copy(p, []rune(m.Placeholder)) + m.Cursor.TextStyle = m.PlaceholderStyle m.Cursor.SetChar(string(p[:1])) v += m.Cursor.View() diff --git a/textinput/textinput_test.go b/textinput/textinput_test.go index 27a7640..95ef0c6 100644 --- a/textinput/textinput_test.go +++ b/textinput/textinput_test.go @@ -30,3 +30,10 @@ func Test_CurrentSuggestion(t *testing.T) { t.Fatalf("Error: expected first suggestion but was %s", suggestion) } } + +func Test_SlicingOutsideCap(t *testing.T) { + textinput := New() + textinput.Placeholder = "作業ディレクトリを指定してください" + textinput.Width = 32 + textinput.View() +}