|
| 1 | +# TTYSampler & TTY Replayer |
| 2 | + |
| 3 | +A small harness to replay scripted terminal events against TauTUI for debugging and regression tests. |
| 4 | + |
| 5 | +## What it is |
| 6 | +- **TTY script format:** JSON (or any Decodable payload) describing a viewport size and an ordered list of events (key, paste, raw escape, resize, sleep). |
| 7 | +- **Replayer API:** `replayTTY(script:buildTUI:)` (in `Sources/TauTUI/Utilities/TTYReplayer.swift`) runs a script against a `VirtualTerminal`, builds a TUI via your closure, and returns a `TTYReplayResult` containing the final snapshot lines and the raw output log (ANSI included). |
| 8 | +- **CLI sampler:** `TTYSampler` executable target (`Examples/TTYSampler`). It loads a script, spins up a simple editor-based TUI (scenario `editor`), replays events, and prints the rendered snapshot (or writes to a file). |
| 9 | + |
| 10 | +## Script schema (JSON) |
| 11 | +```jsonc |
| 12 | +{ |
| 13 | + "columns": 80, // optional, default 80 |
| 14 | + "rows": 24, // optional, default 24 |
| 15 | + "events": [ |
| 16 | + { "type": "key", "data": "H" }, |
| 17 | + { "type": "key", "data": "i" }, |
| 18 | + { "type": "key", "data": "enter" }, |
| 19 | + { "type": "paste", "data": "pasted text" }, |
| 20 | + { "type": "sleep", "ms": 10 }, |
| 21 | + { "type": "resize", "columns": 60, "rows": 20 } |
| 22 | + ] |
| 23 | +} |
| 24 | +``` |
| 25 | + |
| 26 | +Supported event types: |
| 27 | +- `key`: `data` is a key token (`enter`, `tab`, `backspace`, `delete`, `left`, `right`, `up`, `down`, `home`, `end`, or a single character). Optional `modifiers`: `["shift"|"ctrl"|"alt"|"option"|"cmd"|"command"|"meta"]`. |
| 28 | +- `paste`: `data` string is inserted via `.paste` event. |
| 29 | +- `raw`: `data` is injected as raw input (escape sequences, etc.). |
| 30 | +- `resize`: `columns`/`rows` adjust viewport and trigger resize. |
| 31 | +- `sleep`: wait `ms` milliseconds. |
| 32 | + |
| 33 | +## CLI usage |
| 34 | +```bash |
| 35 | +# Run with sample script |
| 36 | +swift run TTYSampler --script Examples/TTYSampler/sample.json |
| 37 | + |
| 38 | +# Save snapshot to file |
| 39 | +swift run TTYSampler --script /path/to/script.json --output /tmp/snapshot.txt |
| 40 | + |
| 41 | +# Explicit scenario (currently only "editor") |
| 42 | +swift run TTYSampler --script script.json --scenario editor |
| 43 | +``` |
| 44 | + |
| 45 | +Output: snapshot lines printed (or saved) representing the final rendered state after replay. ANSI is preserved; pipe through `ansi2txt` if you want plain text. |
| 46 | + |
| 47 | +## API usage in tests |
| 48 | +```swift |
| 49 | +import TauTUI |
| 50 | + |
| 51 | +let script = TTYScript( |
| 52 | + columns: 40, |
| 53 | + rows: 10, |
| 54 | + events: [ |
| 55 | + .init(type: .key, data: "H", modifiers: nil, columns: nil, rows: nil, ms: nil), |
| 56 | + .init(type: .key, data: "i", modifiers: nil, columns: nil, rows: nil, ms: nil), |
| 57 | + .init(type: .key, data: "enter", modifiers: nil, columns: nil, rows: nil, ms: nil), |
| 58 | + .init(type: .paste, data: "there", modifiers: nil, columns: nil, rows: nil, ms: nil) |
| 59 | + ]) |
| 60 | + |
| 61 | +let result = try await MainActor.run { |
| 62 | + try replayTTY(script: script) { vt in |
| 63 | + let tui = TUI(terminal: vt) |
| 64 | + let editor = Editor() |
| 65 | + tui.addChild(editor) |
| 66 | + tui.setFocus(editor) |
| 67 | + return tui |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +// Assert on result.snapshot (rendered lines) or result.outputLog (raw ANSI) |
| 72 | +``` |
| 73 | + |
| 74 | +## Notes |
| 75 | +- `replayTTY` drives rendering synchronously via `renderNow()` to make tests deterministic; it still honors `sleep` events for basic timing gaps. |
| 76 | +- `TTYReplayResult.snapshot` is scrollback-aware; `VirtualTerminal.snapshotLines()` includes pending line content. |
| 77 | +- The CLI currently has one scenario (`editor`); add more by branching on `Scenario` in `Examples/TTYSampler/main.swift`. |
| 78 | +- `Examples/TTYSampler/sample.json` is bundled with the executable target for quick smoke runs. |
| 79 | + |
| 80 | +## Ideas / next steps |
| 81 | +- Add scenarios for select list and markdown rendering. |
| 82 | +- Optional HTML export (ansi-to-html) for visual diffs. |
| 83 | +- Script generator to capture real sessions and replay them. |
0 commit comments