Terminalgränssnitt: BubbleTea (Go) vs Ratatui (Rust)

Elm-style (Go) vs immediate-mode (Rust) TUI-ramverk snabbvy

Sidinnehåll

Två starka alternativ för att bygga terminalanvändargränssnitt idag är BubbleTea (Go) och Ratatui (Rust). En ger dig en opinionsbaserad, Elm-stilad ramverk; den andra en flexibel, omedelbar lägebibliotek.

Den här artikeln sammanfattar vad varje alternativ är, visar ett minimalt exempel för båda och föreslår när du bör välja vilket. Och ja, den ger också några användbara länkar.

Crush UI - implementerad med BubbleTea ramverk

Crush UI (översiktsskärmen ovan) är implementerad med BubbleTea ramverk.

Vad är BubbleTea?

BubbleTea är ett Go-ramverk för TUI:s som baseras på The Elm Architecture. Du beskriver din app med en model (tillstånd) och tre delar: Init (initial kommando), Update (hantera meddelanden, returnera ny model och eventuell kommando), och View (rendera UI som en sträng). Ramverket kör händelse-loopen, omvandlar tangenttryck och I/O till meddelanden och återställer när modellen ändras. Så: vad är BubbleTea? Kort sagt, det är det roliga, tillståndsmässiga sättet att bygga terminalappar i Go med en enda källa till sanning och förutsägbara uppdateringar.

BubbleTea är produktionsklar (v1.x), har tiotusentals GitHub-stjärnor och tusentals kända importörer, och fungerar inline, fullskärmsvis eller blandat. Du parar ofta det med Bubbles för komponenter (inmatningar, vyportar, spinner) och Lip Gloss för stil. Om du bygger en Go TUI, är ett fast första steg att följa vanliga Go-projektstrukturer så att dina cmd/ och paket hålls tydliga när appen växer.

Ett minimalt BubbleTea-program ser ut så här: en model, Init, Update (hanterar tangentmeddelanden), och View som returnerar en sträng. Körningen gör resten.

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 := "Vad ska vi köpa?\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 + "\nTryck q för att avsluta.\n"
}

func main() {
    if _, err := tea.NewProgram(model{
        choices:  []string{"Köp morötter", "Köp persilja", "Köp kohlrabi"},
        selected: make(map[int]struct{}),
    }).Run(); err != nil {
        fmt.Printf("fel: %v", err)
        os.Exit(1)
    }
}

Notabla appar som byggts med BubbleTea inkluderar Crush (Charm’s TUI-baserade AI-kodningsagent), Glow, Huh, och många verktyg från toppens mest populära Go-projekt ekosystem. För mer komplexa Go-appar kan du lägga till beroendeinjektion och solid enhets-testning; samma idéer gäller för BubbleTea-modeller och kommandon.

Vad är Ratatui?

Ratatui är en Rust-bibliotek för TUI:s som använder omedelbar rendering: varje ram beskriver du hela UI:n (widgetar och layout), och Ratatui ritar den. Vad är Ratatui? Det är ett lättviktigt, opinionstunt verktyg – det pålägger inte en Elm-stilad modell eller en specifik appstruktur. Du behåller ditt eget tillstånd, kör din egen händelse-loop (ofta med crossterm, termion eller termwiz), och anropar terminal.draw(|f| { ... }) för att rendera. Så skillnaden mellan Elm-stil och omedelbar läge är exakt detta: i Elm-stil äger ramverket loopen och du reagerar via Update/View; i omedelbar läge äger du loopen och återställer hela UI:n från det aktuella tillståndet varje ram.

Ratatui används av över 2 100+ paket och förtroende från företag som Netflix (t.ex. bpftop), OpenAI, AWS (t.ex. amazon-q-developer-cli) och Vercel. Version 0.30.x är aktuell, med starka dokumentationer och valbara bakändor. Det är ett bra val när du vill ha full kontroll över inmatning och rendering, eller när du redan är i Rust-ekosystemet.

Ett minimalt Ratatui-program: du initierar terminalen, kör en loop som ritar och sedan läser händelser, och återställer terminalen vid avslut.

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("Hej, Ratatui! Tryck q för att avsluta.").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(())
}

Så: när bör jag välja BubbleTea mot Ratatui? Välj BubbleTea när du vill ha den snabbaste vägen till en polerad TUI i Go, med en enda modell och tydlig Update/View, och när din team eller ekosystem är Go (t.ex. du redan använder Go-ORM:er eller Ollama i Go). Välj Ratatui när du behöver maximal kontroll, är i Rust, eller bygger prestandakänsliga eller resurserbegränsade TUI:s; dess omedelbara design och valbara bakändor ger den flexibiliteten.

Sammanfattning

Aspekt BubbleTea (Go) Ratatui (Rust)
Stil Elm-arkitektur (model, Init/Update/View) Omedelbar läge (du äger loopen, ritar varje ram)
Ekosystem Bubbles, Lip Gloss, 10 000+ appar, Crush 2 100+ paket, Netflix/OpenAI/AWS/Vercel
Bäst för Snabb iteration, Go-teams, CLI:er Kontroll, prestanda, Rust-kodbasar

Båda är utmärkta val; det språk du föredrar och hur mycket struktur du vill ha från ramverket bör styra beslutet.

Några användbara länkar

Externa resurser