Upgrade to Pro — share decks privately, control downloads, hide ads and more …

入門 Bubble Tea

motemen
June 11, 2022

入門 Bubble Tea

motemen

June 11, 2022
Tweet

More Decks by motemen

Other Decks in Technology

Transcript

  1. charmbracelet/ bubbletea Go TUI The fun, functional and stateful way

    to build terminal apps. A Go framework based on The Elm Architecture.
  2. The Elm Architecture • Model: ΞϓϦέʔγϣϯͷεςʔτ • View: Model ͔Β

    HTML Λੜ੒ • Update: Msg ʹج͖ͮ Model Λߋ৽ • Msg ͸ϢʔβೖྗͳͲϞσϧͷ֎෦ View() Update(msg) Model Msg
  3. interface tea.Model // Model contains the program's state as well

    as its core functions. type Model interface { // Init is the first function that will be called. It returns an optional // initial command. To not perform an initial command return nil. Init() Cmd // Update is called when a message is received. Use it to inspect messages // and, in response, update the model and/or send a command. Update(Msg) (Model, Cmd) // View renders the program's UI, which is just a string. The view is // rendered after every Update. View() string }
  4. model, View() string type model struct { count int }

    func (model) Init() tea.Cmd { return nil } func (m model) View() string { return fmt.Sprintf("count: %v", m.count) }
  5. Update(tea.Msg) (tea.Model, tea.Cmd) func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd)

    { switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case " ": m.count = m.count + 1 return m, nil } } return m, nil } ߋ৽͞ΕͨϞσϧΛฦ͢ View() ͕ը໘ʹඳը͞ΕΔ
  6. Msg ͸Ϣʔβʗ֎ք͔Βͷೖྗ Msg contain data from the result of a

    IO operation. Msgs trigger the update function and, henceforth, the UI. tea.KeyMsg tea.MouseMsg tea.WindowMsg Msg type Msg interface{}
  7. bubbletea ʹ৐ͤΔ 🚀 func main() { prog := tea.NewProgram(model{count: 0})

    err := prog.Start() if err != nil { log.Fatal(err) } }
  8. ऴྃͰ͖ΔΑ͏ʹ͢Δ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch

    msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "q", "ctrl+c": return m, tea.Quit case " ": m.count = m.count + 1 return m, nil } } return m, nil } CmdΛฦ͢
  9. tea.Cmd • “Cmd is an IO operation that returns a

    message when it's complete” • ֎ք΁ͷ໋ྩ • ऴΘͬͨΒ Msg Λ໭ؔ͢਺ • goroutine Ͱ࣮ߦ͞ΕΔ View() Cmd Update(msg) Model Msg
  10. HTTP ௨৴Λ൐͏ྫ type countLoadedMsg struct { count int } func

    (m model) hitCounter() tea.Msg { count, err := m.api.Hit() if err != nil { panic(err) } return countLoadedMsg{count: count} } var _ tea.Cmd = model{}.hitCounter ͜ͷϝιουͷܕ͕ tea.Cmd IO͕ऴΘͬͨΒMsgΛฦ͢
  11. ΦϦδφϧͷ Msg Λड͚औΔ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd)

    { switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case " ": m.loading = true return m, m.hitCounter } case countLoadedMsg: m.count = msg.count m.loading = false return m, nil } return m, nil } CmdΛฦ͢ MsgΛड͚औͬͨΒϞσϧߋ৽
  12. Init(), View() func (m model) Init() tea.Cmd { return m.hitCounter

    } func (m model) View() string { if m.loading { return "..." } else { return fmt.Sprintf("count: %v", m.count) } } ϓϩάϥϜ։࢝࣌ʹൃߦ͍ͨ͠Cmd
  13. bubbles ࢖ͬͨྫ type model struct { ... spinner spinner.Model }

    func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd m.spinner, cmd = m.spinner.Update(msg) ... } func (m model) View() string { if m.loading { return m.spinner.View() } ... } func (m model) Init() tea.Cmd { return tea.Batch( m.hitCounter, m.spinner.Tick, ) } • charmbracelet/bubbles • bubbletea ༻ͷ TUI ίϯ ϙʔωϯτू ModelΛೖΕࢠʹ ࢠڙʹ΋MsgΛ౉͢ Ξχϝʔγϣϯ༻Cmd