Terminal UI: BubbleTea (Go) vs Ratatui (Rust)

Elm-stijl (Go) vs immediate-mode (Rust) TUI-kerstvensters quickview

Inhoud

Twee sterke opties voor het bouwen van terminalgebruikersinterfaces vandaag zijn BubbleTea (Go) en Ratatui (Rust). Een biedt je een opgezette, Elm-stijl framework; de ander een flexibele, immediate-mode bibliotheek.

Deze post samenvat wat elk is, laat een minimale voorbeeld zien voor beide, en stelt voor wanneer je welk moet kiezen. En ja, geeft ook enkele nuttige links.

Crush UI - geïmplementeerd met behulp van het BubbleTea framework

Crush UI (schermafdruk hierboven) is geïmplementeerd met behulp van het BubbleTea framework.

Wat is BubbleTea?

BubbleTea is een Go framework voor TUI’s gebaseerd op The Elm Architecture. Je beschrijft je app met een model (staat) en drie onderdelen: Init (initiële opdracht), Update (berichten verwerken, nieuwe model en optionele opdracht retourneren), en View (de UI als string renderen). Het framework voert de gebeurtenisloop uit, zet toetsaanslagen en I/O om in berichten en herlaadt wanneer het model verandert. Dus: wat is BubbleTea? Kort gezegd, het is de plezierige, statevolle manier om terminalapplicaties in Go te bouwen, met één bron van waarheid en voorspelbare updates.

BubbleTea is productie-geklaard (v1.x), heeft tienduizenden sterren op GitHub en duizenden bekende importeurs, en werkt inline, fullscreen of gemengd. Je gebruikt meestal Bubbles voor componenten (inputs, viewports, spinners) en Lip Gloss voor styling. Als je een Go TUI bouwt, is een solide eerste stap om te volgen de algemene Go projectstructuur zodat je cmd/ en pakketten duidelijk blijven als de app groeit.

Een minimale BubbleTea applicatie ziet er zo uit: een model, Init, Update (verwerkt toetsberichten), en View die een string retourneert. De runtime doet de rest.

package main

import (
    "fmt"
    "os"
    tea "github.com/charmbracelet/bubbletea"
)

type model struct {
    choices  []string
    cursor   int
    selected map[int]struct{}
}

func (m model) Init() tea.Cmd { return nil }

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
    switch msg := msg.(type) {
    case tea.KeyMsg:
        switch msg.String() {
        case "ctrl+c", "q":
            return m, tea.Quit
        case "up", "k":
            if m.cursor > 0 { m.cursor-- }
        case "down", "j":
            if m.cursor < len(m.choices)-1 { m.cursor++ }
        case "enter", " ":
            if _, ok := m.selected[m.cursor]; ok {
                delete(m.selected, m.cursor)
            } else {
                m.selected[m.cursor] = struct{}{}
            }
        }
    }
    return m, nil
}

func (m model) View() string {
    s := "Wat moeten we kopen?\n\n"
    for i, choice := range m.choices {
        cursor := " "
        if m.cursor == i { cursor = ">" }
        checked := " "
        if _, ok := m.selected[i]; ok { checked = "x" }
        s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice)
    }
    return s + "\nDruk op q om af te sluiten.\n"
}

func main() {
    if _, err := tea.NewProgram(model{
        choices:  []string{"Koop wortels", "Koop peen", "Koop knooppunt"},
        selected: make(map[int]struct{}),
    }).Run(); err != nil {
        fmt.Printf("fout: %v", err)
        os.Exit(1)
    }
}

Belangrijke apps gebouwd met BubbleTea omvatten Crush (Charm’s TUI-gebaseerde AI code agent), Glow, Huh en veel tools uit het top trending Go projecten ecosystem. Voor complexere Go apps kun je dependency injection en solide unit tests toevoegen; dezelfde ideeën gelden voor BubbleTea modellen en opdrachten.

Wat is Ratatui?

Ratatui is een Rust bibliotheek voor TUI’s die immediate-mode rendering gebruikt: elke frame beschrijf je de hele UI (widgets en layout), en Ratatui tekent het. Wat is Ratatui? Het is een lichtgewicht, onopgezette toolkit – het legt geen Elm-stijl model of specifieke app structuur op. Je houdt je eigen staat, draait je eigen gebeurtenisloop (meestal met crossterm, termion of termwiz), en roept terminal.draw(|f| { ... }) aan om te renderen. Dus de verschillen tussen Elm-stijl en immediate mode zijn precies dit: in Elm-stijl beheerst het framework de loop en reageer je via Update/View; in immediate mode beheer je de loop en herlaadt je de hele UI vanuit de huidige staat elke frame.

Ratatui wordt gebruikt door 2.100+ crates en vertrouwd door bedrijven zoals Netflix (bijvoorbeeld bpftop), OpenAI, AWS (bijvoorbeeld amazon-q-developer-cli) en Vercel. Versie 0.30.x is actueel, met sterke documentatie en optionele backends. Het is een goede keuze wanneer je volledige controle over invoer en rendering wilt, of wanneer je al in het Rust ecosystem bent.

Een minimale Ratatui app: je initialiseert de terminal, draait een lus die tekent en dan gebeurtenissen leest, en herstelt de terminal bij het afsluiten.

use crossterm::event::{self, Event, KeyCode};
use ratatui::{prelude::*, widgets::Paragraph};
use std::time::Duration;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut terminal = ratatui::init();
    loop {
        terminal.draw(|frame| {
            let area = frame.area();
            frame.render_widget(
                Paragraph::new("Hallo, Ratatui! Druk op q om af te sluiten.").alignment(Alignment::Center),
                area,
            );
        })?;
        if event::poll(Duration::from_millis(250))? {
            if let Event::Key(key) = event::read()? {
                if key.code == KeyCode::Char('q') {
                    break;
                }
            }
        }
    }
    ratatui::restore();
    Ok(())
}

Dus: wanneer moet ik BubbleTea kiezen in plaats van Ratatui? Kies BubbleTea wanneer je de snelste weg naar een afgeronde TUI in Go wilt, met één model en duidelijke Update/View, en wanneer je team of ecosystem Go is (bijvoorbeeld als je al Go ORMs of Ollama in Go gebruikt). Kies Ratatui wanneer je maximale controle nodig hebt, in Rust bent of performancekritische of resourcebeperkte TUI’s bouwt; zijn immediate-mode ontwerp en optionele backends geven dat flexibiliteit.

Samenvatting

Aspect BubbleTea (Go) Ratatui (Rust)
Stijl Elm Architecture (model, Init/Update/View) Immediate mode (je beheert de loop, teken elke frame)
Ecosysteem Bubbles, Lip Gloss, 10k+ apps, Crush 2,100+ crates, Netflix/OpenAI/AWS/Vercel
Beste voor Snel itereren, Go teams, CLI’s Controle, prestaties, Rust codebases

Beide zijn uitstekende keuzes; de voorkeur voor taal en hoeveel structuur we willen van het framework moet de beslissing bepalen.

Externe bronnen