Grid System
The Grid System is how Monolex gets pre-processed data from Rust to your screen instantly.Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ THE CORE IDEA │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Standard Terminal: │
│ ────────────────── │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Raw │ → │ Parse │ → │ Parse │ → │ Render │ │
│ │ Output │ │ in JS │ │ Again! │ │ to GPU │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ❌ Slow ❌ Redundant │
│ │
│ │
│ Monolex Grid System: │
│ ──────────────────── │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Raw │ → │ Parse │ → │ Direct │ → │ Render │ │
│ │ Output │ │ in Rust │ │ Inject │ │ to GPU │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ✅ Fast ✅ No double │
│ (Alacritty) parsing │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
How It Works
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ GRID SYSTEM FLOW │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ PTY DAEMON (Rust) │ │
│ │ │ │
│ │ Program Output │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ Alacritty VTE Parser │ │ │
│ │ │ │ │ │
│ │ │ • Interprets escape sequences │ │ │
│ │ │ • Calculates colors, styles, positions │ │ │
│ │ │ • Handles Unicode and wide characters │ │ │
│ │ │ │ │ │
│ │ └────────────────────────────┬────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ Grid Update (Pre-processed Cells) │ │ │
│ │ │ │ │ │
│ │ │ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │ │ │
│ │ │ │ H │ e │ l │ l │ o │ │ W │ o │ r │ l │ d │ ... │ │ │
│ │ │ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘ │ │ │
│ │ │ Each cell: character + foreground + background + flags │ │ │
│ │ │ │ │ │
│ │ └────────────────────────────┬────────────────────────────────┘ │ │
│ │ │ │ │
│ └────────────────────────────────│──────────────────────────────────────┘ │
│ │ │
│ │ Tauri emit() │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ FRONTEND (TypeScript) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ Grid Buffer Injector │ │ │
│ │ │ │ │ │
│ │ │ • Receives pre-processed cells │ │ │
│ │ │ • Writes directly to xterm.js memory │ │ │
│ │ │ • NO JavaScript parsing needed! │ │ │
│ │ │ │ │ │
│ │ └────────────────────────────┬────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ xterm.js WebGL Renderer │ │ │
│ │ │ │ │ │
│ │ │ • GPU-accelerated rendering │ │ │
│ │ │ • Renders the frame you see │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Why Alacritty? Alacritty is one of the fastest terminal VTE parsers, written in Rust.
Monolex uses its parsing engine for maximum speed.
Standard vs Grid: The Difference
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ STANDARD TERMINAL (Double Parsing Problem) │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Program sends: "\x1b[31mHello\x1b[0m" (red "Hello") │
│ │
│ ┌────────────┐ │
│ │ Backend │ → Might parse for logging │
│ └─────┬──────┘ │
│ │ │
│ │ Raw text sent to frontend │
│ ▼ │
│ ┌────────────┐ │
│ │ Frontend │ → Parses AGAIN (slow JavaScript) │
│ │ (xterm) │ • What color is this? │
│ │ │ • What position? │
│ │ │ • What attributes? │
│ └────────────┘ │
│ │
│ ❌ Same work done TWICE │
│ ❌ JavaScript parsing is slow │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ MONOLEX GRID SYSTEM (Parse Once) │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Program sends: "\x1b[31mHello\x1b[0m" (red "Hello") │
│ │
│ ┌────────────┐ │
│ │ Backend │ → Alacritty parses (fast Rust) │
│ │ (Rust) │ Result: [H:red][e:red][l:red][l:red][o:red] │
│ └─────┬──────┘ │
│ │ │
│ │ Pre-processed cells sent │
│ ▼ │
│ ┌────────────┐ │
│ │ Frontend │ → Just inject! No parsing needed. │
│ │ (xterm) │ Cells go directly to memory. │
│ └────────────┘ │
│ │
│ ✅ Parsing happens ONCE (in fast Rust) │
│ ✅ Frontend just receives ready-to-display data │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Smart Updates
Not every update needs to refresh the whole screen.Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ SMART DIFF: ONLY UPDATE WHAT CHANGED │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ │
│ FULL UPDATE (when needed) PARTIAL UPDATE (most common) │
│ ──────────────────────── ────────────────────────────── │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│ │ │ │
│ │▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│ │ │ │
│ │▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│ │▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│ ← Only this line │
│ │▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│ │ │ changed! │
│ │▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│ │ │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ Update 4,800 cells Update ~120 cells │
│ (120 cols × 40 rows) (just 1 row) │
│ │
│ │
│ ════════════════════════════════════════════════════════════════════════════ │
│ │
│ When typing at a prompt: │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ $ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ ↓ You type 'l' │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ $ l │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Only ONE character changed → Only ONE cell updated! │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
DiffHint tells the frontend exactly which lines changed.
The frontend only updates those specific lines, saving significant processing time.
Flow Control: ACK System
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ ACK FLOW CONTROL │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Problem: What if backend sends faster than frontend can display? │
│ ───────────────────────────────────────────────────────────────── │
│ │
│ Without flow control: │
│ │
│ Backend: [update1] [update2] [update3] [update4] [update5] ... │
│ │ │ │ │ │ │
│ └─────────┴─────────┴─────────┴─────────┘ │
│ │ │
│ Frontend overwhelmed! 💥 │
│ Memory fills up, lag increases │
│ │
│ │
│ With ACK flow control: │
│ ───────────────────────── │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Backend │ │ Frontend │ │
│ └────┬─────┘ └────┬─────┘ │
│ │ │ │
│ │ ───────── update1 ─────────────────▶ │ │
│ │ │ Processing... │
│ │ (waits) │ │
│ │ │ │
│ │ ◀──────── ACK ───────────────────── │ Done! │
│ │ │ │
│ │ ───────── update2 ─────────────────▶ │ │
│ │ │ Processing... │
│ │ (waits) │ │
│ │ │ │
│ │ ◀──────── ACK ───────────────────── │ Done! │
│ │ │ │
│ │
│ Backend only sends next update when frontend is ready. │
│ No memory overflow. Smooth frames. Happy users. │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Epoch: Handling Resize
What happens when you resize the terminal window?Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ EPOCH SYSTEM: SAFE RESIZE │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ The Problem: │
│ ──────────── │
│ │
│ You resize: 120×40 → 150×50 │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Old updates (120×40) still traveling to frontend... │ │
│ │ │ │
│ │ Update (120×40) ────▶ │ │
│ │ Update (120×40) ────▶ ← These are now WRONG! │ │
│ │ Update (150×50) ────▶ ← This is correct │ │
│ │ │ │
│ │ If we inject old updates into new buffer = CHAOS! │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ │
│ The Solution: Epoch Counter │
│ ─────────────────────────── │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Each resize increments the epoch: │ │
│ │ │ │
│ │ Epoch 1: Terminal is 120×40 │ │
│ │ ↓ (resize happens) │ │
│ │ Epoch 2: Terminal is 150×50 │ │
│ │ │ │
│ │ Update arrives with Epoch 1? │ │
│ │ → DISCARD! It's from the old size. │ │
│ │ │ │
│ │ Update arrives with Epoch 2? │ │
│ │ → ACCEPT! It matches current size. │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ Result: No corruption during resize. Smooth transition. │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
The Cell Format
Each character on screen is represented as a cell.Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ CELL STRUCTURE │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ What you see: A │
│ │
│ What's stored: │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Character │ │ Foreground │ │ Background │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ 'A' │ │ White │ │ Black │ │ │
│ │ │ + width │ │ + bold │ │ │ │ │
│ │ │ │ │ + italic │ │ │ │ │
│ │ │ │ │ + underline│ │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ Slot 1 Slot 2 Slot 3 │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ A terminal with 120 columns × 40 rows = 4,800 cells │
│ Each cell = 3 slots │
│ Total: 14,400 values to represent one screen │
│ │
│ Grid System processes these at native Rust speed, │
│ then injects them directly into xterm.js WebGL buffer. │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Summary
Copy
╔═══════════════════════════════════════════════════════════════════════════════╗
║ GRID SYSTEM SUMMARY ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║ ║
║ WHAT IT DOES: ║
║ ───────────── ║
║ Delivers pre-processed terminal cells directly from Rust to your screen. ║
║ ║
║ ║
║ KEY BENEFITS: ║
║ ───────────── ║
║ ║
║ ┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐ ║
║ │ Parse Once │ │ Smart Updates │ │ Flow Control │ ║
║ │ ───────────── │ │ ───────────── │ │ ───────────── │ ║
║ │ Rust parses, │ │ Only changed │ │ ACK prevents │ ║
║ │ JS doesn't. │ │ lines update. │ │ overflow. │ ║
║ └────────────────────┘ └────────────────────┘ └────────────────────┘ ║
║ ║
║ ┌────────────────────┐ ┌────────────────────┐ ║
║ │ Safe Resize │ │ GPU Rendering │ ║
║ │ ───────────── │ │ ───────────── │ ║
║ │ Epoch system │ │ WebGL takes │ ║
║ │ handles it. │ │ it from here. │ ║
║ └────────────────────┘ └────────────────────┘ ║
║ ║
║ ║
║ THE RESULT: ║
║ ─────────── ║
║ Faster rendering, smoother scrolling, responsive typing. ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════════╝