/
spinner.go
77 lines (67 loc) · 1.42 KB
/
spinner.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package tui
import (
"errors"
"fmt"
"strings"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
var _ tea.Model = &SpinnerModel[any]{}
type SpinnerModel[V any] struct {
spinner.Model
hint string
err error
do func() (V, error)
Val V
}
func NewSpinnerModel[V any](hint string, do func() (V, error)) *SpinnerModel[V] {
return &SpinnerModel[V]{
hint: hint,
do: do,
Model: spinner.Model{
Spinner: spinner.Dot,
Style: lipgloss.NewStyle().Foreground(lipgloss.Color("205")),
},
}
}
func (s *SpinnerModel[V]) Init() tea.Cmd {
return tea.Batch(s.Model.Tick,
func() tea.Msg {
if v, err := s.do(); err != nil {
return errMsg(err)
} else {
return doneMsg[V]{v: v}
}
})
}
func (s *SpinnerModel[V]) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c":
s.err = errors.New("Ctrl+C interrupted")
return s, tea.Quit
}
case errMsg:
s.err = msg
case doneMsg[V]:
s.Val = msg.v
return s, tea.Quit
default:
var cmd tea.Cmd
s.Model, cmd = s.Model.Update(msg)
return s, cmd
}
return s, nil
}
func (s *SpinnerModel[V]) View() string {
str := fmt.Sprintf("%s %s", s.Model.View(), s.hint)
return str + strings.Repeat(" ", 10) + "\r"
}
func (s *SpinnerModel[V]) Value() V {
return s.Val
}
func (s *SpinnerModel[V]) Error() error {
return s.err
}