From 5110925e8788a8ecfd206df0da8dbeed36cde0f0 Mon Sep 17 00:00:00 2001 From: Florian Rey Date: Fri, 7 Jun 2024 18:24:16 +0200 Subject: [PATCH 01/33] feat: Introduce paginator options --- paginator/paginator.go | 27 +++++++++++++++++++++++++-- paginator/paginator_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/paginator/paginator.go b/paginator/paginator.go index 82dc3ed3c..de05a85bc 100644 --- a/paginator/paginator.go +++ b/paginator/paginator.go @@ -130,9 +130,12 @@ func (m Model) OnFirstPage() bool { return m.Page == 0 } +// Option is used to set options in New. +type Option func(*Model) + // New creates a new model with defaults. -func New() Model { - return Model{ +func New(opts ...Option) Model { + m := Model{ Type: Arabic, Page: 0, PerPage: 1, @@ -142,6 +145,12 @@ func New() Model { InactiveDot: "○", ArabicFormat: "%d/%d", } + + for _, opt := range opts { + opt(&m) + } + + return m } // NewModel creates a new model with defaults. @@ -149,6 +158,20 @@ func New() Model { // Deprecated: use [New] instead. var NewModel = New +// WithTotalPages sets the total pages. +func WithTotalPages(totalPages int) Option { + return func(m *Model) { + m.TotalPages = totalPages + } +} + +// WithPerPage sets the total pages. +func WithPerPage(perPage int) Option { + return func(m *Model) { + m.PerPage = perPage + } +} + // Update is the Tea update function which binds keystrokes to pagination. func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { switch msg := msg.(type) { diff --git a/paginator/paginator_test.go b/paginator/paginator_test.go index 57f326c66..679e68249 100644 --- a/paginator/paginator_test.go +++ b/paginator/paginator_test.go @@ -6,6 +6,32 @@ import ( tea "github.com/charmbracelet/bubbletea" ) +func TestNew(t *testing.T) { + model := New() + + if model.PerPage != 1 { + t.Errorf("PerPage = %d, expected %d", model.PerPage, 1) + } + if model.TotalPages != 1 { + t.Errorf("TotalPages = %d, expected %d", model.TotalPages, 1) + } + + perPage := 42 + totalPages := 42 + + model = New( + WithPerPage(perPage), + WithTotalPages(totalPages), + ) + + if model.PerPage != perPage { + t.Errorf("PerPage = %d, expected %d", model.PerPage, perPage) + } + if model.TotalPages != totalPages { + t.Errorf("TotalPages = %d, expected %d", model.TotalPages, totalPages) + } +} + func TestSetTotalPages(t *testing.T) { tests := []struct { name string From 3eaf8da348203f12a72ce4f994334dc4cd8d91ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 09:40:18 -0300 Subject: [PATCH 02/33] feat(deps): bump github.com/charmbracelet/bubbletea from 0.27.0 to 1.0.0 (#604) Bumps [github.com/charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea) from 0.27.0 to 1.0.0. - [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/v0.27.0...v1.0.0) --- updated-dependencies: - dependency-name: github.com/charmbracelet/bubbletea 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 | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 57141d99d..c2442fc35 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,9 @@ go 1.18 require ( github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 - github.com/charmbracelet/bubbletea v0.27.0 + github.com/charmbracelet/bubbletea v1.0.0 github.com/charmbracelet/harmonica v0.2.0 - github.com/charmbracelet/lipgloss v0.12.1 + github.com/charmbracelet/lipgloss v0.13.0 github.com/charmbracelet/x/ansi v0.1.4 github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b github.com/dustin/go-humanize v1.0.1 diff --git a/go.sum b/go.sum index a6bd9e942..27621a12b 100644 --- a/go.sum +++ b/go.sum @@ -6,12 +6,12 @@ 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 v0.27.0 h1:Mznj+vvYuYagD9Pn2mY7fuelGvP0HAXtZYGgRBCbHvU= -github.com/charmbracelet/bubbletea v0.27.0/go.mod h1:5MdP9XH6MbQkgGhnlxUqCNmBXf9I74KRQ8HIidRxV1Y= +github.com/charmbracelet/bubbletea v1.0.0 h1:BlNvkVed3DADQlV+W79eioNUOrnMUY25EEVdFUoDoGA= +github.com/charmbracelet/bubbletea v1.0.0/go.mod h1:xc4gm5yv+7tbniEvQ0naiG9P3fzYhk16cTgDZQQW6YE= 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.12.1 h1:/gmzszl+pedQpjCOH+wFkZr/N90Snz40J/NR7A0zQcs= -github.com/charmbracelet/lipgloss v0.12.1/go.mod h1:V2CiwIuhx9S1S1ZlADfOj9HmxeMAORuz5izHb0zGbB8= +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.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM= github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q= From 72de4f47dce78fa0541c382e2980807b118b3520 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Mon, 2 Sep 2024 10:09:59 -0400 Subject: [PATCH 03/33] chore(lint): update mnd name, remove deprecated directives Linter output for this change: * The linter "deadcode" is deprecated (step 2) and deactivated. It should be removed from the list of disabled linters. https://golangci-lint.run/product/roadmap/#linter-deprecation-cycle * The linter "structcheck" is deprecated (step 2) and deactivated. It should be removed from the list of disabled linters. https://golangci-lint.run/product/roadmap/#linter-deprecation-cycle * The linter "varcheck" is deprecated (step 2) and deactivated. It should be removed from the list of disabled linters. https://golangci-lint.run/product/roadmap/#linter-deprecation-cycle * The linter 'gomnd' is deprecated (since v1.58.0) due to: The linter has been renamed. Replaced by mnd. --- .golangci-soft.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.golangci-soft.yml b/.golangci-soft.yml index 0170561d5..d11d36b7a 100644 --- a/.golangci-soft.yml +++ b/.golangci-soft.yml @@ -20,7 +20,7 @@ linters: - goconst - godot - godox - - gomnd + - mnd - gomoddirectives - goprintffuncname # - lll @@ -34,14 +34,11 @@ linters: # disable default linters, they are already enabled in .golangci.yml disable: - - deadcode - errcheck - gosimple - govet - ineffassign - staticcheck - - structcheck - typecheck - unused - - varcheck - predeclared From a163c6c59d524156380749d1d20c87e5daa1b8a0 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Mon, 2 Sep 2024 10:14:47 -0400 Subject: [PATCH 04/33] chore(lint): disable predeclared due to false positives --- .golangci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 43d348b65..92a977140 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -28,4 +28,6 @@ linters: - unconvert - unparam - whitespace - - predeclared + # We're isabling predeclared because the linter is running a newer version + # of Go than then Go module. + # - predeclared From 6fc27e99d3b0e0cf5db13111e518b47435c42f5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2024 14:07:41 -0300 Subject: [PATCH 05/33] feat(deps): bump github.com/charmbracelet/bubbletea from 1.0.0 to 1.1.0 (#607) Bumps [github.com/charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea) from 1.0.0 to 1.1.0. - [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.0.0...v1.1.0) --- updated-dependencies: - dependency-name: github.com/charmbracelet/bubbletea 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 | 9 +++------ go.sum | 19 ++++++------------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index c2442fc35..28157038a 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.0.0 + github.com/charmbracelet/bubbletea v1.1.0 github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss v0.13.0 - github.com/charmbracelet/x/ansi v0.1.4 + github.com/charmbracelet/x/ansi v0.2.3 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 @@ -21,16 +21,13 @@ require ( require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-udiff v0.2.0 // indirect - github.com/charmbracelet/x/input v0.1.0 // indirect - github.com/charmbracelet/x/term v0.1.1 // indirect - github.com/charmbracelet/x/windows v0.1.0 // indirect + github.com/charmbracelet/x/term v0.2.0 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.1 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect - github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.24.0 // indirect golang.org/x/text v0.3.8 // indirect diff --git a/go.sum b/go.sum index 27621a12b..9eb7dd65a 100644 --- a/go.sum +++ b/go.sum @@ -6,22 +6,18 @@ 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.0.0 h1:BlNvkVed3DADQlV+W79eioNUOrnMUY25EEVdFUoDoGA= -github.com/charmbracelet/bubbletea v1.0.0/go.mod h1:xc4gm5yv+7tbniEvQ0naiG9P3fzYhk16cTgDZQQW6YE= +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/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/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM= -github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +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/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/input v0.1.0 h1:TEsGSfZYQyOtp+STIjyBq6tpRaorH0qpwZUj8DavAhQ= -github.com/charmbracelet/x/input v0.1.0/go.mod h1:ZZwaBxPF7IG8gWWzPUVqHEtWhc1+HXJPNuerJGRGZ28= -github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI= -github.com/charmbracelet/x/term v0.1.1/go.mod h1:wB1fHt5ECsu3mXYusyzcngVWWlu1KKUmmLhfgr/Flxw= -github.com/charmbracelet/x/windows v0.1.0 h1:gTaxdvzDM5oMa/I2ZNF7wN78X/atWemG9Wph7Ika2k4= -github.com/charmbracelet/x/windows v0.1.0/go.mod h1:GLEO/l+lizvFDBPLIOk+49gdX49L9YWMB5t+DZd0jkQ= +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= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= @@ -47,9 +43,6 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA= github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= -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-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= 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= From d3bd075ed2b27a3b5d76bb79b5d1c928dcd780d0 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Thu, 5 Sep 2024 14:10:05 -0300 Subject: [PATCH 06/33] feat(cursor): focus/blur support (#581) Signed-off-by: Carlos Alexandro Becker --- cursor/cursor.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cursor/cursor.go b/cursor/cursor.go index a4f479385..1297422d4 100644 --- a/cursor/cursor.go +++ b/cursor/cursor.go @@ -101,6 +101,13 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { cmd := m.BlinkCmd() return m, cmd + case tea.FocusMsg: + return m, m.Focus() + + case tea.BlurMsg: + m.Blur() + return m, nil + case BlinkMsg: // We're choosy about whether to accept blinkMsgs so that our cursor // only exactly when it should. From d019ed3cc97e07dfe5e7b30ec15159033fbe6826 Mon Sep 17 00:00:00 2001 From: Tai Groot Date: Tue, 10 Sep 2024 10:22:03 -0700 Subject: [PATCH 07/33] feat(list): add SetFilterText and SetFilterState (#335) * Add SetFilterText and SetFilterState * make linter happy * make SetFilterState state not hardcoded * tests for SetFilterText and SetFilterState * fix small typo --------- Co-authored-by: k-x7 <97758178+k-x7@users.noreply.github.com> --- list/list.go | 37 ++++++++++++++++++++++++--- list/list_test.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 5 deletions(-) diff --git a/list/list.go b/list/list.go index 17e6e1559..00d27a05d 100644 --- a/list/list.go +++ b/list/list.go @@ -10,15 +10,16 @@ import ( "strings" "time" + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/x/ansi" + "github.com/sahilm/fuzzy" + "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/paginator" "github.com/charmbracelet/bubbles/spinner" "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - "github.com/charmbracelet/x/ansi" - "github.com/sahilm/fuzzy" ) // Item is an item that appears in the list. @@ -269,6 +270,34 @@ func (m *Model) SetShowTitle(v bool) { m.updatePagination() } +// 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 +func (m *Model) SetFilterText(filter string) { + m.filterState = Filtering + m.FilterInput.SetValue(filter) + cmd := filterItems(*m) + msg := cmd() + fmm, _ := msg.(FilterMatchesMsg) + m.filteredItems = filteredItems(fmm) + m.filterState = FilterApplied + m.Paginator.Page = 0 + m.cursor = 0 + m.FilterInput.CursorEnd() + m.updatePagination() + m.updateKeybindings() +} + +// Helper method for setting the filtering state manually +func (m *Model) SetFilterState(state FilterState) { + m.Paginator.Page = 0 + m.cursor = 0 + m.filterState = state + m.FilterInput.CursorEnd() + m.FilterInput.Focus() + m.updateKeybindings() +} + // ShowTitle returns whether or not the title bar is set to be rendered. func (m Model) ShowTitle() bool { return m.showTitle diff --git a/list/list_test.go b/list/list_test.go index 2c925aab4..2627e5b1a 100644 --- a/list/list_test.go +++ b/list/list_test.go @@ -3,6 +3,7 @@ package list import ( "fmt" "io" + "reflect" "strings" "testing" @@ -11,7 +12,7 @@ import ( type item string -func (i item) FilterValue() string { return "" } +func (i item) FilterValue() string { return string(i) } type itemDelegate struct{} @@ -72,3 +73,65 @@ func TestCustomStatusBarItemName(t *testing.T) { t.Fatalf("Error: expected view to contain %s", expected) } } + +func TestSetFilterText(t *testing.T) { + tc := []Item{item("foo"), item("bar"), item("baz")} + + list := New(tc, itemDelegate{}, 10, 10) + list.SetFilterText("ba") + + list.SetFilterState(Unfiltered) + expected := tc + // TODO: replace with slices.Equal() when project move to go1.18 or later + if !reflect.DeepEqual(list.VisibleItems(), expected) { + t.Fatalf("Error: expected view to contain only %s", expected) + } + + list.SetFilterState(Filtering) + expected = []Item{item("bar"), item("baz")} + if !reflect.DeepEqual(list.VisibleItems(), expected) { + t.Fatalf("Error: expected view to contain only %s", expected) + } + + list.SetFilterState(FilterApplied) + if !reflect.DeepEqual(list.VisibleItems(), expected) { + t.Fatalf("Error: expected view to contain only %s", expected) + } +} + +func TestSetFilterState(t *testing.T) { + tc := []Item{item("foo"), item("bar"), item("baz")} + + list := New(tc, itemDelegate{}, 10, 10) + list.SetFilterText("ba") + + list.SetFilterState(Unfiltered) + expected, notExpected := "up", "clear filter" + + lines := strings.Split(list.View(), "\n") + footer := lines[len(lines)-1] + + if !strings.Contains(footer, expected) || strings.Contains(footer, notExpected) { + t.Fatalf("Error: expected view to contain '%s' not '%s'", expected, notExpected) + } + + list.SetFilterState(Filtering) + expected, notExpected = "filter", "more" + + lines = strings.Split(list.View(), "\n") + footer = lines[len(lines)-1] + + if !strings.Contains(footer, expected) || strings.Contains(footer, notExpected) { + t.Fatalf("Error: expected view to contain '%s' not '%s'", expected, notExpected) + } + + list.SetFilterState(FilterApplied) + expected = "clear" + + lines = strings.Split(list.View(), "\n") + footer = lines[len(lines)-1] + + if !strings.Contains(footer, expected) { + t.Fatalf("Error: expected view to contain '%s'", expected) + } +} From 2caa9d4bdf051e9255b15ef8d7223c991b7a6b8a Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Wed, 11 Sep 2024 17:05:46 -0400 Subject: [PATCH 08/33] 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 e0a4cc33f..1d2423a6e 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 09/33] chore(lint): update deprecated directive --- .golangci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 92a977140..a096c2a3f 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 10/33] 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 28157038a..db9c9fb7a 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 9eb7dd65a..78b8b2f98 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 11/33] 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 db9c9fb7a..c5d16c8f1 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 78b8b2f98..493b47863 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 12/33] 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 a096c2a3f..4e2ea0268 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 9a1235a7b..2288a5d2a 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 13/33] 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 c5d16c8f1..6aec38333 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 493b47863..cf3b38390 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 14/33] 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 6aec38333..1b53f262d 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 cf3b38390..fafd9e282 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 15/33] 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 93bc150bc..cf944b89f 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 16/33] 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 2288a5d2a..57fe02d5f 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 defa98133..cf3dbb4af 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 bb53597fe..7138af1bc 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 6b298f791..bf4e39c85 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 eb085e00d..076ee6fff 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 17/33] 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 60e802c2d..ad073edf1 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 3f07cef6f..763dad1c8 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 18/33] 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 6103c8361..73687b97b 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 19/33] 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 00d27a05d..9ee1643d3 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 20/33] 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 f4e1c9713..85afbee13 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 21/33] 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 1b53f262d..95d681773 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 fafd9e282..bbb72b1ef 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 000000000..79601d789 --- /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 000000000..e8c569b13 --- /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 000000000..1183a10ec --- /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 000000000..e0227d09c --- /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 22/33] docs: update contributing guidelines (#640) --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index f6e4d21c2..66abbd785 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 23/33] 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 95d681773..13ee2147e 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 bbb72b1ef..8411f1efc 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 24/33] 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 57fe02d5f..113c6c963 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 763dad1c8..4affe342a 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 9ee1643d3..6808142b3 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 e4451f87b..e663c07b8 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 de05a85bc..961b4e560 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 cf3dbb4af..cfd18cb56 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 7138af1bc..ac6e34aba 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 73687b97b..d68b626ff 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 153f39ef3..95c435156 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 cf944b89f..d1abf1247 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 1d2423a6e..f220d1eb6 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 25/33] 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 13ee2147e..5dd4b8ffd 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 8411f1efc..0e2339c82 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 26/33] 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 2eb25262d..000000000 --- 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 000000000..ecf858024 --- /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 86612f09e..a1d6d0e51 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 d11d36b7a..000000000 --- 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 4e2ea0268..d6789e014 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 27/33] 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 5dd4b8ffd..575d4f5b3 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 0e2339c82..bd41a6f3e 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 28/33] 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 000000000..d325d4fcc --- /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 29/33] 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 bf4e39c85..e5d5f6333 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 076ee6fff..d0b6da615 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 30/33] 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 95c435156..a3943a4e4 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 31/33] 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 a3943a4e4..8a2071f3f 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 32/33] 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 e43b0f988..1a074454e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .DS_Store +dist/ diff --git a/.goreleaser.yml b/.goreleaser.yml index c61970e07..3353d0202 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 33/33] 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 d1abf1247..66e451859 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 27a7640a8..95ef0c616 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() +}