2021-06-16 21:20:56 -04:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
// A simple example that shows how to send messages to a Bubble Tea program
|
|
|
|
|
// from outside the program using Program.Send(Msg).
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"math/rand"
|
|
|
|
|
"os"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/charmbracelet/bubbles/spinner"
|
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
|
|
|
"github.com/charmbracelet/lipgloss"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
spinnerStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("63"))
|
|
|
|
|
helpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("241")).Margin(1, 0)
|
|
|
|
|
dotStyle = helpStyle.Copy().UnsetMargins()
|
|
|
|
|
foodStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("36"))
|
|
|
|
|
durationStyle = dotStyle.Copy()
|
|
|
|
|
appStyle = lipgloss.NewStyle().Margin(1, 2, 0, 2)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type resultMsg struct {
|
|
|
|
|
duration time.Duration
|
|
|
|
|
food string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r resultMsg) String() string {
|
|
|
|
|
if r.duration == 0 {
|
|
|
|
|
return dotStyle.Render(strings.Repeat(".", 30))
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf("🍔 Ate %s %s", r.food,
|
|
|
|
|
durationStyle.Render(r.duration.String()))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type model struct {
|
|
|
|
|
spinner spinner.Model
|
|
|
|
|
results []resultMsg
|
|
|
|
|
quitting bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func newModel() model {
|
|
|
|
|
const numLastResults = 5
|
2022-01-10 20:42:10 -05:00
|
|
|
|
s := spinner.New()
|
2021-06-16 21:20:56 -04:00
|
|
|
|
s.Style = spinnerStyle
|
|
|
|
|
return model{
|
|
|
|
|
spinner: s,
|
|
|
|
|
results: make([]resultMsg, numLastResults),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m model) Init() tea.Cmd {
|
|
|
|
|
return spinner.Tick
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 resultMsg:
|
|
|
|
|
m.results = append(m.results[1:], msg)
|
|
|
|
|
return m, nil
|
|
|
|
|
case spinner.TickMsg:
|
|
|
|
|
var cmd tea.Cmd
|
|
|
|
|
m.spinner, cmd = m.spinner.Update(msg)
|
|
|
|
|
return m, cmd
|
|
|
|
|
default:
|
|
|
|
|
return m, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m model) View() string {
|
|
|
|
|
var s string
|
|
|
|
|
|
|
|
|
|
if m.quitting {
|
|
|
|
|
s += "That’s all for today!"
|
|
|
|
|
} else {
|
|
|
|
|
s += m.spinner.View() + " Eating food..."
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s += "\n\n"
|
|
|
|
|
|
|
|
|
|
for _, res := range m.results {
|
|
|
|
|
s += res.String() + "\n"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !m.quitting {
|
|
|
|
|
s += helpStyle.Render("Press any key to exit")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if m.quitting {
|
|
|
|
|
s += "\n"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return appStyle.Render(s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
rand.Seed(time.Now().UTC().UnixNano())
|
|
|
|
|
|
|
|
|
|
done := make(chan struct{})
|
|
|
|
|
|
|
|
|
|
p := tea.NewProgram(newModel())
|
|
|
|
|
go func() {
|
|
|
|
|
if err := p.Start(); err != nil {
|
|
|
|
|
fmt.Println("Error running program:", err)
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
|
|
|
|
close(done)
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
// Simulate activity
|
|
|
|
|
go func() {
|
|
|
|
|
for {
|
|
|
|
|
pause := time.Duration(rand.Int63n(899)+100) * time.Millisecond
|
|
|
|
|
time.Sleep(pause)
|
|
|
|
|
|
|
|
|
|
// Send the Bubble Tea program a message from outside the program.
|
|
|
|
|
p.Send(resultMsg{food: randomFood(), duration: pause})
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
<-done
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func randomFood() string {
|
|
|
|
|
food := []string{"an apple", "a pear", "a gherkin", "a party gherkin",
|
|
|
|
|
"a kohlrabi", "some spaghetti", "tacos", "a currywurst", "some curry",
|
|
|
|
|
"a sandwich", "some peanut butter", "some cashews", "some ramen"}
|
|
|
|
|
return string(food[rand.Intn(len(food))])
|
|
|
|
|
}
|