Skip to content

Commit

Permalink
docs(tutorials): upgrade tuts to v2 (#1155)
Browse files Browse the repository at this point in the history
  • Loading branch information
meowgorithm authored Sep 18, 2024
1 parent 7cb34be commit 3274e41
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 80 deletions.
37 changes: 15 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,34 +89,27 @@ type model struct {
}
```

### Initialization
## Initialization

Next, we’ll define our application’s initial state. In this case, we’re defining
a function to return our initial model, however, we could just as easily define
the initial model as a variable elsewhere, too.
Next, we’ll define our application’s initial state in the `Init` method. `Init`
can return a `Cmd` that could perform some initial I/O. For now, we don't need
to do any I/O, so for the command, we'll just return `nil`, which translates to
"no command."

```go
func initialModel() model {
return model{
func (m model) Init() (tea.Model, tea.Cmd) {
m = {
// Our to-do list is a grocery list
choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"},

// A map which indicates which choices are selected. We're using
// the map like a mathematical set. The keys refer to the indexes
// the map like a mathematical set. The keys refer to the indexes
// of the `choices` slice, above.
selected: make(map[int]struct{}),
}
}
```

Next, we define the `Init` method. `Init` can return a `Cmd` that could perform
some initial I/O. For now, we don't need to do any I/O, so for the command,
we'll just return `nil`, which translates to "no command."

```go
func (m model) Init() tea.Cmd {
// Just return `nil`, which means "no I/O right now, please."
return nil
return m, nil
}
```

Expand All @@ -137,15 +130,15 @@ tick, or a response from a server.
We usually figure out which type of `Msg` we received with a type switch, but
you could also use a type assertion.

For now, we'll just deal with `tea.KeyMsg` messages, which are automatically
sent to the update function when keys are pressed.
For now, we'll just deal with `tea.KeyPressMsg` messages, which are
automatically sent to the update function when keys are pressed.

```go
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {

// Is it a key press?
case tea.KeyMsg:
case tea.KeyPressMsg:

// Cool, what was the actual key pressed?
switch msg.String() {
Expand All @@ -166,9 +159,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.cursor++
}

// The "enter" key and the spacebar (a literal space) toggle
// the selected state for the item that the cursor is pointing at.
case "enter", " ":
// The "enter" key and the space bar (a literal space) toggle the
// selected state for the item that the cursor is pointing at.
case "enter", "space":
_, ok := m.selected[m.cursor]
if ok {
delete(m.selected, m.cursor)
Expand Down
60 changes: 26 additions & 34 deletions tutorials/basics/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
Bubble Tea Basics
=================
# Bubble Tea Basics

Bubble Tea is based on the functional design paradigms of [The Elm
Architecture][elm], which happens to work nicely with Go. It's a delightful way
Expand All @@ -11,7 +10,7 @@ By the way, the non-annotated source code for this program is available
[on GitHub][tut-source].

[elm]: https://guide.elm-lang.org/architecture/
[tut-source]:https://github.com/charmbracelet/bubbletea/tree/master/tutorials/basics
[tut-source]: https://github.com/charmbracelet/bubbletea/tree/master/tutorials/basics

## Enough! Let's get to it.

Expand All @@ -34,9 +33,9 @@ import (
Bubble Tea programs are comprised of a **model** that describes the application
state and three simple methods on that model:

* **Init**, a function that returns an initial command for the application to run.
* **Update**, a function that handles incoming events and updates the model accordingly.
* **View**, a function that renders the UI based on the data in the model.
- **Init**, a function that returns an initial command for the application to run.
- **Update**, a function that handles incoming events and updates the model accordingly.
- **View**, a function that renders the UI based on the data in the model.

## The Model

Expand All @@ -53,13 +52,14 @@ type model struct {

## Initialization

Next, we’ll define our application’s initial state. In this case, we’re defining
a function to return our initial model, however, we could just as easily define
the initial model as a variable elsewhere, too.
Next, we’ll define our application’s initial state in the `Init` method. `Init`
can return a `Cmd` that could perform some initial I/O. For now, we don't need
to do any I/O, so for the command, we'll just return `nil`, which translates to
"no command."

```go
func initialModel() model {
return model{
func (m model) Init() (tea.Model, tea.Cmd) {
m = {
// Our to-do list is a grocery list
choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"},

Expand All @@ -68,17 +68,9 @@ func initialModel() model {
// of the `choices` slice, above.
selected: make(map[int]struct{}),
}
}
```

Next, we define the `Init` method. `Init` can return a `Cmd` that could perform
some initial I/O. For now, we don't need to do any I/O, so for the command,
we'll just return `nil`, which translates to "no command."

```go
func (m model) Init() (tea.Model, tea.Cmd) {
// Just return `nil`, which means "no I/O right now, please."
return nil
return m, nil
}
```

Expand All @@ -99,15 +91,15 @@ tick, or a response from a server.
We usually figure out which type of `Msg` we received with a type switch, but
you could also use a type assertion.

For now, we'll just deal with `tea.KeyMsg` messages, which are automatically
sent to the update function when keys are pressed.
For now, we'll just deal with `tea.KeyPressMsg` messages, which are
automatically sent to the update function when keys are pressed.

```go
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {

// Is it a key press?
case tea.KeyMsg:
case tea.KeyPressMsg:

// Cool, what was the actual key pressed?
switch msg.String() {
Expand All @@ -128,9 +120,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.cursor++
}

// The "enter" key and the spacebar (a literal space) toggle
// the selected state for the item that the cursor is pointing at.
case "enter", " ":
// The enter key and the space bar toggle the selected state for the
// item that the cursor is pointing at.
case "enter", "space":
_, ok := m.selected[m.cursor]
if ok {
delete(m.selected, m.cursor)
Expand Down Expand Up @@ -194,12 +186,12 @@ func (m model) View() string {

## All Together Now

The last step is to simply run our program. We pass our initial model to
The last step is to simply run our program. We pass and empty model
`tea.NewProgram` and let it rip:

```go
func main() {
p := tea.NewProgram(initialModel())
p := tea.NewProgram(model{})
if _, err := p.Run(); err != nil {
fmt.Printf("Alas, there's been an error: %v", err)
os.Exit(1)
Expand All @@ -222,18 +214,18 @@ there are [Go Docs][docs].

## Additional Resources

* [Libraries we use with Bubble Tea](https://github.com/charmbracelet/bubbletea/#libraries-we-use-with-bubble-tea)
* [Bubble Tea in the Wild](https://github.com/charmbracelet/bubbletea/#bubble-tea-in-the-wild)
- [Libraries we use with Bubble Tea](https://github.com/charmbracelet/bubbletea/#libraries-we-use-with-bubble-tea)
- [Bubble Tea in the Wild](https://github.com/charmbracelet/bubbletea/#bubble-tea-in-the-wild)

### Feedback

We'd love to hear your thoughts on this tutorial. Feel free to drop us a note!

* [Twitter](https://twitter.com/charmcli)
* [The Fediverse](https://mastodon.social/@charmcli)
* [Discord](https://charm.sh/chat)
- [Twitter](https://twitter.com/charmcli)
- [The Fediverse](https://mastodon.social/@charmcli)
- [Discord](https://charm.sh/chat)

***
---

Part of [Charm](https://charm.sh).

Expand Down
13 changes: 5 additions & 8 deletions tutorials/basics/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,21 @@ type model struct {
selected map[int]struct{}
}

func initialModel() model {
return model{
func (m model) Init() (tea.Model, tea.Cmd) {
m = model{
choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"},

// A map which indicates which choices are selected. We're using
// the map like a mathematical set. The keys refer to the indexes
// of the `choices` slice, above.
selected: make(map[int]struct{}),
}
}

func (m model) Init() (tea.Model, tea.Cmd) {
return m, tea.SetWindowTitle("Grocery List")
}

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
case tea.KeyPressMsg:
switch msg.String() {
case "ctrl+c", "q":
return m, tea.Quit
Expand All @@ -42,7 +39,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.cursor < len(m.choices)-1 {
m.cursor++
}
case "enter", " ":
case "enter", "space":
_, ok := m.selected[m.cursor]
if ok {
delete(m.selected, m.cursor)
Expand Down Expand Up @@ -78,7 +75,7 @@ func (m model) View() string {
}

func main() {
p := tea.NewProgram(initialModel())
p := tea.NewProgram(model{})
if _, err := p.Run(); err != nil {
fmt.Printf("Alas, there's been an error: %v", err)
os.Exit(1)
Expand Down
27 changes: 13 additions & 14 deletions tutorials/commands/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
Commands in Bubble Tea
======================
# Commands in Bubble Tea

This is the second tutorial for Bubble Tea covering commands, which deal with
I/O. The tutorial assumes you have a working knowledge of Go and a decent
Expand Down Expand Up @@ -92,8 +91,8 @@ Note that we don't call the function; the Bubble Tea runtime will do that when
the time is right.

```go
func (m model) Init() (tea.Cmd) {
return checkServer
func (m model) Init() (tea.Model, tea.Cmd) {
return m, checkServer
}
```

Expand Down Expand Up @@ -122,13 +121,13 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.err = msg
return m, tea.Quit

case tea.KeyMsg:
case tea.KeyPressMsg:
// Ctrl+c exits. Even with short running programs it's good to have
// a quit key, just in case your logic is off. Users will be very
// annoyed if they can't exit.
if msg.Type == tea.KeyCtrlC {
return m, tea.Quit
}
if msg.Mod == tea.ModCtrl && msg.Code == 'c' {
return m, tea.Quit
}
}

// If we happen to get any other messages, don't do anything.
Expand Down Expand Up @@ -227,18 +226,18 @@ And, of course, check out the [Go Docs][docs].

## Additional Resources

* [Libraries we use with Bubble Tea](https://github.com/charmbracelet/bubbletea/#libraries-we-use-with-bubble-tea)
* [Bubble Tea in the Wild](https://github.com/charmbracelet/bubbletea/#bubble-tea-in-the-wild)
- [Libraries we use with Bubble Tea](https://github.com/charmbracelet/bubbletea/#libraries-we-use-with-bubble-tea)
- [Bubble Tea in the Wild](https://github.com/charmbracelet/bubbletea/#bubble-tea-in-the-wild)

### Feedback

We'd love to hear your thoughts on this tutorial. Feel free to drop us a note!

* [Twitter](https://twitter.com/charmcli)
* [The Fediverse](https://mastodon.social/@charmcli)
* [Discord](https://charm.sh/chat)
- [Twitter](https://twitter.com/charmcli)
- [The Fediverse](https://mastodon.social/@charmcli)
- [Discord](https://charm.sh/chat)

***
---

Part of [Charm](https://charm.sh).

Expand Down
4 changes: 2 additions & 2 deletions tutorials/commands/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.err = msg
return m, tea.Quit

case tea.KeyMsg:
if msg.String() == "ctrl+c" {
case tea.KeyPressMsg:
if msg.Mod == tea.ModCtrl && msg.Code == 'c' {
return m, tea.Quit
}
}
Expand Down

0 comments on commit 3274e41

Please sign in to comment.