diff --git a/filepicker/filepicker.go b/filepicker/filepicker.go index 8402e168b..5becaeb34 100644 --- a/filepicker/filepicker.go +++ b/filepicker/filepicker.go @@ -106,24 +106,18 @@ type Styles struct { // DefaultStyles defines the default styling for the file picker. func DefaultStyles() Styles { - return DefaultStylesWithRenderer(lipgloss.DefaultRenderer()) -} - -// DefaultStylesWithRenderer defines the default styling for the file picker, -// with a given Lip Gloss renderer. -func DefaultStylesWithRenderer(r *lipgloss.Renderer) Styles { return Styles{ - DisabledCursor: r.NewStyle().Foreground(lipgloss.Color("247")), - Cursor: r.NewStyle().Foreground(lipgloss.Color("212")), - Symlink: r.NewStyle().Foreground(lipgloss.Color("36")), - Directory: r.NewStyle().Foreground(lipgloss.Color("99")), - File: r.NewStyle(), - DisabledFile: r.NewStyle().Foreground(lipgloss.Color("243")), - DisabledSelected: r.NewStyle().Foreground(lipgloss.Color("247")), - Permission: r.NewStyle().Foreground(lipgloss.Color("244")), - Selected: r.NewStyle().Foreground(lipgloss.Color("212")).Bold(true), - FileSize: r.NewStyle().Foreground(lipgloss.Color("240")).Width(fileSizeWidth).Align(lipgloss.Right), - EmptyDirectory: r.NewStyle().Foreground(lipgloss.Color("240")).PaddingLeft(paddingLeft).SetString("Bummer. No Files Found."), + DisabledCursor: lipgloss.NewStyle().Foreground(lipgloss.Color("247")), + Cursor: lipgloss.NewStyle().Foreground(lipgloss.Color("212")), + Symlink: lipgloss.NewStyle().Foreground(lipgloss.Color("36")), + Directory: lipgloss.NewStyle().Foreground(lipgloss.Color("99")), + File: lipgloss.NewStyle(), + DisabledFile: lipgloss.NewStyle().Foreground(lipgloss.Color("243")), + DisabledSelected: lipgloss.NewStyle().Foreground(lipgloss.Color("247")), + Permission: lipgloss.NewStyle().Foreground(lipgloss.Color("244")), + Selected: lipgloss.NewStyle().Foreground(lipgloss.Color("212")).Bold(true), + FileSize: lipgloss.NewStyle().Foreground(lipgloss.Color("240")).Width(fileSizeWidth).Align(lipgloss.Right), + EmptyDirectory: lipgloss.NewStyle().Foreground(lipgloss.Color("240")).PaddingLeft(paddingLeft).SetString("Bummer. No Files Found."), } } @@ -379,7 +373,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/go.mod b/go.mod index 92b583a75..e957b6e32 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,10 @@ go 1.18 require ( github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 - github.com/charmbracelet/bubbles v0.20.0 - github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20240919172237-265996c29bea + github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20241024164833-a31857d07198 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/lipgloss v0.13.2-0.20241023173701-23b08d1d3588 + 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 @@ -22,11 +21,15 @@ require ( require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-udiff v0.2.0 // indirect + github.com/charmbracelet/colorprofile v0.1.2 // indirect + github.com/charmbracelet/x/input v0.2.0 // indirect github.com/charmbracelet/x/term v0.2.0 // indirect github.com/charmbracelet/x/windows 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/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.25.0 // indirect + golang.org/x/sys v0.26.0 // indirect ) diff --git a/go.sum b/go.sum index d4cb7efaa..34acff053 100644 --- a/go.sum +++ b/go.sum @@ -6,25 +6,30 @@ 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/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE= -github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU= -github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20240919172237-265996c29bea h1:i32Z8pIQujNjR2BffDviAnai2L9oLMW7jMd7aCD8Jqg= -github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20240919172237-265996c29bea/go.mod h1:j0gn4ft5CE7NDYNZjAA3hBM8t2OPjI8urxuAD0oR4w8= +github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20241024164833-a31857d07198 h1:3IZlVJQnGjyr8i3VFeto8Me3nJ3FwIfMAFhA81z/z9w= +github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20241024164833-a31857d07198/go.mod h1:dXpO25BjSsBATkCzGTxvzdhRqtgdUT4wdpFtoNZKE1A= +github.com/charmbracelet/colorprofile v0.1.2 h1:nuB1bd/yAExT4fkcZvpqtQ2N5/8cJHSRIKb6CzT7lAM= +github.com/charmbracelet/colorprofile v0.1.2/go.mod h1:1htIKZYeI4TQs+OykPvpuBTUbUJxBYeSYBDIZuejMj0= 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.3.2 h1:wsEwgAN+C9U06l9dCVMX0/L3x7ptvY1qmjMwyfE6USY= -github.com/charmbracelet/x/ansi v0.3.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/lipgloss v0.13.2-0.20241023173701-23b08d1d3588 h1:P0eMGSpqhHhVEN9HRD9Dl0ZaXIJWHINkW4DjPC/0EIQ= +github.com/charmbracelet/lipgloss v0.13.2-0.20241023173701-23b08d1d3588/go.mod h1:S+zi6HCChYq08TKQZpf3KEi7D/RO62JjxwNXbv6KVxA= +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/input v0.2.0 h1:1Sv+y/flcqUfUH2PXNIDKDIdT2G8smOnGOgawqhwy8A= +github.com/charmbracelet/x/input v0.2.0/go.mod h1:KUSFIS6uQymtnr5lHVSOK9j8RvwTD4YHnWnzJUYnd/M= 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/charmbracelet/x/windows v0.2.0 h1:ilXA1GJjTNkgOm94CLPeSz7rar54jtFatdmoiONPuEw= github.com/charmbracelet/x/windows v0.2.0/go.mod h1:ZibNFR49ZFqCXgP76sYanisxRyC+EYrBE7TTknD8s1s= 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= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= @@ -42,9 +47,10 @@ 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/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= 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.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.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= diff --git a/help/help.go b/help/help.go index cd75ba95f..6dade0c33 100644 --- a/help/help.go +++ b/help/help.go @@ -41,6 +41,34 @@ type Styles struct { FullSeparator lipgloss.Style } +func newStyles(isDark bool) Styles { + lightDark := lipgloss.LightDark(isDark) + + keyStyle := lipgloss.NewStyle().Foreground(lightDark("#909090", "#626262")) + descStyle := lipgloss.NewStyle().Foreground(lightDark("#B2B2B2", "#4A4A4A")) + sepStyle := lipgloss.NewStyle().Foreground(lightDark("#DADADA", "#3C3C3C")) + + return Styles{ + ShortKey: keyStyle, + ShortDesc: descStyle, + ShortSeparator: sepStyle, + Ellipsis: sepStyle, + FullKey: keyStyle, + FullDesc: descStyle, + FullSeparator: sepStyle, + } +} + +// DefaultDarkStyles returns a set of default styles for dark backgrounds. +func DefaultDarkStyles() Styles { + return newStyles(true) +} + +// DefaultLightStyles returns a set of default styles for light backgrounds. +func DefaultLightStyles() Styles { + return newStyles(false) +} + // Model contains the state of the help view. type Model struct { Width int @@ -58,34 +86,11 @@ type Model struct { // New creates a new help view with some useful defaults. func New() Model { - keyStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ - Light: "#909090", - Dark: "#626262", - }) - - descStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ - Light: "#B2B2B2", - Dark: "#4A4A4A", - }) - - sepStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ - Light: "#DDDADA", - Dark: "#3C3C3C", - }) - return Model{ ShortSeparator: " • ", FullSeparator: " ", Ellipsis: "…", - Styles: Styles{ - ShortKey: keyStyle, - ShortDesc: descStyle, - ShortSeparator: sepStyle, - Ellipsis: sepStyle, - FullKey: keyStyle, - FullDesc: descStyle, - FullSeparator: sepStyle, - }, + Styles: DefaultDarkStyles(), } } diff --git a/help/help_test.go b/help/help_test.go index 79601d789..9214e0fe4 100644 --- a/help/help_test.go +++ b/help/help_test.go @@ -4,9 +4,9 @@ import ( "fmt" "testing" + "github.com/charmbracelet/bubbles/v2/key" + "github.com/charmbracelet/x/ansi" "github.com/charmbracelet/x/exp/golden" - - "github.com/charmbracelet/bubbles/key" ) func TestFullHelp(t *testing.T) { @@ -32,6 +32,7 @@ func TestFullHelp(t *testing.T) { t.Run(fmt.Sprintf("full help %d width", w), func(t *testing.T) { m.Width = w s := m.FullHelpView(kb) + s = ansi.Strip(s) golden.RequireEqual(t, []byte(s)) }) } diff --git a/textarea/memoization/memoization.go b/internal/memoization/memoization.go similarity index 97% rename from textarea/memoization/memoization.go rename to internal/memoization/memoization.go index ccb80a9f1..46c347a67 100644 --- a/textarea/memoization/memoization.go +++ b/internal/memoization/memoization.go @@ -1,3 +1,5 @@ +// Package memoization implement a simple memoization cache. It's designed to +// improve performance in textarea. package memoization import ( diff --git a/textarea/memoization/memoization_test.go b/internal/memoization/memoization_test.go similarity index 100% rename from textarea/memoization/memoization_test.go rename to internal/memoization/memoization_test.go diff --git a/runeutil/runeutil.go b/internal/runeutil/runeutil.go similarity index 95% rename from runeutil/runeutil.go rename to internal/runeutil/runeutil.go index 82ea90a2e..6856cc87f 100644 --- a/runeutil/runeutil.go +++ b/internal/runeutil/runeutil.go @@ -1,5 +1,5 @@ -// Package runeutil provides a utility function for use in Bubbles -// that can process Key messages containing runes. +// Package runeutil provides utility functions for tidying up incoming runes +// from Key messages. package runeutil import ( diff --git a/runeutil/runeutil_test.go b/internal/runeutil/runeutil_test.go similarity index 100% rename from runeutil/runeutil_test.go rename to internal/runeutil/runeutil_test.go diff --git a/list/defaultitem.go b/list/defaultitem.go index 31b55bb7e..9c8ab260a 100644 --- a/list/defaultitem.go +++ b/list/defaultitem.go @@ -32,29 +32,31 @@ type DefaultItemStyles struct { // NewDefaultItemStyles returns style definitions for a default item. See // DefaultItemView for when these come into play. -func NewDefaultItemStyles() (s DefaultItemStyles) { +func NewDefaultItemStyles(isDark bool) (s DefaultItemStyles) { + lightDark := lipgloss.LightDark(isDark) + s.NormalTitle = lipgloss.NewStyle(). - Foreground(lipgloss.AdaptiveColor{Light: "#1a1a1a", Dark: "#dddddd"}). - Padding(0, 0, 0, 2) + Foreground(lightDark("#1a1a1a", "#dddddd")). + Padding(0, 0, 0, 2) //nolint:mnd s.NormalDesc = s.NormalTitle. - Foreground(lipgloss.AdaptiveColor{Light: "#A49FA5", Dark: "#777777"}) + Foreground(lightDark("#A49FA5", "#777777")) s.SelectedTitle = lipgloss.NewStyle(). Border(lipgloss.NormalBorder(), false, false, false, true). - BorderForeground(lipgloss.AdaptiveColor{Light: "#F793FF", Dark: "#AD58B4"}). - Foreground(lipgloss.AdaptiveColor{Light: "#EE6FF8", Dark: "#EE6FF8"}). + BorderForeground(lightDark("#F793FF", "#AD58B4")). + Foreground(lightDark("#EE6FF8", "#EE6FF8")). Padding(0, 0, 0, 1) s.SelectedDesc = s.SelectedTitle. - Foreground(lipgloss.AdaptiveColor{Light: "#F793FF", Dark: "#AD58B4"}) + Foreground(lightDark("#F793FF", "#AD58B4")) s.DimmedTitle = lipgloss.NewStyle(). - Foreground(lipgloss.AdaptiveColor{Light: "#A49FA5", Dark: "#777777"}). - Padding(0, 0, 0, 2) + Foreground(lightDark("#A49FA5", "#777777")). + Padding(0, 0, 0, 2) //nolint:mnd s.DimmedDesc = s.DimmedTitle. - Foreground(lipgloss.AdaptiveColor{Light: "#C2B8C2", Dark: "#4D4D4D"}) + Foreground(lightDark("#C2B8C2", "#4D4D4D")) s.FilterMatch = lipgloss.NewStyle().Underline(true) @@ -93,11 +95,15 @@ 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, + // XXX: Let the user choose between light and dark colors. We've + // temporarily hardcoded the dark colors here. + Styles: NewDefaultItemStyles(true), + height: defaultHeight, + spacing: defaultSpacing, } } diff --git a/list/list.go b/list/list.go index 171729c7d..980c74a48 100644 --- a/list/list.go +++ b/list/list.go @@ -197,7 +197,9 @@ type Model struct { // New returns a new model with sensible defaults. func New(items []Item, delegate ItemDelegate, width, height int) Model { - styles := DefaultStyles() + // XXX: Let the user choose between light and dark colors. We've + // temporarily hardcoded the dark colors here. + styles := DefaultStyles(true) sp := spinner.New() sp.Spinner = spinner.Line @@ -268,7 +270,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) @@ -284,7 +286,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 @@ -717,7 +719,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) @@ -1148,7 +1150,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") @@ -1164,7 +1166,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) } @@ -1181,7 +1183,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..1892022e3 100644 --- a/list/style.go +++ b/list/style.go @@ -41,11 +41,13 @@ type Styles struct { // DefaultStyles returns a set of default style definitions for this list // component. -func DefaultStyles() (s Styles) { - verySubduedColor := lipgloss.AdaptiveColor{Light: "#DDDADA", Dark: "#3C3C3C"} - subduedColor := lipgloss.AdaptiveColor{Light: "#9B9B9B", Dark: "#5C5C5C"} +func DefaultStyles(isDark bool) (s Styles) { + lightDark := lipgloss.LightDark(isDark) - s.TitleBar = lipgloss.NewStyle().Padding(0, 0, 1, 2) + verySubduedColor := lightDark("#DDDADA", "#3C3C3C") + subduedColor := lightDark("#9B9B9B", "#5C5C5C") + + s.TitleBar = lipgloss.NewStyle().Padding(0, 0, 1, 2) //nolint:mnd s.Title = lipgloss.NewStyle(). Background(lipgloss.Color("62")). @@ -53,38 +55,38 @@ func DefaultStyles() (s Styles) { Padding(0, 1) s.Spinner = lipgloss.NewStyle(). - Foreground(lipgloss.AdaptiveColor{Light: "#8E8E8E", Dark: "#747373"}) + Foreground(lightDark("#8E8E8E", "#747373")) s.FilterPrompt = lipgloss.NewStyle(). - Foreground(lipgloss.AdaptiveColor{Light: "#04B575", Dark: "#ECFD65"}) + Foreground(lightDark("#04B575", "#ECFD65")) s.FilterCursor = lipgloss.NewStyle(). - Foreground(lipgloss.AdaptiveColor{Light: "#EE6FF8", Dark: "#EE6FF8"}) + Foreground(lightDark("#EE6FF8", "#EE6FF8")) s.DefaultFilterCharacterMatch = lipgloss.NewStyle().Underline(true) s.StatusBar = lipgloss.NewStyle(). - Foreground(lipgloss.AdaptiveColor{Light: "#A49FA5", Dark: "#777777"}). - Padding(0, 0, 1, 2) + Foreground(lightDark("#A49FA5", "#777777")). + Padding(0, 0, 1, 2) //nolint:mnd s.StatusEmpty = lipgloss.NewStyle().Foreground(subduedColor) s.StatusBarActiveFilter = lipgloss.NewStyle(). - Foreground(lipgloss.AdaptiveColor{Light: "#1a1a1a", Dark: "#dddddd"}) + Foreground(lightDark("#1a1a1a", "#dddddd")) s.StatusBarFilterCount = lipgloss.NewStyle().Foreground(verySubduedColor) s.NoItems = lipgloss.NewStyle(). - Foreground(lipgloss.AdaptiveColor{Light: "#909090", Dark: "#626262"}) + Foreground(lightDark("#909090", "#626262")) 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"}). + Foreground(lightDark("#847A85", "#979797")). SetString(bullet) s.InactivePaginationDot = lipgloss.NewStyle(). diff --git a/paginator/paginator.go b/paginator/paginator.go index bb4fe41c6..ecdbf583c 100644 --- a/paginator/paginator.go +++ b/paginator/paginator.go @@ -173,7 +173,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 1a568b1bc..70b4f246a 100644 --- a/progress/progress.go +++ b/progress/progress.go @@ -330,7 +330,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 b88585c24..bee084dc8 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 37be1336d..bed0fd26e 100644 --- a/table/table.go +++ b/table/table.go @@ -132,7 +132,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(), @@ -215,9 +215,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 9866a8268..2732f0e8f 100644 --- a/textarea/textarea.go +++ b/textarea/textarea.go @@ -10,9 +10,9 @@ import ( "github.com/atotto/clipboard" "github.com/charmbracelet/bubbles/v2/cursor" + "github.com/charmbracelet/bubbles/v2/internal/memoization" + "github.com/charmbracelet/bubbles/v2/internal/runeutil" "github.com/charmbracelet/bubbles/v2/key" - "github.com/charmbracelet/bubbles/v2/runeutil" - "github.com/charmbracelet/bubbles/v2/textarea/memoization" "github.com/charmbracelet/bubbles/v2/viewport" tea "github.com/charmbracelet/bubbletea/v2" "github.com/charmbracelet/lipgloss" @@ -126,14 +126,22 @@ type LineInfo struct { CharOffset int } -// Style that will be applied to the text area. +// Styles are the styles for the textarea, separated into focused and blurred +// states. The appropriate styles will be chosen based on the focus state of +// the textarea. +type Styles struct { + Focused StyleState + Blurred StyleState +} + +// StyleState that will be applied to the text area. // -// Style can be applied to focused and unfocused states to change the styles +// StyleState can be applied to focused and unfocused states to change the styles // depending on the focus state. // // For an introduction to styling with Lip Gloss see: // https://github.com/charmbracelet/lipgloss -type Style struct { +type StyleState struct { Base lipgloss.Style CursorLine lipgloss.Style CursorLineNumber lipgloss.Style @@ -144,34 +152,34 @@ type Style struct { Text lipgloss.Style } -func (s Style) computedCursorLine() lipgloss.Style { +func (s StyleState) computedCursorLine() lipgloss.Style { return s.CursorLine.Inherit(s.Base).Inline(true) } -func (s Style) computedCursorLineNumber() lipgloss.Style { +func (s StyleState) computedCursorLineNumber() lipgloss.Style { return s.CursorLineNumber. Inherit(s.CursorLine). Inherit(s.Base). Inline(true) } -func (s Style) computedEndOfBuffer() lipgloss.Style { +func (s StyleState) computedEndOfBuffer() lipgloss.Style { return s.EndOfBuffer.Inherit(s.Base).Inline(true) } -func (s Style) computedLineNumber() lipgloss.Style { +func (s StyleState) computedLineNumber() lipgloss.Style { return s.LineNumber.Inherit(s.Base).Inline(true) } -func (s Style) computedPlaceholder() lipgloss.Style { +func (s StyleState) computedPlaceholder() lipgloss.Style { return s.Placeholder.Inherit(s.Base).Inline(true) } -func (s Style) computedPrompt() lipgloss.Style { +func (s StyleState) computedPrompt() lipgloss.Style { return s.Prompt.Inherit(s.Base).Inline(true) } -func (s Style) computedText() lipgloss.Style { +func (s StyleState) computedText() lipgloss.Style { return s.Text.Inherit(s.Base).Inline(true) } @@ -219,13 +227,13 @@ type Model struct { // Styling. FocusedStyle and BlurredStyle are used to style the textarea in // focused and blurred states. - FocusedStyle Style - BlurredStyle Style - // style is the current styling to use. + Styles Styles + + // activeStyle is the current styling to use. // It is used to abstract the differences in focus state when styling the - // model, since we can simply assign the set of styles to this variable + // model, since we can simply assign the set of activeStyle to this variable // when switching focus states. - style *Style + activeStyle *StyleState // Cursor is the text area cursor. Cursor cursor.Model @@ -301,16 +309,15 @@ func New() Model { vp.KeyMap = viewport.KeyMap{} cur := cursor.New() - focusedStyle, blurredStyle := DefaultStyles() + styles := DefaultStyles(true) m := Model{ CharLimit: defaultCharLimit, MaxHeight: defaultMaxHeight, MaxWidth: defaultMaxWidth, Prompt: lipgloss.ThickBorder().Left + " ", - style: &blurredStyle, - FocusedStyle: focusedStyle, - BlurredStyle: blurredStyle, + Styles: styles, + activeStyle: &styles.Blurred, cache: memoization.NewMemoCache[line, [][]rune](defaultMaxHeight), EndOfBufferCharacter: ' ', ShowLineNumbers: true, @@ -334,29 +341,31 @@ func New() Model { // DefaultStyles returns the default styles for focused and blurred states for // the textarea. -func DefaultStyles() (Style, Style) { - focused := Style{ +func DefaultStyles(isDark bool) Styles { + lightDark := lipgloss.LightDark(isDark) + + var s Styles + s.Focused = StyleState{ Base: lipgloss.NewStyle(), - CursorLine: lipgloss.NewStyle().Background(lipgloss.AdaptiveColor{Light: "255", Dark: "0"}), - CursorLineNumber: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "240"}), - EndOfBuffer: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "254", Dark: "0"}), - LineNumber: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "249", Dark: "7"}), + CursorLine: lipgloss.NewStyle().Background(lightDark("255", "0")), + CursorLineNumber: lipgloss.NewStyle().Foreground(lightDark("240", "240")), + EndOfBuffer: lipgloss.NewStyle().Foreground(lightDark("254", "0")), + LineNumber: lipgloss.NewStyle().Foreground(lightDark("249", "7")), Placeholder: lipgloss.NewStyle().Foreground(lipgloss.Color("240")), Prompt: lipgloss.NewStyle().Foreground(lipgloss.Color("7")), Text: lipgloss.NewStyle(), } - blurred := Style{ + s.Blurred = StyleState{ Base: lipgloss.NewStyle(), - CursorLine: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "245", Dark: "7"}), - CursorLineNumber: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "249", Dark: "7"}), - EndOfBuffer: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "254", Dark: "0"}), - LineNumber: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "249", Dark: "7"}), + CursorLine: lipgloss.NewStyle().Foreground(lightDark("245", "7")), + CursorLineNumber: lipgloss.NewStyle().Foreground(lightDark("249", "7")), + EndOfBuffer: lipgloss.NewStyle().Foreground(lightDark("254", "0")), + LineNumber: lipgloss.NewStyle().Foreground(lightDark("249", "7")), Placeholder: lipgloss.NewStyle().Foreground(lipgloss.Color("240")), Prompt: lipgloss.NewStyle().Foreground(lipgloss.Color("7")), - Text: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "245", Dark: "7"}), + Text: lipgloss.NewStyle().Foreground(lightDark("245", "7")), } - - return focused, blurred + return s } // SetValue sets the value of the text input. @@ -527,7 +536,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() @@ -561,7 +571,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() @@ -609,7 +620,7 @@ func (m Model) Focused() bool { // receive keyboard input and the cursor will be hidden. func (m *Model) Focus() tea.Cmd { m.focus = true - m.style = &m.FocusedStyle + m.activeStyle = &m.Styles.Focused return m.Cursor.Focus() } @@ -617,7 +628,7 @@ func (m *Model) Focus() tea.Cmd { // not receive keyboard input and the cursor will be hidden. func (m *Model) Blur() { m.focus = false - m.style = &m.BlurredStyle + m.activeStyle = &m.Styles.Blurred m.Cursor.Blur() } @@ -930,7 +941,7 @@ func (m *Model) SetWidth(w int) { } // Add base style borders and padding to reserved outer width. - reservedOuter := m.style.Base.GetHorizontalFrameSize() + reservedOuter := m.activeStyle.Base.GetHorizontalFrameSize() // Add prompt width to reserved inner width. reservedInner := m.promptWidth @@ -1164,7 +1175,7 @@ func (m Model) suggestionView(offset int) string { var lines []string for _, line := range strings.Split(suggestion[len(m.Value())+offset:], "\n") { - lines = append(lines, m.style.Placeholder.Inline(true).Render(line)) + lines = append(lines, m.activeStyle.Placeholder.Inline(true).Render(line)) } if len(lines) > m.Height() { m.SetHeight(len(lines) + 1) @@ -1177,7 +1188,7 @@ func (m Model) View() string { if m.Value() == "" && m.row == 0 && m.col == 0 && m.Placeholder != "" { return m.placeholderView() } - m.Cursor.TextStyle = m.style.computedCursorLine() + m.Cursor.TextStyle = m.activeStyle.computedCursorLine() var ( s strings.Builder @@ -1192,34 +1203,33 @@ func (m Model) View() string { wrappedLines := m.memoizedWrap(line, m.width) if m.row == l { - style = m.style.computedCursorLine() + style = m.activeStyle.computedCursorLine() } else { - style = m.style.computedText() + style = m.activeStyle.computedText() } for wl, wrappedLine := range wrappedLines { prompt := m.getPromptString(displayLine) - prompt = m.style.computedPrompt().Render(prompt) - + prompt = m.activeStyle.computedPrompt().Render(prompt) s.WriteString(style.Render(prompt)) 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))) + ln = style.Render(m.activeStyle.computedCursorLineNumber().Render(m.formatLineNumber(l + 1))) s.WriteString(ln) } else { - ln = style.Render(m.style.computedLineNumber().Render(m.formatLineNumber(l + 1))) + ln = style.Render(m.activeStyle.computedLineNumber().Render(m.formatLineNumber(l + 1))) s.WriteString(ln) } } else { if m.row == l { - ln = style.Render(m.style.computedCursorLineNumber().Render(m.formatLineNumber(" "))) + ln = style.Render(m.activeStyle.computedCursorLineNumber().Render(m.formatLineNumber(" "))) s.WriteString(ln) } else { - ln = style.Render(m.style.computedLineNumber().Render(m.formatLineNumber(" "))) + ln = style.Render(m.activeStyle.computedLineNumber().Render(m.formatLineNumber(" "))) s.WriteString(ln) } } @@ -1264,7 +1274,7 @@ func (m Model) View() string { if len(suggestion) >= m.row { suggestion = suggestion[m.row:] } - m.Cursor.TextStyle = m.style.Placeholder + m.Cursor.TextStyle = m.activeStyle.Placeholder if len(suggestion) > m.row && len(suggestion[m.row]) > m.col { m.Cursor.SetChar(string(suggestion[m.row][m.col])) } @@ -1299,7 +1309,7 @@ func (m Model) View() string { // To do this we can simply pad out a few extra new lines in the view. for i := 0; i < m.height; i++ { prompt := m.getPromptString(displayLine) - prompt = m.style.computedPrompt().Render(prompt) + prompt = m.activeStyle.computedPrompt().Render(prompt) s.WriteString(prompt) displayLine++ @@ -1307,16 +1317,16 @@ func (m Model) View() string { leftGutter := string(m.EndOfBufferCharacter) rightGapWidth := m.Width() - lipgloss.Width(leftGutter) + widestLineNumber rightGap := strings.Repeat(" ", max(0, rightGapWidth)) - s.WriteString(m.style.computedEndOfBuffer().Render(leftGutter + rightGap)) + s.WriteString(m.activeStyle.computedEndOfBuffer().Render(leftGutter + rightGap)) s.WriteRune('\n') } m.viewport.SetContent(s.String()) - return m.style.Base.Render(m.viewport.View()) + return m.activeStyle.Base.Render(m.viewport.View()) } // 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. @@ -1342,7 +1352,7 @@ func (m Model) placeholderView() string { var ( s strings.Builder p = m.Placeholder - style = m.style.computedPlaceholder() + style = m.activeStyle.computedPlaceholder() ) // word wrap lines @@ -1353,16 +1363,16 @@ func (m Model) placeholderView() string { plines := strings.Split(strings.TrimSpace(pwrap), "\n") for i := 0; i < m.height; i++ { - lineStyle := m.style.computedPlaceholder() - lineNumberStyle := m.style.computedLineNumber() + lineStyle := m.activeStyle.computedPlaceholder() + lineNumberStyle := m.activeStyle.computedLineNumber() if len(plines) > i { - lineStyle = m.style.computedCursorLine() - lineNumberStyle = m.style.computedCursorLineNumber() + lineStyle = m.activeStyle.computedCursorLine() + lineNumberStyle = m.activeStyle.computedCursorLineNumber() } // render prompt prompt := m.getPromptString(i) - prompt = m.style.computedPrompt().Render(prompt) + prompt = m.activeStyle.computedPrompt().Render(prompt) s.WriteString(lineStyle.Render(prompt)) // when show line numbers enabled: @@ -1386,7 +1396,7 @@ func (m Model) placeholderView() string { // first line case i == 0: // first character of first line as cursor with character - m.Cursor.TextStyle = m.style.computedPlaceholder() + m.Cursor.TextStyle = m.activeStyle.computedPlaceholder() m.Cursor.SetChar(string(plines[0][0])) s.WriteString(lineStyle.Render(m.Cursor.View())) @@ -1400,7 +1410,7 @@ func (m Model) placeholderView() string { } default: // end of line buffer character - eob := m.style.computedEndOfBuffer().Render(string(m.EndOfBufferCharacter)) + eob := m.activeStyle.computedEndOfBuffer().Render(string(m.EndOfBufferCharacter)) s.WriteString(eob) } @@ -1409,7 +1419,7 @@ func (m Model) placeholderView() string { } m.viewport.SetContent(s.String()) - return m.style.Base.Render(m.viewport.View()) + return m.activeStyle.Base.Render(m.viewport.View()) } // Blink returns the blink command for the cursor. @@ -1586,7 +1596,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/textarea/textarea_test.go b/textarea/textarea_test.go index 7831ce1e3..cdc4edc76 100644 --- a/textarea/textarea_test.go +++ b/textarea/textarea_test.go @@ -1032,7 +1032,7 @@ func TestView(t *testing.T) { { name: "set width with style", modelFunc: func(m Model) Model { - m.FocusedStyle.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) + m.Styles.Focused.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) m.Focus() m.SetWidth(12) @@ -1060,7 +1060,7 @@ func TestView(t *testing.T) { { name: "set width with style max width minus one", modelFunc: func(m Model) Model { - m.FocusedStyle.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) + m.Styles.Focused.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) m.Focus() m.SetWidth(12) @@ -1088,7 +1088,7 @@ func TestView(t *testing.T) { { name: "set width with style max width", modelFunc: func(m Model) Model { - m.FocusedStyle.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) + m.Styles.Focused.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) m.Focus() m.SetWidth(12) @@ -1116,7 +1116,7 @@ func TestView(t *testing.T) { { name: "set width with style max width plus one", modelFunc: func(m Model) Model { - m.FocusedStyle.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) + m.Styles.Focused.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) m.Focus() m.SetWidth(12) @@ -1144,7 +1144,7 @@ func TestView(t *testing.T) { { name: "set width without line numbers with style", modelFunc: func(m Model) Model { - m.FocusedStyle.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) + m.Styles.Focused.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) m.Focus() m.ShowLineNumbers = false @@ -1173,7 +1173,7 @@ func TestView(t *testing.T) { { name: "set width without line numbers with style max width minus one", modelFunc: func(m Model) Model { - m.FocusedStyle.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) + m.Styles.Focused.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) m.Focus() m.ShowLineNumbers = false @@ -1202,7 +1202,7 @@ func TestView(t *testing.T) { { name: "set width without line numbers with style max width", modelFunc: func(m Model) Model { - m.FocusedStyle.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) + m.Styles.Focused.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) m.Focus() m.ShowLineNumbers = false @@ -1231,7 +1231,7 @@ func TestView(t *testing.T) { { name: "set width without line numbers with style max width plus one", modelFunc: func(m Model) Model { - m.FocusedStyle.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) + m.Styles.Focused.Base = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) m.Focus() m.ShowLineNumbers = false diff --git a/textinput/textinput.go b/textinput/textinput.go index 2359d92c7..340445d00 100644 --- a/textinput/textinput.go +++ b/textinput/textinput.go @@ -7,8 +7,8 @@ import ( "github.com/atotto/clipboard" "github.com/charmbracelet/bubbles/v2/cursor" + "github.com/charmbracelet/bubbles/v2/internal/runeutil" "github.com/charmbracelet/bubbles/v2/key" - "github.com/charmbracelet/bubbles/v2/runeutil" tea "github.com/charmbracelet/bubbletea/v2" "github.com/charmbracelet/lipgloss" rw "github.com/mattn/go-runewidth" @@ -553,7 +553,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.KeyPressMsg: @@ -649,7 +649,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 bb0cb407d..949e2ebe8 100644 --- a/viewport/viewport.go +++ b/viewport/viewport.go @@ -144,7 +144,7 @@ func (m *Model) HalfViewDown() { return } - m.LineDown(m.Height / 2) + m.LineDown(m.Height / 2) //nolint:mnd } // HalfViewUp moves the view up by half the height of the viewport. @@ -153,7 +153,7 @@ func (m *Model) HalfViewUp() { return } - m.LineUp(m.Height / 2) + m.LineUp(m.Height / 2) //nolint:mnd } // LineDown moves the view down by the given number of lines. @@ -246,7 +246,7 @@ func (m Model) updateAsModel(msg tea.Msg) Model { break } - switch msg.Button { + switch msg.Button { //nolint:exhaustive case tea.MouseWheelDown: m.LineDown(m.MouseWheelDelta)