Add survey example app demonstrating Terminal.Gui + Spectre.Console#9
Open
tig wants to merge 28 commits into
Open
Add survey example app demonstrating Terminal.Gui + Spectre.Console#9tig wants to merge 28 commits into
tig wants to merge 28 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9c189c4ff4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
tig
pushed a commit
that referenced
this pull request
May 26, 2026
The --cat path in CliHost returned the cat result's exit code but never wrote its message, so a viewer command that fails validation (e.g. card --age 999 --cat) exited 65 with no diagnostic output. Route non-success cat results through ResultWriter so the error reaches stderr (or the error envelope under --json) while successful renders are untouched. Adds a regression test. Addresses Codex review feedback on PR #9. https://claude.ai/code/session_014gpZxbbFxi3SNNqqHPc4Wi
Ports Spectre.Console's Prompt example to Terminal.Gui.Cli as a TG/Spectre collaboration (spectre.console#2128): Terminal.Gui handles interaction, the host adds structured --json, --cat, OpenCLI, and an agent guide, and Spectre.Console renders the resulting profile card (Panel, Table, BarChart). To emit a structured result value under source-generated JSON (constitution C4), add CliHostOptions.ResultJsonResolver plus a JsonEnvelope.ToJson overload that combines a consumer JsonSerializerContext with the built-in context via JsonTypeInfoResolver.Combine. This keeps serialization reflection-free and AOT-compatible; update specs/library-spec.md accordingly. The in-TUI Spectre rendering (SpectreView) will be wired once the Terminal.Gui.Interop.Spectre bridge package is published. https://claude.ai/code/session_014gpZxbbFxi3SNNqqHPc4Wi
The --cat path in CliHost returned the cat result's exit code but never wrote its message, so a viewer command that fails validation (e.g. card --age 999 --cat) exited 65 with no diagnostic output. Route non-success cat results through ResultWriter so the error reaches stderr (or the error envelope under --json) while successful renders are untouched. Adds a regression test. Addresses Codex review feedback on PR #9. https://claude.ai/code/session_014gpZxbbFxi3SNNqqHPc4Wi
- Remove CardCommand and card.md; survey is the sole default command - Replace flat form with a 7-step Wizard (Name, Fruits, FavoriteFruit, Sport, Age, Password, Color) matching the Spectre Prompt example - Use AppModel.Inline for inline terminal rendering - Wizard is the main runnable (no wrapper Window/Runnable) - Title: 'Survey - Enter to accept, Esc to quit' - Rounded border with top-only thickness (clet-style) - Multi-select ListView with hierarchical berries (indented sub-items) - Conditional 'pick one' step only shown when >1 fruit selected - OptionSelector for sport with linked TextField for custom input - ColorPicker with text fields and color name enabled - Secret TextField for password entry - Render Spectre card to stdout after wizard completes - Update SurveyAnswers to include FavoriteFruit and Password fields - Update ProfileInput, SpectreProfile, JSON context, help files - Update integration tests for new command structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add Label views before each input control (e.g. _Name:, _Age:) - Fix wizard.Accepting to not set args.Handled (allows natural close) - Add --confirm option with final confirmation step showing results - Use explicit heights instead of Dim.Fill for Dim.Auto compatibility - Extract BuildAnswers and FormatPreview helper methods - Route empty args to default command in CliHost Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add Accepting += args.Handled = true on all TextFields to prevent Enter from bubbling up to the Wizard and closing it prematurely - Move labels inline with fields (X = Pos.Right(label) + 1, Y = 0) - Use Height = Dim.Fill() on ListView, ColorPicker, and confirm label so all wizard steps share the same height as the tallest - Add tests: default command routing and --confirm option acceptance Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Major cleanup addressing review feedback: - Replace 4 parallel string arrays with single tuple array for fruit data - Remove TextField.Accepting overrides (filed gui-cs/Terminal.Gui#5430) - Set explicit wizard Height based on tallest step (fruits list) - Add age validation via wizard.MovingNext that prevents advancement - Use vendored SpectreView for --confirm step (renders Spectre card) - Add --confirm to help documentation - Simplify sport TextField.TextChanged logic Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use BuildTable() instead of Build() for the confirm step's SpectreView so the results render without the outer Panel/Double border (the WizardStep already provides its own border). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Build() now returns just the rounded Table (no outer Panel with BoxBorder.Double). Removed the duplicate BuildTable() method since Build() is now identical. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- All TextFields now use Width = Dim.Percent(50) instead of Dim.Fill() - Confirm step extracts background color from the WizardStep via GetAttributeForRole(VisualRole.Normal) and passes it to SpectreProfile.Build() so the table border blends with the wizard - Final stdout output still uses default colors (no backgroundColor) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Set wizard SchemeName to SchemeManager.SchemesToSchemeName(Schemes.Accent) - Changed fruitsList and favFruitList Width from Dim.Fill() to Dim.Auto() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The VS debugger's internal console doesn't properly support the virtual terminal escape sequences needed by Terminal.Gui's Inline AppModel. Setting useExternalConsole=true launches an external terminal (Windows Terminal) which handles VT sequences correctly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
AppModel.Inline was causing a blank/hung console in the VS debugger. Clet doesn't set AppModel either - it uses the default (FullScreen) which the CliHost handles via Application.Create().Init(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- TextField.Text is non-null in current TG API, remove ?? string.Empty - Add using aliases for Attribute and Color to avoid verbose qualifiers - Use 'and' pattern instead of separate >= check - Use ?? instead of ternary for null coalescing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
9cbb2f5 to
324c0d2
Compare
The #15 fix skipped Init() for inline commands, but Terminal.Gui requires Init before Run/RunAsync. Call Init() unconditionally after setting AppModel. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Setting app.AppModel on the instance after Create() was too late - the constructor copies from the static Application.AppModel. Set the static property before Create() so the instance picks it up correctly and the driver initializes in inline mode. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Spectre card was being written to Console.Out inside RunAsync while TG was still active, causing it to render in the wrong position. Now the command returns CommandStatus.Ok with the result, and SurveyAnswers.ToString() renders the Spectre table. ResultWriter outputs it after the IApplication is disposed and the console is properly restored. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
d1167ba to
5be0b2e
Compare
Terminal.Gui changes Console.OutputEncoding during its session, which replaces Console.Out internally. After shutdown the caller's captured stdout reference is stale (points to the old writer with wrong encoding). After RunWithTerminalGuiAsync returns, ensure UTF-8 and refresh stdout/stderr to Console.Out/Error so both Spectre's Unicode detection in ToString() and the actual write use the correct encoding and writer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
5be0b2e to
135fe25
Compare
Each step now has a right-side help panel demonstrating various markdown features: headings, bold/italic, bullet lists, numbered lists, tables, blockquotes, inline code, and links. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the new TreeView CheckboxMode (from the copilot-add-built-in-checkbox- mode-for-treeview branch) instead of the ListView hack with manual [x]/[ ] prefixes. Berries are now a proper parent node with child items, and checking/unchecking cascades through the hierarchy. Switched local TG reference to the checkbox mode branch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The StepChanged handler was calling GoNext() whenever favFruitStep had <=1 selected fruits, regardless of direction. This caused pressing Back from the sport step to immediately bounce forward again. Track direction via MovingBack/MovingNext events and call GoBack() when navigating backward through an irrelevant step. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ctre - Update TerminalGuiVersion to 2.4.3-develop.57 (includes wizard fix, TreeView CheckboxMode) - Add Terminal.Gui.Interop.Spectre package reference to survey project - Remove vendored SpectreView.cs and SpectreMarkupBridge.cs (now in package) - Remove UseLocalTerminalGui/LocalTerminalGuiPath from Directory.Build.props - Remove conditional ProjectReference from Terminal.Gui.Cli.csproj Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove driver buffer content assertions that are unreliable with TextMateSyntaxHighlighter in headless CI environments. The Markdown view requires multiple main loop iterations to render content which is non-deterministic in CI. Tests still validate command correctness via CommandStatus.Ok assertion. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
8659a5a to
a18e942
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Addresses review feedback raised on the (bogus) back-merge PRs #20/#21 so this branch is the complete/correct source of truth: - Fix example project paths in README.md and examples/greet/README.md to the actual examples/greet location (PR #21 P2). The old examples/Terminal.Gui.Cli.ExampleApp / examples/Terminal.Gui.Cli.Greet paths no longer exist and produced project-not-found errors. - Document CliHostOptions.DefaultCommand dispatch semantics in specs/library-spec.md, satisfying constitution C2 (PR #20 P1). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tig
added a commit
that referenced
this pull request
Jun 11, 2026
…g in CliHost (C1) (#22) * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering. Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again. No public API change; rendering behavior is unchanged. Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style: apply ReSharper cleanup normalizations Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Revert "style: apply ReSharper cleanup normalizations" This reverts commit 25921ba. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The defensive init existed only because CliHost previously skipped Init() for inline input commands. This branch makes CliHost always call app.Init() before command.RunAsync, so the call is dead code — and it was itself a C1 violation (only CliHost may call Terminal.Gui lifecycle APIs). Completes the lifecycle centralization started in #22. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tig
added a commit
that referenced
this pull request
Jun 11, 2026
* feat: library improvements extracted from survey example work (#9) Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here): CliHost: - Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently - Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly - Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create() - Run DefaultCommand when args are empty instead of falling through to root help JSON envelope (constitution C4): - Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine InputCommandRunner: - Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation Docs/specs (constitution C2): - Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md - Fix stale example project paths in README.md and examples/greet/README.md Tests/infra: - Add envelope resolver round-trip test - Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions) - Bump Terminal.Gui to 2.4.3 release Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: preserve caller-supplied writers after TUI shutdown (Codex P2) The post-TUI console refresh used `stdout is not StringWriter` to decide whether to re-acquire Console.Out/Error, so any caller-supplied writer that was not a StringWriter (e.g. a StreamWriter over a stream or file) was silently replaced and the result went to the process console. Capture whether each writer is the real console (by reference) before Terminal.Gui runs - the comparison is only valid then, since changing Console.OutputEncoding replaces Console.Out/Error - and refresh each writer independently, leaving caller-supplied writers untouched. Adds an integration regression test that routes the TUI path through a StreamWriter-over-MemoryStream stdout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tig
added a commit
that referenced
this pull request
Jun 11, 2026
* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22) * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering. Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again. No public API change; rendering behavior is unchanged. Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style: apply ReSharper cleanup normalizations Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Revert "style: apply ReSharper cleanup normalizations" This reverts commit 25921ba. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Library improvements extracted from survey example work (#23) * feat: library improvements extracted from survey example work (#9) Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here): CliHost: - Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently - Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly - Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create() - Run DefaultCommand when args are empty instead of falling through to root help JSON envelope (constitution C4): - Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine InputCommandRunner: - Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation Docs/specs (constitution C2): - Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md - Fix stale example project paths in README.md and examples/greet/README.md Tests/infra: - Add envelope resolver round-trip test - Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions) - Bump Terminal.Gui to 2.4.3 release Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: preserve caller-supplied writers after TUI shutdown (Codex P2) The post-TUI console refresh used `stdout is not StringWriter` to decide whether to re-acquire Console.Out/Error, so any caller-supplied writer that was not a StringWriter (e.g. a StreamWriter over a stream or file) was silently replaced and the result went to the process console. Capture whether each writer is the real console (by reference) before Terminal.Gui runs - the comparison is only valid then, since changing Console.OutputEncoding replaces Console.Out/Error - and refresh each writer independently, leaving caller-supplied writers untouched. Adds an integration regression test that routes the TUI path through a StreamWriter-over-MemoryStream stdout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump version to 0.2.0-develop for upcoming release Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tig
added a commit
that referenced
this pull request
Jun 11, 2026
* Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Release v0.1.0-beta.1 (#17) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: remove duplicate TestSetup class introduced by merge --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> * Release v0.1.0 (#19) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Release v0.2.0 (#24) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22) * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering. Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again. No public API change; rendering behavior is unchanged. Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style: apply ReSharper cleanup normalizations Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Revert "style: apply ReSharper cleanup normalizations" This reverts commit 25921ba. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Library improvements extracted from survey example work (#23) * feat: library improvements extracted from survey example work (#9) Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here): CliHost: - Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently - Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly - Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create() - Run DefaultCommand when args are empty instead of falling through to root help JSON envelope (constitution C4): - Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine InputCommandRunner: - Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation Docs/specs (constitution C2): - Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md - Fix stale example project paths in README.md and examples/greet/README.md Tests/infra: - Add envelope resolver round-trip test - Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions) - Bump Terminal.Gui to 2.4.3 release Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: preserve caller-supplied writers after TUI shutdown (Codex P2) The post-TUI console refresh used `stdout is not StringWriter` to decide whether to re-acquire Console.Out/Error, so any caller-supplied writer that was not a StringWriter (e.g. a StreamWriter over a stream or file) was silently replaced and the result went to the process console. Capture whether each writer is the real console (by reference) before Terminal.Gui runs - the comparison is only valid then, since changing Console.OutputEncoding replaces Console.Out/Error - and refresh each writer independently, leaving caller-supplied writers untouched. Adds an integration regression test that routes the TUI path through a StreamWriter-over-MemoryStream stdout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump version to 0.2.0-develop for upcoming release Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tig
added a commit
that referenced
this pull request
Jun 11, 2026
* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22) * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering. Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again. No public API change; rendering behavior is unchanged. Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style: apply ReSharper cleanup normalizations Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Revert "style: apply ReSharper cleanup normalizations" This reverts commit 25921ba. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Library improvements extracted from survey example work (#23) * feat: library improvements extracted from survey example work (#9) Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here): CliHost: - Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently - Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly - Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create() - Run DefaultCommand when args are empty instead of falling through to root help JSON envelope (constitution C4): - Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine InputCommandRunner: - Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation Docs/specs (constitution C2): - Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md - Fix stale example project paths in README.md and examples/greet/README.md Tests/infra: - Add envelope resolver round-trip test - Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions) - Bump Terminal.Gui to 2.4.3 release Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: preserve caller-supplied writers after TUI shutdown (Codex P2) The post-TUI console refresh used `stdout is not StringWriter` to decide whether to re-acquire Console.Out/Error, so any caller-supplied writer that was not a StringWriter (e.g. a StreamWriter over a stream or file) was silently replaced and the result went to the process console. Capture whether each writer is the real console (by reference) before Terminal.Gui runs - the comparison is only valid then, since changing Console.OutputEncoding replaces Console.Out/Error - and refresh each writer independently, leaving caller-supplied writers untouched. Adds an integration regression test that routes the TUI path through a StreamWriter-over-MemoryStream stdout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump version to 0.2.0-develop for upcoming release Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Back-merge v0.2.0 from main into develop (#25) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Release v0.1.0-beta.1 (#17) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: remove duplicate TestSetup class introduced by merge --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> * Release v0.1.0 (#19) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Release v0.2.0 (#24) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22) * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering. Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again. No public API change; rendering behavior is unchanged. Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style: apply ReSharper cleanup normalizations Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Revert "style: apply ReSharper cleanup normalizations" This reverts commit 25921ba. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Library improvements extracted from survey example work (#23) * feat: library improvements extracted from survey example work (#9) Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here): CliHost: - Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently - Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly - Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create() - Run DefaultCommand when args are empty instead of falling through to root help JSON envelope (constitution C4): - Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine InputCommandRunner: - Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation Docs/specs (constitution C2): - Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md - Fix stale example project paths in README.md and examples/greet/README.md Tests/infra: - Add envelope resolver round-trip test - Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions) - Bump Terminal.Gui to 2.4.3 release Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: preserve caller-supplied writers after TUI shutdown (Codex P2) The post-TUI console refresh used `stdout is not StringWriter` to decide whether to re-acquire Console.Out/Error, so any caller-supplied writer that was not a StringWriter (e.g. a StreamWriter over a stream or file) was silently replaced and the result went to the process console. Capture whether each writer is the real console (by reference) before Terminal.Gui runs - the comparison is only valid then, since changing Console.OutputEncoding replaces Console.Out/Error - and refresh each writer independently, leaving caller-supplied writers untouched. Adds an integration regression test that routes the TUI path through a StreamWriter-over-MemoryStream stdout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump version to 0.2.0-develop for upcoming release Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: restore Application.AppModel after dispatch and lock in init contract (#27) Application.AppModel is process-wide static state. RunWithTerminalGuiAsync left it set to the dispatched command's app model (e.g. Inline), so later Terminal.Gui sessions in the same process - embedding scenarios, headless MarkdownRenderer rendering - inherited the wrong model. Save the previous value and restore it in a finally block (issue #26). Adds regression tests written first: - InputCommand_Inline_RestoresAppModelAfterDispatch and InputCommand_ThrowsCancellation_RestoresAppModel failed before the fix. - InputCommand_Inline_ReceivesInitializedApplication locks in the ICliCommand.RunAsync init contract for the inline path (issue #18, already fixed by the always-Init change in #23). Fixes #18 Fixes #26 Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * chore: bump version to 0.2.1-develop for upcoming release Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
tig
added a commit
that referenced
this pull request
Jun 11, 2026
* Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Release v0.1.0-beta.1 (#17) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: remove duplicate TestSetup class introduced by merge --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> * Release v0.1.0 (#19) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Release v0.2.0 (#24) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22) * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering. Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again. No public API change; rendering behavior is unchanged. Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style: apply ReSharper cleanup normalizations Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Revert "style: apply ReSharper cleanup normalizations" This reverts commit 25921ba2e94cb5bd699c766a8b81f84bc9e2df8d. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Library improvements extracted from survey example work (#23) * feat: library improvements extracted from survey example work (#9) Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here): CliHost: - Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently - Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly - Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create() - Run DefaultCommand when args are empty instead of falling through to root help JSON envelope (constitution C4): - Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine InputCommandRunner: - Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation Docs/specs (constitution C2): - Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md - Fix stale example project paths in README.md and examples/greet/README.md Tests/infra: - Add envelope resolver round-trip test - Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions) - Bump Terminal.Gui to 2.4.3 release Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: preserve caller-supplied writers after TUI shutdown (Codex P2) The post-TUI console refresh used `stdout is not StringWriter` to decide whether to re-acquire Console.Out/Error, so any caller-supplied writer that was not a StringWriter (e.g. a StreamWriter over a stream or file) was silently replaced and the result went to the process console. Capture whether each writer is the real console (by reference) before Terminal.Gui runs - the comparison is only valid then, since changing Console.OutputEncoding replaces Console.Out/Error - and refresh each writer independently, leaving caller-supplied writers untouched. Adds an integration regression test that routes the TUI path through a StreamWriter-over-MemoryStream stdout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump version to 0.2.0-develop for upcoming release Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Release v0.2.1 (#28) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22) * fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering. Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again. No public API change; rendering behavior is unchanged. Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style: apply ReSharper cleanup normalizations Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Revert "style: apply ReSharper cleanup normalizations" This reverts commit 25921ba2e94cb5bd699c766a8b81f84bc9e2df8d. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Library improvements extracted from survey example work (#23) * feat: library improvements extracted from survey example work (#9) Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here): CliHost: - Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently - Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly - Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create() - Run DefaultCommand when args are empty instead of falling through to root help JSON envelope (constitution C4): - Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine InputCommandRunner: - Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation Docs/specs (constitution C2): - Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md - Fix stale example project paths in README.md and examples/greet/README.md Tests/infra: - Add envelope resolver round-trip test - Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions) - Bump Terminal.Gui to 2.4.3 release Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: preserve caller-supplied writers after TUI shutdown (Codex P2) The post-TUI console refresh used `stdout is not StringWriter` to decide whether to re-acquire Console.Out/Error, so any caller-supplied writer that was not a StringWriter (e.g. a StreamWriter over a stream or file) was silently replaced and the result went to the process console. Capture whether each writer is the real console (by reference) before Terminal.Gui runs - the comparison is only valid then, since changing Console.OutputEncoding replaces Console.Out/Error - and refresh each writer independently, leaving caller-supplied writers untouched. Adds an integration regression test that routes the TUI path through a StreamWriter-over-MemoryStream stdout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump version to 0.2.0-develop for upcoming release Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Back-merge v0.2.0 from main into develop (#25) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Release v0.1.0-beta.1 (#17) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks (#14) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help TUI: set Markdown.Text in Initialized handler, add integration tests The help command's TUI viewer rendered empty content because Markdown.Text was set before the view was initialized/laid out. Following the pattern from gui-cs/clet's MarkdownClet, set the text inside the Initialized event handler on the containing Runnable. Also switches from RunnableWrapper to a plain Runnable with an embedded Markdown view — the help viewer is read-only and needs no result extraction. Adds integration tests using Application.Create()/Init(ansi) with StopAfterFirstIteration to verify: - The TUI renders without hanging - Driver contents contain expected command text - Subcommand help renders correctly - RenderCatAsync produces ANSI output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hero GIF recording and polish README - Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app - Rewrite README for clarity: add badges, a Why section, feature table, real JSON output example, contributing pointer, and cleaner structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MarkdownRenderer global state leaks - Save and restore DisableRealDriverIO env var in finally block - Move app.Init inside try/finally so cleanup runs if Init throws - Add MarkdownRendererTests verifying env var restoration - Disable test parallelization (Terminal.Gui uses global state) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: set IApplication.AppModel and defer Init() for inline input commands (#16) RunWithTerminalGuiAsync previously always called Init() regardless of whether the command actually uses the TUI. For inline input commands, Init() modifies terminal state (cursor save/scroll), and if the command returns without running the TUI event loop (e.g. greet hello), Dispose() restores the cursor to the wrong position, causing output to appear at incorrect rows. Fix: - Set app.AppModel on the IApplication instance (not the process-wide static) - Only call Init() upfront for fullscreen commands (viewers, --fullscreen) - For inline input commands, defer Init() to InputCommandRunner where the TUI is actually started via app.RunAsync() - Commands that compute and return without TUI (like greet) never trigger Init(), so terminal state is never modified Fixes #15 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: remove duplicate TestSetup class introduced by merge --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> * Release v0.1.0 (#19) * feat: help TUI viewer, markdown rendering, rename ExampleApp to greet - HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable + Markdown + StatusBar) matching clet's pattern, instead of returning raw text in CommandResult - MetadataHelpProvider.GetRootHelp emits markdown (tables, headers) instead of plain text - CliHost.WriteRootFlag passes --help output through MarkdownRenderer.RenderToAnsi for ANSI-styled stdout - Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet with AssemblyName=greet - Add README.md for the greet example app - Add visual UI tests (CommandUiHarness + golden-file assertions) ported from clet's CletUiHarness pattern - Add MetadataHelpProviderTests and CliHost help rendering tests Closes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix terminal encoding for ANSI rendering and add multiple help topics - Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw cycle, and restore encoding afterward. Fixes garbled box-drawing chars. - Add FarewellCommand with --until option for navigation testing - Add embedded markdown help files (help.md, greet.md, farewell.md, info.md) - Configure EmbeddedMarkdownHelpProvider in greet example - Fix InfoCommand to properly launch TUI viewer (was returning text without calling app.RunAsync, causing terminal to hang until Enter pressed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add default command support, help link navigation, and fix positional args - Add DefaultCommand option to CliHostOptions so bare args/options are retried as the default command (e.g. 'greet World' == 'greet greet World') - Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync - Add help:topic link navigation in HelpCommand via Markdown.LinkClicked - Add 'Back to main help' links in all sub-topic help files - Add help:command anchors in root help.md for topic navigation - Make GreetCommand and FarewellCommand accept positional args for name - Set greet example DefaultCommand = 'greet' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Port clet's BrowseBar with back/forward nav and syntax highlighting - Add BrowseBar (ported from clet) with back/forward history stacks, Ctrl+Left/Right shortcuts, and proper statusbar styling - Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern: BrowseBar, LinkClicked handler, NavigateTo, viewport reset - Add TextMateSyntaxHighlighter for code block coloring - Add horizontal scrollbar to markdown view - Update golden file for new status bar layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add visual help browser tests and greet example execution tests - HelpBrowserUiTests: proves BrowseBar back/forward arrows render, embedded help content displays, subcommand view shows options, and golden file assertion for the browser layout - GreetExampleTests: proves every documented example in the help files actually works (greet World, --formal Alice, farewell Bob, farewell --until tomorrow Bob, default command dispatch, etc.) - Add embedded help.md resource to integration test assembly - Total: 24 integration tests, 17 unit tests (41 total, all passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Escape markdown table cells in MetadataHelpProvider Pipe characters and newlines in command/option descriptions would break the generated markdown table structure. Add EscapeCell helper that replaces | with \| and collapses newlines to spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit type in collection expression for ReSharper compliance ReSharper cannot infer target type for 'new' inside collection expressions, so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add SourceLink and symbol package support (#11) Enable source debugging and .snupkg generation for NuGet consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Back-merge main into develop (#13) * Plan: help command and --help flag should render markdown Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix help command and --help flag to render markdown - Convert MetadataHelpProvider.GetRootHelp to generate markdown with ## headings, bullet lists, and backtick formatting - Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi instead of plain stdout.WriteLine - Fix HelpCommand.RunAsync to display markdown in a fullscreen Terminal.Gui Markdown viewer using RunnableWrapper - Add tests for --help ANSI output, help --cat, and MetadataHelpProvider markdown generation Fixes #5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>…
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Adds a complete example application (
survey) that demonstrates the collaboration between Terminal.Gui and Spectre.Console, along with the scriptable surfaces provided by Terminal.Gui.Cli (JSON output,--catrendering, OpenCLI metadata, and agent guides).The survey app collects a user profile through either an interactive Terminal.Gui form or headless command-line options, then renders it as a rich Spectre.Console card. It showcases how Terminal.Gui handles interaction and navigation while Spectre.Console provides rich rendering, with the host layer adding JSON serialization, structured output, and AI-agent discoverability.
Key Changes
New example project (
examples/survey/Terminal.Gui.Cli.Survey.csproj):SurveyCommand— input command with interactive Terminal.Gui form and headless modeCardCommand— viewer command rendering profiles as Spectre.Console cardsSurveyAnswers— structured result type (record)ProfileInput— shared option parsing and validationSpectreProfile— Spectre.Console renderable builderSurveyJsonContext— source-generated JSON serialization contextSurveyApp— host configuration and command registrationLibrary enhancements to support consumer-defined result types:
CliHostOptions.ResultJsonResolver— allows registering a consumerIJsonTypeInfoResolverfor custom result type serializationJsonEnvelope.ToJson(IJsonTypeInfoResolver?)— overload that combines consumer and built-in JSON contextsResultWriter.Write()— updated to pass resolver through the serialization pipelineCliHost.ExecuteCommandAsync()— passes resolver to result writerTest coverage:
SurveyExampleTests— integration tests covering headless input, JSON output, validation, and Spectre renderingDocumentation:
specs/library-spec.md— updated to document result value JSON serialization contractImplementation Details
TextField,Label, andStatusBarwith F2 to submit and validation feedback--catis used, or shows markdown in a Terminal.Gui window otherwiseJsonSerializerContexton the hosthttps://claude.ai/code/session_014gpZxbbFxi3SNNqqHPc4Wi