From 03d1aa6c087e47a965cc465141d2fdb718735545 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Mon, 20 Dec 2021 17:46:33 -0500 Subject: [PATCH] Rename 'countdown' example to 'timer' and use timer Bubble --- examples/countdown/main.go | 69 --------------------- examples/timer/main.go | 122 +++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 69 deletions(-) delete mode 100644 examples/countdown/main.go create mode 100644 examples/timer/main.go diff --git a/examples/countdown/main.go b/examples/countdown/main.go deleted file mode 100644 index 5bb33b2..0000000 --- a/examples/countdown/main.go +++ /dev/null @@ -1,69 +0,0 @@ -package main - -import ( - "fmt" - "os" - "time" - - tea "github.com/charmbracelet/bubbletea" -) - -var ( - duration = time.Second * 10 - interval = time.Millisecond -) - -func main() { - m := model{ - timeout: time.Now().Add(duration), - } - - if err := tea.NewProgram(m).Start(); err != nil { - fmt.Println("Oh no, it didn't work:", err) - os.Exit(1) - } -} - -type tickMsg time.Time - -type model struct { - timeout time.Time - lastTick time.Time -} - -func (m model) Init() tea.Cmd { - return tick() -} - -func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "q", "esc": - return m, tea.Quit - } - - case tickMsg: - t := time.Time(msg) - if t.After(m.timeout) { - return m, tea.Quit - } - m.lastTick = t - return m, tick() - } - - return m, nil -} - -func (m model) View() string { - t := m.timeout.Sub(m.lastTick).Milliseconds() - secs := t / 1000 - millis := t % 1000 / 10 - return fmt.Sprintf("This program will quit in %02d:%02d\n", secs, millis) -} - -func tick() tea.Cmd { - return tea.Tick(time.Duration(interval), func(t time.Time) tea.Msg { - return tickMsg(t) - }) -} diff --git a/examples/timer/main.go b/examples/timer/main.go new file mode 100644 index 0000000..bf3a2c9 --- /dev/null +++ b/examples/timer/main.go @@ -0,0 +1,122 @@ +package main + +import ( + "fmt" + "os" + "time" + + "github.com/charmbracelet/bubbles/help" + "github.com/charmbracelet/bubbles/key" + "github.com/charmbracelet/bubbles/timer" + tea "github.com/charmbracelet/bubbletea" +) + +const timeout = time.Second * 5 + +type model struct { + timer timer.Model + keymap keymap + help help.Model + quitting bool +} + +type keymap struct { + start key.Binding + stop key.Binding + reset key.Binding + quit key.Binding +} + +func (m model) Init() tea.Cmd { + return m.timer.Init() +} + +func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case timer.TickMsg: + var cmd tea.Cmd + m.timer, cmd = m.timer.Update(msg) + return m, cmd + + case timer.StartStopMsg: + var cmd tea.Cmd + m.timer, cmd = m.timer.Update(msg) + m.keymap.stop.SetEnabled(m.timer.Running()) + m.keymap.start.SetEnabled(!m.timer.Running()) + return m, cmd + + case timer.TimeoutMsg: + m.quitting = true + return m, tea.Quit + + case tea.KeyMsg: + switch { + case key.Matches(msg, m.keymap.quit): + m.quitting = true + return m, tea.Quit + case key.Matches(msg, m.keymap.reset): + m.timer.Timeout = timeout + case key.Matches(msg, m.keymap.start, m.keymap.stop): + return m, m.timer.Toggle() + } + } + + return m, nil +} + +func (m model) helpView() string { + return "\n" + m.help.ShortHelpView([]key.Binding{ + m.keymap.start, + m.keymap.stop, + m.keymap.reset, + m.keymap.quit, + }) +} + +func (m model) View() string { + // For a more detailed timer view you could read m.timer.Timeout to get + // the remaining time as a time.Duration and skip calling m.timer.View() + // entirely. + s := m.timer.View() + + if m.timer.Timedout() { + s = "All done!" + } + s += "\n" + if !m.quitting { + s = "Exiting in " + s + s += m.helpView() + } + return s +} + +func main() { + m := model{ + timer: timer.NewWithInterval(timeout, time.Millisecond), + keymap: keymap{ + start: key.NewBinding( + key.WithKeys("s"), + key.WithHelp("s", "start"), + ), + stop: key.NewBinding( + key.WithKeys("s"), + key.WithHelp("s", "stop"), + ), + reset: key.NewBinding( + key.WithKeys("r"), + key.WithHelp("r", "reset"), + ), + quit: key.NewBinding( + key.WithKeys("q", "ctrl+c"), + key.WithHelp("q", "quit"), + ), + }, + help: help.NewModel(), + } + m.keymap.start.SetEnabled(false) + + if err := tea.NewProgram(m).Start(); err != nil { + fmt.Println("Uh oh, we encountered an error:", err) + os.Exit(1) + } +}