mirror of
https://github.com/taigrr/bubbletea.git
synced 2026-04-14 16:51:09 -07:00
Remove entire subscription model
It was a valiant effort, and the implementation was solid and dependable, but at the end of the day we can achieve the same functionality in a much simpler fashion with commands, especially because Go is not held to the same restrictions as Elm.
This commit is contained in:
@@ -14,21 +14,17 @@ type model int
|
||||
|
||||
type tickMsg time.Time
|
||||
|
||||
func newTickMsg(t time.Time) boba.Msg {
|
||||
return tickMsg(t)
|
||||
}
|
||||
|
||||
func main() {
|
||||
boba.AltScreen()
|
||||
defer boba.ExitAltScreen()
|
||||
err := boba.NewProgram(initialize, update, view, subscriptions).Start()
|
||||
err := boba.NewProgram(initialize, update, view).Start()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func initialize() (boba.Model, boba.Cmd) {
|
||||
return model(5), nil
|
||||
return model(5), tick()
|
||||
}
|
||||
|
||||
func update(message boba.Msg, mdl boba.Model) (boba.Model, boba.Cmd) {
|
||||
@@ -51,19 +47,20 @@ func update(message boba.Msg, mdl boba.Model) (boba.Model, boba.Cmd) {
|
||||
if m <= 0 {
|
||||
return m, boba.Quit
|
||||
}
|
||||
return m, tick()
|
||||
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func subscriptions(_ boba.Model) boba.Subs {
|
||||
return boba.Subs{
|
||||
"tick": boba.Every(time.Second, newTickMsg),
|
||||
}
|
||||
}
|
||||
|
||||
func view(mdl boba.Model) string {
|
||||
m, _ := mdl.(model)
|
||||
return fmt.Sprintf("\n\n Hi. This program will exit in %d seconds...", m)
|
||||
}
|
||||
|
||||
func tick() boba.Cmd {
|
||||
return boba.Tick(time.Second, func(t time.Time) boba.Msg {
|
||||
return tickMsg(t)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ type statusMsg int
|
||||
type errMsg error
|
||||
|
||||
func main() {
|
||||
p := boba.NewProgram(initialize, update, view, nil)
|
||||
p := boba.NewProgram(initialize, update, view)
|
||||
if err := p.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ func main() {
|
||||
initialize,
|
||||
update,
|
||||
view,
|
||||
subscriptions,
|
||||
)
|
||||
|
||||
if err := p.Start(); err != nil {
|
||||
@@ -38,7 +37,7 @@ func initialize() (boba.Model, boba.Cmd) {
|
||||
return Model{
|
||||
textInput: inputModel,
|
||||
err: nil,
|
||||
}, nil
|
||||
}, input.Blink(inputModel)
|
||||
}
|
||||
|
||||
func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
|
||||
@@ -74,20 +73,6 @@ func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
func subscriptions(model boba.Model) boba.Subs {
|
||||
m, ok := model.(Model)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
sub, err := input.MakeSub(m.textInput)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return boba.Subs{
|
||||
"input": sub,
|
||||
}
|
||||
}
|
||||
|
||||
func view(model boba.Model) string {
|
||||
m, ok := model.(Model)
|
||||
if !ok {
|
||||
|
||||
@@ -18,7 +18,11 @@ func main() {
|
||||
|
||||
boba.AltScreen()
|
||||
defer boba.ExitAltScreen()
|
||||
if err := pager.NewProgram(string(content)).Start(); err != nil {
|
||||
if err := boba.NewProgram(
|
||||
pager.Init(string(content)),
|
||||
pager.Update,
|
||||
pager.View,
|
||||
).Start(); err != nil {
|
||||
fmt.Println("could not run program:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
// A model can be more or less any type of data. It holds all the data for a
|
||||
// program, so often it's a struct. For this simple example, however, all
|
||||
// we'll need is a simple integer.
|
||||
type Model int
|
||||
type model int
|
||||
|
||||
// Messages are events that we respond to in our Update function. This
|
||||
// particular one indicates that the timer has ticked.
|
||||
@@ -21,22 +21,22 @@ type tickMsg time.Time
|
||||
|
||||
func main() {
|
||||
// Initialize our program
|
||||
p := boba.NewProgram(initialize, update, view, subscriptions)
|
||||
p := boba.NewProgram(initialize, update, view)
|
||||
if err := p.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func initialize() (boba.Model, boba.Cmd) {
|
||||
return Model(5), nil
|
||||
return model(5), tick
|
||||
}
|
||||
|
||||
// Update is called when messages are recived. The idea is that you inspect
|
||||
// the message and update the model (or send back a new one) accordingly. You
|
||||
// can also return a commmand, which is a function that peforms I/O and
|
||||
// returns a message.
|
||||
func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
|
||||
m, _ := model.(Model)
|
||||
func update(msg boba.Msg, mdl boba.Model) (boba.Model, boba.Cmd) {
|
||||
m, _ := mdl.(model)
|
||||
|
||||
switch msg.(type) {
|
||||
case boba.KeyMsg:
|
||||
@@ -46,23 +46,19 @@ func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
|
||||
if m <= 0 {
|
||||
return m, boba.Quit
|
||||
}
|
||||
return m, tick
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Views take data from the model and return a string which will be rendered
|
||||
// to the terminal.
|
||||
func view(model boba.Model) string {
|
||||
m, _ := model.(Model)
|
||||
func view(mdl boba.Model) string {
|
||||
m, _ := mdl.(model)
|
||||
return fmt.Sprintf("Hi. This program will exit in %d seconds. To quit sooner press any key.\n", m)
|
||||
}
|
||||
|
||||
// This is a subscription which we setup in NewProgram(). It waits for one
|
||||
// second, sends a tick, and then restarts.
|
||||
func subscriptions(_ boba.Model) boba.Subs {
|
||||
return boba.Subs{
|
||||
"tick": boba.Every(time.Second, func(t time.Time) boba.Msg {
|
||||
return tickMsg(t)
|
||||
}),
|
||||
}
|
||||
func tick() boba.Msg {
|
||||
time.Sleep(time.Second)
|
||||
return tickMsg{}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ type Model struct {
|
||||
type errMsg error
|
||||
|
||||
func main() {
|
||||
p := boba.NewProgram(initialize, update, view, subscriptions)
|
||||
p := boba.NewProgram(initialize, update, view)
|
||||
if err := p.Start(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
@@ -30,12 +30,12 @@ func main() {
|
||||
}
|
||||
|
||||
func initialize() (boba.Model, boba.Cmd) {
|
||||
m := spinner.NewModel()
|
||||
m.Type = spinner.Dot
|
||||
s := spinner.NewModel()
|
||||
s.Type = spinner.Dot
|
||||
|
||||
return Model{
|
||||
spinner: m,
|
||||
}, nil
|
||||
spinner: s,
|
||||
}, spinner.Tick(s)
|
||||
}
|
||||
|
||||
func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
|
||||
@@ -64,8 +64,9 @@ func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
|
||||
return m, nil
|
||||
|
||||
default:
|
||||
m.spinner, _ = spinner.Update(msg, m.spinner)
|
||||
return m, nil
|
||||
var cmd boba.Cmd
|
||||
m.spinner, cmd = spinner.Update(msg, m.spinner)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
}
|
||||
@@ -88,18 +89,3 @@ func view(model boba.Model) string {
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
func subscriptions(model boba.Model) boba.Subs {
|
||||
m, ok := model.(Model)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
sub, err := spinner.MakeSub(m.spinner)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return boba.Subs{
|
||||
"tick": sub,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ func main() {
|
||||
initialize,
|
||||
update,
|
||||
view,
|
||||
subscriptions,
|
||||
).Start(); err != nil {
|
||||
fmt.Printf("could not start program: %s\n", err)
|
||||
os.Exit(1)
|
||||
@@ -53,7 +52,13 @@ func initialize() (boba.Model, boba.Cmd) {
|
||||
email.Placeholder = "Email"
|
||||
email.Prompt = blurredPrompt
|
||||
|
||||
return Model{0, name, nickName, email, blurredSubmitButton}, nil
|
||||
return Model{0, name, nickName, email, blurredSubmitButton},
|
||||
boba.Batch(
|
||||
input.Blink(name),
|
||||
input.Blink(nickName),
|
||||
input.Blink(email),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
|
||||
@@ -62,6 +67,8 @@ func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
|
||||
panic("could not perform assertion on model")
|
||||
}
|
||||
|
||||
var cmd boba.Cmd
|
||||
|
||||
switch msg := msg.(type) {
|
||||
|
||||
case boba.KeyMsg:
|
||||
@@ -135,44 +142,29 @@ func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
|
||||
|
||||
default:
|
||||
// Handle character input
|
||||
m = updateInputs(msg, m)
|
||||
return m, nil
|
||||
m, cmd = updateInputs(msg, m)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
default:
|
||||
// Handle blinks
|
||||
m = updateInputs(msg, m)
|
||||
return m, nil
|
||||
m, cmd = updateInputs(msg, m)
|
||||
return m, cmd
|
||||
}
|
||||
}
|
||||
|
||||
func updateInputs(msg boba.Msg, m Model) Model {
|
||||
m.nameInput, _ = input.Update(msg, m.nameInput)
|
||||
m.nickNameInput, _ = input.Update(msg, m.nickNameInput)
|
||||
m.emailInput, _ = input.Update(msg, m.emailInput)
|
||||
return m
|
||||
}
|
||||
|
||||
func subscriptions(model boba.Model) boba.Subs {
|
||||
m, ok := model.(Model)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
// It's a little hacky, but we're using the subscription from one
|
||||
// input element to handle the blinking for all elements. It doesn't
|
||||
// have to be this way, we're just feeling a bit lazy at the moment.
|
||||
inputSub, err := input.MakeSub(m.nameInput)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return boba.Subs{
|
||||
// It's a little hacky, but we're using the subscription from one
|
||||
// input element to handle the blinking for all elements. It doesn't
|
||||
// have to be this way, we're just feeling a bit lazy at the moment.
|
||||
"blink": inputSub,
|
||||
}
|
||||
func updateInputs(msg boba.Msg, m Model) (Model, boba.Cmd) {
|
||||
var (
|
||||
cmd boba.Cmd
|
||||
cmds []boba.Cmd
|
||||
)
|
||||
m.nameInput, cmd = input.Update(msg, m.nameInput)
|
||||
cmds = append(cmds, cmd)
|
||||
m.nickNameInput, cmd = input.Update(msg, m.nickNameInput)
|
||||
cmds = append(cmds, cmd)
|
||||
m.emailInput, cmd = input.Update(msg, m.emailInput)
|
||||
cmds = append(cmds, cmd)
|
||||
return m, boba.Batch(cmds...)
|
||||
}
|
||||
|
||||
func view(model boba.Model) string {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
// TODO: This code feels messy. Clean it up.
|
||||
// TODO: The views feel messy. Clean 'em up.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -17,7 +17,6 @@ func main() {
|
||||
initialize,
|
||||
update,
|
||||
view,
|
||||
subscriptions,
|
||||
)
|
||||
if err := p.Start(); err != nil {
|
||||
fmt.Println("could not start program:", err)
|
||||
@@ -26,17 +25,9 @@ func main() {
|
||||
|
||||
// MSG
|
||||
|
||||
type tickMsg time.Time
|
||||
type tickMsg struct{}
|
||||
|
||||
func newTickMsg(t time.Time) boba.Msg {
|
||||
return tickMsg(t)
|
||||
}
|
||||
|
||||
type frameMsg time.Time
|
||||
|
||||
func newFrameMsg(t time.Time) boba.Msg {
|
||||
return frameMsg(t)
|
||||
}
|
||||
type frameMsg struct{}
|
||||
|
||||
// MODEL
|
||||
|
||||
@@ -53,21 +44,19 @@ type Model struct {
|
||||
// INIT
|
||||
|
||||
func initialize() (boba.Model, boba.Cmd) {
|
||||
return Model{0, false, 10, 0, 0, false}, nil
|
||||
return Model{0, false, 10, 0, 0, false}, tick
|
||||
}
|
||||
|
||||
// SUBSCRIPTIONS
|
||||
// CMDS
|
||||
|
||||
func subscriptions(model boba.Model) boba.Subs {
|
||||
m, _ := model.(Model)
|
||||
if !m.Chosen || m.Loaded {
|
||||
return boba.Subs{
|
||||
"tick": boba.Every(time.Second, newTickMsg),
|
||||
}
|
||||
}
|
||||
return boba.Subs{
|
||||
"frame": boba.Every(time.Second/60, newFrameMsg),
|
||||
}
|
||||
func tick() boba.Msg {
|
||||
time.Sleep(time.Second)
|
||||
return tickMsg{}
|
||||
}
|
||||
|
||||
func frame() boba.Msg {
|
||||
time.Sleep(time.Second / 60)
|
||||
return frameMsg{}
|
||||
}
|
||||
|
||||
// UPDATE
|
||||
@@ -118,7 +107,7 @@ func updateChoices(msg boba.Msg, m Model) (boba.Model, boba.Cmd) {
|
||||
m.Ticks -= 1
|
||||
}
|
||||
|
||||
return m, nil
|
||||
return m, tick
|
||||
}
|
||||
|
||||
func updateChosen(msg boba.Msg, m Model) (boba.Model, boba.Cmd) {
|
||||
@@ -137,7 +126,7 @@ func updateChosen(msg boba.Msg, m Model) (boba.Model, boba.Cmd) {
|
||||
case frameMsg:
|
||||
if !m.Loaded {
|
||||
m.Frames += 1
|
||||
m.Progress = ease.OutBounce(float64(m.Frames) / float64(120))
|
||||
m.Progress = ease.OutBounce(float64(m.Frames) / float64(160))
|
||||
if m.Progress >= 1 {
|
||||
m.Progress = 1
|
||||
m.Loaded = true
|
||||
@@ -154,7 +143,7 @@ func updateChosen(msg boba.Msg, m Model) (boba.Model, boba.Cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
return m, frame
|
||||
}
|
||||
|
||||
// VIEW
|
||||
|
||||
Reference in New Issue
Block a user