From ff783205c523356c537902399740fb5c6e68f24a Mon Sep 17 00:00:00 2001 From: Phil Scott Date: Thu, 9 Apr 2026 11:26:58 -0400 Subject: [PATCH] Add new example VCR scripts and corresponding SVG assets for CLI documentation --- .../VCR/cli-customizing-help-usage.tape | 14 +++ .../VCR/cli-defining-arguments-help.tape | 14 +++ .../VCR/cli-di-step1.tape | 17 ++++ .../VCR/cli-di-step2.tape | 14 +++ .../VCR/cli-di-step3.tape | 20 +++++ .../VCR/cli-dictionary-lookup-output.tape | 14 +++ .../VCR/cli-flag-arguments-help.tape | 14 +++ .../VCR/cli-logging-step1.tape | 14 +++ .../VCR/cli-logging-step2.tape | 14 +++ .../VCR/cli-logging-step3.tape | 20 +++++ .../VCR/cli-multi-command-step1.tape | 21 +++++ .../VCR/cli-multi-command-step2.tape | 26 ++++++ .../VCR/cli-multi-command-step3.tape | 21 +++++ .../VCR/cli-required-options-help.tape | 14 +++ .../creating-custom-renderables-tutorial.tape | 2 - Spectre.Docs.Examples/VCR/rule.tape | 1 - .../Components/Shared/Screenshot.razor | 86 ++++++++++++++++--- .../assets/cli-customizing-help-usage.svg | 1 + .../assets/cli-defining-arguments-help.svg | 1 + Spectre.Docs/Content/assets/cli-di-step1.svg | 1 + Spectre.Docs/Content/assets/cli-di-step2.svg | 1 + Spectre.Docs/Content/assets/cli-di-step3.svg | 1 + .../assets/cli-dictionary-lookup-output.svg | 1 + .../assets/cli-flag-arguments-help.svg | 1 + .../Content/assets/cli-logging-step1.svg | 1 + .../Content/assets/cli-logging-step2.svg | 1 + .../Content/assets/cli-logging-step3.svg | 1 + .../assets/cli-multi-command-step1.svg | 1 + .../assets/cli-multi-command-step2.svg | 1 + .../assets/cli-multi-command-step3.svg | 1 + .../assets/cli-required-options-help.svg | 1 + .../configuring-commandapp-and-commands.md | 18 +--- .../how-to/customizing-help-text-and-usage.md | 12 +-- .../how-to/defining-commands-and-arguments.md | 11 +-- .../cli/how-to/making-options-required.md | 7 +- .../using-dictionary-and-lookup-options.md | 9 +- .../cli/how-to/using-flag-arguments.md | 10 +-- .../building-a-multi-command-cli-tool.md | 35 +------- .../dependency-injection-in-cli-apps.md | 24 +----- .../cli/tutorials/logging-in-cli-apps.md | 29 +------ Spectre.Docs/appsettings.Development.json | 2 +- 41 files changed, 343 insertions(+), 154 deletions(-) create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-customizing-help-usage.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-defining-arguments-help.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-di-step1.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-di-step2.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-di-step3.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-dictionary-lookup-output.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-flag-arguments-help.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-logging-step1.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-logging-step2.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-logging-step3.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step1.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step2.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step3.tape create mode 100644 Spectre.Docs.Cli.Examples/VCR/cli-required-options-help.tape create mode 100644 Spectre.Docs/Content/assets/cli-customizing-help-usage.svg create mode 100644 Spectre.Docs/Content/assets/cli-defining-arguments-help.svg create mode 100644 Spectre.Docs/Content/assets/cli-di-step1.svg create mode 100644 Spectre.Docs/Content/assets/cli-di-step2.svg create mode 100644 Spectre.Docs/Content/assets/cli-di-step3.svg create mode 100644 Spectre.Docs/Content/assets/cli-dictionary-lookup-output.svg create mode 100644 Spectre.Docs/Content/assets/cli-flag-arguments-help.svg create mode 100644 Spectre.Docs/Content/assets/cli-logging-step1.svg create mode 100644 Spectre.Docs/Content/assets/cli-logging-step2.svg create mode 100644 Spectre.Docs/Content/assets/cli-logging-step3.svg create mode 100644 Spectre.Docs/Content/assets/cli-multi-command-step1.svg create mode 100644 Spectre.Docs/Content/assets/cli-multi-command-step2.svg create mode 100644 Spectre.Docs/Content/assets/cli-multi-command-step3.svg create mode 100644 Spectre.Docs/Content/assets/cli-required-options-help.svg diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-customizing-help-usage.tape b/Spectre.Docs.Cli.Examples/VCR/cli-customizing-help-usage.tape new file mode 100644 index 0000000..d989e8c --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-customizing-help-usage.tape @@ -0,0 +1,14 @@ +Set DisableCursor true +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 80 +Set Rows 20 +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.CustomizingHelpText.Demo.RunAsync(System.String[])" + +Exec "./example --help" +Wait +Sleep 1s +Screenshot "Spectre.Docs/Content/assets/cli-customizing-help-usage.svg" diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-defining-arguments-help.tape b/Spectre.Docs.Cli.Examples/VCR/cli-defining-arguments-help.tape new file mode 100644 index 0000000..31d04ba --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-defining-arguments-help.tape @@ -0,0 +1,14 @@ +Set DisableCursor true +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 80 +Set Rows 20 +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.DefiningCommandsAndArguments.Demo.RunAsync(System.String[])" + +Exec "./example --help" +Wait +Sleep 1s +Screenshot "Spectre.Docs/Content/assets/cli-defining-arguments-help.svg" diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-di-step1.tape b/Spectre.Docs.Cli.Examples/VCR/cli-di-step1.tape new file mode 100644 index 0000000..ad0741f --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-di-step1.tape @@ -0,0 +1,17 @@ +Set DisableCursor true +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 70 +Set Rows 10 +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.DependencyInjection.NoDI.Demo.RunAsync(System.String[])" + +Exec "./example Alice" +Wait +Sleep 1s +Exec "./example Alice --formal" +Wait +Sleep 1s +Screenshot "Spectre.Docs/Content/assets/cli-di-step1.svg" diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-di-step2.tape b/Spectre.Docs.Cli.Examples/VCR/cli-di-step2.tape new file mode 100644 index 0000000..50c700a --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-di-step2.tape @@ -0,0 +1,14 @@ +Set DisableCursor true +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 70 +Set Rows 8 +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.DependencyInjection.WithService.Demo.RunAsync(System.String[])" + +Exec "./example Alice" +Wait +Sleep 1s +Screenshot "Spectre.Docs/Content/assets/cli-di-step2.svg" diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-di-step3.tape b/Spectre.Docs.Cli.Examples/VCR/cli-di-step3.tape new file mode 100644 index 0000000..f25c116 --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-di-step3.tape @@ -0,0 +1,20 @@ +Set DisableCursor true +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 70 +Set Rows 12 +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.DependencyInjection.DIComplete.Demo.RunAsync(System.String[])" + +Exec "./example Alice" +Wait +Sleep 1s +Exec "./example Alice --style Formal" +Wait +Sleep 1s +Exec "./example Alice --style Enthusiastic" +Wait +Sleep 1s +Screenshot "Spectre.Docs/Content/assets/cli-di-step3.svg" diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-dictionary-lookup-output.tape b/Spectre.Docs.Cli.Examples/VCR/cli-dictionary-lookup-output.tape new file mode 100644 index 0000000..cc4adc7 --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-dictionary-lookup-output.tape @@ -0,0 +1,14 @@ +Set DisableCursor true +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 80 +Set Rows 14 +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.DictionaryOptions.Demo.RunAsync(System.String[])" + +Exec "./example --lookup env=dev --lookup env=staging --lookup env=prod --lookup region=us" +Wait +Sleep 1s +Screenshot "Spectre.Docs/Content/assets/cli-dictionary-lookup-output.svg" diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-flag-arguments-help.tape b/Spectre.Docs.Cli.Examples/VCR/cli-flag-arguments-help.tape new file mode 100644 index 0000000..8fc766f --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-flag-arguments-help.tape @@ -0,0 +1,14 @@ +Set DisableCursor true +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 80 +Set Rows 20 +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.FlagArguments.Demo.RunAsync(System.String[])" + +Exec "./example --help" +Wait +Sleep 1s +Screenshot "Spectre.Docs/Content/assets/cli-flag-arguments-help.svg" diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-logging-step1.tape b/Spectre.Docs.Cli.Examples/VCR/cli-logging-step1.tape new file mode 100644 index 0000000..39a0c2a --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-logging-step1.tape @@ -0,0 +1,14 @@ +Set DisableCursor true +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 70 +Set Rows 12 +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.Logging.NoLogging.Demo.RunAsync(System.String[])" + +Exec "./example myfile.txt" +Wait +Sleep 1s +Screenshot "Spectre.Docs/Content/assets/cli-logging-step1.svg" diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-logging-step2.tape b/Spectre.Docs.Cli.Examples/VCR/cli-logging-step2.tape new file mode 100644 index 0000000..b35c05d --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-logging-step2.tape @@ -0,0 +1,14 @@ +Set DisableCursor true +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 70 +Set Rows 14 +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.Logging.WithLogging.Demo.RunAsync(System.String[])" + +Exec "./example myfile.txt" +Wait +Sleep 1s +Screenshot "Spectre.Docs/Content/assets/cli-logging-step2.svg" diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-logging-step3.tape b/Spectre.Docs.Cli.Examples/VCR/cli-logging-step3.tape new file mode 100644 index 0000000..90009e4 --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-logging-step3.tape @@ -0,0 +1,20 @@ +Set DisableCursor true +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 70 +Set Rows 20 +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.Logging.LoggingComplete.Demo.RunAsync(System.String[])" + +Exec "./example myfile.txt" +Wait +Sleep 1s +Exec "./example myfile.txt --logLevel Debug" +Wait +Sleep 1s +Exec "./example myfile.txt --logLevel Warning" +Wait +Sleep 1s +Screenshot "Spectre.Docs/Content/assets/cli-logging-step3.svg" diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step1.tape b/Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step1.tape new file mode 100644 index 0000000..a95c973 --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step1.tape @@ -0,0 +1,21 @@ +Output "Spectre.Docs/Content/assets/cli-multi-command-step1.svg" + +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 70 +Set Rows 12 +Set EndBuffer 5s +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.MultiCommand.Step1.Demo.RunAsync(System.String[])" + +Type "./example add Newtonsoft.Json" +Sleep 400ms +Enter +Sleep 1s + +Type "./example list" +Sleep 400ms +Enter +Sleep 3s diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step2.tape b/Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step2.tape new file mode 100644 index 0000000..bcdc79d --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step2.tape @@ -0,0 +1,26 @@ +Output "Spectre.Docs/Content/assets/cli-multi-command-step2.svg" + +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 70 +Set Rows 16 +Set EndBuffer 5s +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.MultiCommand.Step2.Demo.RunAsync(System.String[])" + +Type "./example add package Newtonsoft.Json" +Sleep 400ms +Enter +Sleep 1s + +Type "./example add reference ../MyLib/MyLib.csproj" +Sleep 400ms +Enter +Sleep 1s + +Type "./example add --help" +Sleep 400ms +Enter +Sleep 5s diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step3.tape b/Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step3.tape new file mode 100644 index 0000000..9fe493f --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-multi-command-step3.tape @@ -0,0 +1,21 @@ +Output "Spectre.Docs/Content/assets/cli-multi-command-step3.svg" + +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 70 +Set Rows 18 +Set EndBuffer 5s +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.MultiCommand.Finished.Demo.RunAsync(System.String[])" + +Type "./example add package Serilog --version 3.0.0 --verbose" +Sleep 400ms +Enter +Sleep 1s + +Type "./example list --verbose" +Sleep 400ms +Enter +Sleep 3s diff --git a/Spectre.Docs.Cli.Examples/VCR/cli-required-options-help.tape b/Spectre.Docs.Cli.Examples/VCR/cli-required-options-help.tape new file mode 100644 index 0000000..c4d7004 --- /dev/null +++ b/Spectre.Docs.Cli.Examples/VCR/cli-required-options-help.tape @@ -0,0 +1,14 @@ +Set DisableCursor true +Set Shell "pwsh" +Set FontSize 22 +Set Theme "one dark" +Set TransparentBackground "true" +Set Cols 80 +Set Rows 20 +Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0" +Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.MakingOptionsRequired.Demo.RunAsync(System.String[])" + +Exec "./example --help" +Wait +Sleep 1s +Screenshot "Spectre.Docs/Content/assets/cli-required-options-help.svg" diff --git a/Spectre.Docs.Examples/VCR/creating-custom-renderables-tutorial.tape b/Spectre.Docs.Examples/VCR/creating-custom-renderables-tutorial.tape index 13f73ba..876f199 100644 --- a/Spectre.Docs.Examples/VCR/creating-custom-renderables-tutorial.tape +++ b/Spectre.Docs.Examples/VCR/creating-custom-renderables-tutorial.tape @@ -1,5 +1,3 @@ -Output "anim.svg" - Set DisableCursor true Set FontSize 22 Set Theme "one dark" diff --git a/Spectre.Docs.Examples/VCR/rule.tape b/Spectre.Docs.Examples/VCR/rule.tape index 2085291..f967e85 100644 --- a/Spectre.Docs.Examples/VCR/rule.tape +++ b/Spectre.Docs.Examples/VCR/rule.tape @@ -1,5 +1,4 @@ Output "Spectre.Docs/Content/assets/rule.svg" -Output "Spectre.Docs/Content/assets/rule.gif" Set DisableCursor true Set FontSize 22 Set Theme "one dark" diff --git a/Spectre.Docs/Components/Shared/Screenshot.razor b/Spectre.Docs/Components/Shared/Screenshot.razor index b84e7a8..5f44646 100644 --- a/Spectre.Docs/Components/Shared/Screenshot.razor +++ b/Spectre.Docs/Components/Shared/Screenshot.razor @@ -14,7 +14,16 @@ ? $"width: 100%; aspect-ratio: {_aspectRatio};" : "width: 100%;"; } - @Alt + @if (_svgContent != null) + { +
+ @((MarkupString)_svgContent) +
+ } + else + { + @Alt + } @@ -26,22 +35,36 @@ [Parameter] public string Alt { get; set; } = "Screenshot"; + [Parameter] + public bool Embed { get; set; } + private string? _aspectRatio; + private string? _svgContent; protected override void OnParametersSet() { _aspectRatio = null; + _svgContent = null; // Only process SVG files from /assets/ if (!string.IsNullOrEmpty(Src) && Src.StartsWith("/assets/", StringComparison.OrdinalIgnoreCase) && Src.EndsWith(".svg", StringComparison.OrdinalIgnoreCase)) { - _aspectRatio = TryGetAspectRatio(Src); + var contentPath = ResolvePath(Src); + if (contentPath != null && File.Exists(contentPath)) + { + if (Embed) + { + _svgContent = TryReadAndPrepareSvg(contentPath); + } + + _aspectRatio = TryParseAspectRatio(_svgContent, contentPath); + } } } - private string? TryGetAspectRatio(string srcUrl) + private string? ResolvePath(string srcUrl) { try { @@ -54,19 +77,56 @@ relativePath = relativePath.Replace('/', Path.DirectorySeparatorChar); } - var contentPath = Path.Combine(Environment.ContentRootPath, "Content", relativePath); + return Path.Combine(Environment.ContentRootPath, "Content", relativePath); + } + catch + { + return null; + } + } - if (!File.Exists(contentPath)) + private static string? TryReadAndPrepareSvg(string contentPath) + { + try + { + var svg = File.ReadAllText(contentPath); + + // Inject width="100%" so inline SVG scales to fill container. + // viewBox handles aspect ratio preservation automatically. + svg = System.Text.RegularExpressions.Regex.Replace( + svg, + @" 1024 ? fullContent[..1024] : fullContent; + } + else + { + // Read only first 1KB - viewBox should be in opening tag + using var stream = new FileStream(contentPath, FileMode.Open, FileAccess.Read, FileShare.Read); + using var reader = new StreamReader(stream); + var buffer = new char[1024]; + var charsRead = reader.Read(buffer, 0, buffer.Length); + content = new string(buffer, 0, charsRead); } - - // Read only first 1KB - viewBox should be in opening tag - using var stream = new FileStream(contentPath, FileMode.Open, FileAccess.Read, FileShare.Read); - using var reader = new StreamReader(stream); - var buffer = new char[1024]; - var charsRead = reader.Read(buffer, 0, buffer.Length); - var content = new string(buffer, 0, charsRead); // Parse viewBox="minX minY width height" - captures the last two numbers (width and height) var match = System.Text.RegularExpressions.Regex.Match( diff --git a/Spectre.Docs/Content/assets/cli-customizing-help-usage.svg b/Spectre.Docs/Content/assets/cli-customizing-help-usage.svg new file mode 100644 index 0000000..f5d43d1 --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-customizing-help-usage.svg @@ -0,0 +1 @@ +USAGE: myapp <environment> [OPTIONS]EXAMPLES: myapp production myapp staging --force myapp dev --dry-run --verboseARGUMENTS: <environment> Target environment (production, staging, dev)OPTIONS: DEFAULT -h, --help Prints help information -f, --force Skip confirmation prompts -n, --dry-run Show what would be deployed without making changes -v, --verbose Enable verbose output --timeout 300 Deployment timeout in seconds \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-defining-arguments-help.svg b/Spectre.Docs/Content/assets/cli-defining-arguments-help.svg new file mode 100644 index 0000000..cfb7889 --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-defining-arguments-help.svg @@ -0,0 +1 @@ +USAGE: example.dll <source> [destination] [OPTIONS]ARGUMENTS: <source> The source file to copy [destination] The destination path (defaults to current directory)OPTIONS: DEFAULT -h, --help Prints help information -f, --force Overwrite existing files without prompting -b, --buffer-size 64 Buffer size in KB for the copy operation --preserve-timestamps Preserve original file timestamps -v Enable verbose output \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-di-step1.svg b/Spectre.Docs/Content/assets/cli-di-step1.svg new file mode 100644 index 0000000..18a7187 --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-di-step1.svg @@ -0,0 +1 @@ +Hello, Alice!Good day, Alice. \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-di-step2.svg b/Spectre.Docs/Content/assets/cli-di-step2.svg new file mode 100644 index 0000000..2194fa6 --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-di-step2.svg @@ -0,0 +1 @@ +Hello, Alice! \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-di-step3.svg b/Spectre.Docs/Content/assets/cli-di-step3.svg new file mode 100644 index 0000000..70efea4 --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-di-step3.svg @@ -0,0 +1 @@ +Hello, Alice!Good day, Alice.Hey there, Alice! Great to see you! \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-dictionary-lookup-output.svg b/Spectre.Docs/Content/assets/cli-dictionary-lookup-output.svg new file mode 100644 index 0000000..02b966b --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-dictionary-lookup-output.svg @@ -0,0 +1 @@ +Lookups (ILookup<string, string>): env = [dev, staging, prod] region = [us] \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-flag-arguments-help.svg b/Spectre.Docs/Content/assets/cli-flag-arguments-help.svg new file mode 100644 index 0000000..e2285f6 --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-flag-arguments-help.svg @@ -0,0 +1 @@ +USAGE: example.dll [OPTIONS]OPTIONS: DEFAULT -h, --help Prints help information --port [PORT] 3000 The port to listen on (default: 3000 if flag present) --timeout [SECONDS] Connection timeout in seconds -h, --host localhost The host to bind to \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-logging-step1.svg b/Spectre.Docs/Content/assets/cli-logging-step1.svg new file mode 100644 index 0000000..7741417 --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-logging-step1.svg @@ -0,0 +1 @@ +Starting to process: myfile.txtProcessing step 1...Processing step 2...Processing step 3...Processing complete! \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-logging-step2.svg b/Spectre.Docs/Content/assets/cli-logging-step2.svg new file mode 100644 index 0000000..6ed1788 --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-logging-step2.svg @@ -0,0 +1 @@ + Starting to process: myfile.txtinfo: Spectre.Docs.Cli.Examples.DemoApps.Logging.WithLogging.ProcessCommand[0] Processing step 1...info: Spectre.Docs.Cli.Examples.DemoApps.Logging.WithLogging.ProcessCommand[0] Processing step 2...info: Spectre.Docs.Cli.Examples.DemoApps.Logging.WithLogging.ProcessCommand[0] Processing step 3...info: Spectre.Docs.Cli.Examples.DemoApps.Logging.WithLogging.ProcessCommand[0] Processing complete! \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-logging-step3.svg b/Spectre.Docs/Content/assets/cli-logging-step3.svg new file mode 100644 index 0000000..d3485bc --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-logging-step3.svg @@ -0,0 +1 @@ + Detailed step 2 informationinfo: Spectre.Docs.Cli.Examples.DemoApps.Logging.LoggingComplete.ProcessCommand[0] Processing step 2...dbug: Spectre.Docs.Cli.Examples.DemoApps.Logging.LoggingComplete.ProcessCommand[0] Detailed step 3 informationinfo: Spectre.Docs.Cli.Examples.DemoApps.Logging.LoggingComplete.ProcessCommand[0] Processing step 3...warn: Spectre.Docs.Cli.Examples.DemoApps.Logging.LoggingComplete.ProcessCommand[0] This is a warning messageinfo: Spectre.Docs.Cli.Examples.DemoApps.Logging.LoggingComplete.ProcessCommand[0] Processing complete!warn: Spectre.Docs.Cli.Examples.DemoApps.Logging.LoggingComplete.ProcessCommand[0] This is a warning message \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-multi-command-step1.svg b/Spectre.Docs/Content/assets/cli-multi-command-step1.svg new file mode 100644 index 0000000..2eab53d --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-multi-command-step1.svg @@ -0,0 +1 @@ +>> .> ./> ./e> ./ex> ./exa> ./exam> ./examp> ./exampl> ./example> ./example > ./example a> ./example ad> ./example add > ./example add N> ./example add New> ./example add Newt> ./example add Newto> ./example add Newton> ./example add Newtons> ./example add Newtonso> ./example add Newtonsof> ./example add Newtonsoft> ./example add Newtonsoft.> ./example add Newtonsoft.J> ./example add Newtonsoft.Js> ./example add Newtonsoft.Jso> ./example add Newtonsoft.JsonAdded package Newtonsoft.Json>> .> ./> ./e> ./ex> ./exa> ./exam> ./examp> ./exampl> ./example> ./example > ./example l> ./example li> ./example lis> ./example listPackages: (none yet)> \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-multi-command-step2.svg b/Spectre.Docs/Content/assets/cli-multi-command-step2.svg new file mode 100644 index 0000000..b02da59 --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-multi-command-step2.svg @@ -0,0 +1 @@ +>> .> ./> ./e> ./ex> ./exa> ./exam> ./examp> ./exampl> ./example> ./example > ./example a> ./example ad> ./example add> ./example add > ./example add p> ./example add pa> ./example add pac> ./example add pack> ./example add packa> ./example add packag> ./example add package> ./example add package > ./example add package N> ./example add package Ne> ./example add package New> ./example add package Newt> ./example add package Newto> ./example add package Newton> ./example add package Newtons> ./example add package Newtonso> ./example add package Newtonsof> ./example add package Newtonsoft> ./example add package Newtonsoft.> ./example add package Newtonsoft.J> ./example add package Newtonsoft.Js> ./example add package Newtonsoft.Jso> ./example add package Newtonsoft.JsonAdded package Newtonsoft.Json>> .> ./> ./e> ./ex> ./exa> ./exam> ./examp> ./exampl> ./example> ./example > ./example a> ./example ad> ./example add> ./example add > ./example add r> ./example add re> ./example add ref> ./example add refe> ./example add refer> ./example add refere> ./example add referen> ./example add referenc> ./example add reference> ./example add reference > ./example add reference .> ./example add reference ..> ./example add reference ../> ./example add reference ../M> ./example add reference ../My> ./example add reference ../MyL> ./example add reference ../MyLi> ./example add reference ../MyLib> ./example add reference ../MyLib/> ./example add reference ../MyLib/M> ./example add reference ../MyLib/My> ./example add reference ../MyLib/MyL> ./example add reference ../MyLib/MyLi> ./example add reference ../MyLib/MyLib> ./example add reference ../MyLib/MyLib.> ./example add reference ../MyLib/MyLib.c> ./example add reference ../MyLib/MyLib.cs> ./example add reference ../MyLib/MyLib.csp> ./example add reference ../MyLib/MyLib.cspr> ./example add reference ../MyLib/MyLib.cspro> ./example add reference ../MyLib/MyLib.csprojAdded reference to ../MyLib/MyLib.csproj>> .> ./> ./e> ./ex> ./exa> ./exam> ./examp> ./exampl> ./example> ./example > ./example a> ./example ad> ./example add> ./example add > ./example add -> ./example add --> ./example add --h> ./example add --he> ./example add --hel> ./example add --helpUSAGE: example.dll add [OPTIONS] <COMMAND>OPTIONS: -h, --help Prints help informationCOMMANDS: package <name> reference <path> > \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-multi-command-step3.svg b/Spectre.Docs/Content/assets/cli-multi-command-step3.svg new file mode 100644 index 0000000..5918876 --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-multi-command-step3.svg @@ -0,0 +1 @@ +>> .> ./> ./e> ./ex> ./exa> ./exam> ./examp> ./exampl> ./example> ./example > ./example a> ./example ad> ./example add> ./example add > ./example add p> ./example add pa> ./example add pac> ./example add pack> ./example add packa> ./example add packag> ./example add package> ./example add package > ./example add package S> ./example add package Se> ./example add package Ser> ./example add package Seri> ./example add package Seril> ./example add package Serilo> ./example add package Serilog> ./example add package Serilog > ./example add package Serilog -> ./example add package Serilog --> ./example add package Serilog --v> ./example add package Serilog --ve> ./example add package Serilog --ver> ./example add package Serilog --vers> ./example add package Serilog --versi> ./example add package Serilog --versio> ./example add package Serilog --version> ./example add package Serilog --version > ./example add package Serilog --version 3> ./example add package Serilog --version 3.> ./example add package Serilog --version 3.0> ./example add package Serilog --version 3.0.> ./example add package Serilog --version 3.0.0> ./example add package Serilog --version 3.0.0 > ./example add package Serilog --version 3.0.0 -> ./example add package Serilog --version 3.0.0 --> ./example add package Serilog --version 3.0.0 --v> ./example add package Serilog --version 3.0.0 --ve> ./example add package Serilog --version 3.0.0 --ver> ./example add package Serilog --version 3.0.0 --verb> ./example add package Serilog --version 3.0.0 --verbo> ./example add package Serilog --version 3.0.0 --verbos> ./example add package Serilog --version 3.0.0 --verboseSearching for package Serilog...Resolving version 3.0.0...Installing to ./packages...Added package Serilog v3.0.0>> .> ./> ./e> ./ex> ./exa> ./exam> ./examp> ./exampl> ./example> ./example > ./example l> ./example li> ./example lis> ./example list> ./example list > ./example list -> ./example list --> ./example list --v> ./example list --ve> ./example list --ver> ./example list --verb> ./example list --verbo> ./example list --verbos> ./example list --verboseReading project file...Packages: Newtonsoft.Json (13.0.1)References: ../MyLib/MyLib.csproj> \ No newline at end of file diff --git a/Spectre.Docs/Content/assets/cli-required-options-help.svg b/Spectre.Docs/Content/assets/cli-required-options-help.svg new file mode 100644 index 0000000..92bbd2c --- /dev/null +++ b/Spectre.Docs/Content/assets/cli-required-options-help.svg @@ -0,0 +1 @@ +USAGE: example.dll [OPTIONS]OPTIONS: -h, --help Prints help information -e, --environment <TARGET> Target environment. Required -v, --version <VERSION> Version to deploy. Required --dry-run Preview changes without applying them \ No newline at end of file diff --git a/Spectre.Docs/Content/cli/how-to/configuring-commandapp-and-commands.md b/Spectre.Docs/Content/cli/how-to/configuring-commandapp-and-commands.md index 9a62ff3..7cfd5f7 100644 --- a/Spectre.Docs/Content/cli/how-to/configuring-commandapp-and-commands.md +++ b/Spectre.Docs/Content/cli/how-to/configuring-commandapp-and-commands.md @@ -5,11 +5,11 @@ uid: "cli-app-configuration" order: 2050 --- -When building a CLI with multiple commands, use `CommandApp.Configure` to register commands, set up aliases, and customize how your application appears in help output. +When building a CLI with multiple commands, use `CommandApp.Configure` to register commands, define aliases, and customize how your application appears in help output. ## What We're Building -A multi-command CLI with `add`, `remove`, and `list`—each with aliases (like `a` for `add`) and descriptions shown in help: +A multi-command CLI with `add`, `remove`, and `list`—each with descriptions and examples in help, plus aliases so users can type shorter names like `a` for `add`: @@ -21,19 +21,7 @@ Use `AddCommand("name")` to register each command, then chain methods to add M:Spectre.Docs.Cli.Examples.DemoApps.ConfiguringCommandApp.Demo.RunAsync(System.String[]) ``` -This produces help output like: - -``` -USAGE: - myapp [COMMAND] [OPTIONS] - -COMMANDS: - add (a) Add a new item - remove (rm, delete) Remove an item - list (ls) List all items -``` - -Users can invoke commands by name or any alias: `myapp rm file.txt` works the same as `myapp remove file.txt`. +Aliases aren't displayed in help output, but they work as alternative names. Users can invoke commands by name or any alias — `myapp rm file.txt` works the same as `myapp remove file.txt`. ## Configure Global Settings diff --git a/Spectre.Docs/Content/cli/how-to/customizing-help-text-and-usage.md b/Spectre.Docs/Content/cli/how-to/customizing-help-text-and-usage.md index 98f34d4..bf880de 100644 --- a/Spectre.Docs/Content/cli/how-to/customizing-help-text-and-usage.md +++ b/Spectre.Docs/Content/cli/how-to/customizing-help-text-and-usage.md @@ -21,17 +21,9 @@ By default, help text shows the executable name (often ending in `.dll` during d M:Spectre.Docs.Cli.Examples.DemoApps.CustomizingHelpText.Demo.RunAsync(System.String[]) ``` -This produces help output like: +This produces the following help output: -``` -USAGE: - myapp [OPTIONS] - -EXAMPLES: - myapp production - myapp staging --force - myapp dev --dry-run --verbose -``` + ## Customize Help Styling diff --git a/Spectre.Docs/Content/cli/how-to/defining-commands-and-arguments.md b/Spectre.Docs/Content/cli/how-to/defining-commands-and-arguments.md index a46249e..b3b4a9b 100644 --- a/Spectre.Docs/Content/cli/how-to/defining-commands-and-arguments.md +++ b/Spectre.Docs/Content/cli/how-to/defining-commands-and-arguments.md @@ -23,16 +23,7 @@ T:Spectre.Docs.Cli.Examples.DemoApps.DefiningCommandsAndArguments.FileCopyComman This settings class produces the following usage: -``` -USAGE: - myapp [destination] [OPTIONS] - -OPTIONS: - -f, --force Overwrite existing files without prompting - -b, --buffer-size Buffer size in KB for the copy operation [default: 64] - --preserve-timestamps Preserve original file timestamps - -v Enable verbose output -``` + Boolean properties become flags—users include them to set `true`, omit them for `false`. Properties with `[DefaultValue]` show their defaults in help text. diff --git a/Spectre.Docs/Content/cli/how-to/making-options-required.md b/Spectre.Docs/Content/cli/how-to/making-options-required.md index f559bd9..0225157 100644 --- a/Spectre.Docs/Content/cli/how-to/making-options-required.md +++ b/Spectre.Docs/Content/cli/how-to/making-options-required.md @@ -23,12 +23,7 @@ T:Spectre.Docs.Cli.Examples.DemoApps.MakingOptionsRequired.DeployCommand.Setting Help output marks these options clearly: -``` -OPTIONS: - -e, --environment Target environment. Required - -v, --version Version to deploy. Required - --dry-run Preview changes without applying them -``` + ## Validate Across Multiple Options diff --git a/Spectre.Docs/Content/cli/how-to/using-dictionary-and-lookup-options.md b/Spectre.Docs/Content/cli/how-to/using-dictionary-and-lookup-options.md index c0fcc80..aad4b15 100644 --- a/Spectre.Docs/Content/cli/how-to/using-dictionary-and-lookup-options.md +++ b/Spectre.Docs/Content/cli/how-to/using-dictionary-and-lookup-options.md @@ -52,14 +52,7 @@ foreach (var group in settings.Lookups) Output: -``` -env: - - dev - - staging - - prod -region: - - us -``` + ## Use Read-Only Dictionaries diff --git a/Spectre.Docs/Content/cli/how-to/using-flag-arguments.md b/Spectre.Docs/Content/cli/how-to/using-flag-arguments.md index 56890af..b2ebf22 100644 --- a/Spectre.Docs/Content/cli/how-to/using-flag-arguments.md +++ b/Spectre.Docs/Content/cli/how-to/using-flag-arguments.md @@ -23,15 +23,7 @@ T:Spectre.Docs.Cli.Examples.DemoApps.FlagArguments.ServerCommand.Settings This produces the following usage: -``` -USAGE: - myapp [OPTIONS] - -OPTIONS: - --port [PORT] The port to listen on (default: 3000 if flag present) - --timeout [SECONDS] Connection timeout in seconds - -h, --host The host to bind to [default: localhost] -``` + ## Check if a Flag Was Provided diff --git a/Spectre.Docs/Content/cli/tutorials/building-a-multi-command-cli-tool.md b/Spectre.Docs/Content/cli/tutorials/building-a-multi-command-cli-tool.md index 5eb71e6..7e37eff 100644 --- a/Spectre.Docs/Content/cli/tutorials/building-a-multi-command-cli-tool.md +++ b/Spectre.Docs/Content/cli/tutorials/building-a-multi-command-cli-tool.md @@ -53,14 +53,7 @@ return app.Run(args); Run the commands: -```bash -dotnet run -- add Newtonsoft.Json -# Added package Newtonsoft.Json - -dotnet run -- list -# Packages: -# (none yet) -``` + Both commands work. Try running `dotnet run -- --help` to see the auto-generated help listing both commands. The CLI knows about `add` and `list` without any extra configuration. @@ -98,16 +91,7 @@ return app.Run(args); Now the commands are organized hierarchically: -```bash -dotnet run -- add package Newtonsoft.Json -# Added package Newtonsoft.Json - -dotnet run -- add reference ../MyLib/MyLib.csproj -# Added reference to ../MyLib/MyLib.csproj - -dotnet run -- add --help -# Shows 'package' and 'reference' as subcommands -``` + The `add` branch groups related commands together. Users can run `add --help` to discover what's available. @@ -146,20 +130,7 @@ return app.Run(args); The `--verbose` flag now works across all commands: -```bash -dotnet run -- add package Serilog --version 3.0.0 --verbose -# Searching for package Serilog... -# Resolving version 3.0.0... -# Installing to ./packages... -# Added package Serilog v3.0.0 - -dotnet run -- list --verbose -# Reading project file... -# Packages: -# Newtonsoft.Json (13.0.1) -# References: -# ../MyLib/MyLib.csproj -``` + Settings inheritance keeps your code DRY. Define common options once, use them everywhere. diff --git a/Spectre.Docs/Content/cli/tutorials/dependency-injection-in-cli-apps.md b/Spectre.Docs/Content/cli/tutorials/dependency-injection-in-cli-apps.md index d23d1b3..36fcf7a 100644 --- a/Spectre.Docs/Content/cli/tutorials/dependency-injection-in-cli-apps.md +++ b/Spectre.Docs/Content/cli/tutorials/dependency-injection-in-cli-apps.md @@ -52,13 +52,7 @@ return app.Run(args); Run the application: -```bash -dotnet run -- Alice -# Hello, Alice! - -dotnet run -- Alice --formal -# Good day, Alice. -``` + This works, but the greeting logic is embedded in the command. If we wanted to test this command, we'd have no way to substitute different greeting behavior. Let's fix that. @@ -105,10 +99,7 @@ return app.Run(args); Run it again: -```bash -dotnet run -- Alice -# Hello, Alice! -``` + The output looks the same, but now the greeting logic is in a separate service. The framework automatically injects `IGreetingService` into the command's constructor. @@ -179,16 +170,7 @@ The `TypeRegistrar` and `TypeResolver` stay the same - they're reusable infrastr Try all the greeting styles using the `--style` option: -```bash -dotnet run -- Alice -# Hello, Alice! - -dotnet run -- Alice --style Formal -# Good day, Alice. - -dotnet run -- Alice --style Enthusiastic -# Hey there, Alice! Great to see you! -``` + This pattern has several advantages: diff --git a/Spectre.Docs/Content/cli/tutorials/logging-in-cli-apps.md b/Spectre.Docs/Content/cli/tutorials/logging-in-cli-apps.md index b0f3832..5239376 100644 --- a/Spectre.Docs/Content/cli/tutorials/logging-in-cli-apps.md +++ b/Spectre.Docs/Content/cli/tutorials/logging-in-cli-apps.md @@ -51,14 +51,7 @@ return app.Run(args); Run the application: -```bash -dotnet run -- myfile.txt -# Starting to process: myfile.txt -# Processing step 1... -# Processing step 2... -# Processing step 3... -# Processing complete! -``` + This works, but we're using `Console.WriteLine` directly. We have no way to control verbosity or integrate with logging infrastructure. @@ -107,13 +100,7 @@ return app.Run(args); Run it again: -```bash -dotnet run -- myfile.txt -# info: ProcessCommand[0] -# Starting to process: myfile.txt -# info: ProcessCommand[0] -# Processing step 1... -``` + Now we have structured logging with category names and log levels. But the level is hard-coded. Let's make it configurable. @@ -179,17 +166,7 @@ The `TypeRegistrar` and `TypeResolver` stay the same as Step 2. Try different log levels: -```bash -dotnet run -- myfile.txt -# info: Processing step 1... - -dotnet run -- myfile.txt --logLevel Debug -# dbug: Detailed step 1 information -# info: Processing step 1... - -dotnet run -- myfile.txt --logLevel Warning -# warn: This is a warning message -``` + This pattern has several advantages: diff --git a/Spectre.Docs/appsettings.Development.json b/Spectre.Docs/appsettings.Development.json index bf8f455..54c9788 100644 --- a/Spectre.Docs/appsettings.Development.json +++ b/Spectre.Docs/appsettings.Development.json @@ -4,7 +4,7 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning", "System.Net.Http.HttpClient": "Warning", - "MyLittleContentEngine": "Trace" + "MyLittleContentEngine": "Warning" }, "Console": { "FormatterName": "Simple",