diff --git a/README.md b/README.md index 91b831b..d733d5d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ -# Tea +# Boba The fun, functional way to build terminal apps. A Go framework based on -[The Elm Architecture][elm]. 茶! +[The Elm Architecture][elm]. + +⚠️ This project is a pre-release so the API is subject to change +a little. That said, we're using it in production. -⚠️ This project is a pre-release! The API is subject to change a little. ## Simple example @@ -16,7 +18,7 @@ import ( "fmt" "log" "time" - "github.com/charmbracelet/tea" + "github.com/charmbracelet/boba" ) type model int @@ -24,36 +26,36 @@ type model int type tickMsg time.Time func main() { - p := tea.NewProgram(init, update, view, subscriptions) + p := boba.NewProgram(init, update, view, subscriptions) if err := p.Start(); err != nil { log.Fatal(err) } } // Listen for messages and update the model accordingly -func update(msg tea.Msg, mdl tea.Model) (tea.Model, tea.Cmd) { +func update(msg boba.Msg, mdl boba.Model) (boba.Model, boba.Cmd) { m, _ := mdl.(model) switch msg.(type) { case tickMsg: m-- if m == 0 { - return m, tea.Quit + return m, boba.Quit } } return m, nil } // Render to the terminal -func view(mdl tea.Model) string { +func view(mdl boba.Model) string { m, _ := mdl.(model) return fmt.Sprintf("Hi. This program will exit in %d seconds...\n", m) } // Subscribe to events -func subscriptions(_ tea.Model) tea.Subs { - return tea.Subs{ - "tick": time.Every(time.Second, func(t time.Time) tea.Msg { +func subscriptions(_ boba.Model) boba.Subs { + return boba.Subs{ + "tick": time.Every(time.Second, func(t time.Time) boba.Msg { return tickMsg(t) }, } @@ -62,12 +64,11 @@ func subscriptions(_ tea.Model) tea.Subs { Hungry for more? See the [other examples][examples]. -[examples]: https://github.com/charmbracelet/tea/tree/master/examples +[examples]: https://github.com/charmbracelet/boba/tree/master/examples + ## Other Resources -* [Tea Party](https://github.com/charmbracelet/teaparty): a collection of Tea - components. * [Termenv](https://github.com/muesli/termenv): advanced ANSI style and color support for your terminal applications. Very useful when rendering your views. @@ -83,9 +84,10 @@ and [go-tea][gotea] by TJ Holowaychuk. [elm]: https://guide.elm-lang.org/architecture/ [gotea]: https://github.com/tj/go-tea + ## License -[MIT](https://github.com/charmbracelet/tea/raw/master/LICENSE) +[MIT](https://github.com/charmbracelet/boba/raw/master/LICENSE) *** diff --git a/tea.go b/boba.go similarity index 99% rename from tea.go rename to boba.go index 7ea73de..9e53129 100644 --- a/tea.go +++ b/boba.go @@ -1,4 +1,4 @@ -package tea +package boba import ( "io" diff --git a/examples/fullscreen/main.go b/examples/fullscreen/main.go index 7fe2938..e5d678a 100644 --- a/examples/fullscreen/main.go +++ b/examples/fullscreen/main.go @@ -7,49 +7,49 @@ import ( "log" "time" - "github.com/charmbracelet/tea" + "github.com/charmbracelet/boba" ) type model int type tickMsg time.Time -func newTickMsg(t time.Time) tea.Msg { +func newTickMsg(t time.Time) boba.Msg { return tickMsg(t) } func main() { - tea.AltScreen() - defer tea.ExitAltScreen() - err := tea.NewProgram(initialize, update, view, subscriptions).Start() + boba.AltScreen() + defer boba.ExitAltScreen() + err := boba.NewProgram(initialize, update, view, subscriptions).Start() if err != nil { log.Fatal(err) } } -func initialize() (tea.Model, tea.Cmd) { +func initialize() (boba.Model, boba.Cmd) { return model(5), nil } -func update(message tea.Msg, mdl tea.Model) (tea.Model, tea.Cmd) { +func update(message boba.Msg, mdl boba.Model) (boba.Model, boba.Cmd) { m, _ := mdl.(model) switch msg := message.(type) { - case tea.KeyMsg: + case boba.KeyMsg: switch msg.String() { case "ctrl+c": fallthrough case "esc": fallthrough case "q": - return m, tea.Quit + return m, boba.Quit } case tickMsg: m -= 1 if m <= 0 { - return m, tea.Quit + return m, boba.Quit } } @@ -57,13 +57,13 @@ func update(message tea.Msg, mdl tea.Model) (tea.Model, tea.Cmd) { return m, nil } -func subscriptions(_ tea.Model) tea.Subs { - return tea.Subs{ - "tick": tea.Every(time.Second, newTickMsg), +func subscriptions(_ boba.Model) boba.Subs { + return boba.Subs{ + "tick": boba.Every(time.Second, newTickMsg), } } -func view(mdl tea.Model) string { +func view(mdl boba.Model) string { m, _ := mdl.(model) return fmt.Sprintf("\n\n Hi. This program will exit in %d seconds...", m) } diff --git a/examples/go.mod b/examples/go.mod index 2aaddf1..07e3457 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -2,11 +2,12 @@ module examples go 1.13 -replace github.com/charmbracelet/tea => ../ +replace github.com/charmbracelet/boba => ../ require ( - github.com/charmbracelet/tea v0.0.0-20200130023737-bb06373836b4 - github.com/charmbracelet/teaparty v0.0.0-20200212224515-b4d35fd52906 + github.com/charmbracelet/boba v0.0.0-00010101000000-000000000000 + github.com/charmbracelet/tea v0.3.0 + github.com/charmbracelet/teaparty v0.0.0-20200511213328-a72bf9128d83 github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776 github.com/muesli/termenv v0.5.2 ) diff --git a/examples/go.sum b/examples/go.sum index 45dde5e..110b8d3 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -1,5 +1,11 @@ +github.com/charmbracelet/tea v0.0.0-20200130023737-bb06373836b4 h1:O8IGyYrKQuCwZZ98JP3DvzQCoPiXM5Y2zjwlDY7mOFM= +github.com/charmbracelet/tea v0.0.0-20200130023737-bb06373836b4/go.mod h1:UsFFdg04MNbcYi1r2FBtdDEFY07bObaYDKHhE1xZUaQ= +github.com/charmbracelet/tea v0.3.0 h1:W5F1x/IYeSCKpZl3/hM3Mn5v2KAagckabDFhhzh5sIE= +github.com/charmbracelet/tea v0.3.0/go.mod h1:uA/DUzCuyIZ1NFyAdCz6k+gF8lspujo6ZvoavcSsLCM= github.com/charmbracelet/teaparty v0.0.0-20200212224515-b4d35fd52906 h1:kcvv+hjb0dJiqhtMXkql5tczxalWMPvKIqwWo7cyhiQ= github.com/charmbracelet/teaparty v0.0.0-20200212224515-b4d35fd52906/go.mod h1:BG6oiwNZL9hB739ZOifRi3ePRGv0nT+kRTfxYLcZj/Y= +github.com/charmbracelet/teaparty v0.0.0-20200511213328-a72bf9128d83 h1:ivIS4ze0LLG9yl9L8cnYerh6dWnqhmBqh1ohmrA3I/I= +github.com/charmbracelet/teaparty v0.0.0-20200511213328-a72bf9128d83/go.mod h1:rlnGPwUokLHs2rQBiIYg6fpLM5m4DvtE2LwzdvS1wsk= github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776 h1:VRIbnDWRmAh5yBdz+J6yFMF5vso1It6vn+WmM/5l7MA= github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776/go.mod h1:9wvnDu3YOfxzWM9Cst40msBF1C2UdQgDv962oTxSuMs= github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f h1:5CjVwnuUcp5adK4gmY6i72gpVFVnZDP2h5TmPScB6u4= @@ -14,7 +20,10 @@ github.com/muesli/termenv v0.5.2/go.mod h1:O1/I6sw+6KcrgAmcs6uiUVr7Lui+DNVbHTzt9 github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942 h1:A7GG7zcGjl3jqAqGPmcNjd/D9hzL95SuoOQAaFNdLU0= github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200430202703-d923437fa56d h1:xmcims+WSpFuY56YEzkKF6IMDxYAVDRipkQRJfXUBZk= golang.org/x/sys v0.0.0-20200430202703-d923437fa56d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f h1:mOhmO9WsBaJCNmaZHPtHs9wOcdqdKCjF6OPJlmDM3KI= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/examples/http/main.go b/examples/http/main.go index 2c43011..d993ef6 100644 --- a/examples/http/main.go +++ b/examples/http/main.go @@ -9,7 +9,7 @@ import ( "net/http" "time" - "github.com/charmbracelet/tea" + "github.com/charmbracelet/boba" ) const url = "https://charm.sh/" @@ -23,17 +23,17 @@ type statusMsg int type errMsg error func main() { - p := tea.NewProgram(initialize, update, view, nil) + p := boba.NewProgram(initialize, update, view, nil) if err := p.Start(); err != nil { log.Fatal(err) } } -func initialize() (tea.Model, tea.Cmd) { +func initialize() (boba.Model, boba.Cmd) { return Model{0, nil}, checkServer } -func update(msg tea.Msg, model tea.Model) (tea.Model, tea.Cmd) { +func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) { m, ok := model.(Model) if !ok { return Model{err: errors.New("could not perform assertion on model during update")}, nil @@ -41,21 +41,21 @@ func update(msg tea.Msg, model tea.Model) (tea.Model, tea.Cmd) { switch msg := msg.(type) { - case tea.KeyMsg: + case boba.KeyMsg: switch msg.String() { case "esc": fallthrough case "ctrl+c": fallthrough case "q": - return m, tea.Quit + return m, boba.Quit default: return m, nil } case statusMsg: m.status = int(msg) - return m, tea.Quit + return m, boba.Quit case errMsg: m.err = msg @@ -66,7 +66,7 @@ func update(msg tea.Msg, model tea.Model) (tea.Model, tea.Cmd) { } } -func view(model tea.Model) string { +func view(model boba.Model) string { m, _ := model.(Model) s := fmt.Sprintf("Checking %s...", url) if m.err != nil { @@ -77,7 +77,7 @@ func view(model tea.Model) string { return s } -func checkServer() tea.Msg { +func checkServer() boba.Msg { c := &http.Client{ Timeout: 10 * time.Second, } diff --git a/examples/input/main.go b/examples/input/main.go index f32ea7a..9871a81 100644 --- a/examples/input/main.go +++ b/examples/input/main.go @@ -7,7 +7,7 @@ import ( "fmt" "log" - "github.com/charmbracelet/tea" + "github.com/charmbracelet/boba" "github.com/charmbracelet/teaparty/input" ) @@ -20,7 +20,7 @@ type tickMsg struct{} type errMsg error func main() { - p := tea.NewProgram( + p := boba.NewProgram( initialize, update, view, @@ -32,7 +32,7 @@ func main() { } } -func initialize() (tea.Model, tea.Cmd) { +func initialize() (boba.Model, boba.Cmd) { inputModel := input.DefaultModel() inputModel.Placeholder = "Pikachu" @@ -42,8 +42,8 @@ func initialize() (tea.Model, tea.Cmd) { }, nil } -func update(msg tea.Msg, model tea.Model) (tea.Model, tea.Cmd) { - var cmd tea.Cmd +func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) { + var cmd boba.Cmd m, ok := model.(Model) if !ok { // When we encounter errors in Update we simply add the error to the @@ -55,12 +55,12 @@ func update(msg tea.Msg, model tea.Model) (tea.Model, tea.Cmd) { } switch msg := msg.(type) { - case tea.KeyMsg: + case boba.KeyMsg: switch msg.Type { - case tea.KeyCtrlC: + case boba.KeyCtrlC: fallthrough - case tea.KeyEsc: - return m, tea.Quit + case boba.KeyEsc: + return m, boba.Quit } // We handle errors just like any other message @@ -73,18 +73,18 @@ func update(msg tea.Msg, model tea.Model) (tea.Model, tea.Cmd) { return m, cmd } -func subscriptions(model tea.Model) tea.Subs { - return tea.Subs{ +func subscriptions(model boba.Model) boba.Subs { + return boba.Subs{ // We just hand off the subscription to the input component, giving // it the model it expects. - "input": func(model tea.Model) tea.Msg { + "input": func(model boba.Model) boba.Msg { m, _ := model.(Model) return input.Blink(m.textInput) }, } } -func view(model tea.Model) string { +func view(model boba.Model) string { m, ok := model.(Model) if !ok { return "Oh no: could not perform assertion on model." diff --git a/examples/pager/main.go b/examples/pager/main.go index e41fc8e..77fcf73 100644 --- a/examples/pager/main.go +++ b/examples/pager/main.go @@ -5,7 +5,7 @@ import ( "io/ioutil" "os" - "github.com/charmbracelet/tea" + "github.com/charmbracelet/boba" "github.com/charmbracelet/teaparty/pager" ) @@ -16,8 +16,8 @@ func main() { os.Exit(1) } - tea.AltScreen() - defer tea.ExitAltScreen() + boba.AltScreen() + defer boba.ExitAltScreen() if err := pager.NewProgram(string(content)).Start(); err != nil { fmt.Println("could not run program:", err) os.Exit(1) diff --git a/examples/simple/main.go b/examples/simple/main.go index 60bf791..a751bd3 100644 --- a/examples/simple/main.go +++ b/examples/simple/main.go @@ -7,7 +7,7 @@ import ( "log" "time" - "github.com/charmbracelet/tea" + "github.com/charmbracelet/boba" ) // A model can be more or less any type of data. It holds all the data for a @@ -21,13 +21,13 @@ type tickMsg time.Time func main() { // Initialize our program - p := tea.NewProgram(initialize, update, view, subscriptions) + p := boba.NewProgram(initialize, update, view, subscriptions) if err := p.Start(); err != nil { log.Fatal(err) } } -func initialize() (tea.Model, tea.Cmd) { +func initialize() (boba.Model, boba.Cmd) { return Model(5), nil } @@ -35,16 +35,16 @@ func initialize() (tea.Model, tea.Cmd) { // 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 tea.Msg, model tea.Model) (tea.Model, tea.Cmd) { +func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) { m, _ := model.(Model) switch msg.(type) { - case tea.KeyMsg: - return m, tea.Quit + case boba.KeyMsg: + return m, boba.Quit case tickMsg: m -= 1 if m <= 0 { - return m, tea.Quit + return m, boba.Quit } } return m, nil @@ -52,16 +52,16 @@ func update(msg tea.Msg, model tea.Model) (tea.Model, tea.Cmd) { // Views take data from the model and return a string which will be rendered // to the terminal. -func view(model tea.Model) string { +func view(model boba.Model) string { m, _ := model.(Model) return fmt.Sprintf("Hi. This program will exit in %d seconds. To quit sooner press any key.", m) } // This is a subscription which we setup in NewProgram(). It waits for one // second, sends a tick, and then restarts. -func subscriptions(_ tea.Model) tea.Subs { - return tea.Subs{ - "tick": tea.Every(time.Second, func(t time.Time) tea.Msg { +func subscriptions(_ boba.Model) boba.Subs { + return boba.Subs{ + "tick": boba.Every(time.Second, func(t time.Time) boba.Msg { return tickMsg(t) }), } diff --git a/examples/spinner/main.go b/examples/spinner/main.go index 056216b..be37058 100644 --- a/examples/spinner/main.go +++ b/examples/spinner/main.go @@ -4,7 +4,7 @@ import ( "fmt" "log" - "github.com/charmbracelet/tea" + "github.com/charmbracelet/boba" "github.com/charmbracelet/teaparty/spinner" "github.com/muesli/termenv" ) @@ -21,13 +21,13 @@ type Model struct { type errMsg error func main() { - p := tea.NewProgram(initialize, update, view, subscriptions) + p := boba.NewProgram(initialize, update, view, subscriptions) if err := p.Start(); err != nil { log.Fatal(err) } } -func initialize() (tea.Model, tea.Cmd) { +func initialize() (boba.Model, boba.Cmd) { m := spinner.NewModel() m.Type = spinner.Dot @@ -36,7 +36,7 @@ func initialize() (tea.Model, tea.Cmd) { }, nil } -func update(msg tea.Msg, model tea.Model) (tea.Model, tea.Cmd) { +func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) { m, ok := model.(Model) if !ok { return model, nil @@ -44,14 +44,14 @@ func update(msg tea.Msg, model tea.Model) (tea.Model, tea.Cmd) { switch msg := msg.(type) { - case tea.KeyMsg: + case boba.KeyMsg: switch msg.String() { case "q": fallthrough case "esc": fallthrough case "ctrl+c": - return m, tea.Quit + return m, boba.Quit default: return m, nil } @@ -67,7 +67,7 @@ func update(msg tea.Msg, model tea.Model) (tea.Model, tea.Cmd) { } -func view(model tea.Model) string { +func view(model boba.Model) string { m, ok := model.(Model) if !ok { return "could not perform assertion on model in view" @@ -82,7 +82,7 @@ func view(model tea.Model) string { return fmt.Sprintf("\n\n %s Loading forever...press q to quit\n\n", s) } -func subscriptions(model tea.Model) tea.Subs { +func subscriptions(model boba.Model) boba.Subs { m, ok := model.(Model) if !ok { return nil @@ -92,7 +92,7 @@ func subscriptions(model tea.Model) tea.Subs { if err != nil { return nil } - return tea.Subs{ + return boba.Subs{ "tick": sub, } } diff --git a/go.mod b/go.mod index b6b5288..ee006e3 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/charmbracelet/tea +module github.com/charmbracelet/boba go 1.13 diff --git a/key.go b/key.go index 22adcc9..02d72a9 100644 --- a/key.go +++ b/key.go @@ -1,4 +1,4 @@ -package tea +package boba import ( "errors" diff --git a/logging.go b/logging.go index 3febb6c..b17fa7f 100644 --- a/logging.go +++ b/logging.go @@ -1,6 +1,6 @@ // +build darwin dragonfly freebsd linux netbsd openbsd solaris -package tea +package boba import ( "log" diff --git a/subscriptions.go b/subscriptions.go index 6443306..fb51d11 100644 --- a/subscriptions.go +++ b/subscriptions.go @@ -1,4 +1,4 @@ -package tea +package boba import ( "time" diff --git a/tty_unix.go b/tty_unix.go index 8fe0339..b911585 100644 --- a/tty_unix.go +++ b/tty_unix.go @@ -1,6 +1,6 @@ // +build darwin dragonfly freebsd linux netbsd openbsd solaris -package tea +package boba import ( "github.com/muesli/termenv" diff --git a/tty_windows.go b/tty_windows.go index 89d7e24..ae333e9 100644 --- a/tty_windows.go +++ b/tty_windows.go @@ -1,6 +1,6 @@ // +build windows -package tea +package boba import "github.com/muesli/termenv"