Interfejs użytkownika terminala: BubbleTea (Go) vs Ratatui (Rust)

Szybki przegląd ramow TUI stylu Elm (Go) vs. trybu natychmiastowego (Rust)

Page content

Dwa silne opcje tworzenia interfejsów użytkownika terminala obecnie to BubbleTea (Go) i Ratatui (Rust). Jedna daje Ci opiniowany, stylowy framework w stylu Elm; druga – elastyczną, natychmiastową bibliotekę.

Ten post podsumowuje, co każdy z nich oferuje, pokazuje minimalny przykład dla obu i sugeruje, kiedy wybrać który. Tak, również podaje przydatne linki.

Crush UI - zaimplementowane przy użyciu frameworku BubbleTea

Crush UI (zrzut ekranu powyżej) jest zaimplementowane przy użyciu frameworku BubbleTea.

Co to jest BubbleTea?

BubbleTea to framework w języku Go do TUI oparty na architekturze Elm. Opisujesz swoje aplikacje za pomocą modelu (stanu) i trzech elementów: Init (początkowy komendy), Update (obsługa wiadomości, zwracanie nowego modelu i opcjonalnej komendy), oraz View (renderowanie interfejsu użytkownika jako łańcucha znaków). Framework uruchamia pętlę zdarzeń, przekształca naciśnięcia klawiszy i I/O na wiadomości, a ponownie rysuje, gdy zmienia się model. Więc: co to jest BubbleTea? Krótko mówiąc, to przyjemny, stanowy sposób na tworzenie aplikacji terminalowych w Go, z jednym źródłem prawdy i przewidywalnymi aktualizacjami.

BubbleTea jest gotowy do produkcji (wersja 1.x), ma dziesiątki tysięcy gwiazd na GitHubie i tysiące znanych importerów, a działa w trybie inline, pełnoekranowym lub mieszanym. Zazwyczaj łączy się z Bubbles do komponentów (wejścia, przewijania, spinnerów) i Lip Gloss do stylizacji. Jeśli tworzysz TUI w Go, solidnym pierwszym krokiem jest przestrzeganie typowych struktur projektów Go, aby cmd/ i pakiety były jasne, gdy aplikacja rośnie.

Minimalna aplikacja BubbleTea wygląda tak: model, Init, Update (obsługa wiadomości klucza), i View, która zwraca łańcuch znaków. Runtime zajmuje się resztą.

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 := "Co powinniśmy kupić?\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 + "\nNaciśnij q, aby wyjść.\n"
}

func main() {
    if _, err := tea.NewProgram(model{
        choices:  []string{"Kup marchewkę", "Kup szpinak", "Kup rzodkiewkę"},
        selected: make(map[int]struct{}),
    }).Run(); err != nil {
        fmt.Printf("błąd: %v", err)
        os.Exit(1)
    }
}

Znane aplikacje zbudowane przy użyciu BubbleTea obejmują Crush (agenta AI w stylu TUI firmy Charm), Glow, Huh i wiele narzędzi z ekosystemu najpopularniejszych projektów Go na GitHubie. Dla bardziej złożonych aplikacji Go możesz dodać iniekcję zależności i solidne testy jednostkowe; te same idee stosują się do modeli i poleceń w BubbleTea.

Co to jest Ratatui?

Ratatui to biblioteka w języku Rust do TUI, która korzysta z natychmiastowego renderowania: w każdej ramce opisujesz cały interfejs użytkownika (widgety i układ), a Ratatui rysuje go. Co to jest Ratatui? To lekkie, nieopiniowane narzędzie – nie narzucia architektury w stylu Elm ani określonej struktury aplikacji. Utrzymujesz własny stan, uruchamiasz własną pętlę zdarzeń (zazwyczaj z crossterm, termion lub termwiz), a następnie wywołujesz terminal.draw(|f| { ... }), aby wyrenderować. Więc różnica między stylem Elm a trybem natychmiastowym polega dokładnie na tym: w stylu Elm framework posiada pętlę, a Ty reagujesz poprzez Update/View; w trybie natychmiastowym Ty posiadasz pętlę i ponownie rysujesz cały interfejs użytkownika z bieżącego stanu w każdej ramce.

Ratatui jest używany przez ponad 2100 kratek i zaufany przez firmy takie jak Netflix (np. bpftop), OpenAI, AWS (np. amazon-q-developer-cli) i Vercel. Aktualna wersja to 0.30.x, z mocnymi dokumentacjami i opcjonalnymi backendami. To dobre dopasowanie, gdy chcesz pełną kontrolę nad wejściem i renderowaniem, lub gdy już jesteś w ekosystemie Rust.

Minimalna aplikacja Ratatui: inicjalizuj terminal, uruchom pętlę, która rysuje i czyta zdarzenia, a przy wyjściu przywracaj terminal.

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("Witaj, Ratatui! Naciśnij q, aby wyjść.").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(())
}

Więc: kiedy powinienem wybrać BubbleTea vs Ratatui? Wybierz BubbleTea, gdy chcesz najszybszy sposób na wytwarzanie polerowanego TUI w Go, z jednym modelem i wyraźnym Update/View, a także gdy Twoja drużyna lub ekosystem to Go (np. już korzystasz z ORM w Go lub Ollama w Go). Wybierz Ratatui, gdy potrzebujesz maksymalnej kontroli, jesteś w Rust, lub tworzysz TUI wrażliwe na wydajność lub ograniczone zasobowo; jego projekt natychmiastowy i opcjonalne backendy dają tę elastyczność.

Podsumowanie

Aspekt BubbleTea (Go) Ratatui (Rust)
Styl Architektura Elm (model, Init/Update/View) Tryb natychmiastowy (masz własną pętlę, rysujesz każdą ramkę)
Ekosystem Bubbles, Lip Gloss, 10k+ aplikacji, Crush 2100+ kratek, Netflix/OpenAI/AWS/Vercel
Najlepszy do Szybkiego iterowania, zespołów Go, CLI Kontroli, wydajności, kodowanych bazach danych w Rust

Oba są świetnym wyborem; preferowany język i stopień struktury, którą chcesz uzyskać od frameworku, powinny decydować o decyzji.

Przydatne linki

Zewnętrzne zasoby