-
Notifications
You must be signed in to change notification settings - Fork 774
Add tuirec recording guide and hero-gif docs #5396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
42face3
Add tuirec recording guide and hero-gif docs
tig 39961e4
Add tuirec recording guide for UICatalog scenarios and CharMap GIF
tig 70cb605
Update tuirec.md: document --kitty-keyboard nav key bug (tuirec#54)
tig 640aad0
Improve CharMap GIF: show Box Drawing, Emojis, and context menu
tig 2269ba1
Move charmap.gif to scenario directory
tig a8bae11
Fix CharMap GIF: avoid wide glyphs, add placement guidance
tig c445b2f
Restructure tuirec docs and fix quit key guidance
tig 53a1e3b
Remove bespoke script guidance; README.md is the single source
tig 17eaef5
Update CharMap keystroke script: Arrows -> Box Drawing -> Emoji
tig 156dfbe
Re-record CharacterMap.gif with updated keystroke script
tig 53b53ec
Fix View GIF placement: docfx/images/views/, not alongside .cs
tig 0ee7561
Add IDesignable.GetDemoKeyStrokes() and upgrade OutputView for tuirec
tig 12e7cf6
Add GetDemoKeyStrokes() to more views and generate 39 view GIFs
tig 5bb4d86
Address CR feedback: fix redundant override, dispose leak, generic re…
tig 81eaa6d
Update IDesignable.GetDemoKeyStrokes XML docs per review feedback
tig 43bc89f
Use tuirec v0.4.2 --trim, fix Code syntax highlighting, add end-pause
tig 1d39a20
Fix preroll artifacts: concealed-char baseline + GetDemoKeyStrokes fo…
tig 380c52c
Fix visible preroll dot: use bg-colored foreground for baseline char
tig cc0a2af
fix: reduce baseline sleep to 50ms to eliminate GIF preroll gray screen
tig 051d1af
feat: update CharMap demo to page down 30x then show context menu
tig 231bd4a
feat: improve demo keystrokes for CharMap, Tabs, TreeView, Markdown, …
tig e4dbe1d
chore: remove accidentally committed artifacts and add gitignore entries
tig 8b31a46
feat: add GIF img tags to all View XML docs for API documentation
tig 3d6d0c3
chore: remove stray images/views/PopoverMenu.gif
tig File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,3 +82,9 @@ log.* | |
| .mcp.json | ||
| .env | ||
| tmpclaude-*-cwd | ||
|
|
||
| # tuirec artifacts | ||
| artifacts/ | ||
| docfx/artifacts/ | ||
| local_packages/ | ||
| *.cast | ||
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,312 @@ | ||
| # Recording Terminal.Gui Apps with `tuirec` | ||
|
|
||
| Use this guide when an issue or PR asks for a GIF/video capture of a Terminal.Gui | ||
| app or scenario. The recording tool is [`gui-cs/tuirec`](https://github.com/gui-cs/tuirec) — | ||
| a Go CLI that spawns the target app in a PTY, injects keystrokes, records terminal | ||
| output as an asciinema v2 cast, and renders an animated GIF via `agg`. | ||
|
|
||
| ## Install | ||
|
|
||
| ```powershell | ||
| # Requires Go 1.22+ | ||
| go install github.com/gui-cs/tuirec/cmd/tuirec@latest | ||
| tuirec --version | ||
|
|
||
| # agg is auto-downloaded on first use — no separate install needed. | ||
| ``` | ||
|
|
||
| Verify: `tuirec --version`. If not on PATH, add `$(go env GOPATH)\bin` to PATH. | ||
|
|
||
| ## Quick Start — Recording a UICatalog Scenario | ||
|
|
||
| ```powershell | ||
| # 1. Build ScenarioRunner (do this ONCE before recording) | ||
| dotnet build Examples/ScenarioRunner/ScenarioRunner.csproj -c Release | ||
|
|
||
| # 2. Record (cross-platform: use dotnet to run the DLL) | ||
| $dll = "./Examples/ScenarioRunner/bin/Release/net10.0/ScenarioRunner.dll" | ||
| $ks = 'wait:1200,Tab,Tab,wait:400,A,wait:1800,B,o,wait:1800,E,wait:1800,Tab,wait:400,CursorDown,CursorDown,CursorDown,wait:400,Shift+F10,wait:1500,Escape,wait:400,Escape' | ||
|
|
||
| tuirec record ` | ||
| --binary dotnet ` | ||
| --args "$dll,run,Character Map" ` | ||
| --name CharacterMap ` | ||
| --title "Character Map" ` | ||
| --keystrokes $ks ` | ||
| --startup-delay 2000 ` | ||
| --drain 1500 ` | ||
| --cols 120 --rows 30 ` | ||
| --open --copy | ||
| ``` | ||
|
|
||
| Output: `artifacts/CharacterMap.gif` and `artifacts/CharacterMap.cast`. | ||
|
|
||
| Copy the GIF to the scenario directory: | ||
| ```powershell | ||
| Copy-Item artifacts/CharacterMap.gif Examples/UICatalog/Scenarios/CharacterMap/CharacterMap.gif | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Recording UICatalog Scenarios | ||
|
|
||
| ### Prerequisites | ||
|
|
||
| 1. **Build ScenarioRunner** — always build before recording to avoid startup noise: | ||
| ```powershell | ||
| dotnet build Examples/ScenarioRunner/ScenarioRunner.csproj -c Release | ||
| ``` | ||
| 2. **Know the scenario name** — list available scenarios: | ||
| ```powershell | ||
| dotnet run --project Examples/ScenarioRunner -c Release --no-build -- list | ||
| ``` | ||
|
|
||
| ### Finding the Right Keystrokes | ||
|
|
||
| Each scenario has a `GetDemoKeyStrokes()` method that defines a canonical | ||
| interaction sequence for benchmarking. **Use this as your starting point:** | ||
|
|
||
| ```powershell | ||
| # Find the demo keystrokes for a scenario: | ||
| grep -n "GetDemoKeyStrokes" Examples/UICatalog/Scenarios/<ScenarioFile>.cs | ||
| ``` | ||
|
|
||
| The demo keystrokes show what keys the scenario expects and what UI flow is | ||
| interesting. Translate them to tuirec syntax: | ||
|
|
||
| | Terminal.Gui Key | tuirec Token | | ||
| |---|---| | ||
| | `Key.CursorDown` | `CursorDown` | | ||
| | `Key.CursorLeft` | `CursorLeft` | | ||
| | `Key.Tab` | `Tab` | | ||
| | `Key.Tab.WithShift` | `Shift+Tab` | | ||
| | `Key.Enter` | `Enter` | | ||
| | `Key.Esc` | `Esc` | | ||
| | `Key.B` | `B` (or `` `B` `` for literal) | | ||
|
|
||
| ### Composing the Keystroke Script | ||
|
|
||
| **Principles for a great recording:** | ||
|
|
||
| 1. **Start with `wait:1000`** — let the UI render fully after startup-delay. | ||
| 2. **Add `wait:` between logical steps** — `wait:500` to `wait:1500` between | ||
| groups of actions so viewers can follow what's happening. | ||
| 3. **Keep it short** — 10–20 seconds of real-time interaction. Fewer keystrokes | ||
| with generous waits beats many rapid keystrokes. | ||
| 4. **Show variety** — demonstrate 2–3 features of the scenario, not just | ||
| scrolling. Navigate between controls, trigger category changes, etc. | ||
| 5. **End with `Escape`** — the default Terminal.Gui quit key. | ||
| 6. **Avoid wide glyphs** — Emoji and CJK characters cause misaligned rendering | ||
| in terminal recordings (agg renders each cell as monospace but wide glyphs | ||
| consume 2 cells). Prefer categories with single-width characters (Arrows, | ||
| Box Drawing, Block Elements, Mathematical Operators, etc.). | ||
|
|
||
| ### Template Command | ||
|
|
||
| ```powershell | ||
| $dll = "./Examples/ScenarioRunner/bin/Release/net10.0/ScenarioRunner.dll" | ||
| $ks = '<your keystroke script here>' | ||
|
|
||
| tuirec record ` | ||
| --binary dotnet ` | ||
| --args "$dll,run,<Scenario Name>" ` | ||
| --name <ScenarioName> ` | ||
| --title "<Scenario Name>" ` | ||
| --keystrokes $ks ` | ||
| --startup-delay 2000 ` | ||
| --drain 2000 ` | ||
| --cols 120 --rows 30 ` | ||
| --verbosity high ` | ||
| --open --copy | ||
|
|
||
| # Copy GIF to scenario directory | ||
| Copy-Item artifacts/<ScenarioName>.gif Examples/UICatalog/Scenarios/<ScenarioDir>/<ScenarioName>.gif | ||
| ``` | ||
|
|
||
| ### Output File Placement | ||
|
|
||
| GIFs live **alongside the `.cs` file they document**: | ||
|
|
||
| | What | Where | | ||
| |------|-------| | ||
| | Scenario in a subdirectory | `Examples/UICatalog/Scenarios/<ScenarioDir>/<ScenarioName>.gif` | | ||
| | Scenario directly in `Scenarios/` | `Examples/UICatalog/Scenarios/<ScenarioName>.gif` | | ||
| | View-derived class | `docfx/images/views/<ViewName>.gif` | | ||
|
|
||
| Use `--name <ScenarioName>` (PascalCase matching the class name) so the output | ||
| file is named correctly. The `--name` value determines the artifact filenames. | ||
|
|
||
| ### Critical: `--kitty-keyboard` Decision | ||
|
|
||
| **Known bug ([gui-cs/tuirec#54](https://github.com/gui-cs/tuirec/issues/54)):** | ||
| tuirec currently encodes navigation keys (`CursorUp`, `CursorDown`, `CursorLeft`, | ||
| `CursorRight`, `PageUp`, `PageDown`, `Home`, `End`) incorrectly under | ||
| `--kitty-keyboard` — it sends fabricated CSI u codepoints that the Kitty spec | ||
| doesn't define. Terminal.Gui ignores or misinterprets these sequences. | ||
|
|
||
| **Workaround until fixed:** | ||
| - **Omit `--kitty-keyboard`** for demos that use navigation keys. | ||
| - **Add `--kitty-keyboard`** only when you need modifier disambiguation for | ||
| non-navigation keys (`Ctrl+M` vs Enter, `Ctrl+I` vs Tab, `Ctrl+Q`, etc.) | ||
| and the demo doesn't rely on arrow/page/home/end keys. | ||
|
|
||
| Once the bug is fixed, `--kitty-keyboard` should be the default for all | ||
| Terminal.Gui recordings (it provides cleaner modifier handling). | ||
|
|
||
| ### `--args` for ScenarioRunner | ||
|
|
||
| The `--args` flag uses **comma-separated** values (not space-separated): | ||
|
|
||
| ```powershell | ||
| --args "run,Character Map" # Correct: two args ["run", "Character Map"] | ||
| --args "run Character Map" # WRONG: one arg "run Character Map" | ||
| ``` | ||
|
|
||
| ### PowerShell Quoting | ||
|
|
||
| Always assign keystrokes to a **single-quoted** `$ks` variable to preserve | ||
| backtick literals: | ||
|
|
||
| ```powershell | ||
| # Correct — single quotes prevent PowerShell backtick interpolation: | ||
| $ks = 'wait:1000,`search text`,Enter,wait:500,Escape' | ||
|
|
||
| # WRONG — PowerShell eats the backticks: | ||
| --keystrokes "wait:1000,`search text`,Enter" | ||
| ``` | ||
|
|
||
| ### Example: Character Map Scenario | ||
|
|
||
| ```powershell | ||
| $dll = "./Examples/ScenarioRunner/bin/Release/net10.0/ScenarioRunner.dll" | ||
|
|
||
| # Navigate to category list, browse Arrows → Box Drawing → Emoji, then context menu | ||
| $ks = 'wait:1200,Tab,Tab,wait:400,A,wait:1800,B,o,wait:1800,E,wait:1800,Tab,wait:400,CursorDown,CursorDown,CursorDown,wait:400,Shift+F10,wait:1500,Escape,wait:400,Escape' | ||
|
|
||
| tuirec record ` | ||
| --binary dotnet ` | ||
| --args "$dll,run,Character Map" ` | ||
| --name CharacterMap ` | ||
| --title "Character Map" ` | ||
| --keystrokes $ks ` | ||
| --startup-delay 2000 ` | ||
| --drain 1500 ` | ||
| --cols 120 --rows 30 ` | ||
| --open --copy | ||
| ``` | ||
|
|
||
| **Script breakdown:** | ||
|
|
||
| | Step | Tokens | What happens | | ||
| |------|--------|--------------| | ||
| | 1 | `wait:1200` | Let the CharMap UI fully render | | ||
| | 2 | `Tab,Tab` | Move focus to category list | | ||
| | 3 | `A` | CollectionNavigator jumps to "Arrows" | | ||
| | 4 | `wait:1800` | Pause so viewer sees arrow characters | | ||
| | 5 | `B,o` | Type "Bo" — jumps to "Box Drawing" | | ||
| | 6 | `wait:1800` | Pause so viewer sees box-drawing characters | | ||
| | 7 | `E` | Type "E" — jumps to "Emoji" | | ||
| | 8 | `wait:1800` | Pause so viewer sees emoji characters | | ||
| | 9 | `Tab` | Return focus to charmap grid | | ||
| | 10 | `CursorDown` ×3 | Navigate to a glyph | | ||
| | 11 | `Shift+F10` | Open context menu (Copy Glyph / Copy Code Point) | | ||
| | 12 | `wait:1500,Escape` | Let viewer see the menu, then dismiss | | ||
| | 13 | `Escape` | Quit | | ||
|
|
||
| **Key techniques demonstrated:** | ||
| - **CollectionNavigator typing** — type category name prefixes to jump directly | ||
| (much better than scrolling through dozens of categories with arrow keys) | ||
| - **Context menu** — `Shift+F10` (the `PopoverMenu.DefaultKey`) shows the | ||
| right-click menu on the selected glyph | ||
| - **Generous waits** — 1800ms between feature demonstrations so viewers | ||
| can absorb each state change | ||
|
|
||
| --- | ||
|
|
||
| ## Recording Individual View Sub-classes with EnableForDesign | ||
|
|
||
| (Coming soon — will use a dedicated design-mode runner that instantiates | ||
| a single View with `EnableForDesign()` and records its interactions.) | ||
|
|
||
| --- | ||
|
|
||
| ## Recording Standalone Example Apps | ||
|
|
||
| For apps in `Examples/` that are not UICatalog scenarios: | ||
|
|
||
| ```powershell | ||
| $dll = "./Examples/<AppName>/bin/Release/net10.0/<AppName>.dll" | ||
| $ks = 'wait:1000,<keystrokes>,Escape' | ||
|
|
||
| tuirec record ` | ||
| --binary dotnet ` | ||
| --args "$dll" ` | ||
| --name <app-id> ` | ||
| --title "<App Name> Demo" ` | ||
| --keystrokes $ks ` | ||
| --startup-delay 2000 ` | ||
| --drain 2000 ` | ||
| --cols 120 --rows 30 ` | ||
| --open --copy | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Validation Checklist | ||
|
|
||
| After every recording, verify: | ||
|
|
||
| - [ ] `tuirec record` exited with code 0 and wrote both `.gif` and `.cast`. | ||
| - [ ] **Error check** — no errors in the cast: | ||
| ```powershell | ||
| Select-String -Path artifacts/<name>.cast -Pattern "error|unknown|not found|usage:" -CaseSensitive:$false | ||
| ``` | ||
| - [ ] **GIF is not blank** — file size > 100KB for a typical scenario recording. | ||
| (A blank/static GIF is typically < 50KB.) | ||
| - [ ] **Visual check** — open the GIF (`--open` flag) and confirm: | ||
| - The app content is visible (menu bar, controls, content). | ||
| - The interaction sequence is visible (scrolling, focus changes, etc.). | ||
| - The recording ends cleanly (no frozen frame or abrupt cutoff). | ||
| - [ ] **Output path is correct** — scenario GIFs go with their scenario code: | ||
| ``` | ||
| Examples/UICatalog/Scenarios/<ScenarioDir>/<ScenarioName>.gif | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| | Problem | Cause | Fix | | ||
| |---------|-------|-----| | ||
| | Wide glyphs misaligned in GIF | Emoji/CJK chars are 2-cell wide; agg renders per-cell | Avoid emoji/CJK categories; use single-width ranges (Arrows, Box Drawing, etc.) | | ||
| | Nav keys ignored with `--kitty-keyboard` | tuirec bug [#54](https://github.com/gui-cs/tuirec/issues/54) — sends wrong codepoints | Remove `--kitty-keyboard` | | ||
| | App doesn't quit | Wrong quit key or key not delivered | Use `Escape` (the default quit key); check `--kitty-keyboard` interaction | | ||
| | Blank frames at start/end | Pre/postroll not trimmed | `--trim` is on by default in v0.4.2+; ensure tuirec is up-to-date | | ||
| | GIF validation: 1 frame | `--trim` removes all frames for static views | Use `--trim=false` for views with no visual change during demo | | ||
| | Recording times out | App stuck / wrong keystrokes | Check with `--verbosity high`, fix script | | ||
| | `--binary` permission error | Relative path on Windows | Use `./` prefix or absolute path with forward slashes | | ||
| | Backtick text missing | PowerShell interpolation | Use single-quoted `$ks` variable | | ||
|
|
||
| --- | ||
|
|
||
| ## Agent Workflow Summary | ||
|
|
||
| When asked to record a scenario GIF: | ||
|
|
||
| 1. **Build** — `dotnet build Examples/ScenarioRunner -c Release` | ||
| 2. **Find scenario name** — `dotnet run --project Examples/ScenarioRunner -c Release --no-build -- list` | ||
| 3. **Read `GetDemoKeyStrokes()`** — find it in the scenario source file | ||
| 4. **Compose keystrokes** — translate to tuirec syntax, add waits, keep short | ||
| 5. **Record** — `tuirec record --binary ... --args "run,<Name>" --keystrokes $ks ...` | ||
| 6. **Validate** — error-grep the cast, check GIF file size, visual confirm | ||
| 7. **If nav keys fail** — remove `--kitty-keyboard` and retry | ||
| 8. **Report** — share the output paths and exact command used | ||
|
|
||
| --- | ||
|
|
||
| ## Reference | ||
|
|
||
| - **tuirec repo:** https://github.com/gui-cs/tuirec | ||
| - **Full keystroke syntax:** `tuirec agent-guide` (embeds the complete reference) | ||
| - **CLI flags:** `tuirec record --help` | ||
| - **ScenarioRunner:** `Examples/ScenarioRunner/` — CLI that runs individual UICatalog scenarios |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # Hero GIF Guidance | ||
|
|
||
| For recording Terminal.Gui app/scenario GIFs, use: | ||
|
|
||
| - [`./README.md`](./README.md) — Full recording workflow with tuirec | ||
|
|
||
| ## Quick Reference | ||
|
|
||
| ```powershell | ||
| # Install tuirec (one-time) | ||
| go install github.com/gui-cs/tuirec/cmd/tuirec@latest | ||
|
|
||
| # Build ScenarioRunner (before any recording) | ||
| dotnet build Examples/ScenarioRunner/ScenarioRunner.csproj -c Release | ||
|
|
||
| # Record a scenario (cross-platform: use dotnet to run the DLL) | ||
| $dll = "./Examples/ScenarioRunner/bin/Release/net10.0/ScenarioRunner.dll" | ||
| $ks = 'wait:1000,<keystrokes>,Escape' | ||
| tuirec record --binary dotnet --args "$dll,run,<Scenario Name>" --name <id> ` | ||
| --keystrokes $ks --startup-delay 2000 --drain 2000 --cols 120 --rows 30 --open | ||
| ``` | ||
|
|
||
| See `README.md` (this directory) for complete guidance including keystroke syntax, | ||
| PowerShell quoting rules, and the `--kitty-keyboard` decision tree. | ||
|
|
||
| ## File Placement | ||
|
|
||
| - **Scenario GIFs** go alongside the scenario `.cs` file: | ||
| `Examples/UICatalog/Scenarios/<ScenarioDir>/<ScenarioName>.gif` | ||
| - **View GIFs** go in `docfx/images/views/<ViewName>.gif` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.