Skip to content

Back-merge v0.1.0 from main into develop#21

Closed
tig wants to merge 9 commits into
developfrom
backmerge/v0.1.0
Closed

Back-merge v0.1.0 from main into develop#21
tig wants to merge 9 commits into
developfrom
backmerge/v0.1.0

Conversation

@tig

@tig tig commented Jun 11, 2026

Copy link
Copy Markdown
Member

Automatic back-merge after release v0.1.0. Merge this to keep develop in sync with main.

tig and others added 9 commits May 24, 2026 09:00
Expand README and add hero GIF recording guide
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- 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>
…on 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>
Help command and --help flag should render markdown
- 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>
* 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>
* 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>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0509092645

ℹ️ 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".

Comment on lines +192 to +195
if (!useInline)
{
app.Init ();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve the RunAsync initialization contract

When an input command is run without --fullscreen, useInline is true and the host now skips app.Init() before invoking command.RunAsync. That violates the existing ICliCommand.RunAsync contract (“Runs the command after the host has initialized Terminal.Gui”) and breaks consumer input commands that use the supplied IApplication directly (for example reading app.Driver/app.Screen or calling app.RunAsync) instead of going through InputCommandRunner; this is now the default path for every input command.

Useful? React with 👍 / 👎.

Comment thread examples/greet/README.md
| Command | Description |
|---------|-------------|
| `greet` | Prompt for a name and return a greeting. |
| `info` | Display application information. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use the actual example project path

The old example app was removed and the solution now points to examples/greet/Terminal.Gui.Cli.Greet.csproj, but this build command still targets examples/Terminal.Gui.Cli.Greet/... (and the run command below uses the same nonexistent directory). Anyone following the new sample README will get a project-not-found error instead of being able to build or run the example.

Useful? React with 👍 / 👎.

Comment thread README.md

# Example app
# Try the example app
dotnet run --project examples/Terminal.Gui.Cli.ExampleApp -- greet --initial "World" --json

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update the root README example path

This command still references examples/Terminal.Gui.Cli.ExampleApp, but that project is deleted in this commit and the solution now includes examples/greet/Terminal.Gui.Cli.Greet.csproj. The documented “Try the example app” command will fail with a missing project path for users building from source.

Useful? React with 👍 / 👎.

tig added a commit that referenced this pull request Jun 11, 2026
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

tig commented Jun 11, 2026

Copy link
Copy Markdown
Member Author

Closing: develop already contains all of this content (via the original feature PRs and back-merge #13) — the commits differ only by SHA. A merge-tree against develop shows the only delta is src/Terminal.Gui.Cli/MarkdownRenderer.cs, where this branch carries the old lifecycle code that would conflict with / regress the C1 fix merged in #22. The valid CR feedback raised here (greet/root README paths, RunAsync Init contract) was folded into #9 instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant