tui-td 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +9 -0
- data/LICENSE.txt +21 -0
- data/README.md +479 -0
- data/bin/tui-td +9 -0
- data/lib/tui_td/ansi_parser.rb +405 -0
- data/lib/tui_td/cli.rb +232 -0
- data/lib/tui_td/driver.rb +188 -0
- data/lib/tui_td/html_renderer.rb +228 -0
- data/lib/tui_td/matchers.rb +72 -0
- data/lib/tui_td/mcp/server.rb +463 -0
- data/lib/tui_td/screenshot.rb +271 -0
- data/lib/tui_td/state.rb +111 -0
- data/lib/tui_td/test_runner.rb +178 -0
- data/lib/tui_td/version.rb +5 -0
- data/lib/tui_td.rb +25 -0
- metadata +159 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 45c5b163ff48383823bccd9c0b9efe73f5a37b009c2e0968fb2619dea4c87d51
|
|
4
|
+
data.tar.gz: '01885208a25d500718f786fb66bc2b0753b2b0ff720cf6ed39c9380c9f1d13bf'
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d4887b9af284ee25b16236b8e4a0aad6eadbb1c8583d14119630250749d3d9fce45a138321f50eb2b59e7de0ea107b34d33461da62113d6b1a76e4f8d789b698
|
|
7
|
+
data.tar.gz: c435e9556f67254b627c2b7ff21199489b9991bd37e06eb5f1e609a4b99414917a6d731776434a0c42af53e7d362103caf203020200feb79328e310077e53903
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Haluk Durmus
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
# TUI Test Drive
|
|
2
|
+
|
|
3
|
+
Testing framework for Terminal User Interfaces (TUIs) with MCP support.
|
|
4
|
+
|
|
5
|
+
**tui-td** lets you:
|
|
6
|
+
1. Start a TUI application in a virtual terminal (PTY)
|
|
7
|
+
2. See the output — as structured JSON, plain text, PNG screenshots, or HTML renders
|
|
8
|
+
3. Send input — keystrokes, text, control sequences
|
|
9
|
+
4. Analyze output — find text, check colors, detect cursor position
|
|
10
|
+
5. Loop — adjust and retest without manual intervention
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
### 1. Install Ruby
|
|
15
|
+
|
|
16
|
+
**rbenv (recommended):**
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# macOS
|
|
20
|
+
brew install rbenv ruby-build
|
|
21
|
+
echo 'eval "$(rbenv init - zsh)"' >> ~/.zshrc
|
|
22
|
+
|
|
23
|
+
# Linux
|
|
24
|
+
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
|
|
25
|
+
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
|
|
26
|
+
echo 'eval "$(~/.rbenv/bin/rbenv init - bash)"' >> ~/.bashrc
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Then install Ruby 3 and activate it:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
rbenv install 3.4.1
|
|
33
|
+
rbenv global 3.4.1
|
|
34
|
+
ruby --version # must show 3.0+
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Alternative — Homebrew (macOS):**
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
brew install ruby
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 2. Install tui-td
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
curl -sL https://github.com/vurte/tui-td/releases/download/v0.1.0/tui-td-0.1.0.gem -o tui-td.gem
|
|
47
|
+
gem install tui-td.gem && rm tui-td.gem
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 3. Test
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
tui-td capture "echo Hello World"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## CLI Usage
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Capture output of any terminal command
|
|
60
|
+
tui-td capture "ls -la"
|
|
61
|
+
|
|
62
|
+
# Capture with custom terminal size
|
|
63
|
+
tui-td -r 24 -c 80 capture "vim --version"
|
|
64
|
+
|
|
65
|
+
# Run a command from a specific directory
|
|
66
|
+
tui-td -C /path/to/project capture "make test"
|
|
67
|
+
|
|
68
|
+
# Output as JSON for scripts
|
|
69
|
+
tui-td --json capture "ls -la"
|
|
70
|
+
|
|
71
|
+
# Save as HTML for browser visualization
|
|
72
|
+
tui-td --html output.html capture "htop"
|
|
73
|
+
|
|
74
|
+
# Save as a PNG screenshot
|
|
75
|
+
tui-td --screenshot output.png capture "htop"
|
|
76
|
+
|
|
77
|
+
# Drive a TUI interactively
|
|
78
|
+
tui-td drive "htop"
|
|
79
|
+
# At the > prompt:
|
|
80
|
+
# state Show current terminal state as pretty JSON
|
|
81
|
+
# raw Show raw ANSI output (first 2000 chars)
|
|
82
|
+
# key <name> Send a special key (enter, up, down, tab, escape, ctrl_c, ...)
|
|
83
|
+
# exit Quit
|
|
84
|
+
# <anything> Sent as text + Enter to the TUI
|
|
85
|
+
|
|
86
|
+
# Start MCP server for AI integration
|
|
87
|
+
tui-td serve
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## CLI Reference
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
Usage: tui-td <command> [options]
|
|
94
|
+
|
|
95
|
+
Commands:
|
|
96
|
+
serve Start MCP server (JSON-RPC over stdio)
|
|
97
|
+
test <file> Run JSON test file
|
|
98
|
+
run <command> Run a TUI app and show live output
|
|
99
|
+
drive <command> Drive a TUI with structured state output
|
|
100
|
+
capture <command> Run once, capture and display state
|
|
101
|
+
|
|
102
|
+
Global options:
|
|
103
|
+
-r, --rows N Terminal rows (default: 40)
|
|
104
|
+
-c, --cols N Terminal cols (default: 120)
|
|
105
|
+
-C, --chdir PATH Working directory for the command
|
|
106
|
+
-t, --timeout N Timeout in seconds (default: 30)
|
|
107
|
+
--screenshot PATH Save PNG screenshot
|
|
108
|
+
--html PATH Save HTML render for browser viewing
|
|
109
|
+
--json Output state as compact JSON (includes raw ANSI)
|
|
110
|
+
--pretty Output state as pretty JSON
|
|
111
|
+
--text Output state as plain text table (default)
|
|
112
|
+
-h, --help Show help
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Ruby API
|
|
116
|
+
|
|
117
|
+
### Driver — Start, send, capture
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
require "tui_td"
|
|
121
|
+
|
|
122
|
+
driver = TUITD::Driver.new("htop", rows: 40, cols: 120, timeout: 30)
|
|
123
|
+
driver.start
|
|
124
|
+
|
|
125
|
+
# Send input
|
|
126
|
+
driver.send("hello world\n")
|
|
127
|
+
driver.send_keys(:enter) # :enter, :tab, :escape
|
|
128
|
+
driver.send_keys(:up) # :up, :down, :left, :right
|
|
129
|
+
driver.send_keys(:ctrl_c) # :ctrl_c, :ctrl_d, :backspace
|
|
130
|
+
|
|
131
|
+
# Wait for expected output
|
|
132
|
+
driver.wait_for_text("> ")
|
|
133
|
+
driver.wait_for_stable # Wait until 300ms of silence
|
|
134
|
+
driver.wait_for_exit # Wait until process ends
|
|
135
|
+
|
|
136
|
+
# Read output
|
|
137
|
+
driver.raw_output # Raw ANSI string
|
|
138
|
+
driver.state_data # Structured Hash with :raw, :rows, :cursor, :size
|
|
139
|
+
driver.state_json # JSON string (includes raw ANSI)
|
|
140
|
+
driver.state_json(pretty: true) # Pretty JSON
|
|
141
|
+
|
|
142
|
+
# Visual capture
|
|
143
|
+
driver.screenshot("screenshot.png") # PNG renderer
|
|
144
|
+
TUITD::HtmlRenderer.new(driver.state_data).render("output.html") # HTML renderer
|
|
145
|
+
html_string = TUITD::HtmlRenderer.new(driver.state_data).to_html # HTML string
|
|
146
|
+
|
|
147
|
+
driver.close
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### State — Analyze terminal content
|
|
151
|
+
|
|
152
|
+
```ruby
|
|
153
|
+
state = TUITD::State.new(driver.state_data)
|
|
154
|
+
|
|
155
|
+
# Read text
|
|
156
|
+
state.plain_text # "Hello\n> prompt\n"
|
|
157
|
+
state.text_at(row, col, length) # Extract substring at position
|
|
158
|
+
state.find_text("error") # [{row: 2, col: 10, text: "error", full_line: "..."}]
|
|
159
|
+
|
|
160
|
+
# Inspect cells
|
|
161
|
+
state.foreground_at(0, 5) # "cyan"
|
|
162
|
+
state.background_at(0, 5) # "bright_black"
|
|
163
|
+
state.style_at(0, 5) # {bold: true, italic: false, underline: false}
|
|
164
|
+
|
|
165
|
+
# AI-optimized compact output
|
|
166
|
+
state.to_ai_json
|
|
167
|
+
# => {
|
|
168
|
+
# size: {rows: 40, cols: 120},
|
|
169
|
+
# cursor: {row: 5, col: 12},
|
|
170
|
+
# text: "> Hello\n...",
|
|
171
|
+
# highlights: [
|
|
172
|
+
# {row: 0, text: "MyApp v1.0.0", bold: true, fg: "cyan"}
|
|
173
|
+
# ],
|
|
174
|
+
# summary: "Cursor at [5,12]. 1 styled row, colors: fg=cyan."
|
|
175
|
+
# }
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Full example — Test a TUI programmatically
|
|
179
|
+
|
|
180
|
+
```ruby
|
|
181
|
+
require "tui_td"
|
|
182
|
+
|
|
183
|
+
driver = TUITD::Driver.new("my_tui_app", rows: 24, cols: 80)
|
|
184
|
+
driver.start
|
|
185
|
+
|
|
186
|
+
# Wait for the initial prompt
|
|
187
|
+
driver.wait_for_text("> ", timeout: 10)
|
|
188
|
+
|
|
189
|
+
# Send a command
|
|
190
|
+
driver.send("list files\n")
|
|
191
|
+
driver.wait_for_stable
|
|
192
|
+
|
|
193
|
+
# Analyze output
|
|
194
|
+
state = TUITD::State.new(driver.state_data)
|
|
195
|
+
|
|
196
|
+
if state.find_text("ERROR").any?
|
|
197
|
+
puts "Bug found!"
|
|
198
|
+
driver.screenshot("error_proof.png")
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Check colors
|
|
202
|
+
welcome_fg = state.foreground_at(0, 0)
|
|
203
|
+
raise "Expected cyan header" unless welcome_fg == "cyan"
|
|
204
|
+
|
|
205
|
+
# Send more commands, inspect, loop...
|
|
206
|
+
driver.send("/quit\n")
|
|
207
|
+
driver.wait_for_exit
|
|
208
|
+
driver.close
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Testing
|
|
212
|
+
|
|
213
|
+
tui-td supports two test formats: **JSON** for declarative, framework-agnostic tests, and **RSpec** for Ruby-native tests with custom matchers.
|
|
214
|
+
|
|
215
|
+
### JSON Test Format
|
|
216
|
+
|
|
217
|
+
Tests are defined as JSON with a sequence of action steps. Each step maps to a tui-td operation.
|
|
218
|
+
|
|
219
|
+
Run with the `tui-td test` command:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
tui-td test examples/echo_test.json
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**Format:**
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"name": "My test",
|
|
230
|
+
"rows": 24,
|
|
231
|
+
"cols": 80,
|
|
232
|
+
"timeout": 10,
|
|
233
|
+
"steps": [
|
|
234
|
+
{ "start": "my_tui_app" },
|
|
235
|
+
{ "wait_for_text": "> " },
|
|
236
|
+
{ "send": "hello\n" },
|
|
237
|
+
{ "assert_text": "hello" },
|
|
238
|
+
{ "assert_fg": [0, 0], "is": "cyan" },
|
|
239
|
+
{ "close": true }
|
|
240
|
+
]
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Available steps:**
|
|
245
|
+
|
|
246
|
+
| Step | Key | Description |
|
|
247
|
+
|------|-----|-------------|
|
|
248
|
+
| `start` | `"command"` | Start a TUI application |
|
|
249
|
+
| `send` | `"text"` | Send text (use `\n` for Enter) |
|
|
250
|
+
| `send_key` | `"key"` | Send a special key (`enter`, `up`, `ctrl_c`, ...) |
|
|
251
|
+
| `wait_for_text` | `"text"` | Wait until text appears |
|
|
252
|
+
| `wait_for_stable` | — | Wait until output is stable |
|
|
253
|
+
| `assert_text` | `"text"` | Assert that text exists on screen |
|
|
254
|
+
| `assert_fg` | `[row, col], "is": "color"` | Assert foreground color |
|
|
255
|
+
| `assert_bg` | `[row, col], "is": "color"` | Assert background color |
|
|
256
|
+
| `assert_style` | `[row, col], "bold": true` | Assert cell style (bold, italic, underline) |
|
|
257
|
+
| `screenshot` | `"path"` | Save PNG screenshot |
|
|
258
|
+
| `html` | `"path"` | Save HTML render for browser viewing |
|
|
259
|
+
| `close` | — | Close the TUI |
|
|
260
|
+
|
|
261
|
+
Example with `html` step for before/after snapshots:
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"name": "Visual diff test",
|
|
266
|
+
"rows": 40, "cols": 120,
|
|
267
|
+
"steps": [
|
|
268
|
+
{ "start": "my_tui_app" },
|
|
269
|
+
{ "wait_for_stable": true },
|
|
270
|
+
{ "html": "/tmp/before.html" },
|
|
271
|
+
{ "send": "Help\n" },
|
|
272
|
+
{ "wait_for_stable": true },
|
|
273
|
+
{ "html": "/tmp/after.html" },
|
|
274
|
+
{ "close": true }
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Ruby API:**
|
|
280
|
+
|
|
281
|
+
```ruby
|
|
282
|
+
plan = File.read("test/example.json")
|
|
283
|
+
result = TUITD::TestRunner.new(plan).run
|
|
284
|
+
puts result[:passed] # => true
|
|
285
|
+
result[:results].each { |r| puts "#{r[:step]}: #{r[:passed]} - #{r[:message]}" }
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### RSpec Tests
|
|
289
|
+
|
|
290
|
+
Use custom matchers for expressive, Ruby-native TUI tests:
|
|
291
|
+
|
|
292
|
+
```ruby
|
|
293
|
+
require "tui_td"
|
|
294
|
+
require "tui_td/matchers"
|
|
295
|
+
|
|
296
|
+
RSpec.describe "My TUI" do
|
|
297
|
+
before(:all) do
|
|
298
|
+
@driver = TUITD::Driver.new("my_tui_app", rows: 24, cols: 80)
|
|
299
|
+
@driver.start
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
after(:all) { @driver&.close }
|
|
303
|
+
|
|
304
|
+
let(:state) { TUITD::State.new(@driver.state_data) }
|
|
305
|
+
|
|
306
|
+
it "shows welcome message" do
|
|
307
|
+
expect(state).to have_text("Welcome")
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
it "has a cyan header" do
|
|
311
|
+
expect(state).to have_fg("cyan").at(0, 0)
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it "has a blue background on row 3" do
|
|
315
|
+
expect(state).to have_bg("blue").at(3, 0)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
it "has bold text on the first line" do
|
|
319
|
+
expect(state).to have_style.at(0, 0).with(bold: true)
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
**Matchers:**
|
|
325
|
+
|
|
326
|
+
| Matcher | Usage |
|
|
327
|
+
|---------|-------|
|
|
328
|
+
| `have_text("...")` | Assert text is present on screen |
|
|
329
|
+
| `have_fg("color").at(row, col)` | Assert foreground color at position |
|
|
330
|
+
| `have_bg("color").at(row, col)` | Assert background color at position |
|
|
331
|
+
| `have_style.at(row, col).with(bold: true, ...)` | Assert cell style |
|
|
332
|
+
|
|
333
|
+
## MCP Server — AI Integration
|
|
334
|
+
|
|
335
|
+
Start the MCP server to let any MCP client control TUIs:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
tui-td serve
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Available tools
|
|
342
|
+
|
|
343
|
+
| Tool | Description |
|
|
344
|
+
|------|-------------|
|
|
345
|
+
| `tui_start` | Start a TUI application. Call first. |
|
|
346
|
+
| `tui_send` | Send text input. Use `\n` for Enter. |
|
|
347
|
+
| `tui_send_key` | Send special keys: `enter`, `tab`, `up`, `down`, `left`, `right`, `escape`, `ctrl_c`, `ctrl_d` |
|
|
348
|
+
| `tui_wait_for_text` | Wait until specified text appears in output (with timeout). |
|
|
349
|
+
| `tui_wait_for_stable` | Wait until terminal output stabilizes (300ms of silence). |
|
|
350
|
+
| `tui_state` | Get terminal state: AI-friendly compact mode (default), `full` grid, or `text` only. |
|
|
351
|
+
| `tui_plain_text` | Get plain text content, ANSI stripped. |
|
|
352
|
+
| `tui_screenshot` | Capture a PNG screenshot of the current terminal. |
|
|
353
|
+
| `tui_close` | Close the TUI and clean up. |
|
|
354
|
+
|
|
355
|
+
### MCP configuration
|
|
356
|
+
|
|
357
|
+
Add to your MCP client configuration:
|
|
358
|
+
|
|
359
|
+
```json
|
|
360
|
+
{
|
|
361
|
+
"mcpServers": {
|
|
362
|
+
"tui-td": {
|
|
363
|
+
"command": "tui-td",
|
|
364
|
+
"args": ["serve"]
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Example MCP session
|
|
371
|
+
|
|
372
|
+
```json
|
|
373
|
+
// 1. Start the TUI
|
|
374
|
+
{"method": "tools/call", "params": {"name": "tui_start", "arguments": {"command": "htop"}}}
|
|
375
|
+
|
|
376
|
+
// 2. Wait for prompt
|
|
377
|
+
{"method": "tools/call", "params": {"name": "tui_wait_for_text", "arguments": {"text": "> "}}}
|
|
378
|
+
|
|
379
|
+
// 3. Send a command
|
|
380
|
+
{"method": "tools/call", "params": {"name": "tui_send", "arguments": {"text": "Write hello.rb\n"}}}
|
|
381
|
+
|
|
382
|
+
// 4. Wait for output
|
|
383
|
+
{"method": "tools/call", "params": {"name": "tui_wait_for_stable", "arguments": {}}}
|
|
384
|
+
|
|
385
|
+
// 5. Get AI-friendly state
|
|
386
|
+
{"method": "tools/call", "params": {"name": "tui_state", "arguments": {"format": "ai"}}}
|
|
387
|
+
|
|
388
|
+
// 6. Take screenshot if needed
|
|
389
|
+
{"method": "tools/call", "params": {"name": "tui_screenshot", "arguments": {"path": "/tmp/proof.png"}}}
|
|
390
|
+
|
|
391
|
+
// 7. Clean up
|
|
392
|
+
{"method": "tools/call", "params": {"name": "tui_close", "arguments": {}}}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## State Format
|
|
396
|
+
|
|
397
|
+
Top-level structure returned by `state_data` / `--json`:
|
|
398
|
+
|
|
399
|
+
```json
|
|
400
|
+
{
|
|
401
|
+
"size": {"rows": 40, "cols": 120},
|
|
402
|
+
"cursor": {"row": 5, "col": 12},
|
|
403
|
+
"rows": [[{"char": "A", "fg": "cyan", ...}]],
|
|
404
|
+
"raw": "\e[31mred\e[0m\n..."
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Each cell in the `rows` grid:
|
|
409
|
+
|
|
410
|
+
```json
|
|
411
|
+
{
|
|
412
|
+
"char": "A",
|
|
413
|
+
"fg": "cyan",
|
|
414
|
+
"bg": "default",
|
|
415
|
+
"bold": true,
|
|
416
|
+
"italic": false,
|
|
417
|
+
"underline": false
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
`raw` is the original ANSI output with all escape sequences preserved.
|
|
422
|
+
|
|
423
|
+
### Color value formats
|
|
424
|
+
|
|
425
|
+
| Format | Example | Description |
|
|
426
|
+
|--------|---------|-------------|
|
|
427
|
+
| `"default"` | — | Terminal default color |
|
|
428
|
+
| Named | `"red"`, `"cyan"` | Standard 16 ANSI colors |
|
|
429
|
+
| Bright | `"bright_red"`, `"bright_green"` | Bright 16 ANSI colors |
|
|
430
|
+
| 256-color | `"color82"` | XTerm 256-color palette |
|
|
431
|
+
| TrueColor | `"#ff6432"` | 24-bit hex RGB |
|
|
432
|
+
|
|
433
|
+
## Screenshot
|
|
434
|
+
|
|
435
|
+
Screenshots are rendered using the embedded Spleen 8×16 bitmap font via `chunky_png`. No external tools required (no npm, no ImageMagick). Handles all color formats and styles (bold, italic, underline).
|
|
436
|
+
|
|
437
|
+
```ruby
|
|
438
|
+
# Via CLI
|
|
439
|
+
tui-td --screenshot output.png capture "echo 'Hello World'"
|
|
440
|
+
|
|
441
|
+
# Via Ruby API
|
|
442
|
+
driver.screenshot("output.png")
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## HTML Renderer
|
|
446
|
+
|
|
447
|
+
Renders terminal state as a self-contained HTML document with inline CSS. Faithfully reproduces colors, bold, italic, underline, and cursor position — so an LLM or human can "see" the TUI in any browser without external dependencies.
|
|
448
|
+
|
|
449
|
+
Features:
|
|
450
|
+
- Dark theme matching terminal appearance
|
|
451
|
+
- Run-length encoding of adjacent identically-styled cells (compact HTML)
|
|
452
|
+
- Cursor indicator (yellow outline)
|
|
453
|
+
- HTML entity escaping (`<`, `>`, `&`, `"`)
|
|
454
|
+
- All ANSI color formats: 16 named, bright, 256-color, TrueColor
|
|
455
|
+
|
|
456
|
+
```bash
|
|
457
|
+
# CLI — capture once
|
|
458
|
+
tui-td --html output.html capture "htop"
|
|
459
|
+
|
|
460
|
+
# CLI — run with custom terminal size
|
|
461
|
+
tui-td --html /tmp/demo.html run "htop" --rows 40 --cols 120
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
```ruby
|
|
465
|
+
# Ruby API — render to file
|
|
466
|
+
TUITD::HtmlRenderer.new(driver.state_data).render("output.html")
|
|
467
|
+
|
|
468
|
+
# Ruby API — get HTML string (e.g. for API responses)
|
|
469
|
+
html = TUITD::HtmlRenderer.new(driver.state_data).to_html
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
```json
|
|
473
|
+
// Test-Runner — before/after snapshots
|
|
474
|
+
{"html": "/tmp/snapshot.html"}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## License
|
|
478
|
+
|
|
479
|
+
MIT
|