helix-editor/helix
helix-tui
Forked from tui-rs, pruned and adapted to Helix's needs. ~5,900 lines of Rust. Sits between helix-view's drawing types (Rect, Style) and the terminal backend.
Purpose
helix-tui provides:
Buffer— an off-screen grid of styledCells that components draw into.Backend— a trait abstracting terminal I/O. Three implementations:termina(Unix),crossterm(Windows), and aTestBackendused by integration tests.Layout— constraint-based rectangle splitting.Widgets — small drawable primitives:Block,Paragraph,Table.Terminal— owns the backend and a double-buffered surface; computes per-frame diffs.
Directory layout
helix-tui/src
├── lib.rs # re-export Terminal, TerminalOptions, Viewport
├── buffer.rs # Cell, Buffer (the surface; ~33k chars)
├── layout.rs # Layout, Constraint, Rect splitting
├── terminal.rs # Terminal<Backend>: draw cycle, viewport, resize handling
├── text.rs # Text/Spans/Span (styled text)
├── symbols.rs # Unicode glyph constants (lines, blocks, dots)
├── backend/
│ ├── mod.rs # Backend trait
│ ├── termina.rs # termina backend (Unix); ~26k chars
│ ├── crossterm.rs # crossterm backend (Windows); ~16k chars
│ └── test.rs # TestBackend for integration tests
└── widgets/
├── mod.rs # Widget trait
├── block.rs # Bordered box widget
├── paragraph.rs # Word-wrapped text
├── reflow.rs # Soft-wrap implementation used by Paragraph
└── table.rs # Table widget (used by file picker, etc.)Note: list.rs exists in tui-rs upstream but is commented out here — Helix's pickers and menus don't use it.
Key abstractions
| Type | File | Purpose |
|---|---|---|
Cell |
buffer.rs |
One terminal cell: symbol (a String), Style, Underline. |
Buffer |
buffer.rs |
A 2D grid of Cells; the type that Component::render writes into. |
Backend (trait) |
backend/mod.rs |
Claim/restore terminal, draw a sparse cell stream, control cursor and clear. |
Terminal<B> |
terminal.rs |
Owns the backend + previous + current Buffer. draw diffs the buffers. |
Viewport |
terminal.rs |
Full (alternate screen) or Inline { height }. |
Rect (re-export from helix-view) |
helix-view/src/graphics.rs |
x, y, width, height. |
Constraint |
layout.rs |
Length, Percentage, Ratio, Min, Max — used to split Rects. |
Widget (trait) |
widgets/mod.rs |
fn render(self, area: Rect, buf: &mut Buffer). |
Render cycle
graph LR
Comp[Compositor.render] -->|fills| Curr[Buffer current]
Curr -->|diff vs| Prev[Buffer previous]
Curr -->|cell deltas| BackendDraw[Backend::draw]
BackendDraw --> TermIO[Terminal escape sequences]
Curr -.swap.-> PrevTerminal::draw (terminal.rs) clears the current buffer, lets the caller paint via a closure, runs Buffer::diff to compute changed cells, sends them through Backend::draw, then swaps the buffers. Only changed cells hit the wire — a typing keystroke usually generates a handful of cell updates rather than a full redraw.
Backends
The backend abstraction allows three concrete implementations:
- TerminaBackend (
backend/termina.rs) — Unix backend using theterminacrate. Handles modern features like the kitty keyboard protocol, OSC 52 clipboard, true color, undercurl, and bracketed paste. - CrosstermBackend (
backend/crossterm.rs) — Windows backend usingcrossterm≥ 0.28. - TestBackend (
backend/test.rs) — in-memory backend used bycargo integration-test. Deterministic sizes and a snapshot of the rendered grid.
The application chooses the backend at compile time via cfg-guards in helix-term/src/application.rs.
Widgets
The Widget trait is small but powerful: the widget consumes itself and writes directly into the buffer. Helix uses three of them:
Block— bordered box with a title; used to frame popups and pickers.Paragraph+reflow.rs— word-wrapped text; used in markdown rendering and signature help.Table— column-aligned rows; used in pickers (file picker, symbol picker, diagnostics picker, etc.).
The fourth tui-rs widget, List, is commented out — Helix uses Menu (helix-term/src/ui/menu.rs) and Picker instead, which expose richer interaction.
Integration points
- The
Celltype pullsStyleandColorfromhelix-view::graphics, so widgets stay independent of theme loading. helix-term::compositor::Compositor::rendercallsTerminal::draw, then walks eachComponentand gives it a&mut Bufferplus aRect.- Backends initialize and tear down through
Backend::claim/restore, called fromApplication::newand the panic hook inhelix-term/src/application.rs.
Entry points for modification
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.