mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-01 01:25:27 +08:00 
			
		
		
		
	Make HelpProvider colors configurable (#1408)
This commit is contained in:
		| @@ -15,6 +15,34 @@ The help is also context aware and tailored depending on what has been specified | ||||
|  | ||||
| `HelpProvider` is the `Spectre.Console` class responsible for determining context and preparing the help text to write to the console. It is an implementation of the public interface `IHelpProvider`. | ||||
|  | ||||
| ## Styling the help text | ||||
|  | ||||
| Basic styling is applied to the generated help text by default, however this is configurable. | ||||
|  | ||||
| `HelpProviderStyle` is the `Spectre.Console` class that holds the style information for the help text. | ||||
|  | ||||
| The default theme shipped with Spectre.Console is provided by a factory method, `HelpProviderStyle.Default`. | ||||
|  | ||||
| However, you can explicitly set a custom theme when configuring a CommandApp, for example: | ||||
|  | ||||
| ```csharp | ||||
| config.Settings.HelpProviderStyles = new HelpProviderStyle() | ||||
| { | ||||
|     Description = new DescriptionStyle() | ||||
|     { | ||||
|         Header = "bold", | ||||
|     }, | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| Removing all styling from help text is also possible, a good choice for ensuring maximum accessibility. This is configured by clearing the style provider entirely: | ||||
|  | ||||
| ```csharp | ||||
| config.Settings.HelpProviderStyles = null; | ||||
| ``` | ||||
|  | ||||
| See [Markup](../markup) for information about the use of markup in Spectre.Console, and [Styles](xref:styles) for a listing of supported styles. | ||||
|  | ||||
| ## Custom help providers | ||||
|  | ||||
| Whilst it shouldn't be common place to implement your own help provider, it is however possible.  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using Spectre.Console.Cli; | ||||
| using Spectre.Console.Cli.Help; | ||||
|  | ||||
| namespace Help; | ||||
|  | ||||
| @@ -12,6 +13,9 @@ public static class Program | ||||
|         { | ||||
|             // Register the custom help provider | ||||
|             config.SetHelpProvider(new CustomHelpProvider(config.Settings)); | ||||
|  | ||||
|             // Render an unstyled help text for maximum accessibility | ||||
|             config.Settings.HelpProviderStyles = null; | ||||
|         }); | ||||
|  | ||||
|         return app.Run(args); | ||||
|   | ||||
| @@ -1,5 +1,3 @@ | ||||
| using Spectre.Console.Cli.Resources; | ||||
|  | ||||
| namespace Spectre.Console.Cli.Help; | ||||
|  | ||||
| /// <summary> | ||||
| @@ -10,7 +8,8 @@ namespace Spectre.Console.Cli.Help; | ||||
| /// </remarks> | ||||
| public class HelpProvider : IHelpProvider | ||||
| { | ||||
|     private HelpProviderResources resources; | ||||
|     private readonly HelpProviderResources resources; | ||||
|     private readonly HelpProviderStyle? helpStyles; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets a value indicating how many examples from direct children to show in the help text. | ||||
| @@ -27,6 +26,14 @@ public class HelpProvider : IHelpProvider | ||||
|     /// </summary> | ||||
|     protected virtual bool TrimTrailingPeriod { get; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets a value indicating whether to emit the markup styles, inline, when rendering the help text. | ||||
|     /// </summary> | ||||
|     /// <remarks> | ||||
|     /// Useful for unit testing different styling of the same help text. | ||||
|     /// </remarks> | ||||
|     protected virtual bool RenderMarkupInline { get; } = false; | ||||
|  | ||||
|     private sealed class HelpArgument | ||||
|     { | ||||
|         public string Name { get; } | ||||
| @@ -94,6 +101,11 @@ public class HelpProvider : IHelpProvider | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     internal Composer NewComposer() | ||||
|     { | ||||
|         return new Composer(RenderMarkupInline); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Initializes a new instance of the <see cref="HelpProvider"/> class. | ||||
|     /// </summary> | ||||
| @@ -104,6 +116,10 @@ public class HelpProvider : IHelpProvider | ||||
|         this.MaximumIndirectExamples = settings.MaximumIndirectExamples; | ||||
|         this.TrimTrailingPeriod = settings.TrimTrailingPeriod; | ||||
|  | ||||
|         // Don't provide a default style if HelpProviderStyles is null, | ||||
|         // as the user will have explicitly done this to output unstyled help text | ||||
|         this.helpStyles = settings.HelpProviderStyles; | ||||
|  | ||||
|         resources = new HelpProviderResources(settings.Culture); | ||||
|     } | ||||
|  | ||||
| @@ -148,8 +164,8 @@ public class HelpProvider : IHelpProvider | ||||
|             yield break; | ||||
|         } | ||||
|  | ||||
|         var composer = new Composer(); | ||||
|         composer.Style("yellow", $"{resources.Description}:").LineBreak(); | ||||
|         var composer = NewComposer(); | ||||
|         composer.Style(helpStyles?.Description?.Header ?? Style.Plain, $"{resources.Description}:").LineBreak(); | ||||
|         composer.Text(command.Description).LineBreak(); | ||||
|         yield return composer.LineBreak(); | ||||
|     } | ||||
| @@ -162,16 +178,16 @@ public class HelpProvider : IHelpProvider | ||||
|     /// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns> | ||||
|     public virtual IEnumerable<IRenderable> GetUsage(ICommandModel model, ICommandInfo? command) | ||||
|     { | ||||
|         var composer = new Composer(); | ||||
|         composer.Style("yellow", $"{resources.Usage}:").LineBreak(); | ||||
|         var composer = NewComposer(); | ||||
|         composer.Style(helpStyles?.Usage?.Header ?? Style.Plain, $"{resources.Usage}:").LineBreak(); | ||||
|         composer.Tab().Text(model.ApplicationName); | ||||
|  | ||||
|         var parameters = new List<string>(); | ||||
|         var parameters = new List<Composer>(); | ||||
|  | ||||
|         if (command == null) | ||||
|         { | ||||
|             parameters.Add($"[grey][[{resources.Options}]][/]"); | ||||
|             parameters.Add($"[aqua]<{resources.Command}>[/]"); | ||||
|             parameters.Add(NewComposer().Style(helpStyles?.Usage?.Options ?? Style.Plain, $"[{resources.Options}]")); | ||||
|             parameters.Add(NewComposer().Style(helpStyles?.Usage?.Command ?? Style.Plain, $"<{resources.Command}>")); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
| @@ -183,11 +199,11 @@ public class HelpProvider : IHelpProvider | ||||
|                 { | ||||
|                     if (isCurrent) | ||||
|                     { | ||||
|                         parameters.Add($"[underline]{current.Name.EscapeMarkup()}[/]"); | ||||
|                         parameters.Add(NewComposer().Style(helpStyles?.Usage?.CurrentCommand ?? Style.Plain, $"{current.Name}")); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         parameters.Add($"{current.Name.EscapeMarkup()}"); | ||||
|                         parameters.Add(NewComposer().Text(current.Name)); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
| @@ -198,7 +214,7 @@ public class HelpProvider : IHelpProvider | ||||
|                         foreach (var argument in current.Parameters.OfType<ICommandArgument>() | ||||
|                             .Where(a => a.Required).OrderBy(a => a.Position).ToArray()) | ||||
|                         { | ||||
|                             parameters.Add($"[aqua]<{argument.Value.EscapeMarkup()}>[/]"); | ||||
|                             parameters.Add(NewComposer().Style(helpStyles?.Usage?.RequiredArgument ?? Style.Plain, $"<{argument.Value}>")); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
| @@ -207,27 +223,27 @@ public class HelpProvider : IHelpProvider | ||||
|                     { | ||||
|                         foreach (var optionalArgument in optionalArguments) | ||||
|                         { | ||||
|                             parameters.Add($"[silver][[{optionalArgument.Value.EscapeMarkup()}]][/]"); | ||||
|                             parameters.Add(NewComposer().Style(helpStyles?.Usage?.OptionalArgument ?? Style.Plain, $"[{optionalArgument.Value}]")); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (isCurrent) | ||||
|                 { | ||||
|                     parameters.Add($"[grey][[{resources.Options}]][/]"); | ||||
|                     parameters.Add(NewComposer().Style(helpStyles?.Usage?.Options ?? Style.Plain, $"[{resources.Options}]")); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (command.IsBranch && command.DefaultCommand == null) | ||||
|             { | ||||
|                 // The user must specify the command | ||||
|                 parameters.Add($"[aqua]<{resources.Command}>[/]"); | ||||
|                 parameters.Add(NewComposer().Style(helpStyles?.Usage?.Command ?? Style.Plain, $"<{resources.Command}>")); | ||||
|             } | ||||
|             else if (command.IsBranch && command.DefaultCommand != null && command.Commands.Count > 0) | ||||
|             { | ||||
|                 // We are on a branch with a default command | ||||
|                 // The user can optionally specify the command | ||||
|                 parameters.Add($"[aqua][[{resources.Command}]][/]"); | ||||
|                 parameters.Add(NewComposer().Style(helpStyles?.Usage?.Command ?? Style.Plain, $"[{resources.Command}]")); | ||||
|             } | ||||
|             else if (command.IsDefaultCommand) | ||||
|             { | ||||
| @@ -237,7 +253,7 @@ public class HelpProvider : IHelpProvider | ||||
|                 { | ||||
|                     // Commands other than the default are present | ||||
|                     // So make these optional in the usage statement | ||||
|                     parameters.Add($"[aqua][[{resources.Command}]][/]"); | ||||
|                     parameters.Add(NewComposer().Style(helpStyles?.Usage?.Command ?? Style.Plain, $"[{resources.Command}]")); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -245,10 +261,7 @@ public class HelpProvider : IHelpProvider | ||||
|         composer.Join(" ", parameters); | ||||
|         composer.LineBreak(); | ||||
|  | ||||
|         return new[] | ||||
|         { | ||||
|             composer, | ||||
|         }; | ||||
|         return new[] { composer }; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
| @@ -302,14 +315,14 @@ public class HelpProvider : IHelpProvider | ||||
|  | ||||
|         if (Math.Min(maxExamples, examples.Count) > 0) | ||||
|         { | ||||
|             var composer = new Composer(); | ||||
|             var composer = NewComposer(); | ||||
|             composer.LineBreak(); | ||||
|             composer.Style("yellow", $"{resources.Examples}:").LineBreak(); | ||||
|             composer.Style(helpStyles?.Examples?.Header ?? Style.Plain, $"{resources.Examples}:").LineBreak(); | ||||
|  | ||||
|             for (var index = 0; index < Math.Min(maxExamples, examples.Count); index++) | ||||
|             { | ||||
|                 var args = string.Join(" ", examples[index]); | ||||
|                 composer.Tab().Text(model.ApplicationName).Space().Style("grey", args); | ||||
|                 composer.Tab().Text(model.ApplicationName).Space().Style(helpStyles?.Examples?.Arguments ?? Style.Plain, args); | ||||
|                 composer.LineBreak(); | ||||
|             } | ||||
|  | ||||
| @@ -334,11 +347,9 @@ public class HelpProvider : IHelpProvider | ||||
|         } | ||||
|  | ||||
|         var result = new List<IRenderable> | ||||
|             { | ||||
|                 new Markup(Environment.NewLine), | ||||
|                 new Markup($"[yellow]{resources.Arguments}:[/]"), | ||||
|                 new Markup(Environment.NewLine), | ||||
|             }; | ||||
|         { | ||||
|             NewComposer().LineBreak().Style(helpStyles?.Arguments?.Header ?? Style.Plain, $"{resources.Arguments}:").LineBreak(), | ||||
|         }; | ||||
|  | ||||
|         var grid = new Grid(); | ||||
|         grid.AddColumn(new GridColumn { Padding = new Padding(4, 4), NoWrap = true }); | ||||
| @@ -347,15 +358,15 @@ public class HelpProvider : IHelpProvider | ||||
|         foreach (var argument in arguments.Where(x => x.Required).OrderBy(x => x.Position)) | ||||
|         { | ||||
|             grid.AddRow( | ||||
|                 $"[silver]<{argument.Name.EscapeMarkup()}>[/]", | ||||
|                 argument.Description?.TrimEnd('.') ?? " "); | ||||
|                 NewComposer().Style(helpStyles?.Arguments?.RequiredArgument ?? Style.Plain, $"<{argument.Name}>"), | ||||
|                 NewComposer().Text(argument.Description?.TrimEnd('.') ?? " ")); | ||||
|         } | ||||
|  | ||||
|         foreach (var argument in arguments.Where(x => !x.Required).OrderBy(x => x.Position)) | ||||
|         { | ||||
|             grid.AddRow( | ||||
|                 $"[grey][[{argument.Name.EscapeMarkup()}]][/]", | ||||
|                 argument.Description?.TrimEnd('.') ?? " "); | ||||
|                 NewComposer().Style(helpStyles?.Arguments?.OptionalArgument ?? Style.Plain, $"[{argument.Name}]"), | ||||
|                 NewComposer().Text(argument.Description?.TrimEnd('.') ?? " ")); | ||||
|         } | ||||
|  | ||||
|         result.Add(grid); | ||||
| @@ -379,11 +390,9 @@ public class HelpProvider : IHelpProvider | ||||
|         } | ||||
|  | ||||
|         var result = new List<IRenderable> | ||||
|             { | ||||
|                 new Markup(Environment.NewLine), | ||||
|                 new Markup($"[yellow]{resources.Options}:[/]"), | ||||
|                 new Markup(Environment.NewLine), | ||||
|             }; | ||||
|         { | ||||
|             NewComposer().LineBreak().Style(helpStyles?.Options?.Header ?? Style.Plain, $"{resources.Options}:").LineBreak(), | ||||
|         }; | ||||
|  | ||||
|         var helpOptions = parameters.ToArray(); | ||||
|         var defaultValueColumn = ShowOptionDefaultValues && helpOptions.Any(e => e.DefaultValue != null); | ||||
| @@ -397,71 +406,24 @@ public class HelpProvider : IHelpProvider | ||||
|  | ||||
|         grid.AddColumn(new GridColumn { Padding = new Padding(0, 0) }); | ||||
|  | ||||
|         static string GetOptionParts(HelpOption option) | ||||
|         { | ||||
|             var builder = new StringBuilder(); | ||||
|             if (option.Short != null) | ||||
|             { | ||||
|                 builder.Append('-').Append(option.Short.EscapeMarkup()); | ||||
|                 if (option.Long != null) | ||||
|                 { | ||||
|                     builder.Append(", "); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 builder.Append("  "); | ||||
|                 if (option.Long != null) | ||||
|                 { | ||||
|                     builder.Append("  "); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (option.Long != null) | ||||
|             { | ||||
|                 builder.Append("--").Append(option.Long.EscapeMarkup()); | ||||
|             } | ||||
|  | ||||
|             if (option.Value != null) | ||||
|             { | ||||
|                 builder.Append(' '); | ||||
|                 if (option.ValueIsOptional ?? false) | ||||
|                 { | ||||
|                     builder.Append("[grey][[").Append(option.Value.EscapeMarkup()).Append("]][/]"); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     builder.Append("[silver]<").Append(option.Value.EscapeMarkup()).Append(">[/]"); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return builder.ToString(); | ||||
|         } | ||||
|  | ||||
|         if (defaultValueColumn) | ||||
|         { | ||||
|             grid.AddRow(" ", $"[lime]{resources.Default}[/]", " "); | ||||
|             grid.AddRow( | ||||
|                 NewComposer().Space(), | ||||
|                 NewComposer().Style(helpStyles?.Options?.DefaultValueHeader ?? Style.Plain, resources.Default), | ||||
|                 NewComposer().Space()); | ||||
|         } | ||||
|  | ||||
|         foreach (var option in helpOptions) | ||||
|         { | ||||
|             var columns = new List<string> { GetOptionParts(option) }; | ||||
|             var columns = new List<IRenderable>() { GetOptionParts(option) }; | ||||
|  | ||||
|             if (defaultValueColumn) | ||||
|             { | ||||
|                 static string Bold(object obj) => $"[bold]{obj.ToString().EscapeMarkup()}[/]"; | ||||
|  | ||||
|                 var defaultValue = option.DefaultValue switch | ||||
|                 { | ||||
|                     null => " ", | ||||
|                     "" => " ", | ||||
|                     Array { Length: 0 } => " ", | ||||
|                     Array array => string.Join(", ", array.Cast<object>().Select(Bold)), | ||||
|                     _ => Bold(option.DefaultValue), | ||||
|                 }; | ||||
|                 columns.Add(defaultValue); | ||||
|                 columns.Add(GetOptionDefaultValue(option.DefaultValue)); | ||||
|             } | ||||
|  | ||||
|             columns.Add(option.Description?.TrimEnd('.') ?? " "); | ||||
|             columns.Add(NewComposer().Text(option.Description?.TrimEnd('.') ?? " ")); | ||||
|  | ||||
|             grid.AddRow(columns.ToArray()); | ||||
|         } | ||||
| @@ -471,6 +433,60 @@ public class HelpProvider : IHelpProvider | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     private IRenderable GetOptionParts(HelpOption option) | ||||
|     { | ||||
|         var composer = NewComposer(); | ||||
|  | ||||
|         if (option.Short != null) | ||||
|         { | ||||
|             composer.Text("-").Text(option.Short); | ||||
|             if (option.Long != null) | ||||
|             { | ||||
|                 composer.Text(", "); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             composer.Text("  "); | ||||
|             if (option.Long != null) | ||||
|             { | ||||
|                 composer.Text("  "); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (option.Long != null) | ||||
|         { | ||||
|             composer.Text("--").Text(option.Long); | ||||
|         } | ||||
|  | ||||
|         if (option.Value != null) | ||||
|         { | ||||
|             composer.Text(" "); | ||||
|             if (option.ValueIsOptional ?? false) | ||||
|             { | ||||
|                 composer.Style(helpStyles?.Options?.OptionalOption ?? Style.Plain, $"[{option.Value}]"); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 composer.Style(helpStyles?.Options?.RequiredOption ?? Style.Plain, $"<{option.Value}>"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return composer; | ||||
|     } | ||||
|  | ||||
|     private IRenderable GetOptionDefaultValue(object? defaultValue) | ||||
|     { | ||||
|         return defaultValue switch | ||||
|         { | ||||
|             null => NewComposer().Text(" "), | ||||
|             "" => NewComposer().Text(" "), | ||||
|             Array { Length: 0 } => NewComposer().Text(" "), | ||||
|             Array array => NewComposer().Join(", ", array.Cast<object>().Select(o => NewComposer().Style(helpStyles?.Options?.DefaultValue ?? Style.Plain, o.ToString() ?? string.Empty))), | ||||
|             _ => NewComposer().Style(helpStyles?.Options?.DefaultValue ?? Style.Plain, defaultValue?.ToString() ?? string.Empty), | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets the commands section of the help information. | ||||
|     /// </summary> | ||||
| @@ -491,11 +507,9 @@ public class HelpProvider : IHelpProvider | ||||
|         } | ||||
|  | ||||
|         var result = new List<IRenderable> | ||||
|             { | ||||
|                 new Markup(Environment.NewLine), | ||||
|                 new Markup($"[yellow]{resources.Commands}:[/]"), | ||||
|                 new Markup(Environment.NewLine), | ||||
|             }; | ||||
|         { | ||||
|             NewComposer().LineBreak().Style(helpStyles?.Commands?.Header ?? Style.Plain, $"{resources.Commands}:").LineBreak(), | ||||
|         }; | ||||
|  | ||||
|         var grid = new Grid(); | ||||
|         grid.AddColumn(new GridColumn { Padding = new Padding(4, 4), NoWrap = true }); | ||||
| @@ -503,27 +517,27 @@ public class HelpProvider : IHelpProvider | ||||
|  | ||||
|         foreach (var child in commands) | ||||
|         { | ||||
|             var arguments = new Composer(); | ||||
|             arguments.Style("silver", child.Name.EscapeMarkup()); | ||||
|             var arguments = NewComposer(); | ||||
|             arguments.Style(helpStyles?.Commands?.ChildCommand ?? Style.Plain, child.Name); | ||||
|             arguments.Space(); | ||||
|  | ||||
|             foreach (var argument in HelpArgument.Get(child).Where(a => a.Required)) | ||||
|             { | ||||
|                 arguments.Style("silver", $"<{argument.Name.EscapeMarkup()}>"); | ||||
|                 arguments.Style(helpStyles?.Commands?.RequiredArgument ?? Style.Plain, $"<{argument.Name}>"); | ||||
|                 arguments.Space(); | ||||
|             } | ||||
|  | ||||
|             if (TrimTrailingPeriod) | ||||
|             { | ||||
|                 grid.AddRow( | ||||
|                     arguments.ToString().TrimEnd(), | ||||
|                     child.Description?.TrimEnd('.') ?? " "); | ||||
|                     NewComposer().Text(arguments.ToString().TrimEnd()), | ||||
|                     NewComposer().Text(child.Description?.TrimEnd('.') ?? " ")); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 grid.AddRow( | ||||
|                     arguments.ToString().TrimEnd(), | ||||
|                     child.Description ?? " "); | ||||
|                     NewComposer().Text(arguments.ToString().TrimEnd()), | ||||
|                     NewComposer().Text(child.Description ?? " ")); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
							
								
								
									
										219
									
								
								src/Spectre.Console.Cli/Help/HelpProviderStyles.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								src/Spectre.Console.Cli/Help/HelpProviderStyles.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,219 @@ | ||||
| namespace Spectre.Console.Cli.Help; | ||||
|  | ||||
| /// <summary> | ||||
| /// Styles for the HelpProvider to use when rendering help text. | ||||
| /// </summary> | ||||
| public sealed class HelpProviderStyle | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for describing the purpose or details of a command. | ||||
|     /// </summary> | ||||
|     public DescriptionStyle? Description { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for specifying the usage format of a command. | ||||
|     /// </summary> | ||||
|     public UsageStyle? Usage { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for providing examples of command usage. | ||||
|     /// </summary> | ||||
|     public ExampleStyle? Examples { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for specifying arguments in a command. | ||||
|     /// </summary> | ||||
|     public ArgumentStyle? Arguments { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for specifying options or flags in a command. | ||||
|     /// </summary> | ||||
|     public OptionStyle? Options { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for specifying subcommands or nested commands. | ||||
|     /// </summary> | ||||
|     public CommandStyle? Commands { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets the default HelpProvider styles. | ||||
|     /// </summary> | ||||
|     public static HelpProviderStyle Default { get; } = | ||||
|         new HelpProviderStyle() | ||||
|         { | ||||
|             Description = new DescriptionStyle() | ||||
|             { | ||||
|                 Header = "yellow", | ||||
|             }, | ||||
|             Usage = new UsageStyle() | ||||
|             { | ||||
|                 Header = "yellow", | ||||
|                 CurrentCommand = "underline", | ||||
|                 Command = "aqua", | ||||
|                 Options = "grey", | ||||
|                 RequiredArgument = "aqua", | ||||
|                 OptionalArgument = "silver", | ||||
|             }, | ||||
|             Examples = new ExampleStyle() | ||||
|             { | ||||
|                 Header = "yellow", | ||||
|                 Arguments = "grey", | ||||
|             }, | ||||
|             Arguments = new ArgumentStyle() | ||||
|             { | ||||
|                 Header = "yellow", | ||||
|                 RequiredArgument = "silver", | ||||
|                 OptionalArgument = "silver", | ||||
|             }, | ||||
|             Commands = new CommandStyle() | ||||
|             { | ||||
|                 Header = "yellow", | ||||
|                 ChildCommand = "silver", | ||||
|                 RequiredArgument = "silver", | ||||
|             }, | ||||
|             Options = new OptionStyle() | ||||
|             { | ||||
|                 Header = "yellow", | ||||
|                 DefaultValueHeader = "lime", | ||||
|                 DefaultValue = "bold", | ||||
|                 RequiredOption = "silver", | ||||
|                 OptionalOption = "grey", | ||||
|             }, | ||||
|         }; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Defines styles for describing the purpose or details of a command. | ||||
| /// </summary> | ||||
| public sealed class DescriptionStyle | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for the header in the description. | ||||
|     /// </summary> | ||||
|     public Style? Header { get; set; } | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Defines styles for specifying the usage format of a command. | ||||
| /// </summary> | ||||
| public sealed class UsageStyle | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for the header in the usage. | ||||
|     /// </summary> | ||||
|     public Style? Header { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for the current command in the usage. | ||||
|     /// </summary> | ||||
|     public Style? CurrentCommand { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for general commands in the usage. | ||||
|     /// </summary> | ||||
|     public Style? Command { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for options in the usage. | ||||
|     /// </summary> | ||||
|     public Style? Options { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for required arguments in the usage. | ||||
|     /// </summary> | ||||
|     public Style? RequiredArgument { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for optional arguments in the usage. | ||||
|     /// </summary> | ||||
|     public Style? OptionalArgument { get; set; } | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Defines styles for providing examples of command usage. | ||||
| /// </summary> | ||||
| public sealed class ExampleStyle | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for the header in the examples. | ||||
|     /// </summary> | ||||
|     public Style? Header { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for arguments in the examples. | ||||
|     /// </summary> | ||||
|     public Style? Arguments { get; set; } | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Defines styles for specifying arguments in a command. | ||||
| /// </summary> | ||||
| public sealed class ArgumentStyle | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for the header in the arguments. | ||||
|     /// </summary> | ||||
|     public Style? Header { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for required arguments. | ||||
|     /// </summary> | ||||
|     public Style? RequiredArgument { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for optional arguments. | ||||
|     /// </summary> | ||||
|     public Style? OptionalArgument { get; set; } | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Defines styles for specifying subcommands or nested commands. | ||||
| /// </summary> | ||||
| public sealed class CommandStyle | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for the header in the command section. | ||||
|     /// </summary> | ||||
|     public Style? Header { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for child commands in the command section. | ||||
|     /// </summary> | ||||
|     public Style? ChildCommand { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for required arguments in the command section. | ||||
|     /// </summary> | ||||
|     public Style? RequiredArgument { get; set; } | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Defines styles for specifying options or flags in a command. | ||||
| /// </summary> | ||||
| public sealed class OptionStyle | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for the header in the options. | ||||
|     /// </summary> | ||||
|     public Style? Header { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for the header of default values in the options. | ||||
|     /// </summary> | ||||
|     public Style? DefaultValueHeader { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for default values in the options. | ||||
|     /// </summary> | ||||
|     public Style? DefaultValue { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for required options. | ||||
|     /// </summary> | ||||
|     public Style? RequiredOption { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the style for optional options. | ||||
|     /// </summary> | ||||
|     public Style? OptionalOption { get; set; } | ||||
| } | ||||
| @@ -41,6 +41,11 @@ public interface ICommandAppSettings | ||||
|     /// </summary> | ||||
|     bool TrimTrailingPeriod { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the styles to used when rendering the help text. | ||||
|     /// </summary> | ||||
|     HelpProviderStyle? HelpProviderStyles { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the <see cref="IAnsiConsole"/>. | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -4,22 +4,43 @@ internal sealed class Composer : IRenderable | ||||
| { | ||||
|     private readonly StringBuilder _content; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Whether to emit the markup styles, inline, when rendering the content. | ||||
|     /// </summary> | ||||
|     private readonly bool _renderMarkup = false; | ||||
|  | ||||
|     public Composer() | ||||
|     { | ||||
|         _content = new StringBuilder(); | ||||
|     } | ||||
|  | ||||
|     public Composer(bool renderMarkup) | ||||
|         : this() | ||||
|     { | ||||
|         _renderMarkup = renderMarkup; | ||||
|     } | ||||
|  | ||||
|     public Composer Text(string text) | ||||
|     { | ||||
|         _content.Append(text); | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
|     public Composer Style(Style style, string text) | ||||
|     { | ||||
|         _content.Append('[').Append(style.ToMarkup()).Append(']'); | ||||
|         _content.Append(text.EscapeMarkup()); | ||||
|         _content.Append("[/]"); | ||||
|  | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
|     public Composer Style(string style, string text) | ||||
|     { | ||||
|         _content.Append('[').Append(style).Append(']'); | ||||
|         _content.Append(text.EscapeMarkup()); | ||||
|         _content.Append("[/]"); | ||||
|  | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
| @@ -28,6 +49,7 @@ internal sealed class Composer : IRenderable | ||||
|         _content.Append('[').Append(style).Append(']'); | ||||
|         action(this); | ||||
|         _content.Append("[/]"); | ||||
|  | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
| @@ -72,12 +94,19 @@ internal sealed class Composer : IRenderable | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
|     public Composer Join(string separator, IEnumerable<string> composers) | ||||
|     public Composer Join(string separator, IEnumerable<Composer> composers) | ||||
|     { | ||||
|         if (composers != null) | ||||
|         { | ||||
|             Space(); | ||||
|             Text(string.Join(separator, composers)); | ||||
|             foreach (var composer in composers) | ||||
|             { | ||||
|                 if (_content.ToString().Length > 0) | ||||
|                 { | ||||
|                     Text(separator); | ||||
|                 } | ||||
|  | ||||
|                 Text(composer.ToString()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return this; | ||||
| @@ -85,12 +114,26 @@ internal sealed class Composer : IRenderable | ||||
|  | ||||
|     public Measurement Measure(RenderOptions options, int maxWidth) | ||||
|     { | ||||
|         return ((IRenderable)new Markup(_content.ToString())).Measure(options, maxWidth); | ||||
|         if (_renderMarkup) | ||||
|         { | ||||
|             return ((IRenderable)new Paragraph(_content.ToString())).Measure(options, maxWidth); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return ((IRenderable)new Markup(_content.ToString())).Measure(options, maxWidth); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public IEnumerable<Segment> Render(RenderOptions options, int maxWidth) | ||||
|     { | ||||
|         return ((IRenderable)new Markup(_content.ToString())).Render(options, maxWidth); | ||||
|         if (_renderMarkup) | ||||
|         { | ||||
|             return ((IRenderable)new Paragraph(_content.ToString())).Render(options, maxWidth); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return ((IRenderable)new Markup(_content.ToString())).Render(options, maxWidth); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public override string ToString() | ||||
|   | ||||
| @@ -14,9 +14,10 @@ internal sealed class CommandAppSettings : ICommandAppSettings | ||||
|     public CaseSensitivity CaseSensitivity { get; set; } | ||||
|     public bool PropagateExceptions { get; set; } | ||||
|     public bool ValidateExamples { get; set; } | ||||
|     public bool TrimTrailingPeriod { get; set; } = true; | ||||
|     public bool TrimTrailingPeriod { get; set; } | ||||
|     public HelpProviderStyle? HelpProviderStyles { get; set; } | ||||
|     public bool StrictParsing { get; set; } | ||||
|     public bool ConvertFlagsToRemainingArguments { get; set; } = false; | ||||
|     public bool ConvertFlagsToRemainingArguments { get; set; } | ||||
|  | ||||
|     public ParsingMode ParsingMode => | ||||
|         StrictParsing ? ParsingMode.Strict : ParsingMode.Relaxed; | ||||
| @@ -29,6 +30,9 @@ internal sealed class CommandAppSettings : ICommandAppSettings | ||||
|         CaseSensitivity = CaseSensitivity.All; | ||||
|         ShowOptionDefaultValues = true; | ||||
|         MaximumIndirectExamples = 5; | ||||
|         TrimTrailingPeriod = true; | ||||
|         HelpProviderStyles = HelpProviderStyle.Default; | ||||
|         ConvertFlagsToRemainingArguments = false; | ||||
|     } | ||||
|  | ||||
|     public bool IsTrue(Func<CommandAppSettings, bool> func, string environmentVariableName) | ||||
|   | ||||
| @@ -26,7 +26,7 @@ internal static class MarkupParser | ||||
|  | ||||
|             if (token.Kind == MarkupTokenKind.Open) | ||||
|             { | ||||
|                 var parsedStyle = StyleParser.Parse(token.Value); | ||||
|                 var parsedStyle = string.IsNullOrEmpty(token.Value) ? Style.Plain : StyleParser.Parse(token.Value); | ||||
|                 stack.Push(parsedStyle); | ||||
|             } | ||||
|             else if (token.Kind == MarkupTokenKind.Close) | ||||
|   | ||||
| @@ -0,0 +1,11 @@ | ||||
| namespace Spectre.Console.Cli.Tests.Data.Help; | ||||
|  | ||||
| internal class RenderMarkupHelpProvider : HelpProvider | ||||
| { | ||||
|     protected override bool RenderMarkupInline { get; } = true; | ||||
|  | ||||
|     public RenderMarkupHelpProvider(ICommandAppSettings settings) | ||||
|         : base(settings) | ||||
|     { | ||||
|     } | ||||
| } | ||||
| @@ -14,4 +14,8 @@ public class LionSettings : CatSettings | ||||
|     [Description("The days the lion goes hunting.")] | ||||
|     [DefaultValue(new[] { DayOfWeek.Monday, DayOfWeek.Thursday })] | ||||
|     public DayOfWeek[] HuntDays { get; set; } | ||||
|  | ||||
|     [CommandOption("-w|--weight [WEIGHT]")] | ||||
|     [Description("The weight of the lion, in kgs.")] | ||||
|     public FlagValue<int?> Weight { get; set; } | ||||
| } | ||||
|   | ||||
| @@ -16,4 +16,5 @@ OPTIONS: | ||||
|     -n, --name <VALUE> | ||||
|         --agility <VALUE>    10                  The agility between 0 and 100 | ||||
|     -c <CHILDREN>                                The number of children the lion has | ||||
|     -d <DAY>                 Monday, Thursday    The days the lion goes hunting | ||||
|     -d <DAY>                 Monday, Thursday    The days the lion goes hunting | ||||
|     -w, --weight [WEIGHT]                        The weight of the lion, in kgs | ||||
| @@ -16,4 +16,5 @@ OPTIONS: | ||||
|     -n, --name <VALUE> | ||||
|         --agility <VALUE>    10                  The agility between 0 and 100 | ||||
|     -c <CHILDREN>                                The number of children the lion has | ||||
|     -d <DAY>                 Monday, Thursday    The days the lion goes hunting | ||||
|     -d <DAY>                 Monday, Thursday    The days the lion goes hunting | ||||
|     -w, --weight [WEIGHT]                        The weight of the lion, in kgs | ||||
| @@ -20,6 +20,7 @@ OPTIONEN: | ||||
|         --agility <VALUE>    10                  The agility between 0 and 100 | ||||
|     -c <CHILDREN>                                The number of children the lion has | ||||
|     -d <DAY>                 Monday, Thursday    The days the lion goes hunting | ||||
|     -w, --weight [WEIGHT]                        The weight of the lion, in kgs | ||||
|  | ||||
| KOMMANDOS: | ||||
|     giraffe <LENGTH>    The giraffe command | ||||
| @@ -20,6 +20,7 @@ OPTIONS: | ||||
|         --agility <VALUE>    10                  The agility between 0 and 100 | ||||
|     -c <CHILDREN>                                The number of children the lion has | ||||
|     -d <DAY>                 Monday, Thursday    The days the lion goes hunting | ||||
|     -w, --weight [WEIGHT]                        The weight of the lion, in kgs | ||||
|  | ||||
| COMMANDS: | ||||
|     giraffe <LENGTH>    The giraffe command | ||||
| @@ -20,6 +20,7 @@ OPTIONS: | ||||
|         --agility <VALUE>    10                  The agility between 0 and 100 | ||||
|     -c <CHILDREN>                                The number of children the lion has | ||||
|     -d <DAY>                 Monday, Thursday    The days the lion goes hunting | ||||
|     -w, --weight [WEIGHT]                        The weight of the lion, in kgs | ||||
|  | ||||
| COMMANDES: | ||||
|     giraffe <LENGTH>    The giraffe command | ||||
| @@ -20,6 +20,7 @@ VAL: | ||||
|         --agility <VALUE>    10                  The agility between 0 and 100 | ||||
|     -c <CHILDREN>                                The number of children the lion has | ||||
|     -d <DAY>                 Monday, Thursday    The days the lion goes hunting | ||||
|     -w, --weight [WEIGHT]                        The weight of the lion, in kgs | ||||
|  | ||||
| KOMMANDON: | ||||
|     giraffe <LENGTH>    The giraffe command | ||||
| @@ -0,0 +1,26 @@ | ||||
| [bold]DESCRIPTION:[/] | ||||
| The lion command. | ||||
|  | ||||
| [bold]USAGE:[/] | ||||
|     myapp []<TEETH>[/] [][[LEGS]][/] [][[OPTIONS]][/] [][[COMMAND]][/] | ||||
|  | ||||
| [bold]EXAMPLES:[/] | ||||
|     myapp []20 --alive[/] | ||||
|  | ||||
| [bold]ARGUMENTS:[/] | ||||
|     []<TEETH>[/]     The number of teeth the lion has | ||||
|     [][[LEGS]][/]    The number of legs | ||||
|  | ||||
| []OPTIONS:[/] | ||||
|                                     []DEFAULT[/] | ||||
|     -h, --help                                                    Prints help information | ||||
|     -v, --version                                                 Prints version information | ||||
|     -a, --alive                                                   Indicates whether or not the animal is alive | ||||
|     -n, --name []<VALUE>[/] | ||||
|         --agility []<VALUE>[/]      []10[/]                       The agility between 0 and 100 | ||||
|     -c []<CHILDREN>[/]                                            The number of children the lion has | ||||
|     -d []<DAY>[/]                   []Monday[/], []Thursday[/]    The days the lion goes hunting | ||||
|     -w, --weight [][[WEIGHT]][/]                                  The weight of the lion, in kgs | ||||
|  | ||||
| [bold]COMMANDS:[/] | ||||
|     []giraffe[/] []<LENGTH>[/]    The giraffe command | ||||
| @@ -0,0 +1,26 @@ | ||||
| [yellow]DESCRIPTION:[/] | ||||
| The lion command. | ||||
|  | ||||
| [yellow]USAGE:[/] | ||||
|     myapp [aqua]<TEETH>[/] [silver][[LEGS]][/] [grey][[OPTIONS]][/] [aqua][[COMMAND]][/] | ||||
|  | ||||
| [yellow]EXAMPLES:[/] | ||||
|     myapp [grey]20 --alive[/] | ||||
|  | ||||
| [yellow]ARGUMENTS:[/] | ||||
|     [silver]<TEETH>[/]     The number of teeth the lion has | ||||
|     [silver][[LEGS]][/]    The number of legs | ||||
|  | ||||
| [yellow]OPTIONS:[/] | ||||
|                                         [lime]DEFAULT[/] | ||||
|     -h, --help                                                                Prints help information | ||||
|     -v, --version                                                             Prints version information | ||||
|     -a, --alive                                                               Indicates whether or not the animal is alive | ||||
|     -n, --name [silver]<VALUE>[/] | ||||
|         --agility [silver]<VALUE>[/]    [bold]10[/]                           The agility between 0 and 100 | ||||
|     -c [silver]<CHILDREN>[/]                                                  The number of children the lion has | ||||
|     -d [silver]<DAY>[/]                 [bold]Monday[/], [bold]Thursday[/]    The days the lion goes hunting | ||||
|     -w, --weight [grey][[WEIGHT]][/]                                          The weight of the lion, in kgs | ||||
|  | ||||
| [yellow]COMMANDS:[/] | ||||
|     [silver]giraffe[/] [silver]<LENGTH>[/]    The giraffe command | ||||
| @@ -0,0 +1,26 @@ | ||||
| []DESCRIPTION:[/] | ||||
| The lion command. | ||||
|  | ||||
| []USAGE:[/] | ||||
|     myapp []<TEETH>[/] [][[LEGS]][/] [][[OPTIONS]][/] [][[COMMAND]][/] | ||||
|  | ||||
| []EXAMPLES:[/] | ||||
|     myapp []20 --alive[/] | ||||
|  | ||||
| []ARGUMENTS:[/] | ||||
|     []<TEETH>[/]     The number of teeth the lion has | ||||
|     [][[LEGS]][/]    The number of legs | ||||
|  | ||||
| []OPTIONS:[/] | ||||
|                                     []DEFAULT[/] | ||||
|     -h, --help                                                    Prints help information | ||||
|     -v, --version                                                 Prints version information | ||||
|     -a, --alive                                                   Indicates whether or not the animal is alive | ||||
|     -n, --name []<VALUE>[/] | ||||
|         --agility []<VALUE>[/]      []10[/]                       The agility between 0 and 100 | ||||
|     -c []<CHILDREN>[/]                                            The number of children the lion has | ||||
|     -d []<DAY>[/]                   []Monday[/], []Thursday[/]    The days the lion goes hunting | ||||
|     -w, --weight [][[WEIGHT]][/]                                  The weight of the lion, in kgs | ||||
|  | ||||
| []COMMANDS:[/] | ||||
|     []giraffe[/] []<LENGTH>[/]    The giraffe command | ||||
| @@ -1,4 +1,4 @@ | ||||
| DESCRIPTION: | ||||
| DESCRIPTION: | ||||
| The lion command. | ||||
|  | ||||
| USAGE: | ||||
| @@ -8,7 +8,8 @@ ARGUMENTS: | ||||
|     <TEETH>    The number of teeth the lion has | ||||
|  | ||||
| OPTIONS: | ||||
|                      DEFAULT | ||||
|     -h, --help                           Prints help information | ||||
|     -c <CHILDREN>                        The number of children the lion has | ||||
|     -d <DAY>         Monday, Thursday    The days the lion goes hunting | ||||
|                              DEFAULT | ||||
|     -h, --help                                   Prints help information | ||||
|     -c <CHILDREN>                                The number of children the lion has | ||||
|     -d <DAY>                 Monday, Thursday    The days the lion goes hunting | ||||
|     -w, --weight [WEIGHT]                        The weight of the lion, in kgs | ||||
| @@ -264,6 +264,101 @@ public sealed partial class CommandAppTests | ||||
|             return Verifier.Verify(result.Output, settings).UseTextForParameters(expectationPrefix); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         [Expectation("Default_Without_Args_Additional_Style_Default")] | ||||
|         public Task Should_Output_Default_Command_And_Additional_Commands_When_Default_Command_Has_Required_Parameters_And_Is_Called_Without_Args_Style_Default() | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new CommandAppTester(); | ||||
|             fixture.SetDefaultCommand<LionCommand>(); | ||||
|             fixture.Configure(configurator => | ||||
|             { | ||||
|                 configurator.SetApplicationName("myapp"); | ||||
|                 configurator.AddExample("20", "--alive"); | ||||
|                 configurator.AddCommand<GiraffeCommand>("giraffe"); | ||||
|                 configurator.SetHelpProvider(new RenderMarkupHelpProvider(configurator.Settings)); | ||||
|             }); | ||||
|  | ||||
|             // When | ||||
|             var result = fixture.Run(); | ||||
|  | ||||
|             // Then | ||||
|             return Verifier.Verify(result.Output); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         [Expectation("Default_Without_Args_Additional_Style_BoldHeadings")] | ||||
|         public Task Should_Output_Default_Command_And_Additional_Commands_When_Default_Command_Has_Required_Parameters_And_Is_Called_Without_Args_Style_BoldHeadings() | ||||
|         { | ||||
|             // Bold headings in the help text | ||||
|             var styles = new HelpProviderStyle() | ||||
|             { | ||||
|                 Description = new DescriptionStyle() | ||||
|                 { | ||||
|                     Header = "bold", | ||||
|                 }, | ||||
|                 Usage = new UsageStyle() | ||||
|                 { | ||||
|                     Header = "bold", | ||||
|                 }, | ||||
|                 Examples = new ExampleStyle() | ||||
|                 { | ||||
|                     Header = "bold", | ||||
|                 }, | ||||
|                 Arguments = new ArgumentStyle() | ||||
|                 { | ||||
|                     Header = "bold", | ||||
|                 }, | ||||
|                 Commands = new CommandStyle() | ||||
|                 { | ||||
|                     Header = "bold", | ||||
|                 }, | ||||
|  | ||||
|                 // Omit OptionStyle to ensure coverage of at least one null style class | ||||
|             }; | ||||
|  | ||||
|             // Given | ||||
|             var fixture = new CommandAppTester(); | ||||
|             fixture.SetDefaultCommand<LionCommand>(); | ||||
|             fixture.Configure(configurator => | ||||
|             { | ||||
|                 configurator.SetApplicationName("myapp"); | ||||
|                 configurator.AddExample("20", "--alive"); | ||||
|                 configurator.AddCommand<GiraffeCommand>("giraffe"); | ||||
|                 configurator.Settings.HelpProviderStyles = styles; | ||||
|                 configurator.SetHelpProvider(new RenderMarkupHelpProvider(configurator.Settings)); | ||||
|             }); | ||||
|  | ||||
|             // When | ||||
|             var result = fixture.Run(); | ||||
|  | ||||
|             // Then | ||||
|             return Verifier.Verify(result.Output); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         [Expectation("Default_Without_Args_Additional_Style_None")] | ||||
|         public Task Should_Output_Default_Command_And_Additional_Commands_When_Default_Command_Has_Required_Parameters_And_Is_Called_Without_Args_Style_None() | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new CommandAppTester(); | ||||
|             fixture.SetDefaultCommand<LionCommand>(); | ||||
|             fixture.Configure(configurator => | ||||
|             { | ||||
|                 configurator.SetApplicationName("myapp"); | ||||
|                 configurator.AddExample("20", "--alive"); | ||||
|                 configurator.AddCommand<GiraffeCommand>("giraffe"); | ||||
|                 configurator.Settings.HelpProviderStyles = null; | ||||
|                 configurator.SetHelpProvider(new RenderMarkupHelpProvider(configurator.Settings)); | ||||
|             }); | ||||
|  | ||||
|             // When | ||||
|             var result = fixture.Run(); | ||||
|  | ||||
|             // Then | ||||
|             return Verifier.Verify(result.Output); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         [Expectation("Default_Greeter")] | ||||
|         public Task Should_Not_Output_Default_Command_When_Command_Has_No_Required_Parameters_And_Is_Called_Without_Args() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Frank Ray
					Frank Ray