Skip to content

Add Spectre.Console integration for rich terminal output#9

Merged
carldebilly merged 9 commits intomainfrom
dev/cdb/spectre
Mar 17, 2026
Merged

Add Spectre.Console integration for rich terminal output#9
carldebilly merged 9 commits intomainfrom
dev/cdb/spectre

Conversation

@carldebilly
Copy link
Member

@carldebilly carldebilly commented Mar 17, 2026

Summary

  • Add Repl.Spectre package providing Spectre.Console integration for REPL applications that want rich terminal rendering
  • SpectreHumanOutputTransformer: renders objects as bordered tables, grids with label-value pairs, and color-coded IReplResult messages (green for success, red for error, yellow for validation/not found, etc.)
  • SpectreInteractionHandler: handles interactive prompts (single/multi selection, confirmation, text input, secret input, clear screen) using Spectre.Console widgets, with automatic fallback to Unhandled for hosted sessions or redirected input
  • SessionAnsiConsole: per-session IAnsiConsole isolation routing output through ReplSessionIO, supporting both live terminal and string-capture rendering modes
  • SpectreConsoleOptions: configurable Unicode support for Spectre rendering
  • SpectreReplExtensions.UseSpectreConsole(): single extension method to register the transformer, interaction handler, and banner format in one call
  • BannerFormats on OutputOptions: extensible set of output format names eligible for banner rendering, replacing the previous hardcoded "human" check — allows custom formats like "spectre" to display banners
  • Mnemonic-aware choice rendering: strips mnemonic markers (_AbortAbort) for Spectre display and maps selections back to original indices
  • Add sample 07-spectre demonstrating 21 Spectre.Console features including tables, panels, trees, bar charts, calendars, Figlet text, and interactive prompts
  • Fix MapBackToOriginalIndex returning 0 instead of -1 on no-match, which silently included the wrong choice in multi-selection results
  • Replace generic catch clauses with specific exception types, add using on disposable StringWriter

Introduces a new extension package that provides:
- SpectreInteractionHandler: rich prompts (SelectionPrompt,
  MultiSelectionPrompt, ConfirmationPrompt, TextPrompt, Secret)
  replacing the built-in arrow-key menus
- IAnsiConsole DI injection for commands to use Spectre renderables
  (tables, trees, panels, markup)
- SpectreHumanOutputTransformer: "spectre" output format rendering
  collections as bordered Spectre tables

Usage: services.AddSpectreConsole() + app.UseSpectreConsole()
Comprehensive sample with 14 commands: tour (guided walkthrough),
list (auto-rendered table), detail (Panel+Grid), chart (BarChart+
BreakdownChart), tree, json (JsonText), path (TextPath+Columns),
calendar, figlet (FigletText), status (spinner), progress (bars),
add/configure/login (Spectre-powered prompts via IReplInteractionChannel).

Also fix banner rendering for custom output formats: both
TryRenderBannerAsync and ShouldRenderBanner hardcoded "human" as the
only banner-eligible format, so banners never appeared with Spectre.
Added OutputOptions.BannerFormats (ISet<string>) so custom formats
like "spectre" can opt in, and UseSpectreConsole() registers itself.
The sample banner now uses IAnsiConsole to render a FigletText header.
Introduce SpectreConsoleOptions with a configurable Unicode property
so terminals that lack Unicode support can opt out:
  .UseSpectreConsole(o => o.Unicode = false)

Force Console.OutputEncoding to UTF-8 when Unicode is enabled,
fixing progress bars, spinners and box-drawing characters that
rendered as '?' on Windows due to the default code page.

Both SessionAnsiConsole factory methods now apply options through
a single ApplyOptions helper, ready for future capability settings.
- samples/07-spectre/README.md: full guide with command reference,
  features coverage table, integration paths, and configuration
- src/Repl.Spectre/README.md: updated with SpectreConsoleOptions,
  banner IAnsiConsole injection, prompt mapping table, setup guide
- README.md: add Repl.Spectre to packages table, sample 07 to
  learning path, interaction doc to documentation index
- docs/architecture.md: add Repl.Spectre to project boundaries
- docs/interaction.md: add Spectre.Console integration section
github-code-quality[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

… catches

- Fix MapBackToOriginalIndex returning 0 instead of -1 on no-match,
  which silently included the first choice in multi-selection results
- Add using declaration on StringWriter in RenderToString
- Replace generic catch clauses with specific exception types
  (IOException, PlatformNotSupportedException, InvalidOperationException)
- Use explicit .Where() filter instead of if-in-foreach
- Add Repl.SpectreTests project with unit tests for the bug and helpers
- Add BannerFormats unit tests in Repl.Tests
@carldebilly carldebilly changed the title Add Spectre support Add Spectre.Console integration for rich terminal output Mar 17, 2026
devin-ai-integration[bot]

This comment was marked as resolved.

Move the swap of the default item to index 0 before building the
SelectionPrompt and calling AddChoices, since Spectre copies items
at call time and ignores subsequent list mutations.
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

When AskSecretOptions is null, the Spectre handler was calling
Secret(mask: null) which hides all keystroke feedback. The core
framework defaults Mask to '*', so the Spectre handler should
match that behavior.
Add remarks explaining the process-wide shared state and the
refactoring path if per-app isolation is needed in the future.
devin-ai-integration[bot]

This comment was marked as resolved.

Distinguish between no options (default to '*') and explicit
Mask = null (invisible input with no echo), matching the contract
defined by AskSecretOptions.
@carldebilly carldebilly enabled auto-merge March 17, 2026 04:25
@carldebilly carldebilly merged commit dec7ccc into main Mar 17, 2026
11 checks passed
@carldebilly carldebilly deleted the dev/cdb/spectre branch March 17, 2026 04:30
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