Créer des interfaces utilisateur en terminal avec Charm
Si vous avez déjà utilisé lazygit, k9s ou htop, vous avez expérimenté ce que peut offrir une interface utilisateur en terminal bien conçue — réactive, structurée et étonnamment élégante. Créer quelque chose de similaire signifiait auparavant se battre avec ncurses ou écrire des codes d’échappement bruts. L’écosystème Charm change complètement la donne.
Cet article explique comment créer des interfaces utilisateur en terminal avec Charm en utilisant Go, en se concentrant sur Bubble Tea et ses bibliothèques complémentaires. Les versions majeures actuelles des bibliothèques Charm utilisent des chemins de modules Go mis à jour, ce que vous verrez reflété dans les exemples ci-dessous. Si vous raisonnez en termes de composants et d’état, le modèle mental vous semblera immédiatement familier.
Points clés à retenir
- Bubble Tea suit l’architecture Elm (Model, Update, View), rendant la gestion d’état prévisible et composable.
- Lip Gloss fournit un style déclaratif pour la sortie terminal, tandis que Bubbles offre des composants d’interface prêts à l’emploi comme des champs de saisie, des spinners et des viewports.
- Les bibliothèques de l’écosystème Charm se superposent proprement les unes aux autres, vous permettant de créer des TUI soignées en Go sans codes d’échappement bruts ni ncurses.
- Huh et Wish étendent la pile respectivement pour les formulaires et les TUI hébergées via SSH.
Qu’est-ce qu’une TUI et pourquoi en créer une ?
Une Interface Utilisateur en Terminal (TUI) est une application interactive et visuellement structurée qui s’exécute dans un terminal. Contrairement à une CLI classique qui accepte une commande et se termine, une TUI maintient un état, répond aux entrées clavier en temps réel et affiche des mises en page dynamiques.
Les TUI valent la peine d’être créées lorsque vous souhaitez :
- Un outil de développement qui fonctionne via SSH sans navigateur
- Une consommation de ressources inférieure à celle d’une application Electron
- Quelque chose de scriptable qui reste soigné
L’écosystème Charm en un coup d’œil
Charm maintient plusieurs bibliothèques qui fonctionnent bien ensemble :
| Bibliothèque | Rôle |
|---|---|
| Bubble Tea | Framework applicatif (boucle d’événements, état) |
| Lip Gloss | Style et mise en page |
| Bubbles | Composants d’interface préconstruits |
| Huh | Primitives de formulaires et de saisie |
| Wish | Serveur SSH pour héberger des TUI à distance |
Bubble Tea est le cœur. Tout le reste se superpose par-dessus.
Comment fonctionne l’architecture de Bubble Tea (Model, Update, View)
Bubble Tea suit l’architecture Elm, un pattern que les développeurs frontend reconnaîtront de Redux ou du hook useReducer de React.
Chaque application Bubble Tea définit trois éléments :
- Model — l’état de votre application
- Update — une fonction qui gère les messages et retourne un nouveau modèle
- View — une fonction qui rend le modèle sous forme de vue terminal
package main
import (
"fmt"
"log"
tea "charm.land/bubbletea/v2"
)
type model struct {
count int
}
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.KeyPressMsg:
switch msg.String() {
case "up":
m.count++
case "q", "ctrl+c":
return m, tea.Quit
}
}
return m, nil
}
func (m model) View() tea.View {
return tea.NewView(fmt.Sprintf("Count: %d\n(press up to increment, q to quit)", m.count))
}
func main() {
p := tea.NewProgram(model{})
if _, err := p.Run(); err != nil {
log.Fatal(err)
}
}
Notez le chemin d’import charm.land/bubbletea/v2. Les versions actuelles des bibliothèques Charm utilisent des chemins de modules charm.land plutôt que les anciens imports github.com/charmbracelet/* qui apparaissent dans de nombreux tutoriels plus anciens.
Ajouter des mises en page et du style avec Lip Gloss
Lip Gloss gère le style. Vous définissez des styles comme des valeurs et les appliquez aux chaînes de caractères avant le rendu.
import "charm.land/lipgloss/v2"
var titleStyle = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("#FF79C6")).
Padding(0, 1)
func (m model) View() tea.View {
return tea.NewView(titleStyle.Render("My TUI App"))
}
Note : Les versions récentes de Lip Gloss ont modifié le fonctionnement du comportement adaptatif des couleurs. La détection de l’arrière-plan et l’adaptation du style sont désormais gérées plus explicitement dans le code de l’application plutôt qu’automatiquement par la bibliothèque.
Discover how at OpenReplay.com.
Utiliser des composants préconstruits de Bubbles
Bubbles fournit des composants prêts à l’emploi — champs de saisie de texte, spinners, barres de progression, viewports, et plus encore. Chaque composant suit le même contrat Model/Update/View, vous pouvez donc les intégrer directement dans votre propre modèle.
import "charm.land/bubbles/v2/textinput"
type model struct {
input textinput.Model
}
Cette composabilité est ce qui permet à Bubble Tea de bien évoluer. Vous construisez des modèles petits et ciblés et les composez en modèles plus grands, exactement comme la composition de composants dans un framework frontend.
Quand utiliser Huh ou Wish
Si votre TUI nécessite des formulaires — saisies multi-champs, confirmations, menus de sélection — Huh gère cela sans que vous ayez à le construire de zéro. Pour héberger une TUI via SSH afin que les utilisateurs puissent y accéder sans rien installer localement, Wish encapsule votre programme Bubble Tea dans un serveur SSH.
Démarrage
go mod init mytui
go get charm.land/bubbletea/v2
go get charm.land/lipgloss/v2
go get charm.land/bubbles/v2
Exécutez votre programme avec :
func main() {
p := tea.NewProgram(model{})
if _, err := p.Run(); err != nil {
log.Fatal(err)
}
}
Conclusion
La pile Charm Bubble Tea vous offre une façon structurée et composable de créer des applications en terminal avec Go. Le pattern Model/Update/View maintient l’état prévisible, Lip Gloss gère le style de manière déclarative, et Bubbles vous fournit des composants que vous passeriez autrement des jours à écrire. Si vous êtes à l’aise avec la pensée frontend basée sur les composants, créer des interfaces utilisateur en terminal avec Charm vous semblera moins comme l’apprentissage d’un nouveau paradigme et plus comme l’application d’un paradigme que vous connaissez déjà — simplement dans un terminal.
FAQ
Bubble Tea est une bibliothèque Go, vous avez donc besoin d'au moins une compréhension de base de Go pour l'utiliser. Cela dit, l'architecture inspirée d'Elm est simple. Si vous êtes familier avec des concepts comme l'état, les messages et les fonctions de rendu dans n'importe quel langage, vous pouvez assimiler la syntaxe spécifique à Go relativement rapidement.
Les versions actuelles utilisent des chemins de modules charm.land tels que charm.land/bubbletea/v2 au lieu des anciens imports github.com/charmbracelet que l'on trouve dans de nombreux tutoriels plus anciens. La fonction Init ne retourne qu'une commande, et la fonction View retourne une vue terminal plutôt qu'une chaîne de caractères brute.
Oui. Comme Update est une fonction pure qui prend un message et retourne un nouveau modèle et une commande, vous pouvez tester unitairement votre logique applicative en appelant Update directement avec des messages spécifiques et en faisant des assertions sur l'état du modèle retourné. La fonction View peut également être testée en vérifiant sa sortie rendue.
Oui. La bibliothèque Wish vous permet d'encapsuler n'importe quel programme Bubble Tea dans un serveur SSH. Les utilisateurs se connectent via SSH et interagissent avec votre TUI directement dans leur terminal sans rien installer localement. C'est utile pour les outils de développement partagés, les tableaux de bord ou les démos interactives.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.