Atomic VTE Parser
The Atomic VTE Parser wraps Alacritty’s battle-tested VTE parser to process ANSI escape sequences with fast native performance.Overview
Copy
┌─────────────────────────────────────────────────────────────────────┐
│ ATOMIC VTE PARSER IN MONOLEX │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ PTY Output (raw bytes + ANSI) │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ AlacrittyRenderer │ │
│ │ │ │
│ │ ┌──────────────────┐ ┌──────────────────────────────┐ │ │
│ │ │ AtomicParser │───→│ alacritty_terminal::Term │ │ │
│ │ │ BSU/ESU detect │ │ VTE Parser + Grid State │ │ │
│ │ └──────────────────┘ └──────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────────────┐ │ │
│ │ │ CellConverter │ │ │
│ │ │ Alacritty→xterm │ │ │
│ │ └──────────────────┘ │ │
│ │ │ │ │
│ └───────────────────────────────────│─────────────────────────┘ │
│ ▼ │
│ GridUpdate { viewport, scrollback, cursor, epoch } │
│ │
└─────────────────────────────────────────────────────────────────────┘
Why Alacritty?
| Aspect | xterm.js Parser | Alacritty Parser |
|---|---|---|
| Language | JavaScript | Rust |
| Performance | Interpreted | Native |
| Memory | GC overhead | Zero-copy |
| Test Coverage | Good | Excellent (1000+) |
| ANSI Support | Standard | Extensive |
| CJK Support | Basic | Full |
Core Components
AlacrittyRenderer
Wrapper around Alacritty’s Term:Copy
┌─────────────────────────────────────────────────────────────────┐
│ ALACRITTY RENDERER STRUCTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ AlacrittyRenderer: │
│ ├── term Alacritty Term instance │
│ ├── size Current terminal dimensions │
│ ├── dirty_lines Set of changed row indices │
│ └── request_full Flag for full update needed │
│ │
│ new(cols, rows): │
│ ───────────────── │
│ 1. Create TermSize with dimensions │
│ 2. Initialize Alacritty Term │
│ 3. Set initial dirty state │
│ │
│ process(data) → Option<GridUpdate>: │
│ ─────────────────────────────────── │
│ 1. Feed each byte to Alacritty VTE parser │
│ 2. Mark dirty lines based on changes │
│ 3. If should emit: │
│ → Return GridUpdate │
│ Else: │
│ → Return None │
│ │
└─────────────────────────────────────────────────────────────────┘
AtomicParser
Detects BSU/ESU (Begin/End Synchronized Update) sequences:Copy
┌─────────────────────────────────────────────────────────────────┐
│ ATOMICPARSER - BSU/ESU DETECTION │
├─────────────────────────────────────────────────────────────────┤
│ │
│ AtomicParser: │
│ ├── state Normal | InAtomicBlock │
│ └── data Accumulated bytes │
│ │
│ process(data) → ProcessResult: │
│ ────────────────────────────── │
│ For each byte: │
│ │ │
│ ├── [Normal state] │
│ │ Is BSU detected? │
│ │ → YES: Switch to InAtomicBlock │
│ │ │
│ └── [InAtomicBlock state] │
│ Is ESU detected? │
│ → YES: Return AtomicBlockComplete │
│ Reset to Normal state │
│ │
│ BSU/ESU SEQUENCES: │
│ ───────────────── │
│ BSU: ESC [ ? 2026 h (Begin Synchronized Update) │
│ ESU: ESC [ ? 2026 l (End Synchronized Update) │
│ │
└─────────────────────────────────────────────────────────────────┘
CellConverter
Converts Alacritty cells to xterm.js format:Copy
┌─────────────────────────────────────────────────────────────────┐
│ CELL CONVERTER │
├─────────────────────────────────────────────────────────────────┤
│ │
│ convert_cell(Alacritty Cell) → xterm Cell: │
│ ────────────────────────────────────────── │
│ Input: │
│ ├── Character (Unicode) │
│ ├── Foreground color │
│ ├── Background color │
│ └── Flags (bold, italic, wide, etc.) │
│ │
│ Output (3 × 32-bit values): │
│ ├── Content slot (codepoint + width) │
│ ├── Foreground slot (color + mode + flags) │
│ └── Background slot (color + mode + flags) │
│ │
│ CONTENT ENCODING: │
│ ───────────────── │
│ ┌────────────────────────────────────────┐ │
│ │ codepoint [0:20] │ combined │ width │ │
│ │ 21 bits │ 1 bit │ 2 bits │ │
│ └────────────────────────────────────────┘ │
│ │
│ COLOR ENCODING: │
│ ─────────────── │
│ ┌────────────────────────────────────────┐ │
│ │ color [0:23] │ mode [24:25] │ flags │ │
│ │ 24 bits │ 2 bits │ 6 bits │ │
│ └────────────────────────────────────────┘ │
│ │
│ Color Modes: │
│ ├── Named (0-15) → 16-color palette │
│ ├── Indexed (16-255) → 256-color palette │
│ └── RGB (24-bit) → True color │
│ │
└─────────────────────────────────────────────────────────────────┘
GridUpdate Structure
The output of AlacrittyRenderer:Copy
┌─────────────────────────────────────────────────────────────────┐
│ GRIDUPDATE STRUCTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ GridUpdate: │
│ ├── viewport Visible area cells (2D array) │
│ ├── scrollback History cells (2D array) │
│ │ │
│ ├── cursor_x Cursor column position │
│ ├── cursor_y Cursor row position │
│ ├── cursor_visible Whether cursor is visible │
│ │ │
│ ├── epoch Synchronization counter │
│ ├── scrollback_lines Number of history lines │
│ │ │
│ ├── dirty_lines List of changed row indices │
│ └── is_full_update Whether full redraw needed │
│ │
│ DATA FLOW: │
│ ────────── │
│ Alacritty Grid → CellConverter → GridUpdate → Frontend │
│ │
│ DIRTY TRACKING: │
│ ─────────────── │
│ is_full_update = true → Send all rows │
│ is_full_update = false → Send only dirty_lines │
│ │
└─────────────────────────────────────────────────────────────────┘
Dirty Tracking
Only emit changed lines for efficiency:Copy
┌─────────────────────────────────────────────────────────────────────┐
│ DIRTY TRACKING │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Full Grid (40 rows): │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Row 0: unchanged │ │
│ │ Row 1: unchanged │ │
│ │ Row 2: DIRTY ← cursor moved here │ │
│ │ Row 3: DIRTY ← new text written │ │
│ │ Row 4: unchanged │ │
│ │ ... │ │
│ │ Row 39: unchanged │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ GridUpdate.dirty_lines = [2, 3] │
│ GridUpdate.is_full_update = false │
│ │
│ → Only rows 2, 3 sent to frontend │
│ → Significant bandwidth reduction │
│ │
└─────────────────────────────────────────────────────────────────────┘
Wide Character Handling
CJK characters (한글, 日本語, 中文) occupy 2 cells:Copy
"한" (Korean character, width=2)
Cell Layout:
┌─────────────┬─────────────┐
│ Col 0 │ Col 1 │
│ "한" │ (spacer) │
│ width=2 │ WIDE_CHAR_ │
│ WIDE_CHAR │ SPACER │
└─────────────┴─────────────┘
Content Encoding:
Main cell:
content = (0xD55C) | (0 << 21) | (2 << 22)
= codepoint | combined_flag | width
Spacer cell:
content = 0 (empty, WebGL handles spacing)
Performance Characteristics
| Operation | Description |
|---|---|
| VTE parsing | Fast native Rust processing |
| Cell conversion | Direct format conversion |
| Dirty tracking | Efficient change detection |
| Overall | Faster than JavaScript parser |
Key Components
Copy
┌─────────────────────────────────────────────────────────────────┐
│ ALACRITTY RENDERER COMPONENTS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Component Purpose │
│ ───────────────── ──────────────────────────────────────── │
│ VTE Renderer Term wrapper, dirty tracking │
│ AtomicParser BSU/ESU detection │
│ Cell Converter Alacritty→xterm format conversion │
│ │
└─────────────────────────────────────────────────────────────────┘
SMPC/OFAC Applied
| Principle | Application |
|---|---|
| SMPC | Single purpose: VTE parsing only |
| Clean interface: process() → GridUpdate | |
| No rendering logic (that’s xterm’s job) | |
| OFAC | Dirty tracking emerged from performance need |
| AtomicParser emerged from BSU/ESU requirement | |
| Cell format emerged from xterm.js internals |