Was macht terminal-rendering?
Ein Terminal-Bildschirm ist ein Spalten × Zeilen-Zellgitter. Korrektheit kommt von VT; „好看“ (Schönheit) kommt von Metriken + Paint. Gleicher Emulator ≠ gleiches Aussehen.
Vier Schichten
| Schicht | Aufgabe | Bei Fehlern |
|---|---|---|
| 1. VT | Bytes → Zellgitter (Cursor, Modi, Scrollback, alternativer Bildschirm) | Verzerrt / falsche Größe / hängender Cursor |
| 2. Metriken | Zellenbreite/-höhe aus Schriftart; PTY-Resize mit Spalten/Zeilen und Zellen-Px | Wackelige Spalten, unscharfe Ränder |
| 3. Paint | Zellen zeichnen: Hintergrundläufe, Glyphen, Sprites, Kontrast | Lücken, dünner Text, zerbrochene TUI-Ränder |
| 4. Sitzung (optional) | Persistieren / Remote: Daemon besitzt VT, Client spiegelt Frames | Scrollback stirbt mit dem Fenster |
Kurzfassung: VT für Korrektheit; Schriftart + Metriken + zellenweise Platzierung + geometrisches Box Drawing für das Aussehen; Dirty-Row-Cache für Geschwindigkeit.
1. VT (Gitter muss korrekt sein)
- Bevorzuge einen echten Emulator (z. B. libghostty-vt), nicht eine selbstgebaute ANSI-Teilmenge, für Agenten-TUIs.
- Jede Zelle: Text (Graphem), VG/HG, fett/kursiv/blass, unterstrichen/durchgestrichen, breites Flag.
- Behandle: breite Zeichen / Emoji-Breite, alternativen Bildschirm, synchronisierte Ausgabe (Modus 2026), Query-Antworten, die vor dem nächsten PTY-Lesen zurückgeschrieben werden.
- Die UI liest eine Momentaufnahme des Gitters; parse den Bytestrom im Paint-Pfad nicht erneut.
2. Metriken
- Spaltenbreite ≈ Vorlauf von
'M'(optionalerCellWidth-Multiplikator). - Zeilenhöhe ≈ Oberlänge + Unterlänge, dann × ~1.15–1.2; an Gerätepixeln ausrichten.
- Breite als Schriftvorlauf beibehalten; Box-/HG-Kanten an Pixeln ausrichten, sodass Nachbarn ohne Nähte aneinanderstoßen (Zellenbreite nicht so runden, dass Glyphen wackeln).
- Beim Resize
cols,rows,cell_width_px,cell_height_pxan die PTY senden (Programme verwenden Pixelgröße für Maus/Bilder).
3. Paint (wo das Aussehen gewonnen oder verloren wird)
Prioritätenreihenfolge bei der Verbesserung eines bestehenden Terminals:
- Eine feste Mono + Nerd-Symbole ausliefern (z. B. JetBrains Mono + Symbols Nerd Font). Systemstandard-Mono / fehlende Powerline-Icons ruinieren Agenten-TUIs.
- Box / Block / Braille / Powerline als Geometrie zeichnen, nicht als Schriftglyphen – Schriftarten hinterlassen Lücken zwischen Zeilen; Vollbild-Ränder müssen verbunden sein.
- Glyphen auf dem Gitter platzieren: gleichartige Läufe mit Force-Width-Shaping, oder zellenweise Zentrierung. Fallback-Glyphen (Emoji), die eine schmale Zelle überlaufen, verkleinern.
- Fehlende PUA / Nerd-Icons zur Symbolschriftart routen (oder durch Outline-Fit in die Zelle einpassen).
- Optionaler Feinschliff:
minimum-contrast(Sprites / beabsichtigte Grafiken überspringen), macOS-Schriftverdickung, mehrstilige Unterstreichungen, Padding-Farbausdehnung.
Paint-Pipeline (pro Frame)
- Pane mit Terminal-HG füllen.
- Ursprung = Padding + vertical spare/2; Ursprung an Gerätepixeln ausrichten.
- Zeilenoperationen nur neu aufbauen, wenn sich die Zeilen-
Arc/ID geändert hat (oder Schriftart/Zellgröße geändert / komplett schmutzig). - Alle Hintergrund-Spannen, dann Sprites, dann Textläufe, dann Cursor / IME / Overlays zeichnen.
Zeilenoperationen
- Aufeinanderfolgende Zellen mit gleichem HG zu einem Quad zusammenführen.
- Eine Sprite-Zelle → geometrisches Zeichnen (siehe Sprites-Ansatz in herdr / Ghostty).
- Sonst einen Textlauf mit gleichem Stil formen; Vorlauf für schmale Zellen auf
cell_werzwingen, damit Spalten fixiert bleiben.
Was nicht der VT angelastet werden sollte
Wenn Ränder klaffen, Icons als Tofu erscheinen oder Text dünn/uneinheitlich aussieht, während der Gitterinhalt korrekt ist — Paint/Schriftarten korrigieren, nicht den Emulator austauschen.
4. Sitzungstopologie
In-Prozess (einfach): PTY → VT → Momentaufnahme → UI-Paint.
Daemon + Client (kero-Stil): Daemon headless VT + PTY; Mirror kodiert VT-Frames des aktuellen Bildschirms; Client VT mit Conn malt Zelle für Zelle; Scrollback überlebt Fensterschließen / Remote-Anbindung.
Referenzimplementierungen
| Projekt | Stack | Anmerkungen |
|---|---|---|
| Ghostty | Zig + libghostty-vt | Quelle der VT- + Sprite-Semantik |
| herdr-app | GPUI + libghostty-vt | Zellen-Paint, Sprites, Kontrast, gebündelte Schriftarten |
| kero | MyGo + libghostty-vt | Spiegel-Frames, Ghostty-Designs, GPU-UI |
| kumu | GPUI-kit + libghostty-vt | Gleiche Paint-Ideen: Sprites + JetBrains + Nerd |
Checkliste
Beim Hinzufügen oder Korrigieren von Terminal-Rendering:
- VT besitzt das Gitter; UI malt nur Momentaufnahmen
- Zellenmetriken von Mono-Schriftart; Resize enthält Pixel-Zellgröße
- Gebündelte (oder garantierte) Mono + Nerd-Symbole
- Box / Powerline / Braille als Formen gezeichnet
- Dirty-Row-Paint-Cache, indiziert nach Zeilenidentität
- Cursor, IME und Auswahl sitzen auf Zellkoordinaten
- Eine bekannte TUI (htop, Claude Code, Statusleiste) mit Ghostty vergleichen
Zusätzliche Details
- Sprite-/Geometriebereiche und Kontrastregeln: paint.md