Move components over and update examples

This commit is contained in:
Christian Rocha
2020-05-12 17:05:16 -04:00
parent 4bf40fbe62
commit 82ddbb8e12
15 changed files with 1002 additions and 57 deletions

View File

@@ -6,8 +6,8 @@ replace github.com/charmbracelet/boba => ../
require (
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
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 // indirect
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f // indirect
)

View File

@@ -1,11 +1,3 @@
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,16 +6,19 @@ github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tW
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/muesli/termenv v0.4.0/go.mod h1:O1/I6sw+6KcrgAmcs6uiUVr7Lui+DNVbHTzt9Lm/PlI=
github.com/muesli/termenv v0.5.2 h1:N1Y1dHRtx6OizOgaIQXd8SkJl4T/cCOV+YyWXiuLUEA=
github.com/muesli/termenv v0.5.2/go.mod h1:O1/I6sw+6KcrgAmcs6uiUVr7Lui+DNVbHTzt9Lm/PlI=
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/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@@ -74,7 +74,7 @@ func view(model boba.Model) string {
} else if m.status != 0 {
s += fmt.Sprintf("%d %s", m.status, http.StatusText(m.status))
}
return s
return s + "\n"
}
func checkServer() boba.Msg {

View File

@@ -1,14 +1,12 @@
package main
// A simple program that counts down from 5 and then exits.
import (
"errors"
"fmt"
"log"
"github.com/charmbracelet/boba"
"github.com/charmbracelet/teaparty/input"
input "github.com/charmbracelet/boba/textinput"
)
type Model struct {
@@ -33,8 +31,9 @@ func main() {
}
func initialize() (boba.Model, boba.Cmd) {
inputModel := input.DefaultModel()
inputModel := input.NewModel()
inputModel.Placeholder = "Pikachu"
inputModel.Focus()
return Model{
textInput: inputModel,
@@ -60,6 +59,8 @@ func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
case boba.KeyCtrlC:
fallthrough
case boba.KeyEsc:
fallthrough
case boba.KeyEnter:
return m, boba.Quit
}
@@ -74,13 +75,16 @@ func update(msg boba.Msg, model boba.Model) (boba.Model, boba.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{
// We just hand off the subscription to the input component, giving
// it the model it expects.
"input": func(model boba.Model) boba.Msg {
m, _ := model.(Model)
return input.Blink(m.textInput)
},
"input": sub,
}
}
@@ -95,5 +99,5 @@ func view(model boba.Model) string {
"Whats your favorite Pokémon?\n\n%s\n\n%s",
input.View(m.textInput),
"(esc to quit)",
)
) + "\n"
}

View File

@@ -6,7 +6,7 @@ import (
"os"
"github.com/charmbracelet/boba"
"github.com/charmbracelet/teaparty/pager"
"github.com/charmbracelet/boba/pager"
)
func main() {

View File

@@ -54,7 +54,7 @@ func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
// to the terminal.
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)
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

View File

@@ -2,10 +2,10 @@ package main
import (
"fmt"
"log"
"os"
"github.com/charmbracelet/boba"
"github.com/charmbracelet/teaparty/spinner"
"github.com/charmbracelet/boba/spinner"
"github.com/muesli/termenv"
)
@@ -14,8 +14,9 @@ var (
)
type Model struct {
spinner spinner.Model
err error
spinner spinner.Model
quitting bool
err error
}
type errMsg error
@@ -23,7 +24,8 @@ type errMsg error
func main() {
p := boba.NewProgram(initialize, update, view, subscriptions)
if err := p.Start(); err != nil {
log.Fatal(err)
fmt.Println(err)
os.Exit(1)
}
}
@@ -51,6 +53,7 @@ func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
case "esc":
fallthrough
case "ctrl+c":
m.quitting = true
return m, boba.Quit
default:
return m, nil
@@ -70,7 +73,7 @@ func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
func view(model boba.Model) string {
m, ok := model.(Model)
if !ok {
return "could not perform assertion on model in view"
return "could not perform assertion on model in view\n"
}
if m.err != nil {
return m.err.Error()
@@ -79,7 +82,11 @@ func view(model boba.Model) string {
String(spinner.View(m.spinner)).
Foreground(color.Color("205")).
String()
return fmt.Sprintf("\n\n %s Loading forever...press q to quit\n\n", s)
str := fmt.Sprintf("\n\n %s Loading forever...press q to quit\n\n", s)
if m.quitting {
return str + "\n"
}
return str
}
func subscriptions(model boba.Model) boba.Subs {

202
examples/textinputs/main.go Normal file
View File

@@ -0,0 +1,202 @@
package main
import (
"fmt"
"os"
"github.com/charmbracelet/boba"
input "github.com/charmbracelet/boba/textinput"
te "github.com/muesli/termenv"
)
var (
color = te.ColorProfile().Color
focusedText = "205"
focusedPrompt = te.String("> ").Foreground(color("205")).String()
blurredPrompt = "> "
focusedSubmitButton = "[ " + te.String("Submit").Foreground(color("205")).String() + " ]"
blurredSubmitButton = "[ " + te.String("Submit").Foreground(color("240")).String() + " ]"
)
func main() {
if err := boba.NewProgram(
initialize,
update,
view,
subscriptions,
).Start(); err != nil {
fmt.Printf("could not start program: %s\n", err)
os.Exit(1)
}
}
type Model struct {
index int
nameInput input.Model
nickNameInput input.Model
emailInput input.Model
submitButton string
}
func initialize() (boba.Model, boba.Cmd) {
name := input.NewModel()
name.Placeholder = "Name"
name.Focus()
name.Prompt = focusedPrompt
name.TextColor = focusedText
nickName := input.NewModel()
nickName.Placeholder = "Nickname"
nickName.Prompt = blurredPrompt
email := input.NewModel()
email.Placeholder = "Email"
email.Prompt = blurredPrompt
return Model{0, name, nickName, email, blurredSubmitButton}, nil
}
func update(msg boba.Msg, model boba.Model) (boba.Model, boba.Cmd) {
m, ok := model.(Model)
if !ok {
panic("could not perform assertion on model")
}
switch msg := msg.(type) {
case boba.KeyMsg:
switch msg.String() {
case "ctrl+c":
return m, boba.Quit
// Cycle between inputs
case "tab":
fallthrough
case "shift+tab":
fallthrough
case "enter":
fallthrough
case "up":
fallthrough
case "down":
inputs := []input.Model{
m.nameInput,
m.nickNameInput,
m.emailInput,
}
s := msg.String()
// Did the user press enter while the submit button was focused?
// If so, exit.
if s == "enter" && m.index == len(inputs) {
return m, boba.Quit
}
// Cycle indexes
if s == "up" || s == "shift+tab" {
m.index--
} else {
m.index++
}
if m.index > len(inputs) {
m.index = 0
} else if m.index < 0 {
m.index = len(inputs)
}
for i := 0; i <= len(inputs)-1; i++ {
if i == m.index {
// Focused input
inputs[i].Focus()
inputs[i].Prompt = focusedPrompt
inputs[i].TextColor = focusedText
continue
}
// Blurred input
inputs[i].Blur()
inputs[i].Prompt = blurredPrompt
inputs[i].TextColor = ""
}
m.nameInput = inputs[0]
m.nickNameInput = inputs[1]
m.emailInput = inputs[2]
if m.index == len(inputs) {
m.submitButton = focusedSubmitButton
} else {
m.submitButton = blurredSubmitButton
}
return m, nil
default:
// Handle character input
m = updateInputs(msg, m)
return m, nil
}
default:
// Handle blinks
m = updateInputs(msg, m)
return m, nil
}
}
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 view(model boba.Model) string {
m, ok := model.(Model)
if !ok {
return "[error] could not perform assertion on model"
}
s := "\n"
inputs := []string{
input.View(m.nameInput),
input.View(m.nickNameInput),
input.View(m.emailInput),
}
for i := 0; i < len(inputs); i++ {
s += inputs[i]
if i < len(inputs)-1 {
s += "\n"
}
}
s += "\n\n" + m.submitButton + "\n"
return s
}

View File

@@ -8,12 +8,12 @@ import (
"strings"
"time"
"github.com/charmbracelet/tea"
"github.com/charmbracelet/boba"
"github.com/fogleman/ease"
)
func main() {
p := tea.NewProgram(
p := boba.NewProgram(
initialize,
update,
view,
@@ -28,13 +28,13 @@ func main() {
type tickMsg time.Time
func newTickMsg(t time.Time) tea.Msg {
func newTickMsg(t time.Time) boba.Msg {
return tickMsg(t)
}
type frameMsg time.Time
func newFrameMsg(t time.Time) tea.Msg {
func newFrameMsg(t time.Time) boba.Msg {
return frameMsg(t)
}
@@ -52,27 +52,27 @@ type Model struct {
// INIT
func initialize() (tea.Model, tea.Cmd) {
func initialize() (boba.Model, boba.Cmd) {
return Model{0, false, 10, 0, 0, false}, nil
}
// SUBSCRIPTIONS
func subscriptions(model tea.Model) tea.Subs {
func subscriptions(model boba.Model) boba.Subs {
m, _ := model.(Model)
if !m.Chosen || m.Loaded {
return tea.Subs{
"tick": tea.Every(time.Second, newTickMsg),
return boba.Subs{
"tick": boba.Every(time.Second, newTickMsg),
}
}
return tea.Subs{
"frame": tea.Every(time.Second/60, newFrameMsg),
return boba.Subs{
"frame": boba.Every(time.Second/60, newFrameMsg),
}
}
// UPDATE
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)
if !m.Chosen {
@@ -81,10 +81,10 @@ func update(msg tea.Msg, model tea.Model) (tea.Model, tea.Cmd) {
return updateChosen(msg, m)
}
func updateChoices(msg tea.Msg, m Model) (tea.Model, tea.Cmd) {
func updateChoices(msg boba.Msg, m Model) (boba.Model, boba.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
case boba.KeyMsg:
switch msg.String() {
case "j":
fallthrough
@@ -108,12 +108,12 @@ func updateChoices(msg tea.Msg, m Model) (tea.Model, tea.Cmd) {
case "esc":
fallthrough
case "ctrl+c":
return m, tea.Quit
return m, boba.Quit
}
case tickMsg:
if m.Ticks == 0 {
return m, tea.Quit
return m, boba.Quit
}
m.Ticks -= 1
}
@@ -121,17 +121,17 @@ func updateChoices(msg tea.Msg, m Model) (tea.Model, tea.Cmd) {
return m, nil
}
func updateChosen(msg tea.Msg, m Model) (tea.Model, tea.Cmd) {
func updateChosen(msg boba.Msg, m Model) (boba.Model, boba.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
}
case frameMsg:
@@ -148,7 +148,7 @@ func updateChosen(msg tea.Msg, m Model) (tea.Model, tea.Cmd) {
case tickMsg:
if m.Loaded {
if m.Ticks == 0 {
return m, tea.Quit
return m, boba.Quit
}
m.Ticks -= 1
}
@@ -159,12 +159,12 @@ func updateChosen(msg tea.Msg, m Model) (tea.Model, tea.Cmd) {
// VIEW
func view(model tea.Model) string {
func view(model boba.Model) string {
m, _ := model.(Model)
if !m.Chosen {
return choicesView(m)
return choicesView(m) + "\n"
}
return chosenView(m)
return chosenView(m) + "\n"
}
const choicesTpl = `What to do today?