One of the things that has always fascinated me is terminal utilities, whether in CLI mode or TUI. It’s no coincidence this blog has its name 😃.
And one of the coolest libraries out there is Charmbracelet Bubbles.
I’ve been testing it for a few years, but this year I decided to actually learn it. Even though I do a lot with C++, Bubbles is for Go, and I still need to mature my Golang skills. That’s one of the reasons I created this series on the blog—I’ll be using it frequently for quick references! 😎
Bubbles is a collection of TUI components that makes building terminal interfaces easier with reactive logic and an attractive visual design.
It includes:
To see how amazing it really is, let’s compile this Textarea example with Bubbles:
mkdir textarea
cd textarea
go mod init textarea
go get github.com/charmbracelet/bubbles/textarea
Now, still inside your project, create a file (e.g., main.go
) and paste the following content:
package main
// A simple program demonstrating the textarea component from the Bubbles
// component library.
import (
"fmt"
"log"
"github.com/charmbracelet/bubbles/textarea"
tea "github.com/charmbracelet/bubbletea"
)
func main() {
p := tea.NewProgram(initialModel())
if _, err := p.Run(); err != nil {
log.Fatal(err)
}
}
type errMsg error
type model struct {
textarea textarea.Model
err error
}
func initialModel() model {
ti := textarea.New()
ti.Placeholder = "Once upon a time..."
ti.Focus()
return model{
textarea: ti,
err: nil,
}
}
func (m model) Init() tea.Cmd {
return textarea.Blink
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
var cmd tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.Type {
case tea.KeyEsc:
if m.textarea.Focused() {
m.textarea.Blur()
}
case tea.KeyCtrlC:
return m, tea.Quit
default:
if !m.textarea.Focused() {
cmd = m.textarea.Focus()
cmds = append(cmds, cmd)
}
}
// We handle errors just like any other message
case errMsg:
m.err = msg
return m, nil
}
m.textarea, cmd = m.textarea.Update(msg)
cmds = append(cmds, cmd)
return m, tea.Batch(cmds...)
}
func (m model) View() string {
return fmt.Sprintf(
"Tell me a story.\n\n%s\n\n%s",
m.textarea.View(),
"(ctrl+c to quit)",
) + "\n\n"
}
Compile and run:
go build main.go
./main
The output will be similar to the GIF below. Try typing something—pressing [enter] creates a new line.
Amazing, right?
Go modules are usually created in a directory under your user’s home. Some files have system permissions, so to remove the directory, run:
sudo rm -rf ~/go/
Bubbles uses the Elm architecture: model
, init
, update
, view
, and provides ready-to-use components. You just need to integrate them into the Bubble Tea model. The example we saw was taken from here.
For more info, visit: https://github.com/charmbracelet/bubbles.