From e1bbe648088b29af388f7250a290d0a0e0ec7774 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 8 Mar 2023 21:23:42 +0100
Subject: [PATCH] chore: bump github.com/charmbracelet/bubbletea from 0.23.1 to
0.23.2 (#1)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
go.mod | 6 +-
go.sum | 14 +-
.../charmbracelet/bubbles/help/help.go | 233 ---
.../charmbracelet/bubbles/list/defaultitem.go | 227 ---
.../charmbracelet/bubbles/list/keys.go | 97 --
.../charmbracelet/bubbles/list/list.go | 1264 -----------------
.../charmbracelet/bubbles/list/style.go | 99 --
.../bubbles/paginator/paginator.go | 202 ---
.../charmbracelet/bubbletea/README.md | 53 +-
.../github.com/charmbracelet/bubbletea/tea.go | 21 +-
vendor/github.com/muesli/termenv/README.md | 104 +-
.../github.com/muesli/termenv/ansi_compat.md | 8 +
vendor/github.com/muesli/termenv/color.go | 12 +-
vendor/github.com/muesli/termenv/copy.go | 19 +-
vendor/github.com/muesli/termenv/hyperlink.go | 6 +-
.../github.com/muesli/termenv/notification.go | 11 +
vendor/github.com/muesli/termenv/output.go | 28 +-
vendor/github.com/muesli/termenv/screen.go | 55 +-
vendor/github.com/muesli/termenv/termenv.go | 13 +-
.../muesli/termenv/termenv_other.go | 14 +-
.../github.com/muesli/termenv/termenv_unix.go | 67 +-
vendor/github.com/sahilm/fuzzy/.editorconfig | 18 -
vendor/github.com/sahilm/fuzzy/.gitignore | 2 -
vendor/github.com/sahilm/fuzzy/.travis.yml | 5 -
.../github.com/sahilm/fuzzy/CONTRIBUTING.md | 1 -
vendor/github.com/sahilm/fuzzy/Gopkg.lock | 20 -
vendor/github.com/sahilm/fuzzy/Gopkg.toml | 4 -
vendor/github.com/sahilm/fuzzy/LICENSE | 21 -
vendor/github.com/sahilm/fuzzy/Makefile | 57 -
vendor/github.com/sahilm/fuzzy/README.md | 184 ---
vendor/github.com/sahilm/fuzzy/fuzzy.go | 235 ---
vendor/golang.org/x/sync/LICENSE | 27 +
vendor/golang.org/x/sync/PATENTS | 22 +
vendor/golang.org/x/sync/errgroup/errgroup.go | 132 ++
vendor/modules.txt | 11 +-
35 files changed, 485 insertions(+), 2807 deletions(-)
delete mode 100644 vendor/github.com/charmbracelet/bubbles/help/help.go
delete mode 100644 vendor/github.com/charmbracelet/bubbles/list/defaultitem.go
delete mode 100644 vendor/github.com/charmbracelet/bubbles/list/keys.go
delete mode 100644 vendor/github.com/charmbracelet/bubbles/list/list.go
delete mode 100644 vendor/github.com/charmbracelet/bubbles/list/style.go
delete mode 100644 vendor/github.com/charmbracelet/bubbles/paginator/paginator.go
create mode 100644 vendor/github.com/muesli/termenv/notification.go
delete mode 100644 vendor/github.com/sahilm/fuzzy/.editorconfig
delete mode 100644 vendor/github.com/sahilm/fuzzy/.gitignore
delete mode 100644 vendor/github.com/sahilm/fuzzy/.travis.yml
delete mode 100644 vendor/github.com/sahilm/fuzzy/CONTRIBUTING.md
delete mode 100644 vendor/github.com/sahilm/fuzzy/Gopkg.lock
delete mode 100644 vendor/github.com/sahilm/fuzzy/Gopkg.toml
delete mode 100644 vendor/github.com/sahilm/fuzzy/LICENSE
delete mode 100644 vendor/github.com/sahilm/fuzzy/Makefile
delete mode 100644 vendor/github.com/sahilm/fuzzy/README.md
delete mode 100644 vendor/github.com/sahilm/fuzzy/fuzzy.go
create mode 100644 vendor/golang.org/x/sync/LICENSE
create mode 100644 vendor/golang.org/x/sync/PATENTS
create mode 100644 vendor/golang.org/x/sync/errgroup/errgroup.go
diff --git a/go.mod b/go.mod
index 08155a4..206dfa7 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.19
require (
github.com/charmbracelet/bubbles v0.14.0
- github.com/charmbracelet/bubbletea v0.23.1
+ github.com/charmbracelet/bubbletea v0.23.2
github.com/charmbracelet/lipgloss v0.5.0
github.com/muesli/reflow v0.3.0
)
@@ -19,9 +19,9 @@ require (
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/muesli/ansi v0.0.0-20221106050444-61f0cd9a192a // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
- github.com/muesli/termenv v0.13.0 // indirect
+ github.com/muesli/termenv v0.14.0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
- github.com/sahilm/fuzzy v0.1.0 // indirect
+ golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/term v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
diff --git a/go.sum b/go.sum
index 63c8681..9bd7892 100644
--- a/go.sum
+++ b/go.sum
@@ -1,24 +1,21 @@
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
-github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymanbagabas/go-osc52 v1.2.1 h1:q2sWUyDcozPLcLabEMd+a+7Ea2DitxZVN9hTxab9L4E=
github.com/aymanbagabas/go-osc52 v1.2.1/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/charmbracelet/bubbles v0.14.0 h1:DJfCwnARfWjZLvMglhSQzo76UZ2gucuHPy9jLWX45Og=
github.com/charmbracelet/bubbles v0.14.0/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc=
github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4=
-github.com/charmbracelet/bubbletea v0.23.1 h1:CYdteX1wCiCzKNUlwm25ZHBIc1GXlYFyUIte8WPvhck=
-github.com/charmbracelet/bubbletea v0.23.1/go.mod h1:JAfGK/3/pPKHTnAS8JIE2u9f61BjWTQY57RbT25aMXU=
+github.com/charmbracelet/bubbletea v0.23.2 h1:vuUJ9HJ7b/COy4I30e8xDVQ+VRDUEFykIjryPfgsdps=
+github.com/charmbracelet/bubbletea v0.23.2/go.mod h1:FaP3WUivcTM0xOKNmhciz60M6I+weYLF76mr1JyI7sM=
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8=
github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
-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.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
@@ -39,14 +36,15 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
-github.com/muesli/termenv v0.13.0 h1:wK20DRpJdDX8b7Ek2QfhvqhRQFZ237RGRO0RQ/Iqdy0=
-github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc=
+github.com/muesli/termenv v0.14.0 h1:8x9NFfOe8lmIWK4pgy3IfVEy47f+ppe3tUqdPZG2Uy0=
+github.com/muesli/termenv v0.14.0/go.mod h1:kG/pF1E7fh949Xhe156crRUrHNyK221IuGO7Ez60Uc8=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
-github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/vendor/github.com/charmbracelet/bubbles/help/help.go b/vendor/github.com/charmbracelet/bubbles/help/help.go
deleted file mode 100644
index 90971ac..0000000
--- a/vendor/github.com/charmbracelet/bubbles/help/help.go
+++ /dev/null
@@ -1,233 +0,0 @@
-package help
-
-import (
- "strings"
-
- "github.com/charmbracelet/bubbles/key"
- tea "github.com/charmbracelet/bubbletea"
- "github.com/charmbracelet/lipgloss"
-)
-
-// KeyMap is a map of keybindings used to generate help. Since it's an
-// interface it can be any type, though struct or a map[string][]key.Binding
-// are likely candidates.
-//
-// Note that if a key is disabled (via key.Binding.SetEnabled) it will not be
-// rendered in the help view, so in theory generated help should self-manage.
-type KeyMap interface {
-
- // ShortHelp returns a slice of bindings to be displayed in the short
- // version of the help. The help bubble will render help in the order in
- // which the help items are returned here.
- ShortHelp() []key.Binding
-
- // MoreHelp returns an extended group of help items, grouped by columns.
- // The help bubble will render the help in the order in which the help
- // items are returned here.
- FullHelp() [][]key.Binding
-}
-
-// Styles is a set of available style definitions for the Help bubble.
-type Styles struct {
- Ellipsis lipgloss.Style
-
- // Styling for the short help
- ShortKey lipgloss.Style
- ShortDesc lipgloss.Style
- ShortSeparator lipgloss.Style
-
- // Styling for the full help
- FullKey lipgloss.Style
- FullDesc lipgloss.Style
- FullSeparator lipgloss.Style
-}
-
-// Model contains the state of the help view.
-type Model struct {
- Width int
- ShowAll bool // if true, render the "full" help menu
-
- ShortSeparator string
- FullSeparator string
-
- // The symbol we use in the short help when help items have been truncated
- // due to width. Periods of ellipsis by default.
- Ellipsis string
-
- Styles Styles
-}
-
-// 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.Copy(),
- FullKey: keyStyle.Copy(),
- FullDesc: descStyle.Copy(),
- FullSeparator: sepStyle.Copy(),
- },
- }
-}
-
-// NewModel creates a new help view with some useful defaults.
-//
-// Deprecated. Use New instead.
-var NewModel = New
-
-// Update helps satisfy the Bubble Tea Model interface. It's a no-op.
-func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
- return m, nil
-}
-
-// View renders the help view's current state.
-func (m Model) View(k KeyMap) string {
- if m.ShowAll {
- return m.FullHelpView(k.FullHelp())
- }
- return m.ShortHelpView(k.ShortHelp())
-}
-
-// ShortHelpView renders a single line help view from a slice of keybindings.
-// If the line is longer than the maximum width it will be gracefully
-// truncated, showing only as many help items as possible.
-func (m Model) ShortHelpView(bindings []key.Binding) string {
- if len(bindings) == 0 {
- return ""
- }
-
- var b strings.Builder
- var totalWidth int
- var separator = m.Styles.ShortSeparator.Inline(true).Render(m.ShortSeparator)
-
- for i, kb := range bindings {
- if !kb.Enabled() {
- continue
- }
-
- var sep string
- if totalWidth > 0 && i < len(bindings) {
- sep = separator
- }
-
- 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 {
- b.WriteString(tail)
- }
-
- break
- }
-
- totalWidth += w
- b.WriteString(str)
- }
-
- return b.String()
-}
-
-// FullHelpView renders help columns from a slice of key binding slices. Each
-// top level slice entry renders into a column.
-func (m Model) FullHelpView(groups [][]key.Binding) string {
- if len(groups) == 0 {
- return ""
- }
-
- // Linter note: at this time we don't think it's worth the additional
- // code complexity involved in preallocating this slice.
- //nolint:prealloc
- var (
- out []string
-
- totalWidth int
- sep = m.Styles.FullSeparator.Render(m.FullSeparator)
- sepWidth = lipgloss.Width(sep)
- )
-
- // Iterate over groups to build columns
- for i, group := range groups {
- if group == nil || !shouldRenderColumn(group) {
- continue
- }
-
- var (
- keys []string
- descriptions []string
- )
-
- // Separate keys and descriptions into different slices
- for _, kb := range group {
- if !kb.Enabled() {
- continue
- }
- keys = append(keys, kb.Help().Key)
- descriptions = append(descriptions, kb.Help().Desc)
- }
-
- col := lipgloss.JoinHorizontal(lipgloss.Top,
- m.Styles.FullKey.Render(strings.Join(keys, "\n")),
- m.Styles.FullKey.Render(" "),
- m.Styles.FullDesc.Render(strings.Join(descriptions, "\n")),
- )
-
- // Column
- totalWidth += lipgloss.Width(col)
- if totalWidth > m.Width {
- break
- }
-
- out = append(out, col)
-
- // Separator
- if i < len(group)-1 {
- totalWidth += sepWidth
- if totalWidth > m.Width {
- break
- }
- }
-
- out = append(out, sep)
- }
-
- return lipgloss.JoinHorizontal(lipgloss.Top, out...)
-}
-
-func shouldRenderColumn(b []key.Binding) (ok bool) {
- for _, v := range b {
- if v.Enabled() {
- return true
- }
- }
- return false
-}
diff --git a/vendor/github.com/charmbracelet/bubbles/list/defaultitem.go b/vendor/github.com/charmbracelet/bubbles/list/defaultitem.go
deleted file mode 100644
index 74e4ee2..0000000
--- a/vendor/github.com/charmbracelet/bubbles/list/defaultitem.go
+++ /dev/null
@@ -1,227 +0,0 @@
-package list
-
-import (
- "fmt"
- "io"
- "strings"
-
- "github.com/charmbracelet/bubbles/key"
- tea "github.com/charmbracelet/bubbletea"
- "github.com/charmbracelet/lipgloss"
- "github.com/muesli/reflow/truncate"
-)
-
-// DefaultItemStyles defines styling for a default list item.
-// See DefaultItemView for when these come into play.
-type DefaultItemStyles struct {
- // The Normal state.
- NormalTitle lipgloss.Style
- NormalDesc lipgloss.Style
-
- // The selected item state.
- SelectedTitle lipgloss.Style
- SelectedDesc lipgloss.Style
-
- // The dimmed state, for when the filter input is initially activated.
- DimmedTitle lipgloss.Style
- DimmedDesc lipgloss.Style
-
- // Charcters matching the current filter, if any.
- FilterMatch lipgloss.Style
-}
-
-// NewDefaultItemStyles returns style definitions for a default item. See
-// DefaultItemView for when these come into play.
-func NewDefaultItemStyles() (s DefaultItemStyles) {
- s.NormalTitle = lipgloss.NewStyle().
- Foreground(lipgloss.AdaptiveColor{Light: "#1a1a1a", Dark: "#dddddd"}).
- Padding(0, 0, 0, 2)
-
- s.NormalDesc = s.NormalTitle.Copy().
- Foreground(lipgloss.AdaptiveColor{Light: "#A49FA5", Dark: "#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"}).
- Padding(0, 0, 0, 1)
-
- s.SelectedDesc = s.SelectedTitle.Copy().
- Foreground(lipgloss.AdaptiveColor{Light: "#F793FF", Dark: "#AD58B4"})
-
- s.DimmedTitle = lipgloss.NewStyle().
- Foreground(lipgloss.AdaptiveColor{Light: "#A49FA5", Dark: "#777777"}).
- Padding(0, 0, 0, 2)
-
- s.DimmedDesc = s.DimmedTitle.Copy().
- Foreground(lipgloss.AdaptiveColor{Light: "#C2B8C2", Dark: "#4D4D4D"})
-
- s.FilterMatch = lipgloss.NewStyle().Underline(true)
-
- return s
-}
-
-// DefaultItem describes an items designed to work with DefaultDelegate.
-type DefaultItem interface {
- Item
- Title() string
- Description() string
-}
-
-// DefaultDelegate is a standard delegate designed to work in lists. It's
-// styled by DefaultItemStyles, which can be customized as you like.
-//
-// The description line can be hidden by setting Description to false, which
-// renders the list as single-line-items. The spacing between items can be set
-// with the SetSpacing method.
-//
-// Setting UpdateFunc is optional. If it's set it will be called when the
-// ItemDelegate called, which is called when the list's Update function is
-// invoked.
-//
-// Settings ShortHelpFunc and FullHelpFunc is optional. They can can be set to
-// include items in the list's default short and full help menus.
-type DefaultDelegate struct {
- ShowDescription bool
- Styles DefaultItemStyles
- UpdateFunc func(tea.Msg, *Model) tea.Cmd
- ShortHelpFunc func() []key.Binding
- FullHelpFunc func() [][]key.Binding
- height int
- spacing int
-}
-
-// NewDefaultDelegate creates a new delegate with default styles.
-func NewDefaultDelegate() DefaultDelegate {
- return DefaultDelegate{
- ShowDescription: true,
- Styles: NewDefaultItemStyles(),
- height: 2,
- spacing: 1,
- }
-}
-
-// SetHeight sets delegate's preferred height.
-func (d *DefaultDelegate) SetHeight(i int) {
- d.height = i
-}
-
-// Height returns the delegate's preferred height.
-// This has effect only if ShowDescription is true,
-// otherwise height is always 1.
-func (d DefaultDelegate) Height() int {
- if d.ShowDescription {
- return d.height
- }
- return 1
-}
-
-// SetSpacing set the delegate's spacing.
-func (d *DefaultDelegate) SetSpacing(i int) {
- d.spacing = i
-}
-
-// Spacing returns the delegate's spacing.
-func (d DefaultDelegate) Spacing() int {
- return d.spacing
-}
-
-// Update checks whether the delegate's UpdateFunc is set and calls it.
-func (d DefaultDelegate) Update(msg tea.Msg, m *Model) tea.Cmd {
- if d.UpdateFunc == nil {
- return nil
- }
- return d.UpdateFunc(msg, m)
-}
-
-// Render prints an item.
-func (d DefaultDelegate) Render(w io.Writer, m Model, index int, item Item) {
- var (
- title, desc string
- matchedRunes []int
- s = &d.Styles
- )
-
- if i, ok := item.(DefaultItem); ok {
- title = i.Title()
- desc = i.Description()
- } else {
- return
- }
-
- if m.width <= 0 {
- // short-circuit
- return
- }
-
- // Prevent text from exceeding list width
- textwidth := uint(m.width - s.NormalTitle.GetPaddingLeft() - s.NormalTitle.GetPaddingRight())
- title = truncate.StringWithTail(title, textwidth, ellipsis)
- if d.ShowDescription {
- var lines []string
- for i, line := range strings.Split(desc, "\n") {
- if i >= d.height-1 {
- break
- }
- lines = append(lines, truncate.StringWithTail(line, textwidth, ellipsis))
- }
- desc = strings.Join(lines, "\n")
- }
-
- // Conditions
- var (
- isSelected = index == m.Index()
- emptyFilter = m.FilterState() == Filtering && m.FilterValue() == ""
- isFiltered = m.FilterState() == Filtering || m.FilterState() == FilterApplied
- )
-
- if isFiltered && index < len(m.filteredItems) {
- // Get indices of matched characters
- matchedRunes = m.MatchesForItem(index)
- }
-
- if emptyFilter {
- title = s.DimmedTitle.Render(title)
- desc = s.DimmedDesc.Render(desc)
- } else if isSelected && m.FilterState() != Filtering {
- if isFiltered {
- // Highlight matches
- unmatched := s.SelectedTitle.Inline(true)
- matched := unmatched.Copy().Inherit(s.FilterMatch)
- title = lipgloss.StyleRunes(title, matchedRunes, matched, unmatched)
- }
- title = s.SelectedTitle.Render(title)
- desc = s.SelectedDesc.Render(desc)
- } else {
- if isFiltered {
- // Highlight matches
- unmatched := s.NormalTitle.Inline(true)
- matched := unmatched.Copy().Inherit(s.FilterMatch)
- title = lipgloss.StyleRunes(title, matchedRunes, matched, unmatched)
- }
- title = s.NormalTitle.Render(title)
- desc = s.NormalDesc.Render(desc)
- }
-
- if d.ShowDescription {
- fmt.Fprintf(w, "%s\n%s", title, desc)
- return
- }
- fmt.Fprintf(w, "%s", title)
-}
-
-// ShortHelp returns the delegate's short help.
-func (d DefaultDelegate) ShortHelp() []key.Binding {
- if d.ShortHelpFunc != nil {
- return d.ShortHelpFunc()
- }
- return nil
-}
-
-// FullHelp returns the delegate's full help.
-func (d DefaultDelegate) FullHelp() [][]key.Binding {
- if d.FullHelpFunc != nil {
- return d.FullHelpFunc()
- }
- return nil
-}
diff --git a/vendor/github.com/charmbracelet/bubbles/list/keys.go b/vendor/github.com/charmbracelet/bubbles/list/keys.go
deleted file mode 100644
index 421a247..0000000
--- a/vendor/github.com/charmbracelet/bubbles/list/keys.go
+++ /dev/null
@@ -1,97 +0,0 @@
-package list
-
-import "github.com/charmbracelet/bubbles/key"
-
-// KeyMap defines keybindings. It satisfies to the help.KeyMap interface, which
-// is used to render the menu menu.
-type KeyMap struct {
- // Keybindings used when browsing the list.
- CursorUp key.Binding
- CursorDown key.Binding
- NextPage key.Binding
- PrevPage key.Binding
- GoToStart key.Binding
- GoToEnd key.Binding
- Filter key.Binding
- ClearFilter key.Binding
-
- // Keybindings used when setting a filter.
- CancelWhileFiltering key.Binding
- AcceptWhileFiltering key.Binding
-
- // Help toggle keybindings.
- ShowFullHelp key.Binding
- CloseFullHelp key.Binding
-
- // The quit keybinding. This won't be caught when filtering.
- Quit key.Binding
-
- // The quit-no-matter-what keybinding. This will be caught when filtering.
- ForceQuit key.Binding
-}
-
-// DefaultKeyMap returns a default set of keybindings.
-func DefaultKeyMap() KeyMap {
- return KeyMap{
- // Browsing.
- CursorUp: key.NewBinding(
- key.WithKeys("up", "k"),
- key.WithHelp("↑/k", "up"),
- ),
- CursorDown: key.NewBinding(
- key.WithKeys("down", "j"),
- key.WithHelp("↓/j", "down"),
- ),
- PrevPage: key.NewBinding(
- key.WithKeys("left", "h", "pgup", "b", "u"),
- key.WithHelp("←/h/pgup", "prev page"),
- ),
- NextPage: key.NewBinding(
- key.WithKeys("right", "l", "pgdown", "f", "d"),
- key.WithHelp("→/l/pgdn", "next page"),
- ),
- GoToStart: key.NewBinding(
- key.WithKeys("home", "g"),
- key.WithHelp("g/home", "go to start"),
- ),
- GoToEnd: key.NewBinding(
- key.WithKeys("end", "G"),
- key.WithHelp("G/end", "go to end"),
- ),
- Filter: key.NewBinding(
- key.WithKeys("/"),
- key.WithHelp("/", "filter"),
- ),
- ClearFilter: key.NewBinding(
- key.WithKeys("esc"),
- key.WithHelp("esc", "clear filter"),
- ),
-
- // Filtering.
- CancelWhileFiltering: key.NewBinding(
- key.WithKeys("esc"),
- key.WithHelp("esc", "cancel"),
- ),
- AcceptWhileFiltering: key.NewBinding(
- key.WithKeys("enter", "tab", "shift+tab", "ctrl+k", "up", "ctrl+j", "down"),
- key.WithHelp("enter", "apply filter"),
- ),
-
- // Toggle help.
- ShowFullHelp: key.NewBinding(
- key.WithKeys("?"),
- key.WithHelp("?", "more"),
- ),
- CloseFullHelp: key.NewBinding(
- key.WithKeys("?"),
- key.WithHelp("?", "close help"),
- ),
-
- // Quitting.
- Quit: key.NewBinding(
- key.WithKeys("q", "esc"),
- key.WithHelp("q", "quit"),
- ),
- ForceQuit: key.NewBinding(key.WithKeys("ctrl+c")),
- }
-}
diff --git a/vendor/github.com/charmbracelet/bubbles/list/list.go b/vendor/github.com/charmbracelet/bubbles/list/list.go
deleted file mode 100644
index bec5e6f..0000000
--- a/vendor/github.com/charmbracelet/bubbles/list/list.go
+++ /dev/null
@@ -1,1264 +0,0 @@
-// Package list provides a feature-rich Bubble Tea component for browsing
-// a general purpose list of items. It features optional filtering, pagination,
-// help, status messages, and a spinner to indicate activity.
-package list
-
-import (
- "fmt"
- "io"
- "sort"
- "strings"
- "time"
-
- "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/muesli/reflow/ansi"
- "github.com/muesli/reflow/truncate"
- "github.com/sahilm/fuzzy"
-)
-
-// Item is an item that appears in the list.
-type Item interface {
- // Filter value is the value we use when filtering against this item when
- // we're filtering the list.
- FilterValue() string
-}
-
-// ItemDelegate encapsulates the general functionality for all list items. The
-// benefit to separating this logic from the item itself is that you can change
-// the functionality of items without changing the actual items themselves.
-//
-// Note that if the delegate also implements help.KeyMap delegate-related
-// help items will be added to the help view.
-type ItemDelegate interface {
- // Render renders the item's view.
- Render(w io.Writer, m Model, index int, item Item)
-
- // Height is the height of the list item.
- Height() int
-
- // Spacing is the size of the horizontal gap between list items in cells.
- Spacing() int
-
- // Update is the update loop for items. All messages in the list's update
- // loop will pass through here except when the user is setting a filter.
- // Use this method to perform item-level updates appropriate to this
- // delegate.
- Update(msg tea.Msg, m *Model) tea.Cmd
-}
-
-type filteredItem struct {
- item Item // item matched
- matches []int // rune indices of matched items
-}
-
-type filteredItems []filteredItem
-
-func (f filteredItems) items() []Item {
- agg := make([]Item, len(f))
- for i, v := range f {
- agg[i] = v.item
- }
- return agg
-}
-
-// FilterMatchesMsg contains data about items matched during filtering. The
-// message should be routed to Update for processing.
-type FilterMatchesMsg []filteredItem
-
-// FilterFunc takes a term and a list of strings to search through
-// (defined by Item#FilterValue).
-// It should return a sorted list of ranks.
-type FilterFunc func(string, []string) []Rank
-
-// Rank defines a rank for a given item.
-type Rank struct {
- // The index of the item in the original input.
- Index int
- // Indices of the actual word that were matched against the filter term.
- MatchedIndexes []int
-}
-
-// DefaultFilter uses the sahilm/fuzzy to filter through the list.
-// This is set by default.
-func DefaultFilter(term string, targets []string) []Rank {
- var ranks = fuzzy.Find(term, targets)
- sort.Stable(ranks)
- result := make([]Rank, len(ranks))
- for i, r := range ranks {
- result[i] = Rank{
- Index: r.Index,
- MatchedIndexes: r.MatchedIndexes,
- }
- }
- return result
-}
-
-type statusMessageTimeoutMsg struct{}
-
-// FilterState describes the current filtering state on the model.
-type FilterState int
-
-// Possible filter states.
-const (
- Unfiltered FilterState = iota // no filter set
- Filtering // user is actively setting a filter
- FilterApplied // a filter is applied and user is not editing filter
-)
-
-// String returns a human-readable string of the current filter state.
-func (f FilterState) String() string {
- return [...]string{
- "unfiltered",
- "filtering",
- "filter applied",
- }[f]
-}
-
-// Model contains the state of this component.
-type Model struct {
- showTitle bool
- showFilter bool
- showStatusBar bool
- showPagination bool
- showHelp bool
- filteringEnabled bool
-
- itemNameSingular string
- itemNamePlural string
-
- Title string
- Styles Styles
-
- // Key mappings for navigating the list.
- KeyMap KeyMap
-
- // Filter is used to filter the list.
- Filter FilterFunc
-
- disableQuitKeybindings bool
-
- // Additional key mappings for the short and full help views. This allows
- // you to add additional key mappings to the help menu without
- // re-implementing the help component. Of course, you can also disable the
- // list's help component and implement a new one if you need more
- // flexibility.
- AdditionalShortHelpKeys func() []key.Binding
- AdditionalFullHelpKeys func() []key.Binding
-
- spinner spinner.Model
- showSpinner bool
- width int
- height int
- Paginator paginator.Model
- cursor int
- Help help.Model
- FilterInput textinput.Model
- filterState FilterState
-
- // How long status messages should stay visible. By default this is
- // 1 second.
- StatusMessageLifetime time.Duration
-
- statusMessage string
- statusMessageTimer *time.Timer
-
- // The master set of items we're working with.
- items []Item
-
- // Filtered items we're currently displaying. Filtering, toggles and so on
- // will alter this slice so we can show what is relevant. For that reason,
- // this field should be considered ephemeral.
- filteredItems filteredItems
-
- delegate ItemDelegate
-}
-
-// New returns a new model with sensible defaults.
-func New(items []Item, delegate ItemDelegate, width, height int) Model {
- styles := DefaultStyles()
-
- sp := spinner.NewModel()
- sp.Spinner = spinner.Line
- sp.Style = styles.Spinner
-
- filterInput := textinput.NewModel()
- filterInput.Prompt = "Filter: "
- filterInput.PromptStyle = styles.FilterPrompt
- filterInput.CursorStyle = styles.FilterCursor
- filterInput.CharLimit = 64
- filterInput.Focus()
-
- p := paginator.NewModel()
- p.Type = paginator.Dots
- p.ActiveDot = styles.ActivePaginationDot.String()
- p.InactiveDot = styles.InactivePaginationDot.String()
-
- m := Model{
- showTitle: true,
- showFilter: true,
- showStatusBar: true,
- showPagination: true,
- showHelp: true,
- itemNameSingular: "item",
- itemNamePlural: "items",
- filteringEnabled: true,
- KeyMap: DefaultKeyMap(),
- Filter: DefaultFilter,
- Styles: styles,
- Title: "List",
- FilterInput: filterInput,
- StatusMessageLifetime: time.Second,
-
- width: width,
- height: height,
- delegate: delegate,
- items: items,
- Paginator: p,
- spinner: sp,
- Help: help.NewModel(),
- }
-
- m.updatePagination()
- m.updateKeybindings()
- return m
-}
-
-// NewModel returns a new model with sensible defaults.
-//
-// Deprecated. Use New instead.
-var NewModel = New
-
-// SetFilteringEnabled enables or disables filtering. Note that this is different
-// from ShowFilter, which merely hides or shows the input view.
-func (m *Model) SetFilteringEnabled(v bool) {
- m.filteringEnabled = v
- if !v {
- m.resetFiltering()
- }
- m.updateKeybindings()
-}
-
-// FilteringEnabled returns whether or not filtering is enabled.
-func (m Model) FilteringEnabled() bool {
- return m.filteringEnabled
-}
-
-// SetShowTitle shows or hides the title bar.
-func (m *Model) SetShowTitle(v bool) {
- m.showTitle = v
- m.updatePagination()
-}
-
-// ShowTitle returns whether or not the title bar is set to be rendered.
-func (m Model) ShowTitle() bool {
- return m.showTitle
-}
-
-// SetShowFilter shows or hides the filer bar. Note that this does not disable
-// filtering, it simply hides the built-in filter view. This allows you to
-// use the FilterInput to render the filtering UI differently without having to
-// re-implement filtering from scratch.
-//
-// To disable filtering entirely use EnableFiltering.
-func (m *Model) SetShowFilter(v bool) {
- m.showFilter = v
- m.updatePagination()
-}
-
-// ShowFilter returns whether or not the filter is set to be rendered. Note
-// that this is separate from FilteringEnabled, so filtering can be hidden yet
-// still invoked. This allows you to render filtering differently without
-// having to re-implement it from scratch.
-func (m Model) ShowFilter() bool {
- return m.showFilter
-}
-
-// SetShowStatusBar shows or hides the view that displays metadata about the
-// list, such as item counts.
-func (m *Model) SetShowStatusBar(v bool) {
- m.showStatusBar = v
- m.updatePagination()
-}
-
-// ShowStatusBar returns whether or not the status bar is set to be rendered.
-func (m Model) ShowStatusBar() bool {
- return m.showStatusBar
-}
-
-// SetStatusBarItemName defines a replacement for the items identifier.
-// Defaults to item/items.
-func (m *Model) SetStatusBarItemName(singular, plural string) {
- m.itemNameSingular = singular
- m.itemNamePlural = plural
-}
-
-// StatusBarItemName returns singular and plural status bar item names.
-func (m Model) StatusBarItemName() (string, string) {
- return m.itemNameSingular, m.itemNamePlural
-}
-
-// SetShowPagination hides or shoes the paginator. Note that pagination will
-// still be active, it simply won't be displayed.
-func (m *Model) SetShowPagination(v bool) {
- m.showPagination = v
- m.updatePagination()
-}
-
-// ShowPagination returns whether the pagination is visible.
-func (m *Model) ShowPagination() bool {
- return m.showPagination
-}
-
-// SetShowHelp shows or hides the help view.
-func (m *Model) SetShowHelp(v bool) {
- m.showHelp = v
- m.updatePagination()
-}
-
-// ShowHelp returns whether or not the help is set to be rendered.
-func (m Model) ShowHelp() bool {
- return m.showHelp
-}
-
-// Items returns the items in the list.
-func (m Model) Items() []Item {
- return m.items
-}
-
-// Set the items available in the list. This returns a command.
-func (m *Model) SetItems(i []Item) tea.Cmd {
- var cmd tea.Cmd
- m.items = i
-
- if m.filterState != Unfiltered {
- m.filteredItems = nil
- cmd = filterItems(*m)
- }
-
- m.updatePagination()
- m.updateKeybindings()
- return cmd
-}
-
-// Select selects the given index of the list and goes to its respective page.
-func (m *Model) Select(index int) {
- m.Paginator.Page = index / m.Paginator.PerPage
- m.cursor = index % m.Paginator.PerPage
-}
-
-// ResetSelected resets the selected item to the first item in the first page of the list.
-func (m *Model) ResetSelected() {
- m.Select(0)
-}
-
-// ResetFilter resets the current filtering state.
-func (m *Model) ResetFilter() {
- m.resetFiltering()
-}
-
-// Replace an item at the given index. This returns a command.
-func (m *Model) SetItem(index int, item Item) tea.Cmd {
- var cmd tea.Cmd
- m.items[index] = item
-
- if m.filterState != Unfiltered {
- cmd = filterItems(*m)
- }
-
- m.updatePagination()
- return cmd
-}
-
-// Insert an item at the given index. If index is out of the upper bound, the
-// item will be appended. This returns a command.
-func (m *Model) InsertItem(index int, item Item) tea.Cmd {
- var cmd tea.Cmd
- m.items = insertItemIntoSlice(m.items, item, index)
-
- if m.filterState != Unfiltered {
- cmd = filterItems(*m)
- }
-
- m.updatePagination()
- m.updateKeybindings()
- return cmd
-}
-
-// RemoveItem removes an item at the given index. If the index is out of bounds
-// this will be a no-op. O(n) complexity, which probably won't matter in the
-// case of a TUI.
-func (m *Model) RemoveItem(index int) {
- m.items = removeItemFromSlice(m.items, index)
- if m.filterState != Unfiltered {
- m.filteredItems = removeFilterMatchFromSlice(m.filteredItems, index)
- if len(m.filteredItems) == 0 {
- m.resetFiltering()
- }
- }
- m.updatePagination()
-}
-
-// Set the item delegate.
-func (m *Model) SetDelegate(d ItemDelegate) {
- m.delegate = d
- m.updatePagination()
-}
-
-// VisibleItems returns the total items available to be shown.
-func (m Model) VisibleItems() []Item {
- if m.filterState != Unfiltered {
- return m.filteredItems.items()
- }
- return m.items
-}
-
-// SelectedItems returns the current selected item in the list.
-func (m Model) SelectedItem() Item {
- i := m.Index()
-
- items := m.VisibleItems()
- if i < 0 || len(items) == 0 || len(items) <= i {
- return nil
- }
-
- return items[i]
-}
-
-// MatchesForItem returns rune positions matched by the current filter, if any.
-// Use this to style runes matched by the active filter.
-//
-// See DefaultItemView for a usage example.
-func (m Model) MatchesForItem(index int) []int {
- if m.filteredItems == nil || index >= len(m.filteredItems) {
- return nil
- }
- return m.filteredItems[index].matches
-}
-
-// Index returns the index of the currently selected item as it appears in the
-// entire slice of items.
-func (m Model) Index() int {
- return m.Paginator.Page*m.Paginator.PerPage + m.cursor
-}
-
-// Cursor returns the index of the cursor on the current page.
-func (m Model) Cursor() int {
- return m.cursor
-}
-
-// CursorUp moves the cursor up. This can also move the state to the previous
-// page.
-func (m *Model) CursorUp() {
- m.cursor--
-
- // If we're at the start, stop
- if m.cursor < 0 && m.Paginator.Page == 0 {
- m.cursor = 0
- return
- }
-
- // Move the cursor as normal
- if m.cursor >= 0 {
- return
- }
-
- // Go to the previous page
- m.Paginator.PrevPage()
- m.cursor = m.Paginator.ItemsOnPage(len(m.VisibleItems())) - 1
-}
-
-// CursorDown moves the cursor down. This can also advance the state to the
-// next page.
-func (m *Model) CursorDown() {
- itemsOnPage := m.Paginator.ItemsOnPage(len(m.VisibleItems()))
-
- m.cursor++
-
- // If we're at the end, stop
- if m.cursor < itemsOnPage {
- return
- }
-
- // Go to the next page
- if !m.Paginator.OnLastPage() {
- m.Paginator.NextPage()
- m.cursor = 0
- return
- }
-
- // During filtering the cursor position can exceed the number of
- // itemsOnPage. It's more intuitive to start the cursor at the
- // topmost position when moving it down in this scenario.
- if m.cursor > itemsOnPage {
- m.cursor = 0
- return
- }
-
- m.cursor = itemsOnPage - 1
-}
-
-// PrevPage moves to the previous page, if available.
-func (m Model) PrevPage() {
- m.Paginator.PrevPage()
-}
-
-// NextPage moves to the next page, if available.
-func (m Model) NextPage() {
- m.Paginator.NextPage()
-}
-
-// FilterState returns the current filter state.
-func (m Model) FilterState() FilterState {
- return m.filterState
-}
-
-// FilterValue returns the current value of the filter.
-func (m Model) FilterValue() string {
- return m.FilterInput.Value()
-}
-
-// SettingFilter returns whether or not the user is currently editing the
-// filter value. It's purely a convenience method for the following:
-//
-// m.FilterState() == Filtering
-//
-// It's included here because it's a common thing to check for when
-// implementing this component.
-func (m Model) SettingFilter() bool {
- return m.filterState == Filtering
-}
-
-// IsFiltered returns whether or not the list is currently filtered.
-// It's purely a convenience method for the following:
-//
-// m.FilterState() == FilterApplied
-//
-func (m Model) IsFiltered() bool {
- return m.filterState == FilterApplied
-}
-
-// Width returns the current width setting.
-func (m Model) Width() int {
- return m.width
-}
-
-// Height returns the current height setting.
-func (m Model) Height() int {
- return m.height
-}
-
-// SetSpinner allows to set the spinner style.
-func (m *Model) SetSpinner(spinner spinner.Spinner) {
- m.spinner.Spinner = spinner
-}
-
-// Toggle the spinner. Note that this also returns a command.
-func (m *Model) ToggleSpinner() tea.Cmd {
- if !m.showSpinner {
- return m.StartSpinner()
- }
- m.StopSpinner()
- return nil
-}
-
-// StartSpinner starts the spinner. Note that this returns a command.
-func (m *Model) StartSpinner() tea.Cmd {
- m.showSpinner = true
- return spinner.Tick
-}
-
-// StopSpinner stops the spinner.
-func (m *Model) StopSpinner() {
- m.showSpinner = false
-}
-
-// Helper for disabling the keybindings used for quitting, in case you want to
-// handle this elsewhere in your application.
-func (m *Model) DisableQuitKeybindings() {
- m.disableQuitKeybindings = true
- m.KeyMap.Quit.SetEnabled(false)
- m.KeyMap.ForceQuit.SetEnabled(false)
-}
-
-// NewStatusMessage sets a new status message, which will show for a limited
-// amount of time. Note that this also returns a command.
-func (m *Model) NewStatusMessage(s string) tea.Cmd {
- m.statusMessage = s
- if m.statusMessageTimer != nil {
- m.statusMessageTimer.Stop()
- }
-
- m.statusMessageTimer = time.NewTimer(m.StatusMessageLifetime)
-
- // Wait for timeout
- return func() tea.Msg {
- <-m.statusMessageTimer.C
- return statusMessageTimeoutMsg{}
- }
-}
-
-// SetSize sets the width and height of this component.
-func (m *Model) SetSize(width, height int) {
- m.setSize(width, height)
-}
-
-// SetWidth sets the width of this component.
-func (m *Model) SetWidth(v int) {
- m.setSize(v, m.height)
-}
-
-// SetHeight sets the height of this component.
-func (m *Model) SetHeight(v int) {
- m.setSize(m.width, v)
-}
-
-func (m *Model) setSize(width, height int) {
- promptWidth := lipgloss.Width(m.Styles.Title.Render(m.FilterInput.Prompt))
-
- m.width = width
- m.height = height
- m.Help.Width = width
- m.FilterInput.Width = width - promptWidth - lipgloss.Width(m.spinnerView())
- m.updatePagination()
-}
-
-func (m *Model) resetFiltering() {
- if m.filterState == Unfiltered {
- return
- }
-
- m.filterState = Unfiltered
- m.FilterInput.Reset()
- m.filteredItems = nil
- m.updatePagination()
- m.updateKeybindings()
-}
-
-func (m Model) itemsAsFilterItems() filteredItems {
- fi := make([]filteredItem, len(m.items))
- for i, item := range m.items {
- fi[i] = filteredItem{
- item: item,
- }
- }
- return filteredItems(fi)
-}
-
-// Set keybindings according to the filter state.
-func (m *Model) updateKeybindings() {
- switch m.filterState {
- case Filtering:
- m.KeyMap.CursorUp.SetEnabled(false)
- m.KeyMap.CursorDown.SetEnabled(false)
- m.KeyMap.NextPage.SetEnabled(false)
- m.KeyMap.PrevPage.SetEnabled(false)
- m.KeyMap.GoToStart.SetEnabled(false)
- m.KeyMap.GoToEnd.SetEnabled(false)
- m.KeyMap.Filter.SetEnabled(false)
- m.KeyMap.ClearFilter.SetEnabled(false)
- m.KeyMap.CancelWhileFiltering.SetEnabled(true)
- m.KeyMap.AcceptWhileFiltering.SetEnabled(m.FilterInput.Value() != "")
- m.KeyMap.Quit.SetEnabled(false)
- m.KeyMap.ShowFullHelp.SetEnabled(false)
- m.KeyMap.CloseFullHelp.SetEnabled(false)
-
- default:
- hasItems := len(m.items) != 0
- m.KeyMap.CursorUp.SetEnabled(hasItems)
- m.KeyMap.CursorDown.SetEnabled(hasItems)
-
- hasPages := m.Paginator.TotalPages > 1
- m.KeyMap.NextPage.SetEnabled(hasPages)
- m.KeyMap.PrevPage.SetEnabled(hasPages)
-
- m.KeyMap.GoToStart.SetEnabled(hasItems)
- m.KeyMap.GoToEnd.SetEnabled(hasItems)
-
- m.KeyMap.Filter.SetEnabled(m.filteringEnabled && hasItems)
- m.KeyMap.ClearFilter.SetEnabled(m.filterState == FilterApplied)
- m.KeyMap.CancelWhileFiltering.SetEnabled(false)
- m.KeyMap.AcceptWhileFiltering.SetEnabled(false)
- m.KeyMap.Quit.SetEnabled(!m.disableQuitKeybindings)
-
- if m.Help.ShowAll {
- m.KeyMap.ShowFullHelp.SetEnabled(true)
- m.KeyMap.CloseFullHelp.SetEnabled(true)
- } else {
- minHelp := countEnabledBindings(m.FullHelp()) > 1
- m.KeyMap.ShowFullHelp.SetEnabled(minHelp)
- m.KeyMap.CloseFullHelp.SetEnabled(minHelp)
- }
- }
-}
-
-// Update pagination according to the amount of items for the current state.
-func (m *Model) updatePagination() {
- index := m.Index()
- availHeight := m.height
-
- if m.showTitle || (m.showFilter && m.filteringEnabled) {
- availHeight -= lipgloss.Height(m.titleView())
- }
- if m.showStatusBar {
- availHeight -= lipgloss.Height(m.statusView())
- }
- if m.showPagination {
- availHeight -= lipgloss.Height(m.paginationView())
- }
- if m.showHelp {
- availHeight -= lipgloss.Height(m.helpView())
- }
-
- m.Paginator.PerPage = max(1, availHeight/(m.delegate.Height()+m.delegate.Spacing()))
-
- if pages := len(m.VisibleItems()); pages < 1 {
- m.Paginator.SetTotalPages(1)
- } else {
- m.Paginator.SetTotalPages(pages)
- }
-
- // Restore index
- m.Paginator.Page = index / m.Paginator.PerPage
- m.cursor = index % m.Paginator.PerPage
-
- // Make sure the page stays in bounds
- if m.Paginator.Page >= m.Paginator.TotalPages-1 {
- m.Paginator.Page = max(0, m.Paginator.TotalPages-1)
- }
-}
-
-func (m *Model) hideStatusMessage() {
- m.statusMessage = ""
- if m.statusMessageTimer != nil {
- m.statusMessageTimer.Stop()
- }
-}
-
-// Update is the Bubble Tea update loop.
-func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
- var cmds []tea.Cmd
-
- switch msg := msg.(type) {
- case tea.KeyMsg:
- if key.Matches(msg, m.KeyMap.ForceQuit) {
- return m, tea.Quit
- }
-
- case FilterMatchesMsg:
- m.filteredItems = filteredItems(msg)
- return m, nil
-
- case spinner.TickMsg:
- newSpinnerModel, cmd := m.spinner.Update(msg)
- m.spinner = newSpinnerModel
- if m.showSpinner {
- cmds = append(cmds, cmd)
- }
-
- case statusMessageTimeoutMsg:
- m.hideStatusMessage()
- }
-
- if m.filterState == Filtering {
- cmds = append(cmds, m.handleFiltering(msg))
- } else {
- cmds = append(cmds, m.handleBrowsing(msg))
- }
-
- return m, tea.Batch(cmds...)
-}
-
-// Updates for when a user is browsing the list.
-func (m *Model) handleBrowsing(msg tea.Msg) tea.Cmd {
- var cmds []tea.Cmd
- numItems := len(m.VisibleItems())
-
- switch msg := msg.(type) {
- case tea.KeyMsg:
- switch {
- // Note: we match clear filter before quit because, by default, they're
- // both mapped to escape.
- case key.Matches(msg, m.KeyMap.ClearFilter):
- m.resetFiltering()
-
- case key.Matches(msg, m.KeyMap.Quit):
- return tea.Quit
-
- case key.Matches(msg, m.KeyMap.CursorUp):
- m.CursorUp()
-
- case key.Matches(msg, m.KeyMap.CursorDown):
- m.CursorDown()
-
- case key.Matches(msg, m.KeyMap.PrevPage):
- m.Paginator.PrevPage()
-
- case key.Matches(msg, m.KeyMap.NextPage):
- m.Paginator.NextPage()
-
- case key.Matches(msg, m.KeyMap.GoToStart):
- m.Paginator.Page = 0
- m.cursor = 0
-
- case key.Matches(msg, m.KeyMap.GoToEnd):
- m.Paginator.Page = m.Paginator.TotalPages - 1
- m.cursor = m.Paginator.ItemsOnPage(numItems) - 1
-
- case key.Matches(msg, m.KeyMap.Filter):
- m.hideStatusMessage()
- if m.FilterInput.Value() == "" {
- // Populate filter with all items only if the filter is empty.
- m.filteredItems = m.itemsAsFilterItems()
- }
- m.Paginator.Page = 0
- m.cursor = 0
- m.filterState = Filtering
- m.FilterInput.CursorEnd()
- m.FilterInput.Focus()
- m.updateKeybindings()
- return textinput.Blink
-
- case key.Matches(msg, m.KeyMap.ShowFullHelp):
- fallthrough
- case key.Matches(msg, m.KeyMap.CloseFullHelp):
- m.Help.ShowAll = !m.Help.ShowAll
- m.updatePagination()
- }
- }
-
- cmd := m.delegate.Update(msg, m)
- cmds = append(cmds, cmd)
-
- // Keep the index in bounds when paginating
- itemsOnPage := m.Paginator.ItemsOnPage(len(m.VisibleItems()))
- if m.cursor > itemsOnPage-1 {
- m.cursor = max(0, itemsOnPage-1)
- }
-
- return tea.Batch(cmds...)
-}
-
-// Updates for when a user is in the filter editing interface.
-func (m *Model) handleFiltering(msg tea.Msg) tea.Cmd {
- var cmds []tea.Cmd
-
- // Handle keys
- if msg, ok := msg.(tea.KeyMsg); ok {
- switch {
- case key.Matches(msg, m.KeyMap.CancelWhileFiltering):
- m.resetFiltering()
- m.KeyMap.Filter.SetEnabled(true)
- m.KeyMap.ClearFilter.SetEnabled(false)
-
- case key.Matches(msg, m.KeyMap.AcceptWhileFiltering):
- m.hideStatusMessage()
-
- if len(m.items) == 0 {
- break
- }
-
- h := m.VisibleItems()
-
- // If we've filtered down to nothing, clear the filter
- if len(h) == 0 {
- m.resetFiltering()
- break
- }
-
- m.FilterInput.Blur()
- m.filterState = FilterApplied
- m.updateKeybindings()
-
- if m.FilterInput.Value() == "" {
- m.resetFiltering()
- }
- }
- }
-
- // Update the filter text input component
- newFilterInputModel, inputCmd := m.FilterInput.Update(msg)
- filterChanged := m.FilterInput.Value() != newFilterInputModel.Value()
- m.FilterInput = newFilterInputModel
- cmds = append(cmds, inputCmd)
-
- // If the filtering input has changed, request updated filtering
- if filterChanged {
- cmds = append(cmds, filterItems(*m))
- m.KeyMap.AcceptWhileFiltering.SetEnabled(m.FilterInput.Value() != "")
- }
-
- // Update pagination
- m.updatePagination()
-
- return tea.Batch(cmds...)
-}
-
-// ShortHelp returns bindings to show in the abbreviated help view. It's part
-// of the help.KeyMap interface.
-func (m Model) ShortHelp() []key.Binding {
- kb := []key.Binding{
- m.KeyMap.CursorUp,
- m.KeyMap.CursorDown,
- }
-
- filtering := m.filterState == Filtering
-
- // If the delegate implements the help.KeyMap interface add the short help
- // items to the short help after the cursor movement keys.
- if !filtering {
- if b, ok := m.delegate.(help.KeyMap); ok {
- kb = append(kb, b.ShortHelp()...)
- }
- }
-
- kb = append(kb,
- m.KeyMap.Filter,
- m.KeyMap.ClearFilter,
- m.KeyMap.AcceptWhileFiltering,
- m.KeyMap.CancelWhileFiltering,
- )
-
- if !filtering && m.AdditionalShortHelpKeys != nil {
- kb = append(kb, m.AdditionalShortHelpKeys()...)
- }
-
- return append(kb,
- m.KeyMap.Quit,
- m.KeyMap.ShowFullHelp,
- )
-}
-
-// FullHelp returns bindings to show the full help view. It's part of the
-// help.KeyMap interface.
-func (m Model) FullHelp() [][]key.Binding {
- kb := [][]key.Binding{{
- m.KeyMap.CursorUp,
- m.KeyMap.CursorDown,
- m.KeyMap.NextPage,
- m.KeyMap.PrevPage,
- m.KeyMap.GoToStart,
- m.KeyMap.GoToEnd,
- }}
-
- filtering := m.filterState == Filtering
-
- // If the delegate implements the help.KeyMap interface add full help
- // keybindings to a special section of the full help.
- if !filtering {
- if b, ok := m.delegate.(help.KeyMap); ok {
- kb = append(kb, b.FullHelp()...)
- }
- }
-
- listLevelBindings := []key.Binding{
- m.KeyMap.Filter,
- m.KeyMap.ClearFilter,
- m.KeyMap.AcceptWhileFiltering,
- m.KeyMap.CancelWhileFiltering,
- }
-
- if !filtering && m.AdditionalFullHelpKeys != nil {
- listLevelBindings = append(listLevelBindings, m.AdditionalFullHelpKeys()...)
- }
-
- return append(kb,
- listLevelBindings,
- []key.Binding{
- m.KeyMap.Quit,
- m.KeyMap.CloseFullHelp,
- })
-}
-
-// View renders the component.
-func (m Model) View() string {
- var (
- sections []string
- availHeight = m.height
- )
-
- if m.showTitle || (m.showFilter && m.filteringEnabled) {
- v := m.titleView()
- sections = append(sections, v)
- availHeight -= lipgloss.Height(v)
- }
-
- if m.showStatusBar {
- v := m.statusView()
- sections = append(sections, v)
- availHeight -= lipgloss.Height(v)
- }
-
- var pagination string
- if m.showPagination {
- pagination = m.paginationView()
- availHeight -= lipgloss.Height(pagination)
- }
-
- var help string
- if m.showHelp {
- help = m.helpView()
- availHeight -= lipgloss.Height(help)
- }
-
- content := lipgloss.NewStyle().Height(availHeight).Render(m.populatedView())
- sections = append(sections, content)
-
- if m.showPagination {
- sections = append(sections, pagination)
- }
-
- if m.showHelp {
- sections = append(sections, help)
- }
-
- return lipgloss.JoinVertical(lipgloss.Left, sections...)
-}
-
-func (m Model) titleView() string {
- var (
- view string
- titleBarStyle = m.Styles.TitleBar.Copy()
-
- // We need to account for the size of the spinner, even if we don't
- // render it, to reserve some space for it should we turn it on later.
- spinnerView = m.spinnerView()
- spinnerWidth = lipgloss.Width(spinnerView)
- spinnerLeftGap = " "
- spinnerOnLeft = titleBarStyle.GetPaddingLeft() >= spinnerWidth+lipgloss.Width(spinnerLeftGap) && m.showSpinner
- )
-
- // If the filter's showing, draw that. Otherwise draw the title.
- if m.showFilter && m.filterState == Filtering {
- view += m.FilterInput.View()
- } else if m.showTitle {
- if m.showSpinner && spinnerOnLeft {
- view += spinnerView + spinnerLeftGap
- titleBarGap := titleBarStyle.GetPaddingLeft()
- titleBarStyle = titleBarStyle.PaddingLeft(titleBarGap - spinnerWidth - lipgloss.Width(spinnerLeftGap))
- }
-
- view += m.Styles.Title.Render(m.Title)
-
- // Status message
- if m.filterState != Filtering {
- view += " " + m.statusMessage
- view = truncate.StringWithTail(view, uint(m.width-spinnerWidth), ellipsis)
- }
- }
-
- // Spinner
- if m.showSpinner && !spinnerOnLeft {
- // Place spinner on the right
- availSpace := m.width - lipgloss.Width(m.Styles.TitleBar.Render(view))
- if availSpace > spinnerWidth {
- view += strings.Repeat(" ", availSpace-spinnerWidth)
- view += spinnerView
- }
- }
-
- if len(view) > 0 {
- return titleBarStyle.Render(view)
- }
- return view
-}
-
-func (m Model) statusView() string {
- var status string
-
- totalItems := len(m.items)
- visibleItems := len(m.VisibleItems())
-
- var itemName string
- if visibleItems != 1 {
- itemName = m.itemNamePlural
- } else {
- itemName = m.itemNameSingular
- }
-
- itemsDisplay := fmt.Sprintf("%d %s", visibleItems, itemName)
-
- if m.filterState == Filtering {
- // Filter results
- if visibleItems == 0 {
- status = m.Styles.StatusEmpty.Render("Nothing matched")
- } else {
- status = itemsDisplay
- }
- } else if len(m.items) == 0 {
- // Not filtering: no items.
- status = m.Styles.StatusEmpty.Render("No " + m.itemNamePlural)
- } else {
- // Normal
- filtered := m.FilterState() == FilterApplied
-
- if filtered {
- f := strings.TrimSpace(m.FilterInput.Value())
- f = truncate.StringWithTail(f, 10, "…")
- status += fmt.Sprintf("“%s” ", f)
- }
-
- status += itemsDisplay
- }
-
- numFiltered := totalItems - visibleItems
- if numFiltered > 0 {
- status += m.Styles.DividerDot.String()
- status += m.Styles.StatusBarFilterCount.Render(fmt.Sprintf("%d filtered", numFiltered))
- }
-
- return m.Styles.StatusBar.Render(status)
-}
-
-func (m Model) paginationView() string {
- if m.Paginator.TotalPages < 2 { //nolint:gomnd
- return ""
- }
-
- s := m.Paginator.View()
-
- // If the dot pagination is wider than the width of the window
- // use the arabic paginator.
- if ansi.PrintableRuneWidth(s) > m.width {
- m.Paginator.Type = paginator.Arabic
- s = m.Styles.ArabicPagination.Render(m.Paginator.View())
- }
-
- style := m.Styles.PaginationStyle
- if m.delegate.Spacing() == 0 && style.GetMarginTop() == 0 {
- style = style.Copy().MarginTop(1)
- }
-
- return style.Render(s)
-}
-
-func (m Model) populatedView() string {
- items := m.VisibleItems()
-
- var b strings.Builder
-
- // Empty states
- if len(items) == 0 {
- if m.filterState == Filtering {
- return ""
- }
- return m.Styles.NoItems.Render("No " + m.itemNamePlural + " found.")
- }
-
- if len(items) > 0 {
- start, end := m.Paginator.GetSliceBounds(len(items))
- docs := items[start:end]
-
- for i, item := range docs {
- m.delegate.Render(&b, m, i+start, item)
- if i != len(docs)-1 {
- fmt.Fprint(&b, strings.Repeat("\n", m.delegate.Spacing()+1))
- }
- }
- }
-
- // If there aren't enough items to fill up this page (always the last page)
- // then we need to add some newlines to fill up the space where items would
- // have been.
- itemsOnPage := m.Paginator.ItemsOnPage(len(items))
- if itemsOnPage < m.Paginator.PerPage {
- n := (m.Paginator.PerPage - itemsOnPage) * (m.delegate.Height() + m.delegate.Spacing())
- if len(items) == 0 {
- n -= m.delegate.Height() - 1
- }
- fmt.Fprint(&b, strings.Repeat("\n", n))
- }
-
- return b.String()
-}
-
-func (m Model) helpView() string {
- return m.Styles.HelpStyle.Render(m.Help.View(m))
-}
-
-func (m Model) spinnerView() string {
- return m.spinner.View()
-}
-
-func filterItems(m Model) tea.Cmd {
- return func() tea.Msg {
- if m.FilterInput.Value() == "" || m.filterState == Unfiltered {
- return FilterMatchesMsg(m.itemsAsFilterItems()) // return nothing
- }
-
- targets := []string{}
- items := m.items
-
- for _, t := range items {
- targets = append(targets, t.FilterValue())
- }
-
- filterMatches := []filteredItem{}
- for _, r := range m.Filter(m.FilterInput.Value(), targets) {
- filterMatches = append(filterMatches, filteredItem{
- item: items[r.Index],
- matches: r.MatchedIndexes,
- })
- }
-
- return FilterMatchesMsg(filterMatches)
- }
-}
-
-func insertItemIntoSlice(items []Item, item Item, index int) []Item {
- if items == nil {
- return []Item{item}
- }
- if index >= len(items) {
- return append(items, item)
- }
-
- index = max(0, index)
-
- items = append(items, nil)
- copy(items[index+1:], items[index:])
- items[index] = item
- return items
-}
-
-// Remove an item from a slice of items at the given index. This runs in O(n).
-func removeItemFromSlice(i []Item, index int) []Item {
- if index >= len(i) {
- return i // noop
- }
- copy(i[index:], i[index+1:])
- i[len(i)-1] = nil
- return i[:len(i)-1]
-}
-
-func removeFilterMatchFromSlice(i []filteredItem, index int) []filteredItem {
- if index >= len(i) {
- return i // noop
- }
- copy(i[index:], i[index+1:])
- i[len(i)-1] = filteredItem{}
- return i[:len(i)-1]
-}
-
-func countEnabledBindings(groups [][]key.Binding) (agg int) {
- for _, group := range groups {
- for _, kb := range group {
- if kb.Enabled() {
- agg++
- }
- }
- }
- return agg
-}
-
-func max(a, b int) int {
- if a > b {
- return a
- }
- return b
-}
diff --git a/vendor/github.com/charmbracelet/bubbles/list/style.go b/vendor/github.com/charmbracelet/bubbles/list/style.go
deleted file mode 100644
index e4451f8..0000000
--- a/vendor/github.com/charmbracelet/bubbles/list/style.go
+++ /dev/null
@@ -1,99 +0,0 @@
-package list
-
-import (
- "github.com/charmbracelet/lipgloss"
-)
-
-const (
- bullet = "•"
- ellipsis = "…"
-)
-
-// Styles contains style definitions for this list component. By default, these
-// values are generated by DefaultStyles.
-type Styles struct {
- TitleBar lipgloss.Style
- Title lipgloss.Style
- Spinner lipgloss.Style
- FilterPrompt lipgloss.Style
- FilterCursor lipgloss.Style
-
- // Default styling for matched characters in a filter. This can be
- // overridden by delegates.
- DefaultFilterCharacterMatch lipgloss.Style
-
- StatusBar lipgloss.Style
- StatusEmpty lipgloss.Style
- StatusBarActiveFilter lipgloss.Style
- StatusBarFilterCount lipgloss.Style
-
- NoItems lipgloss.Style
-
- PaginationStyle lipgloss.Style
- HelpStyle lipgloss.Style
-
- // Styled characters.
- ActivePaginationDot lipgloss.Style
- InactivePaginationDot lipgloss.Style
- ArabicPagination lipgloss.Style
- DividerDot lipgloss.Style
-}
-
-// 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"}
-
- s.TitleBar = lipgloss.NewStyle().Padding(0, 0, 1, 2)
-
- s.Title = lipgloss.NewStyle().
- Background(lipgloss.Color("62")).
- Foreground(lipgloss.Color("230")).
- Padding(0, 1)
-
- s.Spinner = lipgloss.NewStyle().
- Foreground(lipgloss.AdaptiveColor{Light: "#8E8E8E", Dark: "#747373"})
-
- s.FilterPrompt = lipgloss.NewStyle().
- Foreground(lipgloss.AdaptiveColor{Light: "#04B575", Dark: "#ECFD65"})
-
- s.FilterCursor = lipgloss.NewStyle().
- Foreground(lipgloss.AdaptiveColor{Light: "#EE6FF8", Dark: "#EE6FF8"})
-
- s.DefaultFilterCharacterMatch = lipgloss.NewStyle().Underline(true)
-
- s.StatusBar = lipgloss.NewStyle().
- Foreground(lipgloss.AdaptiveColor{Light: "#A49FA5", Dark: "#777777"}).
- Padding(0, 0, 1, 2)
-
- s.StatusEmpty = lipgloss.NewStyle().Foreground(subduedColor)
-
- s.StatusBarActiveFilter = lipgloss.NewStyle().
- Foreground(lipgloss.AdaptiveColor{Light: "#1a1a1a", Dark: "#dddddd"})
-
- s.StatusBarFilterCount = lipgloss.NewStyle().Foreground(verySubduedColor)
-
- s.NoItems = lipgloss.NewStyle().
- Foreground(lipgloss.AdaptiveColor{Light: "#909090", Dark: "#626262"})
-
- s.ArabicPagination = lipgloss.NewStyle().Foreground(subduedColor)
-
- s.PaginationStyle = lipgloss.NewStyle().PaddingLeft(2) //nolint:gomnd
-
- s.HelpStyle = lipgloss.NewStyle().Padding(1, 0, 0, 2)
-
- s.ActivePaginationDot = lipgloss.NewStyle().
- Foreground(lipgloss.AdaptiveColor{Light: "#847A85", Dark: "#979797"}).
- SetString(bullet)
-
- s.InactivePaginationDot = lipgloss.NewStyle().
- Foreground(verySubduedColor).
- SetString(bullet)
-
- s.DividerDot = lipgloss.NewStyle().
- Foreground(verySubduedColor).
- SetString(" " + bullet + " ")
-
- return s
-}
diff --git a/vendor/github.com/charmbracelet/bubbles/paginator/paginator.go b/vendor/github.com/charmbracelet/bubbles/paginator/paginator.go
deleted file mode 100644
index a84819a..0000000
--- a/vendor/github.com/charmbracelet/bubbles/paginator/paginator.go
+++ /dev/null
@@ -1,202 +0,0 @@
-// Package paginator provides a Bubble Tea package for calulating pagination
-// and rendering pagination info. Note that this package does not render actual
-// pages: it's purely for handling keystrokes related to pagination, and
-// rendering pagination status.
-package paginator
-
-import (
- "fmt"
-
- tea "github.com/charmbracelet/bubbletea"
-)
-
-// Type specifies the way we render pagination.
-type Type int
-
-// Pagination rendering options.
-const (
- Arabic Type = iota
- Dots
-)
-
-// Model is the Bubble Tea model for this user interface.
-type Model struct {
- Type Type
- Page int
- PerPage int
- TotalPages int
- ActiveDot string
- InactiveDot string
- ArabicFormat string
- UsePgUpPgDownKeys bool
- UseLeftRightKeys bool
- UseUpDownKeys bool
- UseHLKeys bool
- UseJKKeys bool
-}
-
-// SetTotalPages is a helper function for calculating the total number of pages
-// from a given number of items. It's use is optional since this pager can be
-// used for other things beyond navigating sets. Note that it both returns the
-// number of total pages and alters the model.
-func (m *Model) SetTotalPages(items int) int {
- if items < 1 {
- return m.TotalPages
- }
- n := items / m.PerPage
- if items%m.PerPage > 0 {
- n++
- }
- m.TotalPages = n
- return n
-}
-
-// ItemsOnPage is a helper function for returning the numer of items on the
-// current page given the total numer of items passed as an argument.
-func (m Model) ItemsOnPage(totalItems int) int {
- if totalItems < 1 {
- return 0
- }
- start, end := m.GetSliceBounds(totalItems)
- return end - start
-}
-
-// GetSliceBounds is a helper function for paginating slices. Pass the length
-// of the slice you're rendering and you'll receive the start and end bounds
-// corresponding the to pagination. For example:
-//
-// bunchOfStuff := []stuff{...}
-// start, end := model.GetSliceBounds(len(bunchOfStuff))
-// sliceToRender := bunchOfStuff[start:end]
-//
-func (m *Model) GetSliceBounds(length int) (start int, end int) {
- start = m.Page * m.PerPage
- end = min(m.Page*m.PerPage+m.PerPage, length)
- return start, end
-}
-
-// PrevPage is a number function for navigating one page backward. It will not
-// page beyond the first page (i.e. page 0).
-func (m *Model) PrevPage() {
- if m.Page > 0 {
- m.Page--
- }
-}
-
-// NextPage is a helper function for navigating one page forward. It will not
-// page beyond the last page (i.e. totalPages - 1).
-func (m *Model) NextPage() {
- if !m.OnLastPage() {
- m.Page++
- }
-}
-
-// OnLastPage returns whether or not we're on the last page.
-func (m Model) OnLastPage() bool {
- return m.Page == m.TotalPages-1
-}
-
-// New creates a new model with defaults.
-func New() Model {
- return Model{
- Type: Arabic,
- Page: 0,
- PerPage: 1,
- TotalPages: 1,
- ActiveDot: "•",
- InactiveDot: "○",
- ArabicFormat: "%d/%d",
- UsePgUpPgDownKeys: true,
- UseLeftRightKeys: true,
- UseUpDownKeys: false,
- UseHLKeys: true,
- UseJKKeys: false,
- }
-}
-
-// NewModel creates a new model with defaults.
-//
-// Deprecated. Use New instead.
-var NewModel = New
-
-// 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) {
- case tea.KeyMsg:
- if m.UsePgUpPgDownKeys {
- switch msg.String() {
- case "pgup":
- m.PrevPage()
- case "pgdown":
- m.NextPage()
- }
- }
- if m.UseLeftRightKeys {
- switch msg.String() {
- case "left":
- m.PrevPage()
- case "right":
- m.NextPage()
- }
- }
- if m.UseUpDownKeys {
- switch msg.String() {
- case "up":
- m.PrevPage()
- case "down":
- m.NextPage()
- }
- }
- if m.UseHLKeys {
- switch msg.String() {
- case "h":
- m.PrevPage()
- case "l":
- m.NextPage()
- }
- }
- if m.UseJKKeys {
- switch msg.String() {
- case "j":
- m.PrevPage()
- case "k":
- m.NextPage()
- }
- }
- }
-
- return m, nil
-}
-
-// View renders the pagination to a string.
-func (m Model) View() string {
- switch m.Type {
- case Dots:
- return m.dotsView()
- default:
- return m.arabicView()
- }
-}
-
-func (m Model) dotsView() string {
- var s string
- for i := 0; i < m.TotalPages; i++ {
- if i == m.Page {
- s += m.ActiveDot
- continue
- }
- s += m.InactiveDot
- }
- return s
-}
-
-func (m Model) arabicView() string {
- return fmt.Sprintf(m.ArabicFormat, m.Page+1, m.TotalPages)
-}
-
-func min(a, b int) int {
- if a < b {
- return a
- }
- return b
-}
diff --git a/vendor/github.com/charmbracelet/bubbletea/README.md b/vendor/github.com/charmbracelet/bubbletea/README.md
index fe1b5cf..3bad838 100644
--- a/vendor/github.com/charmbracelet/bubbletea/README.md
+++ b/vendor/github.com/charmbracelet/bubbletea/README.md
@@ -316,51 +316,58 @@ your program in another window.
For some Bubble Tea programs in production, see:
-* [AT CLI](https://github.com/daskycodes/at_cli): a utility for executing AT Commands via serial port connections
+* [AT CLI](https://github.com/daskycodes/at_cli): execute AT Commands via serial port connections
* [Aztify](https://github.com/Azure/aztfy): bring Microsoft Azure resources under Terraform
+* [brows](https://github.com/rubysolo/brows): a GitHub release browser
* [Canard](https://github.com/mrusme/canard): an RSS client
* [charm](https://github.com/charmbracelet/charm): the official Charm user account manager
-* [chezmoi](https://github.com/twpayne/chezmoi): manage your dotfiles across multiple machines, securely
-* [circumflex](https://github.com/bensadeh/circumflex): read Hacker News in your terminal
-* [clidle](https://github.com/ajeetdsouza/clidle): a Wordle clone for your terminal
+* [chezmoi](https://github.com/twpayne/chezmoi): securely manage your dotfiles across multiple machines
+* [chtop](https://github.com/chhetripradeep/chtop): monitor your ClickHouse node without leaving terminal
+* [circumflex](https://github.com/bensadeh/circumflex): read Hacker News in the terminal
+* [clidle](https://github.com/ajeetdsouza/clidle): a Wordle clone
+* [cLive](https://github.com/koki-develop/clive): automate terminal operations and view them live in a browser
* [container-canary](https://github.com/NVIDIA/container-canary): a container validator
-* [dns53](https://github.com/purpleclay/dns53): dynamic DNS with Amazon Route53. Expose your EC2 quickly, securely and privately
+* [dns53](https://github.com/purpleclay/dns53): dynamic DNS with Amazon Route53: expose your EC2 quickly, securely and privately
+* [enola](https://github.com/sherlock-project/enola): hunt down social media accounts by username across social networks
* [flapioca](https://github.com/kbrgl/flapioca): Flappy Bird on the CLI!
* [fm](https://github.com/knipferrc/fm): a terminal-based file manager
-* [fork-cleaner](https://github.com/caarlos0/fork-cleaner): cleans up old and inactive forks in your GitHub account
-* [fztea](https://github.com/jon4hz/fztea): connect to your Flipper's UI over serial or make it accessible via SSH
-* [gambit](https://github.com/maaslalani/gambit): play chess in the terminal
+* [fork-cleaner](https://github.com/caarlos0/fork-cleaner): clean up old and inactive forks in your GitHub account
+* [fztea](https://github.com/jon4hz/fztea): a Flipper Zero TUI
+* [gambit](https://github.com/maaslalani/gambit): chess in the terminal
* [gembro](https://git.sr.ht/~rafael/gembro): a mouse-driven Gemini browser
-* [gh-b](https://github.com/joaom00/gh-b): GitHub CLI extension to easily manage your branches
-* [gh-dash](https://www.github.com/dlvhdr/gh-dash): GitHub CLI extension to display a dashboard of PRs and issues
+* [gh-b](https://github.com/joaom00/gh-b): a GitHub CLI extension for managing branches
+* [gh-dash](https://www.github.com/dlvhdr/gh-dash): a GitHub CLI extension for PRs and issues
* [gitflow-toolkit](https://github.com/mritd/gitflow-toolkit): a GitFlow submission tool
-* [Glow](https://github.com/charmbracelet/glow): a markdown reader, browser and online markdown stash
+* [Glow](https://github.com/charmbracelet/glow): a markdown reader, browser, and online markdown stash
* [gocovsh](https://github.com/orlangure/gocovsh): explore Go coverage reports from the CLI
* [got](https://github.com/fedeztk/got): a simple translator and text-to-speech app build on top of simplytranslate's APIs
* [httpit](https://github.com/gonetx/httpit): a rapid http(s) benchmark tool
-* [IDNT](https://github.com/r-darwish/idnt): batch software uninstaller
+* [IDNT](https://github.com/r-darwish/idnt): a batch software uninstaller
* [kboard](https://github.com/CamiloGarciaLaRotta/kboard): a typing game
-* [mandelbrot-cli](https://github.com/MicheleFiladelfia/mandelbrot-cli): Multiplatform terminal mandelbrot set explorer
+* [mandelbrot-cli](https://github.com/MicheleFiladelfia/mandelbrot-cli): a multiplatform terminal mandelbrot set explorer
* [mc](https://github.com/minio/mc): the official [MinIO](https://min.io) client
* [mergestat](https://github.com/mergestat/mergestat): run SQL queries on git repositories
-* [Noted](https://github.com/torbratsberg/noted): Note viewer and manager
-* [pathos](https://github.com/chip/pathos): pathos - CLI for editing a PATH env variable
-* [portal](https://github.com/ZinoKader/portal): securely send transfer between computers
-* [redis-viewer](https://github.com/SaltFishPr/redis-viewer): browse Redis databases
-* [sku](https://github.com/fedeztk/sku): a simple TUI for playing sudoku inside the terminal
+* [Neon Modem Overdrive](https://github.com/mrusme/neonmodem): a BBS-style TUI client for Discourse, Lemmy, Lobste.rs and Hacker News
+* [Noted](https://github.com/torbratsberg/noted): a note viewer and manager
+* [pathos](https://github.com/chip/pathos): a PATH env variable editor
+* [portal](https://github.com/ZinoKader/portal): secure transfers between computers
+* [redis-viewer](https://github.com/SaltFishPr/redis-viewer): a Redis databases browser
+* [sku](https://github.com/fedeztk/sku): Sudoku on the CLI
* [Slides](https://github.com/maaslalani/slides): a markdown-based presentation tool
+* [SlurmCommander](https://github.com/CLIP-HPC/SlurmCommander): a Slurm workload manager TUI
* [Soft Serve](https://github.com/charmbracelet/soft-serve): a command-line-first Git server that runs a TUI over SSH
+* [solitaire-tui](https://github.com/brianstrauch/solitaire-tui): Klondike Solitaire for the terminal
* [StormForge Optimize Controller](https://github.com/thestormforge/optimize-controller): a tool for experimenting with application configurations in Kubernetes
-* [STTG](https://github.com/wille1101/sttg): teletext client for SVT, Sweden’s national public television station
-* [sttr](https://github.com/abhimanyu003/sttr): run various text transformations
+* [STTG](https://github.com/wille1101/sttg): a teletext client for SVT, Sweden’s national public television station
+* [sttr](https://github.com/abhimanyu003/sttr): a general-purpose text transformer
* [tasktimer](https://github.com/caarlos0/tasktimer): a dead-simple task timer
* [termdbms](https://github.com/mathaou/termdbms): a keyboard and mouse driven database browser
-* [ticker](https://github.com/achannarasappa/ticker): a terminal stock watcher and stock position tracker
-* [tran](https://github.com/abdfnx/tran): securely transfer stuff between computers (based on [portal][portal])
+* [ticker](https://github.com/achannarasappa/ticker): a terminal stock viewer and stock position tracker
+* [tran](https://github.com/abdfnx/tran): securely transfer stuff between computers (based on [portal][https://github.com/ZinoKader/portal])
* [Typer](https://github.com/maaslalani/typer): a typing test
* [tz](https://github.com/oz/tz): an aid for scheduling across multiple time zones
* [ugm](https://github.com/ariasmn/ugm): a unix user and group browser
-* [wander](https://github.com/robinovitch61/wander): HashiCorp Nomad terminal client
+* [wander](https://github.com/robinovitch61/wander): a HashiCorp Nomad terminal client
* [wishlist](https://github.com/charmbracelet/wishlist): an SSH directory
## Feedback
diff --git a/vendor/github.com/charmbracelet/bubbletea/tea.go b/vendor/github.com/charmbracelet/bubbletea/tea.go
index 03734bc..f5f452b 100644
--- a/vendor/github.com/charmbracelet/bubbletea/tea.go
+++ b/vendor/github.com/charmbracelet/bubbletea/tea.go
@@ -24,6 +24,7 @@ import (
isatty "github.com/mattn/go-isatty"
"github.com/muesli/cancelreader"
"github.com/muesli/termenv"
+ "golang.org/x/sync/errgroup"
)
// ErrProgramKilled is returned by [Program.Run] when the program got killed.
@@ -310,7 +311,25 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
go func() {
// Execute commands one at a time, in order.
for _, cmd := range msg {
- p.Send(cmd())
+ if cmd == nil {
+ continue
+ }
+ msg := cmd()
+ if batchMsg, ok := msg.(BatchMsg); ok {
+ g, _ := errgroup.WithContext(p.ctx)
+ for _, cmd := range batchMsg {
+ cmd := cmd
+ g.Go(func() error {
+ p.Send(cmd())
+ return nil
+ })
+ }
+ //nolint:errcheck
+ g.Wait() // wait for all commands from batch msg to finish
+ continue
+ } else {
+ p.Send(msg)
+ }
}
}()
}
diff --git a/vendor/github.com/muesli/termenv/README.md b/vendor/github.com/muesli/termenv/README.md
index 1fc63dd..29dcf01 100644
--- a/vendor/github.com/muesli/termenv/README.md
+++ b/vendor/github.com/muesli/termenv/README.md
@@ -248,6 +248,15 @@ output.HideCursor()
// Show the cursor
output.ShowCursor()
+
+// Copy to clipboard
+output.Copy(message)
+
+// Copy to primary clipboard (X11)
+output.CopyPrimary(message)
+
+// Trigger notification
+output.Notify(title, body)
```
## Mouse
@@ -294,30 +303,72 @@ termenv.EnableBracketedPaste()
termenv.DisableBracketedPaste()
```
-## Optional Feature Support
-
-| Terminal | Alt Screen | Query Color Scheme | Query Cursor Position | Set Window Title | Change Cursor Color | Change Default Foreground Setting | Change Default Background Setting | Copy (OSC52) | Hyperlinks (OSC8) | Bracketed Paste |
-| ---------------- | :--------: | :----------------: | :-------------------: | :--------------: | :-----------------: | :-------------------------------: | :-------------------------------: | :----------: | :---------------: | :-------------: |
-| alacritty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌[^alacritty] | ✅ |
-| foot | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
-| kitty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
-| Konsole | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌[^konsole] | ✅ | ✅ |
-| rxvt | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ |
-| urxvt | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅[^urxvt] | ❌ | ✅ |
-| screen | ✅ | ⛔[^mux] | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌[^screen] | ❌ |
-| st | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
-| tmux | ✅ | ⛔[^mux] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌[^tmux] | ✅ |
-| vte-based[^vte] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌[^vte] | ✅ | ✅ |
-| wezterm | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
-| xterm | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ |
-| Linux Console | ✅ | ❌ | ✅ | ⛔ | ❌ | ❌ | ❌ | ⛔ | ⛔ | ❌ |
-| Apple Terminal | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅[^apple] | ❌ | ✅ |
-| iTerm | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
-| Windows cmd | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
-| Windows Terminal | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
+## Terminal Feature Support
-[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal. OSC52 is not supported, see [issue#2495](https://gitlab.gnome.org/GNOME/vte/-/issues/2495).
+### Color Support
+
+- 24-bit (RGB): alacritty, foot, iTerm, kitty, Konsole, st, tmux, vte-based, wezterm, Windows Terminal
+- 8-bit (256): rxvt, screen, xterm, Apple Terminal
+- 4-bit (16): Linux Console
+
+### Control Sequences
+
+
+Click to show feature matrix
+
+| Terminal | Query Color Scheme | Query Cursor Position | Set Window Title | Change Cursor Color | Change Default Foreground Setting | Change Default Background Setting | Bracketed Paste | Extended Mouse (SGR) | Pixels Mouse (SGR-Pixels) |
+| ---------------- | :----------------: | :-------------------: | :--------------: | :-----------------: | :-------------------------------: | :-------------------------------: | :-------------: | :------------------: | :-----------------------: |
+| alacritty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
+| foot | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
+| kitty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
+| Konsole | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
+| rxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
+| urxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
+| screen | ⛔[^mux] | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
+| st | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
+| tmux | ⛔[^mux] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
+| vte-based[^vte] | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ |
+| wezterm | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
+| xterm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
+| Linux Console | ❌ | ✅ | ⛔ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
+| Apple Terminal | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
+| iTerm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
+| Windows cmd | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
+| Windows Terminal | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
+
+[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal.
[^mux]: Unavailable as multiplexers (like tmux or screen) can be connected to multiple terminals (with different color settings) at the same time.
+
+You can help improve this list! Check out [how to](ansi_compat.md) and open an issue or pull request.
+
+
+
+### System Commands
+
+
+Click to show feature matrix
+
+| Terminal | Copy to Clipboard (OSC52) | Hyperlinks (OSC8) | Notifications (OSC777) |
+| ---------------- | :-----------------------: | :---------------: | :--------------------: |
+| alacritty | ✅ | ❌[^alacritty] | ❌ |
+| foot | ✅ | ✅ | ✅ |
+| kitty | ✅ | ✅ | ✅ |
+| Konsole | ❌[^konsole] | ✅ | ❌ |
+| rxvt | ❌ | ❌ | ❌ |
+| urxvt | ✅[^urxvt] | ❌ | ✅ |
+| screen | ✅ | ❌[^screen] | ❌ |
+| st | ✅ | ❌ | ❌ |
+| tmux | ✅ | ❌[^tmux] | ❌ |
+| vte-based[^vte] | ❌[^vte] | ✅ | ❌ |
+| wezterm | ✅ | ✅ | ❌ |
+| xterm | ✅ | ❌ | ❌ |
+| Linux Console | ⛔ | ⛔ | ❌ |
+| Apple Terminal | ✅[^apple] | ❌ | ❌ |
+| iTerm | ✅ | ✅ | ❌ |
+| Windows cmd | ❌ | ❌ | ❌ |
+| Windows Terminal | ✅ | ✅ | ❌ |
+
+[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal. OSC52 is not supported, see [issue#2495](https://gitlab.gnome.org/GNOME/vte/-/issues/2495).
[^urxvt]: Workaround for urxvt not supporting OSC52. See [this](https://unix.stackexchange.com/a/629485) for more information.
[^konsole]: OSC52 is not supported, for more info see [bug#372116](https://bugs.kde.org/show_bug.cgi?id=372116).
[^apple]: OSC52 works with a [workaround](https://github.com/roy2220/osc52pty).
@@ -325,13 +376,7 @@ termenv.DisableBracketedPaste()
[^screen]: OSC8 is not supported, for more info see [bug#50952](https://savannah.gnu.org/bugs/index.php?50952).
[^alacritty]: OSC8 is not supported, for more info see [issue#922](https://github.com/alacritty/alacritty/issues/922).
-You can help improve this list! Check out [how to](ansi_compat.md) and open an issue or pull request.
-
-### Color Support
-
-- 24-bit (RGB): alacritty, foot, iTerm, kitty, Konsole, st, tmux, vte-based, wezterm, Windows Terminal
-- 8-bit (256): rxvt, screen, xterm, Apple Terminal
-- 4-bit (16): Linux Console
+
## Platform Support
@@ -350,7 +395,6 @@ you need to enable ANSI processing in your application first:
The above code is safe to include on non-Windows systems or when os.Stdout does
not refer to a terminal (e.g. in tests).
-
## Color Chart
![ANSI color chart](https://github.com/muesli/termenv/raw/master/examples/color-chart/color-chart.png)
diff --git a/vendor/github.com/muesli/termenv/ansi_compat.md b/vendor/github.com/muesli/termenv/ansi_compat.md
index b403d74..6b68a3a 100644
--- a/vendor/github.com/muesli/termenv/ansi_compat.md
+++ b/vendor/github.com/muesli/termenv/ansi_compat.md
@@ -55,3 +55,11 @@ displayed on the terminal should contain the codes `200~` and `201~`:
```bash
echo -ne "\033[?2004h" && sleep 10
```
+
+## Trigger Notification
+
+This command should trigger a notification:
+
+```bash
+echo -ne "\033]777;notify;Title;Body\033\\"
+```
diff --git a/vendor/github.com/muesli/termenv/color.go b/vendor/github.com/muesli/termenv/color.go
index 885ad51..0d11f43 100644
--- a/vendor/github.com/muesli/termenv/color.go
+++ b/vendor/github.com/muesli/termenv/color.go
@@ -117,12 +117,12 @@ func xTermColor(s string) (RGBColor, error) {
}
switch {
- case strings.HasSuffix(s, "\a"):
- s = strings.TrimSuffix(s, "\a")
- case strings.HasSuffix(s, "\033"):
- s = strings.TrimSuffix(s, "\033")
- case strings.HasSuffix(s, "\033\\"):
- s = strings.TrimSuffix(s, "\033\\")
+ case strings.HasSuffix(s, string(BEL)):
+ s = strings.TrimSuffix(s, string(BEL))
+ case strings.HasSuffix(s, string(ESC)):
+ s = strings.TrimSuffix(s, string(ESC))
+ case strings.HasSuffix(s, ST):
+ s = strings.TrimSuffix(s, ST)
default:
return RGBColor(""), ErrInvalidColor
}
diff --git a/vendor/github.com/muesli/termenv/copy.go b/vendor/github.com/muesli/termenv/copy.go
index 5c975d9..f65f5b6 100644
--- a/vendor/github.com/muesli/termenv/copy.go
+++ b/vendor/github.com/muesli/termenv/copy.go
@@ -4,13 +4,28 @@ import (
"github.com/aymanbagabas/go-osc52"
)
+func (o Output) osc52Output() *osc52.Output {
+ return osc52.NewOutput(o.tty, o.environ.Environ())
+}
+
// Copy copies text to clipboard using OSC 52 escape sequence.
func (o Output) Copy(str string) {
- out := osc52.NewOutput(o.tty, o.environ.Environ())
- out.Copy(str)
+ o.osc52Output().Copy(str)
+}
+
+// CopyPrimary copies text to primary clipboard (X11) using OSC 52 escape
+// sequence.
+func (o Output) CopyPrimary(str string) {
+ o.osc52Output().CopyPrimary(str)
}
// Copy copies text to clipboard using OSC 52 escape sequence.
func Copy(str string) {
output.Copy(str)
}
+
+// CopyPrimary copies text to primary clipboard (X11) using OSC 52 escape
+// sequence.
+func CopyPrimary(str string) {
+ output.CopyPrimary(str)
+}
diff --git a/vendor/github.com/muesli/termenv/hyperlink.go b/vendor/github.com/muesli/termenv/hyperlink.go
index 9d45450..97e760a 100644
--- a/vendor/github.com/muesli/termenv/hyperlink.go
+++ b/vendor/github.com/muesli/termenv/hyperlink.go
@@ -1,9 +1,5 @@
package termenv
-import (
- "fmt"
-)
-
// Hyperlink creates a hyperlink using OSC8.
func Hyperlink(link, name string) string {
return output.Hyperlink(link, name)
@@ -11,5 +7,5 @@ func Hyperlink(link, name string) string {
// Hyperlink creates a hyperlink using OSC8.
func (o *Output) Hyperlink(link, name string) string {
- return fmt.Sprintf("\x1b]8;;%s\x1b\\%s\x1b]8;;\x1b\\", link, name)
+ return OSC + "8;;" + link + ST + name + OSC + "8;;" + ST
}
diff --git a/vendor/github.com/muesli/termenv/notification.go b/vendor/github.com/muesli/termenv/notification.go
new file mode 100644
index 0000000..2a8cf06
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/notification.go
@@ -0,0 +1,11 @@
+package termenv
+
+// Notify triggers a notification using OSC777.
+func Notify(title, body string) {
+ output.Notify(title, body)
+}
+
+// Notify triggers a notification using OSC777.
+func (o *Output) Notify(title, body string) {
+ _, _ = o.WriteString(OSC + "777;notify;" + title + ";" + body + ST)
+}
diff --git a/vendor/github.com/muesli/termenv/output.go b/vendor/github.com/muesli/termenv/output.go
index 5477892..37a0db9 100644
--- a/vendor/github.com/muesli/termenv/output.go
+++ b/vendor/github.com/muesli/termenv/output.go
@@ -8,7 +8,7 @@ import (
var (
// output is the default global output.
- output = NewOutput(os.Stdout)
+ output = NewOutput(nil)
)
// File represents a file descriptor.
@@ -17,12 +17,16 @@ type File interface {
Fd() uintptr
}
+// OutputOption sets an option on Output.
+type OutputOption = func(*Output)
+
// Output is a terminal output.
type Output struct {
Profile
tty io.Writer
environ Environ
+ unsafe bool
cache bool
fgSync *sync.Once
fgColor Color
@@ -52,7 +56,7 @@ func DefaultOutput() *Output {
}
// NewOutput returns a new Output for the given file descriptor.
-func NewOutput(tty io.Writer, opts ...func(*Output)) *Output {
+func NewOutput(tty io.Writer, opts ...OutputOption) *Output {
o := &Output{
tty: tty,
environ: &osEnviron{},
@@ -69,19 +73,22 @@ func NewOutput(tty io.Writer, opts ...func(*Output)) *Output {
if o.Profile < 0 {
o.Profile = o.EnvColorProfile()
}
+ if o.tty == nil {
+ o.tty = os.Stdout
+ }
return o
}
// WithEnvironment returns a new Output for the given environment.
-func WithEnvironment(environ Environ) func(*Output) {
+func WithEnvironment(environ Environ) OutputOption {
return func(o *Output) {
o.environ = environ
}
}
// WithProfile returns a new Output for the given profile.
-func WithProfile(profile Profile) func(*Output) {
+func WithProfile(profile Profile) OutputOption {
return func(o *Output) {
o.Profile = profile
}
@@ -89,7 +96,7 @@ func WithProfile(profile Profile) func(*Output) {
// WithColorCache returns a new Output with fore- and background color values
// pre-fetched and cached.
-func WithColorCache(v bool) func(*Output) {
+func WithColorCache(v bool) OutputOption {
return func(o *Output) {
o.cache = v
@@ -99,6 +106,17 @@ func WithColorCache(v bool) func(*Output) {
}
}
+// WithUnsafe returns a new Output with unsafe mode enabled. Unsafe mode doesn't
+// check whether or not the terminal is a TTY.
+//
+// This is useful when mocking console output and enforcing ANSI escape output
+// e.g. on SSH sessions.
+func WithUnsafe() OutputOption {
+ return func(o *Output) {
+ o.unsafe = true
+ }
+}
+
// ForegroundColor returns the terminal's default foreground color.
func (o *Output) ForegroundColor() Color {
f := func() {
diff --git a/vendor/github.com/muesli/termenv/screen.go b/vendor/github.com/muesli/termenv/screen.go
index 1bd3307..a71181b 100644
--- a/vendor/github.com/muesli/termenv/screen.go
+++ b/vendor/github.com/muesli/termenv/screen.go
@@ -32,16 +32,20 @@ const (
EraseEntireLineSeq = "2K"
// Mouse.
- EnableMousePressSeq = "?9h" // press only (X10)
- DisableMousePressSeq = "?9l"
- EnableMouseSeq = "?1000h" // press, release, wheel
- DisableMouseSeq = "?1000l"
- EnableMouseHiliteSeq = "?1001h" // highlight
- DisableMouseHiliteSeq = "?1001l"
- EnableMouseCellMotionSeq = "?1002h" // press, release, move on pressed, wheel
- DisableMouseCellMotionSeq = "?1002l"
- EnableMouseAllMotionSeq = "?1003h" // press, release, move, wheel
- DisableMouseAllMotionSeq = "?1003l"
+ EnableMousePressSeq = "?9h" // press only (X10)
+ DisableMousePressSeq = "?9l"
+ EnableMouseSeq = "?1000h" // press, release, wheel
+ DisableMouseSeq = "?1000l"
+ EnableMouseHiliteSeq = "?1001h" // highlight
+ DisableMouseHiliteSeq = "?1001l"
+ EnableMouseCellMotionSeq = "?1002h" // press, release, move on pressed, wheel
+ DisableMouseCellMotionSeq = "?1002l"
+ EnableMouseAllMotionSeq = "?1003h" // press, release, move, wheel
+ DisableMouseAllMotionSeq = "?1003l"
+ EnableMouseExtendedModeSeq = "?1006h" // press, release, move, wheel, extended coordinates
+ DisableMouseExtendedModeSeq = "?1006l"
+ EnableMousePixelsModeSeq = "?1016h" // press, release, move, wheel, extended pixel coordinates
+ DisableMousePixelsModeSeq = "?1016l"
// Screen.
RestoreScreenSeq = "?47l"
@@ -57,10 +61,10 @@ const (
EndBracketedPasteSeq = "201~"
// Session.
- SetWindowTitleSeq = "2;%s\007"
- SetForegroundColorSeq = "10;%s\007"
- SetBackgroundColorSeq = "11;%s\007"
- SetCursorColorSeq = "12;%s\007"
+ SetWindowTitleSeq = "2;%s" + string(BEL)
+ SetForegroundColorSeq = "10;%s" + string(BEL)
+ SetBackgroundColorSeq = "11;%s" + string(BEL)
+ SetCursorColorSeq = "12;%s" + string(BEL)
ShowCursorSeq = "?25h"
HideCursorSeq = "?25l"
)
@@ -259,6 +263,29 @@ func (o Output) DisableMouseAllMotion() {
fmt.Fprint(o.tty, CSI+DisableMouseAllMotionSeq)
}
+// EnableMouseExtendedMotion enables Extended Mouse mode (SGR). This should be
+// enabled in conjunction with EnableMouseCellMotion, and EnableMouseAllMotion.
+func (o Output) EnableMouseExtendedMode() {
+ fmt.Fprint(o.tty, CSI+EnableMouseExtendedModeSeq)
+}
+
+// DisableMouseExtendedMotion disables Extended Mouse mode (SGR).
+func (o Output) DisableMouseExtendedMode() {
+ fmt.Fprint(o.tty, CSI+DisableMouseExtendedModeSeq)
+}
+
+// EnableMousePixelsMotion enables Pixel Motion Mouse mode (SGR-Pixels). This
+// should be enabled in conjunction with EnableMouseCellMotion, and
+// EnableMouseAllMotion.
+func (o Output) EnableMousePixelsMode() {
+ fmt.Fprint(o.tty, CSI+EnableMousePixelsModeSeq)
+}
+
+// DisableMousePixelsMotion disables Pixel Motion Mouse mode (SGR-Pixels).
+func (o Output) DisableMousePixelsMode() {
+ fmt.Fprint(o.tty, CSI+DisableMousePixelsModeSeq)
+}
+
// SetWindowTitle sets the terminal window title.
func (o Output) SetWindowTitle(title string) {
fmt.Fprintf(o.tty, OSC+SetWindowTitleSeq, title)
diff --git a/vendor/github.com/muesli/termenv/termenv.go b/vendor/github.com/muesli/termenv/termenv.go
index 5031f03..e39ccc5 100644
--- a/vendor/github.com/muesli/termenv/termenv.go
+++ b/vendor/github.com/muesli/termenv/termenv.go
@@ -12,13 +12,22 @@ var (
)
const (
+ // Escape character
+ ESC = '\x1b'
+ // Bell
+ BEL = '\a'
// Control Sequence Introducer
- CSI = "\x1b["
+ CSI = string(ESC) + "["
// Operating System Command
- OSC = "\x1b]"
+ OSC = string(ESC) + "]"
+ // String Terminator
+ ST = string(ESC) + `\`
)
func (o *Output) isTTY() bool {
+ if o.unsafe {
+ return true
+ }
if len(o.environ.Getenv("CI")) > 0 {
return false
}
diff --git a/vendor/github.com/muesli/termenv/termenv_other.go b/vendor/github.com/muesli/termenv/termenv_other.go
index 3c4b703..93a43b6 100644
--- a/vendor/github.com/muesli/termenv/termenv_other.go
+++ b/vendor/github.com/muesli/termenv/termenv_other.go
@@ -3,7 +3,11 @@
package termenv
-func colorProfile() Profile {
+import "io"
+
+// ColorProfile returns the supported color profile:
+// ANSI256
+func (o Output) ColorProfile() Profile {
return ANSI256
}
@@ -16,3 +20,11 @@ func (o Output) backgroundColor() Color {
// default black
return ANSIColor(0)
}
+
+// EnableVirtualTerminalProcessing enables virtual terminal processing on
+// Windows for w and returns a function that restores w to its previous state.
+// On non-Windows platforms, or if w does not refer to a terminal, then it
+// returns a non-nil no-op function and no error.
+func EnableVirtualTerminalProcessing(w io.Writer) (func() error, error) {
+ return func() error { return nil }, nil
+}
diff --git a/vendor/github.com/muesli/termenv/termenv_unix.go b/vendor/github.com/muesli/termenv/termenv_unix.go
index 778c354..11746d2 100644
--- a/vendor/github.com/muesli/termenv/termenv_unix.go
+++ b/vendor/github.com/muesli/termenv/termenv_unix.go
@@ -109,7 +109,8 @@ func (o Output) backgroundColor() Color {
return ANSIColor(0)
}
-func waitForData(fd uintptr, timeout time.Duration) error {
+func (o *Output) waitForData(timeout time.Duration) error {
+ fd := o.TTY().Fd()
tv := unix.NsecToTimeval(int64(timeout))
var readfds unix.FdSet
readfds.Set(int(fd))
@@ -132,13 +133,15 @@ func waitForData(fd uintptr, timeout time.Duration) error {
return nil
}
-func readNextByte(f File) (byte, error) {
- if err := waitForData(f.Fd(), OSCTimeout); err != nil {
- return 0, err
+func (o *Output) readNextByte() (byte, error) {
+ if !o.unsafe {
+ if err := o.waitForData(OSCTimeout); err != nil {
+ return 0, err
+ }
}
var b [1]byte
- n, err := f.Read(b[:])
+ n, err := o.TTY().Read(b[:])
if err != nil {
return 0, err
}
@@ -153,15 +156,15 @@ func readNextByte(f File) (byte, error) {
// readNextResponse reads either an OSC response or a cursor position response:
// - OSC response: "\x1b]11;rgb:1111/1111/1111\x1b\\"
// - cursor position response: "\x1b[42;1R"
-func readNextResponse(fd File) (response string, isOSC bool, err error) {
- start, err := readNextByte(fd)
+func (o *Output) readNextResponse() (response string, isOSC bool, err error) {
+ start, err := o.readNextByte()
if err != nil {
return "", false, err
}
// first byte must be ESC
- for start != '\033' {
- start, err = readNextByte(fd)
+ for start != ESC {
+ start, err = o.readNextByte()
if err != nil {
return "", false, err
}
@@ -170,7 +173,7 @@ func readNextResponse(fd File) (response string, isOSC bool, err error) {
response += string(start)
// next byte is either '[' (cursor position response) or ']' (OSC response)
- tpe, err := readNextByte(fd)
+ tpe, err := o.readNextByte()
if err != nil {
return "", false, err
}
@@ -188,7 +191,7 @@ func readNextResponse(fd File) (response string, isOSC bool, err error) {
}
for {
- b, err := readNextByte(fd)
+ b, err := o.readNextByte()
if err != nil {
return "", false, err
}
@@ -197,7 +200,7 @@ func readNextResponse(fd File) (response string, isOSC bool, err error) {
if oscResponse {
// OSC can be terminated by BEL (\a) or ST (ESC)
- if b == '\a' || strings.HasSuffix(response, "\033") {
+ if b == BEL || strings.HasSuffix(response, string(ESC)) {
return response, true, nil
}
} else {
@@ -229,33 +232,35 @@ func (o Output) termStatusReport(sequence int) (string, error) {
return "", ErrStatusReport
}
- fd := int(tty.Fd())
- // if in background, we can't control the terminal
- if !isForeground(fd) {
- return "", ErrStatusReport
- }
+ if !o.unsafe {
+ fd := int(tty.Fd())
+ // if in background, we can't control the terminal
+ if !isForeground(fd) {
+ return "", ErrStatusReport
+ }
- t, err := unix.IoctlGetTermios(fd, tcgetattr)
- if err != nil {
- return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
- }
- defer unix.IoctlSetTermios(fd, tcsetattr, t) //nolint:errcheck
+ t, err := unix.IoctlGetTermios(fd, tcgetattr)
+ if err != nil {
+ return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
+ }
+ defer unix.IoctlSetTermios(fd, tcsetattr, t) //nolint:errcheck
- noecho := *t
- noecho.Lflag = noecho.Lflag &^ unix.ECHO
- noecho.Lflag = noecho.Lflag &^ unix.ICANON
- if err := unix.IoctlSetTermios(fd, tcsetattr, &noecho); err != nil {
- return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
+ noecho := *t
+ noecho.Lflag = noecho.Lflag &^ unix.ECHO
+ noecho.Lflag = noecho.Lflag &^ unix.ICANON
+ if err := unix.IoctlSetTermios(fd, tcsetattr, &noecho); err != nil {
+ return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
+ }
}
// first, send OSC query, which is ignored by terminal which do not support it
- fmt.Fprintf(tty, "\033]%d;?\033\\", sequence)
+ fmt.Fprintf(tty, OSC+"%d;?"+ST, sequence)
// then, query cursor position, should be supported by all terminals
- fmt.Fprintf(tty, "\033[6n")
+ fmt.Fprintf(tty, CSI+"6n")
// read the next response
- res, isOSC, err := readNextResponse(tty)
+ res, isOSC, err := o.readNextResponse()
if err != nil {
return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
}
@@ -266,7 +271,7 @@ func (o Output) termStatusReport(sequence int) (string, error) {
}
// read the cursor query response next and discard the result
- _, _, err = readNextResponse(tty)
+ _, _, err = o.readNextResponse()
if err != nil {
return "", err
}
diff --git a/vendor/github.com/sahilm/fuzzy/.editorconfig b/vendor/github.com/sahilm/fuzzy/.editorconfig
deleted file mode 100644
index 8a8f6a5..0000000
--- a/vendor/github.com/sahilm/fuzzy/.editorconfig
+++ /dev/null
@@ -1,18 +0,0 @@
-[*]
-charset = utf-8
-end_of_line = lf
-insert_final_newline = true
-trim_trailing_whitespace = true
-indent_style = space
-indent_size = 2
-
-[*.sh]
-indent_size = 4
-
-[Makefile]
-indent_style = tab
-indent_size = 4
-
-[*.go]
-indent_style = tab
-indent_size = 4
diff --git a/vendor/github.com/sahilm/fuzzy/.gitignore b/vendor/github.com/sahilm/fuzzy/.gitignore
deleted file mode 100644
index d6c59ee..0000000
--- a/vendor/github.com/sahilm/fuzzy/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-vendor/
-coverage/
diff --git a/vendor/github.com/sahilm/fuzzy/.travis.yml b/vendor/github.com/sahilm/fuzzy/.travis.yml
deleted file mode 100644
index 6756d80..0000000
--- a/vendor/github.com/sahilm/fuzzy/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: go
-go:
- - 1.x
-script:
- - make
diff --git a/vendor/github.com/sahilm/fuzzy/CONTRIBUTING.md b/vendor/github.com/sahilm/fuzzy/CONTRIBUTING.md
deleted file mode 100644
index 7068ce1..0000000
--- a/vendor/github.com/sahilm/fuzzy/CONTRIBUTING.md
+++ /dev/null
@@ -1 +0,0 @@
-Everyone is welcome to contribute. Please send me a pull request or file an issue. I promise to respond promptly.
diff --git a/vendor/github.com/sahilm/fuzzy/Gopkg.lock b/vendor/github.com/sahilm/fuzzy/Gopkg.lock
deleted file mode 100644
index 6e3a7fe..0000000
--- a/vendor/github.com/sahilm/fuzzy/Gopkg.lock
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
-
-
-[[projects]]
- branch = "master"
- digest = "1:ee97ec8a00b2424570c1ce53d7b410e96fbd4c241b29df134276ff6aa3750335"
- name = "github.com/kylelemons/godebug"
- packages = [
- "diff",
- "pretty",
- ]
- pruneopts = ""
- revision = "d65d576e9348f5982d7f6d83682b694e731a45c6"
-
-[solve-meta]
- analyzer-name = "dep"
- analyzer-version = 1
- input-imports = ["github.com/kylelemons/godebug/pretty"]
- solver-name = "gps-cdcl"
- solver-version = 1
diff --git a/vendor/github.com/sahilm/fuzzy/Gopkg.toml b/vendor/github.com/sahilm/fuzzy/Gopkg.toml
deleted file mode 100644
index 8f96b11..0000000
--- a/vendor/github.com/sahilm/fuzzy/Gopkg.toml
+++ /dev/null
@@ -1,4 +0,0 @@
-# Test dependency
-[[constraint]]
- branch = "master"
- name = "github.com/kylelemons/godebug"
diff --git a/vendor/github.com/sahilm/fuzzy/LICENSE b/vendor/github.com/sahilm/fuzzy/LICENSE
deleted file mode 100644
index f848719..0000000
--- a/vendor/github.com/sahilm/fuzzy/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2017 Sahil Muthoo
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vendor/github.com/sahilm/fuzzy/Makefile b/vendor/github.com/sahilm/fuzzy/Makefile
deleted file mode 100644
index 7fa2be4..0000000
--- a/vendor/github.com/sahilm/fuzzy/Makefile
+++ /dev/null
@@ -1,57 +0,0 @@
-.PHONY: all
-all: setup lint test
-
-.PHONY: test
-test: setup
- go test -bench ./...
-
-.PHONY: cover
-cover: setup
- mkdir -p coverage
- gocov test ./... | gocov-html > coverage/coverage.html
-
-sources = $(shell find . -name '*.go' -not -path './vendor/*')
-.PHONY: goimports
-goimports: setup
- goimports -w $(sources)
-
-.PHONY: lint
-lint: setup
- gometalinter ./... --enable=goimports --disable=gocyclo --vendor -t
-
-.PHONY: install
-install: setup
- go install
-
-BIN_DIR := $(GOPATH)/bin
-GOIMPORTS := $(BIN_DIR)/goimports
-GOMETALINTER := $(BIN_DIR)/gometalinter
-DEP := $(BIN_DIR)/dep
-GOCOV := $(BIN_DIR)/gocov
-GOCOV_HTML := $(BIN_DIR)/gocov-html
-
-$(GOIMPORTS):
- go get -u golang.org/x/tools/cmd/goimports
-
-$(GOMETALINTER):
- go get -u github.com/alecthomas/gometalinter
- gometalinter --install &> /dev/null
-
-$(GOCOV):
- go get -u github.com/axw/gocov/gocov
-
-$(GOCOV_HTML):
- go get -u gopkg.in/matm/v1/gocov-html
-
-$(DEP):
- go get -u github.com/golang/dep/cmd/dep
-
-tools: $(GOIMPORTS) $(GOMETALINTER) $(GOCOV) $(GOCOV_HTML) $(DEP)
-
-vendor: $(DEP)
- dep ensure
-
-setup: tools vendor
-
-updatedeps:
- dep ensure -update
diff --git a/vendor/github.com/sahilm/fuzzy/README.md b/vendor/github.com/sahilm/fuzzy/README.md
deleted file mode 100644
index c632da5..0000000
--- a/vendor/github.com/sahilm/fuzzy/README.md
+++ /dev/null
@@ -1,184 +0,0 @@
-
-
-# fuzzy
-[![Build Status](https://travis-ci.org/sahilm/fuzzy.svg?branch=master)](https://travis-ci.org/sahilm/fuzzy)
-[![Documentation](https://godoc.org/github.com/sahilm/fuzzy?status.svg)](https://godoc.org/github.com/sahilm/fuzzy)
-
-Go library that provides fuzzy string matching optimized for filenames and code symbols in the style of Sublime Text,
-VSCode, IntelliJ IDEA et al. This library is external dependency-free. It only depends on the Go standard library.
-
-## Features
-
-- Intuitive matching. Results are returned in descending order of match quality. Quality is determined by:
- - The first character in the pattern matches the first character in the match string.
- - The matched character is camel cased.
- - The matched character follows a separator such as an underscore character.
- - The matched character is adjacent to a previous match.
-
-- Speed. Matches are returned in milliseconds. It's perfect for interactive search boxes.
-
-- The positions of matches is returned. Allows you to highlight matching characters.
-
-- Unicode aware.
-
-## Demo
-
-Here is a [demo](_example/main.go) of matching various patterns against ~16K files from the Unreal Engine 4 codebase.
-
-![demo](assets/demo.gif)
-
-You can run the demo yourself like so:
-
-```
-cd _example/
-go get github.com/jroimartin/gocui
-go run main.go
-```
-
-## Usage
-
-The following example prints out matches with the matched chars in bold.
-
-```go
-package main
-
-import (
- "fmt"
-
- "github.com/sahilm/fuzzy"
-)
-
-func main() {
- const bold = "\033[1m%s\033[0m"
- pattern := "mnr"
- data := []string{"game.cpp", "moduleNameResolver.ts", "my name is_Ramsey"}
-
- matches := fuzzy.Find(pattern, data)
-
- for _, match := range matches {
- for i := 0; i < len(match.Str); i++ {
- if contains(i, match.MatchedIndexes) {
- fmt.Print(fmt.Sprintf(bold, string(match.Str[i])))
- } else {
- fmt.Print(string(match.Str[i]))
- }
- }
- fmt.Println()
- }
-}
-
-func contains(needle int, haystack []int) bool {
- for _, i := range haystack {
- if needle == i {
- return true
- }
- }
- return false
-}
-```
-If the data you want to match isn't a slice of strings, you can use `FindFromSource` by implementing
-the provided `Source` interface. Here's an example:
-
-```go
-package main
-
-import (
- "fmt"
-
- "github.com/sahilm/fuzzy"
-)
-
-type employee struct {
- name string
- age int
-}
-
-type employees []employee
-
-func (e employees) String(i int) string {
- return e[i].name
-}
-
-func (e employees) Len() int {
- return len(e)
-}
-
-func main() {
- emps := employees{
- {
- name: "Alice",
- age: 45,
- },
- {
- name: "Bob",
- age: 35,
- },
- {
- name: "Allie",
- age: 35,
- },
- }
- results := fuzzy.FindFrom("al", emps)
- fmt.Println(results)
-}
-```
-
-Check out the [godoc](https://godoc.org/github.com/sahilm/fuzzy) for detailed documentation.
-
-## Installation
-
-`go get github.com/sahilm/fuzzy` or use your favorite dependency management tool.
-
-## Speed
-
-Here are a few benchmark results on a normal laptop.
-
-```
-BenchmarkFind/with_unreal_4_(~16K_files)-4 100 12915315 ns/op
-BenchmarkFind/with_linux_kernel_(~60K_files)-4 50 30885038 ns/op
-```
-
-Matching a pattern against ~60K files from the Linux kernel takes about 30ms.
-
-## Contributing
-
-Everyone is welcome to contribute. Please send me a pull request or file an issue. I promise
-to respond promptly.
-
-## Credits
-
-* [@ericpauley](https://github.com/ericpauley) & [@lunixbochs](https://github.com/lunixbochs) contributed Unicode awareness and various performance optimisations.
-
-* The algorithm is based of the awesome work of [forrestthewoods](https://github.com/forrestthewoods/lib_fts/blob/master/code/fts_fuzzy_match.js).
-See [this](https://blog.forrestthewoods.com/reverse-engineering-sublime-text-s-fuzzy-match-4cffeed33fdb#.d05n81yjy)
-blog post for details of the algorithm.
-
-* The artwork is by my lovely wife Sanah. It's based on the Go Gopher.
-
-* The Go gopher was designed by Renee French (http://reneefrench.blogspot.com/).
-The design is licensed under the Creative Commons 3.0 Attributions license.
-
-## License
-
-The MIT License (MIT)
-
-Copyright (c) 2017 Sahil Muthoo
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
diff --git a/vendor/github.com/sahilm/fuzzy/fuzzy.go b/vendor/github.com/sahilm/fuzzy/fuzzy.go
deleted file mode 100644
index bd66ee6..0000000
--- a/vendor/github.com/sahilm/fuzzy/fuzzy.go
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
-Package fuzzy provides fuzzy string matching optimized
-for filenames and code symbols in the style of Sublime Text,
-VSCode, IntelliJ IDEA et al.
-*/
-package fuzzy
-
-import (
- "sort"
- "unicode"
- "unicode/utf8"
-)
-
-// Match represents a matched string.
-type Match struct {
- // The matched string.
- Str string
- // The index of the matched string in the supplied slice.
- Index int
- // The indexes of matched characters. Useful for highlighting matches.
- MatchedIndexes []int
- // Score used to rank matches
- Score int
-}
-
-const (
- firstCharMatchBonus = 10
- matchFollowingSeparatorBonus = 20
- camelCaseMatchBonus = 20
- adjacentMatchBonus = 5
- unmatchedLeadingCharPenalty = -5
- maxUnmatchedLeadingCharPenalty = -15
-)
-
-var separators = []rune("/-_ .\\")
-
-// Matches is a slice of Match structs
-type Matches []Match
-
-func (a Matches) Len() int { return len(a) }
-func (a Matches) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-func (a Matches) Less(i, j int) bool { return a[i].Score >= a[j].Score }
-
-// Source represents an abstract source of a list of strings. Source must be iterable type such as a slice.
-// The source will be iterated over till Len() with String(i) being called for each element where i is the
-// index of the element. You can find a working example in the README.
-type Source interface {
- // The string to be matched at position i.
- String(i int) string
- // The length of the source. Typically is the length of the slice of things that you want to match.
- Len() int
-}
-
-type stringSource []string
-
-func (ss stringSource) String(i int) string {
- return ss[i]
-}
-
-func (ss stringSource) Len() int { return len(ss) }
-
-/*
-Find looks up pattern in data and returns matches
-in descending order of match quality. Match quality
-is determined by a set of bonus and penalty rules.
-
-The following types of matches apply a bonus:
-
-* The first character in the pattern matches the first character in the match string.
-
-* The matched character is camel cased.
-
-* The matched character follows a separator such as an underscore character.
-
-* The matched character is adjacent to a previous match.
-
-Penalties are applied for every character in the search string that wasn't matched and all leading
-characters upto the first match.
-*/
-func Find(pattern string, data []string) Matches {
- return FindFrom(pattern, stringSource(data))
-}
-
-/*
-FindFrom is an alternative implementation of Find using a Source
-instead of a list of strings.
-*/
-func FindFrom(pattern string, data Source) Matches {
- if len(pattern) == 0 {
- return nil
- }
- runes := []rune(pattern)
- var matches Matches
- var matchedIndexes []int
- for i := 0; i < data.Len(); i++ {
- var match Match
- match.Str = data.String(i)
- match.Index = i
- if matchedIndexes != nil {
- match.MatchedIndexes = matchedIndexes
- } else {
- match.MatchedIndexes = make([]int, 0, len(runes))
- }
- var score int
- patternIndex := 0
- bestScore := -1
- matchedIndex := -1
- currAdjacentMatchBonus := 0
- var last rune
- var lastIndex int
- nextc, nextSize := utf8.DecodeRuneInString(data.String(i))
- var candidate rune
- var candidateSize int
- for j := 0; j < len(data.String(i)); j += candidateSize {
- candidate, candidateSize = nextc, nextSize
- if equalFold(candidate, runes[patternIndex]) {
- score = 0
- if j == 0 {
- score += firstCharMatchBonus
- }
- if unicode.IsLower(last) && unicode.IsUpper(candidate) {
- score += camelCaseMatchBonus
- }
- if j != 0 && isSeparator(last) {
- score += matchFollowingSeparatorBonus
- }
- if len(match.MatchedIndexes) > 0 {
- lastMatch := match.MatchedIndexes[len(match.MatchedIndexes)-1]
- bonus := adjacentCharBonus(lastIndex, lastMatch, currAdjacentMatchBonus)
- score += bonus
- // adjacent matches are incremental and keep increasing based on previous adjacent matches
- // thus we need to maintain the current match bonus
- currAdjacentMatchBonus += bonus
- }
- if score > bestScore {
- bestScore = score
- matchedIndex = j
- }
- }
- var nextp rune
- if patternIndex < len(runes)-1 {
- nextp = runes[patternIndex+1]
- }
- if j+candidateSize < len(data.String(i)) {
- if data.String(i)[j+candidateSize] < utf8.RuneSelf { // Fast path for ASCII
- nextc, nextSize = rune(data.String(i)[j+candidateSize]), 1
- } else {
- nextc, nextSize = utf8.DecodeRuneInString(data.String(i)[j+candidateSize:])
- }
- } else {
- nextc, nextSize = 0, 0
- }
- // We apply the best score when we have the next match coming up or when the search string has ended.
- // Tracking when the next match is coming up allows us to exhaustively find the best match and not necessarily
- // the first match.
- // For example given the pattern "tk" and search string "The Black Knight", exhaustively matching allows us
- // to match the second k thus giving this string a higher score.
- if equalFold(nextp, nextc) || nextc == 0 {
- if matchedIndex > -1 {
- if len(match.MatchedIndexes) == 0 {
- penalty := matchedIndex * unmatchedLeadingCharPenalty
- bestScore += max(penalty, maxUnmatchedLeadingCharPenalty)
- }
- match.Score += bestScore
- match.MatchedIndexes = append(match.MatchedIndexes, matchedIndex)
- score = 0
- bestScore = -1
- patternIndex++
- }
- }
- lastIndex = j
- last = candidate
- }
- // apply penalty for each unmatched character
- penalty := len(match.MatchedIndexes) - len(data.String(i))
- match.Score += penalty
- if len(match.MatchedIndexes) == len(runes) {
- matches = append(matches, match)
- matchedIndexes = nil
- } else {
- matchedIndexes = match.MatchedIndexes[:0] // Recycle match index slice
- }
- }
- sort.Stable(matches)
- return matches
-}
-
-// Taken from strings.EqualFold
-func equalFold(tr, sr rune) bool {
- if tr == sr {
- return true
- }
- if tr < sr {
- tr, sr = sr, tr
- }
- // Fast check for ASCII.
- if tr < utf8.RuneSelf {
- // ASCII, and sr is upper case. tr must be lower case.
- if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' {
- return true
- }
- return false
- }
-
- // General case. SimpleFold(x) returns the next equivalent rune > x
- // or wraps around to smaller values.
- r := unicode.SimpleFold(sr)
- for r != sr && r < tr {
- r = unicode.SimpleFold(r)
- }
- return r == tr
-}
-
-func adjacentCharBonus(i int, lastMatch int, currentBonus int) int {
- if lastMatch == i {
- return currentBonus*2 + adjacentMatchBonus
- }
- return 0
-}
-
-func isSeparator(s rune) bool {
- for _, sep := range separators {
- if s == sep {
- return true
- }
- }
- return false
-}
-
-func max(x int, y int) int {
- if x > y {
- return x
- }
- return y
-}
diff --git a/vendor/golang.org/x/sync/LICENSE b/vendor/golang.org/x/sync/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/sync/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/sync/PATENTS b/vendor/golang.org/x/sync/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/sync/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go
new file mode 100644
index 0000000..cbee7a4
--- /dev/null
+++ b/vendor/golang.org/x/sync/errgroup/errgroup.go
@@ -0,0 +1,132 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package errgroup provides synchronization, error propagation, and Context
+// cancelation for groups of goroutines working on subtasks of a common task.
+package errgroup
+
+import (
+ "context"
+ "fmt"
+ "sync"
+)
+
+type token struct{}
+
+// A Group is a collection of goroutines working on subtasks that are part of
+// the same overall task.
+//
+// A zero Group is valid, has no limit on the number of active goroutines,
+// and does not cancel on error.
+type Group struct {
+ cancel func()
+
+ wg sync.WaitGroup
+
+ sem chan token
+
+ errOnce sync.Once
+ err error
+}
+
+func (g *Group) done() {
+ if g.sem != nil {
+ <-g.sem
+ }
+ g.wg.Done()
+}
+
+// WithContext returns a new Group and an associated Context derived from ctx.
+//
+// The derived Context is canceled the first time a function passed to Go
+// returns a non-nil error or the first time Wait returns, whichever occurs
+// first.
+func WithContext(ctx context.Context) (*Group, context.Context) {
+ ctx, cancel := context.WithCancel(ctx)
+ return &Group{cancel: cancel}, ctx
+}
+
+// Wait blocks until all function calls from the Go method have returned, then
+// returns the first non-nil error (if any) from them.
+func (g *Group) Wait() error {
+ g.wg.Wait()
+ if g.cancel != nil {
+ g.cancel()
+ }
+ return g.err
+}
+
+// Go calls the given function in a new goroutine.
+// It blocks until the new goroutine can be added without the number of
+// active goroutines in the group exceeding the configured limit.
+//
+// The first call to return a non-nil error cancels the group's context, if the
+// group was created by calling WithContext. The error will be returned by Wait.
+func (g *Group) Go(f func() error) {
+ if g.sem != nil {
+ g.sem <- token{}
+ }
+
+ g.wg.Add(1)
+ go func() {
+ defer g.done()
+
+ if err := f(); err != nil {
+ g.errOnce.Do(func() {
+ g.err = err
+ if g.cancel != nil {
+ g.cancel()
+ }
+ })
+ }
+ }()
+}
+
+// TryGo calls the given function in a new goroutine only if the number of
+// active goroutines in the group is currently below the configured limit.
+//
+// The return value reports whether the goroutine was started.
+func (g *Group) TryGo(f func() error) bool {
+ if g.sem != nil {
+ select {
+ case g.sem <- token{}:
+ // Note: this allows barging iff channels in general allow barging.
+ default:
+ return false
+ }
+ }
+
+ g.wg.Add(1)
+ go func() {
+ defer g.done()
+
+ if err := f(); err != nil {
+ g.errOnce.Do(func() {
+ g.err = err
+ if g.cancel != nil {
+ g.cancel()
+ }
+ })
+ }
+ }()
+ return true
+}
+
+// SetLimit limits the number of active goroutines in this group to at most n.
+// A negative value indicates no limit.
+//
+// Any subsequent call to the Go method will block until it can add an active
+// goroutine without exceeding the configured limit.
+//
+// The limit must not be modified while any goroutines in the group are active.
+func (g *Group) SetLimit(n int) {
+ if n < 0 {
+ g.sem = nil
+ return
+ }
+ if len(g.sem) != 0 {
+ panic(fmt.Errorf("errgroup: modify limit while %v goroutines in the group are still active", len(g.sem)))
+ }
+ g.sem = make(chan token, n)
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index defc002..b1ff5f2 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -6,14 +6,11 @@ github.com/atotto/clipboard
github.com/aymanbagabas/go-osc52
# github.com/charmbracelet/bubbles v0.14.0
## explicit; go 1.13
-github.com/charmbracelet/bubbles/help
github.com/charmbracelet/bubbles/key
-github.com/charmbracelet/bubbles/list
-github.com/charmbracelet/bubbles/paginator
github.com/charmbracelet/bubbles/spinner
github.com/charmbracelet/bubbles/textinput
github.com/charmbracelet/bubbles/viewport
-# github.com/charmbracelet/bubbletea v0.23.1
+# github.com/charmbracelet/bubbletea v0.23.2
## explicit; go 1.16
github.com/charmbracelet/bubbletea
# github.com/charmbracelet/lipgloss v0.5.0
@@ -47,15 +44,15 @@ github.com/muesli/reflow/ansi
github.com/muesli/reflow/truncate
github.com/muesli/reflow/wordwrap
github.com/muesli/reflow/wrap
-# github.com/muesli/termenv v0.13.0
+# github.com/muesli/termenv v0.14.0
## explicit; go 1.13
github.com/muesli/termenv
# github.com/rivo/uniseg v0.4.3
## explicit; go 1.18
github.com/rivo/uniseg
-# github.com/sahilm/fuzzy v0.1.0
+# golang.org/x/sync v0.1.0
## explicit
-github.com/sahilm/fuzzy
+golang.org/x/sync/errgroup
# golang.org/x/sys v0.4.0
## explicit; go 1.17
golang.org/x/sys/internal/unsafeheader