-
Notifications
You must be signed in to change notification settings - Fork 723
/
main.go
139 lines (115 loc) ยท 2.89 KB
/
main.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package main
import (
"flag"
"fmt"
"io"
"log"
"math/rand"
"os"
"time"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/mattn/go-isatty"
"github.com/muesli/reflow/indent"
)
var helpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("241")).Render
func main() {
rand.Seed(time.Now().UTC().UnixNano())
var (
daemonMode bool
showHelp bool
opts []tea.ProgramOption
)
flag.BoolVar(&daemonMode, "d", false, "run as a daemon")
flag.BoolVar(&showHelp, "h", false, "show help")
flag.Parse()
if showHelp {
flag.Usage()
os.Exit(0)
}
if daemonMode || !isatty.IsTerminal(os.Stdout.Fd()) {
// If we're in daemon mode don't render the TUI
opts = []tea.ProgramOption{tea.WithoutRenderer()}
} else {
// If we're in TUI mode, discard log output
log.SetOutput(io.Discard)
}
p := tea.NewProgram(newModel(), opts...)
if _, err := p.Run(); err != nil {
fmt.Println("Error starting Bubble Tea program:", err)
os.Exit(1)
}
}
type result struct {
duration time.Duration
emoji string
}
type model struct {
spinner spinner.Model
results []result
quitting bool
}
func newModel() model {
const showLastResults = 5
sp := spinner.New()
sp.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("206"))
return model{
spinner: sp,
results: make([]result, showLastResults),
}
}
func (m model) Init() tea.Cmd {
log.Println("Starting work...")
return tea.Batch(
spinner.Tick,
runPretendProcess,
)
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
m.quitting = true
return m, tea.Quit
case spinner.TickMsg:
var cmd tea.Cmd
m.spinner, cmd = m.spinner.Update(msg)
return m, cmd
case processFinishedMsg:
d := time.Duration(msg)
res := result{emoji: randomEmoji(), duration: d}
log.Printf("%s Job finished in %s", res.emoji, res.duration)
m.results = append(m.results[1:], res)
return m, runPretendProcess
default:
return m, nil
}
}
func (m model) View() string {
s := "\n" +
m.spinner.View() + " Doing some work...\n\n"
for _, res := range m.results {
if res.duration == 0 {
s += "........................\n"
} else {
s += fmt.Sprintf("%s Job finished in %s\n", res.emoji, res.duration)
}
}
s += helpStyle("\nPress any key to exit\n")
if m.quitting {
s += "\n"
}
return indent.String(s, 1)
}
// processFinishedMsg is send when a pretend process completes.
type processFinishedMsg time.Duration
// pretendProcess simulates a long-running process.
func runPretendProcess() tea.Msg {
pause := time.Duration(rand.Int63n(899)+100) * time.Millisecond
time.Sleep(pause)
return processFinishedMsg(pause)
}
func randomEmoji() string {
emojis := []rune("๐ฆ๐ง๐ก๐ค ๐พ๐ญ๐ฆ๐ฏ๐ฆ๐ฅจ๐๐๐๐ฅ๐ฎ๐ฆ๐ฆ๐ถ๐ธ๐๐ฅ๐งฒ๐๐ฅ๐๐ฝ")
return string(emojis[rand.Intn(len(emojis))])
}