From 169abca986f1230e7efce4e1219a269821c73343 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Fri, 10 Oct 2025 21:12:54 +0200 Subject: [PATCH 01/22] Add blog post for 0.52.0 --- .../2025-10-10-spectre-console-0.52-released.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 docs/input/blog/posts/2025-10-10-spectre-console-0.52-released.md diff --git a/docs/input/blog/posts/2025-10-10-spectre-console-0.52-released.md b/docs/input/blog/posts/2025-10-10-spectre-console-0.52-released.md new file mode 100644 index 000000000..ba8046ec2 --- /dev/null +++ b/docs/input/blog/posts/2025-10-10-spectre-console-0.52-released.md @@ -0,0 +1,17 @@ +Title: Spectre.Console 0.52.0 released! +Description: Don't eat (too much) glue. +Published: 2025-10-10 +Category: Release Notes +Excluded: false +--- + +Version`0.52.0` of Spectre.Console has been released! + +Exciting things are happening. We’ve merged support for my love child, OpenCli, in this release. That means you can now pass the parameter `--help-dump-opencli` to your application to get an [OpenCli](https://opencli.org) description dumped to stdout. + +## What's Changed + +* Add OpenCLI integration to Spectre.Console.Cli by [@patriksvensson](https://github.com/patriksvensson) in [#1909](https://github.com/spectreconsole/spectre.console/pull/1909) +* Fix OPENCLI_VISIBILITY_INTERNAL to DefineConstants concat by [@devlead](https://github.com/devlead) in [#1912](https://github.com/spectreconsole/spectre.console/pull/1912) + +**Full Changelog**: https://github.com/spectreconsole/spectre.console/compare/0.51.1...0.52.0 \ No newline at end of file From d90e94dbb32add90182e76a0645205fdc58a8ef5 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Fri, 10 Oct 2025 21:27:37 +0200 Subject: [PATCH 02/22] Fix spacing in blog post --- .../blog/posts/2025-10-10-spectre-console-0.52-released.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/input/blog/posts/2025-10-10-spectre-console-0.52-released.md b/docs/input/blog/posts/2025-10-10-spectre-console-0.52-released.md index ba8046ec2..f0fc88527 100644 --- a/docs/input/blog/posts/2025-10-10-spectre-console-0.52-released.md +++ b/docs/input/blog/posts/2025-10-10-spectre-console-0.52-released.md @@ -5,7 +5,7 @@ Category: Release Notes Excluded: false --- -Version`0.52.0` of Spectre.Console has been released! +Version `0.52.0` of Spectre.Console has been released! Exciting things are happening. We’ve merged support for my love child, OpenCli, in this release. That means you can now pass the parameter `--help-dump-opencli` to your application to get an [OpenCli](https://opencli.org) description dumped to stdout. From f5f61ca61010cec92828079b795d4c524070b1ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Mon, 9 Sep 2024 00:21:17 +0200 Subject: [PATCH 03/22] Add top-level CancellationToken support to Spectre.Console.Cli Also raise CA2016 (forward the CancellationToken parameter to methods that take one) to warning Fixes #701 --- .../Commands/ColorGeneratorCommand.cs | 3 +- .../Commands/EmojiGeneratorCommand.cs | 3 +- .../Generator/Commands/SampleCommand.cs | 3 +- .../Commands/SpinnerGeneratorCommand.cs | 3 +- src/.editorconfig | 7 ++- src/Spectre.Console.Cli/AsyncCommand.cs | 11 ++-- src/Spectre.Console.Cli/AsyncCommandOfT.cs | 11 ++-- src/Spectre.Console.Cli/Command.cs | 11 ++-- src/Spectre.Console.Cli/CommandApp.cs | 30 ++++------ src/Spectre.Console.Cli/CommandAppOfT.cs | 25 +++----- src/Spectre.Console.Cli/CommandOfT.cs | 11 ++-- .../ConfiguratorExtensions.cs | 34 ++++++++--- src/Spectre.Console.Cli/ICommand.cs | 3 +- src/Spectre.Console.Cli/ICommandApp.cs | 6 +- .../ICommandAppSettings.cs | 6 ++ src/Spectre.Console.Cli/ICommandOfT.cs | 3 +- src/Spectre.Console.Cli/IConfigurator.cs | 4 +- src/Spectre.Console.Cli/IConfiguratorOfT.cs | 4 +- .../Internal/CommandExecutor.cs | 11 ++-- .../Internal/Commands/ExplainCommand.cs | 2 +- .../Commands/OpenCliGeneratorCommand.cs | 2 +- .../Internal/Commands/VersionCommand.cs | 2 +- .../Internal/Commands/XmlDocCommand.cs | 2 +- .../Configuration/CommandAppSettings.cs | 2 + .../Internal/Configuration/Configurator.cs | 8 +-- .../Internal/Configuration/ConfiguratorOfT.cs | 8 +-- .../Configuration/ConfiguredCommand.cs | 6 +- .../Internal/DelegateCommand.cs | 8 +-- .../Internal/Modelling/CommandInfo.cs | 2 +- .../Cli/CommandAppTester.cs | 46 +++------------ .../Data/Commands/AsynchronousCommand.cs | 4 +- .../Data/Commands/CatCommand.cs | 2 +- .../Data/Commands/DogCommand.cs | 2 +- .../Data/Commands/DumpRemainingCommand.cs | 2 +- .../Data/Commands/EmptyCommand.cs | 2 +- .../Data/Commands/GenericCommand.cs | 2 +- .../Data/Commands/GiraffeCommand.cs | 2 +- .../Data/Commands/GreeterCommand.cs | 2 +- .../Data/Commands/HiddenOptionsCommand.cs | 2 +- .../Data/Commands/HorseCommand.cs | 2 +- .../Data/Commands/InvalidCommand.cs | 2 +- .../Data/Commands/LionCommand.cs | 2 +- .../Data/Commands/NoDescriptionCommand.cs | 2 +- .../Data/Commands/OptionVectorCommand.cs | 2 +- .../Data/Commands/ThrowingCommand.cs | 2 +- .../Data/Commands/TurtleCommand.cs | 2 +- .../Data/Commands/VersionCommand.cs | 2 +- .../Properties/Usings.cs | 1 + .../Unit/CommandAppTests.Async.cs | 58 ++++++++++++++++++- .../Unit/CommandAppTests.Constructor.cs | 4 +- .../CommandAppTests.Injection.Settings.cs | 2 +- .../Unit/CommandAppTests.Interceptor.cs | 2 +- .../Unit/CommandAppTests.cs | 12 ++-- .../Unit/Testing/CommandAppTesterTests.cs | 2 +- .../Unit/Testing/InteractiveCommandTests.cs | 2 +- 55 files changed, 222 insertions(+), 174 deletions(-) diff --git a/resources/scripts/Generator/Commands/ColorGeneratorCommand.cs b/resources/scripts/Generator/Commands/ColorGeneratorCommand.cs index 6088cdf02..bcc9aee29 100644 --- a/resources/scripts/Generator/Commands/ColorGeneratorCommand.cs +++ b/resources/scripts/Generator/Commands/ColorGeneratorCommand.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Threading; using Generator.Models; using Scriban; using Spectre.Console.Cli; @@ -21,7 +22,7 @@ public sealed class Settings : GeneratorSettings public string Input { get; set; } } - public override int Execute(CommandContext context, Settings settings) + public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) { var templates = new FilePath[] { diff --git a/resources/scripts/Generator/Commands/EmojiGeneratorCommand.cs b/resources/scripts/Generator/Commands/EmojiGeneratorCommand.cs index 1af0cbd77..b4c1ea1c5 100644 --- a/resources/scripts/Generator/Commands/EmojiGeneratorCommand.cs +++ b/resources/scripts/Generator/Commands/EmojiGeneratorCommand.cs @@ -2,6 +2,7 @@ using System.IO; using System.Linq; using System.Net.Http; +using System.Threading; using System.Threading.Tasks; using AngleSharp.Html.Parser; using Generator.Models; @@ -39,7 +40,7 @@ public EmojiGeneratorCommand() _parser = new HtmlParser(); } - public override async Task ExecuteAsync(CommandContext context, Settings settings) + public override async Task ExecuteAsync(CommandContext context, Settings settings, CancellationToken cancellationToken) { var output = new DirectoryPath(settings.Output); if (!_fileSystem.Directory.Exists(settings.Output)) diff --git a/resources/scripts/Generator/Commands/SampleCommand.cs b/resources/scripts/Generator/Commands/SampleCommand.cs index 5c6f6ff69..275662354 100644 --- a/resources/scripts/Generator/Commands/SampleCommand.cs +++ b/resources/scripts/Generator/Commands/SampleCommand.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; +using System.Threading; using Generator.Commands.Samples; using Spectre.Console; using Spectre.Console.Cli; @@ -38,7 +39,7 @@ public SampleCommand(IAnsiConsole console) _console = new AsciiCastConsole(console); } - public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings) + public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings, CancellationToken cancellationToken) { var samples = typeof(BaseSample).Assembly .GetTypes() diff --git a/resources/scripts/Generator/Commands/SpinnerGeneratorCommand.cs b/resources/scripts/Generator/Commands/SpinnerGeneratorCommand.cs index 7dd4497d9..de59cfdc6 100644 --- a/resources/scripts/Generator/Commands/SpinnerGeneratorCommand.cs +++ b/resources/scripts/Generator/Commands/SpinnerGeneratorCommand.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Threading; using Generator.Models; using Scriban; using Spectre.Console.Cli; @@ -16,7 +17,7 @@ public SpinnerGeneratorCommand() _fileSystem = new FileSystem(); } - public override int Execute(CommandContext context, GeneratorSettings settings) + public override int Execute(CommandContext context, GeneratorSettings settings, CancellationToken cancellationToken) { // Read the spinner model. var spinners = new List(); diff --git a/src/.editorconfig b/src/.editorconfig index e01b77d55..2ab117801 100644 --- a/src/.editorconfig +++ b/src/.editorconfig @@ -100,5 +100,8 @@ dotnet_diagnostic.RCS1047.severity = none # RCS1090: Call 'ConfigureAwait(false)'. dotnet_diagnostic.RCS1090.severity = warning -# The file header is missing or not located at the top of the file -dotnet_diagnostic.SA1633.severity = none \ No newline at end of file +# SA1633: The file header is missing or not located at the top of the file +dotnet_diagnostic.SA1633.severity = none + +# CA2016: Forward the CancellationToken parameter to methods that take one +dotnet_diagnostic.CA2016.severity = warning \ No newline at end of file diff --git a/src/Spectre.Console.Cli/AsyncCommand.cs b/src/Spectre.Console.Cli/AsyncCommand.cs index 5dd120906..55fb31667 100644 --- a/src/Spectre.Console.Cli/AsyncCommand.cs +++ b/src/Spectre.Console.Cli/AsyncCommand.cs @@ -9,19 +9,20 @@ public abstract class AsyncCommand : ICommand /// Executes the command. /// /// The command context. + /// A that can be used to abort the command. /// An integer indicating whether or not the command executed successfully. - public abstract Task ExecuteAsync(CommandContext context); + public abstract Task ExecuteAsync(CommandContext context, CancellationToken cancellationToken); /// - Task ICommand.Execute(CommandContext context, EmptyCommandSettings settings) + Task ICommand.ExecuteAsync(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) { - return ExecuteAsync(context); + return ExecuteAsync(context, cancellationToken); } /// - Task ICommand.Execute(CommandContext context, CommandSettings settings) + Task ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) { - return ExecuteAsync(context); + return ExecuteAsync(context, cancellationToken); } /// diff --git a/src/Spectre.Console.Cli/AsyncCommandOfT.cs b/src/Spectre.Console.Cli/AsyncCommandOfT.cs index 87da022a0..5172b6819 100644 --- a/src/Spectre.Console.Cli/AsyncCommandOfT.cs +++ b/src/Spectre.Console.Cli/AsyncCommandOfT.cs @@ -23,8 +23,9 @@ public virtual ValidationResult Validate(CommandContext context, TSettings setti /// /// The command context. /// The settings. + /// A that can be used to abort the command. /// An integer indicating whether or not the command executed successfully. - public abstract Task ExecuteAsync(CommandContext context, TSettings settings); + public abstract Task ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken); /// ValidationResult ICommand.Validate(CommandContext context, CommandSettings settings) @@ -33,15 +34,15 @@ ValidationResult ICommand.Validate(CommandContext context, CommandSettings setti } /// - Task ICommand.Execute(CommandContext context, CommandSettings settings) + Task ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) { Debug.Assert(settings is TSettings, "Command settings is of unexpected type."); - return ExecuteAsync(context, (TSettings)settings); + return ExecuteAsync(context, (TSettings)settings, cancellationToken); } /// - Task ICommand.Execute(CommandContext context, TSettings settings) + Task ICommand.ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken) { - return ExecuteAsync(context, settings); + return ExecuteAsync(context, settings, cancellationToken); } } \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Command.cs b/src/Spectre.Console.Cli/Command.cs index 2261e6f9d..7d9b6e5d9 100644 --- a/src/Spectre.Console.Cli/Command.cs +++ b/src/Spectre.Console.Cli/Command.cs @@ -10,19 +10,20 @@ public abstract class Command : ICommand /// Executes the command. /// /// The command context. + /// A that can be used to abort the command. /// An integer indicating whether or not the command executed successfully. - public abstract int Execute(CommandContext context); + public abstract int Execute(CommandContext context, CancellationToken cancellationToken); /// - Task ICommand.Execute(CommandContext context, EmptyCommandSettings settings) + Task ICommand.ExecuteAsync(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) { - return Task.FromResult(Execute(context)); + return Task.FromResult(Execute(context, cancellationToken)); } /// - Task ICommand.Execute(CommandContext context, CommandSettings settings) + Task ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) { - return Task.FromResult(Execute(context)); + return Task.FromResult(Execute(context, cancellationToken)); } /// diff --git a/src/Spectre.Console.Cli/CommandApp.cs b/src/Spectre.Console.Cli/CommandApp.cs index fa94e915b..d60d6740a 100644 --- a/src/Spectre.Console.Cli/CommandApp.cs +++ b/src/Spectre.Console.Cli/CommandApp.cs @@ -26,10 +26,7 @@ public CommandApp(ITypeRegistrar? registrar = null) _executor = new CommandExecutor(registrar); } - /// - /// Configures the command line application. - /// - /// The configuration. + /// public void Configure(Action configuration) { if (configuration == null) @@ -51,22 +48,14 @@ public DefaultCommandConfigurator SetDefaultCommand() return new DefaultCommandConfigurator(GetConfigurator().SetDefaultCommand()); } - /// - /// Runs the command line application with specified arguments. - /// - /// The arguments. - /// The exit code from the executed command. - public int Run(IEnumerable args) + /// + public int Run(IEnumerable args, CancellationToken cancellationToken = default) { - return RunAsync(args).GetAwaiter().GetResult(); + return RunAsync(args, cancellationToken).GetAwaiter().GetResult(); } - /// - /// Runs the command line application with specified arguments. - /// - /// The arguments. - /// The exit code from the executed command. - public async Task RunAsync(IEnumerable args) + /// + public async Task RunAsync(IEnumerable args, CancellationToken cancellationToken = default) { try { @@ -86,7 +75,7 @@ public async Task RunAsync(IEnumerable args) } return await _executor - .Execute(_configurator, args) + .ExecuteAsync(_configurator, args, cancellationToken) .ConfigureAwait(false); } catch (Exception ex) @@ -109,6 +98,11 @@ public async Task RunAsync(IEnumerable args) return _configurator.Settings.ExceptionHandler(ex, null); } + if (ex is OperationCanceledException) + { + return _configurator.Settings.CancellationExitCode; + } + // Render the exception. var pretty = GetRenderableErrorMessage(ex); if (pretty != null) diff --git a/src/Spectre.Console.Cli/CommandAppOfT.cs b/src/Spectre.Console.Cli/CommandAppOfT.cs index 6df8539ff..a06e43bdd 100644 --- a/src/Spectre.Console.Cli/CommandAppOfT.cs +++ b/src/Spectre.Console.Cli/CommandAppOfT.cs @@ -25,33 +25,22 @@ public CommandApp(ITypeRegistrar? registrar = null) _defaultCommandConfigurator = _app.SetDefaultCommand(); } - /// - /// Configures the command line application. - /// - /// The configuration. + /// public void Configure(Action configuration) { _app.Configure(configuration); } - /// - /// Runs the command line application with specified arguments. - /// - /// The arguments. - /// The exit code from the executed command. - public int Run(IEnumerable args) + /// + public int Run(IEnumerable args, CancellationToken cancellationToken = default) { - return _app.Run(args); + return _app.Run(args, cancellationToken); } - /// - /// Runs the command line application with specified arguments. - /// - /// The arguments. - /// The exit code from the executed command. - public Task RunAsync(IEnumerable args) + /// + public Task RunAsync(IEnumerable args, CancellationToken cancellationToken = default) { - return _app.RunAsync(args); + return _app.RunAsync(args, cancellationToken); } internal Configurator GetConfigurator() diff --git a/src/Spectre.Console.Cli/CommandOfT.cs b/src/Spectre.Console.Cli/CommandOfT.cs index e2be58ef1..d35823dcb 100644 --- a/src/Spectre.Console.Cli/CommandOfT.cs +++ b/src/Spectre.Console.Cli/CommandOfT.cs @@ -24,8 +24,9 @@ public virtual ValidationResult Validate(CommandContext context, TSettings setti /// /// The command context. /// The settings. + /// A that can be used to abort the command. /// An integer indicating whether or not the command executed successfully. - public abstract int Execute(CommandContext context, TSettings settings); + public abstract int Execute(CommandContext context, TSettings settings, CancellationToken cancellationToken); /// ValidationResult ICommand.Validate(CommandContext context, CommandSettings settings) @@ -34,15 +35,15 @@ ValidationResult ICommand.Validate(CommandContext context, CommandSettings setti } /// - Task ICommand.Execute(CommandContext context, CommandSettings settings) + Task ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) { Debug.Assert(settings is TSettings, "Command settings is of unexpected type."); - return Task.FromResult(Execute(context, (TSettings)settings)); + return Task.FromResult(Execute(context, (TSettings)settings, cancellationToken)); } /// - Task ICommand.Execute(CommandContext context, TSettings settings) + Task ICommand.ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken) { - return Task.FromResult(Execute(context, settings)); + return Task.FromResult(Execute(context, settings, cancellationToken)); } } \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ConfiguratorExtensions.cs b/src/Spectre.Console.Cli/ConfiguratorExtensions.cs index 6a03617cd..87f6272a0 100644 --- a/src/Spectre.Console.Cli/ConfiguratorExtensions.cs +++ b/src/Spectre.Console.Cli/ConfiguratorExtensions.cs @@ -201,6 +201,24 @@ public static IConfigurator PropagateExceptions(this IConfigurator configurator) return configurator; } + /// + /// Tells the command line application to return the specified exit code when it's aborted through the . + /// The default cancellation exit code is 130. + /// + /// The configurator. + /// The exit code to return in case of cancellation. + /// A configurator that can be used to configure the application further. + public static IConfigurator CancellationExitCode(this IConfigurator configurator, int exitCode) + { + if (configurator == null) + { + throw new ArgumentNullException(nameof(configurator)); + } + + configurator.Settings.CancellationExitCode = exitCode; + return configurator; + } + /// /// Configures case sensitivity. /// @@ -304,14 +322,14 @@ public static IBranchConfigurator AddBranch( public static ICommandConfigurator AddDelegate( this IConfigurator configurator, string name, - Func func) + Func func) { if (configurator == null) { throw new ArgumentNullException(nameof(configurator)); } - return configurator.AddDelegate(name, (c, _) => func(c)); + return configurator.AddDelegate(name, (c, _, ct) => func(c, ct)); } /// @@ -324,14 +342,14 @@ public static ICommandConfigurator AddDelegate( public static ICommandConfigurator AddAsyncDelegate( this IConfigurator configurator, string name, - Func> func) + Func> func) { if (configurator == null) { throw new ArgumentNullException(nameof(configurator)); } - return configurator.AddAsyncDelegate(name, (c, _) => func(c)); + return configurator.AddAsyncDelegate(name, (c, _, ct) => func(c, ct)); } /// @@ -345,7 +363,7 @@ public static ICommandConfigurator AddAsyncDelegate( public static ICommandConfigurator AddDelegate( this IConfigurator? configurator, string name, - Func func) + Func func) where TSettings : CommandSettings { if (typeof(TSettings).IsAbstract) @@ -358,7 +376,7 @@ public static ICommandConfigurator AddDelegate( throw new ArgumentNullException(nameof(configurator)); } - return configurator.AddDelegate(name, (c, _) => func(c)); + return configurator.AddDelegate(name, (c, _, ct) => func(c, ct)); } /// @@ -372,7 +390,7 @@ public static ICommandConfigurator AddDelegate( public static ICommandConfigurator AddAsyncDelegate( this IConfigurator configurator, string name, - Func> func) + Func> func) where TSettings : CommandSettings { if (configurator == null) @@ -380,7 +398,7 @@ public static ICommandConfigurator AddAsyncDelegate( throw new ArgumentNullException(nameof(configurator)); } - return configurator.AddAsyncDelegate(name, (c, _) => func(c)); + return configurator.AddAsyncDelegate(name, (c, _, ct) => func(c, ct)); } /// diff --git a/src/Spectre.Console.Cli/ICommand.cs b/src/Spectre.Console.Cli/ICommand.cs index 8cbcbf770..90ce2caf8 100644 --- a/src/Spectre.Console.Cli/ICommand.cs +++ b/src/Spectre.Console.Cli/ICommand.cs @@ -18,6 +18,7 @@ public interface ICommand /// /// The command context. /// The settings. + /// A that can be used to abort the command. /// The validation result. - Task Execute(CommandContext context, CommandSettings settings); + Task ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken); } \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ICommandApp.cs b/src/Spectre.Console.Cli/ICommandApp.cs index 5d5e2e740..381a2812d 100644 --- a/src/Spectre.Console.Cli/ICommandApp.cs +++ b/src/Spectre.Console.Cli/ICommandApp.cs @@ -15,13 +15,15 @@ public interface ICommandApp /// Runs the command line application with specified arguments. /// /// The arguments. + /// A that can be used to abort the application. /// The exit code from the executed command. - int Run(IEnumerable args); + int Run(IEnumerable args, CancellationToken cancellationToken = default); /// /// Runs the command line application with specified arguments. /// /// The arguments. + /// A that can be used to abort the application. /// The exit code from the executed command. - Task RunAsync(IEnumerable args); + Task RunAsync(IEnumerable args, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ICommandAppSettings.cs b/src/Spectre.Console.Cli/ICommandAppSettings.cs index 0c865e28f..d0e78517d 100644 --- a/src/Spectre.Console.Cli/ICommandAppSettings.cs +++ b/src/Spectre.Console.Cli/ICommandAppSettings.cs @@ -88,6 +88,12 @@ public interface ICommandAppSettings /// bool PropagateExceptions { get; set; } + /// + /// Gets or sets the value used as the application exit code when it's aborted through the . + /// The default cancellation exit code is 130. + /// + int CancellationExitCode { get; set; } + /// /// Gets or sets a value indicating whether or not examples should be validated. /// diff --git a/src/Spectre.Console.Cli/ICommandOfT.cs b/src/Spectre.Console.Cli/ICommandOfT.cs index 5b92cf8be..bb3b03eec 100644 --- a/src/Spectre.Console.Cli/ICommandOfT.cs +++ b/src/Spectre.Console.Cli/ICommandOfT.cs @@ -12,6 +12,7 @@ public interface ICommand : ICommandLimiter /// /// The command context. /// The settings. + /// A that can be used to abort the command. /// An integer indicating whether or not the command executed successfully. - Task Execute(CommandContext context, TSettings settings); + Task ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken); } \ No newline at end of file diff --git a/src/Spectre.Console.Cli/IConfigurator.cs b/src/Spectre.Console.Cli/IConfigurator.cs index 4e55ce341..ec4051c01 100644 --- a/src/Spectre.Console.Cli/IConfigurator.cs +++ b/src/Spectre.Console.Cli/IConfigurator.cs @@ -48,7 +48,7 @@ ICommandConfigurator AddCommand(string name) /// The name of the command. /// The delegate to execute as part of command execution. /// A command configurator that can be used to configure the command further. - ICommandConfigurator AddDelegate(string name, Func func) + ICommandConfigurator AddDelegate(string name, Func func) where TSettings : CommandSettings; /// @@ -58,7 +58,7 @@ ICommandConfigurator AddDelegate(string name, FuncThe name of the command. /// The delegate to execute as part of command execution. /// A command configurator that can be used to configure the command further. - ICommandConfigurator AddAsyncDelegate(string name, Func> func) + ICommandConfigurator AddAsyncDelegate(string name, Func> func) where TSettings : CommandSettings; /// diff --git a/src/Spectre.Console.Cli/IConfiguratorOfT.cs b/src/Spectre.Console.Cli/IConfiguratorOfT.cs index 0c71b348c..7c0b26f23 100644 --- a/src/Spectre.Console.Cli/IConfiguratorOfT.cs +++ b/src/Spectre.Console.Cli/IConfiguratorOfT.cs @@ -54,7 +54,7 @@ ICommandConfigurator AddCommand(string name) /// The name of the command. /// The delegate to execute as part of command execution. /// A command configurator that can be used to configure the command further. - ICommandConfigurator AddDelegate(string name, Func func) + ICommandConfigurator AddDelegate(string name, Func func) where TDerivedSettings : TSettings; /// @@ -64,7 +64,7 @@ ICommandConfigurator AddDelegate(string name, FuncThe name of the command. /// The delegate to execute as part of command execution. /// A command configurator that can be used to configure the command further. - ICommandConfigurator AddAsyncDelegate(string name, Func> func) + ICommandConfigurator AddAsyncDelegate(string name, Func> func) where TDerivedSettings : TSettings; /// diff --git a/src/Spectre.Console.Cli/Internal/CommandExecutor.cs b/src/Spectre.Console.Cli/Internal/CommandExecutor.cs index 5bfbc2157..4d1d7dec8 100644 --- a/src/Spectre.Console.Cli/Internal/CommandExecutor.cs +++ b/src/Spectre.Console.Cli/Internal/CommandExecutor.cs @@ -12,7 +12,7 @@ public CommandExecutor(ITypeRegistrar registrar) _registrar.Register(typeof(DefaultPairDeconstructor), typeof(DefaultPairDeconstructor)); } - public async Task Execute(IConfiguration configuration, IEnumerable args) + public async Task ExecuteAsync(IConfiguration configuration, IEnumerable args, CancellationToken cancellationToken) { CommandTreeParserResult parsedResult; @@ -125,7 +125,7 @@ public async Task Execute(IConfiguration configuration, IEnumerable leaf.Command.Data); // Execute the command tree. - return await Execute(leaf, parsedResult.Tree, context, resolver, configuration).ConfigureAwait(false); + return await ExecuteAsync(leaf, parsedResult.Tree, context, resolver, configuration, cancellationToken).ConfigureAwait(false); } } @@ -222,12 +222,13 @@ private CommandTreeParserResult ParseCommandLineArguments(CommandModel model, Co return (parsedResult, tokenizerResult); } - private static async Task Execute( + private static async Task ExecuteAsync( CommandTree leaf, CommandTree tree, CommandContext context, ITypeResolver resolver, - IConfiguration configuration) + IConfiguration configuration, + CancellationToken cancellationToken) { try { @@ -256,7 +257,7 @@ private static async Task Execute( } // Execute the command. - var result = await command.Execute(context, settings); + var result = await command.ExecuteAsync(context, settings, cancellationToken); foreach (var interceptor in interceptors) { interceptor.InterceptResult(context, settings, ref result); diff --git a/src/Spectre.Console.Cli/Internal/Commands/ExplainCommand.cs b/src/Spectre.Console.Cli/Internal/Commands/ExplainCommand.cs index c1576beb9..29744fca4 100644 --- a/src/Spectre.Console.Cli/Internal/Commands/ExplainCommand.cs +++ b/src/Spectre.Console.Cli/Internal/Commands/ExplainCommand.cs @@ -27,7 +27,7 @@ public sealed class Settings : CommandSettings public bool IncludeHidden { get; set; } } - public override int Execute(CommandContext context, Settings settings) + public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) { var tree = new Tree("CLI Configuration"); tree.AddNode(ValueMarkup("Application Name", _commandModel.ApplicationName, "no application name")); diff --git a/src/Spectre.Console.Cli/Internal/Commands/OpenCliGeneratorCommand.cs b/src/Spectre.Console.Cli/Internal/Commands/OpenCliGeneratorCommand.cs index 7d3e444af..e33b058ae 100644 --- a/src/Spectre.Console.Cli/Internal/Commands/OpenCliGeneratorCommand.cs +++ b/src/Spectre.Console.Cli/Internal/Commands/OpenCliGeneratorCommand.cs @@ -13,7 +13,7 @@ public OpenCliGeneratorCommand(IConfiguration configuration, CommandModel model) _model = model ?? throw new ArgumentNullException(nameof(model)); } - public override int Execute(CommandContext context) + public override int Execute(CommandContext context, CancellationToken cancellationToken) { var document = new OpenCliDocument { diff --git a/src/Spectre.Console.Cli/Internal/Commands/VersionCommand.cs b/src/Spectre.Console.Cli/Internal/Commands/VersionCommand.cs index 419171e7e..c6bef190a 100644 --- a/src/Spectre.Console.Cli/Internal/Commands/VersionCommand.cs +++ b/src/Spectre.Console.Cli/Internal/Commands/VersionCommand.cs @@ -11,7 +11,7 @@ public VersionCommand(IConfiguration configuration) _writer = configuration.Settings.Console.GetConsole(); } - public override int Execute(CommandContext context) + public override int Execute(CommandContext context, CancellationToken cancellationToken) { _writer.MarkupLine( "[yellow]Spectre.Cli[/] version [aqua]{0}[/]", diff --git a/src/Spectre.Console.Cli/Internal/Commands/XmlDocCommand.cs b/src/Spectre.Console.Cli/Internal/Commands/XmlDocCommand.cs index 2b322e02e..8b2e82ed8 100644 --- a/src/Spectre.Console.Cli/Internal/Commands/XmlDocCommand.cs +++ b/src/Spectre.Console.Cli/Internal/Commands/XmlDocCommand.cs @@ -13,7 +13,7 @@ public XmlDocCommand(IConfiguration configuration, CommandModel model) _writer = configuration.Settings.Console.GetConsole(); } - public override int Execute(CommandContext context) + public override int Execute(CommandContext context, CancellationToken cancellationToken) { _writer.Write(Serialize(_model), Style.Plain); return 0; diff --git a/src/Spectre.Console.Cli/Internal/Configuration/CommandAppSettings.cs b/src/Spectre.Console.Cli/Internal/Configuration/CommandAppSettings.cs index 91b51a498..65b669072 100644 --- a/src/Spectre.Console.Cli/Internal/Configuration/CommandAppSettings.cs +++ b/src/Spectre.Console.Cli/Internal/Configuration/CommandAppSettings.cs @@ -18,6 +18,7 @@ internal sealed class CommandAppSettings : ICommandAppSettings public HelpProviderStyle? HelpProviderStyles { get; set; } public bool StrictParsing { get; set; } public bool ConvertFlagsToRemainingArguments { get; set; } + public int CancellationExitCode { get; set; } public ParsingMode ParsingMode => StrictParsing ? ParsingMode.Strict : ParsingMode.Relaxed; @@ -33,6 +34,7 @@ public CommandAppSettings(ITypeRegistrar registrar) TrimTrailingPeriod = true; HelpProviderStyles = HelpProviderStyle.Default; ConvertFlagsToRemainingArguments = false; + CancellationExitCode = 130; } public bool IsTrue(Func func, string environmentVariableName) diff --git a/src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs b/src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs index 5f2d20a2b..4605e0114 100644 --- a/src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs +++ b/src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs @@ -56,19 +56,19 @@ public ICommandConfigurator AddCommand(string name) return new CommandConfigurator(command); } - public ICommandConfigurator AddDelegate(string name, Func func) + public ICommandConfigurator AddDelegate(string name, Func func) where TSettings : CommandSettings { var command = Commands.AddAndReturn(ConfiguredCommand.FromDelegate( - name, (context, settings) => Task.FromResult(func(context, (TSettings)settings)))); + name, (context, settings, cancellationToken) => Task.FromResult(func(context, (TSettings)settings, cancellationToken)))); return new CommandConfigurator(command); } - public ICommandConfigurator AddAsyncDelegate(string name, Func> func) + public ICommandConfigurator AddAsyncDelegate(string name, Func> func) where TSettings : CommandSettings { var command = Commands.AddAndReturn(ConfiguredCommand.FromDelegate( - name, (context, settings) => func(context, (TSettings)settings))); + name, (context, settings, cancellationToken) => func(context, (TSettings)settings, cancellationToken))); return new CommandConfigurator(command); } diff --git a/src/Spectre.Console.Cli/Internal/Configuration/ConfiguratorOfT.cs b/src/Spectre.Console.Cli/Internal/Configuration/ConfiguratorOfT.cs index 537e48540..05c8ef958 100644 --- a/src/Spectre.Console.Cli/Internal/Configuration/ConfiguratorOfT.cs +++ b/src/Spectre.Console.Cli/Internal/Configuration/ConfiguratorOfT.cs @@ -46,21 +46,21 @@ public ICommandConfigurator AddCommand(string name) return configurator; } - public ICommandConfigurator AddDelegate(string name, Func func) + public ICommandConfigurator AddDelegate(string name, Func func) where TDerivedSettings : TSettings { var command = ConfiguredCommand.FromDelegate( - name, (context, settings) => Task.FromResult(func(context, (TDerivedSettings)settings))); + name, (context, settings, cancellationToken) => Task.FromResult(func(context, (TDerivedSettings)settings, cancellationToken))); _command.Children.Add(command); return new CommandConfigurator(command); } - public ICommandConfigurator AddAsyncDelegate(string name, Func> func) + public ICommandConfigurator AddAsyncDelegate(string name, Func> func) where TDerivedSettings : TSettings { var command = ConfiguredCommand.FromDelegate( - name, (context, settings) => func(context, (TDerivedSettings)settings)); + name, (context, settings, cancellationToken) => func(context, (TDerivedSettings)settings, cancellationToken)); _command.Children.Add(command); return new CommandConfigurator(command); diff --git a/src/Spectre.Console.Cli/Internal/Configuration/ConfiguredCommand.cs b/src/Spectre.Console.Cli/Internal/Configuration/ConfiguredCommand.cs index e39663f1f..75ad9ddba 100644 --- a/src/Spectre.Console.Cli/Internal/Configuration/ConfiguredCommand.cs +++ b/src/Spectre.Console.Cli/Internal/Configuration/ConfiguredCommand.cs @@ -8,7 +8,7 @@ internal sealed class ConfiguredCommand public object? Data { get; set; } public Type? CommandType { get; } public Type SettingsType { get; } - public Func>? Delegate { get; } + public Func>? Delegate { get; } public bool IsDefaultCommand { get; } public bool IsHidden { get; set; } @@ -19,7 +19,7 @@ private ConfiguredCommand( string name, Type? commandType, Type settingsType, - Func>? @delegate, + Func>? @delegate, bool isDefaultCommand) { Name = name; @@ -60,7 +60,7 @@ public static ConfiguredCommand FromType(string name, bool isDefaultCo } public static ConfiguredCommand FromDelegate( - string name, Func>? @delegate = null) + string name, Func>? @delegate = null) where TSettings : CommandSettings { return new ConfiguredCommand(name, null, typeof(TSettings), @delegate, false); diff --git a/src/Spectre.Console.Cli/Internal/DelegateCommand.cs b/src/Spectre.Console.Cli/Internal/DelegateCommand.cs index 4786fdd43..30825bcb0 100644 --- a/src/Spectre.Console.Cli/Internal/DelegateCommand.cs +++ b/src/Spectre.Console.Cli/Internal/DelegateCommand.cs @@ -2,16 +2,16 @@ namespace Spectre.Console.Cli; internal sealed class DelegateCommand : ICommand { - private readonly Func> _func; + private readonly Func> _func; - public DelegateCommand(Func> func) + public DelegateCommand(Func> func) { _func = func; } - public Task Execute(CommandContext context, CommandSettings settings) + public Task ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) { - return _func(context, settings); + return _func(context, settings, cancellationToken); } public ValidationResult Validate(CommandContext context, CommandSettings settings) diff --git a/src/Spectre.Console.Cli/Internal/Modelling/CommandInfo.cs b/src/Spectre.Console.Cli/Internal/Modelling/CommandInfo.cs index 08bad48dd..e96ed3393 100644 --- a/src/Spectre.Console.Cli/Internal/Modelling/CommandInfo.cs +++ b/src/Spectre.Console.Cli/Internal/Modelling/CommandInfo.cs @@ -8,7 +8,7 @@ internal sealed class CommandInfo : ICommandContainer, ICommandInfo public object? Data { get; } public Type? CommandType { get; } public Type SettingsType { get; } - public Func>? Delegate { get; } + public Func>? Delegate { get; } public bool IsDefaultCommand { get; } public CommandInfo? Parent { get; } public IList Children { get; } diff --git a/src/Spectre.Console.Testing/Cli/CommandAppTester.cs b/src/Spectre.Console.Testing/Cli/CommandAppTester.cs index 3817903e6..f2156e951 100644 --- a/src/Spectre.Console.Testing/Cli/CommandAppTester.cs +++ b/src/Spectre.Console.Testing/Cli/CommandAppTester.cs @@ -98,7 +98,7 @@ public CommandAppFailure RunAndCatch(params string[] args) { try { - Run(args, Console, c => c.PropagateExceptions()); + RunAsync(args, Console, c => c.PropagateExceptions()).GetAwaiter().GetResult(); throw new InvalidOperationException("Expected an exception to be thrown, but there was none."); } catch (T ex) @@ -129,53 +129,21 @@ public CommandAppFailure RunAndCatch(params string[] args) /// The result. public CommandAppResult Run(params string[] args) { - return Run(args, Console); - } - - private CommandAppResult Run(string[] args, TestConsole console, Action? config = null) - { - CommandContext? context = null; - CommandSettings? settings = null; - - var app = new CommandApp(Registrar); - _appConfiguration?.Invoke(app); - - if (_configuration != null) - { - app.Configure(_configuration); - } - - if (config != null) - { - app.Configure(config); - } - - app.Configure(c => c.ConfigureConsole(console)); - app.Configure(c => c.SetInterceptor(new CallbackCommandInterceptor((ctx, s) => - { - context = ctx; - settings = s; - }))); - - var result = app.Run(args); - - var output = console.Output.NormalizeLineEndings(); - output = TestSettings.TrimConsoleOutput ? output.TrimLines().Trim() : output; - - return new CommandAppResult(result, output, context, settings); + return RunAsync(args, Console).GetAwaiter().GetResult(); } /// /// Runs the command application asynchronously. /// /// The arguments. + /// The token to monitor for cancellation requests. /// The result. - public async Task RunAsync(params string[] args) + public async Task RunAsync(string[]? args = null, CancellationToken cancellationToken = default) { - return await RunAsync(args, Console); + return await RunAsync(args ?? [], Console, cancellationToken: cancellationToken); } - private async Task RunAsync(string[] args, TestConsole console, Action? config = null) + private async Task RunAsync(string[] args, TestConsole console, Action? config = null, CancellationToken cancellationToken = default) { CommandContext? context = null; CommandSettings? settings = null; @@ -200,7 +168,7 @@ private async Task RunAsync(string[] args, TestConsole console settings = s; }))); - var result = await app.RunAsync(args); + var result = await app.RunAsync(args, cancellationToken); var output = console.Output.NormalizeLineEndings(); output = TestSettings.TrimConsoleOutput ? output.TrimLines().Trim() : output; diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AsynchronousCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AsynchronousCommand.cs index 0da13ac2f..891d1ce9b 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AsynchronousCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AsynchronousCommand.cs @@ -9,10 +9,10 @@ public AsynchronousCommand(IAnsiConsole console) _console = console; } - public async override Task ExecuteAsync(CommandContext context, AsynchronousCommandSettings settings) + public async override Task ExecuteAsync(CommandContext context, AsynchronousCommandSettings settings, CancellationToken cancellationToken) { // Simulate a long running asynchronous task - await Task.Delay(200); + await Task.Delay(200, cancellationToken); if (settings.ThrowException) { diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/CatCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/CatCommand.cs index ab0a6afa8..97eb2b432 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/CatCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/CatCommand.cs @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; public class CatCommand : AnimalCommand { - public override int Execute(CommandContext context, CatSettings settings) + public override int Execute(CommandContext context, CatSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DogCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DogCommand.cs index 1bb5e3ea1..9361fdae0 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DogCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DogCommand.cs @@ -23,7 +23,7 @@ public override ValidationResult Validate(CommandContext context, DogSettings se return base.Validate(context, settings); } - public override int Execute(CommandContext context, DogSettings settings) + public override int Execute(CommandContext context, DogSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DumpRemainingCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DumpRemainingCommand.cs index dc8e71da0..b848787de 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DumpRemainingCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DumpRemainingCommand.cs @@ -9,7 +9,7 @@ public DumpRemainingCommand(IAnsiConsole console) _console = console; } - public override int Execute(CommandContext context, EmptyCommandSettings settings) + public override int Execute(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) { if (context.Remaining.Raw.Count > 0) { diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/EmptyCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/EmptyCommand.cs index 6ab33907e..498884e28 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/EmptyCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/EmptyCommand.cs @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; public sealed class EmptyCommand : Command { - public override int Execute(CommandContext context, EmptyCommandSettings settings) + public override int Execute(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GenericCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GenericCommand.cs index a0ae21cdd..0353508a4 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GenericCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GenericCommand.cs @@ -3,7 +3,7 @@ namespace Spectre.Console.Tests.Data; public sealed class GenericCommand : Command where TSettings : CommandSettings { - public override int Execute(CommandContext context, TSettings settings) + public override int Execute(CommandContext context, TSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GiraffeCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GiraffeCommand.cs index 87d0f04d2..e6569ae3a 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GiraffeCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GiraffeCommand.cs @@ -3,7 +3,7 @@ namespace Spectre.Console.Tests.Data; [Description("The giraffe command.")] public sealed class GiraffeCommand : Command { - public override int Execute(CommandContext context, GiraffeSettings settings) + public override int Execute(CommandContext context, GiraffeSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GreeterCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GreeterCommand.cs index d466f4607..03ff8eaed 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GreeterCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GreeterCommand.cs @@ -9,7 +9,7 @@ public GreeterCommand(IAnsiConsole console) _console = console; } - public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings) + public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings, CancellationToken cancellationToken) { _console.WriteLine(settings.Greeting); return 0; diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HiddenOptionsCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HiddenOptionsCommand.cs index dded24cfc..15dcfb606 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HiddenOptionsCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HiddenOptionsCommand.cs @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; public sealed class HiddenOptionsCommand : Command { - public override int Execute(CommandContext context, HiddenOptionSettings settings) + public override int Execute(CommandContext context, HiddenOptionSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HorseCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HorseCommand.cs index 148999cdc..7e7e89e65 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HorseCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HorseCommand.cs @@ -3,7 +3,7 @@ namespace Spectre.Console.Tests.Data; [Description("The horse command.")] public class HorseCommand : AnimalCommand { - public override int Execute(CommandContext context, HorseSettings settings) + public override int Execute(CommandContext context, HorseSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/InvalidCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/InvalidCommand.cs index 27ee20541..ef2cf1a5b 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/InvalidCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/InvalidCommand.cs @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; public sealed class InvalidCommand : Command { - public override int Execute(CommandContext context, InvalidSettings settings) + public override int Execute(CommandContext context, InvalidSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/LionCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/LionCommand.cs index eb7dfa54a..bd415d696 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/LionCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/LionCommand.cs @@ -3,7 +3,7 @@ namespace Spectre.Console.Tests.Data; [Description("The lion command.")] public class LionCommand : AnimalCommand { - public override int Execute(CommandContext context, LionSettings settings) + public override int Execute(CommandContext context, LionSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/NoDescriptionCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/NoDescriptionCommand.cs index 5e9c0bc9b..1a7d064bf 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/NoDescriptionCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/NoDescriptionCommand.cs @@ -5,7 +5,7 @@ public sealed class NoDescriptionCommand : Command [CommandOption("-f|--foo ")] public int Foo { get; set; } - public override int Execute(CommandContext context, EmptyCommandSettings settings) + public override int Execute(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/OptionVectorCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/OptionVectorCommand.cs index a892881ea..bfb76e787 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/OptionVectorCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/OptionVectorCommand.cs @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; public class OptionVectorCommand : Command { - public override int Execute(CommandContext context, OptionVectorSettings settings) + public override int Execute(CommandContext context, OptionVectorSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/ThrowingCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/ThrowingCommand.cs index 480452502..493c3f14a 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/ThrowingCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/ThrowingCommand.cs @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Data; public sealed class ThrowingCommand : Command { - public override int Execute(CommandContext context, ThrowingCommandSettings settings) + public override int Execute(CommandContext context, ThrowingCommandSettings settings, CancellationToken cancellationToken) { throw new InvalidOperationException("W00t?"); } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/TurtleCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/TurtleCommand.cs index 0b99327b3..957671a54 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/TurtleCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/TurtleCommand.cs @@ -3,7 +3,7 @@ namespace Spectre.Console.Tests.Data; [Description("The turtle command.")] public class TurtleCommand : AnimalCommand { - public override int Execute(CommandContext context, TurtleSettings settings) + public override int Execute(CommandContext context, TurtleSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/VersionCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/VersionCommand.cs index 551883708..8c7c33033 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/VersionCommand.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/VersionCommand.cs @@ -9,7 +9,7 @@ public VersionCommand(IAnsiConsole console) _console = console; } - public override int Execute(CommandContext context, VersionSettings settings) + public override int Execute(CommandContext context, VersionSettings settings, CancellationToken cancellationToken) { _console.WriteLine($"VersionCommand ran, Version: {settings.Version ?? string.Empty}"); diff --git a/src/Tests/Spectre.Console.Cli.Tests/Properties/Usings.cs b/src/Tests/Spectre.Console.Cli.Tests/Properties/Usings.cs index 7436882cc..6b28670a5 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Properties/Usings.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Properties/Usings.cs @@ -5,6 +5,7 @@ global using System.Globalization; global using System.Linq; global using System.Runtime.CompilerServices; +global using System.Threading; global using System.Threading.Tasks; global using Shouldly; global using Spectre.Console.Cli; diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Async.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Async.cs index 8ce3ee141..892a3b31c 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Async.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Async.cs @@ -53,7 +53,7 @@ public async Task Should_Throw_Exception_Asynchronously() }); // When - var result = await Record.ExceptionAsync(async () => + var exception = await Record.ExceptionAsync(async () => await app.RunAsync(new[] { "--ThrowException", @@ -61,10 +61,64 @@ await app.RunAsync(new[] })); // Then - result.ShouldBeOfType().And(ex => + exception.ShouldBeOfType().And(ex => { ex.Message.ShouldBe("Throwing exception asynchronously"); }); } + + [Fact] + public async Task Should_Throw_OperationCanceledException_When_Propagated_And_Cancelled() + { + // Given + var app = new CommandAppTester(); + app.SetDefaultCommand(); + app.Configure(config => + { + config.PropagateExceptions(); + }); + + // When + var exception = await Record.ExceptionAsync(async () => + await app.RunAsync(cancellationToken: new CancellationToken(canceled: true))); + + // Then + exception.ShouldNotBeNull(); + exception.ShouldBeAssignableTo(); + } + + [Fact] + public async Task Should_Return_Default_Exit_Code_When_Cancelled() + { + // Given + var app = new CommandAppTester(); + app.SetDefaultCommand(); + + // When + var result = await app.RunAsync(cancellationToken: new CancellationToken(canceled: true)); + + // Then + result.ExitCode.ShouldBe(130); + result.Output.ShouldBeEmpty(); + } + + [Fact] + public async Task Should_Return_Custom_Exit_Code_When_Cancelled() + { + // Given + var app = new CommandAppTester(); + app.SetDefaultCommand(); + app.Configure(config => + { + config.CancellationExitCode(123); + }); + + // When + var result = await app.RunAsync(cancellationToken: new CancellationToken(canceled: true)); + + // Then + result.ExitCode.ShouldBe(123); + result.Output.ShouldBeEmpty(); + } } } \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Constructor.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Constructor.cs index 96d329aa7..2385a01c5 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Constructor.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Constructor.cs @@ -28,12 +28,12 @@ public class NullableWithInitSettings : CommandSettings public class NullableCommand : Command { - public override int Execute(CommandContext context, NullableSettings settings) => 0; + public override int Execute(CommandContext context, NullableSettings settings, CancellationToken cancellationToken) => 0; } public class NullableWithInitCommand : Command { - public override int Execute(CommandContext context, NullableWithInitSettings settings) => 0; + public override int Execute(CommandContext context, NullableWithInitSettings settings, CancellationToken cancellationToken) => 0; } [Fact] diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.Settings.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.Settings.cs index 8541ed915..b151cce2e 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.Settings.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.Settings.cs @@ -19,7 +19,7 @@ public CustomInheritedCommand(SomeFakeDependency dep) _dep = dep; } - public override int Execute(CommandContext context, CustomInheritedCommandSettings settings) + public override int Execute(CommandContext context, CustomInheritedCommandSettings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Interceptor.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Interceptor.cs index 338e2e294..13ad0b9c8 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Interceptor.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Interceptor.cs @@ -10,7 +10,7 @@ public sealed class Settings : CommandSettings { } - public override int Execute(CommandContext context, Settings settings) + public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) { return 0; } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs index 34d852001..0f024025c 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs @@ -1117,7 +1117,7 @@ public void Should_Execute_Delegate_Command_At_Root_Level() { config.PropagateExceptions(); config.AddDelegate( - "foo", (context, settings) => + "foo", (context, settings, _) => { dog = settings; data = (int)context.Data; @@ -1145,7 +1145,7 @@ public void Should_Execute_Nested_Delegate_Empty_Command() { cfg.AddBranch("a", d => { - d.AddDelegate("b", _ => 0); + d.AddDelegate("b", (_, _) => 0); }); }); @@ -1165,7 +1165,7 @@ public void Should_Execute_Delegate_Empty_Command_At_Root_Level() var app = new CommandAppTester(); app.Configure(cfg => { - cfg.AddDelegate("a", _ => 0); + cfg.AddDelegate("a", (_, _) => 0); }); // When @@ -1189,7 +1189,7 @@ public async Task Should_Execute_Async_Delegate_Command_At_Root_Level() { config.PropagateExceptions(); config.AddAsyncDelegate( - "foo", (context, settings) => + "foo", (context, settings, _) => { dog = settings; data = (int)context.Data; @@ -1222,7 +1222,7 @@ public void Should_Execute_Nested_Delegate_Command() config.AddBranch("foo", foo => { foo.AddDelegate( - "bar", (context, settings) => + "bar", (context, settings, _) => { dog = settings; data = (int)context.Data; @@ -1256,7 +1256,7 @@ public async Task Should_Execute_Nested_Async_Delegate_Command() config.AddBranch("foo", foo => { foo.AddAsyncDelegate( - "bar", (context, settings) => + "bar", (context, settings, _) => { dog = settings; data = (int)context.Data; diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/CommandAppTesterTests.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/CommandAppTesterTests.cs index 7af0d4c95..284054025 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/CommandAppTesterTests.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/CommandAppTesterTests.cs @@ -14,7 +14,7 @@ public CommandAppTesterCommand(IAnsiConsole console) _console = console; } - public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings) + public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings, CancellationToken cancellationToken) { _console.Write(settings.Greeting); return 0; diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/InteractiveCommandTests.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/InteractiveCommandTests.cs index 98879e191..20a4a6ae1 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/InteractiveCommandTests.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/InteractiveCommandTests.cs @@ -11,7 +11,7 @@ public InteractiveCommand(IAnsiConsole console) _console = console; } - public override int Execute(CommandContext context) + public override int Execute(CommandContext context, CancellationToken cancellationToken) { var fruits = _console.Prompt( new MultiSelectionPrompt() From 749f0fded8bf92795501fe013c3bb405b78bb87c Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Sat, 11 Oct 2025 20:54:48 +0200 Subject: [PATCH 04/22] Update Verify to 31.0.1 --- src/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 8a0ce4989..38a6b3a28 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -17,7 +17,7 @@ - + From e51812237eb001b04ce2fdd9bcb90f0e4230b4e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Thu, 16 Oct 2025 22:34:28 +0200 Subject: [PATCH 05/22] Update the Spectre.Console.Cli documentation with CancellationToken Now that #1911 is merged, all `Execute` methods of commands have a new CancellationToken parameter. Update the documentation to reflect that. New documentation shall still be written with an example on how to pass the top-level CancellationToken to the app.Run(Async) method. --- docs/input/cli/commands.md | 2 +- docs/input/cli/composing.md | 4 ++-- docs/input/cli/getting-started.md | 2 +- docs/input/cli/introduction.md | 4 ++-- docs/input/cli/unit-testing.md | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/input/cli/commands.md b/docs/input/cli/commands.md index 167c19cd3..f77e0905e 100644 --- a/docs/input/cli/commands.md +++ b/docs/input/cli/commands.md @@ -18,7 +18,7 @@ public class HelloCommand : Command } - public override int Execute(CommandContext context, Settings settings) + public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) { AnsiConsole.MarkupLine($"Hello, [blue]{settings.Name}[/]"); return 0; diff --git a/docs/input/cli/composing.md b/docs/input/cli/composing.md index 7eafe9ce5..7407106fa 100644 --- a/docs/input/cli/composing.md +++ b/docs/input/cli/composing.md @@ -55,7 +55,7 @@ in the previous step. ```csharp public class AddPackageCommand : Command { - public override int Execute(CommandContext context, AddPackageSettings settings) + public override int Execute(CommandContext context, AddPackageSettings settings, CancellationToken cancellationToken) { // Omitted return 0; @@ -64,7 +64,7 @@ public class AddPackageCommand : Command public class AddReferenceCommand : Command { - public override int Execute(CommandContext context, AddReferenceSettings settings) + public override int Execute(CommandContext context, AddReferenceSettings settings, CancellationToken cancellationToken) { // Omitted return 0; diff --git a/docs/input/cli/getting-started.md b/docs/input/cli/getting-started.md index 7ccdb5dd1..47b72bae8 100644 --- a/docs/input/cli/getting-started.md +++ b/docs/input/cli/getting-started.md @@ -33,7 +33,7 @@ internal sealed class FileSizeCommand : Command public bool IncludeHidden { get; init; } } - public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings) + public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) { var searchOptions = new EnumerationOptions { diff --git a/docs/input/cli/introduction.md b/docs/input/cli/introduction.md index e6dba28ec..da6563044 100644 --- a/docs/input/cli/introduction.md +++ b/docs/input/cli/introduction.md @@ -61,7 +61,7 @@ in the previous step. ```csharp public class AddPackageCommand : Command { - public override int Execute(CommandContext context, AddPackageSettings settings) + public override int Execute(CommandContext context, AddPackageSettings settings, CancellationToken cancellationToken) { // Omitted return 0; @@ -70,7 +70,7 @@ public class AddPackageCommand : Command public class AddReferenceCommand : Command { - public override int Execute(CommandContext context, AddReferenceSettings settings) + public override int Execute(CommandContext context, AddReferenceSettings settings, CancellationToken cancellationToken) { // Omitted return 0; diff --git a/docs/input/cli/unit-testing.md b/docs/input/cli/unit-testing.md index bef67f362..d174737cd 100644 --- a/docs/input/cli/unit-testing.md +++ b/docs/input/cli/unit-testing.md @@ -40,7 +40,7 @@ The following example validates the exit code and terminal output of a `Spectre. _console = console; } - public override int Execute(CommandContext context) + public override int Execute(CommandContext context, CancellationToken cancellationToken) { _console.WriteLine("Hello world."); return 0; @@ -78,7 +78,7 @@ public sealed class InteractiveCommandTests _console = console; } - public override int Execute(CommandContext context) + public override int Execute(CommandContext context, CancellationToken cancellationToken) { var fruits = _console.Prompt( new MultiSelectionPrompt() From 4562f014ac711f1f4771111ef3e8b8f16ccf8d97 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Sun, 26 Oct 2025 17:45:07 +0100 Subject: [PATCH 06/22] Update dependencies --- src/Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 38a6b3a28..f6f7d849e 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -4,7 +4,7 @@ - + @@ -17,7 +17,7 @@ - + From 64c31f5b76c61789dc87a4d2984c222558448641 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Sun, 26 Oct 2025 17:50:15 +0100 Subject: [PATCH 07/22] Update GitHub Actions dependencies --- .github/workflows/ci.yaml | 2 +- .github/workflows/publish.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a434b93d0..e3aa89210 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -37,7 +37,7 @@ jobs: - name: Upload Verify Test Results if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: verify-test-results path: | diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 6d94dc560..983948e38 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -61,7 +61,7 @@ jobs: uses: actions/setup-dotnet@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version: '22' From 5dcf72cb8fb10dd27d4d969aadfed3a95f4b040e Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Sun, 26 Oct 2025 17:50:26 +0100 Subject: [PATCH 08/22] Update generator dependencies --- resources/scripts/Generator/Generator.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/scripts/Generator/Generator.csproj b/resources/scripts/Generator/Generator.csproj index cb7b969c8..cfb7586d5 100644 --- a/resources/scripts/Generator/Generator.csproj +++ b/resources/scripts/Generator/Generator.csproj @@ -47,7 +47,7 @@ - + From 5af8e0911132955520b49e1ebc89d611c70d960e Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Sun, 26 Oct 2025 17:50:35 +0100 Subject: [PATCH 09/22] Update .NET SDK version --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index c8af6e927..0f15a22eb 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "$schema": "http://json.schemastore.org/global", "sdk": { - "version": "9.0.305", + "version": "9.0.306", "rollForward": "latestFeature" } } From 010beffae042a039daa273c3bae41643ad3c04ef Mon Sep 17 00:00:00 2001 From: Phil Scott Date: Mon, 10 Feb 2025 20:57:38 -0500 Subject: [PATCH 10/22] Normalizes paths when writing exceptions to the console for tests. The verified output for Should_Write_GenericException was outputting ProjectDirectory}Data\Exceptions.cs on my Windows machine, but the Verified version wasProjectDirectory}Data/Exceptions.cs Wasn't causing a build issue because we run those on Ubuntu, but locally it was giving me an error. --- .../TestConsoleExtensions.Exceptions.cs | 59 ------------------- .../Utilities/TestConsoleExtensions.cs | 41 +++++++++++++ 2 files changed, 41 insertions(+), 59 deletions(-) delete mode 100644 src/Spectre.Console.Testing/Extensions/TestConsoleExtensions.Exceptions.cs create mode 100644 src/Tests/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs diff --git a/src/Spectre.Console.Testing/Extensions/TestConsoleExtensions.Exceptions.cs b/src/Spectre.Console.Testing/Extensions/TestConsoleExtensions.Exceptions.cs deleted file mode 100644 index 582ddf182..000000000 --- a/src/Spectre.Console.Testing/Extensions/TestConsoleExtensions.Exceptions.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace Spectre.Console.Testing; - -/// -/// Provides extension methods for working with in a testing context, -/// including stack trace normalization for consistent and deterministic test output. -/// -public static partial class TestConsoleExtensions -{ - private static readonly Regex _lineNumberRegex = new Regex(":\\d+", RegexOptions.Singleline); - private static readonly Regex _filenameRegex = new Regex("\\sin\\s.*cs:nn", RegexOptions.Multiline); - - /// - /// Writes the given exception to the and returns a normalized string - /// representation of the exception, with file paths and line numbers sanitized. - /// - /// The to write to. - /// The exception to write and normalize. - /// Optional formatting options for exception output. - /// A normalized string of the exception's output, safe for snapshot testing. - /// - /// Thrown if the console's output buffer is not empty before writing the exception. - /// - public static string WriteNormalizedException(this TestConsole console, Exception ex, ExceptionFormats formats = ExceptionFormats.Default) - { - if (!string.IsNullOrWhiteSpace(console.Output)) - { - throw new InvalidOperationException("Output buffer is not empty."); - } - - console.WriteException(ex, formats); - return string.Join("\n", NormalizeStackTrace(console.Output) - .NormalizeLineEndings() - .Split(new char[] { '\n' }) - .Select(line => line.TrimEnd())); - } - - /// - /// Normalizes a stack trace string by replacing line numbers with ":nn" - /// and converting full file paths to a fixed placeholder path ("/xyz/filename.cs"). - /// - /// The stack trace text to normalize. - /// A sanitized stack trace suitable for stable testing output. - public static string NormalizeStackTrace(string text) - { - text = _lineNumberRegex.Replace(text, match => - { - return ":nn"; - }); - - return _filenameRegex.Replace(text, match => - { - var value = match.Value; - var index = value.LastIndexOfAny(new[] { '\\', '/' }); - var filename = value.Substring(index + 1, value.Length - index - 1); - - return $" in /xyz/{filename}"; - }); - } -} diff --git a/src/Tests/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs b/src/Tests/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs new file mode 100644 index 000000000..8617ebca2 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs @@ -0,0 +1,41 @@ +namespace Spectre.Console.Tests; + +public static class TestConsoleExtensions +{ + private static readonly Regex _lineNumberRegex = new Regex(":\\d+", RegexOptions.Singleline); + private static readonly Regex _filenameRegex = new Regex("\\sin\\s.*cs:nn", RegexOptions.Multiline); + private static readonly Regex _pathSeparatorRegex = new Regex(@"[/\\]+"); + + public static string WriteNormalizedException(this TestConsole console, Exception ex, ExceptionFormats formats = ExceptionFormats.Default) + { + if (!string.IsNullOrWhiteSpace(console.Output)) + { + throw new InvalidOperationException("Output buffer is not empty."); + } + + console.WriteException(ex, formats); + return string.Join("\n", NormalizeStackTrace(console.Output) + .NormalizeLineEndings() + .Split(new char[] { '\n' }) + .Select(line => line.TrimEnd())); + } + + public static string NormalizeStackTrace(string text) + { + // First normalize line numbers + text = _lineNumberRegex.Replace(text, ":nn"); + + // Then normalize paths and filenames + text = _filenameRegex.Replace(text, match => + { + var value = match.Value; + var index = value.LastIndexOfAny(new[] { '\\', '/' }); + var filename = value.Substring(index + 1, value.Length - index - 1); + + return $" in /xyz/{filename}"; + }); + + // Finally normalize any remaining path separators + return _pathSeparatorRegex.Replace(text, "/"); + } +} From 1ec7b8ae8f756e59ec65048ba8e7b11bda6c053b Mon Sep 17 00:00:00 2001 From: Phil Scott Date: Fri, 31 Oct 2025 10:53:57 -0400 Subject: [PATCH 11/22] Fixes issue with Panel not applying overflow to children Add tests for widget content overflow scenarios in Panel, Table, and Grid widgets. --- src/Spectre.Console/Widgets/Panel.cs | 13 +- ...r_Cell_Markup_Overflow.Output.verified.txt | 3 + ...der_Cell_Overflow_Crop.Output.verified.txt | 3 + ...Cell_Overflow_Ellipsis.Output.verified.txt | 3 + ...der_Cell_Overflow_Fold.Output.verified.txt | 5 + ...l_Overflow_With_NoWrap.Output.verified.txt | 3 + ...rkup_Overflow_Ellipsis.Output.verified.txt | 5 + ...ed_Panel_With_Overflow.Output.verified.txt | 7 + ...der_Text_Overflow_Crop.Output.verified.txt | 5 + ...Text_Overflow_Ellipsis.Output.verified.txt | 5 + ...der_Text_Overflow_Fold.Output.verified.txt | 7 + ..._Overflow_With_Padding.Output.verified.txt | 5 + ...r_Cell_Markup_Overflow.Output.verified.txt | 7 + ...der_Cell_Overflow_Crop.Output.verified.txt | 7 + ...Cell_Overflow_Ellipsis.Output.verified.txt | 7 + ...der_Cell_Overflow_Fold.Output.verified.txt | 9 ++ ...Overflow_Multiple_Rows.Output.verified.txt | 11 ++ ...l_Overflow_With_NoWrap.Output.verified.txt | 7 + .../Unit/Widgets/GridTests.cs | 100 ++++++++++++++ .../Unit/Widgets/PanelTests.cs | 125 +++++++++++++++++ .../Unit/Widgets/Table/TableTests.cs | 126 ++++++++++++++++++ 21 files changed, 457 insertions(+), 6 deletions(-) create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt diff --git a/src/Spectre.Console/Widgets/Panel.cs b/src/Spectre.Console/Widgets/Panel.cs index 7a34d9592..7fd0620b8 100644 --- a/src/Spectre.Console/Widgets/Panel.cs +++ b/src/Spectre.Console/Widgets/Panel.cs @@ -83,12 +83,13 @@ private Measurement Measure(RenderOptions options, int maxWidth, IRenderable chi if (Width != null) { var width = Width.Value - edgeWidth; - if (width > childWidth.Max) - { - childWidth = new Measurement( - childWidth.Min, - width); - } + + // If Width is specified, constrain or expand the measurement + // to exactly the specified width (clamped by maxWidth) + var constrainedWidth = Math.Min(width, maxWidth - edgeWidth); + childWidth = new Measurement( + Math.Min(childWidth.Min, constrainedWidth), + constrainedWidth); } return new Measurement( diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt new file mode 100644 index 000000000..5cc383515 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt @@ -0,0 +1,3 @@ +foo Short text +pneumonoultramicr… +bar diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt new file mode 100644 index 000000000..f1f82d196 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt @@ -0,0 +1,3 @@ +foo Short text +pneumonoultrami +bar diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt new file mode 100644 index 000000000..127535510 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt @@ -0,0 +1,3 @@ +foo Short text +pneumonoultram… +bar diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt new file mode 100644 index 000000000..b04f31311 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt @@ -0,0 +1,5 @@ +foo Short text +pneumonoultrami +croscopicsilico +volcanoconiosis +bar diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt new file mode 100644 index 000000000..127535510 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt @@ -0,0 +1,3 @@ +foo Short text +pneumonoultram… +bar diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt new file mode 100644 index 000000000..b73f65d10 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt @@ -0,0 +1,5 @@ +┌──────────────────┐ +│ foo │ +│ pneumonoultrami… │ +│ bar qux │ +└──────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt new file mode 100644 index 000000000..3a6e9b27a --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt @@ -0,0 +1,7 @@ +┌───────────────────────┐ +│ ┌─────────────┐ │ +│ │ foo │ │ +│ │ pneumonoult │ │ +│ │ bar qux │ │ +│ └─────────────┘ │ +└───────────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt new file mode 100644 index 000000000..079270650 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt @@ -0,0 +1,5 @@ +┌──────────────────┐ +│ foo │ +│ pneumonoultramic │ +│ bar qux │ +└──────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt new file mode 100644 index 000000000..b73f65d10 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt @@ -0,0 +1,5 @@ +┌──────────────────┐ +│ foo │ +│ pneumonoultrami… │ +│ bar qux │ +└──────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt new file mode 100644 index 000000000..8f0c51fb0 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt @@ -0,0 +1,7 @@ +┌──────────────────┐ +│ foo │ +│ pneumonoultramic │ +│ roscopicsilicovo │ +│ lcanoconiosis │ +│ bar qux │ +└──────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt new file mode 100644 index 000000000..6f4fa4d96 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt @@ -0,0 +1,5 @@ +┌───────────────────────┐ +│ foo │ +│ pneumonoultramicro… │ +│ bar qux │ +└───────────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt new file mode 100644 index 000000000..1fb1ad3f6 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt @@ -0,0 +1,7 @@ +┌────────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├────────────────────┼─────────────────┤ +│ foo │ Short text │ +│ pneumonoultramicr… │ │ +│ bar │ │ +└────────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt new file mode 100644 index 000000000..d73678d37 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt @@ -0,0 +1,7 @@ +┌─────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├─────────────────┼─────────────────┤ +│ foo │ Short text │ +│ pneumonoultrami │ │ +│ bar │ │ +└─────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt new file mode 100644 index 000000000..69623fbbe --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt @@ -0,0 +1,7 @@ +┌─────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├─────────────────┼─────────────────┤ +│ foo │ Short text │ +│ pneumonoultram… │ │ +│ bar │ │ +└─────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt new file mode 100644 index 000000000..a20cf4889 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt @@ -0,0 +1,9 @@ +┌─────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├─────────────────┼─────────────────┤ +│ foo │ Short text │ +│ pneumonoultrami │ │ +│ croscopicsilico │ │ +│ volcanoconiosis │ │ +│ bar │ │ +└─────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt new file mode 100644 index 000000000..65711330e --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt @@ -0,0 +1,11 @@ +┌─────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├─────────────────┼─────────────────┤ +│ foo │ First row │ +│ pneumonoultrami │ │ +│ bar │ Second row │ +│ supercalifragi… │ │ +│ qux │ Third row │ +│ antidisestablis │ │ +│ hmentarianism │ │ +└─────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt new file mode 100644 index 000000000..69623fbbe --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt @@ -0,0 +1,7 @@ +┌─────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├─────────────────┼─────────────────┤ +│ foo │ Short text │ +│ pneumonoultram… │ │ +│ bar │ │ +└─────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/GridTests.cs b/src/Tests/Spectre.Console.Tests/Unit/Widgets/GridTests.cs index 4644790c8..3a25db3f7 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/GridTests.cs +++ b/src/Tests/Spectre.Console.Tests/Unit/Widgets/GridTests.cs @@ -192,4 +192,104 @@ public Task Should_Render_Explicit_Grid_Column_Padding_Correctly() // Then return Verifier.Verify(console.Output); } + + [Fact] + [Expectation("Render_Cell_Overflow_Crop")] + public Task Should_Respect_Cell_Content_Overflow_Crop() + { + // Given + var console = new TestConsole().Width(40); + var grid = new Grid(); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Crop), + new Text("Short text")); + + // When + console.Write(grid); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_Ellipsis")] + public Task Should_Respect_Cell_Content_Overflow_Ellipsis() + { + // Given + var console = new TestConsole().Width(40); + var grid = new Grid(); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Ellipsis), + new Text("Short text")); + + // When + console.Write(grid); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_Fold")] + public Task Should_Respect_Cell_Content_Overflow_Fold() + { + // Given + var console = new TestConsole().Width(40); + var grid = new Grid(); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Fold), + new Text("Short text")); + + // When + console.Write(grid); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Markup_Overflow")] + public Task Should_Respect_Markup_Content_Overflow_In_Cell() + { + // Given + var console = new TestConsole().Width(40); + var grid = new Grid(); + grid.AddColumn(new GridColumn { Width = 18 }); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddRow( + new Markup("[yellow]foo[/] [red]pneumonoultramicroscopicsilicovolcanoconiosis[/] [blue]bar[/]").Overflow(Overflow.Ellipsis), + new Markup("[green]Short text[/]")); + + // When + console.Write(grid); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_With_NoWrap")] + public Task Should_Respect_Cell_Content_Overflow_With_NoWrap_Column() + { + // Given + var console = new TestConsole().Width(40); + var grid = new Grid(); + grid.AddColumn(new GridColumn { Width = 15, NoWrap = true }); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Ellipsis), + new Text("Short text")); + + // When + console.Write(grid); + + // Then + return Verifier.Verify(console.Output); + } } diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs b/src/Tests/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs index 3d042fae4..e698aecb2 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs +++ b/src/Tests/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs @@ -366,4 +366,129 @@ public Task Should_Wrap_Table_With_CJK_Tables_In_Panel_Correctly() // Then return Verifier.Verify(console.Output); } + + [Fact] + [Expectation("Render_Text_Overflow_Crop")] + public Task Should_Respect_Text_Overflow_Crop_In_Panel() + { + // Given + var console = new TestConsole(); + var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux") + .Overflow(Overflow.Crop); + var panel = new Panel(text) + { + Width = 20, + }; + + // When + console.Write(panel); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Text_Overflow_Ellipsis")] + public Task Should_Respect_Text_Overflow_Ellipsis_In_Panel() + { + // Given + var console = new TestConsole(); + var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux") + .Overflow(Overflow.Ellipsis); + var panel = new Panel(text) + { + Width = 20, + }; + + // When + console.Write(panel); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Text_Overflow_Fold")] + public Task Should_Respect_Text_Overflow_Fold_In_Panel() + { + // Given + var console = new TestConsole(); + var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux") + .Overflow(Overflow.Fold); + var panel = new Panel(text) + { + Width = 20, + }; + + // When + console.Write(panel); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Markup_Overflow_Ellipsis")] + public Task Should_Respect_Markup_Overflow_Ellipsis_In_Panel() + { + // Given + var console = new TestConsole(); + var markup = new Markup("[yellow]foo[/] [red]pneumonoultramicroscopicsilicovolcanoconiosis[/] [blue]bar qux[/]") + .Overflow(Overflow.Ellipsis); + var panel = new Panel(markup) + { + Width = 20, + }; + + // When + console.Write(panel); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Text_Overflow_With_Padding")] + public Task Should_Respect_Text_Overflow_In_Panel_With_Padding() + { + // Given + var console = new TestConsole(); + var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux") + .Overflow(Overflow.Ellipsis); + var panel = new Panel(text) + { + Width = 25, + Padding = new Padding(2, 0, 2, 0), + }; + + // When + console.Write(panel); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Nested_Panel_With_Overflow")] + public Task Should_Respect_Text_Overflow_In_Nested_Panel() + { + // Given + var console = new TestConsole(); + var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux") + .Overflow(Overflow.Crop); + var innerPanel = new Panel(text) + { + Width = 15, + }; + var outerPanel = new Panel(innerPanel) + { + Width = 25, + }; + + // When + console.Write(outerPanel); + + // Then + return Verifier.Verify(console.Output); + } } diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs b/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs index 18379bdcd..4c26b7aa0 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs +++ b/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs @@ -631,4 +631,130 @@ public Task Should_Render_Empty_Column_Correctly() // Then return Verifier.Verify(console.Output); } + + [Fact] + [Expectation("Render_Cell_Overflow_Crop")] + public Task Should_Respect_Cell_Content_Overflow_Crop() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(15)); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Crop), + new Text("Short text")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_Ellipsis")] + public Task Should_Respect_Cell_Content_Overflow_Ellipsis() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(15)); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Ellipsis), + new Text("Short text")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_Fold")] + public Task Should_Respect_Cell_Content_Overflow_Fold() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(15)); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Fold), + new Text("Short text")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Markup_Overflow")] + public Task Should_Respect_Markup_Content_Overflow_In_Cell() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(18)); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Markup("[yellow]foo[/] [red]pneumonoultramicroscopicsilicovolcanoconiosis[/] [blue]bar[/]").Overflow(Overflow.Ellipsis), + new Markup("[green]Short text[/]")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_Multiple_Rows")] + public Task Should_Respect_Cell_Content_Overflow_In_Multiple_Rows() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(15)); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis").Overflow(Overflow.Crop), + new Text("First row")); + table.AddRow( + new Text("bar supercalifragilisticexpialidocious").Overflow(Overflow.Ellipsis), + new Text("Second row")); + table.AddRow( + new Text("qux antidisestablishmentarianism").Overflow(Overflow.Fold), + new Text("Third row")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_With_NoWrap")] + public Task Should_Respect_Cell_Content_Overflow_With_NoWrap_Column() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(15).NoWrap()); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Ellipsis), + new Text("Short text")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } } From 45799107a394f2160807ceec42a23bf4866766c4 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Sun, 26 Oct 2025 22:32:22 +0100 Subject: [PATCH 12/22] Remove Spectre.Console.Cli from repository * Move Spectre.Console.Cli to its own repository * Update build script to use Cake.Sdk and .NET Make * Remove StyleCop (unmaintained) * Add linting using dotnet format * Fix generator which was broken * Update dependencies --- .editorconfig | 153 +- .github/workflows/ci.yaml | 3 +- .github/workflows/publish.yaml | 3 +- README.md | 21 - README.pt-BR.md | 28 +- README.zh.md | 27 +- build.cake => build.cs | 63 +- docs/Program.cs | 1 - docs/input/cli/commandApp.md | 5 +- docs/input/cli/commands.md | 3 - docs/input/cli/settings.md | 4 - docs/input/cli/unit-testing.md | 4 - dotnet-tools.json | 16 +- global.json | 2 +- resources/nuget/Spectre.Console.Cli.md | 5 - resources/scripts/Generate-Colors.ps1 | 5 +- resources/scripts/Generate-Emoji.ps1 | 5 +- resources/scripts/Generate-Samples.ps1 | 15 +- resources/scripts/Generate-Spinners.ps1 | 7 +- .../AsciiCast/AnsiConsoleExtensions.cs | 33 - .../Commands/AsciiCast/AsciiCastConsole.cs | 40 - .../Commands/AsciiCast/AsciiCastExtensions.cs | 15 - .../Commands/AsciiCast/AsciiCastInput.cs | 92 -- .../Commands/AsciiCast/AsciiCastOut.cs | 95 -- .../AsciiCast/Samples/BarChartSample.cs | 20 - .../Commands/AsciiCast/Samples/BaseSample.cs | 61 - .../AsciiCast/Samples/BreakdownChartSample.cs | 21 - .../AsciiCast/Samples/CalendarSamples.cs | 40 - .../AsciiCast/Samples/CanvasImageSample.cs | 27 - .../AsciiCast/Samples/CanvasSample.cs | 29 - .../Commands/AsciiCast/Samples/Exceptions.cs | 81 -- .../AsciiCast/Samples/FigletSample.cs | 16 - .../Commands/AsciiCast/Samples/InputSample.cs | 97 -- .../Commands/AsciiCast/Samples/JsonSample.cs | 39 - .../AsciiCast/Samples/LayoutSample.cs | 30 - .../Commands/AsciiCast/Samples/LiveSample.cs | 84 -- .../AsciiCast/Samples/MultiSelectionSample.cs | 40 - .../Commands/AsciiCast/Samples/PanelSample.cs | 16 - .../AsciiCast/Samples/ProgressSample.cs | 87 -- .../Commands/AsciiCast/Samples/RuleSample.cs | 21 - .../AsciiCast/Samples/SelectionSample.cs | 29 - .../AsciiCast/Samples/StatusSample.cs | 71 - .../Commands/AsciiCast/Samples/TableSample.cs | 46 - .../AsciiCast/Samples/TextPathSample.cs | 44 - .../Commands/AsciiCast/Samples/TreeSample.cs | 39 - .../Commands/ColorGeneratorCommand.cs | 59 - .../Commands/EmojiGeneratorCommand.cs | 107 -- .../Generator/Commands/GeneratorSettings.cs | 10 - .../Generator/Commands/SampleCommand.cs | 101 -- .../Commands/SpinnerGeneratorCommand.cs | 47 - resources/scripts/Generator/Generator.csproj | 59 - resources/scripts/Generator/Models/Color.cs | 79 - .../scripts/Generator/Models/ColorModel.cs | 14 - resources/scripts/Generator/Models/Emoji.cs | 95 -- resources/scripts/Generator/Models/Palette.cs | 6 - resources/scripts/Generator/Models/Spinner.cs | 31 - resources/scripts/Generator/Program.cs | 22 - src/.editorconfig | 150 ++ src/Directory.Build.props | 7 - src/Directory.Build.targets | 8 - src/Directory.Packages.props | 8 +- .../Spectre.Console.Json/IJsonParser.cs | 2 +- .../Spectre.Console.Json/JsonParser.cs | 2 +- .../Spectre.Console.Json/JsonText.cs | 2 +- .../JsonTextExtensions.cs | 2 +- .../Spectre.Console.Json/JsonTextStyles.cs | 2 +- .../Spectre.Console.Json/JsonToken.cs | 2 +- .../Spectre.Console.Json/JsonTokenReader.cs | 2 +- .../Spectre.Console.Json/JsonTokenType.cs | 2 +- .../Spectre.Console.Json/JsonTokenizer.cs | 4 +- .../Syntax/JsonBoolean.cs | 2 +- .../Spectre.Console.Json/Syntax/JsonMember.cs | 2 +- .../Spectre.Console.Json/Syntax/JsonNull.cs | 2 +- .../Spectre.Console.Json/Syntax/JsonNumber.cs | 2 +- .../Spectre.Console.Json/Syntax/JsonObject.cs | 2 +- .../Spectre.Console.Json/Syntax/JsonString.cs | 2 +- .../Spectre.Console.Json/Syntax/JsonSyntax.cs | 2 +- .../Syntax/JsonSyntaxVisitor.cs | 2 +- .../AsciiCast/AnsiConsoleExtensions.cs | 32 + .../Commands/AsciiCast/AsciiCastConsole.cs | 39 + .../Commands/AsciiCast/AsciiCastExtensions.cs | 14 + .../Commands/AsciiCast/AsciiCastInput.cs | 91 ++ .../Commands/AsciiCast/AsciiCastOut.cs | 94 ++ .../AsciiCast/Samples/AwaitSpinnerSample.cs | 2 +- .../AsciiCast/Samples/BarChartSample.cs | 19 + .../Commands/AsciiCast/Samples/BaseSample.cs | 60 + .../AsciiCast/Samples/BreakdownChartSample.cs | 20 + .../AsciiCast/Samples/CalendarSamples.cs | 39 + .../AsciiCast/Samples/CanvasImageSample.cs | 26 + .../AsciiCast/Samples/CanvasSample.cs | 28 + .../AsciiCast/Samples/ColumnsSample.cs | 6 +- .../Commands/AsciiCast/Samples/Exceptions.cs | 80 ++ .../AsciiCast/Samples/FigletSample.cs | 15 + .../Commands/AsciiCast/Samples/InputSample.cs | 96 ++ .../Commands/AsciiCast/Samples/JsonSample.cs | 38 + .../AsciiCast/Samples/LayoutSample.cs | 28 + .../Commands/AsciiCast/Samples/LiveSample.cs | 83 ++ .../AsciiCast/Samples/MultiSelectionSample.cs | 39 + .../Commands/AsciiCast/Samples/PanelSample.cs | 15 + .../AsciiCast/Samples/ProgressSample.cs | 87 ++ .../Commands/AsciiCast/Samples/RuleSample.cs | 20 + .../AsciiCast/Samples/SelectionSample.cs | 28 + .../AsciiCast/Samples/StatusSample.cs | 71 + .../Commands/AsciiCast/Samples/TableSample.cs | 45 + .../AsciiCast/Samples/TextPathSample.cs | 42 + .../Commands/AsciiCast/Samples/TreeSample.cs | 38 + .../Commands/ColorGeneratorCommand.cs | 73 + .../Commands/EmojiGeneratorCommand.cs | 106 ++ src/Generator/Commands/GeneratorSettings.cs | 9 + src/Generator/Commands/SampleCommand.cs | 100 ++ .../Commands/SpinnerGeneratorCommand.cs | 56 + src/Generator/Data/cake.png | Bin 0 -> 52832 bytes .../Generator/Data/colors.json | 0 .../Generator/Data/spinners_default.json | 0 .../Generator/Data/spinners_sindresorhus.json | 0 src/Generator/Generator.csproj | 42 + .../scripts => src}/Generator/Generator.slnx | 3 +- src/Generator/Models/Color.cs | 82 ++ src/Generator/Models/ColorModel.cs | 13 + src/Generator/Models/Emoji.cs | 94 ++ src/Generator/Models/Palette.cs | 5 + src/Generator/Models/Spinner.cs | 32 + src/Generator/Program.cs | 21 + .../Templates/Color.Generated.template | 0 .../Templates/ColorPalette.Generated.template | 12 +- .../Templates/ColorTable.Generated.template | 0 .../Templates/Emoji.Generated.template | 0 .../Generator/Templates/Emoji.Json.template | 0 .../Templates/Spinner.Generated.template | 0 .../Annotations/CommandArgumentAttribute.cs | 50 - .../Annotations/CommandOptionAttribute.cs | 72 - .../Annotations/PairDeconstructorAttribute.cs | 28 - .../ParameterValidationAttribute.cs | 31 - .../ParameterValueProviderAttribute.cs | 17 - src/Spectre.Console.Cli/AsyncCommand.cs | 33 - src/Spectre.Console.Cli/AsyncCommandOfT.cs | 48 - src/Spectre.Console.Cli/CaseSensitivity.cs | 28 - src/Spectre.Console.Cli/Command.cs | 34 - src/Spectre.Console.Cli/CommandApp.cs | 155 -- .../CommandAppException.cs | 26 - src/Spectre.Console.Cli/CommandAppOfT.cs | 72 - .../CommandConfigurationException.cs | 76 - src/Spectre.Console.Cli/CommandContext.cs | 55 - src/Spectre.Console.Cli/CommandOfT.cs | 49 - .../CommandParameterContext.cs | 35 - .../CommandParseException.cs | 121 -- .../CommandRuntimeException.cs | 71 - src/Spectre.Console.Cli/CommandSettings.cs | 16 - .../CommandTemplateException.cs | 156 -- .../ConfiguratorExtensions.cs | 437 ------ .../EmptyCommandSettings.cs | 8 - src/Spectre.Console.Cli/FlagValue.cs | 55 - src/Spectre.Console.Cli/Help/HelpProvider.cs | 620 -------- .../Help/HelpProviderResources.cs | 131 -- .../Help/HelpProviderStyles.cs | 224 --- .../Help/ICommandArgument.cs | 17 - .../Help/ICommandContainer.cs | 25 - src/Spectre.Console.Cli/Help/ICommandInfo.cs | 42 - .../Help/ICommandInfoExtensions.cs | 23 - src/Spectre.Console.Cli/Help/ICommandModel.cs | 17 - .../Help/ICommandOption.cs | 27 - .../Help/ICommandParameter.cs | 32 - src/Spectre.Console.Cli/Help/IHelpProvider.cs | 20 - .../IBranchConfigurator.cs | 14 - src/Spectre.Console.Cli/ICommand.cs | 24 - src/Spectre.Console.Cli/ICommandApp.cs | 29 - .../ICommandAppSettings.cs | 109 -- .../ICommandConfigurator.cs | 43 - .../ICommandInterceptor.cs | 36 - src/Spectre.Console.Cli/ICommandLimiterOfT.cs | 11 - src/Spectre.Console.Cli/ICommandOfT.cs | 18 - .../ICommandParameterInfo.cs | 24 - src/Spectre.Console.Cli/IConfigurator.cs | 73 - src/Spectre.Console.Cli/IConfiguratorOfT.cs | 79 - src/Spectre.Console.Cli/IFlagValue.cs | 22 - .../IRemainingArguments.cs | 18 - src/Spectre.Console.Cli/ITypeRegistrar.cs | 35 - .../ITypeRegistrarFrontend.cs | 31 - src/Spectre.Console.Cli/ITypeResolver.cs | 14 - .../Binding/CommandConstructorBinder.cs | 57 - .../Internal/Binding/CommandPropertyBinder.cs | 41 - .../Internal/Binding/CommandValueBinder.cs | 120 -- .../Internal/Binding/CommandValueLookup.cs | 57 - .../Internal/Binding/CommandValueResolver.cs | 229 --- .../Internal/Collections/IMultiMap.cs | 13 - .../Internal/Collections/MultiMap.cs | 168 --- .../Internal/CommandBinder.cs | 28 - .../Internal/CommandExecutor.cs | 273 ---- .../Internal/CommandPart.cs | 7 - .../Internal/CommandSuggestor.cs | 73 - .../Internal/CommandValidator.cs | 47 - .../Internal/Commands/ExplainCommand.cs | 257 ---- .../Internal/Commands/IBuiltInCommand.cs | 9 - .../Commands/OpenCliGeneratorCommand.cs | 224 --- .../Internal/Commands/VersionCommand.cs | 26 - .../Internal/Commands/XmlDocCommand.cs | 199 --- src/Spectre.Console.Cli/Internal/Composer.cs | 143 -- .../Internal/Composition/Activators.cs | 128 -- .../Composition/ComponentRegistration.cs | 27 - .../Internal/Composition/ComponentRegistry.cs | 56 - .../Composition/DefaultTypeRegistrar.cs | 51 - .../Composition/DefaultTypeResolver.cs | 62 - .../Configuration/BranchConfigurator.cs | 17 - .../Configuration/CommandAppSettings.cs | 58 - .../Configuration/CommandConfigurator.cs | 41 - .../Configuration/ConfigurationHelper.cs | 38 - .../Internal/Configuration/Configurator.cs | 117 -- .../Internal/Configuration/ConfiguratorOfT.cs | 111 -- .../Configuration/ConfiguredCommand.cs | 68 - .../DefaultCommandConfigurator.cs | 36 - .../Internal/Configuration/IConfiguration.cs | 27 - .../Internal/Configuration/TemplateParser.cs | 146 -- .../Internal/Configuration/TemplateToken.cs | 26 - .../Configuration/TemplateTokenizer.cs | 131 -- src/Spectre.Console.Cli/Internal/Constants.cs | 24 - .../Internal/DefaultPairDeconstructor.cs | 71 - .../Internal/DelegateCommand.cs | 21 - .../CommandLineParseExceptionFactory.cs | 48 - .../CommandLineTemplateExceptionFactory.cs | 54 - .../Extensions/AnsiConsoleExtensions.cs | 37 - .../Extensions/CaseSensitivityExtensions.cs | 32 - .../Extensions/EnumerableExtensions.cs | 14 - .../Internal/Extensions/ListExtensions.cs | 51 - .../Internal/Extensions/OpenCliExtensions.cs | 13 - .../Internal/Extensions/StringExtensions.cs | 13 - .../Internal/Extensions/TypeExtensions.cs | 34 - .../Extensions/TypeRegistrarExtensions.cs | 54 - .../Extensions/XmlElementExtensions.cs | 39 - .../Internal/IPairDeconstructor.cs | 21 - .../Internal/Modelling/CommandArgument.cs | 19 - .../Modelling/CommandContainerExtensions.cs | 18 - .../Internal/Modelling/CommandInfo.cs | 58 - .../Modelling/CommandInfoExtensions.cs | 86 -- .../Internal/Modelling/CommandModel.cs | 61 - .../Internal/Modelling/CommandModelBuilder.cs | 247 ---- .../Modelling/CommandModelValidator.cs | 188 --- .../Internal/Modelling/CommandOption.cs | 31 - .../Internal/Modelling/CommandParameter.cs | 151 -- .../Modelling/CommandParameterComparer.cs | 29 - .../Internal/Modelling/ICommandContainer.cs | 20 - .../Internal/Modelling/ParameterKind.cs | 19 - .../Internal/Parsing/CommandTree.cs | 34 - .../Internal/Parsing/CommandTreeExtensions.cs | 66 - .../Internal/Parsing/CommandTreeParser.cs | 419 ------ .../Parsing/CommandTreeParserContext.cs | 48 - .../Parsing/CommandTreeParserResult.cs | 14 - .../Internal/Parsing/CommandTreeToken.cs | 31 - .../Parsing/CommandTreeTokenStream.cs | 86 -- .../Internal/Parsing/CommandTreeTokenizer.cs | 276 ---- .../Parsing/CommandTreeTokenizerContext.cs | 44 - .../Parsing/MappedCommandParameter.cs | 14 - .../Internal/ParsingMode.cs | 7 - .../Internal/RemainingArguments.cs | 15 - .../Internal/StringWriterWithEncoding.cs | 11 - .../Internal/TextBuffer.cs | 89 -- .../Internal/TypeRegistrar.cs | 38 - .../Internal/TypeResolverAdapter.cs | 47 - .../Internal/VersionHelper.cs | 11 - src/Spectre.Console.Cli/PairDeconstructor.cs | 38 - src/Spectre.Console.Cli/Properties/Usings.cs | 17 - .../Resources/HelpProvider.Designer.cs | 153 -- .../Resources/HelpProvider.de.resx | 150 -- .../Resources/HelpProvider.es.resx | 150 -- .../Resources/HelpProvider.fr.resx | 150 -- .../Resources/HelpProvider.it.resx | 150 -- .../Resources/HelpProvider.ja.resx | 150 -- .../Resources/HelpProvider.ko.resx | 150 -- .../Resources/HelpProvider.pt.resx | 150 -- .../Resources/HelpProvider.resx | 150 -- .../Resources/HelpProvider.ru.resx | 150 -- .../Resources/HelpProvider.sv.resx | 150 -- .../Resources/HelpProvider.zh-Hans.resx | 150 -- .../Spectre.Console.Cli.csproj | 52 - .../Unsafe/IUnsafeBranchConfigurator.cs | 19 - .../Unsafe/IUnsafeConfigurator.cs | 24 - .../Unsafe/UnsafeConfiguratorExtensions.cs | 80 -- .../Cli/CallbackCommandInterceptor.cs | 31 - .../Cli/CommandAppFailure.cs | 25 - .../Cli/CommandAppResult.cs | 35 - .../Cli/CommandAppTester.cs | 178 --- .../Cli/CommandAppTesterSettings.cs | 15 - .../Cli/TypeRegistrarBaseTests.cs | 271 ---- .../Extensions/ShouldlyExtensions.cs | 2 +- .../FakeTypeRegistrar.cs | 76 - .../FakeTypeResolver.cs | 73 - .../Properties/Usings.cs | 3 - .../Spectre.Console.Testing.csproj | 1 - .../Spectre.Console.Tests/Data/Exceptions.cs | 4 +- .../Spectre.Console.Tests/Data/example.json | 0 .../Spectre.Console.Tests/Data/poison.flf | 0 .../Spectre.Console.Tests/Data/starwars.flf | 0 .../AlternateScreen/Show.Output.verified.txt | 0 ...ntCannotContainOptions.Output.verified.txt | 0 ...dCharacterInOptionName.Output.verified.txt | 0 ...idCharacterInValueName.Output.verified.txt | 0 ...veMoreThanOneCharacter.Output.verified.txt | 0 ...issingLongAndShortName.Output.verified.txt | 0 ...nValuesAreNotSupported.Output.verified.txt | 0 ...eValuesAreNotSupported.Output.verified.txt | 0 ...esCannotStartWithDigit.Output.verified.txt | 0 .../OptionsMustHaveName.Output.verified.txt | 0 ...MustOnlyBeOneCharacter.Output.verified.txt | 0 .../UnexpectedCharacter.Output.verified.txt | 0 .../UnterminatedValueName.Output.verified.txt | 0 .../ValuesMustHaveName.Output.verified.txt | 0 .../Help/ArgumentOrder.Output.verified.txt | 0 .../Cli/Help/Command.Output.verified.txt | 0 .../Help/CommandExamples.Output.verified.txt | 0 .../Cli/Help/Default.Output.verified.txt | 0 .../Help/DefaultExamples.Output.verified.txt | 0 ...Hidden_Command_Options.Output.verified.txt | 0 .../Help/Hidden_Commands.Output.verified.txt | 0 .../Cli/Help/Leaf.Output.verified.txt | 0 .../Help/NoDescription.Output.verified.txt | 0 .../Cli/Help/Root.Output.verified.txt | 0 .../Cli/Help/RootExamples.Output.verified.txt | 0 .../RootExamples_Children.Output.verified.txt | 0 .../RootExamples_Leafs.Output.verified.txt | 0 .../Test_1.Output.verified.txt | 0 .../Test_2.Output.verified.txt | 0 .../Test_1.Output.verified.txt | 0 .../Test_1.Output.verified.txt | 0 .../Test_1.Output.verified.txt | 0 .../Test_1.Output.verified.txt | 0 .../Test_1.Output.verified.txt | 0 .../Test_1.Output.verified.txt | 0 .../Test_1.Output.verified.txt | 0 .../Test_2.Output.verified.txt | 0 .../Test_1.Output.verified.txt | 0 .../Test_2.Output.verified.txt | 0 .../Test_3.Output.verified.txt | 0 .../Test_4.Output.verified.txt | 0 .../Test_5.Output.verified.txt | 0 .../Test_1.Output.verified.txt | 0 .../Test_2.Output.verified.txt | 0 .../UnknownCommand/Test_1.Output.verified.txt | 0 .../UnknownCommand/Test_2.Output.verified.txt | 0 .../UnknownCommand/Test_3.Output.verified.txt | 0 .../UnknownCommand/Test_4.Output.verified.txt | 0 .../UnknownCommand/Test_5.Output.verified.txt | 0 .../UnknownCommand/Test_6.Output.verified.txt | 0 .../UnknownCommand/Test_7.Output.verified.txt | 0 .../UnknownCommand/Test_8.Output.verified.txt | 0 .../UnknownOption/Test_1.Output.verified.txt | 0 .../UnknownOption/Test_2.Output.verified.txt | 0 ...Hidden_Command_Options.Output.verified.txt | 0 .../Cli/Xml/Test_1.Output.verified.txt | 0 .../Cli/Xml/Test_2.Output.verified.txt | 0 .../Cli/Xml/Test_3.Output.verified.txt | 0 .../Cli/Xml/Test_4.Output.verified.txt | 0 .../Cli}/Xml/Test_5.Output.verified.txt | 0 .../Cli/Xml/Test_6.Output.verified.txt | 0 .../Exception/CallSite.Output.verified.txt | 0 .../Exception/Default.Output.verified.txt | 0 ...tput_exceptionFormats=Default.verified.txt | 0 ...exceptionFormats=ShortenTypes.verified.txt | 0 .../InnerException.Output.verified.txt | 0 .../NoStackTrace.Output.verified.txt | 0 .../Exception/OutParam.Output.verified.txt | 0 .../ShortenedMethods.Output.verified.txt | 0 .../ShortenedTypes.Output.verified.txt | 0 .../Exception/Tuple.Output.verified.txt | 0 .../Render_ReduceWidth.Output.verified.txt | 0 .../Live/Status/Render.Output.verified.txt | 0 .../Text/AcceptChoice.Output.verified.txt | 0 ...AutoComplete_BestMatch.Output.verified.txt | 0 .../AutoComplete_Empty.Output.verified.txt | 0 ...utoComplete_NextChoice.Output.verified.txt | 0 ...omplete_PreviousChoice.Output.verified.txt | 0 .../ChoicesStyleNotSet.Output.verified.txt | 0 .../Text/ChoicesStyleSet.Output.verified.txt | 0 .../Text/ConversionError.Output.verified.txt | 0 .../Text/CustomConverter.Output.verified.txt | 0 .../Text/CustomValidation.Output.verified.txt | 0 .../Text/DefaultValue.Output.verified.txt | 0 ...efaultValueStyleNotSet.Output.verified.txt | 0 .../DefaultValueStyleSet.Output.verified.txt | 0 .../Text/InvalidChoice.Output.verified.txt | 0 .../Prompts/Text/NoSuffix.Output.verified.txt | 0 .../SecretDefaultValue.Output.verified.txt | 0 ...DefaultValueCustomMask.Output.verified.txt | 0 ...etDefaultValueNullMask.Output.verified.txt | 0 ...ValueBackspaceNullMask.Output.verified.txt | 0 .../Box/AsciiBorder.Output.verified.txt | 0 .../Box/DoubleBorder.Output.verified.txt | 0 .../Box/HeavyBorder.Output.verified.txt | 0 .../Borders/Box/NoBorder.Output.verified.txt | 0 .../NoBorder_With_Header.Output.verified.txt | 0 .../Box/RoundedBorder.Output.verified.txt | 0 .../Box/SquareBorder.Output.verified.txt | 0 .../Table/Ascii2Border.Output.verified.txt | 0 .../Table/AsciiBorder.Output.verified.txt | 0 .../AsciiDoubleHeadBorder.Output.verified.txt | 0 .../Table/DoubleBorder.Output.verified.txt | 0 .../DoubleEdgeBorder.Output.verified.txt | 0 .../Table/HeavyBorder.Output.verified.txt | 0 .../Table/HeavyEdgeBorder.Output.verified.txt | 0 .../Table/HeavyHeadBorder.Output.verified.txt | 0 .../HorizontalBorder.Output.verified.txt | 0 .../Table/MarkdownBorder.Output.verified.txt | 0 ...arkdownBorder_Centered.Output.verified.txt | 0 ...downBorder_LeftAligned.Output.verified.txt | 0 ...ownBorder_RightAligned.Output.verified.txt | 0 .../Table/MinimalBorder.Output.verified.txt | 0 ...inimalDoubleHeadBorder.Output.verified.txt | 0 ...MinimalHeavyHeadBorder.Output.verified.txt | 0 .../Table/NoBorder.Output.verified.txt | 0 .../Table/RoundedBorder.Output.verified.txt | 0 .../Table/SimpleBorder.Output.verified.txt | 0 .../SimpleHeavyBorder.Output.verified.txt | 0 .../Table/SquareBorder.Output.verified.txt | 0 ...pdateMethod.Should_Update_Row.verified.txt | 0 ...ld_Update_Row_With_Renderable.verified.txt | 0 ...Should_Update_Row_With_String.verified.txt | 0 .../Align/Center_Bottom.Output.verified.txt | 0 .../Align/Center_Middle.Output.verified.txt | 0 .../Align/Center_Top.Output.verified.txt | 0 .../Align/Left_Bottom.Output.verified.txt | 0 .../Align/Left_Middle.Output.verified.txt | 0 .../Align/Left_Top.Output.verified.txt | 0 .../Align/Right_Bottom.Output.verified.txt | 0 .../Align/Right_Middle.Output.verified.txt | 0 .../Align/Right_Top.Output.verified.txt | 0 .../Fixed_Max_Value.Output.verified.txt | 0 .../BarChart/Render.Output.verified.txt | 0 .../BarChart/Zero_Value.Output.verified.txt | 0 .../BreakdownChart/Ansi.Output.verified.txt | 0 .../Culture.Output.verified.txt | 0 .../Default.Output.verified.txt | 0 .../FullSize.Output.verified.txt | 0 .../HideTagValues.Output.verified.txt | 0 .../HideTags.Output.verified.txt | 0 .../TagFormat.Output.verified.txt | 0 .../ValueColor.Output.verified.txt | 0 .../BreakdownChart/Width.Output.verified.txt | 0 .../Calendar/Centered.Output.verified.txt | 0 .../Calendar/Culture.Output.verified.txt | 0 .../Calendar/LeftAligned.Output.verified.txt | 0 .../Calendar/Render.Output.verified.txt | 0 .../Calendar/RightAligned.Output.verified.txt | 0 .../Widgets/Canvas/Render.Output.verified.txt | 0 .../Render_MaxWidth.Output.verified.txt | 0 .../Render_NarrowTerminal.Output.verified.txt | 0 .../Canvas/Render_Nested.Output.verified.txt | 0 .../Columns/Render.Output.verified.txt | 0 ...am.Output_fontfile=poison.flf.verified.txt | 0 ....Output_fontfile=starwars.flf.verified.txt | 0 .../Widgets/Figlet/Render.Output.verified.txt | 0 .../Render_Centered.Output.verified.txt | 0 .../Render_LeftAligned.Output.verified.txt | 0 .../Render_RightAligned.Output.verified.txt | 0 .../Figlet/Render_Wrapped.Output.verified.txt | 0 .../AddEmptyRow/Render.Output.verified.txt | 0 .../Widgets/Grid/Render.Output.verified.txt | 0 .../Widgets/Grid/Render_2.Output.verified.txt | 0 .../Grid/Render_Alignment.Output.verified.txt | 0 ...r_Cell_Markup_Overflow.Output.verified.txt | 0 ...der_Cell_Overflow_Crop.Output.verified.txt | 0 ...Cell_Overflow_Ellipsis.Output.verified.txt | 0 ...der_Cell_Overflow_Fold.Output.verified.txt | 0 ...l_Overflow_With_NoWrap.Output.verified.txt | 0 ...Render_ExplicitPadding.Output.verified.txt | 0 .../Grid/Render_Padding.Output.verified.txt | 0 .../Json/Render_Json.Output.verified.txt | 0 .../Render_Empty_Layout.Output.verified.txt | 0 ...Render_Fallback_Layout.Output.verified.txt | 0 .../Layout/Render_Layout.Output.verified.txt | 0 ...er_Layout_With_Columns.Output.verified.txt | 0 ...ut_With_Nested_Columns.Output.verified.txt | 0 ...ayout_With_Nested_Rows.Output.verified.txt | 0 ...ested_Rows_And_Columns.Output.verified.txt | 0 ..._Rows_In_One_Column.Output_17.verified.txt | 0 ..._Rows_In_One_Column.Output_20.verified.txt | 0 ..._Rows_In_One_Column.Output_23.verified.txt | 0 ..._Rows_In_One_Column.Output_28.verified.txt | 0 ..._Rows_In_One_Column.Output_30.verified.txt | 0 ..._Rows_In_One_Column.Output_31.verified.txt | 0 ...espect_To_Minimum_Size.Output.verified.txt | 0 ..._With_Respect_To_Ratio.Output.verified.txt | 0 ...t_With_Respect_To_Size.Output.verified.txt | 0 ...ender_Layout_With_Rows.Output.verified.txt | 0 ...out_Invisible_Children.Output.verified.txt | 0 .../Widgets/Padder/Render.Output.verified.txt | 0 .../Render_Expanded.Output.verified.txt | 0 .../Padder/Render_Nested.Output.verified.txt | 0 .../Widgets/Panel/Render.Output.verified.txt | 0 .../Panel/Render_CJK.Output.verified.txt | 0 .../Render_Child_Centered.Output.verified.txt | 0 .../Render_Child_Panel.Output.verified.txt | 0 ...der_Child_RightAligned.Output.verified.txt | 0 .../Panel/Render_Expand.Output.verified.txt | 0 .../Panel/Render_Header.Output.verified.txt | 0 ...Render_Header_Centered.Output.verified.txt | 0 ...Render_Header_Collapse.Output.verified.txt | 0 ...der_Header_LeftAligned.Output.verified.txt | 0 ...er_Header_RightAligned.Output.verified.txt | 0 .../Panel/Render_Height.Output.verified.txt | 0 .../Render_LineEndings.Output.verified.txt | 0 ...rkup_Overflow_Ellipsis.Output.verified.txt | 0 .../Render_Multiline.Output.verified.txt | 0 ...ed_Panel_With_Overflow.Output.verified.txt | 0 .../Panel/Render_Padding.Output.verified.txt | 0 ...der_Text_Overflow_Crop.Output.verified.txt | 0 ...Text_Overflow_Ellipsis.Output.verified.txt | 0 ...der_Text_Overflow_Fold.Output.verified.txt | 0 ..._Overflow_With_Padding.Output.verified.txt | 0 .../Panel/Render_Unicode.Output.verified.txt | 0 .../Panel/Render_Width.Output.verified.txt | 0 .../Render_Width_Height.Output.verified.txt | 0 .../Render_Width_MaxWidth.Output.verified.txt | 0 .../Panel/Render_Wrap.Output.verified.txt | 0 .../Render_ZeroPadding.Output.verified.txt | 0 .../ProgressBar/Formatted.Output.verified.txt | 0 .../ProgressBar/Render.Output.verified.txt | 0 .../Widgets/Recorder/Html.Output.verified.txt | 0 .../Widgets/Recorder/Text.Output.verified.txt | 0 .../Rows/GH-1188-Rows.Output.verified.txt | 0 .../Widgets/Rows/Render.Output.verified.txt | 0 .../Rows/Render_Empty.Output.verified.txt | 0 ...er_Expanded_And_Nested.Output.verified.txt | 0 .../Rows/Render_Nested.Output.verified.txt | 0 .../Widgets/Rule/Render.Output.verified.txt | 0 .../Render_Border_Header.Output.verified.txt | 0 ...Render_Border_NoHeader.Output.verified.txt | 0 ...eader_DefaultAlignment.Output.verified.txt | 0 ...der_Header_LeftAligned.Output.verified.txt | 0 ...er_Header_RightAligned.Output.verified.txt | 0 .../Render_Linebreaks.Output.verified.txt | 0 .../Rule/Render_Truncate.Output.verified.txt | 0 .../Table/AddEmptyRow.Output.verified.txt | 0 .../Widgets/Table/Render.Output.verified.txt | 0 .../Render_CellPadding.Output.verified.txt | 0 ...r_Cell_Markup_Overflow.Output.verified.txt | 0 ...der_Cell_Overflow_Crop.Output.verified.txt | 0 ...Cell_Overflow_Ellipsis.Output.verified.txt | 0 ...der_Cell_Overflow_Fold.Output.verified.txt | 0 ...Overflow_Multiple_Rows.Output.verified.txt | 0 ...l_Overflow_With_NoWrap.Output.verified.txt | 0 .../Render_Centered.Align_Widget.verified.txt | 0 .../Table/Render_Centered.Output.verified.txt | 0 ...er_ColumnJustification.Output.verified.txt | 0 .../Render_EA_Character.Output.verified.txt | 0 .../Render_Empty_Column.Output.verified.txt | 0 .../Table/Render_Expand.Output.verified.txt | 0 .../Table/Render_Fold.Output.verified.txt | 0 .../Table/Render_Footers.Output.verified.txt | 0 .../Render_Impossible.Output.verified.txt | 0 ...nder_LeftAligned.Align_Widget.verified.txt | 0 .../Render_LeftAligned.Output.verified.txt | 0 .../Render_Multiline.Output.verified.txt | 0 .../Table/Render_Nested.Output.verified.txt | 0 .../Table/Render_NoRows.Output.verified.txt | 0 ...der_RightAligned.Align_Widget.verified.txt | 0 .../Render_RightAligned.Output.verified.txt | 0 .../Render_Row_Separators.Output.verified.txt | 0 ...w_Separators_No_Header.Output.verified.txt | 0 .../Render_Title_Caption.Output.verified.txt | 0 ...Title_Caption_Centered.Output.verified.txt | 0 ...le_Caption_LeftAligned.Output.verified.txt | 0 ...itle_Caption_LowerCase.Output.verified.txt | 0 ...e_Caption_RightAligned.Output.verified.txt | 0 .../Table/Rows/Add.Output.verified.txt | 0 .../Extensions/Add.Renderables.verified.txt | 0 .../Rows/Extensions/Add.Strings.verified.txt | 0 .../Insert.Renderables.verified.txt | 0 .../Extensions/Insert.Strings.verified.txt | 0 .../Extensions/Remove.Output.verified.txt | 0 .../Table/Rows/Insert.Output.verified.txt | 0 .../Table/Rows/Remove.Output.verified.txt | 0 .../TextPath/GH-1307.Output.verified.txt | 0 .../Widgets/Tree/Render.Output.verified.txt | 0 .../Render_NoChildren.Output.verified.txt | 0 .../Extensions/ConsoleKeyExtensions.cs | 0 .../Extensions/StreamExtensions.cs | 2 +- .../Properties/Usings.cs | 0 .../Spectre.Console.Tests.csproj | 7 +- .../Unit/AlternateScreenTests.cs | 2 +- .../Unit/AnsiConsoleTests.Advanced.cs | 2 +- .../Unit/AnsiConsoleTests.Colors.cs | 2 +- .../Unit/AnsiConsoleTests.Cursor.cs | 2 +- .../Unit/AnsiConsoleTests.Markup.cs | 2 +- .../AnsiConsoleTests.MarkupInterpolated.cs | 2 +- .../Unit/AnsiConsoleTests.Prompt.cs | 2 +- .../Unit/AnsiConsoleTests.Style.cs | 2 +- .../Unit/AnsiConsoleTests.cs | 2 +- .../Unit/ColorSystemTests.cs | 2 +- .../Spectre.Console.Tests/Unit/ColorTests.cs | 12 +- .../Spectre.Console.Tests/Unit/EmojiTests.cs | 2 +- .../Unit/ExceptionTests.cs | 2 +- .../Unit/HighlightTests.cs | 0 .../Unit/Internal/FileSizeTests.cs | 0 .../Live/Progress/DownloadedColumnTests.cs | 2 +- .../Live/Progress/ProgressColumnFixture.cs | 2 +- .../Unit/Live/Progress/ProgressTests.cs | 8 +- .../Unit/Live/StatusTests.cs | 2 +- .../Unit/Prompts/ListPromptStateTests.cs | 2 +- .../Unit/Prompts/MultiSelectionPromptTests.cs | 20 +- .../Unit/Prompts/SelectionPromptTests.cs | 2 +- .../Unit/Prompts/TextPromptTests.cs | 2 +- .../Unit/RecorderTests.cs | 2 +- .../Unit/Rendering/Borders/BoxBorderTests.cs | 2 +- .../Rendering/Borders/TableBorderTests.cs | 2 +- .../Unit/Rendering/RenderHookTests.cs | 2 +- .../Unit/Rendering/SegmentTests.cs | 4 +- .../Spectre.Console.Tests/Unit/StyleTests.cs | 4 +- .../Unit/Widgets/AlignTests.cs | 2 +- .../Unit/Widgets/BarChartTests.cs | 2 +- .../Unit/Widgets/BreakdownChartTests.cs | 2 +- .../Unit/Widgets/CalendarTests.cs | 2 +- .../Unit/Widgets/CanvasTests.cs | 2 +- .../Unit/Widgets/ColumnsTests.cs | 6 +- .../Unit/Widgets/FigletTests.cs | 2 +- .../Unit/Widgets/GridTests.cs | 4 +- .../Unit/Widgets/JsonTextTests.cs | 2 +- .../Unit/Widgets/LayoutTests.cs | 2 +- .../Unit/Widgets/MarkupTests.cs | 2 +- .../Unit/Widgets/PadderTests.cs | 2 +- .../Unit/Widgets/PanelTests.cs | 2 +- .../Unit/Widgets/ProgressBarTests.cs | 0 .../Unit/Widgets/RowsTests.cs | 2 +- .../Unit/Widgets/RuleTests.cs | 2 +- .../TableRowCollectionExtensionsTests.cs | 2 +- .../Widgets/Table/TableRowCollectionTests.cs | 6 +- .../Unit/Widgets/Table/TableTests.cs | 8 +- .../Unit/Widgets/TextPathTests.cs | 2 +- .../Unit/Widgets/TextTests.cs | 2 +- .../Unit/Widgets/TreeTests.cs | 2 +- .../Utilities/EmbeddedResourceReader.cs | 18 +- .../Utilities/GitHubIssueAttribute.cs | 0 .../Utilities/ModuleInitializerAttribute.cs | 0 .../Utilities/TestConsoleExtensions.cs | 2 +- .../VerifyConfiguration.cs | 2 +- src/Spectre.Console.slnx | 20 +- src/Spectre.Console/AnsiConsole.Prompt.cs | 2 - src/Spectre.Console/Color.Generated.cs | 170 +++ .../Extensions/AlignExtensions.cs | 2 +- .../Extensions/AlignableExtensions.cs | 2 +- .../AnsiConsoleExtensions.Prompt.cs | 2 - .../Extensions/LayoutExtensions.cs | 2 +- .../Extensions/RenderOptionsExtensions.cs | 2 +- .../Extensions/TextPathExtensions.cs | 2 +- src/Spectre.Console/HorizontalAlignment.cs | 2 +- src/Spectre.Console/IAlignable.cs | 2 +- .../Internal/Backends/Ansi/AnsiDetector.cs | 2 +- src/Spectre.Console/Internal/Cell.cs | 6 +- .../Internal/IRatioResolvable.cs | 2 +- .../Internal/Polyfill/CancellationToken.cs | 13 +- .../Internal/Polyfill/EnumHelpers.cs | 2 +- .../Internal/Polyfill/IsExternalInit.cs | 17 +- .../Internal/TypeConverterHelper.cs | 4 +- .../Live/Progress/ProgressContext.cs | 2 +- src/Spectre.Console/Properties/Usings.cs | 1 - .../Rendering/RenderOptions.cs | 2 +- src/Spectre.Console/Rendering/Segment.cs | 2 +- src/Spectre.Console/Size.cs | 2 +- src/Spectre.Console/VerticalAlignment.cs | 2 +- src/Spectre.Console/Widgets/Align.cs | 2 +- src/Spectre.Console/Widgets/Layout/Layout.cs | 2 +- .../Widgets/Layout/LayoutPlaceholder.cs | 2 +- .../Widgets/Layout/LayoutSplitter.cs | 2 +- src/Spectre.Console/Widgets/Paragraph.cs | 2 +- src/Spectre.Console/Widgets/TextPath.cs | 2 +- src/Tests/.editorconfig | 107 -- src/Tests/Directory.Build.props | 13 - .../Spectre.Console.Cli.Tests/Constants.cs | 19 - .../Data/Commands/AnimalCommand.cs | 8 - .../Data/Commands/AsynchronousCommand.cs | 28 - .../Data/Commands/CatCommand.cs | 9 - .../Data/Commands/DogCommand.cs | 30 - .../Data/Commands/DumpRemainingCommand.cs | 34 - .../Data/Commands/EmptyCommand.cs | 9 - .../Data/Commands/GenericCommand.cs | 10 - .../Data/Commands/GiraffeCommand.cs | 10 - .../Data/Commands/GreeterCommand.cs | 17 - .../Data/Commands/HiddenOptionsCommand.cs | 9 - .../Data/Commands/HorseCommand.cs | 10 - .../Data/Commands/InvalidCommand.cs | 9 - .../Data/Commands/LionCommand.cs | 10 - .../Data/Commands/NoDescriptionCommand.cs | 12 - .../Data/Commands/OptionVectorCommand.cs | 9 - .../Data/Commands/ThrowingCommand.cs | 9 - .../Data/Commands/TurtleCommand.cs | 10 - .../Data/Commands/VersionCommand.cs | 18 - .../Data/Converters/CatAgilityConverter.cs | 14 - .../Converters/StringToIntegerConverter.cs | 14 - .../Data/Help/CustomHelpProvider.cs | 34 - .../Data/Help/RedirectHelpProvider.cs | 21 - .../Data/Help/RenderMarkupHelpProvider.cs | 11 - .../Data/Settings/AnimalSettings.cs | 14 - .../Data/Settings/ArgumentOrderSettings.cs | 19 - .../Data/Settings/ArgumentVectorSettings.cs | 7 - .../Settings/AsynchronousCommandSettings.cs | 8 - .../Data/Settings/BarCommandSettings.cs | 8 - .../Data/Settings/CatSettings.cs | 11 - .../Data/Settings/DogSettings.cs | 20 - .../Data/Settings/FooSettings.cs | 8 - .../Data/Settings/GiraffeSettings.cs | 8 - .../Data/Settings/HiddenOptionSettings.cs | 16 - .../Data/Settings/HorseSettings.cs | 16 - .../Data/Settings/InvalidSettings.cs | 7 - .../Data/Settings/LionSettings.cs | 21 - .../Data/Settings/MammalSettings.cs | 7 - .../MultipleArgumentVectorSettings.cs | 19 - .../Data/Settings/OptionVectorSettings.cs | 10 - ...ptionalArgumentWithDefaultValueSettings.cs | 50 - .../Data/Settings/ReptileSettings.cs | 7 - .../Data/Settings/RequiredOptionsSettings.cs | 14 - .../Data/Settings/StringOptionSettings.cs | 7 - .../Data/Settings/ThrowingCommandSettings.cs | 5 - .../Data/Settings/TurtleSettings.cs | 16 - .../Data/Settings/VersionSettings.cs | 8 - .../EvenNumberValidatorAttribute.cs | 25 - .../PositiveNumberValidatorAttribute.cs | 25 - .../Help/ArgumentOrder.Output.verified.txt | 12 - .../Help/Branch.Output.verified.txt | 18 - ...ch_Called_Without_Help.Output.verified.txt | 18 - ...Branch_Default_Greeter.Output.verified.txt | 11 - .../Help/Branch_Examples.Output.verified.txt | 30 - .../Command_Hide_Default.Output.verified.txt | 17 - ...Configured_By_Instance.Output.verified.txt | 14 - ...elp_Configured_By_Type.Output.verified.txt | 1 - ...Registered_By_Instance.Output.verified.txt | 14 - ...elp_Registered_By_Type.Output.verified.txt | 1 - .../Help/Default.Output.verified.txt | 19 - ...t_Custom_Help_Provider.Output.verified.txt | 15 - .../Help/Default_Examples.Output.verified.txt | 23 - .../Help/Default_Greeter.Output.verified.txt | 1 - .../Default_Without_Args.Output.verified.txt | 19 - ...out_Args_Additional.Output_DE.verified.txt | 26 - ...out_Args_Additional.Output_EN.verified.txt | 26 - ...out_Args_Additional.Output_FR.verified.txt | 26 - ...out_Args_Additional.Output_IT.verified.txt | 26 - ...out_Args_Additional.Output_JA.verified.txt | 26 - ...out_Args_Additional.Output_KO.verified.txt | 26 - ...out_Args_Additional.Output_PT.verified.txt | 26 - ...out_Args_Additional.Output_RU.verified.txt | 26 - ...out_Args_Additional.Output_SV.verified.txt | 26 - ...rgs_Additional.Output_ZH-HANS.verified.txt | 26 - ...nal_Style_BoldHeadings.Output.verified.txt | 25 - ...ditional_Style_Default.Output.verified.txt | 25 - ..._Additional_Style_None.Output.verified.txt | 25 - ...ion_No_Trailing_Period.Output.verified.txt | 15 - ...Hidden_Command_Options.Output.verified.txt | 9 - .../Help/Hidden_Commands.Output.verified.txt | 9 - .../Help/Leaf.Output.verified.txt | 15 - .../Help/NoDescription.Output.verified.txt | 8 - .../Help/NoVersion.Output.verified.txt | 12 - .../Help/Required_Options.Output.verified.txt | 6 - ...Options_No_Description.Output.verified.txt | 6 - .../Help/Root.Output.verified.txt | 10 - .../Help/Root.QuestionMark.verified.txt | 10 - .../Help/Root_Command.Output.verified.txt | 17 - .../Root_Command.QuestionMark.verified.txt | 17 - .../Help/Root_Examples.Output.verified.txt | 23 - ...Root_Examples_Children.Output.verified.txt | 16 - ...xamples_Children_Eight.Output.verified.txt | 19 - ...Examples_Children_None.Output.verified.txt | 9 - ...amples_Children_Twelve.Output.verified.txt | 23 - .../Root_Examples_Leafs.Output.verified.txt | 15 - ...t_Examples_Leafs_Eight.Output.verified.txt | 18 - ...ot_Examples_Leafs_None.Output.verified.txt | 8 - ..._Examples_Leafs_Twelve.Output.verified.txt | 22 - .../Help/Version.Output.verified.txt | 13 - .../OpenCli/Generate.Output.verified.txt | 190 --- .../Test_1.Output.verified.txt | 4 - .../Test_2.Output.verified.txt | 4 - .../Xml/Test_1.Output.verified.txt | 41 - .../Xml/Test_10.Output.verified.txt | 26 - .../Xml/Test_2.Output.verified.txt | 22 - .../Xml/Test_3.Output.verified.txt | 37 - .../Xml/Test_4.Output.verified.txt | 27 - .../Xml/Test_6.Output.verified.txt | 42 - .../Xml/Test_7.Output.verified.txt | 33 - .../Xml/Test_8.Output.verified.txt | 37 - .../Xml/Test_9.Output.verified.txt | 39 - .../Properties/Usings.cs | 18 - .../Spectre.Console.Cli.Tests.csproj | 26 - ...CommandArgumentAttributeTests.Rendering.cs | 85 -- .../CommandArgumentAttributeTests.cs | 59 - .../CommandOptionAttributeTests.Rendering.cs | 230 --- .../CommandOptionAttributeTests.cs | 214 --- .../Unit/CommandAppTests.Async.cs | 124 -- .../Unit/CommandAppTests.Branches.cs | 381 ----- .../Unit/CommandAppTests.Constructor.cs | 104 -- .../Unit/CommandAppTests.Context.cs | 23 - .../Unit/CommandAppTests.Exceptions.cs | 136 -- .../Unit/CommandAppTests.FlagValues.cs | 214 --- .../Unit/CommandAppTests.Help.cs | 1103 -------------- .../CommandAppTests.Injection.Settings.cs | 116 -- .../Unit/CommandAppTests.Injection.cs | 94 -- .../Unit/CommandAppTests.Interceptor.cs | 90 -- .../Unit/CommandAppTests.OpenCli.cs | 33 - .../Unit/CommandAppTests.Options.cs | 27 - .../Unit/CommandAppTests.Pairs.cs | 316 ---- .../Unit/CommandAppTests.Parsing.cs | 600 -------- .../Unit/CommandAppTests.Remaining.cs | 411 ------ .../Unit/CommandAppTests.Sensitivity.cs | 111 -- .../Unit/CommandAppTests.Settings.cs | 21 - .../Unit/CommandAppTests.TypeConverters.cs | 104 -- .../Unit/CommandAppTests.Unsafe.cs | 291 ---- .../Unit/CommandAppTests.Validation.cs | 106 -- .../Unit/CommandAppTests.ValueProviders.cs | 88 -- .../Unit/CommandAppTests.Vectors.cs | 104 -- .../Unit/CommandAppTests.Version.Help.cs | 236 --- .../Unit/CommandAppTests.Version.cs | 290 ---- .../Unit/CommandAppTests.Xml.cs | 238 --- .../Unit/CommandAppTests.cs | 1279 ----------------- .../Unit/DefaultTypeRegistrarTests.cs | 11 - .../Unit/Parsing/CommandTreeTokenizerTests.cs | 314 ---- .../Unit/Testing/CommandAppTesterTests.cs | 83 -- .../Unit/Testing/FakeTypeRegistrarTests.cs | 12 - .../Unit/Testing/InteractiveCommandTests.cs | 111 -- .../Utilities/CommandContextExtensions.cs | 25 - ...ntCannotContainOptions.Output.verified.txt | 5 - ...dCharacterInOptionName.Output.verified.txt | 5 - ...idCharacterInValueName.Output.verified.txt | 5 - ...veMoreThanOneCharacter.Output.verified.txt | 5 - ...issingLongAndShortName.Output.verified.txt | 5 - ...nValuesAreNotSupported.Output.verified.txt | 5 - ...eValuesAreNotSupported.Output.verified.txt | 5 - ...esCannotStartWithDigit.Output.verified.txt | 5 - .../OptionsMustHaveName.Output.verified.txt | 5 - ...MustOnlyBeOneCharacter.Output.verified.txt | 5 - .../UnexpectedCharacter.Output.verified.txt | 5 - .../UnterminatedValueName.Output.verified.txt | 5 - .../ValuesMustHaveName.Output.verified.txt | 5 - .../Test_1.Output.verified.txt | 4 - .../Test_1.Output.verified.txt | 4 - .../Test_1.Output.verified.txt | 4 - .../Test_1.Output.verified.txt | 4 - .../Test_1.Output.verified.txt | 4 - .../Test_1.Output.verified.txt | 4 - .../Test_1.Output.verified.txt | 4 - .../Test_2.Output.verified.txt | 4 - .../Test_1.Output.verified.txt | 4 - .../Test_2.Output.verified.txt | 4 - .../Test_3.Output.verified.txt | 4 - .../Test_4.Output.verified.txt | 4 - .../Test_5.Output.verified.txt | 4 - .../Test_1.Output.verified.txt | 4 - .../Test_2.Output.verified.txt | 4 - .../UnknownCommand/Test_1.Output.verified.txt | 4 - .../UnknownCommand/Test_2.Output.verified.txt | 4 - .../UnknownCommand/Test_3.Output.verified.txt | 4 - .../UnknownCommand/Test_4.Output.verified.txt | 4 - .../UnknownCommand/Test_5.Output.verified.txt | 4 - .../UnknownCommand/Test_6.Output.verified.txt | 4 - .../UnknownCommand/Test_7.Output.verified.txt | 4 - .../UnknownCommand/Test_8.Output.verified.txt | 4 - .../UnknownOption/Test_1.Output.verified.txt | 4 - .../UnknownOption/Test_2.Output.verified.txt | 4 - ...Hidden_Command_Options.Output.verified.txt | 14 - .../Cli/Xml/Test_5.Output.verified.txt | 10 - .../Utilities/ModuleInitializerAttribute.cs | 8 - .../VerifyConfiguration.cs | 10 - src/stylecop.json | 26 - 856 files changed, 2415 insertions(+), 24551 deletions(-) rename build.cake => build.cs (57%) delete mode 100644 resources/nuget/Spectre.Console.Cli.md mode change 100644 => 100755 resources/scripts/Generate-Colors.ps1 mode change 100644 => 100755 resources/scripts/Generate-Emoji.ps1 mode change 100644 => 100755 resources/scripts/Generate-Samples.ps1 mode change 100644 => 100755 resources/scripts/Generate-Spinners.ps1 delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/AnsiConsoleExtensions.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/AsciiCastConsole.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/AsciiCastExtensions.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/AsciiCastInput.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/AsciiCastOut.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/BarChartSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/BaseSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/BreakdownChartSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/CalendarSamples.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/CanvasImageSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/CanvasSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/Exceptions.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/FigletSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/InputSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/JsonSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/LayoutSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/LiveSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/MultiSelectionSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/PanelSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/ProgressSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/RuleSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/SelectionSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/StatusSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/TableSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/TextPathSample.cs delete mode 100644 resources/scripts/Generator/Commands/AsciiCast/Samples/TreeSample.cs delete mode 100644 resources/scripts/Generator/Commands/ColorGeneratorCommand.cs delete mode 100644 resources/scripts/Generator/Commands/EmojiGeneratorCommand.cs delete mode 100644 resources/scripts/Generator/Commands/GeneratorSettings.cs delete mode 100644 resources/scripts/Generator/Commands/SampleCommand.cs delete mode 100644 resources/scripts/Generator/Commands/SpinnerGeneratorCommand.cs delete mode 100644 resources/scripts/Generator/Generator.csproj delete mode 100644 resources/scripts/Generator/Models/Color.cs delete mode 100644 resources/scripts/Generator/Models/ColorModel.cs delete mode 100644 resources/scripts/Generator/Models/Emoji.cs delete mode 100644 resources/scripts/Generator/Models/Palette.cs delete mode 100644 resources/scripts/Generator/Models/Spinner.cs delete mode 100644 resources/scripts/Generator/Program.cs delete mode 100644 src/Directory.Build.targets create mode 100644 src/Generator/Commands/AsciiCast/AnsiConsoleExtensions.cs create mode 100644 src/Generator/Commands/AsciiCast/AsciiCastConsole.cs create mode 100644 src/Generator/Commands/AsciiCast/AsciiCastExtensions.cs create mode 100644 src/Generator/Commands/AsciiCast/AsciiCastInput.cs create mode 100644 src/Generator/Commands/AsciiCast/AsciiCastOut.cs rename {resources/scripts => src}/Generator/Commands/AsciiCast/Samples/AwaitSpinnerSample.cs (96%) create mode 100644 src/Generator/Commands/AsciiCast/Samples/BarChartSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/BaseSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/BreakdownChartSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/CalendarSamples.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/CanvasImageSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/CanvasSample.cs rename {resources/scripts => src}/Generator/Commands/AsciiCast/Samples/ColumnsSample.cs (94%) create mode 100644 src/Generator/Commands/AsciiCast/Samples/Exceptions.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/FigletSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/InputSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/JsonSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/LayoutSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/LiveSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/MultiSelectionSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/PanelSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/ProgressSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/RuleSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/SelectionSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/StatusSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/TableSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/TextPathSample.cs create mode 100644 src/Generator/Commands/AsciiCast/Samples/TreeSample.cs create mode 100644 src/Generator/Commands/ColorGeneratorCommand.cs create mode 100644 src/Generator/Commands/EmojiGeneratorCommand.cs create mode 100644 src/Generator/Commands/GeneratorSettings.cs create mode 100644 src/Generator/Commands/SampleCommand.cs create mode 100644 src/Generator/Commands/SpinnerGeneratorCommand.cs create mode 100644 src/Generator/Data/cake.png rename {resources/scripts => src}/Generator/Data/colors.json (100%) rename {resources/scripts => src}/Generator/Data/spinners_default.json (100%) rename {resources/scripts => src}/Generator/Data/spinners_sindresorhus.json (100%) create mode 100644 src/Generator/Generator.csproj rename {resources/scripts => src}/Generator/Generator.slnx (83%) create mode 100644 src/Generator/Models/Color.cs create mode 100644 src/Generator/Models/ColorModel.cs create mode 100644 src/Generator/Models/Emoji.cs create mode 100644 src/Generator/Models/Palette.cs create mode 100644 src/Generator/Models/Spinner.cs create mode 100644 src/Generator/Program.cs rename {resources/scripts => src}/Generator/Templates/Color.Generated.template (100%) rename {resources/scripts => src}/Generator/Templates/ColorPalette.Generated.template (79%) rename {resources/scripts => src}/Generator/Templates/ColorTable.Generated.template (100%) rename {resources/scripts => src}/Generator/Templates/Emoji.Generated.template (100%) rename {resources/scripts => src}/Generator/Templates/Emoji.Json.template (100%) rename {resources/scripts => src}/Generator/Templates/Spinner.Generated.template (100%) delete mode 100644 src/Spectre.Console.Cli/Annotations/CommandArgumentAttribute.cs delete mode 100644 src/Spectre.Console.Cli/Annotations/CommandOptionAttribute.cs delete mode 100644 src/Spectre.Console.Cli/Annotations/PairDeconstructorAttribute.cs delete mode 100644 src/Spectre.Console.Cli/Annotations/ParameterValidationAttribute.cs delete mode 100644 src/Spectre.Console.Cli/Annotations/ParameterValueProviderAttribute.cs delete mode 100644 src/Spectre.Console.Cli/AsyncCommand.cs delete mode 100644 src/Spectre.Console.Cli/AsyncCommandOfT.cs delete mode 100644 src/Spectre.Console.Cli/CaseSensitivity.cs delete mode 100644 src/Spectre.Console.Cli/Command.cs delete mode 100644 src/Spectre.Console.Cli/CommandApp.cs delete mode 100644 src/Spectre.Console.Cli/CommandAppException.cs delete mode 100644 src/Spectre.Console.Cli/CommandAppOfT.cs delete mode 100644 src/Spectre.Console.Cli/CommandConfigurationException.cs delete mode 100644 src/Spectre.Console.Cli/CommandContext.cs delete mode 100644 src/Spectre.Console.Cli/CommandOfT.cs delete mode 100644 src/Spectre.Console.Cli/CommandParameterContext.cs delete mode 100644 src/Spectre.Console.Cli/CommandParseException.cs delete mode 100644 src/Spectre.Console.Cli/CommandRuntimeException.cs delete mode 100644 src/Spectre.Console.Cli/CommandSettings.cs delete mode 100644 src/Spectre.Console.Cli/CommandTemplateException.cs delete mode 100644 src/Spectre.Console.Cli/ConfiguratorExtensions.cs delete mode 100644 src/Spectre.Console.Cli/EmptyCommandSettings.cs delete mode 100644 src/Spectre.Console.Cli/FlagValue.cs delete mode 100644 src/Spectre.Console.Cli/Help/HelpProvider.cs delete mode 100644 src/Spectre.Console.Cli/Help/HelpProviderResources.cs delete mode 100644 src/Spectre.Console.Cli/Help/HelpProviderStyles.cs delete mode 100644 src/Spectre.Console.Cli/Help/ICommandArgument.cs delete mode 100644 src/Spectre.Console.Cli/Help/ICommandContainer.cs delete mode 100644 src/Spectre.Console.Cli/Help/ICommandInfo.cs delete mode 100644 src/Spectre.Console.Cli/Help/ICommandInfoExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Help/ICommandModel.cs delete mode 100644 src/Spectre.Console.Cli/Help/ICommandOption.cs delete mode 100644 src/Spectre.Console.Cli/Help/ICommandParameter.cs delete mode 100644 src/Spectre.Console.Cli/Help/IHelpProvider.cs delete mode 100644 src/Spectre.Console.Cli/IBranchConfigurator.cs delete mode 100644 src/Spectre.Console.Cli/ICommand.cs delete mode 100644 src/Spectre.Console.Cli/ICommandApp.cs delete mode 100644 src/Spectre.Console.Cli/ICommandAppSettings.cs delete mode 100644 src/Spectre.Console.Cli/ICommandConfigurator.cs delete mode 100644 src/Spectre.Console.Cli/ICommandInterceptor.cs delete mode 100644 src/Spectre.Console.Cli/ICommandLimiterOfT.cs delete mode 100644 src/Spectre.Console.Cli/ICommandOfT.cs delete mode 100644 src/Spectre.Console.Cli/ICommandParameterInfo.cs delete mode 100644 src/Spectre.Console.Cli/IConfigurator.cs delete mode 100644 src/Spectre.Console.Cli/IConfiguratorOfT.cs delete mode 100644 src/Spectre.Console.Cli/IFlagValue.cs delete mode 100644 src/Spectre.Console.Cli/IRemainingArguments.cs delete mode 100644 src/Spectre.Console.Cli/ITypeRegistrar.cs delete mode 100644 src/Spectre.Console.Cli/ITypeRegistrarFrontend.cs delete mode 100644 src/Spectre.Console.Cli/ITypeResolver.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Binding/CommandConstructorBinder.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Binding/CommandPropertyBinder.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Binding/CommandValueBinder.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Binding/CommandValueLookup.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Binding/CommandValueResolver.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Collections/IMultiMap.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Collections/MultiMap.cs delete mode 100644 src/Spectre.Console.Cli/Internal/CommandBinder.cs delete mode 100644 src/Spectre.Console.Cli/Internal/CommandExecutor.cs delete mode 100644 src/Spectre.Console.Cli/Internal/CommandPart.cs delete mode 100644 src/Spectre.Console.Cli/Internal/CommandSuggestor.cs delete mode 100644 src/Spectre.Console.Cli/Internal/CommandValidator.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Commands/ExplainCommand.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Commands/IBuiltInCommand.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Commands/OpenCliGeneratorCommand.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Commands/VersionCommand.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Commands/XmlDocCommand.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Composer.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Composition/Activators.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Composition/ComponentRegistration.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Composition/ComponentRegistry.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Composition/DefaultTypeRegistrar.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Composition/DefaultTypeResolver.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/BranchConfigurator.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/CommandAppSettings.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/CommandConfigurator.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/ConfigurationHelper.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/ConfiguratorOfT.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/ConfiguredCommand.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/DefaultCommandConfigurator.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/IConfiguration.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/TemplateParser.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/TemplateToken.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Configuration/TemplateTokenizer.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Constants.cs delete mode 100644 src/Spectre.Console.Cli/Internal/DefaultPairDeconstructor.cs delete mode 100644 src/Spectre.Console.Cli/Internal/DelegateCommand.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Exceptions/CommandLineParseExceptionFactory.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Exceptions/CommandLineTemplateExceptionFactory.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Extensions/AnsiConsoleExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Extensions/CaseSensitivityExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Extensions/EnumerableExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Extensions/ListExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Extensions/OpenCliExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Extensions/StringExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Extensions/TypeExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Extensions/TypeRegistrarExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Extensions/XmlElementExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/IPairDeconstructor.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/CommandArgument.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/CommandContainerExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/CommandInfo.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/CommandInfoExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/CommandModel.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/CommandModelBuilder.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/CommandModelValidator.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/CommandOption.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/CommandParameter.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/CommandParameterComparer.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/ICommandContainer.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Modelling/ParameterKind.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Parsing/CommandTree.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Parsing/CommandTreeExtensions.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParser.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParserContext.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParserResult.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Parsing/CommandTreeToken.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenStream.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizer.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizerContext.cs delete mode 100644 src/Spectre.Console.Cli/Internal/Parsing/MappedCommandParameter.cs delete mode 100644 src/Spectre.Console.Cli/Internal/ParsingMode.cs delete mode 100644 src/Spectre.Console.Cli/Internal/RemainingArguments.cs delete mode 100644 src/Spectre.Console.Cli/Internal/StringWriterWithEncoding.cs delete mode 100644 src/Spectre.Console.Cli/Internal/TextBuffer.cs delete mode 100644 src/Spectre.Console.Cli/Internal/TypeRegistrar.cs delete mode 100644 src/Spectre.Console.Cli/Internal/TypeResolverAdapter.cs delete mode 100644 src/Spectre.Console.Cli/Internal/VersionHelper.cs delete mode 100644 src/Spectre.Console.Cli/PairDeconstructor.cs delete mode 100644 src/Spectre.Console.Cli/Properties/Usings.cs delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.Designer.cs delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.de.resx delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.es.resx delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.fr.resx delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.it.resx delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.ja.resx delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.ko.resx delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.pt.resx delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.resx delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.ru.resx delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.sv.resx delete mode 100644 src/Spectre.Console.Cli/Resources/HelpProvider.zh-Hans.resx delete mode 100644 src/Spectre.Console.Cli/Spectre.Console.Cli.csproj delete mode 100644 src/Spectre.Console.Cli/Unsafe/IUnsafeBranchConfigurator.cs delete mode 100644 src/Spectre.Console.Cli/Unsafe/IUnsafeConfigurator.cs delete mode 100644 src/Spectre.Console.Cli/Unsafe/UnsafeConfiguratorExtensions.cs delete mode 100644 src/Spectre.Console.Testing/Cli/CallbackCommandInterceptor.cs delete mode 100644 src/Spectre.Console.Testing/Cli/CommandAppFailure.cs delete mode 100644 src/Spectre.Console.Testing/Cli/CommandAppResult.cs delete mode 100644 src/Spectre.Console.Testing/Cli/CommandAppTester.cs delete mode 100644 src/Spectre.Console.Testing/Cli/CommandAppTesterSettings.cs delete mode 100644 src/Spectre.Console.Testing/Cli/TypeRegistrarBaseTests.cs delete mode 100644 src/Spectre.Console.Testing/FakeTypeRegistrar.cs delete mode 100644 src/Spectre.Console.Testing/FakeTypeResolver.cs rename src/{Tests => }/Spectre.Console.Tests/Data/Exceptions.cs (95%) rename src/{Tests => }/Spectre.Console.Tests/Data/example.json (100%) rename src/{Tests => }/Spectre.Console.Tests/Data/poison.flf (100%) rename src/{Tests => }/Spectre.Console.Tests/Data/starwars.flf (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/AlternateScreen/Show.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/ArgumentCannotContainOptions.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/InvalidCharacterInOptionName.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/InvalidCharacterInValueName.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/LongOptionMustHaveMoreThanOneCharacter.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/MissingLongAndShortName.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/MultipleOptionValuesAreNotSupported.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/MultipleValuesAreNotSupported.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/OptionNamesCannotStartWithDigit.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/OptionsMustHaveName.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/ShortOptionMustOnlyBeOneCharacter.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/UnexpectedCharacter.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/UnterminatedValueName.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Arguments/ValuesMustHaveName.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/ArgumentOrder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/Command.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/CommandExamples.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/Default.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/DefaultExamples.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/Hidden_Command_Options.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/Hidden_Commands.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/Leaf.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/NoDescription.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/Root.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples_Children.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples_Leafs.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Parsing/CannotAssignValueToFlag/Test_1.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Parsing/CannotAssignValueToFlag/Test_2.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/InvalidShortOptionName/Test_1.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/LongOptionNameContainSymbol/Test_1.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/LongOptionNameIsMissing/Test_1.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/LongOptionNameIsOneCharacter/Test_1.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/LongOptionNameStartWithDigit/Test_1.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/NoMatchingArgument/Test_1.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/NoValueForOption/Test_1.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/NoValueForOption/Test_2.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/OptionWithoutName/Test_1.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/OptionWithoutName/Test_2.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/OptionWithoutName/Test_3.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/OptionWithoutName/Test_4.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/OptionWithoutName/Test_5.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnexpectedOption/Test_1.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnexpectedOption/Test_2.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnknownCommand/Test_1.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnknownCommand/Test_2.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnknownCommand/Test_3.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnknownCommand/Test_4.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnknownCommand/Test_5.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnknownCommand/Test_6.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnknownCommand/Test_7.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnknownCommand/Test_8.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnknownOption/Test_1.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Parsing/UnknownOption/Test_2.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Xml/Hidden_Command_Options.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Xml/Test_1.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Xml/Test_2.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Xml/Test_3.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Xml/Test_4.Output.verified.txt (100%) rename src/{Tests/Spectre.Console.Cli.Tests/Expectations => Spectre.Console.Tests/Expectations/Cli}/Xml/Test_5.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Cli/Xml/Test_6.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Exception/CallSite.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Exception/Default.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=Default.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenTypes.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Exception/InnerException.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Exception/NoStackTrace.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Exception/OutParam.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Exception/ShortenedMethods.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Exception/ShortenedTypes.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Exception/Tuple.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Live/Progress/Render_ReduceWidth.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Live/Status/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/AcceptChoice.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_BestMatch.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_Empty.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_NextChoice.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_PreviousChoice.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/ChoicesStyleNotSet.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/ChoicesStyleSet.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/ConversionError.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/CustomConverter.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/CustomValidation.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValue.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValueStyleNotSet.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValueStyleSet.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/InvalidChoice.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/NoSuffix.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValue.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValueCustomMask.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValueNullMask.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Prompts/Text/SecretValueBackspaceNullMask.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/AsciiBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/DoubleBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/HeavyBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder_With_Header.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/RoundedBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/SquareBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/Ascii2Border.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/AsciiBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/AsciiDoubleHeadBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/DoubleBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/DoubleEdgeBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyEdgeBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyHeadBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HorizontalBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_Centered.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_LeftAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_RightAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalDoubleHeadBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalHeavyHeadBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/NoBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/RoundedBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SimpleBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SimpleHeavyBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SquareBorder.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_Renderable.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_String.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Bottom.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Middle.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Top.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Bottom.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Middle.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Top.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Bottom.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Middle.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Top.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BarChart/Fixed_Max_Value.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BarChart/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BarChart/Zero_Value.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Ansi.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Culture.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Default.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/FullSize.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/HideTagValues.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/HideTags.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/TagFormat.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/ValueColor.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Width.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Calendar/Centered.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Calendar/Culture.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Calendar/LeftAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Calendar/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Calendar/RightAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_MaxWidth.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_NarrowTerminal.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_Nested.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Columns/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Figlet/Load_Stream.Output_fontfile=poison.flf.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Figlet/Load_Stream.Output_fontfile=starwars.flf.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_Centered.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_LeftAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_RightAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_Wrapped.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Grid/AddEmptyRow/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Grid/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_2.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Alignment.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_ExplicitPadding.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Padding.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Json/Render_Json.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Empty_Layout.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Fallback_Layout.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Columns.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Columns.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Rows.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Rows_And_Columns.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_17.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_20.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_23.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_28.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_30.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_31.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Minimum_Size.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Ratio.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Size.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Rows.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_Without_Invisible_Children.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Padder/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Padder/Render_Expanded.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Padder/Render_Nested.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_CJK.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_Centered.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_Panel.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_RightAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Expand.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_Centered.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_Collapse.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_LeftAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_RightAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Height.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_LineEndings.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Multiline.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Padding.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Unicode.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width_Height.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width_MaxWidth.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Wrap.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_ZeroPadding.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/ProgressBar/Formatted.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/ProgressBar/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Recorder/Html.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Recorder/Text.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rows/GH-1188-Rows.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rows/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Empty.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Expanded_And_Nested.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Nested.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rule/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Border_Header.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Border_NoHeader.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_DefaultAlignment.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_LeftAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_RightAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Linebreaks.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Truncate.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/AddEmptyRow.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_CellPadding.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Centered.Align_Widget.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Centered.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_ColumnJustification.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_EA_Character.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Empty_Column.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Expand.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Fold.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Footers.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Impossible.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_LeftAligned.Align_Widget.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_LeftAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Multiline.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Nested.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_NoRows.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_RightAligned.Align_Widget.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_RightAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators_No_Header.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_Centered.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_LeftAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_LowerCase.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_RightAligned.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Add.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Add.Renderables.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Add.Strings.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Insert.Renderables.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Insert.Strings.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Remove.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Insert.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Remove.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/TextPath/GH-1307.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Tree/Render.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Expectations/Widgets/Tree/Render_NoChildren.Output.verified.txt (100%) rename src/{Tests => }/Spectre.Console.Tests/Extensions/ConsoleKeyExtensions.cs (100%) rename src/{Tests => }/Spectre.Console.Tests/Extensions/StreamExtensions.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Properties/Usings.cs (100%) rename src/{Tests => }/Spectre.Console.Tests/Spectre.Console.Tests.csproj (74%) rename src/{Tests => }/Spectre.Console.Tests/Unit/AlternateScreenTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/AnsiConsoleTests.Colors.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/AnsiConsoleTests.Cursor.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/AnsiConsoleTests.Markup.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/AnsiConsoleTests.MarkupInterpolated.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/AnsiConsoleTests.Style.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/ColorSystemTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/ColorTests.cs (97%) rename src/{Tests => }/Spectre.Console.Tests/Unit/EmojiTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/ExceptionTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/HighlightTests.cs (100%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Internal/FileSizeTests.cs (100%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Live/Progress/DownloadedColumnTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Live/Progress/ProgressColumnFixture.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Live/Progress/ProgressTests.cs (98%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Live/StatusTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Prompts/ListPromptStateTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs (89%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Prompts/SelectionPromptTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Prompts/TextPromptTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/RecorderTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Rendering/Borders/BoxBorderTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Rendering/Borders/TableBorderTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Rendering/RenderHookTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Rendering/SegmentTests.cs (98%) rename src/{Tests => }/Spectre.Console.Tests/Unit/StyleTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/AlignTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/BarChartTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/BreakdownChartTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/CalendarTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/CanvasTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/ColumnsTests.cs (90%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/FigletTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/GridTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/JsonTextTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/LayoutTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/MarkupTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/PadderTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/ProgressBarTests.cs (100%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/RowsTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/RuleTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionExtensionsTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/TextPathTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/TextTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Unit/Widgets/TreeTests.cs (99%) rename src/{Tests => }/Spectre.Console.Tests/Utilities/EmbeddedResourceReader.cs (61%) rename src/{Tests => }/Spectre.Console.Tests/Utilities/GitHubIssueAttribute.cs (100%) rename src/{Tests/Spectre.Console.Cli.Tests => Spectre.Console.Tests}/Utilities/ModuleInitializerAttribute.cs (100%) rename src/{Tests => }/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs (99%) rename src/{Tests/Spectre.Console.Cli.Tests => Spectre.Console.Tests}/VerifyConfiguration.cs (99%) delete mode 100644 src/Tests/.editorconfig delete mode 100644 src/Tests/Directory.Build.props delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Constants.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AnimalCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AsynchronousCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/CatCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DogCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DumpRemainingCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/EmptyCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GenericCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GiraffeCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GreeterCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HiddenOptionsCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HorseCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/InvalidCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/LionCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/NoDescriptionCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/OptionVectorCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/ThrowingCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/TurtleCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Commands/VersionCommand.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Converters/CatAgilityConverter.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Converters/StringToIntegerConverter.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Help/CustomHelpProvider.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Help/RedirectHelpProvider.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Help/RenderMarkupHelpProvider.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/AnimalSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ArgumentOrderSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ArgumentVectorSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/AsynchronousCommandSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/BarCommandSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/CatSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/DogSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/FooSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/GiraffeSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/HiddenOptionSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/HorseSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/InvalidSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/LionSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/MammalSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/MultipleArgumentVectorSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/OptionVectorSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/OptionalArgumentWithDefaultValueSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ReptileSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/RequiredOptionsSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/StringOptionSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ThrowingCommandSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/TurtleSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Settings/VersionSettings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Validators/EvenNumberValidatorAttribute.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Data/Validators/PositiveNumberValidatorAttribute.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/ArgumentOrder.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Called_Without_Help.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Default_Greeter.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Examples.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Command_Hide_Default.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Configured_By_Instance.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Configured_By_Type.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Registered_By_Instance.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Registered_By_Type.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Custom_Help_Provider.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Examples.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Greeter.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_DE.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_EN.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_FR.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_IT.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_JA.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_KO.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_PT.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_RU.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_SV.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_ZH-HANS.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_BoldHeadings.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_Default.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_None.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Description_No_Trailing_Period.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Hidden_Command_Options.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Hidden_Commands.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Leaf.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/NoDescription.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/NoVersion.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Required_Options.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Required_Options_No_Description.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root.QuestionMark.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Command.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Command.QuestionMark.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_Eight.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_None.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_Twelve.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_Eight.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_None.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_Twelve.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Version.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/OpenCli/Generate.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/CannotAssignValueToFlag/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/CannotAssignValueToFlag/Test_2.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_10.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_2.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_3.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_4.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_6.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_7.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_8.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_9.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Properties/Usings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Spectre.Console.Cli.Tests.csproj delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandArgumentAttributeTests.Rendering.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandArgumentAttributeTests.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandOptionAttributeTests.Rendering.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandOptionAttributeTests.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Async.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Branches.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Constructor.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Context.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Exceptions.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.FlagValues.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Help.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.Settings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Interceptor.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.OpenCli.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Options.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Pairs.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Parsing.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Remaining.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Sensitivity.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Settings.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.TypeConverters.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Unsafe.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Validation.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.ValueProviders.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Vectors.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.Help.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Xml.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/DefaultTypeRegistrarTests.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/Parsing/CommandTreeTokenizerTests.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/CommandAppTesterTests.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/FakeTypeRegistrarTests.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/InteractiveCommandTests.cs delete mode 100644 src/Tests/Spectre.Console.Cli.Tests/Utilities/CommandContextExtensions.cs delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/ArgumentCannotContainOptions.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInOptionName.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInValueName.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/LongOptionMustHaveMoreThanOneCharacter.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MissingLongAndShortName.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleOptionValuesAreNotSupported.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleValuesAreNotSupported.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionNamesCannotStartWithDigit.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionsMustHaveName.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/ShortOptionMustOnlyBeOneCharacter.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/UnexpectedCharacter.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/UnterminatedValueName.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/ValuesMustHaveName.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/InvalidShortOptionName/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameContainSymbol/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsMissing/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsOneCharacter/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameStartWithDigit/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoMatchingArgument/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_2.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_2.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_3.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_4.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_5.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_2.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_2.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_3.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_4.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_5.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_6.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_7.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_8.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_1.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_2.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Hidden_Command_Options.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_5.Output.verified.txt delete mode 100644 src/Tests/Spectre.Console.Tests/Utilities/ModuleInitializerAttribute.cs delete mode 100644 src/Tests/Spectre.Console.Tests/VerifyConfiguration.cs delete mode 100644 src/stylecop.json diff --git a/.editorconfig b/.editorconfig index 8ad4f171d..927012154 100644 --- a/.editorconfig +++ b/.editorconfig @@ -24,155 +24,4 @@ indent_size = 2 indent_size = 2 [*.md] -trim_trailing_whitespace = false - -[*.cs] -# Prefer file scoped namespace declarations -csharp_style_namespace_declarations = file_scoped:warning - -# Sort using and Import directives with System.* appearing first -dotnet_sort_system_directives_first = true -dotnet_separate_import_directive_groups = false - -# Avoid "this." and "Me." if not necessary -dotnet_style_qualification_for_field = false:refactoring -dotnet_style_qualification_for_property = false:refactoring -dotnet_style_qualification_for_method = false:refactoring -dotnet_style_qualification_for_event = false:refactoring - -# Use language keywords instead of framework type names for type references -dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion -dotnet_style_predefined_type_for_member_access = true:suggestion - -# Suggest more modern language features when available -dotnet_style_object_initializer = true:suggestion -dotnet_style_collection_initializer = true:suggestion -dotnet_style_coalesce_expression = true:suggestion -dotnet_style_null_propagation = true:suggestion -dotnet_style_explicit_tuple_names = true:suggestion - -# Non-private static fields are PascalCase -dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields -dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style -dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field -dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected -dotnet_naming_symbols.non_private_static_fields.required_modifiers = static -dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case - -# Non-private readonly fields are PascalCase -dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields -dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_field_style -dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field -dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected -dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly -dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case - -# Constants are PascalCase -dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants -dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style -dotnet_naming_symbols.constants.applicable_kinds = field, local -dotnet_naming_symbols.constants.required_modifiers = const -dotnet_naming_style.constant_style.capitalization = pascal_case - -# Instance fields are camelCase and start with _ -dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion -dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields -dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style -dotnet_naming_symbols.instance_fields.applicable_kinds = field -dotnet_naming_style.instance_field_style.capitalization = camel_case -dotnet_naming_style.instance_field_style.required_prefix = _ - -# Locals and parameters are camelCase -dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion -dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters -dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style -dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local -dotnet_naming_style.camel_case_style.capitalization = camel_case - -# Local functions are PascalCase -dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions -dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style -dotnet_naming_symbols.local_functions.applicable_kinds = local_function -dotnet_naming_style.local_function_style.capitalization = pascal_case - -# By default, name items with PascalCase -dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members -dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style -dotnet_naming_symbols.all_members.applicable_kinds = * -dotnet_naming_style.pascal_case_style.capitalization = pascal_case - -# Newline settings -csharp_new_line_before_open_brace = all -csharp_new_line_before_else = true -csharp_new_line_before_catch = true -csharp_new_line_before_finally = true -csharp_new_line_before_members_in_object_initializers = true -csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_between_query_expression_clauses = true - -# Indentation preferences -csharp_indent_block_contents = true -csharp_indent_braces = false -csharp_indent_case_contents = true -csharp_indent_case_contents_when_block = true -csharp_indent_switch_labels = true -csharp_indent_labels = flush_left - -# Prefer "var" everywhere -csharp_style_var_for_built_in_types = true:suggestion -csharp_style_var_when_type_is_apparent = true:suggestion -csharp_style_var_elsewhere = true:suggestion - -# Prefer method-like constructs to have a block body -csharp_style_expression_bodied_methods = false:none -csharp_style_expression_bodied_constructors = false:none -csharp_style_expression_bodied_operators = false:none - -# Prefer property-like constructs to have an expression-body -csharp_style_expression_bodied_properties = true:none -csharp_style_expression_bodied_indexers = true:none -csharp_style_expression_bodied_accessors = true:none - -# Suggest more modern language features when available -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion -csharp_style_inlined_variable_declaration = true:suggestion -csharp_style_throw_expression = true:suggestion -csharp_style_conditional_delegate_call = true:suggestion - -# Space preferences -csharp_space_after_cast = false -csharp_space_after_colon_in_inheritance_clause = true -csharp_space_after_comma = true -csharp_space_after_dot = false -csharp_space_after_keywords_in_control_flow_statements = true -csharp_space_after_semicolon_in_for_statement = true -csharp_space_around_binary_operators = before_and_after -csharp_space_around_declaration_statements = do_not_ignore -csharp_space_before_colon_in_inheritance_clause = true -csharp_space_before_comma = false -csharp_space_before_dot = false -csharp_space_before_open_square_brackets = false -csharp_space_before_semicolon_in_for_statement = false -csharp_space_between_empty_square_brackets = false -csharp_space_between_method_call_empty_parameter_list_parentheses = false -csharp_space_between_method_call_name_and_opening_parenthesis = false -csharp_space_between_method_call_parameter_list_parentheses = false -csharp_space_between_method_declaration_empty_parameter_list_parentheses = false -csharp_space_between_method_declaration_name_and_open_parenthesis = false -csharp_space_between_method_declaration_parameter_list_parentheses = false -csharp_space_between_parentheses = false -csharp_space_between_square_brackets = false - -# Blocks are allowed -csharp_prefer_braces = true:silent -csharp_preserve_single_line_blocks = true -csharp_preserve_single_line_statements = true - -# warning RS0037: PublicAPI.txt is missing '#nullable enable' -dotnet_diagnostic.RS0037.severity = none \ No newline at end of file +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e3aa89210..391f66265 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -28,12 +28,13 @@ jobs: dotnet-version: | 8.0.x 9.0.x + 10.0.x - name: Build shell: bash run: | dotnet tool restore - dotnet cake + dotnet make - name: Upload Verify Test Results if: failure() diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 983948e38..24c874f54 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -34,12 +34,13 @@ jobs: dotnet-version: | 8.0.x 9.0.x + 10.0.x - name: Publish shell: bash run: | dotnet tool restore - dotnet cake --target="publish" \ + dotnet make publish \ --nuget-key="${{secrets.NUGET_API_KEY}}" \ --github-key="${{secrets.GITHUB_TOKEN}}" diff --git a/README.md b/README.md index 9724aaa5c..9fe25f6be 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ It is heavily inspired by the excellent Python library, [Rich](https://github.co 1. [Installing](#installing) 1. [Documentation](#documentation) 1. [Examples](#examples) -1. [Sponsors](#sponsors) 1. [Code of Conduct](#code-of-conduct) 1. [.NET Foundation](#net-foundation) 1. [License](#license) @@ -52,26 +51,6 @@ https://spectreconsole.net To see `Spectre.Console` in action, please see the [examples repository](https://github.com/spectreconsole/examples). -## Sponsors - -The following people are [sponsoring](https://github.com/sponsors/patriksvensson) -`Spectre.Console` to show their support and to ensure the longevity of the project. - -* [Rodney Littles II](https://github.com/RLittlesII) -* [Martin Björkström](https://github.com/bjorkstromm) -* [Dave Glick](https://github.com/daveaglick) -* [Kim Gunnarsson](https://github.com/kimgunnarsson) -* [Andrew McClenaghan](https://github.com/andymac4182) -* [C. Augusto Proiete](https://github.com/augustoproiete) -* [Viktor Elofsson](https://github.com/vktr) -* [Steven Knox](https://github.com/stevenknox) -* [David Pendray](https://github.com/dpen2000) -* [Elmah.io](https://github.com/elmahio) -* [Tom Kerkhove](https://github.com/tomkerkhove) - -We really appreciate it. -**Thank you very much!** - ## Code of Conduct This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community. diff --git a/README.pt-BR.md b/README.pt-BR.md index 267dab194..ea15a20c0 100644 --- a/README.pt-BR.md +++ b/README.pt-BR.md @@ -9,11 +9,10 @@ para Python. ## Índice de Conteúdo 1. [Funcionalidades](#funcionalidades) -2. [Instalação](#instalação) -3. [Documentação](#documentação) -4. [Exemplos](#exemplos) -5. [Patrocinadores](#patrocinadores) -5. [Licença](#licença) +1. [Instalação](#instalação) +1. [Documentação](#documentação) +1. [Exemplos](#exemplos) +1. [Licença](#licença) ## Funcionalidades @@ -46,25 +45,6 @@ https://spectreconsole.net/ To see `Spectre.Console` in action, please see the [examples repository](https://github.com/spectreconsole/examples). -## Patrocinadores - -As seguintes pessoas estão [patrocinando](https://github.com/sponsors/patriksvensson) -o Spectre.Console para mostrar o seu apoio e garantir a longevidade do projeto. - -* [Rodney Littles II](https://github.com/RLittlesII) -* [Martin Björkström](https://github.com/bjorkstromm) -* [Dave Glick](https://github.com/daveaglick) -* [Kim Gunanrsson](https://github.com/kimgunnarsson) -* [Andrew McClenaghan](https://github.com/andymac4182) -* [C. Augusto Proiete](https://github.com/augustoproiete) -* [Viktor Elofsson](https://github.com/vktr) -* [Steven Knox](https://github.com/stevenknox) -* [David Pendray](https://github.com/dpen2000) -* [Elmah.io](https://github.com/elmahio) - -Eu estou muito agradecido. -**Muito obrigado!** - ## Licença Copyright © Patrik Svensson, Phil Scott, Nils Andresen, Cédric Luthi, Frank Ray diff --git a/README.zh.md b/README.zh.md index f6298737e..a775b1f9e 100644 --- a/README.zh.md +++ b/README.zh.md @@ -9,11 +9,10 @@ _[![Spectre.Console NuGet Version](https://img.shields.io/nuget/v/spectre.consol ## 目录 1. [功能](#功能) -2. [安装](#安装) -3. [文档](#文档) -4. [例子](#例子) -5. [Sponsors](#Sponsors) -6. [开源许可](#开源许可) +1. [安装](#安装) +1. [文档](#文档) +1. [例子](#例子) +1. [开源许可](#开源许可) ## 功能 @@ -42,24 +41,6 @@ https://spectreconsole.net/ To see `Spectre.Console` in action, please see the [examples repository](https://github.com/spectreconsole/examples). -## Sponsors - -下面这些用户正在[sponsor](https://github.com/sponsors/patriksvensson)上支持着Spectre.Console,确保这个项目的持续维护。 - -* [Rodney Littles II](https://github.com/RLittlesII) -* [Martin Björkström](https://github.com/bjorkstromm) -* [Dave Glick](https://github.com/daveaglick) -* [Kim Gunanrsson](https://github.com/kimgunnarsson) -* [Andrew McClenaghan](https://github.com/andymac4182) -* [C. Augusto Proiete](https://github.com/augustoproiete) -* [Viktor Elofsson](https://github.com/vktr) -* [Steven Knox](https://github.com/stevenknox) -* [David Pendray](https://github.com/dpen2000) -* [Elmah.io](https://github.com/elmahio) - -我对此表示十分感激 -**非常感谢各位!** - ## 开源许可 版权所有 © Patrik Svensson, Phil Scott, Nils Andresen, Cédric Luthi, Frank Ray diff --git a/build.cake b/build.cs similarity index 57% rename from build.cake rename to build.cs index 195ba510e..cda564fc9 100644 --- a/build.cake +++ b/build.cs @@ -1,3 +1,12 @@ +#:sdk Cake.Sdk@5.1.25296.94-beta + +var solution = "./src/Spectre.Console.slnx"; +var generatorSolution = "./resources/scripts/Generator/Generator.slnx"; +var testProject = "./src/Spectre.Console.Tests/Spectre.Console.Tests.csproj"; + +//////////////////////////////////////////////////////////////// +// Arguments + var target = Argument("target", "Default"); var configuration = Argument("configuration", "Release"); @@ -5,33 +14,31 @@ // Tasks Task("Clean") - .Does(context => + .Does(ctx => { - context.CleanDirectory("./.artifacts"); + ctx.CleanDirectory("./.artifacts"); }); -Task("Build") - .IsDependentOn("Clean") - .Does(context => +Task("Lint") + .Does(ctx => { - Information("Compiling generator..."); - DotNetBuild("./resources/scripts/Generator/Generator.slnx", new DotNetBuildSettings + ctx.DotNetFormat(solution, new DotNetFormatSettings { - Configuration = configuration, - Verbosity = DotNetVerbosity.Minimal, - NoLogo = true, - NoIncremental = context.HasArgument("rebuild"), - MSBuildSettings = new DotNetMSBuildSettings() - .TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error) + VerifyNoChanges = true, }); +}); - Information("\nCompiling Spectre.Console..."); - DotNetBuild("./src/Spectre.Console.slnx", new DotNetBuildSettings +Task("Build") + .IsDependentOn("Clean") + .IsDependentOn("Lint") + .Does(ctx => +{ + ctx.DotNetBuild(solution, new DotNetBuildSettings { Configuration = configuration, Verbosity = DotNetVerbosity.Minimal, NoLogo = true, - NoIncremental = context.HasArgument("rebuild"), + NoIncremental = ctx.HasArgument("rebuild"), MSBuildSettings = new DotNetMSBuildSettings() .TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error) }); @@ -39,17 +46,9 @@ Task("Test") .IsDependentOn("Build") - .Does(context => + .Does(ctx => { - DotNetTest("./src/Tests/Spectre.Console.Tests/Spectre.Console.Tests.csproj", new DotNetTestSettings { - Configuration = configuration, - Verbosity = DotNetVerbosity.Minimal, - NoLogo = true, - NoRestore = true, - NoBuild = true, - }); - - DotNetTest("./src/Tests/Spectre.Console.Cli.Tests/Spectre.Console.Cli.Tests.csproj", new DotNetTestSettings { + ctx.DotNetTest(testProject, new DotNetTestSettings { Configuration = configuration, Verbosity = DotNetVerbosity.Minimal, NoLogo = true, @@ -60,9 +59,9 @@ Task("Package") .IsDependentOn("Test") - .Does(context => + .Does(ctx => { - context.DotNetPack($"./src/Spectre.Console.slnx", new DotNetPackSettings + ctx.DotNetPack(solution, new DotNetPackSettings { Configuration = configuration, Verbosity = DotNetVerbosity.Minimal, @@ -78,17 +77,17 @@ Task("Publish-NuGet") .WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions") .IsDependentOn("Package") - .Does(context => + .Does(ctx => { - var apiKey = Argument("nuget-key", null); + var apiKey = Argument("nuget-key", null); if(string.IsNullOrWhiteSpace(apiKey)) { throw new CakeException("No NuGet API key was provided."); } // Publish to GitHub Packages - foreach(var file in context.GetFiles("./.artifacts/*.nupkg")) + foreach(var file in ctx.GetFiles("./.artifacts/*.nupkg")) { - context.Information("Publishing {0}...", file.GetFilename().FullPath); + ctx.Information("Publishing {0}...", file.GetFilename().FullPath); DotNetNuGetPush(file.FullPath, new DotNetNuGetPushSettings { Source = "https://api.nuget.org/v3/index.json", diff --git a/docs/Program.cs b/docs/Program.cs index c1e45183d..17ef606a4 100644 --- a/docs/Program.cs +++ b/docs/Program.cs @@ -22,7 +22,6 @@ await Bootstrapper.Factory .AddSetting(Constants.SourceFiles, new List { "../../src/Spectre.Console/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs", - "../../src/Spectre.Console.Cli/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs", "../../src/Spectre.Console.Testing/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs", "../../src/Extensions/Spectre.Console.ImageSharp/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs", "../../src/Extensions/Spectre.Console.Json/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs" diff --git a/docs/input/cli/commandApp.md b/docs/input/cli/commandApp.md index 83a4bc260..1bf4c2b74 100644 --- a/docs/input/cli/commandApp.md +++ b/docs/input/cli/commandApp.md @@ -1,9 +1,6 @@ Title: CommandApp Order: 2 Description: "**CommandApp** is the entry point for a *Spectre.Console.Cli* command line application. It is used to configure the settings and commands used for execution of the application." -Reference: - - T:Spectre.Console.Cli.CommandApp - - T:Spectre.Console.Cli.CommandApp`1 --- `CommandApp` is the entry point for a `Spectre.Console.Cli` command line application. It is used to configure the settings and commands used for execution of the application. Most `Spectre.Console.Cli` applications will need to specify a custom configuration using the `Configure` method. @@ -76,7 +73,7 @@ return app.Run(args); ``` - `MyTypeRegistrar` is a custom class that implements [ITypeRegistrar](xref:T:Spectre.Console.Cli.ITypeRegistrar) and must be provided by the user. + `MyTypeRegistrar` is a custom class that implements `ITypeRegistrar` and must be provided by the user. There is a working [example of dependency injection](https://github.com/spectreconsole/examples/tree/main/examples/Cli/Injection) that uses `Microsoft.Extensions.DependencyInjection` as the container. Example implementations of `ITypeRegistrar` and `ITypeResolver` are provided, which you can copy and paste to your application for dependency injection. diff --git a/docs/input/cli/commands.md b/docs/input/cli/commands.md index f77e0905e..6ae9564d2 100644 --- a/docs/input/cli/commands.md +++ b/docs/input/cli/commands.md @@ -1,9 +1,6 @@ Title: Creating Commands Order: 6 Description: "How to create commands for *Spectre.Console.Cli*" -Reference: - - T:Spectre.Console.Cli.AsyncCommand`1 - - T:Spectre.Console.Cli.Command`1 --- Commands in `Spectre.Console.Cli` are defined by creating a class that inherits from either `Command` or `AsyncCommand`. `Command` must implement an `Execute` method that returns an int where as `AsyncCommand` must implement `ExecuteAsync` returning `Task`. diff --git a/docs/input/cli/settings.md b/docs/input/cli/settings.md index ba44d707a..55710aeca 100644 --- a/docs/input/cli/settings.md +++ b/docs/input/cli/settings.md @@ -1,10 +1,6 @@ Title: Specifying Settings Order: 5 Description: "How to define command line argument settings for your *Spectre.Console.Cli* Commands" -Reference: - - T:Spectre.Console.Cli.CommandSettings - - T:Spectre.Console.Cli.CommandArgumentAttribute - - T:Spectre.Console.Cli.CommandOptionAttribute --- Settings for `Spectre.Console.Cli` commands are defined via classes that inherit from `CommandSettings`. Attributes are used to indicate how the parser interprets the command line arguments and create a runtime instance of the settings to be used. diff --git a/docs/input/cli/unit-testing.md b/docs/input/cli/unit-testing.md index d174737cd..45e87ad99 100644 --- a/docs/input/cli/unit-testing.md +++ b/docs/input/cli/unit-testing.md @@ -1,10 +1,6 @@ Title: Unit Testing Order: 14 Description: Instructions for unit testing a Spectre.Console application. -Reference: - - T:Spectre.Console.Testing.CommandAppTester - - T:Spectre.Console.Testing.TestConsole - - T:Spectre.Console.Testing.TestConsoleInput --- `Spectre.Console` has a separate project that contains test harnesses for unit testing your own console applications. diff --git a/dotnet-tools.json b/dotnet-tools.json index 549e7116e..116445f2c 100644 --- a/dotnet-tools.json +++ b/dotnet-tools.json @@ -2,17 +2,19 @@ "version": 1, "isRoot": true, "tools": { - "cake.tool": { - "version": "5.1.0", - "commands": [ - "dotnet-cake" - ] - }, "verify.tool": { "version": "0.6.0", "commands": [ "dotnet-verify" - ] + ], + "rollForward": false + }, + "make": { + "version": "0.8.0", + "commands": [ + "dotnet-make" + ], + "rollForward": false } } } \ No newline at end of file diff --git a/global.json b/global.json index 0f15a22eb..ca25c41e5 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "$schema": "http://json.schemastore.org/global", "sdk": { - "version": "9.0.306", + "version": "10.0.100-rc.2.25502.107", "rollForward": "latestFeature" } } diff --git a/resources/nuget/Spectre.Console.Cli.md b/resources/nuget/Spectre.Console.Cli.md deleted file mode 100644 index 898df57f4..000000000 --- a/resources/nuget/Spectre.Console.Cli.md +++ /dev/null @@ -1,5 +0,0 @@ -# `Spectre.Console.Cli` - -`Spectre.Console.Cli` is a modern library for parsing command line arguments. While it's extremely opinionated in what it does, it tries to follow established industry conventions, and draws its inspiration from applications you use everyday. - -Detailed instructions for using this library is located on the project website, https://spectreconsole.net \ No newline at end of file diff --git a/resources/scripts/Generate-Colors.ps1 b/resources/scripts/Generate-Colors.ps1 old mode 100644 new mode 100755 index 62a355472..bc99bb8e0 --- a/resources/scripts/Generate-Colors.ps1 +++ b/resources/scripts/Generate-Colors.ps1 @@ -1,8 +1,11 @@ +#!/usr/local/bin/pwsh + ########################################################## # Script that generates known colors and lookup tables. ########################################################## $Output = Join-Path $PSScriptRoot "Temp" +$Generator = Join-Path $PSScriptRoot "/../../src/Generator" $Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console" if(!(Test-Path $Output -PathType Container)) { @@ -10,7 +13,7 @@ if(!(Test-Path $Output -PathType Container)) { } # Generate the files -Push-Location Generator +Push-Location $Generator &dotnet run -- colors "$Output" if(!$?) { Pop-Location diff --git a/resources/scripts/Generate-Emoji.ps1 b/resources/scripts/Generate-Emoji.ps1 old mode 100644 new mode 100755 index 074d41473..41dee1029 --- a/resources/scripts/Generate-Emoji.ps1 +++ b/resources/scripts/Generate-Emoji.ps1 @@ -1,8 +1,11 @@ +#!/usr/local/bin/pwsh + ########################################################## # Script that generates the emoji lookup table. ########################################################## $Output = Join-Path $PSScriptRoot "Temp" +$Generator = Join-Path $PSScriptRoot "/../../src/Generator" $Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console" $Docs = Join-Path $PSScriptRoot "/../../docs/src/Data" @@ -11,7 +14,7 @@ if(!(Test-Path $Output -PathType Container)) { } # Generate the files -Push-Location Generator +Push-Location $Generator &dotnet run -- emoji "$Output" --input $Output if(!$?) { Pop-Location diff --git a/resources/scripts/Generate-Samples.ps1 b/resources/scripts/Generate-Samples.ps1 old mode 100644 new mode 100755 index 51c5b62f5..3843cf40b --- a/resources/scripts/Generate-Samples.ps1 +++ b/resources/scripts/Generate-Samples.ps1 @@ -1,11 +1,22 @@ +#!/usr/local/bin/pwsh + +[CmdletBinding(PositionalBinding=$false)] +Param( + [Parameter(ValueFromRemainingArguments)] + [string[]]$Remaining +) + # first arg is either the name of a single sample you want to run or leave # blank if you want to run them all. the samples aren't going to run at the same # speed each time so if you run all of them you'll have everything as a change # for your commit so use this sparingly. +$Generator = Join-Path $PSScriptRoot "/../../src/Generator" +$Output = Join-Path $PSScriptRoot "../../docs/input/assets/casts" + # Generate the files -Push-Location Generator -dotnet run -- samples -o "../../../docs/input/assets/casts" $args[0] +Push-Location $Generator +&dotnet run -- samples -o "$Output" $Remaining if(!$?) { Pop-Location Throw "An error occured when generating code." diff --git a/resources/scripts/Generate-Spinners.ps1 b/resources/scripts/Generate-Spinners.ps1 old mode 100644 new mode 100755 index c96484493..a802eba48 --- a/resources/scripts/Generate-Spinners.ps1 +++ b/resources/scripts/Generate-Spinners.ps1 @@ -1,8 +1,11 @@ +#!/usr/local/bin/pwsh + ########################################################## # Script that generates progress spinners. ########################################################## $Output = Join-Path $PSScriptRoot "Temp" +$Generator = Join-Path $PSScriptRoot "/../../src/Generator" $Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console" if(!(Test-Path $Output -PathType Container)) { @@ -10,8 +13,8 @@ if(!(Test-Path $Output -PathType Container)) { } # Generate the files -Push-Location Generator -&dotnet run -- spinners "$Output" --input $Output +Push-Location $Generator +&dotnet run -- spinners "$Output" if(!$?) { Pop-Location Throw "An error occured when generating code." diff --git a/resources/scripts/Generator/Commands/AsciiCast/AnsiConsoleExtensions.cs b/resources/scripts/Generator/Commands/AsciiCast/AnsiConsoleExtensions.cs deleted file mode 100644 index 927eaa07e..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/AnsiConsoleExtensions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using Spectre.Console; -using Generator.Commands; -using System.Threading; - -namespace DocExampleGenerator -{ - internal static class AnsiConsoleExtensions - { - /// - /// Displays something via AnsiConsole, waits a bit and then simulates typing based on the input. If the console - /// doesn't have the focus this will just type into whatever window does so watch the alt-tab. - /// - /// - /// The display action. - /// The characters to type. ↑ for an up arrow, ↓ for down arrow, ↲ for a return and ¦ for a pause. - /// How long to delay before typing. This should be at least 100ms because we won't check if the prompt has displayed before simulating typing. - /// Delay between keypresses. There will be a bit of randomness between each keypress +/- 20% of this value. - public static void DisplayThenType(this IAnsiConsole console, Action action, string input, int initialDelayMs = 500, int keypressDelayMs = 200) - { - if (console is not AsciiCastConsole asciiConsole) - { - throw new InvalidOperationException("Not an ASCII cast console"); - } - - asciiConsole.Input.PushText(input, keypressDelayMs); - - Thread.Sleep(initialDelayMs); - - action(console); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/AsciiCastConsole.cs b/resources/scripts/Generator/Commands/AsciiCast/AsciiCastConsole.cs deleted file mode 100644 index d3bece75c..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/AsciiCastConsole.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using Spectre.Console; -using Spectre.Console.Rendering; - -namespace Generator.Commands -{ - public sealed class AsciiCastConsole : IAnsiConsole - { - private readonly IAnsiConsole _console; - private readonly AsciiCastInput _input; - - public Profile Profile => _console.Profile; - - public IAnsiConsoleCursor Cursor => _console.Cursor; - - IAnsiConsoleInput IAnsiConsole.Input => _input; - - public AsciiCastInput Input => _input; - - public IExclusivityMode ExclusivityMode => _console.ExclusivityMode; - - public RenderPipeline Pipeline => _console.Pipeline; - - public AsciiCastConsole(IAnsiConsole console) - { - _console = console ?? throw new ArgumentNullException(nameof(console)); - _input = new AsciiCastInput(); - } - - public void Clear(bool home) - { - _console.Clear(home); - } - - public void Write(IRenderable renderable) - { - _console.Write(renderable); - } - } -} diff --git a/resources/scripts/Generator/Commands/AsciiCast/AsciiCastExtensions.cs b/resources/scripts/Generator/Commands/AsciiCast/AsciiCastExtensions.cs deleted file mode 100644 index 307e1e6a6..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/AsciiCastExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Spectre.Console; - -namespace Generator.Commands -{ - public static class AsciiCastExtensions - { - public static AsciiCastOut WrapWithAsciiCastRecorder(this IAnsiConsole ansiConsole) - { - AsciiCastOut castRecorder = new(ansiConsole.Profile.Out); - ansiConsole.Profile.Out = castRecorder; - - return castRecorder; - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/AsciiCastInput.cs b/resources/scripts/Generator/Commands/AsciiCast/AsciiCastInput.cs deleted file mode 100644 index bf98d9381..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/AsciiCastInput.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Spectre.Console; - -namespace Generator.Commands -{ - public sealed class AsciiCastInput : IAnsiConsoleInput - { - private readonly Queue<(ConsoleKeyInfo?, int)> _input; - private readonly Random _random = new Random(); - - public AsciiCastInput() - { - _input = new Queue<(ConsoleKeyInfo?, int)>(); - } - - public void PushText(string input, int keypressDelayMs) - { - if (input is null) - { - throw new ArgumentNullException(nameof(input)); - } - - foreach (var character in input) - { - PushCharacter(character, keypressDelayMs); - } - } - - public void PushTextWithEnter(string input, int keypressDelayMs) - { - PushText(input, keypressDelayMs); - PushKey(ConsoleKey.Enter, keypressDelayMs); - } - - public void PushCharacter(char input, int keypressDelayMs) - { - var delay = keypressDelayMs + _random.Next((int)(keypressDelayMs * -.2), (int)(keypressDelayMs * .2)); - - switch (input) - { - case '↑': - PushKey(ConsoleKey.UpArrow, keypressDelayMs); - break; - case '↓': - PushKey(ConsoleKey.DownArrow, keypressDelayMs); - break; - case '↲': - PushKey(ConsoleKey.Enter, keypressDelayMs); - break; - case '¦': - _input.Enqueue((null, delay)); - break; - default: - var control = char.IsUpper(input); - _input.Enqueue((new ConsoleKeyInfo(input, (ConsoleKey)input, false, false, control), delay)); - break; - } - } - - public void PushKey(ConsoleKey input, int keypressDelayMs) - { - var delay = keypressDelayMs + _random.Next((int)(keypressDelayMs * -.2), (int)(keypressDelayMs * .2)); - _input.Enqueue((new ConsoleKeyInfo((char)input, input, false, false, false), delay)); - } - - public bool IsKeyAvailable() - { - return _input.Count > 0; - } - - public ConsoleKeyInfo? ReadKey(bool intercept) - { - if (_input.Count == 0) - { - throw new InvalidOperationException("No input available."); - } - - var result = _input.Dequeue(); - - Thread.Sleep(result.Item2); - return result.Item1; - } - - public Task ReadKeyAsync(bool intercept, CancellationToken cancellationToken) - { - return Task.FromResult(ReadKey(intercept)); - } - } -} diff --git a/resources/scripts/Generator/Commands/AsciiCast/AsciiCastOut.cs b/resources/scripts/Generator/Commands/AsciiCast/AsciiCastOut.cs deleted file mode 100644 index ff63e3c03..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/AsciiCastOut.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Globalization; -using System.IO; -using System.Text; -using System.Text.Json; -using Spectre.Console; - -namespace Generator.Commands -{ - public class AsciiCastOut : IAnsiConsoleOutput - { - private sealed class AsciiCastWriter : TextWriter - { - private readonly TextWriter _wrappedTextWriter; - private readonly StringBuilder _builder = new StringBuilder(); - private int? _firstTick; - - public AsciiCastWriter(TextWriter wrappedTextWriter) - { - _wrappedTextWriter = wrappedTextWriter; - } - - public override void Write(string value) - { - if (value == null) - { - return; - } - - Append(value); - _wrappedTextWriter.Write(value); - base.Write(value); - } - - public override Encoding Encoding => _wrappedTextWriter.Encoding; - - private void Append(string value) - { - var tick = 0m; - if (_firstTick.HasValue) - { - tick = Environment.TickCount - _firstTick.Value; - } - else - { - _firstTick = Environment.TickCount; - } - - tick /= 1000m; - - _builder.Append('[') - .AppendFormat(CultureInfo.InvariantCulture, "{0}", tick) - .Append(", \"o\", \"").Append(JsonEncodedText.Encode(value)).AppendLine("\"]"); - } - - public string GetJsonAndClearBuffer() - { - var json = _builder.ToString(); - - // reset the buffer and also reset the first tick count - _builder.Clear(); - _firstTick = null; - return json; - } - } - - private readonly IAnsiConsoleOutput _wrappedAnsiConsole; - private readonly AsciiCastWriter _asciiCastWriter; - - public AsciiCastOut(IAnsiConsoleOutput wrappedAnsiConsole) - { - _wrappedAnsiConsole = wrappedAnsiConsole ?? throw new ArgumentNullException(nameof(wrappedAnsiConsole)); - _asciiCastWriter = new AsciiCastWriter(_wrappedAnsiConsole.Writer); - } - - public TextWriter Writer => _asciiCastWriter; - - public bool IsTerminal => _wrappedAnsiConsole.IsTerminal; - - public int Width => _wrappedAnsiConsole.Width; - - public int Height => _wrappedAnsiConsole.Height; - - public void SetEncoding(Encoding encoding) - { - _wrappedAnsiConsole.SetEncoding(encoding); - } - - public string GetCastJson(string title, int? width = null, int? height = null) - { - var header = $"{{\"version\": 2, \"width\": {width ?? _wrappedAnsiConsole.Width}, \"height\": {height ?? _wrappedAnsiConsole.Height}, \"title\": \"{JsonEncodedText.Encode(title)}\", \"env\": {{\"TERM\": \"Spectre.Console\"}}}}"; - return $"{header}{Environment.NewLine}{_asciiCastWriter.GetJsonAndClearBuffer()}{Environment.NewLine}"; - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/BarChartSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/BarChartSample.cs deleted file mode 100644 index 0f5ad70db..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/BarChartSample.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class BarChartSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 5); - - public override void Run(IAnsiConsole console) - { - console.Write(new BarChart() - .Width(60) - .Label("[green bold underline]Number of fruits[/]") - .CenterLabel() - .AddItem("Apple", 12, Color.Yellow) - .AddItem("Orange", 54, Color.Green) - .AddItem("Banana", 33, Color.Red)); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/BaseSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/BaseSample.cs deleted file mode 100644 index 75a7d9949..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/BaseSample.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - public abstract class BaseSample - { - public abstract void Run(IAnsiConsole console); - public virtual string Name() => PascalToKebab(GetType().Name.Replace("Sample","")); - public virtual (int Cols, int Rows) ConsoleSize => (82, 24); - public virtual IEnumerable<(string Name, Action CapabilitiesAction)> GetCapabilities() - { - return new (string Name, Action CapabilitiesAction)[] - { - ("plain", capabilities => - { - capabilities.Unicode = false; - capabilities.Ansi = true; - capabilities.Interactive = true; - capabilities.Legacy = false; - capabilities.Links = false; - capabilities.ColorSystem = ColorSystem.Legacy; - }), - ("rich", capabilities => - { - capabilities.Unicode = true; - capabilities.Ansi = true; - capabilities.Interactive = true; - capabilities.Legacy = false; - capabilities.Links = false; - capabilities.ColorSystem = ColorSystem.TrueColor; - }), - }; - } - - private string PascalToKebab(ReadOnlySpan input) - { - var sb = new StringBuilder(); - var previousUpper = true; - foreach (var chr in input) - { - if (char.IsUpper(chr) && previousUpper == false) - { - sb.Append('-'); - previousUpper = true; - } - else - { - previousUpper = false; - } - - sb.Append(char.ToLower(chr)); - } - - return sb.ToString(); - - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/BreakdownChartSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/BreakdownChartSample.cs deleted file mode 100644 index 0f736b5df..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/BreakdownChartSample.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class BreakdownChartSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 5); - - public override void Run(IAnsiConsole console) - { - console.Write(new BreakdownChart() - .Width(60) - .AddItem("SCSS", 80, Color.Red) - .AddItem("HTML", 28.3, Color.Blue) - .AddItem("C#", 22.6, Color.Green) - .AddItem("JavaScript", 6, Color.Yellow) - .AddItem("Ruby", 6, Color.LightGreen) - .AddItem("Shell", 0.1, Color.Aqua)); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/CalendarSamples.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/CalendarSamples.cs deleted file mode 100644 index f13d14b1c..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/CalendarSamples.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal abstract class BaseCalendarSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 12); - } - - internal class CalendarSample : BaseCalendarSample - { - - public override void Run(IAnsiConsole console) => console.Write(new Calendar(2020,10)); - } - - internal class CalendarCultureSample : BaseCalendarSample - { - public override void Run(IAnsiConsole console) => console.Write(new Calendar(2020,10).Culture("sv-SE")); - } - - internal class CalendarHeader : BaseCalendarSample - { - public override void Run(IAnsiConsole console) - { - var calendar = new Calendar(2020,10); - calendar.HeaderStyle(Style.Parse("blue bold")); - console.Write(calendar); - } - } - - internal class CalendarHighlightSample : BaseCalendarSample - { - public override void Run(IAnsiConsole console) - { - var calendar = new Calendar(2020, 10).HighlightStyle(Style.Parse("yellow bold")); - calendar.AddCalendarEvent(2020, 10, 11); - console.Write(calendar); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/CanvasImageSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/CanvasImageSample.cs deleted file mode 100644 index 5d3c9bb8c..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/CanvasImageSample.cs +++ /dev/null @@ -1,27 +0,0 @@ -using SixLabors.ImageSharp.Processing; -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class CanvasImageSample : BaseSample - { - public override void Run(IAnsiConsole console) - { - var image = new CanvasImage("../../../examples/Console/Canvas/cake.png"); - image.MaxWidth(16); - console.Write(image); - } - } - - internal class CanvasImageManipulationSample : BaseSample - { - public override void Run(IAnsiConsole console) - { - var image = new CanvasImage("../../../examples/Console/Canvas/cake.png"); - image.MaxWidth(24); - image.BilinearResampler(); - image.Mutate(ctx => ctx.Grayscale().Rotate(-45).EntropyCrop()); - console.Write(image); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/CanvasSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/CanvasSample.cs deleted file mode 100644 index 0a067424c..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/CanvasSample.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class CanvasSample : BaseSample - { - public override void Run(IAnsiConsole console) - { - var canvas = new Canvas(16, 16); - - // Draw some shapes - for(var i = 0; i < canvas.Width; i++) - { - // Cross - canvas.SetPixel(i, i, Color.White); - canvas.SetPixel(canvas.Width - i - 1, i, Color.White); - - // Border - canvas.SetPixel(i, 0, Color.Red); - canvas.SetPixel(0, i, Color.Green); - canvas.SetPixel(i, canvas.Height - 1, Color.Blue); - canvas.SetPixel(canvas.Width - 1, i, Color.Yellow); - } - - // Render the canvas - console.Write(canvas); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/Exceptions.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/Exceptions.cs deleted file mode 100644 index 4c9edd621..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/Exceptions.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Security.Authentication; -using Generator.Commands.Samples; -using Spectre.Console; - -// keep the namespace here short because it'll be used in the display of the exceptions -// and we want to keep that below 100 characters wide. -namespace Samples -{ - public class Exceptions - { - internal abstract class BaseExceptionSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (100, 12); - - protected readonly Exception Exception = null!; - - protected BaseExceptionSample() - { - try - { - DoMagic(42, null); - } - catch (Exception ex) - { - Exception = ex; - } - } - } - - internal class DefaultExceptionSample : BaseExceptionSample - { - public override void Run(IAnsiConsole console) => console.WriteException(Exception, ExceptionFormats.ShortenPaths); - } - - internal class ShortenedExceptionSample : BaseExceptionSample - { - public override void Run(IAnsiConsole console) => console.WriteException(Exception, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks); - } - - internal class CustomColorsExceptionSample : BaseExceptionSample - { - public override void Run(IAnsiConsole console) - { - console.WriteException(Exception, new ExceptionSettings - { - Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks, - Style = new ExceptionStyle - { - Exception = new Style().Foreground(Color.Grey), - Message = new Style().Foreground(Color.White), - NonEmphasized = new Style().Foreground(Color.Cornsilk1), - Parenthesis = new Style().Foreground(Color.Cornsilk1), - Method = new Style().Foreground(Color.Red), - ParameterName = new Style().Foreground(Color.Cornsilk1), - ParameterType = new Style().Foreground(Color.Red), - Path = new Style().Foreground(Color.Red), - LineNumber = new Style().Foreground(Color.Cornsilk1), - } - }); - } - } - - private static void DoMagic(int foo, string[,] bar) - { - try - { - CheckCredentials(foo, bar); - } - catch(Exception ex) - { - throw new InvalidOperationException("Whaaat?", ex); - } - } - - private static void CheckCredentials(int qux, string[,] corgi) - { - throw new InvalidCredentialException("The credentials are invalid."); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/FigletSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/FigletSample.cs deleted file mode 100644 index eb926b574..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/FigletSample.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - public class FigletSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (100, 24); - - public override void Run(IAnsiConsole console) - { - console.Write(new FigletText("Left aligned").LeftJustified().Color(Color.Red)); - console.Write(new FigletText("Centered").Centered().Color(Color.Green)); - console.Write(new FigletText("Right aligned").RightJustified().Color(Color.Blue)); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/InputSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/InputSample.cs deleted file mode 100644 index d4171281c..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/InputSample.cs +++ /dev/null @@ -1,97 +0,0 @@ -using DocExampleGenerator; -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class InputSample : BaseSample - { - public override void Run(IAnsiConsole console) - { - var age = 0; - var name = string.Empty; - var sport = string.Empty; - var password = string.Empty; - var color = string.Empty; - - console.DisplayThenType(c => name = AskName(c), "Peter F↲"); - console.DisplayThenType(c => sport = AskSport(c), "football↲¦¦¦¦Hockey↲"); - console.DisplayThenType(c => age = AskAge(c), "Forty↲¦¦¦¦40↲"); - console.DisplayThenType(c => password = AskPassword(c), "hunter2↲"); - console.DisplayThenType(c => color = AskColor(c), "↲"); - - AnsiConsole.Write(new Rule("[yellow]Results[/]").RuleStyle("grey").LeftJustified()); - AnsiConsole.Write(new Table().AddColumns("[grey]Question[/]", "[grey]Answer[/]") - .RoundedBorder() - .BorderColor(Color.Grey) - .AddRow("[grey]Name[/]", name) - .AddRow("[grey]Favorite sport[/]", sport) - .AddRow("[grey]Age[/]", age.ToString()) - .AddRow("[grey]Password[/]", password) - .AddRow("[grey]Favorite color[/]", string.IsNullOrEmpty(color) ? "Unknown" : color)); - } - - private static string AskName(IAnsiConsole console) - { - console.WriteLine(); - console.Write(new Rule("[yellow]Strings[/]").RuleStyle("grey").LeftJustified()); - var name = console.Ask("What's your [green]name[/]?"); - return name; - } - - - private static string AskSport(IAnsiConsole console) - { - console.WriteLine(); - console.Write(new Rule("[yellow]Choices[/]").RuleStyle("grey").LeftJustified()); - - return console.Prompt( - new TextPrompt("What's your [green]favorite sport[/]?") - .InvalidChoiceMessage("[red]That's not a sport![/]") - .DefaultValue("Sport?") - .AddChoice("Soccer") - .AddChoice("Hockey") - .AddChoice("Basketball")); - } - - private static int AskAge(IAnsiConsole console) - { - console.WriteLine(); - console.Write(new Rule("[yellow]Integers[/]").RuleStyle("grey").LeftJustified()); - - return console.Prompt( - new TextPrompt("How [green]old[/] are you?") - .PromptStyle("green") - .ValidationErrorMessage("[red]That's not a valid age[/]") - .Validate(age => - { - return age switch - { - <= 0 => ValidationResult.Error("[red]You must at least be 1 years old[/]"), - >= 123 => ValidationResult.Error("[red]You must be younger than the oldest person alive[/]"), - _ => ValidationResult.Success(), - }; - })); - } - - private static string AskPassword(IAnsiConsole console) - { - console.WriteLine(); - console.Write(new Rule("[yellow]Secrets[/]").RuleStyle("grey").LeftJustified()); - - return console.Prompt( - new TextPrompt("Enter [green]password[/]?") - .PromptStyle("red") - .Secret()); - } - - private static string AskColor(IAnsiConsole console) - { - console.WriteLine(); - console.Write(new Rule("[yellow]Optional[/]").RuleStyle("grey").LeftJustified()); - - return console.Prompt( - new TextPrompt("[grey][[Optional]][/] What is your [green]favorite color[/]?") - .AllowEmpty()); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/JsonSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/JsonSample.cs deleted file mode 100644 index 07331de4b..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/JsonSample.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Spectre.Console; -using Spectre.Console.Json; - -namespace Generator.Commands.Samples -{ - public class JsonSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (60, 20); - - public override void Run(IAnsiConsole console) - { - var json = new JsonText( - """ - { - "hello": 32, - "world": { - "foo": 21, - "bar": 255, - "baz": [ - 0.32, 0.33e-32, - 0.42e32, 0.55e+32, - { - "hello": "world", - "lol": null - } - ] - } - } - """); - - AnsiConsole.Write( - new Panel(json) - .Header("Some JSON in a panel") - .Collapse() - .RoundedBorder() - .BorderColor(Color.Yellow)); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/LayoutSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/LayoutSample.cs deleted file mode 100644 index 832592f8e..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/LayoutSample.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Spectre.Console; -using Spectre.Console.Json; - -namespace Generator.Commands.Samples -{ - public class LayoutSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (80, 24); - - public override void Run(IAnsiConsole console) - { - var layout = new Layout("Root") - .SplitColumns( - new Layout("Left"), - new Layout("Right") - .SplitRows( - new Layout("Top"), - new Layout("Bottom"))); - - layout["Left"].Update( - new Panel( - Align.Center( - new Markup("Hello [blue]World![/]"), - VerticalAlignment.Middle)) - .Expand()); - - AnsiConsole.Write(layout); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/LiveSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/LiveSample.cs deleted file mode 100644 index ed24f5e86..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/LiveSample.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Threading; -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class LiveSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (100, 20); - - public override void Run(IAnsiConsole console) - { - var table = new Table(); - - // Animate - console.Live(table) - .AutoClear(false) - .Overflow(VerticalOverflow.Ellipsis) - .Cropping(VerticalOverflowCropping.Top) - .Start(ctx => - { - void Update(int delay, Action action) - { - action(); - ctx.Refresh(); - Thread.Sleep(delay); - } - - // Columns - Update(230, () => table.AddColumn("Release date")); - Update(230, () => table.AddColumn("Title")); - Update(230, () => table.AddColumn("Budget")); - Update(230, () => table.AddColumn("Opening Weekend")); - Update(230, () => table.AddColumn("Box office")); - - // Rows - Update(70, () => table.AddRow("May 25, 1977", "[yellow]Star Wars[/] [grey]Ep.[/] [u]IV[/]", "$11,000,000", "$1,554,475", "$775,398,007")); - Update(70, () => table.AddRow("May 21, 1980", "[yellow]Star Wars[/] [grey]Ep.[/] [u]V[/]", "$18,000,000", "$4,910,483", "$547,969,004")); - Update(70, () => table.AddRow("May 25, 1983", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VI[/]", "$32,500,000", "$23,019,618", "$475,106,177")); - Update(70, () => table.AddRow("May 19, 1999", "[yellow]Star Wars[/] [grey]Ep.[/] [u]I[/]", "$115,000,000", "$64,810,870", "$1,027,044,677")); - Update(70, () => table.AddRow("May 16, 2002", "[yellow]Star Wars[/] [grey]Ep.[/] [u]II[/]", "$115,000,000", "$80,027,814", "$649,436,358")); - Update(70, () => table.AddRow("May 19, 2005", "[yellow]Star Wars[/] [grey]Ep.[/] [u]III[/]", "$113,000,000", "$108,435,841", "$850,035,635")); - Update(70, () => table.AddRow("Dec 18, 2015", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VII[/]", "$245,000,000", "$247,966,675", "$2,068,223,624")); - Update(70, () => table.AddRow("Dec 15, 2017", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VIII[/]", "$317,000,000", "$220,009,584", "$1,333,539,889")); - Update(70, () => table.AddRow("Dec 20, 2019", "[yellow]Star Wars[/] [grey]Ep.[/] [u]IX[/]", "$245,000,000", "$177,383,864", "$1,074,114,248")); - - // Column footer - Update(230, () => table.Columns[2].Footer("$1,633,000,000")); - Update(230, () => table.Columns[3].Footer("$928,119,224")); - Update(400, () => table.Columns[4].Footer("$10,318,030,576")); - - // Column alignment - Update(230, () => table.Columns[2].RightAligned()); - Update(230, () => table.Columns[3].RightAligned()); - Update(400, () => table.Columns[4].RightAligned()); - - // Column titles - Update(70, () => table.Columns[0].Header("[bold]Release date[/]")); - Update(70, () => table.Columns[1].Header("[bold]Title[/]")); - Update(70, () => table.Columns[2].Header("[red bold]Budget[/]")); - Update(70, () => table.Columns[3].Header("[green bold]Opening Weekend[/]")); - Update(400, () => table.Columns[4].Header("[blue bold]Box office[/]")); - - // Footers - Update(70, () => table.Columns[2].Footer("[red bold]$1,633,000,000[/]")); - Update(70, () => table.Columns[3].Footer("[green bold]$928,119,224[/]")); - Update(400, () => table.Columns[4].Footer("[blue bold]$10,318,030,576[/]")); - - // Title - Update(500, () => table.Title("Star Wars Movies")); - Update(400, () => table.Title("[[ [yellow]Star Wars Movies[/] ]]")); - - // Borders - Update(230, () => table.BorderColor(Color.Yellow)); - Update(230, () => table.MinimalBorder()); - Update(230, () => table.SimpleBorder()); - Update(230, () => table.SimpleHeavyBorder()); - - // Caption - Update(400, () => table.Caption("[[ [blue]THE END[/] ]]")); - }); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/MultiSelectionSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/MultiSelectionSample.cs deleted file mode 100644 index 04cbc415a..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/MultiSelectionSample.cs +++ /dev/null @@ -1,40 +0,0 @@ -using DocExampleGenerator; -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class MultiSelectionSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 14); - - public override void Run(IAnsiConsole console) - { - console.DisplayThenType(AskFruit, "↓↓ ¦¦↑↑ ¦¦ ¦¦↓ ↓↓↓↓↓ ↓↓↓↓ ¦¦↲"); - } - - private static void AskFruit(IAnsiConsole console) - { - var favorites = console.Prompt( - new MultiSelectionPrompt() - .PageSize(10) - .Title("What are your [green]favorite fruits[/]?") - .MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]") - .InstructionsText("[grey](Press [blue][/] to toggle a fruit, [green][/] to accept)[/]") - .AddChoiceGroup("Berries", new[] - { - "Blackcurrant", "Blueberry", "Cloudberry", - "Elderberry", "Honeyberry", "Mulberry" - }) - .AddChoices(new[] - { - "Apple", "Apricot", "Avocado", "Banana", - "Cherry", "Cocunut", "Date", "Dragonfruit", "Durian", - "Egg plant", "Fig", "Grape", "Guava", - "Jackfruit", "Jambul", "Kiwano", "Kiwifruit", "Lime", "Lylo", - "Lychee", "Melon", "Nectarine", "Orange", "Olive" - })); - - console.MarkupLine("Your selected: [yellow]{0}[/]", string.Join(',', favorites)); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/PanelSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/PanelSample.cs deleted file mode 100644 index b99addfc0..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/PanelSample.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class PanelSample : BaseSample - { - public override void Run(IAnsiConsole console) - { - var panel = new Panel("[red]Spaghetti\nLinguini\nFettucine\nTortellini\nCapellini\nLasagna[/]"); - panel.Header = new PanelHeader("[underline]Pasta Menu[/]", Justify.Center); - panel.Border = BoxBorder.Double; - panel.Padding = new Padding(2, 2, 2, 2); - console.Write(panel); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/ProgressSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/ProgressSample.cs deleted file mode 100644 index 217cc2eec..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/ProgressSample.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class ProgressSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 10); - - public override IEnumerable<(string Name, Action CapabilitiesAction)> GetCapabilities() - { - yield return ("non-interactive", capabilities => - { - capabilities.Ansi = false; - capabilities.Interactive = false; - capabilities.Legacy = false; - capabilities.Unicode = true; - capabilities.ColorSystem = ColorSystem.TrueColor; - }); - - foreach (var capability in base.GetCapabilities()) - { - yield return capability; - } - } - - public override void Run(IAnsiConsole console) - { - // Show progress - console.Progress() - .AutoClear(false) - .Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new RemainingTimeColumn(), new SpinnerColumn()) - .Start(ctx => - { - var random = new Random(122978); - - // Create some tasks - var tasks = CreateTasks(ctx, random); - var warpTask = ctx.AddTask("Going to warp", autoStart: false).IsIndeterminate(); - - // Wait for all tasks (except the indeterminate one) to complete - while (!ctx.IsFinished) - { - // Increment progress - foreach (var (task, increment) in tasks) - { - task.Increment(random.NextDouble() * increment); - } - - // Simulate some delay - Thread.Sleep(100); - } - - // Now start the "warp" task - warpTask.StartTask(); - warpTask.IsIndeterminate(false); - while (!ctx.IsFinished) - { - warpTask.Increment(12 * random.NextDouble()); - - // Simulate some delay - Thread.Sleep(100); - } - }); - } - - private static List<(ProgressTask Task, int Delay)> CreateTasks(ProgressContext progress, Random random) - { - var tasks = new List<(ProgressTask, int)>(); - - var names = new[] - { - "Retriculating algorithms", "Colliding splines", "Solving quarks", "Folding data structures", - "Rerouting capacitators " - }; - - for (var i = 0; i < 5; i++) - { - tasks.Add((progress.AddTask(names[i]), random.Next(2, 10))); - } - - return tasks; - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/RuleSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/RuleSample.cs deleted file mode 100644 index dd3eb6ae5..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/RuleSample.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class RuleSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (82, 10); - - public override void Run(IAnsiConsole console) - { - console.Write(new Rule()); - console.WriteLine(); - console.Write(new Rule("[blue]Left aligned[/]").LeftJustified().RuleStyle("red")); - console.WriteLine(); - console.Write(new Rule("[green]Centered[/]").Centered().RuleStyle("green")); - console.WriteLine(); - console.Write(new Rule("[red]Right aligned[/]").RightJustified().RuleStyle("blue")); - console.WriteLine(); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/SelectionSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/SelectionSample.cs deleted file mode 100644 index e99a619a6..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/SelectionSample.cs +++ /dev/null @@ -1,29 +0,0 @@ -using DocExampleGenerator; -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class SelectionSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 14); - - public override void Run(IAnsiConsole console) - { - console.DisplayThenType(AskFruit, "↓↓↓¦¦¦¦ "); - } - - private static void AskFruit(IAnsiConsole console) - { - // Ask for the user's favorite fruit - var fruit = console.Prompt( - new SelectionPrompt() - .Title("What's your [green]favorite fruit[/]?") - .PageSize(10) - .MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]") - .AddChoices(new [] {"Apple", "Apricot", "Avocado", "Banana", "Blackcurrant", "Blueberry", "Cherry", "Cloudberry", "Cocunut"})); - - // Echo the fruit back to the terminal - console.WriteLine($"I agree. {fruit} is tasty!"); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/StatusSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/StatusSample.cs deleted file mode 100644 index 93823ed01..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/StatusSample.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Threading; -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class StatusSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 10); - - private static void WriteLogMessage(string message) - { - AnsiConsole.MarkupLine($"[grey]LOG:[/] {message}[grey]...[/]"); - } - - public override void Run(IAnsiConsole console) - { - console.Status() - .AutoRefresh(true) - .Spinner(Spinner.Known.Default) - .Start("[yellow]Initializing warp drive[/]", ctx => - { - // Initialize - Thread.Sleep(3000); - WriteLogMessage("Starting gravimetric field displacement manifold"); - Thread.Sleep(1000); - WriteLogMessage("Warming up deuterium chamber"); - Thread.Sleep(2000); - WriteLogMessage("Generating antideuterium"); - - // Warp nacelles - Thread.Sleep(3000); - ctx.Spinner(Spinner.Known.BouncingBar); - ctx.Status("[bold blue]Unfolding warp nacelles[/]"); - WriteLogMessage("Unfolding left warp nacelle"); - Thread.Sleep(2000); - WriteLogMessage("Left warp nacelle [green]online[/]"); - WriteLogMessage("Unfolding right warp nacelle"); - Thread.Sleep(1000); - WriteLogMessage("Right warp nacelle [green]online[/]"); - - // Warp bubble - Thread.Sleep(3000); - ctx.Spinner(Spinner.Known.Star2); - ctx.Status("[bold blue]Generating warp bubble[/]"); - Thread.Sleep(3000); - ctx.Spinner(Spinner.Known.Star); - ctx.Status("[bold blue]Stabilizing warp bubble[/]"); - - // Safety - ctx.Spinner(Spinner.Known.Monkey); - ctx.Status("[bold blue]Performing safety checks[/]"); - WriteLogMessage("Enabling interior dampening"); - Thread.Sleep(2000); - WriteLogMessage("Interior dampening [green]enabled[/]"); - - // Warp! - Thread.Sleep(3000); - ctx.Spinner(Spinner.Known.Moon); - WriteLogMessage("Preparing for warp"); - Thread.Sleep(1000); - for (var warp = 1; warp < 10; warp++) - { - ctx.Status($"[bold blue]Warp {warp}[/]"); - Thread.Sleep(500); - } - }); - - // Done - AnsiConsole.MarkupLine("[bold green]Crusing at Warp 9.8[/]"); } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/TableSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/TableSample.cs deleted file mode 100644 index 63b0c5887..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/TableSample.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class TableSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (100, 30); - - public override void Run(IAnsiConsole console) - { - var simple = new Table() - .Border(TableBorder.Square) - .BorderColor(Color.Red) - .AddColumn(new TableColumn("[u]CDE[/]").Footer("EDC").Centered()) - .AddColumn(new TableColumn("[u]FED[/]").Footer("DEF")) - .AddColumn(new TableColumn("[u]IHG[/]").Footer("GHI")) - .AddRow("Hello", "[red]World![/]", "") - .AddRow("[blue]Bonjour[/]", "[white]le[/]", "[red]monde![/]") - .AddRow("[blue]Hej[/]", "[yellow]Världen![/]", ""); - - var second = new Table() - .Border(TableBorder.Rounded) - .BorderColor(Color.Green) - .AddColumn(new TableColumn("[u]Foo[/]")) - .AddColumn(new TableColumn("[u]Bar[/]")) - .AddColumn(new TableColumn("[u]Baz[/]")) - .AddRow("Hello", "[red]World![/]", "") - .AddRow(simple, new Text("Whaaat"), new Text("Lolz")) - .AddRow("[blue]Hej[/]", "[yellow]Världen![/]", ""); - - var table = new Table() - .Centered() - .Border(TableBorder.DoubleEdge) - .Title("TABLE [yellow]TITLE[/]") - .Caption("TABLE [yellow]CAPTION[/]") - .AddColumn(new TableColumn(new Panel("[u]ABC[/]").BorderColor(Color.Red)).Footer("[u]FOOTER 1[/]")) - .AddColumn(new TableColumn(new Panel("[u]DEF[/]").BorderColor(Color.Green)).Footer("[u]FOOTER 2[/]")) - .AddColumn(new TableColumn(new Panel("[u]GHI[/]").BorderColor(Color.Blue)).Footer("[u]FOOTER 3[/]")) - .AddRow(new Text("Hello").Centered(), new Markup("[red]World![/]"), Text.Empty) - .AddRow(second, new Text("Whaaat"), new Text("Lol")) - .AddRow(new Markup("[blue]Hej[/]").Centered(), new Markup("[yellow]Världen![/]"), Text.Empty); - - console.Write(table); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/TextPathSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/TextPathSample.cs deleted file mode 100644 index 007aa4d17..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/TextPathSample.cs +++ /dev/null @@ -1,44 +0,0 @@ -using DocExampleGenerator; -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class TextPathSample : BaseSample - { - public override (int Cols, int Rows) ConsoleSize => (40, 23); - - public override void Run(IAnsiConsole console) - { - console.Write( - new Panel( - new Padder(new TextPath("C:/This/Is/A/Super/Long/Path/That/Will/Be/Truncated.txt"), new Padding(0,1))) - .BorderStyle(new Style(foreground: Color.Grey)) - .Header("Windows path")); - - console.Write( - new Panel( - new Padder(new TextPath("/This/Is/A/Super/Long/Path/That/Will/Be/Truncated.txt"), new Padding(0,1))) - .BorderStyle(new Style(foreground: Color.Grey)) - .Header("Unix path")); - - console.Write( - new Panel( - new Padder(new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt") - .RootColor(Color.Green) - .SeparatorColor(Color.Red) - .StemColor(Color.Yellow) - .LeafColor(Color.Blue), new Padding(0,1))) - .BorderStyle(new Style(foreground: Color.Grey)) - .Header("Styling")); - - console.Write( - new Panel( - new Padder(new Rows( - new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt").LeftJustified(), - new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt").Centered(), - new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt").RightJustified()), new Padding(0,1))) - .BorderStyle(new Style(foreground: Color.Grey)) - .Header("Alignment")); - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/TreeSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/TreeSample.cs deleted file mode 100644 index bbeadc2bb..000000000 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/TreeSample.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Spectre.Console; - -namespace Generator.Commands.Samples -{ - internal class TreeSample : BaseSample - { - public override void Run(IAnsiConsole console) - { - // Create the tree - var tree = new Tree("Root") - .Style(Style.Parse("red")) - .Guide(TreeGuide.Line); - - // Add some nodes - var foo = tree.AddNode("[yellow]Nest objects like tables[/]"); - var table = foo.AddNode(new Table() - .RoundedBorder() - .AddColumn("First") - .AddColumn("Second") - .AddRow("1", "2") - .AddRow("3", "4") - .AddRow("5", "6")); - - table.AddNode("[blue]with[/]"); - table.AddNode("[blue]multiple[/]"); - table.AddNode("[blue]children too[/]"); - - var bar = tree.AddNode("Any IRenderable can be nested, such as [yellow]calendars[/]"); - bar.AddNode(new Calendar(2020, 12) - .Border(TableBorder.Rounded) - .BorderStyle(new Style(Color.Green3_1)) - .AddCalendarEvent(2020, 12, 12) - .HideHeader()); - - console.Write(tree); - - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/ColorGeneratorCommand.cs b/resources/scripts/Generator/Commands/ColorGeneratorCommand.cs deleted file mode 100644 index bcc9aee29..000000000 --- a/resources/scripts/Generator/Commands/ColorGeneratorCommand.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.IO; -using System.Threading; -using Generator.Models; -using Scriban; -using Spectre.Console.Cli; -using Spectre.IO; - -namespace Generator.Commands -{ - public sealed class ColorGeneratorCommand : Command - { - private readonly IFileSystem _fileSystem; - - public ColorGeneratorCommand() - { - _fileSystem = new FileSystem(); - } - - public sealed class Settings : GeneratorSettings - { - [CommandOption("-i|--input ")] - public string Input { get; set; } - } - - public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) - { - var templates = new FilePath[] - { - "Templates/ColorPalette.Generated.template", - "Templates/Color.Generated.template", - "Templates/ColorTable.Generated.template" - }; - - // Read the color model. - var model = Color.Parse(File.ReadAllText("Data/colors.json")); - - var output = new DirectoryPath(settings.Output); - if (!_fileSystem.Directory.Exists(settings.Output)) - { - _fileSystem.Directory.Create(settings.Output); - } - - foreach (var templatePath in templates) - { - // Parse the Scriban template. - var template = Template.Parse(File.ReadAllText(templatePath.FullPath)); - - // Render the template with the model. - var result = template.Render(new { Colors = model }); - - // Write output to file - var file = output.CombineWithFilePath(templatePath.GetFilename().ChangeExtension(".cs")); - File.WriteAllText(file.FullPath, result); - } - - return 0; - } - } -} diff --git a/resources/scripts/Generator/Commands/EmojiGeneratorCommand.cs b/resources/scripts/Generator/Commands/EmojiGeneratorCommand.cs deleted file mode 100644 index b4c1ea1c5..000000000 --- a/resources/scripts/Generator/Commands/EmojiGeneratorCommand.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using AngleSharp.Html.Parser; -using Generator.Models; -using Scriban; -using Scriban.Runtime; -using Spectre.Console.Cli; -using Spectre.IO; -using Path = Spectre.IO.Path; -using SpectreEnvironment = Spectre.IO.Environment; - -namespace Generator.Commands -{ - public sealed class EmojiGeneratorCommand : AsyncCommand - { - private readonly IFileSystem _fileSystem; - private readonly IEnvironment _environment; - private readonly IHtmlParser _parser; - - private readonly Dictionary _templates = new Dictionary - { - { "Templates/Emoji.Generated.template", "Emoji.Generated.cs" }, - { "Templates/Emoji.Json.template", "emojis.json" }, // For documentation - }; - - public sealed class Settings : GeneratorSettings - { - [CommandOption("-i|--input ")] - public string Input { get; set; } - } - - public EmojiGeneratorCommand() - { - _fileSystem = new FileSystem(); - _environment = new SpectreEnvironment(); - _parser = new HtmlParser(); - } - - public override async Task ExecuteAsync(CommandContext context, Settings settings, CancellationToken cancellationToken) - { - var output = new DirectoryPath(settings.Output); - if (!_fileSystem.Directory.Exists(settings.Output)) - { - _fileSystem.Directory.Create(settings.Output); - } - - var stream = await FetchEmojis(settings); - var document = await _parser.ParseDocumentAsync(stream); - var emojis = Emoji.Parse(document).OrderBy(x => x.Name) - .Where(emoji => !emoji.HasCombinators) - .ToList(); - - // Render all templates - foreach (var (templateFilename, outputFilename) in _templates) - { - var result = await RenderTemplate(new FilePath(templateFilename), emojis); - - var outputPath = output.CombineWithFilePath(outputFilename); - await File.WriteAllTextAsync(outputPath.FullPath, result); - } - - return 0; - } - - private async Task FetchEmojis(Settings settings) - { - var input = string.IsNullOrEmpty(settings.Input) - ? _environment.WorkingDirectory - : new DirectoryPath(settings.Input); - - var file = _fileSystem.File.Retrieve(input.CombineWithFilePath("emoji-list.html")); - if (!file.Exists) - { - using var http = new HttpClient(); - using var httpStream = await http.GetStreamAsync("http://www.unicode.org/emoji/charts/emoji-list.html"); - using var outStream = file.OpenWrite(); - - await httpStream.CopyToAsync(outStream); - } - - return file.OpenRead(); - } - - private static async Task RenderTemplate(Path path, IReadOnlyCollection emojis) - { - var text = await File.ReadAllTextAsync(path.FullPath); - - var template = Template.Parse(text); - var templateContext = new TemplateContext - { - // Because of the insane amount of Emojis, - // we need to get rid of some secure defaults :P - LoopLimit = int.MaxValue, - }; - - var scriptObject = new ScriptObject(); - scriptObject.Import(new { Emojis = emojis }); - templateContext.PushGlobal(scriptObject); - - return await template.RenderAsync(templateContext); - } - } -} diff --git a/resources/scripts/Generator/Commands/GeneratorSettings.cs b/resources/scripts/Generator/Commands/GeneratorSettings.cs deleted file mode 100644 index dbcba605e..000000000 --- a/resources/scripts/Generator/Commands/GeneratorSettings.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Spectre.Console.Cli; - -namespace Generator.Commands -{ - public class GeneratorSettings : CommandSettings - { - [CommandArgument(0, "")] - public string Output { get; set; } - } -} diff --git a/resources/scripts/Generator/Commands/SampleCommand.cs b/resources/scripts/Generator/Commands/SampleCommand.cs deleted file mode 100644 index 275662354..000000000 --- a/resources/scripts/Generator/Commands/SampleCommand.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using Generator.Commands.Samples; -using Spectre.Console; -using Spectre.Console.Cli; - -namespace Generator.Commands -{ - internal class SampleCommand : Command - { - public class Settings : CommandSettings - { - public Settings(string outputPath, string sample, bool list) - { - Sample = sample; - OutputPath = outputPath ?? Environment.CurrentDirectory; - List = list; - } - - [CommandArgument(0, "[sample]")] - public string Sample { get; } - - [CommandOption("-o|--output")] - public string OutputPath { get; } - - [CommandOption("-l|--list")] - public bool List { get; } - } - - private readonly IAnsiConsole _console; - - public SampleCommand(IAnsiConsole console) - { - _console = new AsciiCastConsole(console); - } - - public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings, CancellationToken cancellationToken) - { - var samples = typeof(BaseSample).Assembly - .GetTypes() - .Where(i => i.IsClass && i.IsAbstract == false && i.IsSubclassOf(typeof(BaseSample))) - .Select(Activator.CreateInstance) - .Cast(); - - var selectedSample = settings.Sample; - if (settings.List) - { - selectedSample = AnsiConsole.Prompt( - new SelectionPrompt() - .Title("Select an example to record") - .PageSize(25) - .AddChoices(samples.Select(x => x.Name()))); - } - - if (!string.IsNullOrWhiteSpace(selectedSample)) - { - var desiredSample = samples.FirstOrDefault(i => i.Name().Equals(selectedSample, StringComparison.OrdinalIgnoreCase)); - if (desiredSample == null) - { - _console.MarkupLine($"[red]Error:[/] could not find sample [blue]{selectedSample}[/]"); - return -1; - } - - samples = new List { desiredSample }; - } - - // from here on out everything we write will be recorded. - var recorder = _console.WrapWithAsciiCastRecorder(); - - foreach (var sample in samples) - { - var sampleName = sample.Name(); - - var originalWidth = _console.Profile.Width; - var originalHeight = _console.Profile.Height; - - _console.Profile.Encoding = Encoding.UTF8; - _console.Profile.Width = sample.ConsoleSize.Cols; - _console.Profile.Height = sample.ConsoleSize.Rows; - - foreach (var (capabilityName, action) in sample.GetCapabilities()) - { - action(_console.Profile.Capabilities); - sample.Run(_console); - var json = recorder.GetCastJson($"{sampleName} ({capabilityName})", sample.ConsoleSize.Cols + 2, sample.ConsoleSize.Rows); - File.WriteAllText(Path.Combine(settings.OutputPath, $"{sampleName}-{capabilityName}.cast"), json); - } - - _console.Profile.Width = originalWidth; - _console.Profile.Height = originalHeight; - } - - return 0; - } - } -} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/SpinnerGeneratorCommand.cs b/resources/scripts/Generator/Commands/SpinnerGeneratorCommand.cs deleted file mode 100644 index de59cfdc6..000000000 --- a/resources/scripts/Generator/Commands/SpinnerGeneratorCommand.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Threading; -using Generator.Models; -using Scriban; -using Spectre.Console.Cli; -using Spectre.IO; - -namespace Generator.Commands -{ - public sealed class SpinnerGeneratorCommand : Command - { - private readonly IFileSystem _fileSystem; - - public SpinnerGeneratorCommand() - { - _fileSystem = new FileSystem(); - } - - public override int Execute(CommandContext context, GeneratorSettings settings, CancellationToken cancellationToken) - { - // Read the spinner model. - var spinners = new List(); - spinners.AddRange(Spinner.Parse(File.ReadAllText("Data/spinners_default.json"))); - spinners.AddRange(Spinner.Parse(File.ReadAllText("Data/spinners_sindresorhus.json"))); - - var output = new DirectoryPath(settings.Output); - if (!_fileSystem.Directory.Exists(settings.Output)) - { - _fileSystem.Directory.Create(settings.Output); - } - - // Parse the Scriban template. - var templatePath = new FilePath("Templates/Spinner.Generated.template"); - var template = Template.Parse(File.ReadAllText(templatePath.FullPath)); - - // Render the template with the model. - var result = template.Render(new { Spinners = spinners }); - - // Write output to file - var file = output.CombineWithFilePath(templatePath.GetFilename().ChangeExtension(".cs")); - File.WriteAllText(file.FullPath, result); - - return 0; - } - } -} diff --git a/resources/scripts/Generator/Generator.csproj b/resources/scripts/Generator/Generator.csproj deleted file mode 100644 index cfb7586d5..000000000 --- a/resources/scripts/Generator/Generator.csproj +++ /dev/null @@ -1,59 +0,0 @@ - - - - Exe - net8.0 - default - - - - - - - - - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - - - - - - - - - - - - - - - - diff --git a/resources/scripts/Generator/Models/Color.cs b/resources/scripts/Generator/Models/Color.cs deleted file mode 100644 index 59724bfed..000000000 --- a/resources/scripts/Generator/Models/Color.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; - -namespace Generator.Models -{ - public sealed class Color - { - public int Number { get; set; } - public string Hex { get; set; } - public string Name { get; set; } - public List Aliases { get; set; } = new List(); - public Rgb Rgb { get; set; } - - public int R => Rgb.R; - public int G => Rgb.G; - public int B => Rgb.B; - - public static IEnumerable Parse(string json) - { - var source = JsonConvert.DeserializeObject>(json); - - var check = new Dictionary(StringComparer.OrdinalIgnoreCase); - - var colorAliases = source - .SelectMany(c => c.Aliases.Select(a => new { Alias = a, Color = c })) - .Select(a => new Color() - { - Hex = a.Color.Hex, - Name = a.Alias, - Number = a.Color.Number, - Rgb = a.Color.Rgb - }) - .ToList(); - - var colors = source - .Union(colorAliases) - .OrderBy(c => c.Number); - - foreach (var color in colors) - { - if (!check.ContainsKey(color.Name)) - { - check.Add(color.Name, color); - } - else - { - var newName = (string)null; - for (int i = 1; i < 100; i++) - { - if (!check.ContainsKey($"{color.Name}_{i}")) - { - newName = $"{color.Name}_{i}"; - break; - } - } - - if (newName == null) - { - throw new InvalidOperationException("Impossible!"); - } - - check.Add(newName, color); - color.Name = newName; - } - } - - return colors; - } - } - - public sealed class Rgb - { - public int R { get; set; } - public int G { get; set; } - public int B { get; set; } - } -} diff --git a/resources/scripts/Generator/Models/ColorModel.cs b/resources/scripts/Generator/Models/ColorModel.cs deleted file mode 100644 index 736d4c048..000000000 --- a/resources/scripts/Generator/Models/ColorModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; - -namespace Generator.Models -{ - public sealed class ColorModel - { - public List Colors { get; set; } - - public ColorModel(IEnumerable colors) - { - Colors = new List(colors); - } - } -} diff --git a/resources/scripts/Generator/Models/Emoji.cs b/resources/scripts/Generator/Models/Emoji.cs deleted file mode 100644 index a7d4e73af..000000000 --- a/resources/scripts/Generator/Models/Emoji.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text; -using AngleSharp.Dom; -using AngleSharp.Html.Dom; -using Humanizer; - -namespace Generator.Models -{ - public class Emoji - { - private static readonly string[] _headers = { "count", "code", "sample", "name" }; - - private Emoji(string identifier, string name, string code, string description) - { - Identifier = identifier; - Name = name; - Code = code; - Description = description; - NormalizedCode = Code.Replace("\\U", "U+"); - HasCombinators = Code.Split(new[] { "\\U" }, System.StringSplitOptions.RemoveEmptyEntries).Length > 1; - } - - public string Identifier { get; set; } - public string Code { get; } - public string NormalizedCode { get; } - public string Name { get; } - public string Description { get; set; } - public bool HasCombinators { get; set; } - - public static IEnumerable Parse(IHtmlDocument document) - { - var rows = document - .GetNodes(predicate: row => - row.Cells.Length >= _headers.Length && // Filter out rows that don't have enough cells. - row.Cells.All(x => x.LocalName == TagNames.Td)); // We're only interested in td cells, not th. - - foreach (var row in rows) - { - var dictionary = _headers - .Zip(row.Cells, (header, cell) => (Header: header, cell.TextContent.Trim())) - .ToDictionary(x => x.Item1, x => x.Item2); - - var code = TransformCode(dictionary["code"]); - var identifier = TransformName(dictionary["name"]) - .Replace("-", "_") - .Replace("(", string.Empty) - .Replace(")", string.Empty); - - var description = dictionary["name"].Humanize(); - - var name = identifier - .Replace("1st", "first") - .Replace("2nd", "second") - .Replace("3rd", "third") - .Pascalize(); - - yield return new Emoji(identifier, name, code, description); - } - } - - private static string TransformName(string name) - { - return name.Replace(":", string.Empty) - .Replace(",", string.Empty) - .Replace(".", string.Empty) - .Replace("\u201c", string.Empty) - .Replace("\u201d", string.Empty) - .Replace("\u229b", string.Empty) - .Replace(' ', '_') - .Replace("’s", "s") - .Replace("’", "_") - .Replace("&", "and") - .Replace("#", "hash") - .Replace("*", "star") - .Replace("!", string.Empty) - .Trim() - .ToLowerInvariant(); - } - - private static string TransformCode(string code) - { - var builder = new StringBuilder(); - - foreach (var part in code.Split(' ')) - { - builder.Append(part.Length == 6 - ? part.Replace("+", "0000") - : part.Replace("+", "000")); - } - - return builder.ToString().Replace("U", "\\U"); - } - } -} diff --git a/resources/scripts/Generator/Models/Palette.cs b/resources/scripts/Generator/Models/Palette.cs deleted file mode 100644 index 1bdf19cf1..000000000 --- a/resources/scripts/Generator/Models/Palette.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Generator.Models -{ - public sealed class Palette - { - } -} diff --git a/resources/scripts/Generator/Models/Spinner.cs b/resources/scripts/Generator/Models/Spinner.cs deleted file mode 100644 index 78f406d6d..000000000 --- a/resources/scripts/Generator/Models/Spinner.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Humanizer; -using Newtonsoft.Json; - -namespace Generator.Models -{ - public sealed class Spinner - { - public string Name { get; set; } - public string NormalizedName { get; set; } - public int Interval { get; set; } - public bool Unicode { get; set; } - public List Frames { get; set; } - - public static IEnumerable Parse(string json) - { - var data = JsonConvert.DeserializeObject>(json); - foreach (var item in data) - { - item.Value.Name = item.Key; - item.Value.NormalizedName = item.Value.Name.Pascalize(); - - var frames = item.Value.Frames; - item.Value.Frames = frames.Select(f => f.Replace("\\", "\\\\")).ToList(); - } - - return data.Values; - } - } -} diff --git a/resources/scripts/Generator/Program.cs b/resources/scripts/Generator/Program.cs deleted file mode 100644 index 15bc3a94d..000000000 --- a/resources/scripts/Generator/Program.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Generator.Commands; -using Spectre.Console.Cli; - -namespace Generator -{ - public static class Program - { - public static int Main(string[] args) - { - var app = new CommandApp(); - app.Configure(config => - { - config.AddCommand("colors"); - config.AddCommand("emoji"); - config.AddCommand("spinners"); - config.AddCommand("samples"); - }); - - return app.Run(args); - } - } -} diff --git a/src/.editorconfig b/src/.editorconfig index 2ab117801..bf8179454 100644 --- a/src/.editorconfig +++ b/src/.editorconfig @@ -1,6 +1,156 @@ root = false [*.cs] +# Prefer file scoped namespace declarations +csharp_style_namespace_declarations = file_scoped:warning + +# Sort using and Import directives with System.* appearing first +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false + +# Avoid "this." and "Me." if not necessary +dotnet_style_qualification_for_field = false:refactoring +dotnet_style_qualification_for_property = false:refactoring +dotnet_style_qualification_for_method = false:refactoring +dotnet_style_qualification_for_event = false:refactoring + +# Use language keywords instead of framework type names for type references +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Suggest more modern language features when available +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion + +# Non-private static fields are PascalCase +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style +dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected +dotnet_naming_symbols.non_private_static_fields.required_modifiers = static +dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case + +# Non-private readonly fields are PascalCase +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_field_style +dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected +dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly +dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case + +# Constants are PascalCase +dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants +dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style +dotnet_naming_symbols.constants.applicable_kinds = field, local +dotnet_naming_symbols.constants.required_modifiers = const +dotnet_naming_style.constant_style.capitalization = pascal_case + +# Instance fields are camelCase and start with _ +dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields +dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style +dotnet_naming_symbols.instance_fields.applicable_kinds = field +dotnet_naming_style.instance_field_style.capitalization = camel_case +dotnet_naming_style.instance_field_style.required_prefix = _ + +# Locals and parameters are camelCase +dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion +dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters +dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style +dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local +dotnet_naming_style.camel_case_style.capitalization = camel_case + +# Local functions are PascalCase +dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions +dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style +dotnet_naming_symbols.local_functions.applicable_kinds = local_function +dotnet_naming_style.local_function_style.capitalization = pascal_case + +# By default, name items with PascalCase +dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members +dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.all_members.applicable_kinds = * +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +# Newline settings +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +# Prefer "var" everywhere +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion + +# Prefer method-like constructs to have a block body +csharp_style_expression_bodied_methods = false:none +csharp_style_expression_bodied_constructors = false:none +csharp_style_expression_bodied_operators = false:none + +# Prefer property-like constructs to have an expression-body +csharp_style_expression_bodied_properties = true:none +csharp_style_expression_bodied_indexers = true:none +csharp_style_expression_bodied_accessors = true:none + +# Suggest more modern language features when available +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = do_not_ignore +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Blocks are allowed +csharp_prefer_braces = true:silent +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +# RS0037: PublicAPI.txt is missing '#nullable enable' +dotnet_diagnostic.RS0037.severity = none + # IDE0055: Fix formatting dotnet_diagnostic.IDE0055.severity = warning diff --git a/src/Directory.Build.props b/src/Directory.Build.props index f5089dad6..bd6a369a6 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -50,17 +50,10 @@ true - - - - - - All - All diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets deleted file mode 100644 index 68be9d04f..000000000 --- a/src/Directory.Build.targets +++ /dev/null @@ -1,8 +0,0 @@ - - - - preview.0 - normal - - - \ No newline at end of file diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index f6f7d849e..2b66bc8b6 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -3,18 +3,22 @@ true + + - + + + + - diff --git a/src/Extensions/Spectre.Console.Json/IJsonParser.cs b/src/Extensions/Spectre.Console.Json/IJsonParser.cs index dffdbe2e9..e0b230d00 100644 --- a/src/Extensions/Spectre.Console.Json/IJsonParser.cs +++ b/src/Extensions/Spectre.Console.Json/IJsonParser.cs @@ -11,4 +11,4 @@ public interface IJsonParser /// The JSON to parse. /// An instance. JsonSyntax Parse(string json); -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/JsonParser.cs b/src/Extensions/Spectre.Console.Json/JsonParser.cs index 4bfc4896c..0a1e18995 100644 --- a/src/Extensions/Spectre.Console.Json/JsonParser.cs +++ b/src/Extensions/Spectre.Console.Json/JsonParser.cs @@ -143,4 +143,4 @@ private static JsonMember ParseMember(JsonTokenReader reader) var value = ParseElement(reader); return new JsonMember(name.Lexeme, value); } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/JsonText.cs b/src/Extensions/Spectre.Console.Json/JsonText.cs index 4d8c8252b..dcb2aaf50 100644 --- a/src/Extensions/Spectre.Console.Json/JsonText.cs +++ b/src/Extensions/Spectre.Console.Json/JsonText.cs @@ -103,4 +103,4 @@ protected override IRenderable Build() _syntax.Accept(JsonBuilder.Shared, context); return context.Paragraph; } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/JsonTextExtensions.cs b/src/Extensions/Spectre.Console.Json/JsonTextExtensions.cs index 407b0415c..634d72ac9 100644 --- a/src/Extensions/Spectre.Console.Json/JsonTextExtensions.cs +++ b/src/Extensions/Spectre.Console.Json/JsonTextExtensions.cs @@ -310,4 +310,4 @@ public static JsonText NullColor(this JsonText text, Color color) text.NullStyle = new Style(color); return text; } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/JsonTextStyles.cs b/src/Extensions/Spectre.Console.Json/JsonTextStyles.cs index 388fa79e1..b10ffa46d 100644 --- a/src/Extensions/Spectre.Console.Json/JsonTextStyles.cs +++ b/src/Extensions/Spectre.Console.Json/JsonTextStyles.cs @@ -11,4 +11,4 @@ internal sealed class JsonTextStyles public Style NumberStyle { get; set; } = null!; public Style BooleanStyle { get; set; } = null!; public Style NullStyle { get; set; } = null!; -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/JsonToken.cs b/src/Extensions/Spectre.Console.Json/JsonToken.cs index 50e0c505a..7e581cad7 100644 --- a/src/Extensions/Spectre.Console.Json/JsonToken.cs +++ b/src/Extensions/Spectre.Console.Json/JsonToken.cs @@ -10,4 +10,4 @@ public JsonToken(JsonTokenType type, string lexeme) Type = type; Lexeme = lexeme ?? throw new ArgumentNullException(nameof(lexeme)); } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/JsonTokenReader.cs b/src/Extensions/Spectre.Console.Json/JsonTokenReader.cs index 324c51150..25d2ab1b1 100644 --- a/src/Extensions/Spectre.Console.Json/JsonTokenReader.cs +++ b/src/Extensions/Spectre.Console.Json/JsonTokenReader.cs @@ -52,4 +52,4 @@ public JsonToken Consume(JsonTokenType type) Position++; return _reader[Position - 1]; } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/JsonTokenType.cs b/src/Extensions/Spectre.Console.Json/JsonTokenType.cs index 1731239ee..eb9ab97ea 100644 --- a/src/Extensions/Spectre.Console.Json/JsonTokenType.cs +++ b/src/Extensions/Spectre.Console.Json/JsonTokenType.cs @@ -12,4 +12,4 @@ internal enum JsonTokenType Number, Boolean, Null, -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/JsonTokenizer.cs b/src/Extensions/Spectre.Console.Json/JsonTokenizer.cs index 8ba42ac7b..d23bbf1da 100644 --- a/src/Extensions/Spectre.Console.Json/JsonTokenizer.cs +++ b/src/Extensions/Spectre.Console.Json/JsonTokenizer.cs @@ -1,5 +1,3 @@ -using System.Text; - namespace Spectre.Console.Json; internal static class JsonTokenizer @@ -202,4 +200,4 @@ private static void ReadDigits(StringBuffer buffer, StringBuilder accumulator, i accumulator.Append(current); } } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/Syntax/JsonBoolean.cs b/src/Extensions/Spectre.Console.Json/Syntax/JsonBoolean.cs index 0cfa00708..c3fe5e445 100644 --- a/src/Extensions/Spectre.Console.Json/Syntax/JsonBoolean.cs +++ b/src/Extensions/Spectre.Console.Json/Syntax/JsonBoolean.cs @@ -23,4 +23,4 @@ internal override void Accept(JsonSyntaxVisitor visitor, T context) { visitor.VisitBoolean(this, context); } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/Syntax/JsonMember.cs b/src/Extensions/Spectre.Console.Json/Syntax/JsonMember.cs index 14f61fd8a..842bc6be1 100644 --- a/src/Extensions/Spectre.Console.Json/Syntax/JsonMember.cs +++ b/src/Extensions/Spectre.Console.Json/Syntax/JsonMember.cs @@ -30,4 +30,4 @@ internal override void Accept(JsonSyntaxVisitor visitor, T context) { visitor.VisitMember(this, context); } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/Syntax/JsonNull.cs b/src/Extensions/Spectre.Console.Json/Syntax/JsonNull.cs index 2fe92698d..90a8f2260 100644 --- a/src/Extensions/Spectre.Console.Json/Syntax/JsonNull.cs +++ b/src/Extensions/Spectre.Console.Json/Syntax/JsonNull.cs @@ -23,4 +23,4 @@ internal override void Accept(JsonSyntaxVisitor visitor, T context) { visitor.VisitNull(this, context); } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/Syntax/JsonNumber.cs b/src/Extensions/Spectre.Console.Json/Syntax/JsonNumber.cs index d06da4fec..c4e27f3a9 100644 --- a/src/Extensions/Spectre.Console.Json/Syntax/JsonNumber.cs +++ b/src/Extensions/Spectre.Console.Json/Syntax/JsonNumber.cs @@ -13,4 +13,4 @@ internal override void Accept(JsonSyntaxVisitor visitor, T context) { visitor.VisitNumber(this, context); } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/Syntax/JsonObject.cs b/src/Extensions/Spectre.Console.Json/Syntax/JsonObject.cs index 3b8b585fb..6f3b8a4c3 100644 --- a/src/Extensions/Spectre.Console.Json/Syntax/JsonObject.cs +++ b/src/Extensions/Spectre.Console.Json/Syntax/JsonObject.cs @@ -22,4 +22,4 @@ internal override void Accept(JsonSyntaxVisitor visitor, T context) { visitor.VisitObject(this, context); } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/Syntax/JsonString.cs b/src/Extensions/Spectre.Console.Json/Syntax/JsonString.cs index ed2dbf75f..9fa756ad6 100644 --- a/src/Extensions/Spectre.Console.Json/Syntax/JsonString.cs +++ b/src/Extensions/Spectre.Console.Json/Syntax/JsonString.cs @@ -23,4 +23,4 @@ internal override void Accept(JsonSyntaxVisitor visitor, T context) { visitor.VisitString(this, context); } -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/Syntax/JsonSyntax.cs b/src/Extensions/Spectre.Console.Json/Syntax/JsonSyntax.cs index fbff17898..8c932b3b2 100644 --- a/src/Extensions/Spectre.Console.Json/Syntax/JsonSyntax.cs +++ b/src/Extensions/Spectre.Console.Json/Syntax/JsonSyntax.cs @@ -6,4 +6,4 @@ namespace Spectre.Console.Json.Syntax; public abstract class JsonSyntax { internal abstract void Accept(JsonSyntaxVisitor visitor, T context); -} +} \ No newline at end of file diff --git a/src/Extensions/Spectre.Console.Json/Syntax/JsonSyntaxVisitor.cs b/src/Extensions/Spectre.Console.Json/Syntax/JsonSyntaxVisitor.cs index 409bb4237..0bb6dd660 100644 --- a/src/Extensions/Spectre.Console.Json/Syntax/JsonSyntaxVisitor.cs +++ b/src/Extensions/Spectre.Console.Json/Syntax/JsonSyntaxVisitor.cs @@ -9,4 +9,4 @@ internal abstract class JsonSyntaxVisitor public abstract void VisitString(JsonString syntax, T context); public abstract void VisitBoolean(JsonBoolean syntax, T context); public abstract void VisitNull(JsonNull syntax, T context); -} +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/AnsiConsoleExtensions.cs b/src/Generator/Commands/AsciiCast/AnsiConsoleExtensions.cs new file mode 100644 index 000000000..8d4ced113 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/AnsiConsoleExtensions.cs @@ -0,0 +1,32 @@ +using System; +using System.Threading; +using Generator.Commands; +using Spectre.Console; + +namespace DocExampleGenerator; + +internal static class AnsiConsoleExtensions +{ + /// + /// Displays something via AnsiConsole, waits a bit and then simulates typing based on the input. If the console + /// doesn't have the focus this will just type into whatever window does so watch the alt-tab. + /// + /// + /// The display action. + /// The characters to type. ↑ for an up arrow, ↓ for down arrow, ↲ for a return and ¦ for a pause. + /// How long to delay before typing. This should be at least 100ms because we won't check if the prompt has displayed before simulating typing. + /// Delay between keypresses. There will be a bit of randomness between each keypress +/- 20% of this value. + public static void DisplayThenType(this IAnsiConsole console, Action action, string input, int initialDelayMs = 500, int keypressDelayMs = 200) + { + if (console is not AsciiCastConsole asciiConsole) + { + throw new InvalidOperationException("Not an ASCII cast console"); + } + + asciiConsole.Input.PushText(input, keypressDelayMs); + + Thread.Sleep(initialDelayMs); + + action(console); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/AsciiCastConsole.cs b/src/Generator/Commands/AsciiCast/AsciiCastConsole.cs new file mode 100644 index 000000000..cababddc6 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/AsciiCastConsole.cs @@ -0,0 +1,39 @@ +using System; +using Spectre.Console; +using Spectre.Console.Rendering; + +namespace Generator.Commands; + +public sealed class AsciiCastConsole : IAnsiConsole +{ + private readonly IAnsiConsole _console; + private readonly AsciiCastInput _input; + + public Profile Profile => _console.Profile; + + public IAnsiConsoleCursor Cursor => _console.Cursor; + + IAnsiConsoleInput IAnsiConsole.Input => _input; + + public AsciiCastInput Input => _input; + + public IExclusivityMode ExclusivityMode => _console.ExclusivityMode; + + public RenderPipeline Pipeline => _console.Pipeline; + + public AsciiCastConsole(IAnsiConsole console) + { + _console = console ?? throw new ArgumentNullException(nameof(console)); + _input = new AsciiCastInput(); + } + + public void Clear(bool home) + { + _console.Clear(home); + } + + public void Write(IRenderable renderable) + { + _console.Write(renderable); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/AsciiCastExtensions.cs b/src/Generator/Commands/AsciiCast/AsciiCastExtensions.cs new file mode 100644 index 000000000..fe80679f0 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/AsciiCastExtensions.cs @@ -0,0 +1,14 @@ +using Spectre.Console; + +namespace Generator.Commands; + +public static class AsciiCastExtensions +{ + public static AsciiCastOut WrapWithAsciiCastRecorder(this IAnsiConsole ansiConsole) + { + AsciiCastOut castRecorder = new(ansiConsole.Profile.Out); + ansiConsole.Profile.Out = castRecorder; + + return castRecorder; + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/AsciiCastInput.cs b/src/Generator/Commands/AsciiCast/AsciiCastInput.cs new file mode 100644 index 000000000..001799547 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/AsciiCastInput.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Spectre.Console; + +namespace Generator.Commands; + +public sealed class AsciiCastInput : IAnsiConsoleInput +{ + private readonly Queue<(ConsoleKeyInfo?, int)> _input; + private readonly Random _random = new Random(); + + public AsciiCastInput() + { + _input = new Queue<(ConsoleKeyInfo?, int)>(); + } + + public void PushText(string input, int keypressDelayMs) + { + if (input is null) + { + throw new ArgumentNullException(nameof(input)); + } + + foreach (var character in input) + { + PushCharacter(character, keypressDelayMs); + } + } + + public void PushTextWithEnter(string input, int keypressDelayMs) + { + PushText(input, keypressDelayMs); + PushKey(ConsoleKey.Enter, keypressDelayMs); + } + + public void PushCharacter(char input, int keypressDelayMs) + { + var delay = keypressDelayMs + _random.Next((int)(keypressDelayMs * -.2), (int)(keypressDelayMs * .2)); + + switch (input) + { + case '↑': + PushKey(ConsoleKey.UpArrow, keypressDelayMs); + break; + case '↓': + PushKey(ConsoleKey.DownArrow, keypressDelayMs); + break; + case '↲': + PushKey(ConsoleKey.Enter, keypressDelayMs); + break; + case '¦': + _input.Enqueue((null, delay)); + break; + default: + var control = char.IsUpper(input); + _input.Enqueue((new ConsoleKeyInfo(input, (ConsoleKey)input, false, false, control), delay)); + break; + } + } + + public void PushKey(ConsoleKey input, int keypressDelayMs) + { + var delay = keypressDelayMs + _random.Next((int)(keypressDelayMs * -.2), (int)(keypressDelayMs * .2)); + _input.Enqueue((new ConsoleKeyInfo((char)input, input, false, false, false), delay)); + } + + public bool IsKeyAvailable() + { + return _input.Count > 0; + } + + public ConsoleKeyInfo? ReadKey(bool intercept) + { + if (_input.Count == 0) + { + throw new InvalidOperationException("No input available."); + } + + var result = _input.Dequeue(); + + Thread.Sleep(result.Item2); + return result.Item1; + } + + public Task ReadKeyAsync(bool intercept, CancellationToken cancellationToken) + { + return Task.FromResult(ReadKey(intercept)); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/AsciiCastOut.cs b/src/Generator/Commands/AsciiCast/AsciiCastOut.cs new file mode 100644 index 000000000..17c9fa8ab --- /dev/null +++ b/src/Generator/Commands/AsciiCast/AsciiCastOut.cs @@ -0,0 +1,94 @@ +using System; +using System.Globalization; +using System.IO; +using System.Text; +using System.Text.Json; +using Spectre.Console; + +namespace Generator.Commands; + +public class AsciiCastOut : IAnsiConsoleOutput +{ + private sealed class AsciiCastWriter : TextWriter + { + private readonly TextWriter _wrappedTextWriter; + private readonly StringBuilder _builder = new StringBuilder(); + private int? _firstTick; + + public AsciiCastWriter(TextWriter wrappedTextWriter) + { + _wrappedTextWriter = wrappedTextWriter; + } + + public override void Write(string? value) + { + if (value == null) + { + return; + } + + Append(value); + _wrappedTextWriter.Write(value); + base.Write(value); + } + + public override Encoding Encoding => _wrappedTextWriter.Encoding; + + private void Append(string value) + { + var tick = 0m; + if (_firstTick.HasValue) + { + tick = Environment.TickCount - _firstTick.Value; + } + else + { + _firstTick = Environment.TickCount; + } + + tick /= 1000m; + + _builder.Append('[') + .AppendFormat(CultureInfo.InvariantCulture, "{0}", tick) + .Append(", \"o\", \"").Append(JsonEncodedText.Encode(value)).AppendLine("\"]"); + } + + public string GetJsonAndClearBuffer() + { + var json = _builder.ToString(); + + // reset the buffer and also reset the first tick count + _builder.Clear(); + _firstTick = null; + return json; + } + } + + private readonly IAnsiConsoleOutput _wrappedAnsiConsole; + private readonly AsciiCastWriter _asciiCastWriter; + + public AsciiCastOut(IAnsiConsoleOutput wrappedAnsiConsole) + { + _wrappedAnsiConsole = wrappedAnsiConsole ?? throw new ArgumentNullException(nameof(wrappedAnsiConsole)); + _asciiCastWriter = new AsciiCastWriter(_wrappedAnsiConsole.Writer); + } + + public TextWriter Writer => _asciiCastWriter; + + public bool IsTerminal => _wrappedAnsiConsole.IsTerminal; + + public int Width => _wrappedAnsiConsole.Width; + + public int Height => _wrappedAnsiConsole.Height; + + public void SetEncoding(Encoding encoding) + { + _wrappedAnsiConsole.SetEncoding(encoding); + } + + public string GetCastJson(string title, int? width = null, int? height = null) + { + var header = $"{{\"version\": 2, \"width\": {width ?? _wrappedAnsiConsole.Width}, \"height\": {height ?? _wrappedAnsiConsole.Height}, \"title\": \"{JsonEncodedText.Encode(title)}\", \"env\": {{\"TERM\": \"Spectre.Console\"}}}}"; + return $"{header}{Environment.NewLine}{_asciiCastWriter.GetJsonAndClearBuffer()}{Environment.NewLine}"; + } +} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/AwaitSpinnerSample.cs b/src/Generator/Commands/AsciiCast/Samples/AwaitSpinnerSample.cs similarity index 96% rename from resources/scripts/Generator/Commands/AsciiCast/Samples/AwaitSpinnerSample.cs rename to src/Generator/Commands/AsciiCast/Samples/AwaitSpinnerSample.cs index d6b7164b6..1c1c46fb0 100644 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/AwaitSpinnerSample.cs +++ b/src/Generator/Commands/AsciiCast/Samples/AwaitSpinnerSample.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Generator.Commands.Samples; using Spectre.Console; using Spectre.Console.Extensions; diff --git a/src/Generator/Commands/AsciiCast/Samples/BarChartSample.cs b/src/Generator/Commands/AsciiCast/Samples/BarChartSample.cs new file mode 100644 index 000000000..8ac37374c --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/BarChartSample.cs @@ -0,0 +1,19 @@ +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class BarChartSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 5); + + public override void Run(IAnsiConsole console) + { + console.Write(new BarChart() + .Width(60) + .Label("[green bold underline]Number of fruits[/]") + .CenterLabel() + .AddItem("Apple", 12, Color.Yellow) + .AddItem("Orange", 54, Color.Green) + .AddItem("Banana", 33, Color.Red)); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/BaseSample.cs b/src/Generator/Commands/AsciiCast/Samples/BaseSample.cs new file mode 100644 index 000000000..cc9633c6f --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/BaseSample.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Spectre.Console; + +namespace Generator.Commands.Samples; + +public abstract class BaseSample +{ + public abstract void Run(IAnsiConsole console); + public virtual string Name() => PascalToKebab(GetType().Name.Replace("Sample", "")); + public virtual (int Cols, int Rows) ConsoleSize => (82, 24); + public virtual IEnumerable<(string Name, Action CapabilitiesAction)> GetCapabilities() + { + return new (string Name, Action CapabilitiesAction)[] + { + ("plain", capabilities => + { + capabilities.Unicode = false; + capabilities.Ansi = true; + capabilities.Interactive = true; + capabilities.Legacy = false; + capabilities.Links = false; + capabilities.ColorSystem = ColorSystem.Legacy; + }), + ("rich", capabilities => + { + capabilities.Unicode = true; + capabilities.Ansi = true; + capabilities.Interactive = true; + capabilities.Legacy = false; + capabilities.Links = false; + capabilities.ColorSystem = ColorSystem.TrueColor; + }), + }; + } + + private string PascalToKebab(ReadOnlySpan input) + { + var sb = new StringBuilder(); + var previousUpper = true; + foreach (var chr in input) + { + if (char.IsUpper(chr) && previousUpper == false) + { + sb.Append('-'); + previousUpper = true; + } + else + { + previousUpper = false; + } + + sb.Append(char.ToLower(chr)); + } + + return sb.ToString(); + + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/BreakdownChartSample.cs b/src/Generator/Commands/AsciiCast/Samples/BreakdownChartSample.cs new file mode 100644 index 000000000..6befe3383 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/BreakdownChartSample.cs @@ -0,0 +1,20 @@ +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class BreakdownChartSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 5); + + public override void Run(IAnsiConsole console) + { + console.Write(new BreakdownChart() + .Width(60) + .AddItem("SCSS", 80, Color.Red) + .AddItem("HTML", 28.3, Color.Blue) + .AddItem("C#", 22.6, Color.Green) + .AddItem("JavaScript", 6, Color.Yellow) + .AddItem("Ruby", 6, Color.LightGreen) + .AddItem("Shell", 0.1, Color.Aqua)); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/CalendarSamples.cs b/src/Generator/Commands/AsciiCast/Samples/CalendarSamples.cs new file mode 100644 index 000000000..27d41e8d4 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/CalendarSamples.cs @@ -0,0 +1,39 @@ +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal abstract class BaseCalendarSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 12); +} + +internal class CalendarSample : BaseCalendarSample +{ + + public override void Run(IAnsiConsole console) => console.Write(new Calendar(2020, 10)); +} + +internal class CalendarCultureSample : BaseCalendarSample +{ + public override void Run(IAnsiConsole console) => console.Write(new Calendar(2020, 10).Culture("sv-SE")); +} + +internal class CalendarHeader : BaseCalendarSample +{ + public override void Run(IAnsiConsole console) + { + var calendar = new Calendar(2020, 10); + calendar.HeaderStyle(Style.Parse("blue bold")); + console.Write(calendar); + } +} + +internal class CalendarHighlightSample : BaseCalendarSample +{ + public override void Run(IAnsiConsole console) + { + var calendar = new Calendar(2020, 10).HighlightStyle(Style.Parse("yellow bold")); + calendar.AddCalendarEvent(2020, 10, 11); + console.Write(calendar); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/CanvasImageSample.cs b/src/Generator/Commands/AsciiCast/Samples/CanvasImageSample.cs new file mode 100644 index 000000000..7144d6b23 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/CanvasImageSample.cs @@ -0,0 +1,26 @@ +using SixLabors.ImageSharp.Processing; +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class CanvasImageSample : BaseSample +{ + public override void Run(IAnsiConsole console) + { + var image = new CanvasImage("./Data/cake.png"); + image.MaxWidth(16); + console.Write(image); + } +} + +internal class CanvasImageManipulationSample : BaseSample +{ + public override void Run(IAnsiConsole console) + { + var image = new CanvasImage("./Data/cake.png"); + image.MaxWidth(24); + image.BilinearResampler(); + image.Mutate(ctx => ctx.Grayscale().Rotate(-45).EntropyCrop()); + console.Write(image); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/CanvasSample.cs b/src/Generator/Commands/AsciiCast/Samples/CanvasSample.cs new file mode 100644 index 000000000..f57b9730e --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/CanvasSample.cs @@ -0,0 +1,28 @@ +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class CanvasSample : BaseSample +{ + public override void Run(IAnsiConsole console) + { + var canvas = new Canvas(16, 16); + + // Draw some shapes + for (var i = 0; i < canvas.Width; i++) + { + // Cross + canvas.SetPixel(i, i, Color.White); + canvas.SetPixel(canvas.Width - i - 1, i, Color.White); + + // Border + canvas.SetPixel(i, 0, Color.Red); + canvas.SetPixel(0, i, Color.Green); + canvas.SetPixel(i, canvas.Height - 1, Color.Blue); + canvas.SetPixel(canvas.Width - 1, i, Color.Yellow); + } + + // Render the canvas + console.Write(canvas); + } +} \ No newline at end of file diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/ColumnsSample.cs b/src/Generator/Commands/AsciiCast/Samples/ColumnsSample.cs similarity index 94% rename from resources/scripts/Generator/Commands/AsciiCast/Samples/ColumnsSample.cs rename to src/Generator/Commands/AsciiCast/Samples/ColumnsSample.cs index 5e2fd48bd..eac4f544b 100644 --- a/resources/scripts/Generator/Commands/AsciiCast/Samples/ColumnsSample.cs +++ b/src/Generator/Commands/AsciiCast/Samples/ColumnsSample.cs @@ -43,11 +43,11 @@ private static string GetContent(Fruit fruit) private sealed class Fruit { - public string Name { get; init; } + public required string Name { get; init; } public static List LoadFriuts() { - return new [] + return new[] { "Apple", "Apricot", @@ -87,7 +87,7 @@ public static List LoadFriuts() "Ximenia", "Yuzu", } - .Select(x => new Fruit{Name = x}) + .Select(x => new Fruit { Name = x }) .ToList(); } } diff --git a/src/Generator/Commands/AsciiCast/Samples/Exceptions.cs b/src/Generator/Commands/AsciiCast/Samples/Exceptions.cs new file mode 100644 index 000000000..2819c7a8a --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/Exceptions.cs @@ -0,0 +1,80 @@ +using System; +using System.Security.Authentication; +using Generator.Commands.Samples; +using Spectre.Console; + +// Keep the namespace here short because it'll be used in the display of the exceptions, +// and we want to keep that below 100 characters wide. +namespace Samples; + +public static class Exceptions +{ + internal abstract class BaseExceptionSample : BaseSample + { + public override (int Cols, int Rows) ConsoleSize => (100, 12); + + protected readonly Exception Exception = null!; + + protected BaseExceptionSample() + { + try + { + DoMagic(42, null!); + } + catch (Exception ex) + { + Exception = ex; + } + } + } + + internal class DefaultExceptionSample : BaseExceptionSample + { + public override void Run(IAnsiConsole console) => console.WriteException(Exception, ExceptionFormats.ShortenPaths); + } + + internal class ShortenedExceptionSample : BaseExceptionSample + { + public override void Run(IAnsiConsole console) => console.WriteException(Exception, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks); + } + + internal class CustomColorsExceptionSample : BaseExceptionSample + { + public override void Run(IAnsiConsole console) + { + console.WriteException(Exception, new ExceptionSettings + { + Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks, + Style = new ExceptionStyle + { + Exception = new Style().Foreground(Color.Grey), + Message = new Style().Foreground(Color.White), + NonEmphasized = new Style().Foreground(Color.Cornsilk1), + Parenthesis = new Style().Foreground(Color.Cornsilk1), + Method = new Style().Foreground(Color.Red), + ParameterName = new Style().Foreground(Color.Cornsilk1), + ParameterType = new Style().Foreground(Color.Red), + Path = new Style().Foreground(Color.Red), + LineNumber = new Style().Foreground(Color.Cornsilk1), + } + }); + } + } + + private static void DoMagic(int foo, string[,] bar) + { + try + { + CheckCredentials(foo, bar); + } + catch (Exception ex) + { + throw new InvalidOperationException("Whaaat?", ex); + } + } + + private static void CheckCredentials(int qux, string[,] corgi) + { + throw new InvalidCredentialException("The credentials are invalid."); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/FigletSample.cs b/src/Generator/Commands/AsciiCast/Samples/FigletSample.cs new file mode 100644 index 000000000..33ae838c3 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/FigletSample.cs @@ -0,0 +1,15 @@ +using Spectre.Console; + +namespace Generator.Commands.Samples; + +public class FigletSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (100, 24); + + public override void Run(IAnsiConsole console) + { + console.Write(new FigletText("Left aligned").LeftJustified().Color(Color.Red)); + console.Write(new FigletText("Centered").Centered().Color(Color.Green)); + console.Write(new FigletText("Right aligned").RightJustified().Color(Color.Blue)); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/InputSample.cs b/src/Generator/Commands/AsciiCast/Samples/InputSample.cs new file mode 100644 index 000000000..05d2449ad --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/InputSample.cs @@ -0,0 +1,96 @@ +using DocExampleGenerator; +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class InputSample : BaseSample +{ + public override void Run(IAnsiConsole console) + { + var age = 0; + var name = string.Empty; + var sport = string.Empty; + var password = string.Empty; + var color = string.Empty; + + console.DisplayThenType(c => name = AskName(c), "Peter F↲"); + console.DisplayThenType(c => sport = AskSport(c), "football↲¦¦¦¦Hockey↲"); + console.DisplayThenType(c => age = AskAge(c), "Forty↲¦¦¦¦40↲"); + console.DisplayThenType(c => password = AskPassword(c), "hunter2↲"); + console.DisplayThenType(c => color = AskColor(c), "↲"); + + AnsiConsole.Write(new Rule("[yellow]Results[/]").RuleStyle("grey").LeftJustified()); + AnsiConsole.Write(new Table().AddColumns("[grey]Question[/]", "[grey]Answer[/]") + .RoundedBorder() + .BorderColor(Color.Grey) + .AddRow("[grey]Name[/]", name) + .AddRow("[grey]Favorite sport[/]", sport) + .AddRow("[grey]Age[/]", age.ToString()) + .AddRow("[grey]Password[/]", password) + .AddRow("[grey]Favorite color[/]", string.IsNullOrEmpty(color) ? "Unknown" : color)); + } + + private static string AskName(IAnsiConsole console) + { + console.WriteLine(); + console.Write(new Rule("[yellow]Strings[/]").RuleStyle("grey").LeftJustified()); + var name = console.Ask("What's your [green]name[/]?"); + return name; + } + + + private static string AskSport(IAnsiConsole console) + { + console.WriteLine(); + console.Write(new Rule("[yellow]Choices[/]").RuleStyle("grey").LeftJustified()); + + return console.Prompt( + new TextPrompt("What's your [green]favorite sport[/]?") + .InvalidChoiceMessage("[red]That's not a sport![/]") + .DefaultValue("Sport?") + .AddChoice("Soccer") + .AddChoice("Hockey") + .AddChoice("Basketball")); + } + + private static int AskAge(IAnsiConsole console) + { + console.WriteLine(); + console.Write(new Rule("[yellow]Integers[/]").RuleStyle("grey").LeftJustified()); + + return console.Prompt( + new TextPrompt("How [green]old[/] are you?") + .PromptStyle("green") + .ValidationErrorMessage("[red]That's not a valid age[/]") + .Validate(age => + { + return age switch + { + <= 0 => ValidationResult.Error("[red]You must at least be 1 years old[/]"), + >= 123 => ValidationResult.Error("[red]You must be younger than the oldest person alive[/]"), + _ => ValidationResult.Success(), + }; + })); + } + + private static string AskPassword(IAnsiConsole console) + { + console.WriteLine(); + console.Write(new Rule("[yellow]Secrets[/]").RuleStyle("grey").LeftJustified()); + + return console.Prompt( + new TextPrompt("Enter [green]password[/]?") + .PromptStyle("red") + .Secret()); + } + + private static string AskColor(IAnsiConsole console) + { + console.WriteLine(); + console.Write(new Rule("[yellow]Optional[/]").RuleStyle("grey").LeftJustified()); + + return console.Prompt( + new TextPrompt("[grey][[Optional]][/] What is your [green]favorite color[/]?") + .AllowEmpty()); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/JsonSample.cs b/src/Generator/Commands/AsciiCast/Samples/JsonSample.cs new file mode 100644 index 000000000..8f7b65fb4 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/JsonSample.cs @@ -0,0 +1,38 @@ +using Spectre.Console; +using Spectre.Console.Json; + +namespace Generator.Commands.Samples; + +public class JsonSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (60, 20); + + public override void Run(IAnsiConsole console) + { + var json = new JsonText( + """ + { + "hello": 32, + "world": { + "foo": 21, + "bar": 255, + "baz": [ + 0.32, 0.33e-32, + 0.42e32, 0.55e+32, + { + "hello": "world", + "lol": null + } + ] + } + } + """); + + AnsiConsole.Write( + new Panel(json) + .Header("Some JSON in a panel") + .Collapse() + .RoundedBorder() + .BorderColor(Color.Yellow)); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/LayoutSample.cs b/src/Generator/Commands/AsciiCast/Samples/LayoutSample.cs new file mode 100644 index 000000000..61a711e03 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/LayoutSample.cs @@ -0,0 +1,28 @@ +using Spectre.Console; + +namespace Generator.Commands.Samples; + +public class LayoutSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (80, 24); + + public override void Run(IAnsiConsole console) + { + var layout = new Layout("Root") + .SplitColumns( + new Layout("Left"), + new Layout("Right") + .SplitRows( + new Layout("Top"), + new Layout("Bottom"))); + + layout["Left"].Update( + new Panel( + Align.Center( + new Markup("Hello [blue]World![/]"), + VerticalAlignment.Middle)) + .Expand()); + + AnsiConsole.Write(layout); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/LiveSample.cs b/src/Generator/Commands/AsciiCast/Samples/LiveSample.cs new file mode 100644 index 000000000..165d7ef7f --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/LiveSample.cs @@ -0,0 +1,83 @@ +using System; +using System.Threading; +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class LiveSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (100, 20); + + public override void Run(IAnsiConsole console) + { + var table = new Table(); + + // Animate + console.Live(table) + .AutoClear(false) + .Overflow(VerticalOverflow.Ellipsis) + .Cropping(VerticalOverflowCropping.Top) + .Start(ctx => + { + void Update(int delay, Action action) + { + action(); + ctx.Refresh(); + Thread.Sleep(delay); + } + + // Columns + Update(230, () => table.AddColumn("Release date")); + Update(230, () => table.AddColumn("Title")); + Update(230, () => table.AddColumn("Budget")); + Update(230, () => table.AddColumn("Opening Weekend")); + Update(230, () => table.AddColumn("Box office")); + + // Rows + Update(70, () => table.AddRow("May 25, 1977", "[yellow]Star Wars[/] [grey]Ep.[/] [u]IV[/]", "$11,000,000", "$1,554,475", "$775,398,007")); + Update(70, () => table.AddRow("May 21, 1980", "[yellow]Star Wars[/] [grey]Ep.[/] [u]V[/]", "$18,000,000", "$4,910,483", "$547,969,004")); + Update(70, () => table.AddRow("May 25, 1983", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VI[/]", "$32,500,000", "$23,019,618", "$475,106,177")); + Update(70, () => table.AddRow("May 19, 1999", "[yellow]Star Wars[/] [grey]Ep.[/] [u]I[/]", "$115,000,000", "$64,810,870", "$1,027,044,677")); + Update(70, () => table.AddRow("May 16, 2002", "[yellow]Star Wars[/] [grey]Ep.[/] [u]II[/]", "$115,000,000", "$80,027,814", "$649,436,358")); + Update(70, () => table.AddRow("May 19, 2005", "[yellow]Star Wars[/] [grey]Ep.[/] [u]III[/]", "$113,000,000", "$108,435,841", "$850,035,635")); + Update(70, () => table.AddRow("Dec 18, 2015", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VII[/]", "$245,000,000", "$247,966,675", "$2,068,223,624")); + Update(70, () => table.AddRow("Dec 15, 2017", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VIII[/]", "$317,000,000", "$220,009,584", "$1,333,539,889")); + Update(70, () => table.AddRow("Dec 20, 2019", "[yellow]Star Wars[/] [grey]Ep.[/] [u]IX[/]", "$245,000,000", "$177,383,864", "$1,074,114,248")); + + // Column footer + Update(230, () => table.Columns[2].Footer("$1,633,000,000")); + Update(230, () => table.Columns[3].Footer("$928,119,224")); + Update(400, () => table.Columns[4].Footer("$10,318,030,576")); + + // Column alignment + Update(230, () => table.Columns[2].RightAligned()); + Update(230, () => table.Columns[3].RightAligned()); + Update(400, () => table.Columns[4].RightAligned()); + + // Column titles + Update(70, () => table.Columns[0].Header("[bold]Release date[/]")); + Update(70, () => table.Columns[1].Header("[bold]Title[/]")); + Update(70, () => table.Columns[2].Header("[red bold]Budget[/]")); + Update(70, () => table.Columns[3].Header("[green bold]Opening Weekend[/]")); + Update(400, () => table.Columns[4].Header("[blue bold]Box office[/]")); + + // Footers + Update(70, () => table.Columns[2].Footer("[red bold]$1,633,000,000[/]")); + Update(70, () => table.Columns[3].Footer("[green bold]$928,119,224[/]")); + Update(400, () => table.Columns[4].Footer("[blue bold]$10,318,030,576[/]")); + + // Title + Update(500, () => table.Title("Star Wars Movies")); + Update(400, () => table.Title("[[ [yellow]Star Wars Movies[/] ]]")); + + // Borders + Update(230, () => table.BorderColor(Color.Yellow)); + Update(230, () => table.MinimalBorder()); + Update(230, () => table.SimpleBorder()); + Update(230, () => table.SimpleHeavyBorder()); + + // Caption + Update(400, () => table.Caption("[[ [blue]THE END[/] ]]")); + }); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/MultiSelectionSample.cs b/src/Generator/Commands/AsciiCast/Samples/MultiSelectionSample.cs new file mode 100644 index 000000000..960846271 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/MultiSelectionSample.cs @@ -0,0 +1,39 @@ +using DocExampleGenerator; +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class MultiSelectionSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 14); + + public override void Run(IAnsiConsole console) + { + console.DisplayThenType(AskFruit, "↓↓ ¦¦↑↑ ¦¦ ¦¦↓ ↓↓↓↓↓ ↓↓↓↓ ¦¦↲"); + } + + private static void AskFruit(IAnsiConsole console) + { + var favorites = console.Prompt( + new MultiSelectionPrompt() + .PageSize(10) + .Title("What are your [green]favorite fruits[/]?") + .MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]") + .InstructionsText("[grey](Press [blue][/] to toggle a fruit, [green][/] to accept)[/]") + .AddChoiceGroup("Berries", new[] + { + "Blackcurrant", "Blueberry", "Cloudberry", + "Elderberry", "Honeyberry", "Mulberry" + }) + .AddChoices(new[] + { + "Apple", "Apricot", "Avocado", "Banana", + "Cherry", "Cocunut", "Date", "Dragonfruit", "Durian", + "Egg plant", "Fig", "Grape", "Guava", + "Jackfruit", "Jambul", "Kiwano", "Kiwifruit", "Lime", "Lylo", + "Lychee", "Melon", "Nectarine", "Orange", "Olive" + })); + + console.MarkupLine("Your selected: [yellow]{0}[/]", string.Join(',', favorites)); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/PanelSample.cs b/src/Generator/Commands/AsciiCast/Samples/PanelSample.cs new file mode 100644 index 000000000..8d83afe93 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/PanelSample.cs @@ -0,0 +1,15 @@ +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class PanelSample : BaseSample +{ + public override void Run(IAnsiConsole console) + { + var panel = new Panel("[red]Spaghetti\nLinguini\nFettucine\nTortellini\nCapellini\nLasagna[/]"); + panel.Header = new PanelHeader("[underline]Pasta Menu[/]", Justify.Center); + panel.Border = BoxBorder.Double; + panel.Padding = new Padding(2, 2, 2, 2); + console.Write(panel); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/ProgressSample.cs b/src/Generator/Commands/AsciiCast/Samples/ProgressSample.cs new file mode 100644 index 000000000..3ec2020db --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/ProgressSample.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class ProgressSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 10); + + public override IEnumerable<(string Name, Action CapabilitiesAction)> GetCapabilities() + { + yield return ("non-interactive", capabilities => + { + capabilities.Ansi = false; + capabilities.Interactive = false; + capabilities.Legacy = false; + capabilities.Unicode = true; + capabilities.ColorSystem = ColorSystem.TrueColor; + } + ); + + foreach (var capability in base.GetCapabilities()) + { + yield return capability; + } + } + + public override void Run(IAnsiConsole console) + { + // Show progress + console.Progress() + .AutoClear(false) + .Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new RemainingTimeColumn(), new SpinnerColumn()) + .Start(ctx => + { + var random = new Random(122978); + + // Create some tasks + var tasks = CreateTasks(ctx, random); + var warpTask = ctx.AddTask("Going to warp", autoStart: false).IsIndeterminate(); + + // Wait for all tasks (except the indeterminate one) to complete + while (!ctx.IsFinished) + { + // Increment progress + foreach (var (task, increment) in tasks) + { + task.Increment(random.NextDouble() * increment); + } + + // Simulate some delay + Thread.Sleep(100); + } + + // Now start the "warp" task + warpTask.StartTask(); + warpTask.IsIndeterminate(false); + while (!ctx.IsFinished) + { + warpTask.Increment(12 * random.NextDouble()); + + // Simulate some delay + Thread.Sleep(100); + } + }); + } + + private static List<(ProgressTask Task, int Delay)> CreateTasks(ProgressContext progress, Random random) + { + var tasks = new List<(ProgressTask, int)>(); + + var names = new[] + { + "Retriculating algorithms", "Colliding splines", "Solving quarks", "Folding data structures", + "Rerouting capacitators " + }; + + for (var i = 0; i < 5; i++) + { + tasks.Add((progress.AddTask(names[i]), random.Next(2, 10))); + } + + return tasks; + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/RuleSample.cs b/src/Generator/Commands/AsciiCast/Samples/RuleSample.cs new file mode 100644 index 000000000..ba91c573e --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/RuleSample.cs @@ -0,0 +1,20 @@ +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class RuleSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (82, 10); + + public override void Run(IAnsiConsole console) + { + console.Write(new Rule()); + console.WriteLine(); + console.Write(new Rule("[blue]Left aligned[/]").LeftJustified().RuleStyle("red")); + console.WriteLine(); + console.Write(new Rule("[green]Centered[/]").Centered().RuleStyle("green")); + console.WriteLine(); + console.Write(new Rule("[red]Right aligned[/]").RightJustified().RuleStyle("blue")); + console.WriteLine(); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/SelectionSample.cs b/src/Generator/Commands/AsciiCast/Samples/SelectionSample.cs new file mode 100644 index 000000000..4459a8ad6 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/SelectionSample.cs @@ -0,0 +1,28 @@ +using DocExampleGenerator; +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class SelectionSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 14); + + public override void Run(IAnsiConsole console) + { + console.DisplayThenType(AskFruit, "↓↓↓¦¦¦¦ "); + } + + private static void AskFruit(IAnsiConsole console) + { + // Ask for the user's favorite fruit + var fruit = console.Prompt( + new SelectionPrompt() + .Title("What's your [green]favorite fruit[/]?") + .PageSize(10) + .MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]") + .AddChoices(new[] { "Apple", "Apricot", "Avocado", "Banana", "Blackcurrant", "Blueberry", "Cherry", "Cloudberry", "Cocunut" })); + + // Echo the fruit back to the terminal + console.WriteLine($"I agree. {fruit} is tasty!"); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/StatusSample.cs b/src/Generator/Commands/AsciiCast/Samples/StatusSample.cs new file mode 100644 index 000000000..f076794cc --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/StatusSample.cs @@ -0,0 +1,71 @@ +using System.Threading; +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class StatusSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 10); + + private static void WriteLogMessage(string message) + { + AnsiConsole.MarkupLine($"[grey]LOG:[/] {message}[grey]...[/]"); + } + + public override void Run(IAnsiConsole console) + { + console.Status() + .AutoRefresh(true) + .Spinner(Spinner.Known.Default) + .Start("[yellow]Initializing warp drive[/]", ctx => + { + // Initialize + Thread.Sleep(3000); + WriteLogMessage("Starting gravimetric field displacement manifold"); + Thread.Sleep(1000); + WriteLogMessage("Warming up deuterium chamber"); + Thread.Sleep(2000); + WriteLogMessage("Generating antideuterium"); + + // Warp nacelles + Thread.Sleep(3000); + ctx.Spinner(Spinner.Known.BouncingBar); + ctx.Status("[bold blue]Unfolding warp nacelles[/]"); + WriteLogMessage("Unfolding left warp nacelle"); + Thread.Sleep(2000); + WriteLogMessage("Left warp nacelle [green]online[/]"); + WriteLogMessage("Unfolding right warp nacelle"); + Thread.Sleep(1000); + WriteLogMessage("Right warp nacelle [green]online[/]"); + + // Warp bubble + Thread.Sleep(3000); + ctx.Spinner(Spinner.Known.Star2); + ctx.Status("[bold blue]Generating warp bubble[/]"); + Thread.Sleep(3000); + ctx.Spinner(Spinner.Known.Star); + ctx.Status("[bold blue]Stabilizing warp bubble[/]"); + + // Safety + ctx.Spinner(Spinner.Known.Monkey); + ctx.Status("[bold blue]Performing safety checks[/]"); + WriteLogMessage("Enabling interior dampening"); + Thread.Sleep(2000); + WriteLogMessage("Interior dampening [green]enabled[/]"); + + // Warp! + Thread.Sleep(3000); + ctx.Spinner(Spinner.Known.Moon); + WriteLogMessage("Preparing for warp"); + Thread.Sleep(1000); + for (var warp = 1; warp < 10; warp++) + { + ctx.Status($"[bold blue]Warp {warp}[/]"); + Thread.Sleep(500); + } + }); + + // Done + AnsiConsole.MarkupLine("[bold green]Crusing at Warp 9.8[/]"); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/TableSample.cs b/src/Generator/Commands/AsciiCast/Samples/TableSample.cs new file mode 100644 index 000000000..223b5a007 --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/TableSample.cs @@ -0,0 +1,45 @@ +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class TableSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (100, 30); + + public override void Run(IAnsiConsole console) + { + var simple = new Table() + .Border(TableBorder.Square) + .BorderColor(Color.Red) + .AddColumn(new TableColumn("[u]CDE[/]").Footer("EDC").Centered()) + .AddColumn(new TableColumn("[u]FED[/]").Footer("DEF")) + .AddColumn(new TableColumn("[u]IHG[/]").Footer("GHI")) + .AddRow("Hello", "[red]World![/]", "") + .AddRow("[blue]Bonjour[/]", "[white]le[/]", "[red]monde![/]") + .AddRow("[blue]Hej[/]", "[yellow]Världen![/]", ""); + + var second = new Table() + .Border(TableBorder.Rounded) + .BorderColor(Color.Green) + .AddColumn(new TableColumn("[u]Foo[/]")) + .AddColumn(new TableColumn("[u]Bar[/]")) + .AddColumn(new TableColumn("[u]Baz[/]")) + .AddRow("Hello", "[red]World![/]", "") + .AddRow(simple, new Text("Whaaat"), new Text("Lolz")) + .AddRow("[blue]Hej[/]", "[yellow]Världen![/]", ""); + + var table = new Table() + .Centered() + .Border(TableBorder.DoubleEdge) + .Title("TABLE [yellow]TITLE[/]") + .Caption("TABLE [yellow]CAPTION[/]") + .AddColumn(new TableColumn(new Panel("[u]ABC[/]").BorderColor(Color.Red)).Footer("[u]FOOTER 1[/]")) + .AddColumn(new TableColumn(new Panel("[u]DEF[/]").BorderColor(Color.Green)).Footer("[u]FOOTER 2[/]")) + .AddColumn(new TableColumn(new Panel("[u]GHI[/]").BorderColor(Color.Blue)).Footer("[u]FOOTER 3[/]")) + .AddRow(new Text("Hello").Centered(), new Markup("[red]World![/]"), Text.Empty) + .AddRow(second, new Text("Whaaat"), new Text("Lol")) + .AddRow(new Markup("[blue]Hej[/]").Centered(), new Markup("[yellow]Världen![/]"), Text.Empty); + + console.Write(table); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/TextPathSample.cs b/src/Generator/Commands/AsciiCast/Samples/TextPathSample.cs new file mode 100644 index 000000000..f306ed60a --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/TextPathSample.cs @@ -0,0 +1,42 @@ +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class TextPathSample : BaseSample +{ + public override (int Cols, int Rows) ConsoleSize => (40, 23); + + public override void Run(IAnsiConsole console) + { + console.Write( + new Panel( + new Padder(new TextPath("C:/This/Is/A/Super/Long/Path/That/Will/Be/Truncated.txt"), new Padding(0, 1))) + .BorderStyle(new Style(foreground: Color.Grey)) + .Header("Windows path")); + + console.Write( + new Panel( + new Padder(new TextPath("/This/Is/A/Super/Long/Path/That/Will/Be/Truncated.txt"), new Padding(0, 1))) + .BorderStyle(new Style(foreground: Color.Grey)) + .Header("Unix path")); + + console.Write( + new Panel( + new Padder(new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt") + .RootColor(Color.Green) + .SeparatorColor(Color.Red) + .StemColor(Color.Yellow) + .LeafColor(Color.Blue), new Padding(0, 1))) + .BorderStyle(new Style(foreground: Color.Grey)) + .Header("Styling")); + + console.Write( + new Panel( + new Padder(new Rows( + new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt").LeftJustified(), + new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt").Centered(), + new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt").RightJustified()), new Padding(0, 1))) + .BorderStyle(new Style(foreground: Color.Grey)) + .Header("Alignment")); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/AsciiCast/Samples/TreeSample.cs b/src/Generator/Commands/AsciiCast/Samples/TreeSample.cs new file mode 100644 index 000000000..dc224d64d --- /dev/null +++ b/src/Generator/Commands/AsciiCast/Samples/TreeSample.cs @@ -0,0 +1,38 @@ +using Spectre.Console; + +namespace Generator.Commands.Samples; + +internal class TreeSample : BaseSample +{ + public override void Run(IAnsiConsole console) + { + // Create the tree + var tree = new Tree("Root") + .Style(Style.Parse("red")) + .Guide(TreeGuide.Line); + + // Add some nodes + var foo = tree.AddNode("[yellow]Nest objects like tables[/]"); + var table = foo.AddNode(new Table() + .RoundedBorder() + .AddColumn("First") + .AddColumn("Second") + .AddRow("1", "2") + .AddRow("3", "4") + .AddRow("5", "6")); + + table.AddNode("[blue]with[/]"); + table.AddNode("[blue]multiple[/]"); + table.AddNode("[blue]children too[/]"); + + var bar = tree.AddNode("Any IRenderable can be nested, such as [yellow]calendars[/]"); + bar.AddNode(new Calendar(2020, 12) + .Border(TableBorder.Rounded) + .BorderStyle(new Style(Color.Green3_1)) + .AddCalendarEvent(2020, 12, 12) + .HideHeader()); + + console.Write(tree); + + } +} \ No newline at end of file diff --git a/src/Generator/Commands/ColorGeneratorCommand.cs b/src/Generator/Commands/ColorGeneratorCommand.cs new file mode 100644 index 000000000..ed03110b4 --- /dev/null +++ b/src/Generator/Commands/ColorGeneratorCommand.cs @@ -0,0 +1,73 @@ +using System.IO; +using System.Linq; +using System.Threading; +using Generator.Models; +using Scriban; +using Spectre.Console.Cli; +using Spectre.IO; + +namespace Generator.Commands; + +public sealed class ColorGeneratorCommand : Command +{ + private readonly IFileSystem _fileSystem; + + public ColorGeneratorCommand() + { + _fileSystem = new FileSystem(); + } + + public sealed class Settings : GeneratorSettings + { + } + + public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) + { + var templates = new FilePath[] + { + "Templates/ColorPalette.Generated.template", "Templates/Color.Generated.template", + "Templates/ColorTable.Generated.template" + }; + + // Read the color model. + var model = Color + .Parse(File.ReadAllText("Data/colors.json")) + .OrderBy(x => x.Number) + .ToArray(); + + // Palettes + var legacyPalette = model.Where(x => x.Number is >= 0 and < 8 && !x.IsAlias) + .OrderBy(x => x.Number).ToArray(); + var standardPalette = model.Where(x => x.Number is >= 8 and < 16 && !x.IsAlias) + .OrderBy(x => x.Number).ToArray(); + var eightBitPalette = model.Where(x => x.Number is >= 16 and < 256 && !x.IsAlias) + .OrderBy(x => x.Number).ToArray(); + + var output = new DirectoryPath(settings.Output); + if (!_fileSystem.Directory.Exists(settings.Output)) + { + _fileSystem.Directory.Create(settings.Output); + } + + foreach (var templatePath in templates) + { + // Parse the Scriban template. + var template = Template.Parse(File.ReadAllText(templatePath.FullPath)); + + // Render the template with the model. + var result = template.Render(new + { + Colors = model, + Legacy = legacyPalette, + Standard = standardPalette, + EightBit = eightBitPalette, + }); + + // Write output to file + var file = output.CombineWithFilePath(templatePath.GetFilename().ChangeExtension(".cs")); + File.WriteAllText(file.FullPath, result); + } + + return 0; + } +} \ No newline at end of file diff --git a/src/Generator/Commands/EmojiGeneratorCommand.cs b/src/Generator/Commands/EmojiGeneratorCommand.cs new file mode 100644 index 000000000..c0ac8afea --- /dev/null +++ b/src/Generator/Commands/EmojiGeneratorCommand.cs @@ -0,0 +1,106 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using AngleSharp.Html.Parser; +using Generator.Models; +using Scriban; +using Scriban.Runtime; +using Spectre.Console.Cli; +using Spectre.IO; +using Path = Spectre.IO.Path; +using SpectreEnvironment = Spectre.IO.Environment; + +namespace Generator.Commands; + +public sealed class EmojiGeneratorCommand : AsyncCommand +{ + private readonly IFileSystem _fileSystem; + private readonly IEnvironment _environment; + private readonly IHtmlParser _parser; + + private readonly Dictionary _templates = new Dictionary + { + { "Templates/Emoji.Generated.template", "Emoji.Generated.cs" }, + { "Templates/Emoji.Json.template", "emojis.json" }, // For documentation + }; + + public sealed class Settings : GeneratorSettings + { + [CommandOption("-i|--input ")] + public string? Input { get; set; } + } + + public EmojiGeneratorCommand() + { + _fileSystem = new FileSystem(); + _environment = new SpectreEnvironment(); + _parser = new HtmlParser(); + } + + public override async Task ExecuteAsync(CommandContext context, Settings settings, CancellationToken cancellationToken) + { + var output = new DirectoryPath(settings.Output); + if (!_fileSystem.Directory.Exists(settings.Output)) + { + _fileSystem.Directory.Create(settings.Output); + } + + var stream = await FetchEmojis(settings); + var document = await _parser.ParseDocumentAsync(stream); + var emojis = Emoji.Parse(document).OrderBy(x => x.Name) + .Where(emoji => !emoji.HasCombinators) + .ToList(); + + // Render all templates + foreach (var (templateFilename, outputFilename) in _templates) + { + var result = await RenderTemplate(new FilePath(templateFilename), emojis); + + var outputPath = output.CombineWithFilePath(outputFilename); + await File.WriteAllTextAsync(outputPath.FullPath, result, cancellationToken); + } + + return 0; + } + + private async Task FetchEmojis(Settings settings) + { + var input = string.IsNullOrEmpty(settings.Input) + ? _environment.WorkingDirectory + : new DirectoryPath(settings.Input); + + var file = _fileSystem.File.Retrieve(input.CombineWithFilePath("emoji-list.html")); + if (!file.Exists) + { + using var http = new HttpClient(); + using var httpStream = await http.GetStreamAsync("http://www.unicode.org/emoji/charts/emoji-list.html"); + using var outStream = file.OpenWrite(); + + await httpStream.CopyToAsync(outStream); + } + + return file.OpenRead(); + } + + private static async Task RenderTemplate(Path path, IReadOnlyCollection emojis) + { + var text = await File.ReadAllTextAsync(path.FullPath); + + var template = Template.Parse(text); + var templateContext = new TemplateContext + { + // Because of the insane amount of Emojis, + // we need to get rid of some secure defaults :P + LoopLimit = int.MaxValue, + }; + + var scriptObject = new ScriptObject(); + scriptObject.Import(new { Emojis = emojis }); + templateContext.PushGlobal(scriptObject); + + return await template.RenderAsync(templateContext); + } +} \ No newline at end of file diff --git a/src/Generator/Commands/GeneratorSettings.cs b/src/Generator/Commands/GeneratorSettings.cs new file mode 100644 index 000000000..17d621416 --- /dev/null +++ b/src/Generator/Commands/GeneratorSettings.cs @@ -0,0 +1,9 @@ +using Spectre.Console.Cli; + +namespace Generator.Commands; + +public class GeneratorSettings : CommandSettings +{ + [CommandArgument(0, "")] + public string Output { get; set; } = null!; +} \ No newline at end of file diff --git a/src/Generator/Commands/SampleCommand.cs b/src/Generator/Commands/SampleCommand.cs new file mode 100644 index 000000000..02e9f3beb --- /dev/null +++ b/src/Generator/Commands/SampleCommand.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using Generator.Commands.Samples; +using Spectre.Console; +using Spectre.Console.Cli; + +namespace Generator.Commands; + +internal class SampleCommand : Command +{ + public class Settings : CommandSettings + { + public Settings(string outputPath, string sample, bool list) + { + Sample = sample; + OutputPath = outputPath ?? Environment.CurrentDirectory; + List = list; + } + + [CommandArgument(0, "[sample]")] + public string Sample { get; } + + [CommandOption("-o|--output")] + public string OutputPath { get; } + + [CommandOption("-l|--list")] + public bool List { get; } + } + + private readonly IAnsiConsole _console; + + public SampleCommand(IAnsiConsole console) + { + _console = new AsciiCastConsole(console); + } + + public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings, CancellationToken cancellationToken) + { + var samples = typeof(BaseSample).Assembly + .GetTypes() + .Where(i => i.IsClass && i.IsAbstract == false && i.IsSubclassOf(typeof(BaseSample))) + .Select(Activator.CreateInstance) + .Cast(); + + var selectedSample = settings.Sample; + if (settings.List) + { + selectedSample = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select an example to record") + .PageSize(25) + .AddChoices(samples.Select(x => x.Name()))); + } + + if (!string.IsNullOrWhiteSpace(selectedSample)) + { + var desiredSample = samples.FirstOrDefault(i => i.Name().Equals(selectedSample, StringComparison.OrdinalIgnoreCase)); + if (desiredSample == null) + { + _console.MarkupLine($"[red]Error:[/] could not find sample [blue]{selectedSample}[/]"); + return -1; + } + + samples = new List { desiredSample }; + } + + // from here on out everything we write will be recorded. + var recorder = _console.WrapWithAsciiCastRecorder(); + + foreach (var sample in samples) + { + var sampleName = sample.Name(); + + var originalWidth = _console.Profile.Width; + var originalHeight = _console.Profile.Height; + + _console.Profile.Encoding = Encoding.UTF8; + _console.Profile.Width = sample.ConsoleSize.Cols; + _console.Profile.Height = sample.ConsoleSize.Rows; + + foreach (var (capabilityName, action) in sample.GetCapabilities()) + { + action(_console.Profile.Capabilities); + sample.Run(_console); + var json = recorder.GetCastJson($"{sampleName} ({capabilityName})", sample.ConsoleSize.Cols + 2, sample.ConsoleSize.Rows); + File.WriteAllText(Path.Combine(settings.OutputPath, $"{sampleName}-{capabilityName}.cast"), json); + } + + _console.Profile.Width = originalWidth; + _console.Profile.Height = originalHeight; + } + + return 0; + } +} \ No newline at end of file diff --git a/src/Generator/Commands/SpinnerGeneratorCommand.cs b/src/Generator/Commands/SpinnerGeneratorCommand.cs new file mode 100644 index 000000000..d1ea6eaf7 --- /dev/null +++ b/src/Generator/Commands/SpinnerGeneratorCommand.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.IO; +using System.Threading; +using Generator.Models; +using Scriban; +using Scriban.Runtime; +using Spectre.Console.Cli; +using Spectre.IO; + +namespace Generator.Commands; + +public sealed class SpinnerGeneratorCommand : Command +{ + private readonly IFileSystem _fileSystem; + + public SpinnerGeneratorCommand() + { + _fileSystem = new FileSystem(); + } + + public override int Execute(CommandContext context, GeneratorSettings settings, CancellationToken cancellationToken) + { + // Read the spinner model. + var spinners = new List(); + spinners.AddRange(Spinner.Parse(File.ReadAllText("Data/spinners_default.json"))); + spinners.AddRange(Spinner.Parse(File.ReadAllText("Data/spinners_sindresorhus.json"))); + + var output = new DirectoryPath(settings.Output); + if (!_fileSystem.Directory.Exists(settings.Output)) + { + _fileSystem.Directory.Create(settings.Output); + } + + // Parse the Scriban template. + var templatePath = new FilePath("Templates/Spinner.Generated.template"); + var template = Template.Parse(File.ReadAllText(templatePath.FullPath)); + + var scriptObject = new ScriptObject(); + scriptObject.Import(new + { + Spinners = spinners + }); + + var templateContext = new TemplateContext(scriptObject); + templateContext.LoopLimit = 0; + + // Render the template with the model. + var result = template.Render(templateContext); + + // Write output to file + var file = output.CombineWithFilePath(templatePath.GetFilename().ChangeExtension(".cs")); + File.WriteAllText(file.FullPath, result); + + return 0; + } +} \ No newline at end of file diff --git a/src/Generator/Data/cake.png b/src/Generator/Data/cake.png new file mode 100644 index 0000000000000000000000000000000000000000..f11d285c9463d14b1c4250457fe2a358678392a7 GIT binary patch literal 52832 zcmd3Ni9eKU_&05oicT3NOWJhGP^T=}qluEG#X6Qs*=MX{A0$#HX{GE&maGXg3`3C= zF~)Ajkfp{phA@M%y!S)D-~0Xv@A-WCoYS1=x$o<~?(6zq-)ngun;7Zs+9AG!kB@KH zW&MlS`S>=ELVpCefnN+WI!3_1wm4oeyuim-94oYZdn@?+b`O0^Z$3Vuf1p47ZH$m* z@FUCzVc~Pb-NDE2w%0vAkK4{@A9?gWpF`*5Ppgg2JM-~1|Ga$h!cBkM$rYhjlHJ(U z$9MRAHcxK5uqlmyZu6Iehr)hu-Y50$P+Qop+9SToq~41L@AlW7mZ9QDr)9o>j`10e z-?#np*L2;J1W%3UrIT`w9nrFTGM;E7%9{AU*aBs|r`aZpc;s(xjHyfKG z64MT|L)~ea8;ESVVak5p>zL#{Erh%I*^_DEttDJ)`M&C zMF_iFdd6_rlQq4myb%T4$D~lvztS)L%22R-`e2?n@Sk+lr1I2&hYcTP*xS)|Z*TWh z$ia=L!hG#x2wSJ)2NpYC?DD75xKpbtf8TE&@h+14!mm!=#Yk`!eWCj-ZTH6iDa%q0 zOFX&Ug{X{7K@RY*|9D70I&io8T^4t8b?NW>zdkISpH|v39a731tW?;u@oSh?8@)Bp z;!!~%ElQLTFTC;VC*hM}LosE~T2{w4e)zddRI@mgwL4};W;nJaKkoOOiJ8%2t!a6>`7JxL*jb@P`U7im z0XlzWlZ)B$GCe>sBDPw*R=StG>LOU<@n=fKM~k;`Q=*nPA35tiGe9hIL#NXXPD6xBY8STD0Yq^mb9f+oi2rCDck&NfT;1vk%5B3yzGKW|6cGNHHg_hxbj9b-uB^>+v`uCh$vk#+PvV!A}Tmj z874)}W~>TNp zKyOHdUJ7HB(&t!RE6_Hl*5wa_+2e{kk3CYz#J*`=!5lg=KL2C9?>+Az9iJVyXiaKv zn4+)C!-x8$Q?Nq-Q^s?>aH+%fZKqxh`{p^aqi!FbKIC!or_$$asSs4vu0)N*LR*1> zzxJqISB&g2-JergI=X05bk7W)rsXx1QjQ>^8gG`PqB+(}ef_&KBYi6CGI?g}*RB2X zguUtfN!Dt@GyZv1ht5rbNGqTA6ob&Ao+7 zy`hj)rM9}l^0Qq|_`i?o9IOp+;hI0xyjFDEtUath3#QQ-VjLuo4GcD^R;n&5*j?!^ zxvsg6m@G~2>Q|+sy(Zw%pv{4O_}F|mLmXNY7$~=5&WmF}M2S?oOK&{A9dm!cr?N(M z?tb9PN7}*G<}n8G>smD&9_aGNI`F(q@?Sw+F0~V`PncWHtzIj#GZPb-QzDGM7n4>M zuQ`5i!;1G$tgndCw&@_&PZ{tjYm+$S44vtw8adi&76$xSvkRq@Ue)oPs8$`ZPJ zbR7+HqvoN=mwpYb@u7zphlWnhWrFpZ&Ui z4{eDKS?x2+dAfOF;iuwSKaIWkxWIEkDK&7R%=2^!7H{fg*;wxR4xzAhKH;9}*4dk` z)B+8HXL|pHk~1Zf9(4mKx5dm25{!@k7V9nP76rfKXYAB~k0GBi-CaoPpobB%M z`NrHGzsYTQyS(P)`l8#{XmB=zD8Bw)?k6jIOmTk^tfgSgU~~D71Bi(d1k-mQ^IDO) zndu4kYuHL4Yw90l=x1B8`Gh472s{oO$a?d>t2U8&R~L9A6{klwvouW)E_TMH%zH*1 zcLm2~F-)xVnGa4v+l1}#*fr|tZg=paHW7xMImr$01AFX{i1HuFW@SboYj%pV+~4Y*mwyc@>6k z!;3`)#(d1JUAW$cS14lqNl}ltZ3!7;hc>BuZ-PWm)3@GCa?UHy%a&%lpvl~_ld>GibX%7OiA9KSO zyo}fuVrv>!bHBo|2g>@i z;Rh_}(almbC-MxL6+Y{aQ_8o^eMj#Xd_VXE>0`{#n5@28(9jTd{v-$oz*)+QwL(3- z&naF92BLJFRJU<*YtP-I$%ouxYy^YSxh`;0(edXnjn4u3Px7BQ#2SASsZP3#YbhDE zES)Lpe{i_U-%V_G{l!lLnwyq-ZIlH{!~$~_9}{Y;mfp_xU@NR*ydU&$A8qF;H;IHC zai*4li>FI`5WZ9xq@WJ|JM@oO(P`s#d9A1Sv^q}pNOYLFzAqgO0fN{tjTj2L3tnw_ zCV;m1+{zrwDibm~Hdxu{6)D;Pt8AWR6f`M5tc&AZ$8K&|^xc%UXq zs>kfn|KkGZXTT0@#$I<+R_%q(HaxEmecP0 zlZ=Wf@UMK)p!TwKKNpOojF%wXdHoa)FR%O9%iXwoD!$TH8vTWm8MOS<<$QqrI!2`# z2XCEwi%kr-KG8DQi}#+GiWVKme78@jAG&Jg-F0)7&?_k(eOXI zx^|K;;xL?~m1`@9=6nmW@`NSqyOq?YwEJR@aZ~x`&Q<7A4n)kGEg4CKU;n$Ca@Ba-g$mJ}{E)4q!REB-Bt zP#%!SH<8z?o6-FwGoR*P`pgIjr4%~EY*Q<$3^d06<=(AM(SoBG%M^lhH!;Zvoy+7h5EaeY8kA5ZffF`-lAXPMMk*AmB}w>QgK3Z)M*> z*QR~;#No8W8^fE+z!_e{7|CG$3`9}?2p~o}e@#sL$cd9_bRAC&G6x4^2#?Qy%K-Lx z93D7N6FACAH@Bo@5(A!Jg7oji$Jv=p>S1*s+Z@Oo(D3z7ta1{zZ^~dPUn1;Bba&T4Fmr3J>UQL6wQHB>*EGOSzWPB3+!+Q{Sr}P(8=>%o@22 z;$Lhk`>dFjXaKNmGtz}PxBs|F>^Zxu0wi1ChFMw zPUZW=Th-S3!wX5;!Zv@mc!v-MG*!d)Rq;D!TW|C(=)v&pZ((SPuyL$#BW_mJ31>yc zGns&O#1$dTuyT;X3dg+1?xE_tBvYX0`3A4u)mCQJ&{_H8wdy`Vxz~yiQa0=GUDx?L z0dP4*vlcj;GkDGK(RxIW(53RPOim$P7*=ig$~|p&Jb_MK)ifczrd=4k^q1Lh(WCNX z39|z!Dg>nMv+fH(<__2Arj;wbm|_)gmtezl$hwt9Iv$*|L5Oz<5wrP!a)K?0LH?C* zt4`>FZ2@O&#ju1?fNSZP`=2!5m=qyk@HD!`b$dD7Wn6UvOv3|Edfqs%+Fxz~0f^G?0~ddm7%SF_hl;|<&KGGrb1(ykc-Zd270N-Q4BuhAfr1_qzSNB zqGvZ$UE<4m^WP>C>$Zl5<_QJT#8EiuUWwL)X-`!(B;$&UCHg9dOZ5C{p@>65^2uWa4g(p zlB=PtPIP}z^{p_mbQGP_Et6Lb!{Lx~E!}uTQ4z;Fuu3#B`+UF=mTuOR2~>;Yn~o(3 zHV=*TeA*>8^%41kMadPKRCR$b4Ry;DF^K7k5d_H5R?3)dsO(4o8v7CY^a*z$3=6CE z*mV^ahc10ld0tVo^^M3r;%Ex&y$cd2MS~2z`3zQ`(S77ZlQXgy6Sc0IFfF-5xk9aS zM(k?Ss8lIO4$9?+_h=T1`_2}p?mH0Om1g@uJp(Z?guk|8Y*06Fs~l!(Y{>NE z2D~1{=#t)4#VOTN#|Fi8dKJpw(1)HNO8rI?rA`fg339jDBRSwvFhI1d*=9LUu&~y% znsWdq2Ni9caSbyY2J5eDA_jVxzrs(b!S zXhrq^*SdYcU<0se;k1BE^Ijm z*DOc7GPNSN&(D_&_slUBYr~Z7hA;hUiU*|@{$QVpxV+Cnck7l$Ifjx^w!8YBn{4h) zx8RBOL#l0faIq84CG*@|8C|56QzaJkAG zd!d7-g$C!3pmRU9=P4$0nEB1u#VD9gD<3-|Rtz`shA?Vq)hbfdIrZ$rdF1~_&1c&&*WMzKC(xXQh@I->7KxsJlC?aw zZO?W0p0x6zFXhk1jy_GC?{5MfE&w;K~%oF@Yp#{uaLUnD?}Sl1ThzIUACshN+S84tR%fkLBDS94fx~$~TE+ zv;h~H#lCtrCJvr~luHME1It$03X*S%HDbEu=bD_TsJwGQ{Z$3T(o?*ZupD=1D)QG2 z;Tols%Kry9DP%b|jvD}nNi20}D+j8+rPr9bxq_PjL}^??QXb}x0o3S@t$8g2+>LwDUekdP7#Fl_nGO*t`J%gy^XSRThP?7_7ZG?n#x}yf)Pz`f8tJ6 zGR=j3RxRpRq~~5xr0Yg~j8e{jdZ~-xCsd{mds(VntQgUlPrF?Xi@m+CF8SEgl|HF zS>UbbTjgL4)uT>OjSBGbWO4L6tP@Q`eVt$)ye9V8vUD3c^>rUpO8uX;0L-4gea_Up z&WSsolFn3WX+Sa*jicQE*HzOBa)iFfeLYpdtcc-|#95Fz6 z2$Qr&q4SE(BM4!RT#+X|{T|nUyf*?yR`$uhKo9p3|4_49R^&5WCOye}pL!&(S`6^^ zhRo74>0i^_2Q)$xol%-6-OPU;ptuHy;}c>lY5 zAh%b3FYkN@Vdup%<*isDf_Nk=`AHpr@BAvDq_CF^bn(Y4m+!Pyy?`=tS zZOZLQFC8_OVqgq;tja}BdSja+W%u{E+s~_N6w40aPeG;y@l+P0Q3LZDp$c_-OR2~%hF=kQ-1CEVK3Sdb*0_1LOaKcDlmxBAb&(D z+T-=sIj6N08>;c@LhPO{$R`s%fl7#+!ln`zB7feklAbY^?u>Wh_z=O_jEbk|Ca4&^p%on93xsIN}o_Fcr;ZWfPf;lr^SF5J!_OVFy~+T;e+-q zNFzC?#%mSw2r&se6miMP`&~_ioZ*4biDZt8P|eCJd(}*NylbxlK%ClZdms{FUqg%X z29Ab;zyIpAhX$YK_LB~iuuh0l5X2;U>_UH^Bi2G!*0Bpy9AB>@BH0huZN9^zG_%O2 zwjD~;k5+T>{WCWUQk3m>gyQN8UJp}DfrFSIJn~(@r(SvNifcE^Y+>G2KybZ;jTr)E zfj^sy-1W>j3=3My7{{+;E9wTEgdm#I5-)yRm&r^))92iQm&X{FGmhr3Z!V~Csshlf zZQ_}V&p1h0q&Fx$qHL5?ML;EYoztxnS{~ar5@2 z^WL`%CdBmz;3N(A{s<&3{_sfs&=3s!1SVPHEMpTxJ$Y<>mo49zwwBMt+$~wkJ9}Bv zvr$S-xSlLfoC^IjT8MsvlIL6{FEL6~&XY*bK+(ySisCeGA)`79nkG1AR5XuT^w6C#lZO>$FiLIp~<=vmG|BP5nSvYT;44q z8S!U#O%Qh$$gIn9^FB$x=}uQc!6dr}o;tpX@P5gSijpbIvM0{u4QSvHaG2w9xGDv2 z@7vTL-duk!-`zraA46STLL*@CFT^^fs0~X!{3zF`2(l5M!4bxvp|bB^;Y&SX!Jr*6 z2h*6VA8La!&`2}3;?Q+k6h_H+atFNF4Z_@}4{YV-W)@w@5lqcGZBZ{`L*I<9bf9tLhm#i})!!?^DgnB6Fi= zv@$)l*#2kJDO`JyQX^kRDS_Oae!Sv@yD!exMUY*G2YC{2%6_K5t90~@UTQ2k!i`<) zB|D|oQnFrhY8tdpS8=79hF!C=_*m24g?*RUil<+hfYqW5N=7KFIC0|2eA%GnE*tdzFaL|^waekWGjyJs1YC8 zTy5^fR#7_xQ`Q>~FWdDH5cGc|6db!|-U6KPp=$OO3kP)cphykMM^An7Gt#B@C(|u& zLfHGsM9j!CN#fu)pMx_$1{u^Npd>4nhw@zg`TM$+56>M|3lCF1AEA)V_#MJ&&5^)q zzC-Alvo@!Er}{qhX}6m9v6~-E?DFENfyGJ_!A!t+Tvjz}OS2rm)70l9GXt&@AWx&f z7&?CLfM_G&=t`S^=aJc?yMgI@~9jD zY1(Sj#V;z~hc{hsnOrM0(~3d^|DO2@U6eBq4|-j3z$ar$BS8hU$ZrPkHL#Y|ux=}@ zZtEG|>Bd|JsW2SZM!V|ztTWOj5wy7|Ae!2Of^E^6py0!{exG6LNxj5>6UHqcS2nBd zOH1VN3&WS%s?qIvxW--<`}={NKrdH?z9#k_)fO&YU^!zHD}1S)-UY@FS|n-zfNCI8qPBos%EdQV z3f-CqZ5{(Ig5pXtOx!x(e9%3{c4m4+q@$f zTKQ--iiG@B(oyNUA`M>x<`rwY&h<0?;l9rPs!ctGdy9(yHYyc_G|QeM&(GVD}Jnzt(&J-XtQ@^ zy50TQ`lYX!h^bnZwHAPO8Eqioci(}4=g@+7ojT=ZgJWw%ZFCW3Z-Z}xOrO~mqDY~w z-k0N}v<(&rF}|T^DSvo1Jfx?G`wa`@2TO*o+cKnsht6z>DS+{OS^wSW(MJUFrifkR zm}H%LRKH>frxXEKm67mt#+HtDB`MT9Y7s=pb5FB}4i&AU+pEMo1O(ReM-$=x@&T4k zGoiSV^n&*z{aT7HyZAEi5S_gzYC7ear!UVi!sCl(@>DNPAvPCb9y}ygc#$16TeU21 zIJ@vrl!|hF0jB}-bQ!8Thj|2Wmz@JHysU?E#Y5GvW^CKl9*)#IA1pxPs_zQ2(Z&u| ze9SZ3zD&}V|NV%tdlDHSG=Z|P-oTE}!yAYuV%G*0s$y3%?K-XI>Wf@o|5Ljsj|x-u zK~Y%&v+6xVUI6FY-S5k;>-R%27)klF>3E)Z_Eh)n;O!K&babLUxV1~eF!BiY8Ees9 zXz+#xv70hQdMonOqFB?)$F<(ZsSZA!jYjTaXujGq&wJWuuzrHmCSvjcek|Vx9OHso z?XcsE&U$C$e6jGKJEp)bxJ!95eXxlVkru|zM}tnFwuIVRl0Zb*T|G!}JF+fLW-#dA zUG#P3L4!t%{@WO4UKEl^-y}IG<1GtZj%z$PtI%o@}_b>+Gc!@|qk1fTh`PX(=Dzq55 zX11yy>0rT1+g#+Y7B|~HEGeUKDE;2s0dPJ|OD-(_KyAFYOM@zKv-VBdsESN^BYK)m z7&3?OyHAG@$$BeUH*;k3*hC}18Sgzjc5 z@5*Bk87+=J|?rzt`0rOSbjdZcvGR5AO4z#FNi#^zY*YG>3OC|qsaZaB$9 z@Oy^EReXZ_fZ>T*e^3tp;56xA$|dP)XiwM-7`k?z9Y298MWo?->a-o4_#L-rne zIxQqlH3%Xjq|c_*-!a5Xpfm!_E`<>?j|5g6>7=LbqSR4^8e^~LG=!B zD}l`Bnfh$f33%D5BqWBAjjEVUD{7-51^2FTwj~wy-P+{(1HJ zX1&ld#F_yR-kh8;viSof%_TMVTH=OKY4SUCW~uGMkg~mHcQ=F@+dPxc-s(}Q*e`FD zszOjp&?;X{c<4+^c}x`P-~Kbg<6?d#a3|zFjdKZvrAm!d&2pD}K2DU~&~TS_`!%u6 z>5JbU2i+C1GYTTmH*trA+73oemk^7{;=r!c+LXDCG&(u>jgWGANnW-VqA(L<2*YQ~ETsEQL zwaju~I(&U5jOb(=Jn9t83zXz&>0R7;88VzJwz3Hy)B2JpUNYPDltRUzx=`BooV_8Y zv@4@HWRkZ4`Uuz$mJd!&3FvLrX8I-CLTSqNcMd~ zkUSk2%d`aB^c(CACuyWsd$Puz7_BBy1_{Al&ff8n6g_Bl@;t~!UB(R4wqMX7v#^1G zZm-{@jfw2M+}F>+ck-%wbT57h9HZgsW)6mjca38h1}m7v7fKAXplm~EDgN<@6g`^P z#V<<+xaxD9Cs>;YfwZie)gR95D}Bq^8(;=%u};)Idk!9kFa7CI%t0oGG--eITT%#K z&|Nn~k!!Lu`7OyLtyNjL>ft*pkWiY#hS`OboNUyRZgzDdRGbhIA0J8Hm^kxxl1tDk zMc7WtfFnFX&K2_q{9rdgIjZtkr9_ha@p!_Ra>0Rjkc5KUF+(jNc3b&e{PJ5Lm$FM} zoRc0AD5;}_YBwfNg{+Gyn6uXx%%!#Ck31Ya%WU}~{mMoqz_038`pS)!^Ir}^17_lOQNQVb|Q3FisN^aJI_I{z}P}e=FoW#Q~}vs9(e-!&eOM>H1RtNq&TNn)y7?A zitpA3_v#^R8`|FaT8SDfs0vC>}-LMor_ zMP;EcBs;bPdp>z7IjscDmpN1SxVv@1`T(*1k%zT-_w{BCZO9pgq6WREce&-yL89#$ z|B}?%4^8eIS#tkulZj}kqLpVNxVp(^!EA;y_V(@d2?CRC>!JPWw|e2_d7y1| zwtn32g0;~>rpwj&ysg*$Uy}+JQV3&3THfmgB9n9DccE7pAQwNr-%4mI7yBqJ#CSto zc)tg{X05WuG?Cd}U|56Ng@RCFFlVnPm`Te|bS zYx~SjpN2f`lk)gTqN!*L;Cym*N`#+-$#E_%Mej+9k-E6mA|mVv`#3;SwB=^&P$Y; z>1j5GQ^+bE-9KQ)pob%I212&U99kZCyXX1sqrYxM(fcVNj59P#4~tt>9uFMLwmS;( zixEV!Q%SDQqGC$Op#*X1cg3#vIa2N63akoUBwo3{1io~iU41IBooYk<(QvTva`Kk7oC zPWfV2$$;caXT$Md6VBBvY80Lw%95mZ_^-CUGzZ3pZw^&_`cV+wrW{+OJ;bx# zuH(P|5Z^k~*%ew>{IhGI)GWoiBzMyyrVZcSKZbhnXQknyYh9{3_F}c~ic4tCq*?O$ z$15(<-J4KuePh;YJ1}RnHb~*!U8jNTb zS!)R$4$Ls@4k*Ptt^=+%%6m9nE90@YDgBI?t}bhjCH@*jz(!!x~_B%my7GJ?5N-KC(g}mN8f)R4%5yM zUPBk@vH0iL0_<#M=hb8ttUj)PH&*T+(}x@h;#TCm+FS;F+##Ljc$$#g@=!EHP_2Vx6580a6nO=C&!%wsZ%#xqu^J? zM73?qEr^#GOo~H|d&^*l+aBC`|+8XNjH`|m9LX7H*~nV(r}^w3jx z?w^aN|1catkyxRH)f6wQmxa}F!l*skLJs4+J3*yqZb|DWGl-X^YC3zy%ul46moe7Xc=^MH)wt`v1^Lr{3u>Z>5*b>E_X)mEA&n>Yj9UYFNx+3aznX9JV36P zVB_45D_c(Ob*u3?CHCSJXr6{W^cbohrY3aeRY9F4(4TXr$TfK$Dis-TvqpxMr4?2a zaGb&WOCic_Ts*4F%wg9U0`>V4t{;txc??*T!9(vGF^M6OF5AltiPzJ;5A4MlfQEY5 zl07m9B`I}+9mlx`upx?5{hk|o9;+^dzHJBHunOT*LG^%_nPeNQ%*3t%06FWNWij?p zLeTUhO$R?y`z*Wk!0PF@#t7rUextT1Gx;9xF*79}1r%`TalHe`oO>@|WK%2p$%fCn zN>7WomHc!_5#Aj<;DRo~EomBz1yMLRt>!pyLw@>Zc%bE_6f7f7e_-`!E~FUz(a61i z>Oj8Rhc=mtMi32i_88lin=HUw0wAq-mA~iK*x96PX8u~I&_FD4)EDO8r^;6iQK=0tVPRV)}^p}3r&geO`i z`c&H3VUw#I7FP+mRZHTayyZ?XuUjMs%@qf1@3a^*7mODXdsfoGm3v1oGv@v$2qvs0 z+Ta~i<(8@6!vC|!X?k~aoF2l+aaK(y8?=pPOUJ4=e|)R>j%QmX-xTgiSV-AeHOpBg z_58WxvEQ5Cf4y9z)6=ubD;>1G3#V7xjBE5E4S0MoH3SLw@WHw5ayOxNX%QHbul4Lg zHAGvew9uUA$*-!-O(`FpY@QP<+VRT9@gC@0&$c2FO}jOkc{u%SG6YK(&X6z$%T)oR z#8NxQLKyZymy^>g-$AeC=&IiwPvCiy*rD_WWR=JCiSBuezFu0^6D?8>7mzwssliQ@# zl=YxPdlkbw(Bcx0w9c5xzNft@M##SF?#`BycPRdtPYLJsbAG_mZVc!-OCMjb{vh9k z4;W|jUct!yw3&{lc_n^NC+yv~buNsW=SV}^d^q<%q2N{Bm(QD_O!PMJ(z>f~Qt#e2 zmhV+e@#EX7m9EJWn+wgz%KmYVRBZq6lwVxJBEI?|_#9-yRlEgA++ZHi*PJFU4dgxc z4%yFIa=LYo8M=;dPG~8q!g`p?+aEN1VlqzOHE`1Mazf>j6K?tYnV(Kw z&i;T0cK22i8ba5gW_Z2qL&t0Iz&IoWtMxMZmy%y9vN{q5Xz0YfJ%fEW?KAAsSC^rt z)7;(rYI=96jXQ!I~sB)fmvA3ojSLl~pX!#|inc64cEg5C5UDhRneFuaJ*JNL@2Bt?@3Fo=QUm}JUD0{$ z?74uv3QL5=?lWm%s%g;5M}=7Q{_DjWo!RMmnQCEHf{PPN93l>Pk6`=N-@!ZjF;hMg zU*cZ=q`KrUbs|ohO+c{29f(?)!l6TrR#vM1X|;O|)419s$h@J} zRo~#LD8IBP;j%uiVGjs|hxQU8X-j3BFQC#L26>mZKx$XRgq{O^qP{HpDt-KpXkKU6 z&S&bRvp~D? zX{*)TO{DhJWZ^vEx0uOxi8q}6;S!s7J6QJi5gcv+nN7FMoiuw&!51i|g}~$>ke3jD z*`O!Aw1auP^nnR1wnT3`YY7KIllkJRvWApakAHA}uGSdtR=lx{ZdOSJY|MJTZp)%sL}tHNE7-j*s-N)YX@q2zF|)?=I+g zRTyi2VP*Tj@7RnAC;+wk==A9{>-aqHNJrF+j|t%4su8}35n)$5>J?zwTeT|@-~yon zeRWh@cS-Mxx-goSJ7KCRjJD!4MtW3wN5HBMWW`4BTfCozWz`RVj{*hoU~WD?N;U%3 zGpWjo;|CtAZ9i7H!-@y*_+yd{xd9kTAY)G?+%q7w&3ED*w~tn*bWUNV)NS50uO_d^ zaWp1pE)=r$^3(bw_O(f?tU@rL{n8&y)h)#NA|-Do^X0ZC zME|Go(4`Zfof7hMJkCw-uz3o{|ML)6BbH#1u(WigQqcw*lW!%+73J`#pkLA44@+t| zOLI=HJ5NcjyWWF|E{M(eYG|24LLtt5@IuUu_Fjgz+51MtKg|=F^DF%+Jn$s$+v_3? zUVi_Y91S%x?s}?oK=^Y#t~e83z9jj9OzZhDe^!v$deb(r;fB}pt4y1^U4>Q$R$5<* z34-8^ImXaI-9=d-bFhPFQ^!-L8nffzfw8{#UGnbHQH>Gr?vy#EcLogaCA}{Ll96+HoIVa(>}wy#HVI}eR>NI!5&AG6QZN_b5d^E6WPa|9yBqxJf##FC z#UAbA!R3VriEhoKNxEi}yR{YL8r!5yOD8I8W>;%2gAkG<1PU9fA^pn>+pr!*wRnO_ z(*yAFRj{E%T<6w%2WVSob`r^Axsew0{oIU#EVK;y3G;J1Or7yU4)u9)dK<3vi3i#) z$jb*a=fO{Zzo$h;!PhY3>rG25ed0vb)IIPGTf~piF8IvsZ$jE5)tq<~#DeSXaMdRh zXvKwX&(Oz%vc2g+*JxKp##a=Oo#7?N4w$85r|s>jzHbjD=_21R`TEhHGqXOg8(mHh z%mo@>K})v@{5e^grP>kcS5-E8Kf(tcq|oAXZyaw(JZgaSARMg|DVuSU-e$zMvK#ee zcY0J`ZxIvAvv{{J;c}-8qi_*jiO~QV%%O8`LW;b7WzCRS=HRPA#5>EoFFT4jXW!+K zk>75J^}MmMgOj#S|Idw)dLlf~_ji1fHI161cjZ6w9ngf>v*1<`96)y6<(?iVfGjmy zS+1D0)~9W~cTcDR-Uc)MNH=!$D;y^H30tMbv3ZBvVSTIWa1|xcd-`5mf#uUz5h#y4 zsY_zDc{hEEhGuC%$O+4>2=IRc?~wSAYPup-!P1mH558;)7_=m55XnfVyY&2Jt51Z; zp0@7))-NOgRs7vbg;?q3Ap3Q$`0L9E@0_!yQ9j7f(PD3JXuXpQ-=){isPQ!jMdWP8 zh*}+7nJ>a-1|{SQgKmn|s-`>*=H@6I1Ec+S&vU9{h5AGC`;{TsNoVgp#dhr;n%<8* zc6%Jj-8tqf`|D@!>*pGrH`ee?eA@qBHP)1HFYp9Wh0i7uQ@t?LkM}DRYJQJ$9mW}9 z&R9jpCY8%pvl#LO)ZkgnnWvB5xWqbjXe802KJeYUj?pK&eu)oRLO`y0K%%ckAqU>^ zKJZ7{Lw9&rJub9=_7f5Q?@n&-mtn_VbObviSF0JW!mdO0vP% zZ@%2ig;M-{pVY{J(EX_j_y%2Ti157HQX4veSkN&85KAK}gC z2TnxDGiLsI9=4m$WQ%*~>f*wogKaREE)``~ZG%~gc}<>zte(J-5Y+?_^D^OGfy8^m zi#}g`U8Q>rd&4~%WJk`_C1y)MlHMG>nWW-C(pQNxIWf7LtXYbQzC=XJ04})jgLy2fbJM%w%{+Zu$@7 z%3&oelc3w1QUKiId)1le-KM9ZxpF;^#$kj(Ls7x;CtHMHqoOcIkN)`ub zdQV;b*sypX9^oDK;={yA#ivcvarZ^3P}dLeJ@l8_TAfm~(+QxL@}B{(|07<$tYE84 zSJvn>OCvhog!~W4A|9leBrX2Zn~?{WaXk^({U)>2^(xZ8yi!eskMG1rW+{C&@55tc zPQ`W3cONew)8GrP&1F?T3)))h2^y(rq3_Mow14bI^Z3FZ-FET&Y@tF7kYkn`13kaU z<>+fw-)B(KGwH2Do790^Qi# ziIPn*dQz{IfolGuVIq_7KFWsn!!0+V{2s_ZCK z7I^#AmU!@e`hh=(y|OgUhWZXnc_B^V_qd6P9Q%x)hfn#>}`h*gRA2RLY}b_%qJlV9nV z!K$;ei6SlZsuIC-V!YPNFschFXu932({_bLNRH3Cx>Quz+^(lf((q@$#osCm;wA7QS>RBV8 zk8`O$LS?Nf%FH;8E>I_{VikabGR(m)>TW z_>8q3gIr1haYAt;7GqTSgj)j{hY7uYa~ zmeBdo<@Zz1MbjjEqE<}h#2sUA`O4dEALVPkx{=5Uhu?D*2o!(h^*-N_?IeSBq0?@e z2Pw091CTRV2d1i7u-@EAr$!5#afF%dC$yVsx11V!IJ$bJbLyICnnuszQWv9r1&o;h z-U3veOL%}vSAzO@92xA-JRO2bUR*A1ZjQhm(>T~i(t~2#;K5ZLNh3G1hyd|V)0ShwD^)LKUnkF?zaFev0kvx-_$@WBN4Fh+lHvTTv``+8MTg`Nk)%NkFNv#9p z))S@h4mm!Zg`Q2PP0Pm2Q;i2|&i66f)jkfX;kyXePGMqap8|lCPttLBC3>JkCX`8f zSNKln`b#Av8T@HxP$4!bPcz4K(17iq8?--)bc6?x!jk`>CxF0eErv9F9*pKW965k0|NM7BNNAZ zKer4Hzv*z@d45UlJAV3cSf(VAv{}1VPEO96p#y)#Y(@==5KLTmo5~+{q|J_{vr|(F z7h1a9dX$Q$JZ*;roL@)Gt}O$RFY;Mj73F1k=c(~+xlD?rNh(h~Fc&-`$rp|-(3uy8n>SGM;mVNEwLC(%`5A>>-?;(DR-Ic31W^?rm zl7`Iu_yiyB86Kb*aHAl3W-I8G%M8Fd}Sk!ampMk;$|q=kl) zaY7}Ly=7|{_ny!m_NZ`(15=ultxSr8Yid*DZs$b&Crb zTlNn7UN26IlfgCHXyqCD)wA?9$H$|D%1R9SAEXJ$I!?6ZNJ>H8rF0b z%R=yNyu;zRf^e3rgy0$HE|u}xfXBYM%Y%CU90a)b>;bsG6+_@Ecfs*uXuwmC)jP|E zpxtWl>5bEn2eRItYMC0RT%h>yh%L9TT$8ioGf^cCi>C2&8;eVu@?8D806tqmaaYPS zt{w-X5&HbX(QVh5$-bV?RYZkUx=z`e<%w0B1~xp4^jzk%(N3i)lugcBu+~ykDRj)x z)II20+1#m;OP@sjhwd`u7e;faJIn*N&eT1gO^Tl|Y8ifjUNT$~6Z`~iO`cdYOA+6*jVRv7NSH1n83J1%r%Y2jLogG_p z7?`7MEzikiLjHr%&?2_zHcVLPi(kCV*fKo*mC-|P6QRsCP+V38cDKvAzQ1eL_u(NJ zgRjo~FXSZ}1R*cIPu^}L!EIkpO-$@+yeQ^>9=DG&+t6v`7fHTAFP2#-Y>rw>YIvP6 z)Sva5$cvD3N8s#LCHua+0&R(Zx#LH&76${}^Eeit?+s0kpYOWr!WQ`T^LE87&1|>T zdK#Q;i{RhLujP3fER=hN50b+dUQON*yftXE-~Y+_>rGlBq>mFCWW|#eeraY3238jC zsa$QCIl|)b5hMIa+2T9x-I4`_*lL?)N^DcFz}_tLM2y5s?bx@Q!}{t6pMCPJZ0=q^ zx@lmANBUuWMctqp1FY63p6yt@h_&YO^8Us)3i5?C5zR#UmBp_6>e%_Wp&hPp-f6)B z>XqWA!aG2^LFy2I<+0_G^*!(a-;!v5<&qjj_~TWJQA)C^mJ@=8YmX|K+qkknr=^__@7CqcXO43% zL`tjs>2U>&wnz6|;@v+xeRTF|rZI*_VUgeTtt}{%O zY~|ovHsLoj+pZ#AdGX=v{gjovO7V5syz8I5UJ|st9ulUF7=NUewlxYXQsCG=UH5W& zad`1k4$lXjnH`JizJDw?4vE9etydqrRI<&)i7WH9yTFsn^rOqk)5@Z%{y0TmOj>Ea zlk)wB74B?RwM+3b2;B1Sv8u+{^6i}P^XUN*l3v|lkNIfbouIZsK4yi7#0MDlQfSIl zh@p3H<&a!uWCAD;bZ6vuE>=1%9OaWNXqzZCY|0N&UQ1t`h*wXq%uOD!{^rp4Eec4t zxqnFs05k`l?+EBR3_H*++U4&{rPt~mt4zwJOgmh+x=3}nS$+T*QPXFve}%K%i*Cs` zKBgo4R***fiIU&)4eJ&dzF#R%niq1UOZP|CtT8Mjz&)Cgd%Q+ce`=Smpl$Dc$K>7aV;1u7B9*RB8+uPDvzaiBUe&(ffP z%BWAD-`sn_aU=K6`!_bp#j-5~1`M4vLMl!!a)+f^z<{G;dfWJ#t4p;6mIkb0^!R41QddKzS!2c;KK}E{FXs&44l`S@qd2U(5;c| zStDW*w4CkFxDw~fk{{U)zxEVQ^%E=1^qie#X5y0|Utlh5ysUm1?OmxJl{t0BeWBtq z116H~2@-3s8Z>3kukS~7#w zOZSWJCf)$JXYMc?r+oAOD7ewqIG$qXJ2z(L$6$Eu=XUukLnppHzqiQcYx#lTF~j1X zww4~Hy80`NvmJA*O`X5sW#i$gbX|tDQ9<6|c!-chC zY|O}-jr6X~kF04YvqHxIi8tBt$nunfE?d0hjOg4odBf<;d(2D|H6ja^5J zhqvEN@CVC(_=6gTiEa5@Y>rJi17hvVob+KzUdi)TkJ+R5&kKF<-YzmrwI(e59Z&gF zdPs8WqjfP|>z(&=fEWC6#B`qUR*M%L90 zL9E3eB8v+{W(cvDmfNiF9~(#v@z`4`Q2NLd8Tjz2^YOBc=d#rB%#N9+ZQj%l_r-4{ z^$qj=W!~1zy9VmQp(BffWYOD!JTmUIk_m^t6R|-&br^8qG=17z^RJ)dk_~e0Uppw) zzS8N*kk4_h8WTGMLd5)GLPXe;sK(MfyYZ=);G5MjKbM2y$9C&Ryoo`cbz|)&p>P3%LF%!a5q1lEr-yGTMmkZ5d?p6IH#4Vpn5%h*=&(%W}`q;>l0 zIfZ(y{sMJnuP*6$@rt#*zuYn1lJo78D1Z5>nu{HtQf*)c>w!Ta45h~Ivp3Y(SVaDj zGn(X?LQwrDsn_jb?^;-(2?~hbGYjG|^MUi7x4$o74GVN33vB(!vLzDY9@S=q2JG^) zExQbrb2*oQkmgRy0+dFg5X)U)mDKgZqF z_GPW~%zi8^sdT{wx~Z_1P&lHS9uM4-@Aj7gU}qiF5b5GWIj=Np)3w?E4lSsQm3YrMKBJiz!n(Zd|RuTDj8InEQu@6{SgZ601M5KD}GXCEd?vY^j0WqBU>$AbdmY&2}2{Q7bLr44S#+h-Aiml8h2FmaSzw zBl@8^bFGK*#(-=j*P{xP0a_nG4C*?!ZIiyk(WBw%x4O3zoSOD-@bBxO99qe)&27Mv zC%M3!A0I+5Saz@w+s6>5=hP&{yHt)`KB)w=A|0EN*=& zAFHwGXps%@d%?>#-dW*a+1*#8)uLG=^@N?xuYPvU$1L9s|CZ_P88vZXBbkv*>hX=! zF?Fx-N$t%78(?;Ydr;AHKyBTHs6U$Y93!1V+WJ;y2rn;8G6 zf5REeHMSgDUM$l0MM}(rJKa=ZrHl#`oknLxff0%23th&R8V4~Ws1muB0YR1JL2_rk z)-<~eKlV})Q1y1duOf9XW6jkKPfAUh1`AA=jXZqWrZhh|)H>u)XILK0*p2*SITuz# zhd8S$v#~w(o1&+{3Ynw+P+Vg%7hQQ?L!)BA(2YipHP!%nxV6hDlhwBiiI3a4Ylg%> zN*!ir>ooo168|jT(r709c*k&11k9yi7%`Rp`+6@6*!+boR4^BsZ5X^F2-iF!ISeu5hXhEo>{O4 zHysFX>_gIGvS=|rWQBJ60a*io`roU844y%nLIE6&^wF~b>7Y*sod}D?>MHStRz~c6 zQxuXfa?UfYE;~9f2d;$UE@QbOIM1Gt?K}6R2g2 zHSu8!BNnByENiJ%@X}7Ub5m--hWliT4wt5w%#A$OYFq&)(U;Zrw=)srf#|&iSofe0 zA;mXU?evO$j<;;Ci^01{>-eYiTfcQT--2%0*tL=be7e#m>6A5r8%lu@YEIS|bamh zb>NbXljjU-s9O!z=)$ntWFsZNQ;OI<=1S}g9lr^3RgqZOkFVx+dBDaNcrAZPqSh%C zNlwWJ4)@){Qv-({elT?wq{;Xw;uz&KK-o=LS_#u($6-LJ-#J!U8-&)_*hJlzO(CAP zo#{w`pd}a1BOOjP^VHlFnR^%R7l<&0afYoqFvSjF3bg{iX;+m*%@)leXwY{%qRe(p zulC+~md$Lk9#=WoV|bZ&@NpjFq~-E&^EFVde9nWY2uEG-QUD`PRJ^-1OM+V{L0$kO z5B#lpb6-4wXB2j9D)#~7@FT-^TFn{(tq{!*;B*1t^b8UIl{G%+aEJvMw7z3ufF}9o z14iYV&jL0R+j`!jc4uwCkE;#sX8v>ru9>e{- zgS!AK{x~-(IksTG1}EeG&6*AYb*D{lC5Kps{qpBHC3Y2u7xj{FY+jU~6sd))siY$Y zi2CfO60BvI@paoxa6Lu1p8Th`cXy4RN4PBYjw9DXO~-7ZovE`2|K+Zk%(RSe1*La( zem+YH$1`OnG4nh6Dtk6)Rh%;%t0Ui2{KU45Eoz7K=`f_&>+9*P9mfR%MpW+?84a@4 zDZmL>2d9Jox_(Y4a^pdVUV9q5};O6Jk66sCb)63xYrD70aFMA}6gq zx!+8xKnH4APik*Gh=XfjMI8ZcK^d+YgZLWXx{d`~W_;jcyl&aIF0%IG{NvE1$g)e@ zeR@(#LYo`Q=((YAhYbwlB_Cg;BVor;BqpW7G1o&* zQlFJB!_2=`pR=P@S}g3M5)4HCRvUTO#aJ92X<*DdwQNFSKvdlhHzy|e?UDwaVbzB; zD$Nm;CrA0hrPeJ|3Ryj!*^F$GTWXr|5JkmC;te z#i%cFewcT@Dv<$U2+<)0pW8tZ6yP@5XNOBCO`w%m!d!OJkN)?z74A0jV3m&O*(K9M znOoB|ecNO3E$rCo_wtz+Uo5uQPaX)I<>YxSIrYldsr15oip#LjOND#e*+m48!0mZy zC1Vad;`r(kDTvivGd(7)V==?5eI+?XaDs6uTnnvl^jrfTV&2#9UMLJ4Im3)EOn7x` zTSE6a=A0OwUmpYDIc!xq+`-x)vCSx?n%Uu4iQt;_QB+HIxA zZJ{G)BYC%DEn%@)uw%19L73HH4PB50x0An$fnAubK#PGRJ%J?{Qz~KSqS(jl_(VsS+fcRSCX>!u_;92s>w-TMapOm6k^6g>T5nD$Yv>f%2hW zwdmrigk?(XbAjb5k3wFf4Uo#L^4S*89C|M-L zWs;ZuST+n1ApiN3x_d zIV|jbe2aoz91V2e?O+#~1u-h4Lc;>G-vhEYUMmQ0DSjV&flIdP02!%sfqD$C*WUSC zt4SGgaqV%A`(rZR@y!Eg1pxhn&0Ohc=e?arp3S2ddL97k1N*&>Jd>Uq6YR#!4O4~+ z$dYfqH3?UE>tnOAtHDQsn%86q2`WlG18v37l`R7l$gOZsl?Q7A^2ZBM*6d!tA@|l- zL{mAk&*}Dg-fh1!d6-X^TX&h#1StzM-#py@XQjCKg_AYXU?Qz$7a4f-J$Wo-0wK9$ zdmyZ8q&_462`P0+Ct^yBt|*+FT307Sh!kn>eXO(iN!|Nkgs%1%3t2Mkt_Zt}!tP$J z>71SdEf`xBr}oW7l9z_>omUTVw07)A%`UhR58SAHsqO{{-=Dg=(_%h$aWo1uSGlQ;Kh%6Y z;MC)J6$<%rPNc%QoNWn~Fes3}{221BI4`@%%RWTUoB_MJAOxToKOI_Y;qb!Y$g>-! zBZjmPH@wn0W%y_ln9}Zdv0IRh-(^LeEX{kjo^x~1vF{bdpkz2*mXyqD{xyBIWqS!ZbaA=jTw$W0bO`KENF*5W$E$0zfFxkE#&T5q49E1Uky)sIDbcQs1jgnU5I>5A(Pc6p);AL9@nS$(x9560N+wJ7Orq@5m9_bu8v9*d|yjV+Hxu(O1Csm;*Pd>kn@eJc@lP%U{eFGg$@g!KY2RU zCm0b5Y@`m_eaik>P?-UGP5MsKDLn_YkHU3$0VqOH+IkcNxUI86SHxh)b;Lc$(cEK{1f z0eZxbh6VOW+`5ka+Er}2ju1ou|BqN&KJ~aU^7V_tNo##0@!`D5<}V-HSJKZH@7Auc z1!D%P%K58tHKIQq<_=QQSXdhkfg+bxi;-nx=O9!%;G`2cCEX!3pJD-FrWiqaT3V}6 zL|79D9mWyBk1KAh@&|A+XTePLAa9*b&Z4a2gecRv=-*mXqVw<9yC!WBKUWOkFaZ8| zN6}ei)|Tl<7-{?AWWD_CO#b{^o2_dzC&>U>4W#{gPqt~tUUfv|RL5ek!D)vVH0=Z0 z+K6SNmWT28X{G1{mdCwdC@+51bA2a%E-6a+2Xbil{T&h;99}FAXGvCw&FzX0kmKoE z9G|oSlv4Eoesb-CZRHtX!OW^A^@cl1a&5c0YBTopnQ>M|I{LXX_yb6w479P+!o+RY zJ>ufxGeA~43OSYsBjOQ7ER_`{|I>~%>ACKlLtG11`YK4X?Fx5^mrGF?31eC7pKeF8 zy(K0teovBJgm4RxXiSS4{ei?x;-L`uIv>713`5!uoO;7hYxu55h5pAoMwzdR4oxLredSXBK@qUud;z!P}_qzqNYlwxP zelU_5?lw12xP8t_ce>^g4w;I_FviFAqvRtzVPU8v@N~r4ihN@4KRfgpzFdvo|U!=<9G$fH^ z?m}~Hg|@6Z%GPl~3k;|U2K@;wjrPdX4tFd`7Qi9vX>%jLVyJLgQ69s~0h(9eLDWp$ zum1+NHq7Bf&DtN#G(e0x9~Ks76)g|Fz?SAPk)W5nFfRQ0!2x@MtvL$HT9JlZH$W-q zZs}i-m~liS63-lkS-S7O%vCf@@o>w&Ml`*{shZWl?mGBKoidCYRE>fr-|IlGMWo(q zzhcH?E#o4=aS1cX$U1-{C(RG#zVF#7;QSzy`uIW$?$oNOZDS45&CVcBcm7IJ{wtuL z@ZBIxGtoVnO!{nG{VCqx#XQ2PVmqn#%CDywUk7K!3c=Vp1ejSWWDEE!ah?+C@5C%# zEMNYutdNNMoj@Io!53Zhg3Z9kZfINlHn^9%*cT7q?UELWShydrv|;}C5qz?RkB^yq zPx!7(;zAtBcGIuG$6K(Pi&da^*X$^Lq;_GxoT@$_*uKest_`2Hx~n>^^fw>IBUl>) z-#Hgv?m-6sFG zmD{!W$vOx5Sp6!=mIvja9jyI?$PAc=Bj5XMCbUd$SEW*Zt&`tEi`-myEZ^7UwYAAJ z)2DIW9Y3UU5pnxQaq)A_Gdzr57{<$lIhBnZyDNHt<=>V&fFK;oA+KGuRyXw%j?*1? zD<-}!`xQ@;;t45G^D8A#!FT@~ybhAf_*0MWj8DiIkW+~q@N&h4`~OOavoE|h-RVnv zYe7|taqI0VS(51uEPT(L?Rkl z$WJ^w40EhIzFaI=TiI>35K+19#l;Jy^DRbsQK1>&(e?Y$Q%p}U7e*xpzdf_<;m5b$V zhFNJO+jq0SisYo_O7JgPb84H`!4#e04yT3JB!?+$i^DA=yk;BjTwb4(X6|G}yM%TV zPPj>_9&!_aLM4pCuhX0=n;RKb2n!sbkaf%ECc^g^CaKeAJBdQWzv_zo>p}X22yf^> z2po-9*;*NR`|(=dBjcM2iLZ-L@Vq4)jO|=N%g?!&-_xIMRnhnk-$;*mJualyO9x10p)^L95A!X zz1Yem7>LsT2*FWojvRPduHSRang`z%sKdj5`R-%YPQ~px8#G~R$W+<9 zg2N@cq2&vl>}%9-+G5((v3Bk1eplJ_SZ>!r4bG9jvFZQnUMo&!^OjlA8281X z(bHk7FEB(7d;e6ps1a>y;#V58;zTk$V@gX21Td3L-CLa9apAkr|BhoxMmx|infEOB z5@4FF++4@JL2j4vbwXt{FRck>3;2e$1=;KBeN5Zy1!>A{Ic)WDkwD-Y`mZd0N&uSh zWU>ruW0)V3qQ{ioA80Z&lopDJuXBGzb;izw=!PT<1#dEF+-k)@=Nvae+)V3nkyJi^ zVnkUcarDct9D-O3)u)4pR3Ko3=;||J)rjXD?;Rsz!SCOBT!hHypZ5EYnaEVAr?J4# z4qeg$AOrWZ9Cw!}(9RO39&;YJaI0VCNHh%2hbakHav8=uXrqld*?TAm?hR6V_Q8n& zgI&P&3j%F=h!Ekyf>d|YuaN4!Sf>a1+jnMk1l_POghFBA2$Y56g47g?l%m>mj)x4L z{*aV>6`bwv(d5^*;2>uI$@(k=<+Jvc$UqD}_$j3#0Fgm~=GaQ6rYX|}bXXrKOfVJd zh}~Hv+qs!vBnbZg$~Ic2?cKxC~3sic2BEZTQFw?S89 zvMmYUM9zYMo;N70mim7{VKI)dD8=MgN*N^Wmxp%)_J+c683e5xl2}V;p)75r5sx*| zAw;~`u%u7*5kFhau+jp=@c6IHt|p9dqSgo$eo*hE&|6`oh&ztOhqPa*Yla)%S=n%_ z&j35pkW|*AFH*!e`};pTvPcnBGcp`~B?v)gTTY!}`~5#{VMek$H_#UMeimX3enkx4P$T}!3UOdLn6mMAnG|S48PJ9&K^s=8 zu!!F8SE8qj3%kQxCjp+r2Y_xNj#}RhoEpnQY4oos&96cVePNhUYF2xV8O>o3pr?G`x zg14oz?P;S;IN43`svV^BUTX6gFZqeguK2l$cd}x0-NWrd^B?L5KkFnb=?a|Xmz-fv zZ3g@xF;)0ng_hlde12FX^w`bi4NIIknH#H^ZAVj?@$~FAO(!?3-{*(5XCOSQ#i-y^7)0dK4mHtix0J__H5M@pQ%e z3=g^R840>rk>Cj6c!@2!oDw=7j?Sa&r8nL0u1hHnUCrRz?)n@oXd!X&hQ=E(UJdr4 zf~Rosy=d!~44uHQsd3g}10`MOHsa5lYAkl8bO4+>Zy<1jtz`TpuLbtp<+K%edH-Z= z@;~=Lf6=$1uR3NTR34js%2+oyn%eCnTVu>1m90?-8-{ zBuJ4rP~}Pe*c5~%K^;t`IjvAK%SwXJYdB+9Qu%sLh=Fc(tpl70i=T_0zugg6DD<)> za{bFA$6?2hUIa%A0$62$Qk}H-zTT{eae_4#_X*s!l!C150$vqxcUsD(Y>_^R_w#C~7@ z(vGO4i|hKFpSQ=p58^^1kgBBOT+=U%JA{t6mV2hXf9x&MJu%VfaPG3gDq%%upno2I znXR~0i&Mqqw_LpGS-^b3I=Kv(m+%0<2NqxLg}m!DdX2K&_{)m^FYkK_6& zI-;T=Sz5uCF`y|bkXUqc-)U%iOf+C71DFhhY=V68=MwpTViBO$s!9?-3kO_gJ>0UX zW{B==Hlq0j#^N*6l;o|m(V)nIAmS$e(%Jf2SnHz+QMhFud*R<3#P_ zbtseq^#-DN=0t4$?6|*Eky%8FIBeUzh}G2PF*l-p*3#ZrHcHBhyjl=EQoH!>1%!DK z;kH_oit~sdns!JQ`GdB4Hwg2PZKzZekJ91F;CK~@$`i*kEtL7pO8tPY_iy0@Gi;go zIp3|7BmMvtq48=|GLaNs|I?J6J=uoJttcd7nl7`d%*w%%$y^5{MB#s1yeT8YSIiMTF5Z&NQSYU-L z;2>ZDMuBCY+P-+~k!om>80Rz6PUFqz7UA#nK-&8ipY4g-nV=ImF`72`5+u&+T}8fY zps;J`IAu|+z_(z1om1&UXP!Jwo(o2}PK^q?JidjyMw?)GsC9s?0rsW3``Kf0Q+zV< zaO5c9D45RWkI;A}1Uo^a*%K#AZR`DOO$tQ@La=q2#NAh#4#1308er%Jm`Ins!9IXn z9vW{q>PMayz^^=|tv<)ZukJgh{5ioB$01PhWG39gUsVh%bBw0AQ@a~856`Z&daD$B z0Z}U{A|Ym)%0km5WBTu!CS#cw&^8qZ##-^Fk8XcNC;HTq>Kq+JPv`BKLAs@v zDSgB!7MS6>IAvBK1iPv$O!7o*@)amHTMkC@ERNELyM#O~b-wCn zKN}62`ztPh?iCxP=yZ_(#)!lMlLQzJdo{PajQsYE?-W!c=#ZkP-D?y-_C zZ9n4ZLG3nhd?ptd)hvgd`NxNg)aW#ytmCauhB~sAc#z8=jbEzyQ_^QIZrFp`a>aRz-RizNmCr$5I1U;6 zEMzL`VGuV2gzi}-d)>E)@Dzz;Ovj$*=6!WXKPPzMg7?{%VqTVgd%GO|&V2y>4zGtZ zp&JD}oX?Pdr{pt4FB#UFq^At{OTBG$Fy)7bfs|UxtOdKULVshYfK@_jp2}Yf>`j?~ zREL(}%AOZO{Moi3F!e#&uuP%k+fYF8>;wo}HLsFb(ABaxoUMMam_X3Qi|Bzn7Z3;o~|+`Q_1^`j<$Ug zY_%Z#D|bRx?W^xC1b0kQq%y2nbC7^Ybo14VMX@S zxcvo(zia%U{V-V-M6w=YsDf2P^ZoC^T&W#_Wi2+02YW z*nec*ravM71+f1MY&M96QuQDvO3nbtL*3N)$^Wy&>B(JyD}H|fnx3=k`MVtgZHVE5 z#Be|-oT7yOXTwXAhkoz*K*{=-fzw06J&zz!DWT~RXZsJR56GFE76jLy^?rTQRojx@Q73}|@9?g)cJ-gA zT}SpJKR-X|SZqqvlVQw!|HIpR{J@8Y_aQZBf|vW4TV5hg){^hxZ%r+$v;Vxp`M91b z@4J!3&=h&1`z)hc?QvE z*w3zT+uzb`H3#(B1Zj_Sw6)Wb!$+0knGdxrSxEMoH5`uq>E20Ex!}FwQs1A{19=a) zrI-;XYtWCU)Vx{~kqD5|kE~B3>x{>Nw{c{h1zS{j44V}35CKe{-~kodc_4wU-TqV) zDn)=e`3`llC&*&vM(*(&2)#S<-*yH!MK%EYZMfBqa9tO%T^b#vnE+BKw>>`vYMhmp zb-Fw-|LrHLHN1_1T<98_H}MTHG`x04<_0B!Jpa;o)hE+3k2v`j{XlkHuT_0!*f$n{ zP>N6k+r;)f%>!h>m@@Npr7dpwE;`g2O_|VQ4vqt2Ig3g9d z4}T@Ozm7r_mAumyj229_wVK4CGCs0b`8?4W{qS zKz#r+38IknhANq8$Pc<2W>HXAy_A7)5Ax!xDhPdeWbYDf@GBa^{xBc>Ty+>i9{O~A zJcgo1Y-~flOo@5cuA&ZBN?%tOJkY*8#1-_vuAxqBZ2ip_!;&*d98bxPRokt2A;+gH zNbNv^D9sN2D7GL(+-Bvf>HrU*OpjCAQCT1{KWs@yfg`>PAZwUKMukB^E+~;{Ej)`D z;Gx%4b30UCalQ!qPRIgB(ZI_}*5Nf7H=RY(62aAj9u`cNR!UzA1&fi)tCVcHb1(gDe#KvZHU|o(4QiEIoyAn8HkLurqP&Y1*1Tlg%CAr#kt_`|7(2cmJf}8X76}#Y5A?DmXRhk9bXMkf zW5W(~&F?=rUJD|XA`ApT0DW_jy8Jlh2`cE%dIDA_Jige$Nl5v-z$Dv1Z2X9d(04Fy zdgTDTTi|5p zMDul};qf7Bzqc;Y$4!}j#KsS(2Vo_R;B93en%&O^@c(SHKa`9$2m#RVv9X9R2N@?h z;PJCX{Xg4eO&dIS29J9mKr~_^S2mO5U7a-#&mz zORC)zp8(f^sgo%_Yf*2l$qTn$@+Soytl3PN-*8#+sOV=HI7!ajoCm3^Ll@8pr$L^0 z0klAVXCAQ;)rS3x+5MR@V1qn^Qh;RON+C-L;m=l9_%oX$3rF!pza&6FW*-p5cFCD= zTo$^8$^b`)8xhpM{X@r+0|xm9<~B*6LSiGT@%a~%l*fQ6aBsnAv!lW*g@(X45)fG% zx~Ss?kICV(9->0S`1+F51+OT8qqt+a;5n!Qtv*RHN54`aT*(j$BL4TeNsbge1pmn63`gS4R5NR!)4t>2U>djQmq?PT++vd*a+3TDC%88*J(ECyGG>w zkR+Jms z8Pj&96bVx^6Nk7vNjmYM1=Jl*P^8cgGL4vOOSwh0m3cbjQB$a@rAJ9oPJ>W=&TW=+H*1w$J|PA0Jt)oO*M@VnpVA32$* zOv*uGTeZ!x<*}pvJ06kqbd0is(TN}&Sf(}4Y~|PVCz3NrwZrq^2d^IKSopU+sIkQ3 z-N#MQ4@5)U;ZIGD$ibD!Udttmt`2yhTDWUSNJ5|1ux|vOqU=2Gf7F)v+keumf!``I zfRNt*DHY2TCvjPq(NCWNie6X0bv--(Y5Gw7=tt;s?05`fVoNf+5$|Wrry%e#d zr{|~X7?q)$t;UqwTS!piaPT5^EG-}qRoU<6M#RZQY7QyD>;LB;u#`+jDdMvExUt@_ zl-peCaEe}+MCyRzBNV3O)&=(nMr1HwPAeh^n0i;Z*Y#a*_FBoJ849XqdHEE~^mur1 ze5F)HdW*=$T*iD_0J>4PTLQU{gWhu43u7~&Q}ku`kI$lOwJs=AS#qq}e^w_h#MQ)( zM)Z>#a511enN|Kpg(xPR!U!E`N0*@Lls;pIexu!BP#k-#QUz9)-pWm*~ne)wD>whv9qxy11EwWEi3Y5tJ=u zwJI}|hymy!t=)bIyuidCR!xpH^Ef&0h`y*QJfn$E0JF-1m9R36pr^|{2Kq-=?8dyH z`SZ)5sB-2OX5NQ3+=Hr{8g#)L=|}Q>5FTtK2B3$Co~pszQOG`QhUS7O%sg?x3tj6D zZi7gNZAnsb$_?{LjM=7Yh44dfE6T*(gM(9Cr<;AFeWFMzR_~`Y^dYI z=t`u)0N83SQF4#HSTAcn1lilK@#>5*rf9$mU5gB+eGeqsi(LRpOS_3!R2~7LYWIRO zXUxzQr4LdCL7#w&Z9>18KZFr$W8pA@aESnWid>Z_qa{6jCzA=dukM4up2W{DvjMOhakEP}6um<0- zxaK_AQ`VJ6+K{Ue?a(|i{{ro zhkr0c)Chi2_XFhHj7!(T*TR$y4{vgATt~B3+b%Zv)efR*M>*{Ug5~ zp0j}yv+J*ac+KF3cShUNzp5s{AvyY&lHB^UY&pRdz=XD0%X zKsWU?5pNwz)9>sD-tw@g(k9VkX5ezNs*O#vK;#=viEt|k(^%UBxXFA0B53r~R}ir@Y7!FPY^ zdpe^qc}AgMYkVFRS(>LMkYZ>^3wZkJFfZ$lXMe!`?yp~Hz63R>1eUBQS<(*yIi`k$ z%+mX)To85`A8r=>RRTDZzvYstiuu_8>(2xLDWq@rxLbR8o|Eu_zORkBd}BgBusk}G zg}sFr>mYt$EgF9dL0lrJ{aJKMPXz{JrOyz|jjw&8)NL5vkq*Wp?KgIU%U_71f|q}P z{|6wMrNq{7%gjpX$`}|#r`v)Uu-;i7m+BJUURlazLG86da%8Lt&H_C}P|*X=JVV%b zzn!J6Ep%;{nfTMs`hR&xoM}O2d$IO|Ky4gdMUV#U&W};&a z9!k#Y&IW9{fwdcw7kaWtN zHAIg%J(@8^KkEe=M6j0BT;uE8wU~K|HFMNmk=BTA&&rUH=cQ!MI~>*Xc%3FxW>Qn1 zM9M<9md`=7S>`+msHzcN9Lhkxcta5mh{+C}kRLP_=m=g`2A{$B8uGVcbeel$#Kpj5 z;u!D2BtyI|P%P%%0&S|nObI~JEc(TZ6bcvxwh<){8FVW+4lY+m%LA~W zYKQA88_j7QFf!(U6&*j~&(zRTQ+Ik%I7Wnkq@^=C$7SSj^CIX+_E%7R21OrN8(x1z zTC@Uke3IdQzxy*%#DG6V$XqBvC&5x?OA?e1BnMW5sTz--prfX=pK>p=^W6tJkz;A3 z8{{eOBOm+*Rw)5^<_ktzsKqX%2?iP4kOu<54Cri3PfHSj$E zBef!ui^f0Y9ej7}f*Ovy#IZll@q@vOw7do)0xlyw?Nzs2R!(;#kZ0}BR6Jq60h-KD zr70PRVb1MHFqm#xa>Fp^T9dq96S3tRhv3|SKSS{gWw++PXLhVsXuU@^wVARBENf9 z*?fZ^lJGz3Dt=lhAH>u%kBh%q0eC(AvRvj9at75>fe&?;bcC{+m2w&Acgd`T+Wd~~ z(0Nxewu5H{G+Ln^<1WN9VGPEb8^I5Zgipd)v&L}xvD_b3BLmA;FV)Yi$zG>QW;A#b zZv->WRY?~8Bt`@eeyQ5W?3mb_AyQ9*N7R>$8l5?b1!fa40s1_vrfQ`%w=%wL79*E!l z8_0+$dJP0@EXsj$2zb_R&l#~IBpV&k_Uxw$ouAhGBSS~s*TxY1D|p(_A!Utmm{dyv z%Vu|eh)S3nq7bzw_8V#lc?8A-t8tP`<{G9A72JFXxLIBgSI)q1{!<4p=fwv=|0Nf+ zb}C!q!n^jM(h3rpmT_MS=FnOP&~XE!(@CA49-4vfXbmg!tXC9Ep2Y%_)o*}14X!bY}pm^4&+ z_keMxEO*8@Ec4!PSZqTP6rs%eAm)Y@8J+SPbfjmKM3FfOFX3V8{PC0B|FJ%QNT`PW z7LrB5e&1Ki|IKPJTmw|j-x-g8Lk$hD-sm$D!9?^&O6gxa@}p9eu{ zI#ZF|7W}*8!-nZst$w%Larz!Tj$ufsI_e>W%&Hpzv%$>2Z95D*<5XOI+VF=2@u*)a zpsS00m8(O}Kgl7XEeP>tOZkj2xpd*fSH1VaJU(_2)5|e@Qp6v!0;=napn2eGBUmp+ zn@U18crvv0R|(R7ND7hhh9vb%Taoal@wHMs)6tyWM!EZn8)Jt(`>IY{8?42fCwp96uZ;xPiV6re_7vdk*( z22X~j{)(Ru6#Ko@WcKBBAv8627L7(XIy$o3aJa7f`B2s0vdwlS$ww(0Y4_z1s^8Xy zs2$Y1!z~^_)Xw8IQK;O+e{$|3oN?uUL8<1?oDiVSMF>#4i;c9M7%N6|EN5z`q2PKD zDu*=GkYdvxq;N(#x0J}H5V3h-LG6WT; z%zmK1i3i?^!`S33W-J_SLjuxB@d7Y~i>#_Xfu~N|wX^sKzMd+!EOWRh?6{cjCLCu3 zU|~*(fx0^?jIWP#^hnVOeX@nK^d})bXkDa%zfB)0@v);ueu0h;%~+&K)Ok~};>v`Z zRr`m3sPLD&^Hw6~fP?EvTNXci0{)!G2)qpsR-9nukoY4l%bQo*b$+OG+CxVpOz4RI zX7aJj1?+|TWstmRKw1-a1dgr|6M=&Mk)NnTqJ0MpODj4i>~LumJbMvVb?IGfIW)wD zJ`v|E`RUN}He9)n9SUT-a=T~{<@5j@bjJJhnV;b+m%%~iX!#WAnM?mji!UF5S`vJH z+Dm~XaB(Q5aI?ibP}((1~#t z{rHTSVLIlpwjkJfwl8{up&mN!=}I>RWd;Y*LDIvdo(=DTNcOE&tosR>dW{&HBUfQ= z!z@yUf^F9WMGoB=4=^Gcn>h=AT75O(F}JJWj=3omGH8Phf)F>vk{;=B@>T8s`U5S* z+b+WGt2-|8k&t(B`73V`^ed1ET=37@Mze`IL zfi^_<%3Ky#E>qgKO!4_o=fwf2$6+Q&MRO)M!QB;*UH zY%YLTbeG6`h9t^T;@CsJkIfQ zh`ay>0|dj_&2@O}e_FI`A_V5Hgb%%a8Ug-DM!#X#8YvBRkrQ%{CbOPKrp_rmd|VU#dbD_o>x7v`Sv` zT0A|o_DC3jYkU;iB9hafA_!|e-s7dFb1<|;j5CKYpt**hUnUasvR-bkX8j>PqrOer zCE2h#B-0XysxE&?DtZo%!|AtWz7sULx#lgoU16+FV+$m-7P3nl@T?Vmb9u9l$0+nw zz<`)6^$}ZPM|yPH*eY?%=c>0hP%UEzawvDBVi=HsRajUP4^H^~GKa7(B=!zzBcs++ z0Q*povA(8M2n7#Z!&U&ey^dJZgbs>~GgkxDqD%#BXlrSL9%gqj`{0Gx?$TyrUB4K%;gq9F&0pJK48<;7>=Qm z<0}vBlK4Gi+YOO^Ek@Pl!K9)GV4>STGutSRflmJhZBuuf_0W8qDz%TFf7D0N$>@TE z0{yPoxrgwz8L&eBX3h+_;vf9kHONORq3?$E5f}7cr%LJb^GAREB-g5`;GiJhpdcv1(QG$+k`fUm# zFj)tv2MvOUvDE@eywWix(HIe-aBMnU)=ayCFOLs!!=UetHqx$?Plx%yW#TQ$CE`VW znE5`ws{k0g&+j6{R3qG`3XL$U`uYBFO@PB*K_UPSMhAo=)co3>Yz-U!dToRrdP*CH z_b0);@h_Uv6Qx@w4AzO&5RK4D)lo^;FB3 zROLK*Ewz$1shNJ-0Aln=QJ!%D_;Lmdp9D0OR$RqC0+?BAYl}{>=R~OPF*1fs(X=i})=g@ZFLkrk2q!rZz{N$*AkOc^~+7$s-#d{>)o+O)f zgg6;b+VXXjSvLaDy}j$&at90>^M&-VyAb1%1&~FBVH03iN9~GNM1+i}p$G^2ogd0` zm?}z4RJf)N^RclN-FwfnIn$Lxpn8{O27su#AjX*rT#x0aUu=Q)M+3Su#zsr@i34=` z=B^z!OQ>lXalf4Zti{>rOa7$%*N)AB78QG9v1THA!_9wcc|qM>HaB=1Ua!;RZ-Aj7 zwwW^pC{6_0af3%*0hg$4zChC~a6lv`zJb?bZ5O<_Q0Xv*Jm`}u*DB!XTX_t06up$T z(^zZaM_iK}%Y0tYQ5@y&($D|cyIydP@Q zAn=6m=Q%1!3sx0xsBGtGu`k}!;>sBfnIR`inh#kHSTOYxCvN zxLhuWr*g|<6e=N)tK3T`_l0{JITm!;99@eE!2gZ@`KLl`rUT?!abr6-mL6}om!ekp ziU}%+S=_k~{oU@n=wsI(R$_5%ec>iK_KoZCHGWIp&Xgx_0`z#%k3re8w4Z~=p9Ntb zXju>hE@yHZo#Ob6J|}j<#^b-f3v_lEyF$XAcWD@x;f$$Qx2pN>LN`eQz5&#@fVeyM z=L91Tj*dnrIXDxW&_Rd|FXIJmpn%rb{PL}mc4{z9&kr;qXEt+XeEC0H zi3spKMbM{fZzf^iMr?gLlfilJrB1Az0J^xGORrqQY$!|*y!2ZR0I{Q=fFxT1%WJXH zn*pvQKKKZ~j3KZS>x-kaFQ{KaalFk$=Y7HliXVga0*zC&ol;Q?oXU{ z?jHi#$Aju)9W-~@4eo14jJ~Sng#ucUk4`E9)<_GJIEhRyj!|GF>;2%3=1$Hp)-Prn z;6s}6D+R;X{J?gF%`y!@E3W8H^AX3-tK_ZC<2%A z2~58F#6Mp8FU~fe(k8p_9|J*cx64ceh!ni87c7Bg0+vG+8vw?P0&w~SUkZW4!cQ)R zRr5P)oZZO%J7Tb?wn!`+(}H~`x6TWI1hl`*3kA@xOw@Vl?>*nh-v(45=6`u`neZwA zOTS1eD6oZ3l8Qk24&1U|pdC(aGNRZzk$g40hW~oY&m^pN8R+H)tW*_{k^qXYc7Tgc zqyy5Wo#X$Q)W;nP?C<^MP$dmr`AQYs@b+}B>wHB!_@H|eT!+l#4TQV%yGbf;WLyU; zg6RxS=Ru|anttgR)C6WW0ST5GGSeNcuuQ<#8FFXSY*dNldUUwqY>4j;N`<@vpu?mc z3;cP_j}#_V2LIZkE&+)NIz096VS@oN-5}ft0V0neuXac zJ7cAi7hD@)aG5;4R6?9%gA2?NaKcb_(sW1lO`-O}wg28oX{k@S`qlL9c%BbWAY}P2 z^gEKzJXwSsdtV<|6YdV|$)MXDD(g#jt|+%0AR{LQqrz*;V=tn8)n&-xSpEi6st^OJ zKEaWQKG)UX4Pr%)+y^S5D;z9kPY#(^tCHbf?AZT6$Jxs9<(**5e&pU`l&;BMkk;<_ zoCecLg~yQ;d!7UA%bztw6 zSsZhbU+=<6Xpt8_!~X)?WedUmZnLTeLnT4RIZpv;|C4>Q!wmuLz<|V49{}oCdZ9SHK!Mvji@o`haxx;;?Gn z1?1470v-SdZXFijj*0?L0DOHS$PVB%VHY%1M84LycyxQ4I@}&;4dOz$(VTB3)?!#?D;sNOR8HFp_*7tW@qw>#N;9jUKIAnQRg9VWEmNh_ZTB!@ ze$#W_7ctAq;$nYqVIF$MICtaCJi*q)!{V4~*&xG`o{-Ug#`eC?LiEt-;qAO{s>Nuh zcN3gU|27L_`{Nhv&fN05#AQXVEN0S%G?7YMXP}FBargll%#8HDia>_7&lV$@7TjTd zg4lFfqd#uJ=D5(=>Vz;vx(=b0G*7TOK7vv;({8XZX1{3aj4H6w?*2R{o|)dFn@$UE z2BY@MY4~T2RRl}*xMe&)G7#G&Tg|L27N!%UF=HMUiI3z}l^b!)s`yBUZS8k$T27=x z7P%>6GezXnXNm$)L! z?w+~zb)Eptv@k~lACNbmXXS~n*B9Z5@6Q$wi_P58^m!WL9QOk&k*wlZCo2%rLu9B_ zTtdd@-c-xFRlHyOlSa$}_+JUk*dyewy1xb)Dv6qg%i6OvQT-*I?$6&pU8g8I$&}ld zAK#l&Yp%!0caw^6~Sy&qc{i`1VneznghF$6AIJ~h`evV+MUN^!tV9nM)Y}J?k-EMzE ztG_s|Tng{6tCl4VD8$9*n;Qc(f?e!T<_dL73Lr88h|~|KBD#X+f3lqS9W<3H!f*9g z%rbhMq`*|%^m*FWJgb~8iIr&AX&9~Y66IT5KF0>ddTfuQh*wALmc^Z3rKYN<5mPvg zu`eSg4hYYkx7tj6ru!MlQRzdN`o73KFnmWYA#E$&Z}t;w*;*fhIl=o0ZH**f?Tot= zHPU$c?;^{%Q9mQKEQ8|xdE%xh3sdcefhz2GSpjGc=;vZqskpyrs(O6>R7cqn@_x}& z?fE~-mFG$%c-u9}4()P*x|DGE$SZa_-KY0w@s!4=ZAEN!+ch*EkKlQ1^W%@6>ezS= z#7<(y^y`5kLK8q0Q)3j6k<;DdU0)MEwTKT_c#8b!a663s?0tkxe(>)oBZWVvuMy)u z5W5Q^uVfX}mQn-%BkuJ|$W+PKL^EFf07Bw$WYh4p3{U^7XS%VrM+U$4c6!@k#-O^3 z0V_mNVr^EdyTRNcJpWmXei7aET7@cyK1KbmocF(W^BVz)_AadKn8@sxz0lF3RkSaS ze#sz+keZ<$XQ>!>YkkkZLS2 zyrfc$kVN3CRL{w^<#~zOAG$-Rp!xa;_5ScbWceI88-SlDym|y%bcm)sdE=c-S*G%p z=i>ga-jB>Q_A@FPs(Ma7a~cTyGr)g#x>CB=9ZJVKql7KP~ zK_;bTqh^yp+^oFamGe&hu(5}Q>7VI>y&o6!FqdAtfeB)n}U=kGY?QZ#19c&WET`u#2ctatc8mPVzI zgz?-bp$ac*lXp4p2$;aviJ9t#e@7m0Jx{Kar!#l=tl8T{T`iO z(JM#=tC~%7hH?i|jROi{FQNt}9~(QgrG~X~kxEItRa-khC?bJWh(yp!=v1HuyP)*@ zHslSflyyyp6tg(!rZQ6MK<{#L35w*FLKe@@d!J6L>=cOVzQv ztzV$aE;$_~Hsds4Rtsadt|u~TR=x`cOPgVD#?2e|29orDj-OCCxUwi>xl!IJtZ6*q z;?uci|40yYI+|M7+&u3aoVV+b{`5QJ=#_9h+(9gDVW^ExgFr_hq_5g9wHS~tQ6xJTSdoB5e6Y-fi zSuZI`c=pim=nYbPfz|gK9&+1ejzf>ybEkoOwX>|%-4Nvc81`GIx|VNfMqbBz+BpqH zPGl-$D{P&4trWTW$Bi1Vh0^gNlg18uH5>-&l{r>UeHtX>6cRCt>#2>D4Yf)&$D{SKh)GF)XYF zNY0^**pWwoD-@(AJ77xAIv-d{&%5GWEW|O>)c1H%St=!{5)VxM*SyT@MyHXgF!qRz zPM`%Gl#pC=kB0_5XSOC-5ky*zWrjRMrKHB)+3j4B{@}d(sQ~8(wHs(Ho>ZyGgY*`U zx2gf@hRqCy2D611g8uo4aYMNYlKN5+jPW^Pf%2vsrjdrtyv(~Co-QF(IX^$yOAl3e6qG# zB->=ExYcVE%^bP$?d`Q%x$@Lt41T#}6Z^X2I)c2vQ>D*R3H5N2Ik#CePO7Xir8u<* z@{n}`{_5Yl#0G=Dd3Z%v%}wVj&XbG$Tv+Hz>0`@yF)T8}mWg4G=Iby9zBt|*A<<}F z5M*ubk!^%^|EZAQAQ9doKKnx_V31e1f16Z=SquHD;P`C;LL znV$1XXMO~=c^U9=^i{$hxv8Jb9KqSNOFEZz+-?#sO#j^rL(Zo7*nT^pZzrt};}2GV9CMd)=hMA-(h=_ogP@W*t( zOy7U~r%L$myv?2Q1a?%+UcTKum+oY1p*E!Zh@TBHzbtNw|CYA0bgX+2JmYN72 zI^W~4NFXjh)gn$R^=x^7Z;sab>EdbRQFK*tubOA#Zm~X{YKIDD>1+9;fXD2-L6#-C zcN9I{i?CA`DXx$f>uX!$FTkK^y%S2zAnt@nSM%E)K(Xh(tjy945u|)wQ(%nA+=3-5 zc#u?;mUB}Hwc%{dIaCO$yOB%%=&AoRbC1t~&TND>_V|;+&w+n+CLf95Nv~|@2Q#zO zXmrOrCHF`)Y0$tWS0%MkoLcnd<7MS)8=(lE50zTS;cxo9b1j{}$QcP+P%ginU+6(y zEE|tve)|5^fD4eEpOD*f->gDfc2*qw5S_DLzjhEacUF}9DVj%(a#^UqWD4&g2ISLq zv`l%Iif(Y4rGlmsr=4?C2cItS-d(=mry~o3^1}~>*YAR$H+QB{edr8J=ckd=eVOi4 zud?%Wt93n~A;N<_2;nC#;e4>lrjLK=RLP-#^UQhZ!xN8K&%C43yETWazp6c5_OgYI za_Q-E(wo8r^%x-hkk=&Fr*x59{`#uDUh^sSBdyeh6ayi|{wY1>XiIeen8kIxv05iUVw6ZKazrsVBLZ{2A2wt}NYDlfFa?Mj)~Y21<=Dg=6rbX$nZATn0D5-xc1nSB z`)B#{`Q=|*`d4LL=qjC-v64&R$Rt2{(fh{_n#J0>;Ynet%w+Oeq0E^JqJSIrOnWE(pKIY2u829Vz$YlU&<+Z*96!BWf$2AmCGU>QZpBT zRH0_1shg{fqbqoX5>nmU^k~7mwo>P=jU!Ofizg|mEAl@On7oQ-qS1+dSI0vWXk-ut z>prc`mFPLYNLy$`4F)2BII}}-B&uiEZO@E+p_u_3sws(BW0}R5*O-zZ9;82_5Ld*0 z30orKCErMIicJB$N~drQ+hd`=B)7Dnb7mr+KQxZBr(Oa>t=n15+FHlp^$scJT1x}U z+R|WISKt$X#2Uq#u4QFz@wnC4)Q_lBo@~P=8v{)CqLRMSgL>AyRteFQ^iymSz<)g) z%<6SBRNHEIVA{1i3H~0C64nXFH_2=c#{*bU?(`^YF_a;S4ju_&4t;a}mQvan&Xa~O z&wB?0T%#10N?qNmx-)e3>$*A0V=BV=n2;~!$wuuKI-a!MBR(-K1(F*m=`^Nyd%X%l z9o_yx&Z%qhqD3W#``V+IPnaeR53^R9hzvIbax;y79#_lS$|3+=f}D*%NN=|UZ(o<& oX0{Z>x`IFbKY!ARK?|YV9EMyIF(zj;_~22RNZlLQYu3;H2c?gkng9R* literal 0 HcmV?d00001 diff --git a/resources/scripts/Generator/Data/colors.json b/src/Generator/Data/colors.json similarity index 100% rename from resources/scripts/Generator/Data/colors.json rename to src/Generator/Data/colors.json diff --git a/resources/scripts/Generator/Data/spinners_default.json b/src/Generator/Data/spinners_default.json similarity index 100% rename from resources/scripts/Generator/Data/spinners_default.json rename to src/Generator/Data/spinners_default.json diff --git a/resources/scripts/Generator/Data/spinners_sindresorhus.json b/src/Generator/Data/spinners_sindresorhus.json similarity index 100% rename from resources/scripts/Generator/Data/spinners_sindresorhus.json rename to src/Generator/Data/spinners_sindresorhus.json diff --git a/src/Generator/Generator.csproj b/src/Generator/Generator.csproj new file mode 100644 index 000000000..b8bfc5ccb --- /dev/null +++ b/src/Generator/Generator.csproj @@ -0,0 +1,42 @@ + + + + Exe + net8.0 + false + $(NoWarn);CS8002 + + + + + + + + PreserveNewest + + + + + + Always + + + Always + + + + + + + + + + + + + + + + + + diff --git a/resources/scripts/Generator/Generator.slnx b/src/Generator/Generator.slnx similarity index 83% rename from resources/scripts/Generator/Generator.slnx rename to src/Generator/Generator.slnx index fe69c40ac..55dc79a47 100644 --- a/resources/scripts/Generator/Generator.slnx +++ b/src/Generator/Generator.slnx @@ -7,8 +7,7 @@ - - + \ No newline at end of file diff --git a/src/Generator/Models/Color.cs b/src/Generator/Models/Color.cs new file mode 100644 index 000000000..999f25d0e --- /dev/null +++ b/src/Generator/Models/Color.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Newtonsoft.Json; + +namespace Generator.Models; + +public sealed class Color +{ + public required int Number { get; init; } + public required string Hex { get; init; } + public required string Name { get; set; } + public List Aliases { get; set; } = []; + public bool IsAlias { get; set; } + public required Rgb Rgb { get; init; } + + public int R => Rgb.R; + public int G => Rgb.G; + public int B => Rgb.B; + + public static IEnumerable Parse(string json) + { + var source = JsonConvert.DeserializeObject>(json); + Trace.Assert(source != null, "Could not deserialize JSON"); + + var check = new Dictionary(StringComparer.OrdinalIgnoreCase); + + var colorAliases = source + .SelectMany(c => c.Aliases.Select(a => new { Alias = a, Color = c })) + .Select(a => new Color() + { + Hex = a.Color.Hex, + Name = a.Alias, + Number = a.Color.Number, + Rgb = a.Color.Rgb, + IsAlias = true, + }) + .ToList(); + + var colors = source + .Union(colorAliases) + .OrderBy(c => c.Number); + + foreach (var color in colors) + { + if (!check.ContainsKey(color.Name)) + { + check.Add(color.Name, color); + } + else + { + var newName = default(string?); + for (var i = 1; i < 100; i++) + { + if (!check.ContainsKey($"{color.Name}_{i}")) + { + newName = $"{color.Name}_{i}"; + break; + } + } + + if (newName == null) + { + throw new InvalidOperationException("Impossible!"); + } + + check.Add(newName, color); + color.Name = newName; + } + } + + return colors; + } +} + +public sealed class Rgb +{ + public int R { get; set; } + public int G { get; set; } + public int B { get; set; } +} \ No newline at end of file diff --git a/src/Generator/Models/ColorModel.cs b/src/Generator/Models/ColorModel.cs new file mode 100644 index 000000000..d2f29287f --- /dev/null +++ b/src/Generator/Models/ColorModel.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace Generator.Models; + +public sealed class ColorModel +{ + public List Colors { get; set; } + + public ColorModel(IEnumerable colors) + { + Colors = new List(colors); + } +} \ No newline at end of file diff --git a/src/Generator/Models/Emoji.cs b/src/Generator/Models/Emoji.cs new file mode 100644 index 000000000..6aa6d3e23 --- /dev/null +++ b/src/Generator/Models/Emoji.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using AngleSharp.Dom; +using AngleSharp.Html.Dom; +using Humanizer; + +namespace Generator.Models; + +public class Emoji +{ + private static readonly string[] _headers = { "count", "code", "sample", "name" }; + + private Emoji(string identifier, string name, string code, string description) + { + Identifier = identifier; + Name = name; + Code = code; + Description = description; + NormalizedCode = Code.Replace("\\U", "U+"); + HasCombinators = Code.Split(new[] { "\\U" }, System.StringSplitOptions.RemoveEmptyEntries).Length > 1; + } + + public string Identifier { get; set; } + public string Code { get; } + public string NormalizedCode { get; } + public string Name { get; } + public string Description { get; set; } + public bool HasCombinators { get; set; } + + public static IEnumerable Parse(IHtmlDocument document) + { + var rows = document + .GetNodes(predicate: row => + row.Cells.Length >= _headers.Length && // Filter out rows that don't have enough cells. + row.Cells.All(x => x.LocalName == TagNames.Td)); // We're only interested in td cells, not th. + + foreach (var row in rows) + { + var dictionary = _headers + .Zip(row.Cells, (header, cell) => (Header: header, cell.TextContent.Trim())) + .ToDictionary(x => x.Item1, x => x.Item2); + + var code = TransformCode(dictionary["code"]); + var identifier = TransformName(dictionary["name"]) + .Replace("-", "_") + .Replace("(", string.Empty) + .Replace(")", string.Empty); + + var description = dictionary["name"].Humanize(); + + var name = identifier + .Replace("1st", "first") + .Replace("2nd", "second") + .Replace("3rd", "third") + .Pascalize(); + + yield return new Emoji(identifier, name, code, description); + } + } + + private static string TransformName(string name) + { + return name.Replace(":", string.Empty) + .Replace(",", string.Empty) + .Replace(".", string.Empty) + .Replace("\u201c", string.Empty) + .Replace("\u201d", string.Empty) + .Replace("\u229b", string.Empty) + .Replace(' ', '_') + .Replace("’s", "s") + .Replace("’", "_") + .Replace("&", "and") + .Replace("#", "hash") + .Replace("*", "star") + .Replace("!", string.Empty) + .Trim() + .ToLowerInvariant(); + } + + private static string TransformCode(string code) + { + var builder = new StringBuilder(); + + foreach (var part in code.Split(' ')) + { + builder.Append(part.Length == 6 + ? part.Replace("+", "0000") + : part.Replace("+", "000")); + } + + return builder.ToString().Replace("U", "\\U"); + } +} \ No newline at end of file diff --git a/src/Generator/Models/Palette.cs b/src/Generator/Models/Palette.cs new file mode 100644 index 000000000..fd9ff17b4 --- /dev/null +++ b/src/Generator/Models/Palette.cs @@ -0,0 +1,5 @@ +namespace Generator.Models; + +public sealed class Palette +{ +} \ No newline at end of file diff --git a/src/Generator/Models/Spinner.cs b/src/Generator/Models/Spinner.cs new file mode 100644 index 000000000..17c3de116 --- /dev/null +++ b/src/Generator/Models/Spinner.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Humanizer; +using Newtonsoft.Json; + +namespace Generator.Models; + +public sealed class Spinner +{ + public string Name { get; set; } = null!; + public string NormalizedName { get; set; } = null!; + public int Interval { get; set; } + public bool Unicode { get; set; } + public List Frames { get; set; } = null!; + + public static IEnumerable Parse(string json) + { + var data = JsonConvert.DeserializeObject>(json); + Trace.Assert(data != null, "Could not deserialize JSON"); + foreach (var item in data) + { + item.Value.Name = item.Key; + item.Value.NormalizedName = item.Value.Name.Pascalize(); + + var frames = item.Value.Frames; + item.Value.Frames = frames.Select(f => f.Replace("\\", "\\\\")).ToList(); + } + + return data.Values; + } +} \ No newline at end of file diff --git a/src/Generator/Program.cs b/src/Generator/Program.cs new file mode 100644 index 000000000..3f8231461 --- /dev/null +++ b/src/Generator/Program.cs @@ -0,0 +1,21 @@ +using Generator.Commands; +using Spectre.Console.Cli; + +namespace Generator; + +public static class Program +{ + public static int Main(string[] args) + { + var app = new CommandApp(); + app.Configure(config => + { + config.AddCommand("colors"); + config.AddCommand("emoji"); + config.AddCommand("spinners"); + config.AddCommand("samples"); + }); + + return app.Run(args); + } +} \ No newline at end of file diff --git a/resources/scripts/Generator/Templates/Color.Generated.template b/src/Generator/Templates/Color.Generated.template similarity index 100% rename from resources/scripts/Generator/Templates/Color.Generated.template rename to src/Generator/Templates/Color.Generated.template diff --git a/resources/scripts/Generator/Templates/ColorPalette.Generated.template b/src/Generator/Templates/ColorPalette.Generated.template similarity index 79% rename from resources/scripts/Generator/Templates/ColorPalette.Generated.template rename to src/Generator/Templates/ColorPalette.Generated.template index 725a64d15..f10aa0da7 100644 --- a/resources/scripts/Generator/Templates/ColorPalette.Generated.template +++ b/src/Generator/Templates/ColorPalette.Generated.template @@ -17,8 +17,8 @@ namespace Spectre.Console { return new List { - {{~ for number in 0..7 ~}} - Color.{{ colors[number].name }}, + {{~ for color in legacy ~}} + Color.{{ color.name }}, {{~ end ~}} }; } @@ -27,8 +27,8 @@ namespace Spectre.Console { return new List(legacy) { - {{~ for number in 8..15 ~}} - Color.{{ colors[number].name }}, + {{~ for color in standard ~}} + Color.{{ color.name }}, {{~ end ~}} }; } @@ -37,8 +37,8 @@ namespace Spectre.Console { return new List(standard) { - {{~ for number in 16..255 ~}} - Color.{{ colors[number].name }}, + {{~ for color in eight_bit ~}} + Color.{{ color.name }}, {{~ end ~}} }; } diff --git a/resources/scripts/Generator/Templates/ColorTable.Generated.template b/src/Generator/Templates/ColorTable.Generated.template similarity index 100% rename from resources/scripts/Generator/Templates/ColorTable.Generated.template rename to src/Generator/Templates/ColorTable.Generated.template diff --git a/resources/scripts/Generator/Templates/Emoji.Generated.template b/src/Generator/Templates/Emoji.Generated.template similarity index 100% rename from resources/scripts/Generator/Templates/Emoji.Generated.template rename to src/Generator/Templates/Emoji.Generated.template diff --git a/resources/scripts/Generator/Templates/Emoji.Json.template b/src/Generator/Templates/Emoji.Json.template similarity index 100% rename from resources/scripts/Generator/Templates/Emoji.Json.template rename to src/Generator/Templates/Emoji.Json.template diff --git a/resources/scripts/Generator/Templates/Spinner.Generated.template b/src/Generator/Templates/Spinner.Generated.template similarity index 100% rename from resources/scripts/Generator/Templates/Spinner.Generated.template rename to src/Generator/Templates/Spinner.Generated.template diff --git a/src/Spectre.Console.Cli/Annotations/CommandArgumentAttribute.cs b/src/Spectre.Console.Cli/Annotations/CommandArgumentAttribute.cs deleted file mode 100644 index 8bf364535..000000000 --- a/src/Spectre.Console.Cli/Annotations/CommandArgumentAttribute.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// An attribute representing a command argument. -/// -/// -[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] -public sealed class CommandArgumentAttribute : Attribute -{ - /// - /// Gets the argument position. - /// - /// The argument position. - public int Position { get; } - - /// - /// Gets the value name of the argument. - /// - /// The value name of the argument. - public string ValueName { get; } - - /// - /// Gets a value indicating whether the argument is required. - /// - /// - /// true if the argument is required; otherwise, false. - /// - public bool IsRequired { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The argument position. - /// The argument template. Wrap in <> for required arguments, [] for optional ones. For example "[MyArgument]". - public CommandArgumentAttribute(int position, string template) - { - if (template == null) - { - throw new ArgumentNullException(nameof(template)); - } - - // Parse the option template. - var result = TemplateParser.ParseArgumentTemplate(template); - - // Assign the result. - Position = position; - ValueName = result.Value; - IsRequired = result.IsRequired; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Annotations/CommandOptionAttribute.cs b/src/Spectre.Console.Cli/Annotations/CommandOptionAttribute.cs deleted file mode 100644 index c43b92702..000000000 --- a/src/Spectre.Console.Cli/Annotations/CommandOptionAttribute.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// An attribute representing a command option. -/// -/// -[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] -public sealed class CommandOptionAttribute : Attribute -{ - /// - /// Gets the long names of the option. - /// - /// The option's long names. - public IReadOnlyList LongNames { get; } - - /// - /// Gets the short names of the option. - /// - /// The option's short names. - public IReadOnlyList ShortNames { get; } - - /// - /// Gets the value name of the option. - /// - /// The option's value name. - public string? ValueName { get; } - - /// - /// Gets a value indicating whether the value is optional. - /// - public bool ValueIsOptional { get; } - - /// - /// Gets a value indicating whether the value is required. - /// - public bool IsRequired { get; } - - /// - /// Gets or sets a value indicating whether this option is hidden from the help text. - /// - public bool IsHidden { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The option template. - /// Indicates whether the option is required or not. - public CommandOptionAttribute(string template, bool isRequired = false) - { - if (template == null) - { - throw new ArgumentNullException(nameof(template)); - } - - // Parse the option template. - var result = TemplateParser.ParseOptionTemplate(template); - - // Assign the result. - LongNames = result.LongNames; - ShortNames = result.ShortNames; - ValueName = result.Value; - ValueIsOptional = result.ValueIsOptional; - IsRequired = isRequired; - } - - internal bool IsMatch(string name) - { - return - ShortNames.Contains(name, StringComparer.Ordinal) || - LongNames.Contains(name, StringComparer.Ordinal); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Annotations/PairDeconstructorAttribute.cs b/src/Spectre.Console.Cli/Annotations/PairDeconstructorAttribute.cs deleted file mode 100644 index b21260271..000000000 --- a/src/Spectre.Console.Cli/Annotations/PairDeconstructorAttribute.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Specifies what type to use as a pair deconstructor for -/// the property this attribute is bound to. -/// -[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] -public sealed class PairDeconstructorAttribute : Attribute -{ - /// - /// Gets the that represents the type of the - /// pair deconstructor class to use for data conversion for the - /// object this attribute is bound to. - /// - public Type Type { get; } - - /// - /// Initializes a new instance of the class. - /// - /// - /// A System.Type that represents the type of the pair deconstructor - /// class to use for data conversion for the object this attribute is bound to. - /// - public PairDeconstructorAttribute(Type type) - { - Type = type ?? throw new ArgumentNullException(nameof(type)); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Annotations/ParameterValidationAttribute.cs b/src/Spectre.Console.Cli/Annotations/ParameterValidationAttribute.cs deleted file mode 100644 index 38f3f19ff..000000000 --- a/src/Spectre.Console.Cli/Annotations/ParameterValidationAttribute.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// A base class attribute used for parameter validation. -/// -/// -[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] -public abstract class ParameterValidationAttribute : Attribute -{ - /// - /// Gets the validation error message. - /// - /// The validation error message. - public string ErrorMessage { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The validation error message. - protected ParameterValidationAttribute(string errorMessage) - { - ErrorMessage = errorMessage; - } - - /// - /// Validates the parameter value. - /// - /// The parameter context. - /// The validation result. - public abstract ValidationResult Validate(CommandParameterContext context); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Annotations/ParameterValueProviderAttribute.cs b/src/Spectre.Console.Cli/Annotations/ParameterValueProviderAttribute.cs deleted file mode 100644 index 69f1f73dc..000000000 --- a/src/Spectre.Console.Cli/Annotations/ParameterValueProviderAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// A base class attribute used for parameter completion. -/// -/// -[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] -public abstract class ParameterValueProviderAttribute : Attribute -{ - /// - /// Gets a value for the parameter. - /// - /// The parameter context. - /// The resulting value. - /// true if a value was provided; otherwise, false. - public abstract bool TryGetValue(CommandParameterContext context, out object? result); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/AsyncCommand.cs b/src/Spectre.Console.Cli/AsyncCommand.cs deleted file mode 100644 index 55fb31667..000000000 --- a/src/Spectre.Console.Cli/AsyncCommand.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Base class for an asynchronous command with no settings. -/// -public abstract class AsyncCommand : ICommand -{ - /// - /// Executes the command. - /// - /// The command context. - /// A that can be used to abort the command. - /// An integer indicating whether or not the command executed successfully. - public abstract Task ExecuteAsync(CommandContext context, CancellationToken cancellationToken); - - /// - Task ICommand.ExecuteAsync(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) - { - return ExecuteAsync(context, cancellationToken); - } - - /// - Task ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) - { - return ExecuteAsync(context, cancellationToken); - } - - /// - ValidationResult ICommand.Validate(CommandContext context, CommandSettings settings) - { - return ValidationResult.Success(); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/AsyncCommandOfT.cs b/src/Spectre.Console.Cli/AsyncCommandOfT.cs deleted file mode 100644 index 5172b6819..000000000 --- a/src/Spectre.Console.Cli/AsyncCommandOfT.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Base class for an asynchronous command. -/// -/// The settings type. -public abstract class AsyncCommand : ICommand - where TSettings : CommandSettings -{ - /// - /// Validates the specified settings and remaining arguments. - /// - /// The command context. - /// The settings. - /// The validation result. - public virtual ValidationResult Validate(CommandContext context, TSettings settings) - { - return ValidationResult.Success(); - } - - /// - /// Executes the command. - /// - /// The command context. - /// The settings. - /// A that can be used to abort the command. - /// An integer indicating whether or not the command executed successfully. - public abstract Task ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken); - - /// - ValidationResult ICommand.Validate(CommandContext context, CommandSettings settings) - { - return Validate(context, (TSettings)settings); - } - - /// - Task ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) - { - Debug.Assert(settings is TSettings, "Command settings is of unexpected type."); - return ExecuteAsync(context, (TSettings)settings, cancellationToken); - } - - /// - Task ICommand.ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken) - { - return ExecuteAsync(context, settings, cancellationToken); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CaseSensitivity.cs b/src/Spectre.Console.Cli/CaseSensitivity.cs deleted file mode 100644 index 778579bdf..000000000 --- a/src/Spectre.Console.Cli/CaseSensitivity.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents case sensitivity. -/// -[Flags] -public enum CaseSensitivity -{ - /// - /// Nothing is case sensitive. - /// - None = 0, - - /// - /// Long options are case sensitive. - /// - LongOptions = 1, - - /// - /// Commands are case sensitive. - /// - Commands = 2, - - /// - /// Everything is case sensitive. - /// - All = LongOptions | Commands, -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Command.cs b/src/Spectre.Console.Cli/Command.cs deleted file mode 100644 index 7d9b6e5d9..000000000 --- a/src/Spectre.Console.Cli/Command.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Base class for a command without settings. -/// -/// -public abstract class Command : ICommand -{ - /// - /// Executes the command. - /// - /// The command context. - /// A that can be used to abort the command. - /// An integer indicating whether or not the command executed successfully. - public abstract int Execute(CommandContext context, CancellationToken cancellationToken); - - /// - Task ICommand.ExecuteAsync(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) - { - return Task.FromResult(Execute(context, cancellationToken)); - } - - /// - Task ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) - { - return Task.FromResult(Execute(context, cancellationToken)); - } - - /// - ValidationResult ICommand.Validate(CommandContext context, CommandSettings settings) - { - return ValidationResult.Success(); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CommandApp.cs b/src/Spectre.Console.Cli/CommandApp.cs deleted file mode 100644 index d60d6740a..000000000 --- a/src/Spectre.Console.Cli/CommandApp.cs +++ /dev/null @@ -1,155 +0,0 @@ -using Spectre.Console.Cli.Internal.Configuration; - -namespace Spectre.Console.Cli; - -/// -/// The entry point for a command line application. -/// -#if !NETSTANDARD2_0 -[RequiresDynamicCode("Spectre.Console.Cli relies on reflection. Use during trimming and AOT compilation is not supported and may result in unexpected behaviors.")] -#endif -public sealed class CommandApp : ICommandApp -{ - private readonly Configurator _configurator; - private readonly CommandExecutor _executor; - private bool _executed; - - /// - /// Initializes a new instance of the class. - /// - /// The registrar. - public CommandApp(ITypeRegistrar? registrar = null) - { - registrar ??= new DefaultTypeRegistrar(); - - _configurator = new Configurator(registrar); - _executor = new CommandExecutor(registrar); - } - - /// - public void Configure(Action configuration) - { - if (configuration == null) - { - throw new ArgumentNullException(nameof(configuration)); - } - - configuration(_configurator); - } - - /// - /// Sets the default command. - /// - /// The command type. - /// A that can be used to configure the default command. - public DefaultCommandConfigurator SetDefaultCommand() - where TCommand : class, ICommand - { - return new DefaultCommandConfigurator(GetConfigurator().SetDefaultCommand()); - } - - /// - public int Run(IEnumerable args, CancellationToken cancellationToken = default) - { - return RunAsync(args, cancellationToken).GetAwaiter().GetResult(); - } - - /// - public async Task RunAsync(IEnumerable args, CancellationToken cancellationToken = default) - { - try - { - if (!_executed) - { - // Add built-in (hidden) commands. - _configurator.AddBranch(CliConstants.Commands.Branch, cli => - { - cli.HideBranch(); - cli.AddCommand(CliConstants.Commands.Version); - cli.AddCommand(CliConstants.Commands.XmlDoc); - cli.AddCommand(CliConstants.Commands.Explain); - cli.AddCommand(CliConstants.Commands.OpenCli); - }); - - _executed = true; - } - - return await _executor - .ExecuteAsync(_configurator, args, cancellationToken) - .ConfigureAwait(false); - } - catch (Exception ex) - { - // Should we always propagate when debugging? - if (Debugger.IsAttached - && ex is CommandAppException appException - && appException.AlwaysPropagateWhenDebugging) - { - throw; - } - - if (_configurator.Settings.PropagateExceptions) - { - throw; - } - - if (_configurator.Settings.ExceptionHandler != null) - { - return _configurator.Settings.ExceptionHandler(ex, null); - } - - if (ex is OperationCanceledException) - { - return _configurator.Settings.CancellationExitCode; - } - - // Render the exception. - var pretty = GetRenderableErrorMessage(ex); - if (pretty != null) - { - _configurator.Settings.Console.SafeRender(pretty); - } - - return -1; - } - } - - internal Configurator GetConfigurator() - { - return _configurator; - } - - private static List? GetRenderableErrorMessage(Exception ex, bool convert = true) - { - if (ex is CommandAppException renderable && renderable.Pretty != null) - { - return new List { renderable.Pretty }; - } - - if (convert) - { - var converted = new List - { - new Composer() - .Text("[red]Error:[/]") - .Space() - .Text(ex.Message.EscapeMarkup()) - .LineBreak(), - }; - - // Got a renderable inner exception? - if (ex.InnerException != null) - { - var innerRenderable = GetRenderableErrorMessage(ex.InnerException, convert: false); - if (innerRenderable != null) - { - converted.AddRange(innerRenderable); - } - } - - return converted; - } - - return null; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CommandAppException.cs b/src/Spectre.Console.Cli/CommandAppException.cs deleted file mode 100644 index cfd5529fa..000000000 --- a/src/Spectre.Console.Cli/CommandAppException.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents errors that occur during application execution. -/// -public abstract class CommandAppException : Exception -{ - /// - /// Gets the pretty formatted exception message. - /// - public IRenderable? Pretty { get; } - - internal virtual bool AlwaysPropagateWhenDebugging => false; - - internal CommandAppException(string message, IRenderable? pretty = null) - : base(message) - { - Pretty = pretty; - } - - internal CommandAppException(string message, Exception ex, IRenderable? pretty = null) - : base(message, ex) - { - Pretty = pretty; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CommandAppOfT.cs b/src/Spectre.Console.Cli/CommandAppOfT.cs deleted file mode 100644 index a06e43bdd..000000000 --- a/src/Spectre.Console.Cli/CommandAppOfT.cs +++ /dev/null @@ -1,72 +0,0 @@ -using Spectre.Console.Cli.Internal.Configuration; - -namespace Spectre.Console.Cli; - -/// -/// The entry point for a command line application with a default command. -/// -/// The type of the default command. -#if !NETSTANDARD2_0 -[RequiresDynamicCode("Spectre.Console.Cli relies on reflection. Use during trimming and AOT compilation is not supported and may result in unexpected behaviors.")] -#endif -public sealed class CommandApp : ICommandApp - where TDefaultCommand : class, ICommand -{ - private readonly CommandApp _app; - private readonly DefaultCommandConfigurator _defaultCommandConfigurator; - - /// - /// Initializes a new instance of the class. - /// - /// The registrar. - public CommandApp(ITypeRegistrar? registrar = null) - { - _app = new CommandApp(registrar); - _defaultCommandConfigurator = _app.SetDefaultCommand(); - } - - /// - public void Configure(Action configuration) - { - _app.Configure(configuration); - } - - /// - public int Run(IEnumerable args, CancellationToken cancellationToken = default) - { - return _app.Run(args, cancellationToken); - } - - /// - public Task RunAsync(IEnumerable args, CancellationToken cancellationToken = default) - { - return _app.RunAsync(args, cancellationToken); - } - - internal Configurator GetConfigurator() - { - return _app.GetConfigurator(); - } - - /// - /// Sets the description of the default command. - /// - /// The default command description. - /// The same instance so that multiple calls can be chained. - public CommandApp WithDescription(string description) - { - _defaultCommandConfigurator.WithDescription(description); - return this; - } - - /// - /// Sets data that will be passed to the command via the . - /// - /// The data to pass to the default command. - /// The same instance so that multiple calls can be chained. - public CommandApp WithData(object data) - { - _defaultCommandConfigurator.WithData(data); - return this; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CommandConfigurationException.cs b/src/Spectre.Console.Cli/CommandConfigurationException.cs deleted file mode 100644 index f1a1ed5a4..000000000 --- a/src/Spectre.Console.Cli/CommandConfigurationException.cs +++ /dev/null @@ -1,76 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents errors that occur during configuration. -/// -public class CommandConfigurationException : CommandAppException -{ - internal override bool AlwaysPropagateWhenDebugging => true; - - internal CommandConfigurationException(string message, IRenderable? pretty = null) - : base(message, pretty) - { - } - - internal CommandConfigurationException(string message, Exception ex, IRenderable? pretty = null) - : base(message, ex, pretty) - { - } - - internal static CommandConfigurationException NoCommandConfigured() - { - return new CommandConfigurationException("No commands have been configured."); - } - - internal static CommandConfigurationException CommandNameConflict(CommandInfo command, string alias) - { - return new CommandConfigurationException($"The alias '{alias}' for '{command.Name}' conflicts with another command."); - } - - internal static CommandConfigurationException DuplicateOption(CommandInfo command, string[] options) - { - var keys = string.Join(", ", options.Select(x => x.Length > 1 ? $"--{x}" : $"-{x}")); - if (options.Length > 1) - { - return new CommandConfigurationException($"Options {keys} are duplicated in command '{command.Name}'."); - } - - return new CommandConfigurationException($"Option {keys} is duplicated in command '{command.Name}'."); - } - - internal static CommandConfigurationException BranchHasNoChildren(CommandInfo command) - { - throw new CommandConfigurationException($"The branch '{command.Name}' does not define any commands."); - } - - internal static CommandConfigurationException TooManyVectorArguments(CommandInfo command) - { - throw new CommandConfigurationException($"The command '{command.Name}' specifies more than one vector argument."); - } - - internal static CommandConfigurationException VectorArgumentNotSpecifiedLast(CommandInfo command) - { - throw new CommandConfigurationException($"The command '{command.Name}' specifies an argument vector that is not the last argument."); - } - - internal static CommandConfigurationException OptionalOptionValueMustBeFlagWithValue(CommandOption option) - { - return new CommandConfigurationException($"The option '{option.GetOptionName()}' has an optional value but does not implement IFlagValue."); - } - - internal static CommandConfigurationException OptionBothHasPairDeconstructorAndTypeParameter(CommandOption option) - { - return new CommandConfigurationException($"The option '{option.GetOptionName()}' is both marked as pair deconstructable and convertable."); - } - - internal static CommandConfigurationException OptionTypeDoesNotSupportDeconstruction(CommandOption option) - { - return new CommandConfigurationException($"The option '{option.GetOptionName()}' is marked as " + - "pair deconstructable, but the underlying type does not support that."); - } - - internal static CommandConfigurationException RequiredArgumentsCannotHaveDefaultValue(CommandArgument option) - { - return new CommandConfigurationException($"The required argument '{option.Value}' cannot have a default value."); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CommandContext.cs b/src/Spectre.Console.Cli/CommandContext.cs deleted file mode 100644 index 0e7a612cf..000000000 --- a/src/Spectre.Console.Cli/CommandContext.cs +++ /dev/null @@ -1,55 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a command context. -/// -public sealed class CommandContext -{ - /// - /// Gets the remaining arguments. - /// - /// - /// The remaining arguments. - /// - public IRemainingArguments Remaining { get; } - - /// - /// Gets all the arguments that were passed to the application. - /// - public IReadOnlyList Arguments { get; } - - /// - /// Gets the name of the command. - /// - /// - /// The name of the command. - /// - public string Name { get; } - - /// - /// Gets the data that was passed to the command during registration (if any). - /// - /// - /// The command data. - /// - public object? Data { get; } - - /// - /// Initializes a new instance of the class. - /// - /// All arguments that were passed to the application. - /// The remaining arguments. - /// The command name. - /// The command data. - public CommandContext( - IEnumerable arguments, - IRemainingArguments remaining, - string name, - object? data) - { - Arguments = arguments.ToSafeReadOnlyList(); - Remaining = remaining ?? throw new System.ArgumentNullException(nameof(remaining)); - Name = name ?? throw new System.ArgumentNullException(nameof(name)); - Data = data; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CommandOfT.cs b/src/Spectre.Console.Cli/CommandOfT.cs deleted file mode 100644 index d35823dcb..000000000 --- a/src/Spectre.Console.Cli/CommandOfT.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Base class for a command. -/// -/// The settings type. -/// -public abstract class Command : ICommand - where TSettings : CommandSettings -{ - /// - /// Validates the specified settings and remaining arguments. - /// - /// The command context. - /// The settings. - /// The validation result. - public virtual ValidationResult Validate(CommandContext context, TSettings settings) - { - return ValidationResult.Success(); - } - - /// - /// Executes the command. - /// - /// The command context. - /// The settings. - /// A that can be used to abort the command. - /// An integer indicating whether or not the command executed successfully. - public abstract int Execute(CommandContext context, TSettings settings, CancellationToken cancellationToken); - - /// - ValidationResult ICommand.Validate(CommandContext context, CommandSettings settings) - { - return Validate(context, (TSettings)settings); - } - - /// - Task ICommand.ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) - { - Debug.Assert(settings is TSettings, "Command settings is of unexpected type."); - return Task.FromResult(Execute(context, (TSettings)settings, cancellationToken)); - } - - /// - Task ICommand.ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken) - { - return Task.FromResult(Execute(context, settings, cancellationToken)); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CommandParameterContext.cs b/src/Spectre.Console.Cli/CommandParameterContext.cs deleted file mode 100644 index a7d5cfde8..000000000 --- a/src/Spectre.Console.Cli/CommandParameterContext.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a context for related operations. -/// -public sealed class CommandParameterContext -{ - /// - /// Gets the parameter. - /// - public ICommandParameterInfo Parameter { get; } - - /// - /// Gets the type resolver. - /// - public ITypeResolver Resolver { get; } - - /// - /// Gets tje parameter value. - /// - public object? Value { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The parameter. - /// The type resolver. - /// The parameter value. - public CommandParameterContext(ICommandParameterInfo parameter, ITypeResolver resolver, object? value) - { - Parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); - Resolver = resolver ?? throw new ArgumentNullException(nameof(resolver)); - Value = value; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CommandParseException.cs b/src/Spectre.Console.Cli/CommandParseException.cs deleted file mode 100644 index 19c0518a1..000000000 --- a/src/Spectre.Console.Cli/CommandParseException.cs +++ /dev/null @@ -1,121 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents errors that occur during parsing. -/// -public sealed class CommandParseException : CommandRuntimeException -{ - internal CommandParseException(string message, IRenderable? pretty = null) - : base(message, pretty) - { - } - - internal static CommandParseException CouldNotCreateSettings(Type settingsType) - { - return new CommandParseException($"Could not create settings of type '{settingsType.FullName}'."); - } - - internal static CommandParseException CouldNotCreateCommand(Type? commandType) - { - if (commandType == null) - { - return new CommandParseException($"Could not create command. Command type is unknown."); - } - - return new CommandParseException($"Could not create command of type '{commandType.FullName}'."); - } - - internal static CommandParseException ExpectedTokenButFoundNull(CommandTreeToken.Kind expected) - { - return new CommandParseException($"Expected to find any token of type '{expected}' but found null instead."); - } - - internal static CommandParseException ExpectedTokenButFoundOther(CommandTreeToken.Kind expected, CommandTreeToken.Kind found) - { - return new CommandParseException($"Expected to find token of type '{expected}' but found '{found}' instead."); - } - - internal static CommandParseException OptionHasNoName(string input, CommandTreeToken token) - { - return CommandLineParseExceptionFactory.Create(input, token, "Option does not have a name.", "Did you forget the option name?"); - } - - internal static CommandParseException OptionValueWasExpected(string input, CommandTreeToken token) - { - return CommandLineParseExceptionFactory.Create(input, token, "Expected an option value.", "Did you forget the option value?"); - } - - internal static CommandParseException OptionHasNoValue(IEnumerable args, CommandTreeToken token, CommandOption option) - { - return CommandLineParseExceptionFactory.Create(args, token, $"Option '{option.GetOptionName()}' is defined but no value has been provided.", "No value provided."); - } - - internal static CommandParseException UnexpectedOption(IEnumerable args, CommandTreeToken token) - { - return CommandLineParseExceptionFactory.Create(args, token, $"Unexpected option '{token.Value}'.", "Did you forget the command?"); - } - - internal static CommandParseException CannotAssignValueToFlag(IEnumerable args, CommandTreeToken token) - { - return CommandLineParseExceptionFactory.Create(args, token, "Flags cannot be assigned a value.", "Can't assign value."); - } - - internal static CommandParseException InvalidShortOptionName(string input, CommandTreeToken token) - { - return CommandLineParseExceptionFactory.Create(input, token, "Short option does not have a valid name.", "Not a valid name for a short option."); - } - - internal static CommandParseException LongOptionNameIsMissing(TextBuffer reader, int position) - { - var token = new CommandTreeToken(CommandTreeToken.Kind.LongOption, position, string.Empty, "--"); - return CommandLineParseExceptionFactory.Create(reader.Original, token, "Invalid long option name.", "Did you forget the option name?"); - } - - internal static CommandParseException LongOptionNameIsOneCharacter(TextBuffer reader, int position, string name) - { - var token = new CommandTreeToken(CommandTreeToken.Kind.LongOption, position, name, $"--{name}"); - var reason = $"Did you mean -{name}?"; - return CommandLineParseExceptionFactory.Create(reader.Original, token, "Invalid long option name.", reason); - } - - internal static CommandParseException LongOptionNameStartWithDigit(TextBuffer reader, int position, string name) - { - var token = new CommandTreeToken(CommandTreeToken.Kind.LongOption, position, name, $"--{name}"); - return CommandLineParseExceptionFactory.Create(reader.Original, token, "Invalid long option name.", "Option names cannot start with a digit."); - } - - internal static CommandParseException LongOptionNameContainSymbol(TextBuffer reader, int position, char character) - { - var name = character.ToString(CultureInfo.InvariantCulture); - var token = new CommandTreeToken(CommandTreeToken.Kind.LongOption, position, name, name); - return CommandLineParseExceptionFactory.Create(reader.Original, token, "Invalid long option name.", "Invalid character."); - } - - internal static CommandParseException UnknownCommand(CommandModel model, CommandTree? node, IEnumerable args, CommandTreeToken token) - { - var suggestion = CommandSuggestor.Suggest(model, node?.Command, token.Value); - var text = suggestion != null ? $"Did you mean '{suggestion.Name}'?" : "No such command."; - return CommandLineParseExceptionFactory.Create(args, token, $"Unknown command '{token.Value}'.", text); - } - - internal static CommandParseException CouldNotMatchArgument(IEnumerable args, CommandTreeToken token) - { - return CommandLineParseExceptionFactory.Create(args, token, $"Could not match '{token.Value}' with an argument.", "Could not match to argument."); - } - - internal static CommandParseException UnknownOption(IEnumerable args, CommandTreeToken token) - { - return CommandLineParseExceptionFactory.Create(args, token, $"Unknown option '{token.Value}'.", "Unknown option."); - } - - internal static CommandParseException ValueIsNotInValidFormat(string value) - { - var text = $"[red]Error:[/] The value '[white]{value}[/]' is not in a correct format"; - return new CommandParseException("Could not parse value", new Markup(text)); - } - - internal static CommandParseException UnknownParsingError() - { - return new CommandParseException("An unknown error occured when parsing the arguments."); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CommandRuntimeException.cs b/src/Spectre.Console.Cli/CommandRuntimeException.cs deleted file mode 100644 index ca94dacf6..000000000 --- a/src/Spectre.Console.Cli/CommandRuntimeException.cs +++ /dev/null @@ -1,71 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents errors that occur during runtime. -/// -public class CommandRuntimeException : CommandAppException -{ - internal CommandRuntimeException(string message, IRenderable? pretty = null) - : base(message, pretty) - { - } - - internal CommandRuntimeException(string message, Exception ex, IRenderable? pretty = null) - : base(message, ex, pretty) - { - } - - internal static CommandRuntimeException CouldNotResolveType(Type type, Exception? ex = null) - { - var message = $"Could not resolve type '{type.FullName}'."; - if (ex != null) - { - // TODO: Show internal stuff here. - return new CommandRuntimeException(message, ex); - } - - return new CommandRuntimeException(message); - } - - internal static CommandRuntimeException MissingRequiredArgument(CommandTree node, CommandArgument argument) - { - if (node.Command.Name == CliConstants.DefaultCommandName) - { - return new CommandRuntimeException($"Missing required argument '{argument.Value}'."); - } - - return new CommandRuntimeException($"Command '{node.Command.Name}' is missing required argument '{argument.Value}'."); - } - - internal static CommandRuntimeException MissingRequiredOption(CommandTree node, CommandOption option) - { - if (node.Command.Name == CliConstants.DefaultCommandName) - { - return new CommandRuntimeException($"Missing required option '{option.GetOptionName()}'."); - } - - return new CommandRuntimeException($"Command '{node.Command.Name}' is missing required argument '{option.GetOptionName()}'."); - } - - internal static CommandRuntimeException NoConverterFound(CommandParameter parameter) - { - return new CommandRuntimeException($"Could not find converter for type '{parameter.ParameterType.FullName}'."); - } - - internal static CommandRuntimeException ConversionFailed(MappedCommandParameter parameter, TypeConverter typeConverter, Exception exception) - { - var standardValues = typeConverter.GetStandardValuesSupported() ? typeConverter.GetStandardValues() : null; - var validValues = standardValues == null ? string.Empty : $" Valid values are '{string.Join("', '", standardValues.Cast().Select(Convert.ToString))}'"; - return new CommandRuntimeException($"Failed to convert '{parameter.Value}' to {parameter.Parameter.ParameterType.Name}.{validValues}", exception); - } - - internal static CommandRuntimeException ValidationFailed(ValidationResult result) - { - return new CommandRuntimeException(result.Message ?? "Unknown validation error."); - } - - internal static Exception CouldNotGetSettingsType(Type commandType) - { - return new CommandRuntimeException($"Could not get settings type for command of type '{commandType.FullName}'."); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CommandSettings.cs b/src/Spectre.Console.Cli/CommandSettings.cs deleted file mode 100644 index a6edea678..000000000 --- a/src/Spectre.Console.Cli/CommandSettings.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Base class for command settings. -/// -public abstract class CommandSettings -{ - /// - /// Performs validation of the settings. - /// - /// The validation result. - public virtual ValidationResult Validate() - { - return ValidationResult.Success(); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/CommandTemplateException.cs b/src/Spectre.Console.Cli/CommandTemplateException.cs deleted file mode 100644 index d862f72bd..000000000 --- a/src/Spectre.Console.Cli/CommandTemplateException.cs +++ /dev/null @@ -1,156 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents errors related to parameter templates. -/// -public sealed class CommandTemplateException : CommandConfigurationException -{ - /// - /// Gets the template that contains the error. - /// - public string Template { get; } - - internal override bool AlwaysPropagateWhenDebugging => true; - - internal CommandTemplateException(string message, string template, IRenderable pretty) - : base(message, pretty) - { - Template = template; - } - - internal static CommandTemplateException UnexpectedCharacter(string template, int position, char character) - { - return CommandLineTemplateExceptionFactory.Create( - template, - new TemplateToken(TemplateToken.Kind.Unknown, position, $"{character}", $"{character}"), - $"Encountered unexpected character '{character}'.", - "Unexpected character."); - } - - internal static CommandTemplateException UnterminatedValueName(string template, TemplateToken token) - { - return CommandLineTemplateExceptionFactory.Create( - template, token, - $"Encountered unterminated value name '{token.Value}'.", - "Unterminated value name."); - } - - internal static CommandTemplateException ArgumentCannotContainOptions(string template, TemplateToken token) - { - return CommandLineTemplateExceptionFactory.Create( - template, token, - "Arguments can not contain options.", - "Not permitted."); - } - - internal static CommandTemplateException MultipleValuesAreNotSupported(string template, TemplateToken token) - { - return CommandLineTemplateExceptionFactory.Create(template, token, - "Multiple values are not supported.", - "Too many values."); - } - - internal static CommandTemplateException ValuesMustHaveName(string template, TemplateToken token) - { - return CommandLineTemplateExceptionFactory.Create(template, token, - "Values without name are not allowed.", - "Missing value name."); - } - - internal static CommandTemplateException OptionsMustHaveName(string template, TemplateToken token) - { - return CommandLineTemplateExceptionFactory.Create(template, token, - "Options without name are not allowed.", - "Missing option name."); - } - - internal static CommandTemplateException OptionNamesCannotStartWithDigit(string template, TemplateToken token) - { - // Rewrite the token to point to the option name instead of the whole string. - token = new TemplateToken( - token.TokenKind, - token.TokenKind == TemplateToken.Kind.ShortName ? token.Position + 1 : token.Position + 2, - token.Value, token.Value); - - return CommandLineTemplateExceptionFactory.Create(template, token, - "Option names cannot start with a digit.", - "Invalid option name."); - } - - internal static CommandTemplateException InvalidCharacterInOptionName(string template, TemplateToken token, char character) - { - // Rewrite the token to point to the invalid character instead of the whole value. - var position = (token.TokenKind == TemplateToken.Kind.ShortName - ? token.Position + 1 - : token.Position + 2) + token.Value.OrdinalIndexOf(character); - - token = new TemplateToken( - token.TokenKind, position, - token.Value, character.ToString(CultureInfo.InvariantCulture)); - - return CommandLineTemplateExceptionFactory.Create(template, token, - $"Encountered invalid character '{character}' in option name.", - "Invalid character."); - } - - internal static CommandTemplateException LongOptionMustHaveMoreThanOneCharacter(string template, TemplateToken token) - { - // Rewrite the token to point to the option name instead of the whole option. - token = new TemplateToken(token.TokenKind, token.Position + 2, token.Value, token.Value); - - return CommandLineTemplateExceptionFactory.Create(template, token, - "Long option names must consist of more than one character.", - "Invalid option name."); - } - - internal static CommandTemplateException MultipleShortOptionNamesNotAllowed(string template, TemplateToken token) - { - return CommandLineTemplateExceptionFactory.Create(template, token, - "Multiple short option names are not supported.", - "Too many short options."); - } - - internal static CommandTemplateException ShortOptionMustOnlyBeOneCharacter(string template, TemplateToken token) - { - // Rewrite the token to point to the option name instead of the whole option. - token = new TemplateToken(token.TokenKind, token.Position + 1, token.Value, token.Value); - - return CommandLineTemplateExceptionFactory.Create(template, token, - "Short option names can not be longer than one character.", - "Invalid option name."); - } - - internal static CommandTemplateException MultipleOptionValuesAreNotSupported(string template, TemplateToken token) - { - return CommandLineTemplateExceptionFactory.Create(template, token, - "Multiple option values are not supported.", - "Too many option values."); - } - - internal static CommandTemplateException InvalidCharacterInValueName(string template, TemplateToken token, char character) - { - // Rewrite the token to point to the invalid character instead of the whole value. - token = new TemplateToken( - token.TokenKind, - token.Position + 1 + token.Value.OrdinalIndexOf(character), - token.Value, character.ToString(CultureInfo.InvariantCulture)); - - return CommandLineTemplateExceptionFactory.Create(template, token, - $"Encountered invalid character '{character}' in value name.", - "Invalid character."); - } - - internal static CommandTemplateException MissingLongAndShortName(string template, TemplateToken? token) - { - return CommandLineTemplateExceptionFactory.Create(template, token, - "No long or short name for option has been specified.", - "Missing option. Was this meant to be an argument?"); - } - - internal static CommandTemplateException ArgumentsMustHaveValueName(string template) - { - return CommandLineTemplateExceptionFactory.Create(template, null, - "Arguments must have a value name.", - "Missing value name."); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ConfiguratorExtensions.cs b/src/Spectre.Console.Cli/ConfiguratorExtensions.cs deleted file mode 100644 index 87f6272a0..000000000 --- a/src/Spectre.Console.Cli/ConfiguratorExtensions.cs +++ /dev/null @@ -1,437 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Contains extensions for -/// and . -/// -public static class ConfiguratorExtensions -{ - /// - /// Sets the help provider for the application. - /// - /// The configurator. - /// The help provider to use. - /// A configurator that can be used to configure the application further. - public static IConfigurator SetHelpProvider(this IConfigurator configurator, IHelpProvider helpProvider) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.SetHelpProvider(helpProvider); - return configurator; - } - - /// - /// Sets the help provider for the application. - /// - /// The configurator. - /// The type of the help provider to instantiate at runtime and use. - /// A configurator that can be used to configure the application further. - public static IConfigurator SetHelpProvider(this IConfigurator configurator) - where T : IHelpProvider - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.SetHelpProvider(); - return configurator; - } - - /// - /// Sets the culture for the application. - /// - /// The configurator. - /// The culture. - /// A configurator that can be used to configure the application further. - /// - /// Text displayed by can be localised, but defaults to English. - /// Setting the application culture informs the resource manager which culture to use when fetching strings. - /// English will be used when a culture has not been specified - /// or a string has not been localised for the specified culture. - /// - public static IConfigurator SetApplicationCulture(this IConfigurator configurator, CultureInfo? culture) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.Culture = culture; - return configurator; - } - - /// - /// Sets the name of the application. - /// - /// The configurator. - /// The name of the application. - /// A configurator that can be used to configure the application further. - public static IConfigurator SetApplicationName(this IConfigurator configurator, string name) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.ApplicationName = name; - return configurator; - } - - /// - /// Sets the version of the application. - /// - /// The configurator. - /// The version of application. - /// A configurator that can be used to configure the application further. - public static IConfigurator SetApplicationVersion(this IConfigurator configurator, string version) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.ApplicationVersion = version; - return configurator; - } - - /// - /// Uses the version retrieved from the - /// as the application's version. - /// - /// The configurator. - /// A configurator that can be used to configure the application further. - public static IConfigurator UseAssemblyInformationalVersion(this IConfigurator configurator) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.ApplicationVersion = - VersionHelper.GetVersion(Assembly.GetEntryAssembly()); - - return configurator; - } - - /// - /// Hides the DEFAULT column that lists default values coming from the - /// in the options help text. - /// - /// The configurator. - /// A configurator that can be used to configure the application further. - public static IConfigurator HideOptionDefaultValues(this IConfigurator configurator) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.ShowOptionDefaultValues = false; - return configurator; - } - - /// - /// Configures the console. - /// - /// The configurator. - /// The console. - /// A configurator that can be used to configure the application further. - public static IConfigurator ConfigureConsole(this IConfigurator configurator, IAnsiConsole console) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.Console = console; - return configurator; - } - - /// - /// Sets the parsing mode to strict. - /// - /// The configurator. - /// A configurator that can be used to configure the application further. - public static IConfigurator UseStrictParsing(this IConfigurator configurator) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.StrictParsing = true; - return configurator; - } - - /// - /// Tells the help provider whether or not to trim trailing period. - /// - /// The configurator. - /// True to trim trailing period (default), false to not. - /// A configurator that can be used to configure the application further. - public static IConfigurator TrimTrailingPeriods(this IConfigurator configurator, bool trimTrailingPeriods) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.TrimTrailingPeriod = trimTrailingPeriods; - return configurator; - } - - /// - /// Tells the command line application to propagate all - /// exceptions to the user. - /// - /// The configurator. - /// A configurator that can be used to configure the application further. - public static IConfigurator PropagateExceptions(this IConfigurator configurator) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.PropagateExceptions = true; - return configurator; - } - - /// - /// Tells the command line application to return the specified exit code when it's aborted through the . - /// The default cancellation exit code is 130. - /// - /// The configurator. - /// The exit code to return in case of cancellation. - /// A configurator that can be used to configure the application further. - public static IConfigurator CancellationExitCode(this IConfigurator configurator, int exitCode) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.CancellationExitCode = exitCode; - return configurator; - } - - /// - /// Configures case sensitivity. - /// - /// The configuration. - /// The case sensitivity. - /// A configurator that can be used to configure the application further. - public static IConfigurator CaseSensitivity(this IConfigurator configurator, CaseSensitivity sensitivity) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.CaseSensitivity = sensitivity; - return configurator; - } - - /// - /// Tells the command line application to validate all - /// examples before running the application. - /// - /// The configurator. - /// A configurator that can be used to configure the application further. - public static IConfigurator ValidateExamples(this IConfigurator configurator) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.ValidateExamples = true; - return configurator; - } - - /// - /// Sets the command interceptor to be used. - /// - /// The configurator. - /// A . - /// A configurator that can be used to configure the application further. - public static IConfigurator SetInterceptor(this IConfigurator configurator, ICommandInterceptor interceptor) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.Registrar.RegisterInstance(interceptor); - return configurator; - } - - /// - /// Adds a command branch. - /// - /// The configurator. - /// The name of the command branch. - /// The command branch configuration. - /// A branch configurator that can be used to configure the branch further. - public static IBranchConfigurator AddBranch( - this IConfigurator configurator, - string name, - Action> action) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - return configurator.AddBranch(name, action); - } - - /// - /// Adds a command branch. - /// - /// The command setting type. - /// The configurator. - /// The name of the command branch. - /// The command branch configuration. - /// A branch configurator that can be used to configure the branch further. - public static IBranchConfigurator AddBranch( - this IConfigurator configurator, - string name, - Action> action) - where TSettings : CommandSettings - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - return configurator.AddBranch(name, action); - } - - /// - /// Adds a command without settings that executes a delegate. - /// - /// The configurator. - /// The name of the command. - /// The delegate to execute as part of command execution. - /// A command configurator that can be used to configure the command further. - public static ICommandConfigurator AddDelegate( - this IConfigurator configurator, - string name, - Func func) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - return configurator.AddDelegate(name, (c, _, ct) => func(c, ct)); - } - - /// - /// Adds a command without settings that executes an async delegate. - /// - /// The configurator. - /// The name of the command. - /// The delegate to execute as part of command execution. - /// A command configurator that can be used to configure the command further. - public static ICommandConfigurator AddAsyncDelegate( - this IConfigurator configurator, - string name, - Func> func) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - return configurator.AddAsyncDelegate(name, (c, _, ct) => func(c, ct)); - } - - /// - /// Adds a command without settings that executes a delegate. - /// - /// The command setting type. - /// The configurator. - /// The name of the command. - /// The delegate to execute as part of command execution. - /// A command configurator that can be used to configure the command further. - public static ICommandConfigurator AddDelegate( - this IConfigurator? configurator, - string name, - Func func) - where TSettings : CommandSettings - { - if (typeof(TSettings).IsAbstract) - { - AddDelegate(configurator as IConfigurator, name, func); - } - - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - return configurator.AddDelegate(name, (c, _, ct) => func(c, ct)); - } - - /// - /// Adds a command without settings that executes an async delegate. - /// - /// The command setting type. - /// The configurator. - /// The name of the command. - /// The delegate to execute as part of command execution. - /// A command configurator that can be used to configure the command further. - public static ICommandConfigurator AddAsyncDelegate( - this IConfigurator configurator, - string name, - Func> func) - where TSettings : CommandSettings - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - return configurator.AddAsyncDelegate(name, (c, _, ct) => func(c, ct)); - } - - /// - /// Sets the ExceptionsHandler. - /// Setting this way will use the - /// default exit code of -1. - /// - /// The configurator. - /// The Action that handles the exception. - /// A configurator that can be used to configure the application further. - public static IConfigurator SetExceptionHandler(this IConfigurator configurator, Action exceptionHandler) - { - return configurator.SetExceptionHandler((ex, resolver) => - { - exceptionHandler(ex, resolver); - return -1; - }); - } - - /// - /// Sets the ExceptionsHandler. - /// - /// The configurator. - /// The Action that handles the exception. - /// A configurator that can be used to configure the application further. - public static IConfigurator SetExceptionHandler(this IConfigurator configurator, Func? exceptionHandler) - { - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - configurator.Settings.ExceptionHandler = exceptionHandler; - return configurator; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/EmptyCommandSettings.cs b/src/Spectre.Console.Cli/EmptyCommandSettings.cs deleted file mode 100644 index 7246c3ff3..000000000 --- a/src/Spectre.Console.Cli/EmptyCommandSettings.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents empty settings. -/// -public sealed class EmptyCommandSettings : CommandSettings -{ -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/FlagValue.cs b/src/Spectre.Console.Cli/FlagValue.cs deleted file mode 100644 index 8e295ced5..000000000 --- a/src/Spectre.Console.Cli/FlagValue.cs +++ /dev/null @@ -1,55 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Implementation of a flag with an optional value. -/// -/// The flag's element type. -public sealed class FlagValue : IFlagValue -{ - /// - /// Gets or sets a value indicating whether or not the flag was set or not. - /// - public bool IsSet { get; set; } - -#pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. - /// - /// Gets or sets the flag's value. - /// - public T Value { get; set; } -#pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. - - /// - Type IFlagValue.Type => typeof(T); - - /// - object? IFlagValue.Value - { - get => Value; - set - { -#pragma warning disable CS8601 // Possible null reference assignment. -#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. - Value = (T)value; -#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. -#pragma warning restore CS8601 // Possible null reference assignment. - } - } - - /// - public override string ToString() - { - var flag = (IFlagValue)this; - if (flag.Value != null) - { - return string.Format( - CultureInfo.InvariantCulture, - "Set={0}, Value={1}", - IsSet, - flag.Value.ToString()); - } - - return string.Format( - CultureInfo.InvariantCulture, - "Set={0}", IsSet); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Help/HelpProvider.cs b/src/Spectre.Console.Cli/Help/HelpProvider.cs deleted file mode 100644 index 58db0aa6a..000000000 --- a/src/Spectre.Console.Cli/Help/HelpProvider.cs +++ /dev/null @@ -1,620 +0,0 @@ -namespace Spectre.Console.Cli.Help; - -/// -/// The help provider for Spectre.Console. -/// -/// -/// Other IHelpProvider implementations can be injected into the CommandApp, if desired. -/// -public class HelpProvider : IHelpProvider -{ - private readonly HelpProviderResources resources; - private readonly HelpProviderStyle? helpStyles; - - /// - /// Gets a value indicating how many examples from direct children to show in the help text. - /// - protected virtual int MaximumIndirectExamples { get; } - - /// - /// Gets a value indicating whether any default values for command options are shown in the help text. - /// - protected virtual bool ShowOptionDefaultValues { get; } - - /// - /// Gets a value indicating whether a trailing period of a description is trimmed in the help text. - /// - protected virtual bool TrimTrailingPeriod { get; } - - /// - /// Gets a value indicating whether to emit the markup styles, inline, when rendering the help text. - /// - /// - /// Useful for unit testing different styling of the same help text. - /// - protected virtual bool RenderMarkupInline { get; } = false; - - private sealed class HelpArgument - { - public string Name { get; } - public int Position { get; set; } - public bool Required { get; } - public string? Description { get; } - - private HelpArgument(string name, int position, bool required, string? description) - { - Name = name; - Position = position; - Required = required; - Description = description; - } - - public static IReadOnlyList Get(ICommandInfo? command) - { - var arguments = new List(); - arguments.AddRange(command?.Parameters?.OfType()?.Select( - x => new HelpArgument(x.Value, x.Position, x.IsRequired, x.Description)) - ?? Array.Empty()); - return arguments; - } - } - - private sealed class HelpOption - { - public string? Short { get; } - public string? Long { get; } - public string? Value { get; } - public bool? ValueIsOptional { get; } - public bool IsRequired { get; } - public string? Description { get; } - public object? DefaultValue { get; } - - private HelpOption( - string? @short, string? @long, string? @value, - bool? valueIsOptional, bool isRequired, - string? description, object? defaultValue) - { - Short = @short; - Long = @long; - Value = value; - ValueIsOptional = valueIsOptional; - IsRequired = isRequired; - Description = description; - DefaultValue = defaultValue; - } - - public static IReadOnlyList Get( - ICommandModel model, - ICommandInfo? command, - HelpProviderResources resources) - { - var parameters = new List - { - new HelpOption("h", "help", null, null, false, - resources.PrintHelpDescription, null), - }; - - // Version information applies to the entire CLI application. - // Whether to show the "-v|--version" option in the help is determined as per: - // - If an application version has been set, and - // -- When at the root of the application, or - // -- When at the root of the application with a default command, unless - // --- The default command has a version option in its settings - if ((command?.Parent == null) && !(command?.IsBranch ?? false) && (command?.IsDefaultCommand ?? true)) - { - // Check whether the default command has a version option in its settings. - var versionCommandOption = command?.Parameters?.OfType()?.FirstOrDefault(o => - (o.ShortNames.FirstOrDefault(v => v.Equals("v", StringComparison.OrdinalIgnoreCase)) != null) || - (o.LongNames.FirstOrDefault(v => v.Equals("version", StringComparison.OrdinalIgnoreCase)) != null)); - - // Only show the version option if the default command doesn't have a version option in its settings. - if (versionCommandOption == null) - { - // Only show the version option if there is an application version set. - if (model.ApplicationVersion != null) - { - parameters.Add(new HelpOption("v", "version", null, null, false, - resources.PrintVersionDescription, null)); - } - } - } - - parameters.AddRange(command?.Parameters.OfType().Where(o => !o.IsHidden).Select(o => - new HelpOption( - o.ShortNames.FirstOrDefault(), o.LongNames.FirstOrDefault(), - o.ValueName, o.ValueIsOptional, o.IsRequired, o.Description, - o.IsFlag && o.DefaultValue?.Value is false ? null : o.DefaultValue?.Value)) - ?? Array.Empty()); - return parameters; - } - } - - /// - /// Initializes a new instance of the class. - /// - /// The command line application settings used for configuration. - public HelpProvider(ICommandAppSettings settings) - { - this.ShowOptionDefaultValues = settings.ShowOptionDefaultValues; - 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); - } - - /// - public virtual IEnumerable Write(ICommandModel model, ICommandInfo? command) - { - var result = new List(); - - result.AddRange(GetHeader(model, command)); - result.AddRange(GetDescription(model, command)); - result.AddRange(GetUsage(model, command)); - result.AddRange(GetExamples(model, command)); - result.AddRange(GetArguments(model, command)); - result.AddRange(GetOptions(model, command)); - result.AddRange(GetCommands(model, command)); - result.AddRange(GetFooter(model, command)); - - return result; - } - - /// - /// Gets the header for the help information. - /// - /// The command model to write help for. - /// The command for which to write help information (optional). - /// An enumerable collection of objects. - public virtual IEnumerable GetHeader(ICommandModel model, ICommandInfo? command) - { - yield break; - } - - /// - /// Gets the description section of the help information. - /// - /// The command model to write help for. - /// The command for which to write help information (optional). - /// An enumerable collection of objects. - public virtual IEnumerable GetDescription(ICommandModel model, ICommandInfo? command) - { - if (command?.Description == null) - { - yield break; - } - - var composer = NewComposer(); - composer.Style(helpStyles?.Description?.Header ?? Style.Plain, $"{resources.Description}:").LineBreak(); - composer.Text(NormalizeDescription(command.Description)).LineBreak(); - yield return composer.LineBreak(); - } - - /// - /// Gets the usage section of the help information. - /// - /// The command model to write help for. - /// The command for which to write help information (optional). - /// An enumerable collection of objects. - public virtual IEnumerable GetUsage(ICommandModel model, ICommandInfo? command) - { - var composer = NewComposer(); - composer.Style(helpStyles?.Usage?.Header ?? Style.Plain, $"{resources.Usage}:").LineBreak(); - composer.Tab().Text(model.ApplicationName); - - var parameters = new List(); - - if (command == null) - { - parameters.Add(NewComposer().Style(helpStyles?.Usage?.Options ?? Style.Plain, $"[{resources.Options}]")); - parameters.Add(NewComposer().Style(helpStyles?.Usage?.Command ?? Style.Plain, $"<{resources.Command}>")); - } - else - { - foreach (var current in command.Flatten()) - { - var isCurrent = current == command; - - if (!current.IsDefaultCommand) - { - if (isCurrent) - { - parameters.Add(NewComposer().Style( - helpStyles?.Usage?.CurrentCommand ?? Style.Plain, - $"{current.Name}")); - } - else - { - parameters.Add(NewComposer().Text(current.Name)); - } - } - - if (current.Parameters.OfType().Any()) - { - if (isCurrent) - { - foreach (var argument in current.Parameters.OfType() - .Where(a => a.IsRequired).OrderBy(a => a.Position).ToArray()) - { - parameters.Add(NewComposer().Style( - helpStyles?.Usage?.RequiredArgument ?? Style.Plain, - $"<{argument.Value}>")); - } - } - - var optionalArguments = current.Parameters.OfType().Where(x => !x.IsRequired) - .ToArray(); - if (optionalArguments.Length > 0 || !isCurrent) - { - foreach (var optionalArgument in optionalArguments) - { - parameters.Add(NewComposer().Style( - helpStyles?.Usage?.OptionalArgument ?? Style.Plain, - $"[{optionalArgument.Value}]")); - } - } - } - - if (isCurrent) - { - 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(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(NewComposer() - .Style(helpStyles?.Usage?.Command ?? Style.Plain, $"[{resources.Command}]")); - } - else if (command.IsDefaultCommand) - { - var commands = model.Commands.Where(x => !x.IsHidden && !x.IsDefaultCommand).ToList(); - - if (commands.Count > 0) - { - // Commands other than the default are present - // So make these optional in the usage statement - parameters.Add(NewComposer() - .Style(helpStyles?.Usage?.Command ?? Style.Plain, $"[{resources.Command}]")); - } - } - } - - composer.Join(" ", parameters); - composer.LineBreak(); - - return new[] { composer }; - } - - /// - /// Gets the examples section of the help information. - /// - /// The command model to write help for. - /// The command for which to write help information (optional). - /// An enumerable collection of objects. - /// - /// Examples from the command's direct children are used - /// if no examples have been set on the specified command or model. - /// - public virtual IEnumerable GetExamples(ICommandModel model, ICommandInfo? command) - { - var maxExamples = int.MaxValue; - - var examples = command?.Examples?.ToList() ?? model.Examples?.ToList() ?? new List(); - if (examples.Count == 0) - { - // Since we're not checking direct examples, - // make sure that we limit the number of examples. - maxExamples = MaximumIndirectExamples; - - // Start at the current command (if exists) - // or alternatively commence at the model. - var commandContainer = command ?? (ICommandContainer)model; - var queue = new Queue(new[] { commandContainer }); - - // Traverse the command tree and look for examples. - // As soon as a node contains commands, bail. - while (queue.Count > 0) - { - var current = queue.Dequeue(); - - foreach (var child in current.Commands.Where(x => !x.IsHidden)) - { - if (child.Examples.Count > 0) - { - examples.AddRange(child.Examples); - } - - queue.Enqueue(child); - } - - if (examples.Count >= maxExamples) - { - break; - } - } - } - - if (Math.Min(maxExamples, examples.Count) > 0) - { - var composer = NewComposer(); - composer.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(helpStyles?.Examples?.Arguments ?? Style.Plain, args); - composer.LineBreak(); - } - - return new[] { composer }; - } - - return Array.Empty(); - } - - /// - /// Gets the arguments section of the help information. - /// - /// The command model to write help for. - /// The command for which to write help information (optional). - /// An enumerable collection of objects. - public virtual IEnumerable GetArguments(ICommandModel model, ICommandInfo? command) - { - var arguments = HelpArgument.Get(command); - if (arguments.Count == 0) - { - return Array.Empty(); - } - - var result = new List - { - 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 }); - grid.AddColumn(new GridColumn { Padding = new Padding(0, 0) }); - - foreach (var argument in arguments.Where(x => x.Required).OrderBy(x => x.Position)) - { - grid.AddRow( - NewComposer().Style(helpStyles?.Arguments?.RequiredArgument ?? Style.Plain, $"<{argument.Name}>"), - NewComposer().Text(NormalizeDescription(argument.Description))); - } - - foreach (var argument in arguments.Where(x => !x.Required).OrderBy(x => x.Position)) - { - grid.AddRow( - NewComposer().Style(helpStyles?.Arguments?.OptionalArgument ?? Style.Plain, $"[{argument.Name}]"), - NewComposer().Text(NormalizeDescription(argument.Description))); - } - - result.Add(grid); - - return result; - } - - /// - /// Gets the options section of the help information. - /// - /// The command model to write help for. - /// The command for which to write help information (optional). - /// An enumerable collection of objects. - public virtual IEnumerable GetOptions(ICommandModel model, ICommandInfo? command) - { - // Collect all options into a single structure. - var parameters = HelpOption.Get(model, command, resources); - if (parameters.Count == 0) - { - return Array.Empty(); - } - - var result = new List - { - NewComposer().LineBreak().Style(helpStyles?.Options?.Header ?? Style.Plain, $"{resources.Options}:") - .LineBreak(), - }; - - var helpOptions = parameters.ToArray(); - var defaultValueColumn = ShowOptionDefaultValues && helpOptions.Any(e => e.DefaultValue != null); - - var grid = new Grid(); - grid.AddColumn(new GridColumn { Padding = new Padding(4, 4), NoWrap = true }); - if (defaultValueColumn) - { - grid.AddColumn(new GridColumn { Padding = new Padding(0, 0, 4, 0) }); - } - - grid.AddColumn(new GridColumn { Padding = new Padding(0, 0) }); - - if (defaultValueColumn) - { - grid.AddRow( - NewComposer().Space(), - NewComposer().Style(helpStyles?.Options?.DefaultValueHeader ?? Style.Plain, resources.Default), - NewComposer().Space()); - } - - foreach (var option in helpOptions) - { - var columns = new List() { GetOptionParts(option) }; - - if (defaultValueColumn) - { - columns.Add(GetDefaultValueForOption(option.DefaultValue)); - } - - var description = option.Description; - if (option.IsRequired) - { - description = string.IsNullOrWhiteSpace(description) - ? "[i]Required[/]" - : description.TrimEnd('.') + ". [i]Required[/]"; - } - - columns.Add(NewComposer().Text(NormalizeDescription(description))); - - grid.AddRow(columns.ToArray()); - } - - result.Add(grid); - - return result; - } - - /// - /// Gets the commands section of the help information. - /// - /// The command model to write help for. - /// The command for which to write help information (optional). - /// An enumerable collection of objects. - public virtual IEnumerable GetCommands(ICommandModel model, ICommandInfo? command) - { - var commandContainer = command ?? (ICommandContainer)model; - bool isDefaultCommand = command?.IsDefaultCommand ?? false; - - var commands = isDefaultCommand ? model.Commands : commandContainer.Commands; - commands = commands.Where(x => !x.IsHidden).ToList(); - - if (commands.Count == 0) - { - return Array.Empty(); - } - - var result = new List - { - 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 }); - grid.AddColumn(new GridColumn { Padding = new Padding(0, 0) }); - - foreach (var child in commands) - { - 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(helpStyles?.Commands?.RequiredArgument ?? Style.Plain, $"<{argument.Name}>"); - arguments.Space(); - } - - grid.AddRow( - NewComposer().Text(arguments.ToString().TrimEnd()), - NewComposer().Text(NormalizeDescription(child.Description))); - } - - result.Add(grid); - - return result; - } - - /// - /// Gets the footer for the help information. - /// - /// The command model to write help for. - /// The command for which to write help information (optional). - /// An enumerable collection of objects. - public virtual IEnumerable GetFooter(ICommandModel model, ICommandInfo? command) - { - yield break; - } - - private Composer NewComposer() - { - return new Composer(RenderMarkupInline); - } - - 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?.OptionalOptionValue ?? Style.Plain, $"[{option.Value}]"); - } - else - { - composer.Style(helpStyles?.Options?.RequiredOptionValue ?? Style.Plain, $"<{option.Value}>"); - } - } - - return composer; - } - - private Composer GetDefaultValueForOption(object? defaultValue) - { - return defaultValue switch - { - null => NewComposer().Text(" "), - "" => NewComposer().Text(" "), - Array { Length: 0 } => NewComposer().Text(" "), - Array array => NewComposer().Join( - ", ", - array.Cast().Select(o => - NewComposer().Style( - helpStyles?.Options?.DefaultValue ?? Style.Plain, - o.ToString() ?? string.Empty))), - _ => NewComposer().Style( - helpStyles?.Options?.DefaultValue ?? Style.Plain, - defaultValue?.ToString() ?? string.Empty), - }; - } - - private string NormalizeDescription(string? description) - { - if (description == null) - { - return " "; - } - - return TrimTrailingPeriod - ? description.TrimEnd('.') - : description; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Help/HelpProviderResources.cs b/src/Spectre.Console.Cli/Help/HelpProviderResources.cs deleted file mode 100644 index 890e24857..000000000 --- a/src/Spectre.Console.Cli/Help/HelpProviderResources.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System.Resources; - -namespace Spectre.Console.Cli.Help; - -/// -/// A strongly-typed resource class, for looking up localized strings, etc. -/// -internal class HelpProviderResources -{ - private readonly ResourceManager resourceManager = new ResourceManager("Spectre.Console.Cli.Resources.HelpProvider", typeof(HelpProvider).Assembly); - private readonly CultureInfo? resourceCulture = null; - - public HelpProviderResources() - { - } - - public HelpProviderResources(CultureInfo? culture) - { - resourceCulture = culture; - } - - /// - /// Gets the localised string for ARGUMENTS. - /// - internal string Arguments - { - get - { - return resourceManager.GetString("Arguments", resourceCulture) ?? string.Empty; - } - } - - /// - /// Gets the localised string for COMMAND. - /// - internal string Command - { - get - { - return resourceManager.GetString("Command", resourceCulture) ?? string.Empty; - } - } - - /// - /// Gets the localised string for COMMANDS. - /// - internal string Commands - { - get - { - return resourceManager.GetString("Commands", resourceCulture) ?? string.Empty; - } - } - - /// - /// Gets the localised string for DEFAULT. - /// - internal string Default - { - get - { - return resourceManager.GetString("Default", resourceCulture) ?? string.Empty; - } - } - - /// - /// Gets the localised string for DESCRIPTION. - /// - internal string Description - { - get - { - return resourceManager.GetString("Description", resourceCulture) ?? string.Empty; - } - } - - /// - /// Gets the localised string for EXAMPLES. - /// - internal string Examples - { - get - { - return resourceManager.GetString("Examples", resourceCulture) ?? string.Empty; - } - } - - /// - /// Gets the localised string for OPTIONS. - /// - internal string Options - { - get - { - return resourceManager.GetString("Options", resourceCulture) ?? string.Empty; - } - } - - /// - /// Gets the localised string for Prints help information. - /// - internal string PrintHelpDescription - { - get - { - return resourceManager.GetString("PrintHelpDescription", resourceCulture) ?? string.Empty; - } - } - - /// - /// Gets the localised string for Prints version information. - /// - internal string PrintVersionDescription - { - get - { - return resourceManager.GetString("PrintVersionDescription", resourceCulture) ?? string.Empty; - } - } - - /// - /// Gets the localised string for USAGE. - /// - internal string Usage - { - get - { - return resourceManager.GetString("Usage", resourceCulture) ?? string.Empty; - } - } -} diff --git a/src/Spectre.Console.Cli/Help/HelpProviderStyles.cs b/src/Spectre.Console.Cli/Help/HelpProviderStyles.cs deleted file mode 100644 index 474f45385..000000000 --- a/src/Spectre.Console.Cli/Help/HelpProviderStyles.cs +++ /dev/null @@ -1,224 +0,0 @@ -namespace Spectre.Console.Cli.Help; - -/// -/// Styles for the HelpProvider to use when rendering help text. -/// -public sealed class HelpProviderStyle -{ - /// - /// Gets or sets the style for describing the purpose or details of a command. - /// - public DescriptionStyle? Description { get; set; } - - /// - /// Gets or sets the style for specifying the usage format of a command. - /// - public UsageStyle? Usage { get; set; } - - /// - /// Gets or sets the style for providing examples of command usage. - /// - public ExampleStyle? Examples { get; set; } - - /// - /// Gets or sets the style for specifying arguments in a command. - /// - public ArgumentStyle? Arguments { get; set; } - - /// - /// Gets or sets the style for specifying options or flags in a command. - /// - public OptionStyle? Options { get; set; } - - /// - /// Gets or sets the style for specifying subcommands or nested commands. - /// - public CommandStyle? Commands { get; set; } - - /// - /// Gets the default HelpProvider styles. - /// - 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", - RequiredOptionValue = "silver", - OptionalOptionValue = "grey", - }, - }; -} - -/// -/// Defines styles for describing the purpose or details of a command. -/// -public sealed class DescriptionStyle -{ - /// - /// Gets or sets the style for the header in the description. - /// - public Style? Header { get; set; } -} - -/// -/// Defines styles for specifying the usage format of a command. -/// -public sealed class UsageStyle -{ - /// - /// Gets or sets the style for the header in the usage. - /// - public Style? Header { get; set; } - - /// - /// Gets or sets the style for the current command in the usage. - /// - public Style? CurrentCommand { get; set; } - - /// - /// Gets or sets the style for general commands in the usage. - /// - public Style? Command { get; set; } - - /// - /// Gets or sets the style for options in the usage. - /// - public Style? Options { get; set; } - - /// - /// Gets or sets the style for required arguments in the usage. - /// - public Style? RequiredArgument { get; set; } - - /// - /// Gets or sets the style for optional arguments in the usage. - /// - public Style? OptionalArgument { get; set; } -} - -/// -/// Defines styles for providing examples of command usage. -/// -public sealed class ExampleStyle -{ - /// - /// Gets or sets the style for the header in the examples. - /// - public Style? Header { get; set; } - - /// - /// Gets or sets the style for arguments in the examples. - /// - public Style? Arguments { get; set; } -} - -/// -/// Defines styles for specifying arguments in a command. -/// -public sealed class ArgumentStyle -{ - /// - /// Gets or sets the style for the header in the arguments. - /// - public Style? Header { get; set; } - - /// - /// Gets or sets the style for required arguments. - /// - public Style? RequiredArgument { get; set; } - - /// - /// Gets or sets the style for optional arguments. - /// - public Style? OptionalArgument { get; set; } -} - -/// -/// Defines styles for specifying subcommands or nested commands. -/// -public sealed class CommandStyle -{ - /// - /// Gets or sets the style for the header in the command section. - /// - public Style? Header { get; set; } - - /// - /// Gets or sets the style for child commands in the command section. - /// - public Style? ChildCommand { get; set; } - - /// - /// Gets or sets the style for required arguments in the command section. - /// - public Style? RequiredArgument { get; set; } -} - -/// -/// Defines styles for specifying options or flags in a command. -/// -public sealed class OptionStyle -{ - /// - /// Gets or sets the style for the header in the options. - /// - public Style? Header { get; set; } - - /// - /// Gets or sets the style for the header of default values in the options. - /// - public Style? DefaultValueHeader { get; set; } - - /// - /// Gets or sets the style for default values in the options. - /// - public Style? DefaultValue { get; set; } - - /// - /// Gets or sets the style for required options. - /// - public Style? RequiredOption { get; set; } - - /// - /// Gets or sets the style for required option values. - /// - public Style? RequiredOptionValue { get; set; } - - /// - /// Gets or sets the style for optional options. - /// - public Style? OptionalOptionValue { get; set; } -} diff --git a/src/Spectre.Console.Cli/Help/ICommandArgument.cs b/src/Spectre.Console.Cli/Help/ICommandArgument.cs deleted file mode 100644 index abf064913..000000000 --- a/src/Spectre.Console.Cli/Help/ICommandArgument.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Spectre.Console.Cli.Help; - -/// -/// Represents a command argument. -/// -public interface ICommandArgument : ICommandParameter -{ - /// - /// Gets the value of the argument. - /// - string Value { get; } - - /// - /// Gets the position of the argument. - /// - int Position { get; } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Help/ICommandContainer.cs b/src/Spectre.Console.Cli/Help/ICommandContainer.cs deleted file mode 100644 index 6eccb8d64..000000000 --- a/src/Spectre.Console.Cli/Help/ICommandContainer.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Spectre.Console.Cli.Help; - -/// -/// Represents a command container. -/// -public interface ICommandContainer -{ - /// - /// Gets all the examples for the container. - /// - IReadOnlyList Examples { get; } - - /// - /// Gets all commands in the container. - /// - IReadOnlyList Commands { get; } - - /// - /// Gets the default command for the container. - /// - /// - /// Returns null if a default command has not been set. - /// - ICommandInfo? DefaultCommand { get; } -} diff --git a/src/Spectre.Console.Cli/Help/ICommandInfo.cs b/src/Spectre.Console.Cli/Help/ICommandInfo.cs deleted file mode 100644 index 9adb16f66..000000000 --- a/src/Spectre.Console.Cli/Help/ICommandInfo.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace Spectre.Console.Cli.Help; - -/// -/// Represents an executable command. -/// -public interface ICommandInfo : ICommandContainer -{ - /// - /// Gets the name of the command. - /// - string Name { get; } - - /// - /// Gets the description of the command. - /// - string? Description { get; } - - /// - /// Gets a value indicating whether the command is a branch. - /// - bool IsBranch { get; } - - /// - /// Gets a value indicating whether the command is the default command within its container. - /// - bool IsDefaultCommand { get; } - - /// - /// Gets a value indicating whether the command is hidden. - /// - bool IsHidden { get; } - - /// - /// Gets the parameters associated with the command. - /// - IReadOnlyList Parameters { get; } - - /// - /// Gets the parent command, if any. - /// - ICommandInfo? Parent { get; } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Help/ICommandInfoExtensions.cs b/src/Spectre.Console.Cli/Help/ICommandInfoExtensions.cs deleted file mode 100644 index 3f54f8ddc..000000000 --- a/src/Spectre.Console.Cli/Help/ICommandInfoExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Spectre.Console.Cli.Help; - -internal static class ICommandInfoExtensions -{ - /// - /// Walks up the command.Parent tree, adding each command into a list as it goes. - /// - /// The first command added to the list is the current (ie. this one). - /// The list of commands from current to root, as traversed by . - public static List Flatten(this ICommandInfo commandInfo) - { - var result = new Stack(); - - var current = commandInfo; - while (current != null) - { - result.Push(current); - current = current.Parent; - } - - return result.ToList(); - } -} diff --git a/src/Spectre.Console.Cli/Help/ICommandModel.cs b/src/Spectre.Console.Cli/Help/ICommandModel.cs deleted file mode 100644 index 2872bf889..000000000 --- a/src/Spectre.Console.Cli/Help/ICommandModel.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Spectre.Console.Cli.Help; - -/// -/// Represents a command model. -/// -public interface ICommandModel : ICommandContainer -{ - /// - /// Gets the name of the application. - /// - string ApplicationName { get; } - - /// - /// Gets the version of the application. - /// - string? ApplicationVersion { get; } -} diff --git a/src/Spectre.Console.Cli/Help/ICommandOption.cs b/src/Spectre.Console.Cli/Help/ICommandOption.cs deleted file mode 100644 index e6c351732..000000000 --- a/src/Spectre.Console.Cli/Help/ICommandOption.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Spectre.Console.Cli.Help; - -/// -/// Represents a command option. -/// -public interface ICommandOption : ICommandParameter -{ - /// - /// Gets the long names of the option. - /// - IReadOnlyList LongNames { get; } - - /// - /// Gets the short names of the option. - /// - IReadOnlyList ShortNames { get; } - - /// - /// Gets the value name of the option, if applicable. - /// - string? ValueName { get; } - - /// - /// Gets a value indicating whether the option value is optional. - /// - bool ValueIsOptional { get; } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Help/ICommandParameter.cs b/src/Spectre.Console.Cli/Help/ICommandParameter.cs deleted file mode 100644 index 1177f861d..000000000 --- a/src/Spectre.Console.Cli/Help/ICommandParameter.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace Spectre.Console.Cli.Help; - -/// -/// Represents a command parameter. -/// -public interface ICommandParameter -{ - /// - /// Gets a value indicating whether the parameter is a flag. - /// - bool IsFlag { get; } - - /// - /// Gets a value indicating whether the parameter is required. - /// - bool IsRequired { get; } - - /// - /// Gets the description of the parameter. - /// - string? Description { get; } - - /// - /// Gets the default value of the parameter, if specified. - /// - DefaultValueAttribute? DefaultValue { get; } - - /// - /// Gets a value indicating whether the parameter is hidden. - /// - bool IsHidden { get; } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Help/IHelpProvider.cs b/src/Spectre.Console.Cli/Help/IHelpProvider.cs deleted file mode 100644 index bca3c8780..000000000 --- a/src/Spectre.Console.Cli/Help/IHelpProvider.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Spectre.Console.Cli.Help; - -/// -/// The help provider interface for Spectre.Console. -/// -/// -/// Implementations of this interface are responsbile -/// for writing command help to the terminal when the -/// `-h` or `--help` has been specified on the command line. -/// -public interface IHelpProvider -{ - /// - /// Writes help information for the application. - /// - /// The command model to write help for. - /// The command for which to write help information (optional). - /// An enumerable collection of objects representing the help information. - IEnumerable Write(ICommandModel model, ICommandInfo? command); -} diff --git a/src/Spectre.Console.Cli/IBranchConfigurator.cs b/src/Spectre.Console.Cli/IBranchConfigurator.cs deleted file mode 100644 index 2b8a44bdf..000000000 --- a/src/Spectre.Console.Cli/IBranchConfigurator.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a branch configurator. -/// -public interface IBranchConfigurator -{ - /// - /// Adds an alias (an alternative name) to the branch being configured. - /// - /// The alias to add to the branch being configured. - /// The same instance so that multiple calls can be chained. - IBranchConfigurator WithAlias(string name); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ICommand.cs b/src/Spectre.Console.Cli/ICommand.cs deleted file mode 100644 index 90ce2caf8..000000000 --- a/src/Spectre.Console.Cli/ICommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a command. -/// -public interface ICommand -{ - /// - /// Validates the specified settings and remaining arguments. - /// - /// The command context. - /// The settings. - /// The validation result. - ValidationResult Validate(CommandContext context, CommandSettings settings); - - /// - /// Executes the command. - /// - /// The command context. - /// The settings. - /// A that can be used to abort the command. - /// The validation result. - Task ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ICommandApp.cs b/src/Spectre.Console.Cli/ICommandApp.cs deleted file mode 100644 index 381a2812d..000000000 --- a/src/Spectre.Console.Cli/ICommandApp.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a command line application. -/// -public interface ICommandApp -{ - /// - /// Configures the command line application. - /// - /// The configuration. - void Configure(Action configuration); - - /// - /// Runs the command line application with specified arguments. - /// - /// The arguments. - /// A that can be used to abort the application. - /// The exit code from the executed command. - int Run(IEnumerable args, CancellationToken cancellationToken = default); - - /// - /// Runs the command line application with specified arguments. - /// - /// The arguments. - /// A that can be used to abort the application. - /// The exit code from the executed command. - Task RunAsync(IEnumerable args, CancellationToken cancellationToken = default); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ICommandAppSettings.cs b/src/Spectre.Console.Cli/ICommandAppSettings.cs deleted file mode 100644 index d0e78517d..000000000 --- a/src/Spectre.Console.Cli/ICommandAppSettings.cs +++ /dev/null @@ -1,109 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a command line application settings. -/// -public interface ICommandAppSettings -{ - /// - /// Gets or sets the culture. - /// - /// - /// Text displayed by can be localised, but defaults to English. - /// Setting this property informs the resource manager which culture to use when fetching strings. - /// English will be used when a culture has not been specified (ie. this property is null) - /// or a string has not been localised for the specified culture. - /// - CultureInfo? Culture { get; set; } - - /// - /// Gets or sets the application name. - /// - string? ApplicationName { get; set; } - - /// - /// Gets or sets the application version (use it to override auto-detected value). - /// - string? ApplicationVersion { get; set; } - - /// - /// Gets or sets a value indicating how many examples from direct children to show in the help text. - /// - int MaximumIndirectExamples { get; set; } - - /// - /// Gets or sets a value indicating whether any default values for command options are shown in the help text. - /// - bool ShowOptionDefaultValues { get; set; } - - /// - /// Gets or sets a value indicating whether a trailing period of a description is trimmed in the help text. - /// - bool TrimTrailingPeriod { get; set; } - - /// - /// Gets or sets the styles to used when rendering the help text. - /// - HelpProviderStyle? HelpProviderStyles { get; set; } - - /// - /// Gets or sets the . - /// - IAnsiConsole? Console { get; set; } - - /// - /// Gets or sets the used - /// to intercept settings before it's being sent to the command. - /// - [Obsolete("Register the interceptor with the ITypeRegistrar.")] - ICommandInterceptor? Interceptor { get; set; } - - /// - /// Gets the type registrar. - /// - ITypeRegistrarFrontend Registrar { get; } - - /// - /// Gets or sets case sensitivity. - /// - CaseSensitivity CaseSensitivity { get; set; } - - /// - /// Gets or sets a value indicating whether or not parsing is strict. - /// - bool StrictParsing { get; set; } - - /// - /// Gets or sets a value indicating whether or not flags found on the command line - /// that would normally result in a being thrown - /// during parsing with the message "Flags cannot be assigned a value." - /// should instead be added to the remaining arguments collection. - /// - bool ConvertFlagsToRemainingArguments { get; set; } - - /// - /// Gets or sets a value indicating whether or not exceptions should be propagated. - /// Setting this to true will disable default Exception handling and - /// any , if set. - /// - bool PropagateExceptions { get; set; } - - /// - /// Gets or sets the value used as the application exit code when it's aborted through the . - /// The default cancellation exit code is 130. - /// - int CancellationExitCode { get; set; } - - /// - /// Gets or sets a value indicating whether or not examples should be validated. - /// - bool ValidateExamples { get; set; } - - /// - /// Gets or sets a handler for Exceptions. - /// This handler will not be called, if is set to true. - /// The argument will only be not-null, when the exception occurs during execution of - /// a command. I.e. only when the resolver is available. - /// - public Func? ExceptionHandler { get; set; } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ICommandConfigurator.cs b/src/Spectre.Console.Cli/ICommandConfigurator.cs deleted file mode 100644 index 37beb0037..000000000 --- a/src/Spectre.Console.Cli/ICommandConfigurator.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a command configurator. -/// -public interface ICommandConfigurator -{ - /// - /// Adds an example of how to use the command. - /// - /// The example arguments. - /// The same instance so that multiple calls can be chained. - ICommandConfigurator WithExample(params string[] args); - - /// - /// Adds an alias (an alternative name) to the command being configured. - /// - /// The alias to add to the command being configured. - /// The same instance so that multiple calls can be chained. - ICommandConfigurator WithAlias(string name); - - /// - /// Sets the description of the command. - /// - /// The command description. - /// The same instance so that multiple calls can be chained. - ICommandConfigurator WithDescription(string description); - - /// - /// Sets data that will be passed to the command via the . - /// - /// The data to pass to the command. - /// The same instance so that multiple calls can be chained. - ICommandConfigurator WithData(object data); - - /// - /// Marks the command as hidden. - /// Hidden commands do not show up in help documentation or - /// generated XML models. - /// - /// The same instance so that multiple calls can be chained. - ICommandConfigurator IsHidden(); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ICommandInterceptor.cs b/src/Spectre.Console.Cli/ICommandInterceptor.cs deleted file mode 100644 index b2b963425..000000000 --- a/src/Spectre.Console.Cli/ICommandInterceptor.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a command settings interceptor that -/// will intercept command settings before it's -/// passed to a command. -/// -public interface ICommandInterceptor -{ - /// - /// Intercepts command information before it's passed to a command. - /// - /// The intercepted . - /// The intercepted . - void Intercept(CommandContext context, CommandSettings settings) -#if NETSTANDARD2_0 - ; -#else - { - } -#endif - - /// - /// Intercepts a command result before it's passed as the result. - /// - /// The intercepted . - /// The intercepted . - /// The result from the command execution. - void InterceptResult(CommandContext context, CommandSettings settings, ref int result) -#if NETSTANDARD2_0 - ; -#else - { - } -#endif -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ICommandLimiterOfT.cs b/src/Spectre.Console.Cli/ICommandLimiterOfT.cs deleted file mode 100644 index 5291b6f73..000000000 --- a/src/Spectre.Console.Cli/ICommandLimiterOfT.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a command limiter. -/// -/// The type of the settings to limit to. -/// -public interface ICommandLimiter : ICommand - where TSettings : CommandSettings -{ -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ICommandOfT.cs b/src/Spectre.Console.Cli/ICommandOfT.cs deleted file mode 100644 index bb3b03eec..000000000 --- a/src/Spectre.Console.Cli/ICommandOfT.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a command. -/// -/// The settings type. -public interface ICommand : ICommandLimiter - where TSettings : CommandSettings -{ - /// - /// Executes the command. - /// - /// The command context. - /// The settings. - /// A that can be used to abort the command. - /// An integer indicating whether or not the command executed successfully. - Task ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ICommandParameterInfo.cs b/src/Spectre.Console.Cli/ICommandParameterInfo.cs deleted file mode 100644 index b6483eff4..000000000 --- a/src/Spectre.Console.Cli/ICommandParameterInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a command parameter. -/// -public interface ICommandParameterInfo -{ - /// - /// Gets the property name. - /// - /// The property name. - public string PropertyName { get; } - - /// - /// Gets the parameter type. - /// - public Type ParameterType { get; } - - /// - /// Gets the description. - /// - /// The description. - public string? Description { get; } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/IConfigurator.cs b/src/Spectre.Console.Cli/IConfigurator.cs deleted file mode 100644 index ec4051c01..000000000 --- a/src/Spectre.Console.Cli/IConfigurator.cs +++ /dev/null @@ -1,73 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a configurator. -/// -public interface IConfigurator -{ - /// - /// Sets the help provider for the application. - /// - /// The help provider to use. - /// A configurator that can be used for further configuration. - public IConfigurator SetHelpProvider(IHelpProvider helpProvider); - - /// - /// Sets the help provider for the application. - /// - /// The type of the help provider to instantiate at runtime and use. - /// A configurator that can be used for further configuration. - public IConfigurator SetHelpProvider() - where T : IHelpProvider; - - /// - /// Gets the command app settings. - /// - public ICommandAppSettings Settings { get; } - - /// - /// Adds an example of how to use the application. - /// - /// The example arguments. - /// A configurator that can be used for further configuration. - IConfigurator AddExample(params string[] args); - - /// - /// Adds a command. - /// - /// The command type. - /// The name of the command. - /// A command configurator that can be used to configure the command further. - ICommandConfigurator AddCommand(string name) - where TCommand : class, ICommand; - - /// - /// Adds a command that executes a delegate. - /// - /// The command setting type. - /// The name of the command. - /// The delegate to execute as part of command execution. - /// A command configurator that can be used to configure the command further. - ICommandConfigurator AddDelegate(string name, Func func) - where TSettings : CommandSettings; - - /// - /// Adds a command that executes an async delegate. - /// - /// The command setting type. - /// The name of the command. - /// The delegate to execute as part of command execution. - /// A command configurator that can be used to configure the command further. - ICommandConfigurator AddAsyncDelegate(string name, Func> func) - where TSettings : CommandSettings; - - /// - /// Adds a command branch. - /// - /// The command setting type. - /// The name of the command branch. - /// The command branch configurator. - /// A branch configurator that can be used to configure the branch further. - IBranchConfigurator AddBranch(string name, Action> action) - where TSettings : CommandSettings; -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/IConfiguratorOfT.cs b/src/Spectre.Console.Cli/IConfiguratorOfT.cs deleted file mode 100644 index 7c0b26f23..000000000 --- a/src/Spectre.Console.Cli/IConfiguratorOfT.cs +++ /dev/null @@ -1,79 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a configurator for specific settings. -/// -/// The command setting type. -public interface IConfigurator - where TSettings : CommandSettings -{ - /// - /// Sets the description of the branch. - /// - /// The description of the branch. - void SetDescription(string description); - - /// - /// Adds an example of how to use the branch. - /// - /// The example arguments. - void AddExample(params string[] args); - - /// - /// Adds a default command. - /// - /// - /// This is the command that will run if the user doesn't specify one on the command line. - /// It must be able to execute successfully by itself ie. without requiring any command line - /// arguments, flags or option values. - /// - /// The default command type. - void SetDefaultCommand() - where TDefaultCommand : class, ICommandLimiter; - - /// - /// Marks the branch as hidden. - /// Hidden branches do not show up in help documentation or - /// generated XML models. - /// - void HideBranch(); - - /// - /// Adds a command. - /// - /// The command type. - /// The name of the command. - /// A command configurator that can be used to configure the command further. - ICommandConfigurator AddCommand(string name) - where TCommand : class, ICommandLimiter; - - /// - /// Adds a command that executes a delegate. - /// - /// The derived command setting type. - /// The name of the command. - /// The delegate to execute as part of command execution. - /// A command configurator that can be used to configure the command further. - ICommandConfigurator AddDelegate(string name, Func func) - where TDerivedSettings : TSettings; - - /// - /// Adds a command that executes an async delegate. - /// - /// The derived command setting type. - /// The name of the command. - /// The delegate to execute as part of command execution. - /// A command configurator that can be used to configure the command further. - ICommandConfigurator AddAsyncDelegate(string name, Func> func) - where TDerivedSettings : TSettings; - - /// - /// Adds a command branch. - /// - /// The derived command setting type. - /// The name of the command branch. - /// The command branch configuration. - /// A branch configurator that can be used to configure the branch further. - IBranchConfigurator AddBranch(string name, Action> action) - where TDerivedSettings : TSettings; -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/IFlagValue.cs b/src/Spectre.Console.Cli/IFlagValue.cs deleted file mode 100644 index 04633194f..000000000 --- a/src/Spectre.Console.Cli/IFlagValue.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a flag with an optional value. -/// -public interface IFlagValue -{ - /// - /// Gets or sets a value indicating whether or not the flag was set or not. - /// - bool IsSet { get; set; } - - /// - /// Gets the flag's element type. - /// - Type Type { get; } - - /// - /// Gets or sets the flag's value. - /// - object? Value { get; set; } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/IRemainingArguments.cs b/src/Spectre.Console.Cli/IRemainingArguments.cs deleted file mode 100644 index acd3b6055..000000000 --- a/src/Spectre.Console.Cli/IRemainingArguments.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents the remaining arguments. -/// -public interface IRemainingArguments -{ - /// - /// Gets the parsed remaining arguments. - /// - ILookup Parsed { get; } - - /// - /// Gets the raw, non-parsed remaining arguments. - /// This is normally everything after the `--` delimiter. - /// - IReadOnlyList Raw { get; } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ITypeRegistrar.cs b/src/Spectre.Console.Cli/ITypeRegistrar.cs deleted file mode 100644 index 0feea7e3f..000000000 --- a/src/Spectre.Console.Cli/ITypeRegistrar.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a type registrar. -/// -public interface ITypeRegistrar -{ - /// - /// Registers the specified service. - /// - /// The service. - /// The implementation. - void Register(Type service, Type implementation); - - /// - /// Registers the specified instance. - /// - /// The service. - /// The implementation. - void RegisterInstance(Type service, object implementation); - - /// - /// Registers the specified instance lazily. - /// - /// The service. - /// The factory that creates the implementation. - void RegisterLazy(Type service, Func factory); - - /// - /// Builds the type resolver representing the registrations - /// specified in the current instance. - /// - /// A type resolver. - ITypeResolver Build(); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ITypeRegistrarFrontend.cs b/src/Spectre.Console.Cli/ITypeRegistrarFrontend.cs deleted file mode 100644 index dbe955e2e..000000000 --- a/src/Spectre.Console.Cli/ITypeRegistrarFrontend.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a user friendly frontend for a . -/// -public interface ITypeRegistrarFrontend -{ - /// - /// Registers the type with the type registrar as a singleton. - /// - /// The exposed service type. - /// The implementing type. - void Register() - where TImplementation : TService; - - /// - /// Registers the specified instance with the type registrar as a singleton. - /// - /// The type of the instance. - /// The instance to register. - void RegisterInstance(TImplementation instance); - - /// - /// Registers the specified instance with the type registrar as a singleton. - /// - /// The exposed service type. - /// implementing type. - /// The instance to register. - void RegisterInstance(TImplementation instance) - where TImplementation : TService; -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/ITypeResolver.cs b/src/Spectre.Console.Cli/ITypeResolver.cs deleted file mode 100644 index fbfa90453..000000000 --- a/src/Spectre.Console.Cli/ITypeResolver.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a type resolver. -/// -public interface ITypeResolver -{ - /// - /// Resolves an instance of the specified type. - /// - /// The type to resolve. - /// An instance of the specified type, or null if no registration for the specified type exists. - object? Resolve(Type? type); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Binding/CommandConstructorBinder.cs b/src/Spectre.Console.Cli/Internal/Binding/CommandConstructorBinder.cs deleted file mode 100644 index 83c877e30..000000000 --- a/src/Spectre.Console.Cli/Internal/Binding/CommandConstructorBinder.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandConstructorBinder -{ - public static CommandSettings CreateSettings(CommandValueLookup lookup, ConstructorInfo constructor, ITypeResolver resolver) - { - if (constructor.DeclaringType == null) - { - throw new InvalidOperationException("Cannot create settings since constructor have no declaring type."); - } - - var parameters = new List(); - var mapped = new HashSet(); - foreach (var parameter in constructor.GetParameters()) - { - if (lookup.TryGetParameterWithName(parameter.Name, out var result)) - { - parameters.Add(result.Value); - mapped.Add(result.Parameter.Id); - } - else - { - var value = resolver.Resolve(parameter.ParameterType); - if (value == null) - { - throw CommandRuntimeException.CouldNotResolveType(parameter.ParameterType); - } - - parameters.Add(value); - } - } - - // Create the settings. - if (!(Activator.CreateInstance(constructor.DeclaringType, parameters.ToArray()) is CommandSettings settings)) - { - throw new InvalidOperationException("Could not create settings"); - } - - // Try to do property injection for parameters that wasn't injected. - foreach (var (parameter, value) in lookup) - { - if (!mapped.Contains(parameter.Id) && parameter.Property.SetMethod != null) - { - parameter.Property.SetValue(settings, value); - } - } - - // Validate the settings. - var validationResult = settings.Validate(); - if (!validationResult.Successful) - { - throw CommandRuntimeException.ValidationFailed(validationResult); - } - - return settings; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Binding/CommandPropertyBinder.cs b/src/Spectre.Console.Cli/Internal/Binding/CommandPropertyBinder.cs deleted file mode 100644 index 31cbf5b0d..000000000 --- a/src/Spectre.Console.Cli/Internal/Binding/CommandPropertyBinder.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandPropertyBinder -{ - public static CommandSettings CreateSettings(CommandValueLookup lookup, Type settingsType, ITypeResolver resolver) - { - var settings = CreateSettings(resolver, settingsType); - - foreach (var (parameter, value) in lookup) - { - if (value != default) - { - parameter.Property.SetValue(settings, value); - } - } - - // Validate the settings. - var validationResult = settings.Validate(); - if (!validationResult.Successful) - { - throw CommandRuntimeException.ValidationFailed(validationResult); - } - - return settings; - } - - private static CommandSettings CreateSettings(ITypeResolver resolver, Type settingsType) - { - if (resolver.Resolve(settingsType) is CommandSettings settings) - { - return settings; - } - - if (Activator.CreateInstance(settingsType) is CommandSettings instance) - { - return instance; - } - - throw CommandParseException.CouldNotCreateSettings(settingsType); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Binding/CommandValueBinder.cs b/src/Spectre.Console.Cli/Internal/Binding/CommandValueBinder.cs deleted file mode 100644 index 8dfbee45d..000000000 --- a/src/Spectre.Console.Cli/Internal/Binding/CommandValueBinder.cs +++ /dev/null @@ -1,120 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandValueBinder -{ - private readonly CommandValueLookup _lookup; - - public CommandValueBinder(CommandValueLookup lookup) - { - _lookup = lookup; - } - - public void Bind(CommandParameter parameter, ITypeResolver resolver, object? value) - { - if (parameter.ParameterKind == ParameterKind.Pair) - { - value = GetLookup(parameter, resolver, value); - } - else if (parameter.ParameterKind == ParameterKind.Vector) - { - value = GetArray(parameter, value); - } - else if (parameter.ParameterKind == ParameterKind.FlagWithValue) - { - value = GetFlag(parameter, value); - } - - _lookup.SetValue(parameter, value); - } - - private object GetLookup(CommandParameter parameter, ITypeResolver resolver, object? value) - { - var genericTypes = parameter.Property.PropertyType.GetGenericArguments(); - - var multimap = (IMultiMap?)_lookup.GetValue(parameter); - if (multimap == null) - { - multimap = Activator.CreateInstance(typeof(MultiMap<,>).MakeGenericType(genericTypes[0], genericTypes[1])) as IMultiMap; - if (multimap == null) - { - throw new InvalidOperationException("Could not create multimap"); - } - } - - // Create deconstructor. - var deconstructorType = parameter.PairDeconstructor?.Type ?? typeof(DefaultPairDeconstructor); - if (!(resolver.Resolve(deconstructorType) is IPairDeconstructor deconstructor)) - { - if (!(Activator.CreateInstance(deconstructorType) is IPairDeconstructor activatedDeconstructor)) - { - throw new InvalidOperationException($"Could not create pair deconstructor."); - } - - deconstructor = activatedDeconstructor; - } - - // Deconstruct and add to multimap. - var pair = deconstructor.Deconstruct(resolver, genericTypes[0], genericTypes[1], value as string); - if (pair.Key != null) - { - multimap.Add(pair); - } - - return multimap; - } - - private object GetArray(CommandParameter parameter, object? value) - { - if (value is Array) - { - return value; - } - - // Add a new item to the array - var array = (Array?)_lookup.GetValue(parameter); - Array newArray; - - var elementType = parameter.Property.PropertyType.GetElementType(); - if (elementType == null) - { - throw new InvalidOperationException("Could not get property type."); - } - - if (array == null) - { - newArray = Array.CreateInstance(elementType, 1); - } - else - { - newArray = Array.CreateInstance(elementType, array.Length + 1); - array.CopyTo(newArray, 0); - } - - newArray.SetValue(value, newArray.Length - 1); - return newArray; - } - - private object GetFlag(CommandParameter parameter, object? value) - { - var flagValue = (IFlagValue?)_lookup.GetValue(parameter); - if (flagValue == null) - { - flagValue = (IFlagValue?)Activator.CreateInstance(parameter.ParameterType); - if (flagValue == null) - { - throw new InvalidOperationException("Could not create flag value."); - } - } - - if (value != null) - { - // Null means set, but not with a valid value. - flagValue.Value = value; - } - - // If the parameter was mapped, then it's set. - flagValue.IsSet = true; - - return flagValue; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Binding/CommandValueLookup.cs b/src/Spectre.Console.Cli/Internal/Binding/CommandValueLookup.cs deleted file mode 100644 index f41f77b3b..000000000 --- a/src/Spectre.Console.Cli/Internal/Binding/CommandValueLookup.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandValueLookup : IEnumerable<(CommandParameter Parameter, object? Value)> -{ - private readonly Dictionary _lookup; - - public CommandValueLookup() - { - _lookup = new Dictionary(); - } - - public IEnumerator<(CommandParameter Parameter, object? Value)> GetEnumerator() - { - foreach (var pair in _lookup) - { - yield return pair.Value; - } - } - - public bool HasParameterWithName(string? name) - { - if (name == null) - { - return false; - } - - return _lookup.Values.Any(pair => pair.Parameter.PropertyName.Equals(name, StringComparison.OrdinalIgnoreCase)); - } - - public bool TryGetParameterWithName(string? name, out (CommandParameter Parameter, object? Value) result) - { - if (HasParameterWithName(name)) - { - result = _lookup.Values.FirstOrDefault(pair => pair.Parameter.PropertyName.Equals(name, StringComparison.OrdinalIgnoreCase)); - return true; - } - - result = default; - return false; - } - - public object? GetValue(CommandParameter parameter) - { - _lookup.TryGetValue(parameter.Id, out var result); - return result.Value; - } - - public void SetValue(CommandParameter parameter, object? value) - { - _lookup[parameter.Id] = (parameter, value); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Binding/CommandValueResolver.cs b/src/Spectre.Console.Cli/Internal/Binding/CommandValueResolver.cs deleted file mode 100644 index 4d817569f..000000000 --- a/src/Spectre.Console.Cli/Internal/Binding/CommandValueResolver.cs +++ /dev/null @@ -1,229 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandValueResolver -{ - public static CommandValueLookup GetParameterValues(CommandTree? tree, ITypeResolver resolver) - { - var lookup = new CommandValueLookup(); - var binder = new CommandValueBinder(lookup); - - CommandValidator.ValidateRequiredParameters(tree); - - while (tree != null) - { - // Process unmapped parameters. - foreach (var parameter in tree.Unmapped) - { - // Got a value provider? - if (parameter.ValueProvider != null) - { - var context = new CommandParameterContext(parameter, resolver, null); - if (parameter.ValueProvider.TryGetValue(context, out var result)) - { - result = ConvertValue(resolver, lookup, binder, parameter, result); - - lookup.SetValue(parameter, result); - CommandValidator.ValidateParameter(parameter, lookup, resolver); - continue; - } - } - - if (parameter.IsFlagValue()) - { - // Set the flag value to an empty, not set instance. - var instance = Activator.CreateInstance(parameter.ParameterType); - lookup.SetValue(parameter, instance); - } - else - { - // Is this an option with a default value? - if (parameter.DefaultValue != null) - { - var value = parameter.DefaultValue?.Value; - value = ConvertValue(resolver, lookup, binder, parameter, value); - - binder.Bind(parameter, resolver, value); - CommandValidator.ValidateParameter(parameter, lookup, resolver); - } - else if (Nullable.GetUnderlyingType(parameter.ParameterType) != null || - !parameter.ParameterType.IsValueType) - { - lookup.SetValue(parameter, null); - } - } - } - - // Process mapped parameters. - foreach (var mapped in tree.Mapped) - { - if (mapped.Parameter.WantRawValue) - { - // Just try to assign the raw value. - binder.Bind(mapped.Parameter, resolver, mapped.Value); - } - else - { - if (mapped.Parameter.IsFlagValue() && mapped.Value == null) - { - if (mapped.Parameter is CommandOption option && option.DefaultValue != null) - { - // Set the default value. - binder.Bind(mapped.Parameter, resolver, option.DefaultValue?.Value); - } - else - { - // Set the flag but not the value. - binder.Bind(mapped.Parameter, resolver, null); - } - } - else - { - object? value; - var converter = GetConverter(lookup, binder, resolver, mapped.Parameter); - var mappedValue = mapped.Value ?? string.Empty; - try - { - value = converter.ConvertFrom(mappedValue); - } - catch (Exception exception) when (exception is not CommandRuntimeException) - { - throw CommandRuntimeException.ConversionFailed(mapped, converter.TypeConverter, exception); - } - - // Assign the value to the parameter. - binder.Bind(mapped.Parameter, resolver, value); - } - } - - // Got a value provider? - if (mapped.Parameter.ValueProvider != null) - { - var context = new CommandParameterContext(mapped.Parameter, resolver, mapped.Value); - if (mapped.Parameter.ValueProvider.TryGetValue(context, out var result)) - { - lookup.SetValue(mapped.Parameter, result); - } - } - - CommandValidator.ValidateParameter(mapped.Parameter, lookup, resolver); - } - - tree = tree.Next; - } - - return lookup; - } - - private static object? ConvertValue(ITypeResolver resolver, CommandValueLookup lookup, CommandValueBinder binder, CommandParameter parameter, object? result) - { - if (result != null && result.GetType() != parameter.ParameterType) - { - var converter = GetConverter(lookup, binder, resolver, parameter); - result = result is Array array ? ConvertArray(array, converter) : converter.ConvertFrom(result); - } - - return result; - } - - private static Array ConvertArray(Array sourceArray, SmartConverter converter) - { - Array? targetArray = null; - for (var i = 0; i < sourceArray.Length; i++) - { - var item = sourceArray.GetValue(i); - if (item != null) - { - var converted = converter.ConvertFrom(item); - if (converted != null) - { - targetArray ??= Array.CreateInstance(converted.GetType(), sourceArray.Length); - targetArray.SetValue(converted, i); - } - } - } - - return targetArray ?? sourceArray; - } - - [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "It's OK")] - private static SmartConverter GetConverter(CommandValueLookup lookup, CommandValueBinder binder, ITypeResolver resolver, CommandParameter parameter) - { - if (parameter.Converter == null) - { - if (parameter.ParameterType.IsArray) - { - // Return a converter for each array item (not the whole array) - var elementType = parameter.ParameterType.GetElementType(); - if (elementType == null) - { - throw new InvalidOperationException("Could not get element type"); - } - - return new SmartConverter(TypeDescriptor.GetConverter(elementType), elementType); - } - - if (parameter.IsFlagValue()) - { - // Is the optional value instantiated? - var value = lookup.GetValue(parameter) as IFlagValue; - if (value == null) - { - // Try to assign it with a null value. - // This will create the optional value instance without a value. - binder.Bind(parameter, resolver, null); - value = lookup.GetValue(parameter) as IFlagValue; - if (value == null) - { - throw new InvalidOperationException("Could not initialize optional value."); - } - } - - // Return a converter for the flag element type. - return new SmartConverter(TypeDescriptor.GetConverter(value.Type), value.Type); - } - - return new SmartConverter(TypeDescriptor.GetConverter(parameter.ParameterType), parameter.ParameterType); - } - - var type = Type.GetType(parameter.Converter.ConverterTypeName); - if (type == null || resolver.Resolve(type) is not TypeConverter typeConverter) - { - throw CommandRuntimeException.NoConverterFound(parameter); - } - - return new SmartConverter(typeConverter, type); - } - - /// - /// Convert inputs using the given and fallback to finding a constructor taking a single argument of the input type. - /// - private readonly ref struct SmartConverter - { - public SmartConverter(TypeConverter typeConverter, Type type) - { - TypeConverter = typeConverter; - Type = type; - } - - public TypeConverter TypeConverter { get; } - private Type Type { get; } - - public object? ConvertFrom(object input) - { - try - { - return TypeConverter.ConvertFrom(null, CultureInfo.InvariantCulture, input); - } - catch (NotSupportedException) - { - var constructor = Type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new[] { input.GetType() }, null); - if (constructor == null) - { - throw; - } - - return constructor.Invoke(new[] { input }); - } - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Collections/IMultiMap.cs b/src/Spectre.Console.Cli/Internal/Collections/IMultiMap.cs deleted file mode 100644 index b0864c625..000000000 --- a/src/Spectre.Console.Cli/Internal/Collections/IMultiMap.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Representation of a multi map. -/// -internal interface IMultiMap -{ - /// - /// Adds a key and a value to the multi map. - /// - /// The pair to add. - void Add((object? Key, object? Value) pair); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Collections/MultiMap.cs b/src/Spectre.Console.Cli/Internal/Collections/MultiMap.cs deleted file mode 100644 index 930970408..000000000 --- a/src/Spectre.Console.Cli/Internal/Collections/MultiMap.cs +++ /dev/null @@ -1,168 +0,0 @@ -namespace Spectre.Console.Cli; - -[SuppressMessage("Performance", "CA1812: Avoid uninstantiated internal classes")] -internal sealed class MultiMap : IMultiMap, ILookup, IDictionary, IReadOnlyDictionary - where TKey : notnull -{ - private readonly IDictionary _lookup; - private readonly IDictionary _dictionary; - - public int Count => _lookup.Count; - - public bool IsReadOnly => false; - - public ICollection Keys => _lookup.Keys; - - public ICollection Values => _dictionary.Values; - - IEnumerable IReadOnlyDictionary.Keys => _lookup.Keys; - - IEnumerable IReadOnlyDictionary.Values => _dictionary.Values; - - TValue IReadOnlyDictionary.this[TKey key] => _dictionary[key]; - - TValue IDictionary.this[TKey key] - { - get - { - return _dictionary[key]; - } - set - { - Add(key, value); - } - } - - public IEnumerable this[TKey key] - { - get - { - if (_lookup.TryGetValue(key, out var group)) - { - return group; - } - - return Array.Empty(); - } - } - - public MultiMap() - { - _lookup = new Dictionary(); - _dictionary = new Dictionary(); - } - - private sealed class MultiMapGrouping : IGrouping - { - private readonly List _items; - - public TKey Key { get; } - - public MultiMapGrouping(TKey key, List items) - { - Key = key; - _items = items; - } - - public void Add(TValue value) - { - _items.Add(value); - } - - public IEnumerator GetEnumerator() - { - return _items.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } - - public bool Contains(TKey key) - { - return _lookup.ContainsKey(key); - } - - public IEnumerator> GetEnumerator() - { - foreach (var group in _lookup.Values) - { - yield return group; - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - public void Add(TKey key, TValue value) - { - if (!_lookup.ContainsKey(key)) - { - _lookup[key] = new MultiMapGrouping(key, new List()); - } - - _lookup[key].Add(value); - _dictionary[key] = value; - } - - public bool ContainsKey(TKey key) - { - return Contains(key); - } - - public bool Remove(TKey key) - { - return _lookup.Remove(key); - } - - public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) - { - return _dictionary.TryGetValue(key, out value); - } - - public void Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } - - public void Clear() - { - _lookup.Clear(); - } - - public bool Contains(KeyValuePair item) - { - return Contains(item.Key); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - _dictionary.CopyTo(array, arrayIndex); - } - - public bool Remove(KeyValuePair item) - { - return Remove(item.Key); - } - - IEnumerator> IEnumerable>.GetEnumerator() - { - return _dictionary.GetEnumerator(); - } - - public void Add((object? Key, object? Value) pair) - { - if (pair.Key != null) - { -#pragma warning disable CS8604 // Possible null reference argument of value. -#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. - Add((TKey)pair.Key, (TValue)pair.Value); -#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. -#pragma warning restore CS8604 // Possible null reference argument of value. - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/CommandBinder.cs b/src/Spectre.Console.Cli/Internal/CommandBinder.cs deleted file mode 100644 index 69d83981c..000000000 --- a/src/Spectre.Console.Cli/Internal/CommandBinder.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandBinder -{ - public static CommandSettings Bind(CommandTree? tree, Type settingsType, ITypeResolver resolver) - { - var lookup = CommandValueResolver.GetParameterValues(tree, resolver); - - // Got a constructor with at least one name corresponding to a settings? - foreach (var constructor in settingsType.GetConstructors()) - { - var parameters = constructor.GetParameters(); - if (parameters.Length > 0) - { - foreach (var parameter in parameters) - { - if (lookup.HasParameterWithName(parameter?.Name)) - { - // Use constructor injection. - return CommandConstructorBinder.CreateSettings(lookup, constructor, resolver); - } - } - } - } - - return CommandPropertyBinder.CreateSettings(lookup, settingsType, resolver); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/CommandExecutor.cs b/src/Spectre.Console.Cli/Internal/CommandExecutor.cs deleted file mode 100644 index 4d1d7dec8..000000000 --- a/src/Spectre.Console.Cli/Internal/CommandExecutor.cs +++ /dev/null @@ -1,273 +0,0 @@ -using static Spectre.Console.Cli.CommandTreeTokenizer; - -namespace Spectre.Console.Cli; - -internal sealed class CommandExecutor -{ - private readonly ITypeRegistrar _registrar; - - public CommandExecutor(ITypeRegistrar registrar) - { - _registrar = registrar ?? throw new ArgumentNullException(nameof(registrar)); - _registrar.Register(typeof(DefaultPairDeconstructor), typeof(DefaultPairDeconstructor)); - } - - public async Task ExecuteAsync(IConfiguration configuration, IEnumerable args, CancellationToken cancellationToken) - { - CommandTreeParserResult parsedResult; - - if (configuration == null) - { - throw new ArgumentNullException(nameof(configuration)); - } - - var arguments = args.ToSafeReadOnlyList(); - - _registrar.RegisterInstance(typeof(IConfiguration), configuration); - _registrar.RegisterLazy(typeof(IAnsiConsole), () => configuration.Settings.Console.GetConsole()); - - // Create the command model. - var model = CommandModelBuilder.Build(configuration); - _registrar.RegisterInstance(typeof(CommandModel), model); - _registrar.RegisterDependencies(model); - - // Got at least one argument? - var firstArgument = arguments.FirstOrDefault(); - if (firstArgument != null) - { - // Asking for version? - if (firstArgument.Equals("-v", StringComparison.OrdinalIgnoreCase) || - firstArgument.Equals("--version", StringComparison.OrdinalIgnoreCase)) - { - if (configuration.Settings.ApplicationVersion != null) - { - // We need to check if the command has a version option on its setting class. - // Do this by first parsing the command line args and checking the remaining args. - try - { - // Parse and map the model against the arguments. - parsedResult = ParseCommandLineArguments(model, configuration.Settings, arguments); - } - catch (Exception) - { - // Something went wrong with parsing the command line arguments, - // however we know the first argument is a version option. - var console = configuration.Settings.Console.GetConsole(); - console.MarkupLine(configuration.Settings.ApplicationVersion); - return 0; - } - - // Check the parsed remaining args for the version options. - if ((firstArgument.Equals("-v", StringComparison.OrdinalIgnoreCase) && parsedResult.Remaining.Parsed.Contains("-v")) || - (firstArgument.Equals("--version", StringComparison.OrdinalIgnoreCase) && parsedResult.Remaining.Parsed.Contains("--version"))) - { - // The version option is not a member of the command settings. - var console = configuration.Settings.Console.GetConsole(); - console.MarkupLine(configuration.Settings.ApplicationVersion); - return 0; - } - } - } - - // OpenCLI? - if (firstArgument.Equals(CliConstants.DumpHelpOpenCliOption, StringComparison.OrdinalIgnoreCase)) - { - // Replace all arguments with the opencligen command - arguments = ["cli", "opencli"]; - } - } - - // Parse and map the model against the arguments. - parsedResult = ParseCommandLineArguments(model, configuration.Settings, arguments); - - // Register the arguments with the container. - _registrar.RegisterInstance(typeof(CommandTreeParserResult), parsedResult); - _registrar.RegisterInstance(typeof(IRemainingArguments), parsedResult.Remaining); - - // Create the resolver. - using (var resolver = new TypeResolverAdapter(_registrar.Build())) - { - // Get the registered help provider, falling back to the default provider - // if no custom implementations have been registered. - var helpProviders = resolver.Resolve(typeof(IEnumerable)) as IEnumerable; - var helpProvider = helpProviders?.LastOrDefault() ?? new HelpProvider(configuration.Settings); - - // Currently the root? - if (parsedResult?.Tree == null) - { - // Display help. - configuration.Settings.Console.SafeRender(helpProvider.Write(model, null)); - return 0; - } - - // Get the command to execute. - var leaf = parsedResult.Tree.GetLeafCommand(); - if (leaf.Command.IsBranch || leaf.ShowHelp) - { - // Branches can't be executed. Show help. - configuration.Settings.Console.SafeRender(helpProvider.Write(model, leaf.Command)); - return leaf.ShowHelp ? 0 : 1; - } - - // Is this the default and is it called without arguments when there are required arguments? - if (leaf.Command.IsDefaultCommand && arguments.Count == 0 && leaf.Command.Parameters.Any(p => p.IsRequired)) - { - // Display help for default command. - configuration.Settings.Console.SafeRender(helpProvider.Write(model, leaf.Command)); - return 1; - } - - // Create the content. - var context = new CommandContext( - arguments, - parsedResult.Remaining, - leaf.Command.Name, - leaf.Command.Data); - - // Execute the command tree. - return await ExecuteAsync(leaf, parsedResult.Tree, context, resolver, configuration, cancellationToken).ConfigureAwait(false); - } - } - - [SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "Improves code readability by grouping together related statements into a block")] - private CommandTreeParserResult ParseCommandLineArguments(CommandModel model, CommandAppSettings settings, IReadOnlyList args) - { - CommandTreeParserResult? parsedResult = null; - CommandTreeTokenizerResult tokenizerResult; - - try - { - (parsedResult, tokenizerResult) = InternalParseCommandLineArguments(model, settings, args); - - var lastParsedLeaf = parsedResult.Tree?.GetLeafCommand(); - var lastParsedCommand = lastParsedLeaf?.Command; - - if (lastParsedLeaf != null && lastParsedCommand != null && - lastParsedCommand.IsBranch && !lastParsedLeaf.ShowHelp && - lastParsedCommand.DefaultCommand != null) - { - // Adjust for any parsed remaining arguments by - // inserting the the default command ahead of them. - var position = tokenizerResult.Tokens.Position; - foreach (var parsedRemaining in parsedResult.Remaining.Parsed) - { - position--; - position -= parsedRemaining.Count(value => value != null); - } - position = position < 0 ? 0 : position; - - // Insert this branch's default command into the command line - // arguments and try again to see if it will parse. - var argsWithDefaultCommand = new List(args); - argsWithDefaultCommand.Insert(position, lastParsedCommand.DefaultCommand.Name); - - (parsedResult, tokenizerResult) = InternalParseCommandLineArguments(model, settings, argsWithDefaultCommand); - } - } - catch (CommandParseException) when (parsedResult == null && settings.ParsingMode == ParsingMode.Strict) - { - // The parsing exception might be resolved by adding in the default command, - // but we can't know for sure. Take a brute force approach and try this for - // every position between the arguments. - for (int i = 0; i < args.Count; i++) - { - var argsWithDefaultCommand = new List(args); - argsWithDefaultCommand.Insert(args.Count - i, "__default_command"); - - try - { - (parsedResult, tokenizerResult) = InternalParseCommandLineArguments(model, settings, argsWithDefaultCommand); - - break; - } - catch (CommandParseException) - { - // Continue. - } - } - - if (parsedResult == null) - { - // Failed to parse having inserted the default command between each argument. - // Repeat the parsing of the original arguments to throw the correct exception. - InternalParseCommandLineArguments(model, settings, args); - } - } - - if (parsedResult == null) - { - // The arguments failed to parse despite everything we tried above. - // Exceptions should be thrown above before ever getting this far, - // however the following is the ulimately backstop and avoids - // the compiler from complaining about returning null. - throw CommandParseException.UnknownParsingError(); - } - - return parsedResult; - } - - /// - /// Parse the command line arguments using the specified and , - /// returning the parser and tokenizer results. - /// - /// The parser and tokenizer results as a tuple. - private (CommandTreeParserResult ParserResult, CommandTreeTokenizerResult TokenizerResult) InternalParseCommandLineArguments(CommandModel model, CommandAppSettings settings, IReadOnlyList args) - { - var parser = new CommandTreeParser(model, settings.CaseSensitivity, settings.ParsingMode, settings.ConvertFlagsToRemainingArguments); - - var parserContext = new CommandTreeParserContext(args, settings.ParsingMode); - var tokenizerResult = CommandTreeTokenizer.Tokenize(args); - var parsedResult = parser.Parse(parserContext, tokenizerResult); - - return (parsedResult, tokenizerResult); - } - - private static async Task ExecuteAsync( - CommandTree leaf, - CommandTree tree, - CommandContext context, - ITypeResolver resolver, - IConfiguration configuration, - CancellationToken cancellationToken) - { - try - { - // Bind the command tree against the settings. - var settings = CommandBinder.Bind(tree, leaf.Command.SettingsType, resolver); - var interceptors = - ((IEnumerable?)resolver.Resolve(typeof(IEnumerable)) - ?? Array.Empty()).ToList(); -#pragma warning disable CS0618 // Type or member is obsolete - if (configuration.Settings.Interceptor != null) - { - interceptors.Add(configuration.Settings.Interceptor); - } -#pragma warning restore CS0618 // Type or member is obsolete - foreach (var interceptor in interceptors) - { - interceptor.Intercept(context, settings); - } - - // Create and validate the command. - var command = leaf.CreateCommand(resolver); - var validationResult = command.Validate(context, settings); - if (!validationResult.Successful) - { - throw CommandRuntimeException.ValidationFailed(validationResult); - } - - // Execute the command. - var result = await command.ExecuteAsync(context, settings, cancellationToken); - foreach (var interceptor in interceptors) - { - interceptor.InterceptResult(context, settings, ref result); - } - - return result; - } - catch (Exception ex) when (configuration.Settings is { ExceptionHandler: not null, PropagateExceptions: false }) - { - return configuration.Settings.ExceptionHandler(ex, resolver); - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/CommandPart.cs b/src/Spectre.Console.Cli/Internal/CommandPart.cs deleted file mode 100644 index 3b0054a6e..000000000 --- a/src/Spectre.Console.Cli/Internal/CommandPart.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Spectre.Console.Cli; - -internal enum CommandPart -{ - CommandName, - LongOption, -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/CommandSuggestor.cs b/src/Spectre.Console.Cli/Internal/CommandSuggestor.cs deleted file mode 100644 index 0c6fba3c3..000000000 --- a/src/Spectre.Console.Cli/Internal/CommandSuggestor.cs +++ /dev/null @@ -1,73 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandSuggestor -{ - private const float SmallestDistance = 2f; - - public static CommandInfo? Suggest(CommandModel model, CommandInfo? command, string name) - { - var result = (CommandInfo?)null; - - var container = command ?? (ICommandContainer)model; - if (command?.IsDefaultCommand ?? false) - { - // Default commands have no children, - // so use the root commands here. - container = model; - } - - var score = float.MaxValue; - foreach (var child in container.Commands.Where(x => !x.IsHidden)) - { - var temp = Score(child.Name, name); - if (temp < score) - { - score = temp; - result = child; - } - } - - if (score <= SmallestDistance) - { - return result; - } - - return null; - } - - private static float Score(string source, string target) - { - source = source.ToUpperInvariant(); - target = target.ToUpperInvariant(); - - var n = source.Length; - var m = target.Length; - - if (n == 0) - { - return m; - } - - if (m == 0) - { - return n; - } - - var d = new int[n + 1, m + 1]; - Enumerable.Range(0, n + 1).ToList().ForEach(i => d[i, 0] = i); - Enumerable.Range(0, m + 1).ToList().ForEach(i => d[0, i] = i); - - for (var sourceIndex = 1; sourceIndex <= n; sourceIndex++) - { - for (var targetIndex = 1; targetIndex <= m; targetIndex++) - { - var cost = (target[targetIndex - 1] == source[sourceIndex - 1]) ? 0 : 1; - d[sourceIndex, targetIndex] = Math.Min( - Math.Min(d[sourceIndex - 1, targetIndex] + 1, d[sourceIndex, targetIndex - 1] + 1), - d[sourceIndex - 1, targetIndex - 1] + cost); - } - } - - return d[n, m]; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/CommandValidator.cs b/src/Spectre.Console.Cli/Internal/CommandValidator.cs deleted file mode 100644 index 0f523b84b..000000000 --- a/src/Spectre.Console.Cli/Internal/CommandValidator.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandValidator -{ - public static void ValidateRequiredParameters(CommandTree? tree) - { - var node = tree?.GetRootCommand(); - while (node != null) - { - foreach (var parameter in node.Unmapped) - { - if (parameter.IsRequired) - { - switch (parameter) - { - case CommandArgument argument: - throw CommandRuntimeException.MissingRequiredArgument(node, argument); - case CommandOption option: - throw CommandRuntimeException.MissingRequiredOption(node, option); - } - } - } - - node = node.Next; - } - } - - public static void ValidateParameter(CommandParameter parameter, CommandValueLookup settings, ITypeResolver resolver) - { - var assignedValue = settings.GetValue(parameter); - foreach (var validator in parameter.Validators) - { - var context = new CommandParameterContext(parameter, resolver, assignedValue); - var validationResult = validator.Validate(context); - if (!validationResult.Successful) - { - // If there is an error message specified in the parameter validator attribute, - // then use that one, otherwise use the validation result. - var result = string.IsNullOrWhiteSpace(validator.ErrorMessage) - ? validationResult - : ValidationResult.Error(validator.ErrorMessage); - - throw CommandRuntimeException.ValidationFailed(result); - } - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Commands/ExplainCommand.cs b/src/Spectre.Console.Cli/Internal/Commands/ExplainCommand.cs deleted file mode 100644 index 29744fca4..000000000 --- a/src/Spectre.Console.Cli/Internal/Commands/ExplainCommand.cs +++ /dev/null @@ -1,257 +0,0 @@ -namespace Spectre.Console.Cli; - -[Description("Displays diagnostics about CLI configurations")] -[SuppressMessage("Performance", "CA1812: Avoid uninstantiated internal classes")] -internal sealed class ExplainCommand : Command, IBuiltInCommand -{ - private readonly CommandModel _commandModel; - private readonly IAnsiConsole _writer; - - public ExplainCommand(IConfiguration configuration, CommandModel commandModel) - { - _commandModel = commandModel ?? throw new ArgumentNullException(nameof(commandModel)); - _writer = configuration.Settings.Console.GetConsole(); - } - - public sealed class Settings : CommandSettings - { - [CommandArgument(0, "[command]")] - public string[]? Commands { get; set; } - - [Description("Include detailed information about the commands.")] - [CommandOption("-d|--detailed")] - public bool? Detailed { get; set; } - - [Description("Include hidden commands and options.")] - [CommandOption("--hidden")] - public bool IncludeHidden { get; set; } - } - - public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) - { - var tree = new Tree("CLI Configuration"); - tree.AddNode(ValueMarkup("Application Name", _commandModel.ApplicationName, "no application name")); - tree.AddNode(ValueMarkup("Parsing Mode", _commandModel.ParsingMode.ToString())); - - if (settings.Commands == null || settings.Commands.Length == 0) - { - // If there is a default command we'll want to include it in the list too. - var commands = _commandModel.DefaultCommand != null - ? new[] { _commandModel.DefaultCommand }.Concat(_commandModel.Commands) - : _commandModel.Commands; - - AddCommands( - tree.AddNode(ParentMarkup("Commands")), - commands, - settings.Detailed ?? false, - settings.IncludeHidden); - } - else - { - var currentCommandTier = _commandModel.Commands; - CommandInfo? currentCommand = null; - foreach (var command in settings.Commands) - { - currentCommand = currentCommandTier - .SingleOrDefault(i => - i.Name.Equals(command, StringComparison.CurrentCultureIgnoreCase) || - i.Aliases - .Any(alias => alias.Equals(command, StringComparison.CurrentCultureIgnoreCase))); - - if (currentCommand == null) - { - break; - } - - currentCommandTier = currentCommand.Children; - } - - if (currentCommand == null) - { - throw new Exception($"Command {string.Join(" ", settings.Commands)} not found"); - } - - AddCommands( - tree.AddNode(ParentMarkup("Commands")), - new[] { currentCommand }, - settings.Detailed ?? true, - settings.IncludeHidden); - } - - _writer.Write(tree); - - return 0; - } - - private IRenderable ValueMarkup(string key, string value) - { - return new Markup($"{key}: [blue]{value.EscapeMarkup()}[/]"); - } - - private IRenderable ValueMarkup(string key, string? value, string noValueText) - { - if (string.IsNullOrWhiteSpace(value)) - { - return new Markup($"{key}: [grey]({noValueText.EscapeMarkup()})[/]"); - } - - var table = new Table().NoBorder().HideHeaders().AddColumns("key", "value"); - table.AddRow($"{key}", $"[blue]{value.EscapeMarkup()}[/]"); - return table; - } - - private string ParentMarkup(string description) - { - return $"[yellow]{description.EscapeMarkup()}[/]"; - } - - private void AddStringList(TreeNode node, string description, IList? strings) - { - if (strings == null || strings.Count == 0) - { - return; - } - - var parentNode = node.AddNode(ParentMarkup(description)); - foreach (var s in strings) - { - parentNode.AddNode(s); - } - } - - private void AddCommands(TreeNode node, IEnumerable commands, bool detailed, bool includeHidden) - { - foreach (var command in commands) - { - if (!includeHidden && command.IsHidden) - { - continue; - } - - var commandName = $"[green]{command.Name}[/]"; - if (command.IsDefaultCommand) - { - commandName += " (default)"; - } - - var commandNode = node.AddNode(commandName); - commandNode.AddNode(ValueMarkup("Description", command.Description, "no description")); - if (command.IsHidden) - { - commandNode.AddNode(ValueMarkup("IsHidden", command.IsHidden.ToString())); - } - - if (!command.IsBranch) - { - commandNode.AddNode(ValueMarkup("Type", command.CommandType?.ToString(), "no command type")); - commandNode.AddNode(ValueMarkup("Settings Type", command.SettingsType.ToString())); - } - - if (command.Parameters.Count > 0) - { - var parametersNode = commandNode.AddNode(ParentMarkup("Parameters")); - foreach (var parameter in command.Parameters) - { - AddParameter(parametersNode, parameter, detailed, includeHidden); - } - } - - AddStringList(commandNode, "Aliases", command.Aliases.ToList()); - AddStringList(commandNode, "Examples", command.Examples.Select(i => string.Join(" ", i)).ToList()); - - if (command.Children.Count > 0) - { - var childNode = commandNode.AddNode(ParentMarkup("Child Commands")); - AddCommands(childNode, command.Children, detailed, includeHidden); - } - } - } - - private void AddParameter(TreeNode parametersNode, CommandParameter parameter, bool detailed, bool includeHidden) - { - if (!includeHidden && parameter.IsHidden) - { - return; - } - - if (!detailed) - { - parametersNode.AddNode( - $"{parameter.PropertyName} [purple]{GetShortOptions(parameter)}[/] [grey]{parameter.Property.PropertyType.ToString().EscapeMarkup()}[/]"); - - return; - } - - var parameterNode = parametersNode.AddNode( - $"{parameter.PropertyName} [grey]{parameter.Property.PropertyType.ToString().EscapeMarkup()}[/]"); - - parameterNode.AddNode(ValueMarkup("Description", parameter.Description, "no description")); - parameterNode.AddNode(ValueMarkup("Parameter Kind", parameter.ParameterKind.ToString())); - - if (parameter is CommandOption commandOptionParameter) - { - if (commandOptionParameter.IsShadowed) - { - parameterNode.AddNode(ValueMarkup("IsShadowed", commandOptionParameter.IsShadowed.ToString())); - } - - if (commandOptionParameter.LongNames.Count > 0) - { - parameterNode.AddNode(ValueMarkup( - "Long Names", - string.Join("|", commandOptionParameter.LongNames.Select(i => $"--{i}")))); - - parameterNode.AddNode(ValueMarkup( - "Short Names", - string.Join("|", commandOptionParameter.ShortNames.Select(i => $"-{i}")))); - } - } - else if (parameter is CommandArgument commandArgumentParameter) - { - parameterNode.AddNode(ValueMarkup("Position", commandArgumentParameter.Position.ToString())); - parameterNode.AddNode(ValueMarkup("Value", commandArgumentParameter.Value)); - } - - parameterNode.AddNode(ValueMarkup("Required", parameter.IsRequired.ToString())); - - if (parameter.Converter != null) - { - parameterNode.AddNode(ValueMarkup( - "Converter", $"\"{parameter.Converter.ConverterTypeName}\"")); - } - - if (parameter.DefaultValue != null) - { - parameterNode.AddNode(ValueMarkup( - "Default Value", $"\"{parameter.DefaultValue.Value}\"")); - } - - if (parameter.PairDeconstructor != null) - { - parameterNode.AddNode(ValueMarkup("Pair Deconstructor", parameter.PairDeconstructor.Type.ToString())); - } - - AddStringList( - parameterNode, - "Validators", - parameter.Validators.Select(i => i.GetType().ToString()).ToList()); - } - - private static string GetShortOptions(CommandParameter parameter) - { - if (parameter is CommandOption commandOptionParameter) - { - return string.Join( - " | ", - commandOptionParameter.LongNames.Select(i => $"--{i}") - .Concat(commandOptionParameter.ShortNames.Select(i => $"-{i}"))); - } - - if (parameter is CommandArgument commandArgumentParameter) - { - return $"{commandArgumentParameter.Value} position {commandArgumentParameter.Position}"; - } - - return string.Empty; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Commands/IBuiltInCommand.cs b/src/Spectre.Console.Cli/Internal/Commands/IBuiltInCommand.cs deleted file mode 100644 index d3b783e75..000000000 --- a/src/Spectre.Console.Cli/Internal/Commands/IBuiltInCommand.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a built-in command. -/// Used as a marker interface. -/// -internal interface IBuiltInCommand : ICommand -{ -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Commands/OpenCliGeneratorCommand.cs b/src/Spectre.Console.Cli/Internal/Commands/OpenCliGeneratorCommand.cs deleted file mode 100644 index e33b058ae..000000000 --- a/src/Spectre.Console.Cli/Internal/Commands/OpenCliGeneratorCommand.cs +++ /dev/null @@ -1,224 +0,0 @@ -using OpenCli; - -namespace Spectre.Console.Cli; - -internal sealed class OpenCliGeneratorCommand : Command, IBuiltInCommand -{ - private readonly IConfiguration _configuration; - private readonly CommandModel _model; - - public OpenCliGeneratorCommand(IConfiguration configuration, CommandModel model) - { - _configuration = configuration; - _model = model ?? throw new ArgumentNullException(nameof(model)); - } - - public override int Execute(CommandContext context, CancellationToken cancellationToken) - { - var document = new OpenCliDocument - { - OpenCli = "0.1-draft", - Info = new OpenCliInfo - { - Title = ((ICommandModel)_model).ApplicationName, Version = _model.ApplicationVersion ?? "1.0", - }, - Commands = CreateCommands(_model.Commands), - Arguments = CreateArguments(_model.DefaultCommand?.GetArguments()), - Options = CreateOptions(_model.DefaultCommand?.GetOptions()), - }; - - var writer = _configuration.Settings.Console.GetConsole(); - writer.WriteLine(document.Write()); - - return 0; - } - - private List CreateCommands(IList commands) - { - var result = new List(); - - foreach (var command in commands.OrderBy(o => o.Name, StringComparer.OrdinalIgnoreCase)) - { - if (typeof(IBuiltInCommand).IsAssignableFrom(command.CommandType)) - { - continue; - } - - var openCliCommand = new OpenCliCommand - { - Name = command.Name, - Aliases = - [ - ..command.Aliases.OrderBy(str => str) - ], - Commands = CreateCommands(command.Children), - Arguments = CreateArguments(command.GetArguments()), - Options = CreateOptions(command.GetOptions()), - Description = command.Description, - Hidden = command.IsHidden, - Examples = [..command.Examples.Select(example => string.Join(" ", example))], - }; - - // Skip branches without commands - if (command.IsBranch && openCliCommand.Commands.Count == 0) - { - continue; - } - - result.Add(openCliCommand); - } - - return result; - } - - private List CreateArguments(IEnumerable? arguments) - { - var result = new List(); - - if (arguments == null) - { - return result; - } - - foreach (var argument in arguments.OrderBy(x => x.Position)) - { - var metadata = default(List); - if (argument.ParameterType != typeof(void) && - argument.ParameterType != typeof(bool)) - { - metadata = - [ - new OpenCliMetadata { Name = "ClrType", Value = argument.ParameterType.ToCliTypeString(), }, - ]; - } - - result.Add(new OpenCliArgument - { - Name = argument.Value, - Required = argument.IsRequired, - Arity = new OpenCliArity - { - // TODO: Look into this - Minimum = 1, - Maximum = 1, - }, - Description = argument.Description, - Hidden = argument.IsHidden, - Metadata = metadata, - AcceptedValues = null, - Group = null, - }); - } - - return result; - } - - private List CreateOptions(IEnumerable? options) - { - var result = new List(); - - if (options == null) - { - return result; - } - - foreach (var option in options.OrderBy(o => o.GetOptionName(), StringComparer.OrdinalIgnoreCase)) - { - var arguments = new List(); - if (option.ParameterType != typeof(void) && - option.ParameterType != typeof(bool)) - { - arguments.Add(new OpenCliArgument - { - Name = option.ValueName ?? "VALUE", - Required = !option.ValueIsOptional, - Arity = new OpenCliArity - { - // TODO: Look into this - Minimum = option.ValueIsOptional - ? 0 - : 1, - Maximum = 1, - }, - AcceptedValues = null, - Group = null, - Hidden = null, - Metadata = - [ - new OpenCliMetadata - { - Name = "ClrType", - Value = option.ParameterType.ToCliTypeString(), - }, - ], - }); - } - - var optionMetadata = default(List); - if (arguments.Count == 0 && option.ParameterType != typeof(void) && - option.ParameterType != typeof(bool)) - { - optionMetadata = - [ - new OpenCliMetadata { Name = "ClrType", Value = option.ParameterType.ToCliTypeString(), }, - ]; - } - - var (optionName, optionAliases) = GetOptionNames(option); - result.Add(new OpenCliOption - { - Name = optionName, - Required = option.IsRequired, - Aliases = [..optionAliases.OrderBy(str => str)], - Arguments = arguments, - Description = option.Description, - Group = null, - Hidden = option.IsHidden, - Recursive = option.IsShadowed, // TODO: Is this correct? - Metadata = optionMetadata, - }); - } - - return result; - } - - private static (string Name, HashSet Aliases) GetOptionNames(CommandOption option) - { - var name = GetOptionName(option); - var aliases = new HashSet(); - - if (option.LongNames.Count > 0) - { - foreach (var alias in option.LongNames.Skip(1)) - { - aliases.Add("--" + alias); - } - - foreach (var alias in option.ShortNames) - { - aliases.Add("-" + alias); - } - } - else - { - foreach (var alias in option.LongNames) - { - aliases.Add("--" + alias); - } - - foreach (var alias in option.ShortNames.Skip(1)) - { - aliases.Add("-" + alias); - } - } - - return (name, aliases); - } - - private static string GetOptionName(CommandOption option) - { - return option.LongNames.Count > 0 - ? "--" + option.LongNames[0] - : "-" + option.ShortNames[0]; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Commands/VersionCommand.cs b/src/Spectre.Console.Cli/Internal/Commands/VersionCommand.cs deleted file mode 100644 index c6bef190a..000000000 --- a/src/Spectre.Console.Cli/Internal/Commands/VersionCommand.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Spectre.Console.Cli; - -[Description("Displays the CLI library version")] -[SuppressMessage("Performance", "CA1812: Avoid uninstantiated internal classes")] -internal sealed class VersionCommand : Command, IBuiltInCommand -{ - private readonly IAnsiConsole _writer; - - public VersionCommand(IConfiguration configuration) - { - _writer = configuration.Settings.Console.GetConsole(); - } - - public override int Execute(CommandContext context, CancellationToken cancellationToken) - { - _writer.MarkupLine( - "[yellow]Spectre.Cli[/] version [aqua]{0}[/]", - VersionHelper.GetVersion(typeof(VersionCommand)?.Assembly)); - - _writer.MarkupLine( - "[yellow]Spectre.Console[/] version [aqua]{0}[/]", - VersionHelper.GetVersion(typeof(IAnsiConsole)?.Assembly)); - - return 0; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Commands/XmlDocCommand.cs b/src/Spectre.Console.Cli/Internal/Commands/XmlDocCommand.cs deleted file mode 100644 index 8b2e82ed8..000000000 --- a/src/Spectre.Console.Cli/Internal/Commands/XmlDocCommand.cs +++ /dev/null @@ -1,199 +0,0 @@ -namespace Spectre.Console.Cli; - -[Description("Generates an XML representation of the CLI configuration.")] -[SuppressMessage("Performance", "CA1812: Avoid uninstantiated internal classes")] -internal sealed class XmlDocCommand : Command, IBuiltInCommand -{ - private readonly CommandModel _model; - private readonly IAnsiConsole _writer; - - public XmlDocCommand(IConfiguration configuration, CommandModel model) - { - _model = model ?? throw new ArgumentNullException(nameof(model)); - _writer = configuration.Settings.Console.GetConsole(); - } - - public override int Execute(CommandContext context, CancellationToken cancellationToken) - { - _writer.Write(Serialize(_model), Style.Plain); - return 0; - } - - public static string Serialize(CommandModel model) - { - var settings = new XmlWriterSettings - { - Indent = true, - IndentChars = " ", - NewLineChars = "\n", - OmitXmlDeclaration = false, - Encoding = Encoding.UTF8, - }; - - using (var buffer = new StringWriterWithEncoding(Encoding.UTF8)) - using (var xmlWriter = XmlWriter.Create(buffer, settings)) - { - SerializeModel(model).WriteTo(xmlWriter); - xmlWriter.Flush(); - return buffer.GetStringBuilder().ToString(); - } - } - - private static XmlDocument SerializeModel(CommandModel model) - { - var document = new XmlDocument(); - var root = document.CreateElement("Model"); - - if (model.DefaultCommand != null) - { - root.AppendChild(document.CreateComment("DEFAULT COMMAND")); - root.AppendChild(CreateCommandNode(document, model.DefaultCommand, isDefaultCommand: true)); - } - - foreach (var command in model.Commands.Where(x => !x.IsHidden)) - { - root.AppendChild(document.CreateComment(command.Name.ToUpperInvariant())); - root.AppendChild(CreateCommandNode(document, command)); - } - - document.AppendChild(root); - return document; - } - - private static XmlNode CreateCommandNode(XmlDocument doc, CommandInfo command, bool isDefaultCommand = false) - { - var node = doc.CreateElement("Command"); - - // Attributes - node.SetNullableAttribute("Name", command.Name); - node.SetBooleanAttribute("IsBranch", command.IsBranch); - - if (isDefaultCommand) - { - node.SetBooleanAttribute("IsDefault", true); - } - - if (command.CommandType != null) - { - node.SetNullableAttribute("ClrType", command.CommandType?.FullName); - } - - node.SetNullableAttribute("Settings", command.SettingsType?.FullName); - - if (!string.IsNullOrWhiteSpace(command.Description)) - { - var descriptionNode = doc.CreateElement("Description"); - descriptionNode.InnerText = command.Description; - node.AppendChild(descriptionNode); - } - - // Parameters - if (command.Parameters.Count > 0) - { - var parameterRootNode = doc.CreateElement("Parameters"); - foreach (var parameter in CreateParameterNodes(doc, command)) - { - parameterRootNode.AppendChild(parameter); - } - - node.AppendChild(parameterRootNode); - } - - // Commands - foreach (var childCommand in command.Children) - { - node.AppendChild(doc.CreateComment(childCommand.Name.ToUpperInvariant())); - node.AppendChild(CreateCommandNode(doc, childCommand)); - } - - // Examples - if (command.Examples.Count > 0) - { - var exampleRootNode = doc.CreateElement("Examples"); - foreach (var example in command.Examples.SelectMany(static x => x)) - { - var exampleNode = CreateExampleNode(doc, example); - exampleRootNode.AppendChild(exampleNode); - } - - node.AppendChild(exampleRootNode); - } - - return node; - } - - private static XmlNode CreateExampleNode(XmlDocument document, string example) - { - var node = document.CreateElement("Example"); - node.SetAttribute("commandLine", example); - - return node; - } - - private static IEnumerable CreateParameterNodes(XmlDocument document, CommandInfo command) - { - // Arguments - foreach (var argument in command.Parameters.OfType().OrderBy(x => x.Position)) - { - var node = document.CreateElement("Argument"); - node.SetNullableAttribute("Name", argument.Value); - node.SetAttribute("Position", argument.Position.ToString(CultureInfo.InvariantCulture)); - node.SetBooleanAttribute("Required", argument.IsRequired); - node.SetEnumAttribute("Kind", argument.ParameterKind); - node.SetNullableAttribute("ClrType", argument.ParameterType?.FullName); - - if (!string.IsNullOrWhiteSpace(argument.Description)) - { - var descriptionNode = document.CreateElement("Description"); - descriptionNode.InnerText = argument.Description; - node.AppendChild(descriptionNode); - } - - if (argument.Validators.Count > 0) - { - var validatorRootNode = document.CreateElement("Validators"); - foreach (var validator in argument.Validators.OrderBy(x => x.GetType().FullName)) - { - var validatorNode = document.CreateElement("Validator"); - validatorNode.SetNullableAttribute("ClrType", validator.GetType().FullName); - validatorNode.SetNullableAttribute("Message", validator.ErrorMessage); - validatorRootNode.AppendChild(validatorNode); - } - - node.AppendChild(validatorRootNode); - } - - yield return node; - } - - // Options - foreach (var option in command.Parameters.OfType() - .Where(x => !x.IsHidden) - .OrderBy(x => string.Join(",", x.LongNames)) - .ThenBy(x => string.Join(",", x.ShortNames))) - { - var node = document.CreateElement("Option"); - - if (option.IsShadowed) - { - node.SetBooleanAttribute("Shadowed", true); - } - - node.SetNullableAttribute("Short", option.ShortNames); - node.SetNullableAttribute("Long", option.LongNames); - node.SetNullableAttribute("Value", option.ValueName); - node.SetBooleanAttribute("Required", option.IsRequired); - node.SetEnumAttribute("Kind", option.ParameterKind); - node.SetNullableAttribute("ClrType", option.ParameterType?.FullName); - - if (!string.IsNullOrWhiteSpace(option.Description)) - { - var descriptionNode = document.CreateElement("Description"); - descriptionNode.InnerText = option.Description; - node.AppendChild(descriptionNode); - } - - yield return node; - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Composer.cs b/src/Spectre.Console.Cli/Internal/Composer.cs deleted file mode 100644 index 0032f1458..000000000 --- a/src/Spectre.Console.Cli/Internal/Composer.cs +++ /dev/null @@ -1,143 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class Composer : IRenderable -{ - private readonly StringBuilder _content; - - /// - /// Whether to emit the markup styles, inline, when rendering the content. - /// - 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; - } - - public Composer Style(string style, Action action) - { - _content.Append('[').Append(style).Append(']'); - action(this); - _content.Append("[/]"); - - return this; - } - - public Composer Space() - { - return Spaces(1); - } - - public Composer Spaces(int count) - { - return Repeat(' ', count); - } - - public Composer Tab() - { - return Tabs(1); - } - - public Composer Tabs(int count) - { - return Spaces(count * 4); - } - - public Composer Repeat(char character, int count) - { - _content.Append(new string(character, count)); - return this; - } - - public Composer LineBreak() - { - return LineBreaks(1); - } - - public Composer LineBreaks(int count) - { - for (var i = 0; i < count; i++) - { - _content.Append(Environment.NewLine); - } - - return this; - } - - public Composer Join(string separator, IEnumerable composers) - { - if (composers != null) - { - foreach (var composer in composers) - { - if (_content.ToString().Length > 0) - { - Text(separator); - } - - Text(composer.ToString()); - } - } - - return this; - } - - public Measurement Measure(RenderOptions options, int maxWidth) - { - if (_renderMarkup) - { - return ((IRenderable)new Paragraph(_content.ToString())).Measure(options, maxWidth); - } - else - { - return ((IRenderable)new Markup(_content.ToString())).Measure(options, maxWidth); - } - } - - public IEnumerable Render(RenderOptions options, int 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() - { - return _content.ToString(); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Composition/Activators.cs b/src/Spectre.Console.Cli/Internal/Composition/Activators.cs deleted file mode 100644 index 9e8d06dec..000000000 --- a/src/Spectre.Console.Cli/Internal/Composition/Activators.cs +++ /dev/null @@ -1,128 +0,0 @@ -namespace Spectre.Console.Cli; - -internal abstract class ComponentActivator -{ - public abstract object Activate(DefaultTypeResolver container); - - public abstract ComponentActivator CreateCopy(); -} - -internal class CachingActivator : ComponentActivator -{ - private readonly ComponentActivator _activator; - private object? _result; - - public CachingActivator(ComponentActivator activator) - { - _activator = activator ?? throw new ArgumentNullException(nameof(activator)); - _result = null; - } - - public override object Activate(DefaultTypeResolver container) - { - return _result ??= _activator.Activate(container); - } - - public override ComponentActivator CreateCopy() - { - return new CachingActivator(_activator.CreateCopy()); - } -} - -internal sealed class InstanceActivator : ComponentActivator -{ - private readonly object _instance; - - public InstanceActivator(object instance) - { - _instance = instance; - } - - public override object Activate(DefaultTypeResolver container) - { - return _instance; - } - - public override ComponentActivator CreateCopy() - { - return new InstanceActivator(_instance); - } -} - -internal sealed class ReflectionActivator : ComponentActivator -{ - private readonly Type _type; - private readonly ConstructorInfo _constructor; - private readonly List _parameters; - - public ReflectionActivator(Type type) - { - _type = type; - _constructor = GetGreediestConstructor(type); - _parameters = new List(); - - foreach (var parameter in _constructor.GetParameters()) - { - _parameters.Add(parameter); - } - } - - public override object Activate(DefaultTypeResolver container) - { - var parameters = new object?[_parameters.Count]; - for (var i = 0; i < _parameters.Count; i++) - { - var parameter = _parameters[i]; - if (parameter.ParameterType == typeof(DefaultTypeResolver)) - { - parameters[i] = container; - } - else - { - var resolved = container.Resolve(parameter.ParameterType); - if (resolved == null) - { - if (!parameter.IsOptional) - { - throw new InvalidOperationException($"Could not find registration for '{parameter.ParameterType.FullName}'."); - } - - parameters[i] = null; - } - else - { - parameters[i] = resolved; - } - } - } - - return _constructor.Invoke(parameters); - } - - public override ComponentActivator CreateCopy() - { - return new ReflectionActivator(_type); - } - - private static ConstructorInfo GetGreediestConstructor(Type type) - { - ConstructorInfo? current = null; - var count = -1; - foreach (var constructor in type.GetTypeInfo().GetConstructors()) - { - var parameters = constructor.GetParameters(); - if (parameters.Length > count) - { - count = parameters.Length; - current = constructor; - } - } - - if (current == null) - { - throw new InvalidOperationException($"Could not find a constructor for '{type.FullName}'."); - } - - return current; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Composition/ComponentRegistration.cs b/src/Spectre.Console.Cli/Internal/Composition/ComponentRegistration.cs deleted file mode 100644 index 5b5d66627..000000000 --- a/src/Spectre.Console.Cli/Internal/Composition/ComponentRegistration.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class ComponentRegistration -{ - public Type ImplementationType { get; } - public ComponentActivator Activator { get; } - public IReadOnlyList RegistrationTypes { get; } - - public ComponentRegistration(Type type, ComponentActivator activator, IEnumerable? registrationTypes = null) - { - var registrations = new List(registrationTypes ?? Array.Empty()); - if (registrations.Count == 0) - { - // Every registration needs at least one registration type. - registrations.Add(type); - } - - ImplementationType = type; - RegistrationTypes = registrations; - Activator = activator ?? throw new ArgumentNullException(nameof(activator)); - } - - public ComponentRegistration CreateCopy() - { - return new ComponentRegistration(ImplementationType, Activator.CreateCopy(), RegistrationTypes); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Composition/ComponentRegistry.cs b/src/Spectre.Console.Cli/Internal/Composition/ComponentRegistry.cs deleted file mode 100644 index 1408845d3..000000000 --- a/src/Spectre.Console.Cli/Internal/Composition/ComponentRegistry.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class ComponentRegistry : IDisposable -{ - private readonly Dictionary> _registrations; - - public ComponentRegistry() - { - _registrations = new Dictionary>(); - } - - public ComponentRegistry CreateCopy() - { - var registry = new ComponentRegistry(); - foreach (var registration in _registrations.SelectMany(p => p.Value)) - { - registry.Register(registration.CreateCopy()); - } - - return registry; - } - - public void Dispose() - { - foreach (var registration in _registrations) - { - registration.Value.Clear(); - } - - _registrations.Clear(); - } - - public void Register(ComponentRegistration registration) - { - foreach (var type in new HashSet(registration.RegistrationTypes)) - { - if (!_registrations.ContainsKey(type)) - { - // Only add each registration type once. - _registrations.Add(type, new HashSet()); - } - - _registrations[type].Add(registration); - } - } - - public ICollection GetRegistrations(Type type) - { - if (_registrations.ContainsKey(type)) - { - return _registrations[type]; - } - - return new List(); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Composition/DefaultTypeRegistrar.cs b/src/Spectre.Console.Cli/Internal/Composition/DefaultTypeRegistrar.cs deleted file mode 100644 index 5672fca53..000000000 --- a/src/Spectre.Console.Cli/Internal/Composition/DefaultTypeRegistrar.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class DefaultTypeRegistrar : ITypeRegistrar -{ - private readonly Queue> _registry; - - public DefaultTypeRegistrar() - { - _registry = new Queue>(); - } - - public ITypeResolver Build() - { - var container = new DefaultTypeResolver(); - while (_registry.Count > 0) - { - var action = _registry.Dequeue(); - action(container.Registry); - } - - return container; - } - - public void Register(Type service, Type implementation) - { - var registration = new ComponentRegistration(implementation, new ReflectionActivator(implementation), new[] { service }); - _registry.Enqueue(registry => registry.Register(registration)); - } - - public void RegisterInstance(Type service, object implementation) - { - var registration = new ComponentRegistration(service, new CachingActivator(new InstanceActivator(implementation))); - _registry.Enqueue(registry => registry.Register(registration)); - } - - public void RegisterLazy(Type service, Func factory) - { - if (factory is null) - { - throw new ArgumentNullException(nameof(factory)); - } - - _registry.Enqueue(registry => - { - var activator = new CachingActivator(new InstanceActivator(factory())); - var registration = new ComponentRegistration(service, activator); - - registry.Register(registration); - }); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Composition/DefaultTypeResolver.cs b/src/Spectre.Console.Cli/Internal/Composition/DefaultTypeResolver.cs deleted file mode 100644 index d59fbb3fb..000000000 --- a/src/Spectre.Console.Cli/Internal/Composition/DefaultTypeResolver.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class DefaultTypeResolver : IDisposable, ITypeResolver -{ - public ComponentRegistry Registry { get; } - - public DefaultTypeResolver() - : this(null) - { - } - - public DefaultTypeResolver(ComponentRegistry? registry) - { - Registry = registry ?? new ComponentRegistry(); - } - - public void Dispose() - { - Registry.Dispose(); - } - - public object? Resolve(Type? type) - { - if (type == null) - { - return null; - } - - var isEnumerable = false; - if (type.IsGenericType) - { - if (type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) - { - isEnumerable = true; - type = type.GenericTypeArguments[0]; - } - } - - var registrations = Registry.GetRegistrations(type); - if (registrations != null) - { - if (isEnumerable) - { - var result = Array.CreateInstance(type, registrations.Count); - for (var index = 0; index < registrations.Count; index++) - { - var registration = registrations.ElementAt(index); - result.SetValue(Resolve(registration), index); - } - - return result; - } - } - - return Resolve(registrations?.LastOrDefault()); - } - - public object? Resolve(ComponentRegistration? registration) - { - return registration?.Activator?.Activate(this); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/BranchConfigurator.cs b/src/Spectre.Console.Cli/Internal/Configuration/BranchConfigurator.cs deleted file mode 100644 index 04c20a3e4..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/BranchConfigurator.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class BranchConfigurator : IBranchConfigurator -{ - public ConfiguredCommand Command { get; } - - public BranchConfigurator(ConfiguredCommand command) - { - Command = command; - } - - public IBranchConfigurator WithAlias(string alias) - { - Command.Aliases.Add(alias); - return this; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/CommandAppSettings.cs b/src/Spectre.Console.Cli/Internal/Configuration/CommandAppSettings.cs deleted file mode 100644 index 65b669072..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/CommandAppSettings.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandAppSettings : ICommandAppSettings -{ - public CultureInfo? Culture { get; set; } - public string? ApplicationName { get; set; } - public string? ApplicationVersion { get; set; } - public int MaximumIndirectExamples { get; set; } - public bool ShowOptionDefaultValues { get; set; } - public IAnsiConsole? Console { get; set; } - [Obsolete("Register the interceptor with the ITypeRegistrar.")] - public ICommandInterceptor? Interceptor { get; set; } - public ITypeRegistrarFrontend Registrar { get; set; } - public CaseSensitivity CaseSensitivity { get; set; } - public bool PropagateExceptions { get; set; } - public bool ValidateExamples { get; set; } - public bool TrimTrailingPeriod { get; set; } - public HelpProviderStyle? HelpProviderStyles { get; set; } - public bool StrictParsing { get; set; } - public bool ConvertFlagsToRemainingArguments { get; set; } - public int CancellationExitCode { get; set; } - - public ParsingMode ParsingMode => - StrictParsing ? ParsingMode.Strict : ParsingMode.Relaxed; - - public Func? ExceptionHandler { get; set; } - - public CommandAppSettings(ITypeRegistrar registrar) - { - Registrar = new TypeRegistrar(registrar); - CaseSensitivity = CaseSensitivity.All; - ShowOptionDefaultValues = true; - MaximumIndirectExamples = 5; - TrimTrailingPeriod = true; - HelpProviderStyles = HelpProviderStyle.Default; - ConvertFlagsToRemainingArguments = false; - CancellationExitCode = 130; - } - - public bool IsTrue(Func func, string environmentVariableName) - { - if (func(this)) - { - return true; - } - - var environmentVariable = Environment.GetEnvironmentVariable(environmentVariableName); - if (!string.IsNullOrWhiteSpace(environmentVariable)) - { - if (environmentVariable.Equals("True", StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - - return false; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/CommandConfigurator.cs b/src/Spectre.Console.Cli/Internal/Configuration/CommandConfigurator.cs deleted file mode 100644 index 64c031bcb..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/CommandConfigurator.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandConfigurator : ICommandConfigurator -{ - public ConfiguredCommand Command { get; } - - public CommandConfigurator(ConfiguredCommand command) - { - Command = command; - } - - public ICommandConfigurator WithExample(params string[] args) - { - Command.Examples.Add(args); - return this; - } - - public ICommandConfigurator WithAlias(string alias) - { - Command.Aliases.Add(alias); - return this; - } - - public ICommandConfigurator WithDescription(string description) - { - Command.Description = description; - return this; - } - - public ICommandConfigurator WithData(object data) - { - Command.Data = data; - return this; - } - - public ICommandConfigurator IsHidden() - { - Command.IsHidden = true; - return this; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/ConfigurationHelper.cs b/src/Spectre.Console.Cli/Internal/Configuration/ConfigurationHelper.cs deleted file mode 100644 index 405a6c8a8..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/ConfigurationHelper.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class ConfigurationHelper -{ - public static Type? GetSettingsType(Type commandType) - { - if (typeof(ICommand).GetTypeInfo().IsAssignableFrom(commandType) && - GetGenericTypeArguments(commandType, typeof(ICommand<>), out var result)) - { - return result[0]; - } - - return null; - } - - private static bool GetGenericTypeArguments(Type? type, Type genericType, - [NotNullWhen(true)] out Type[]? genericTypeArguments) - { - while (type != null) - { - foreach (var @interface in type.GetTypeInfo().GetInterfaces()) - { - if (!@interface.GetTypeInfo().IsGenericType || @interface.GetGenericTypeDefinition() != genericType) - { - continue; - } - - genericTypeArguments = @interface.GenericTypeArguments; - return true; - } - - type = type.GetTypeInfo().BaseType; - } - - genericTypeArguments = null; - return false; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs b/src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs deleted file mode 100644 index 4605e0114..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs +++ /dev/null @@ -1,117 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class Configurator : IUnsafeConfigurator, IConfigurator, IConfiguration -{ - private readonly ITypeRegistrar _registrar; - - public IList Commands { get; } - public CommandAppSettings Settings { get; } - public ConfiguredCommand? DefaultCommand { get; private set; } - public IList Examples { get; } - - ICommandAppSettings IConfigurator.Settings => Settings; - - public Configurator(ITypeRegistrar registrar) - { - _registrar = registrar; - - Commands = new List(); - Settings = new CommandAppSettings(registrar); - Examples = new List(); - } - - public IConfigurator SetHelpProvider(IHelpProvider helpProvider) - { - // Register the help provider - _registrar.RegisterInstance(typeof(IHelpProvider), helpProvider); - return this; - } - - public IConfigurator SetHelpProvider() - where T : IHelpProvider - { - // Register the help provider - _registrar.Register(typeof(IHelpProvider), typeof(T)); - return this; - } - - public IConfigurator AddExample(params string[] args) - { - Examples.Add(args); - return this; - } - - public ConfiguredCommand SetDefaultCommand() - where TDefaultCommand : class, ICommand - { - DefaultCommand = ConfiguredCommand.FromType( - CliConstants.DefaultCommandName, isDefaultCommand: true); - return DefaultCommand; - } - - public ICommandConfigurator AddCommand(string name) - where TCommand : class, ICommand - { - var command = Commands.AddAndReturn(ConfiguredCommand.FromType(name, isDefaultCommand: false)); - return new CommandConfigurator(command); - } - - public ICommandConfigurator AddDelegate(string name, Func func) - where TSettings : CommandSettings - { - var command = Commands.AddAndReturn(ConfiguredCommand.FromDelegate( - name, (context, settings, cancellationToken) => Task.FromResult(func(context, (TSettings)settings, cancellationToken)))); - return new CommandConfigurator(command); - } - - public ICommandConfigurator AddAsyncDelegate(string name, Func> func) - where TSettings : CommandSettings - { - var command = Commands.AddAndReturn(ConfiguredCommand.FromDelegate( - name, (context, settings, cancellationToken) => func(context, (TSettings)settings, cancellationToken))); - return new CommandConfigurator(command); - } - - public IBranchConfigurator AddBranch(string name, Action> action) - where TSettings : CommandSettings - { - var command = ConfiguredCommand.FromBranch(name); - action(new Configurator(command, _registrar)); - var added = Commands.AddAndReturn(command); - return new BranchConfigurator(added); - } - - ICommandConfigurator IUnsafeConfigurator.AddCommand(string name, Type command) - { - var method = GetType().GetMethod("AddCommand"); - if (method == null) - { - throw new CommandConfigurationException("Could not find AddCommand by reflection."); - } - - method = method.MakeGenericMethod(command); - - if (!(method.Invoke(this, new object[] { name }) is ICommandConfigurator result)) - { - throw new CommandConfigurationException("Invoking AddCommand returned null."); - } - - return result; - } - - IBranchConfigurator IUnsafeConfigurator.AddBranch(string name, Type settings, Action action) - { - var command = ConfiguredCommand.FromBranch(settings, name); - - // Create the configurator. - var configuratorType = typeof(Configurator<>).MakeGenericType(settings); - if (!(Activator.CreateInstance(configuratorType, new object?[] { command, _registrar }) is IUnsafeBranchConfigurator configurator)) - { - throw new CommandConfigurationException("Could not create configurator by reflection."); - } - - action(configurator); - var added = Commands.AddAndReturn(command); - return new BranchConfigurator(added); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/ConfiguratorOfT.cs b/src/Spectre.Console.Cli/Internal/Configuration/ConfiguratorOfT.cs deleted file mode 100644 index 05c8ef958..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/ConfiguratorOfT.cs +++ /dev/null @@ -1,111 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class Configurator : IUnsafeBranchConfigurator, IConfigurator - where TSettings : CommandSettings -{ - private readonly ConfiguredCommand _command; - private readonly ITypeRegistrar? _registrar; - - public Configurator(ConfiguredCommand command, ITypeRegistrar? registrar) - { - _command = command; - _registrar = registrar; - } - - public void SetDescription(string description) - { - _command.Description = description; - } - - public void AddExample(params string[] args) - { - _command.Examples.Add(args); - } - - public void SetDefaultCommand() - where TDefaultCommand : class, ICommandLimiter - { - var defaultCommand = ConfiguredCommand.FromType( - CliConstants.DefaultCommandName, isDefaultCommand: true); - - _command.Children.Add(defaultCommand); - } - - public void HideBranch() - { - _command.IsHidden = true; - } - - public ICommandConfigurator AddCommand(string name) - where TCommand : class, ICommandLimiter - { - var command = ConfiguredCommand.FromType(name, isDefaultCommand: false); - var configurator = new CommandConfigurator(command); - - _command.Children.Add(command); - return configurator; - } - - public ICommandConfigurator AddDelegate(string name, Func func) - where TDerivedSettings : TSettings - { - var command = ConfiguredCommand.FromDelegate( - name, (context, settings, cancellationToken) => Task.FromResult(func(context, (TDerivedSettings)settings, cancellationToken))); - - _command.Children.Add(command); - return new CommandConfigurator(command); - } - - public ICommandConfigurator AddAsyncDelegate(string name, Func> func) - where TDerivedSettings : TSettings - { - var command = ConfiguredCommand.FromDelegate( - name, (context, settings, cancellationToken) => func(context, (TDerivedSettings)settings, cancellationToken)); - - _command.Children.Add(command); - return new CommandConfigurator(command); - } - - public IBranchConfigurator AddBranch(string name, Action> action) - where TDerivedSettings : TSettings - { - var command = ConfiguredCommand.FromBranch(name); - action(new Configurator(command, _registrar)); - var added = _command.Children.AddAndReturn(command); - return new BranchConfigurator(added); - } - - ICommandConfigurator IUnsafeConfigurator.AddCommand(string name, Type command) - { - var method = GetType().GetMethod("AddCommand"); - if (method == null) - { - throw new CommandConfigurationException("Could not find AddCommand by reflection."); - } - - method = method.MakeGenericMethod(command); - - if (!(method.Invoke(this, new object[] { name }) is ICommandConfigurator result)) - { - throw new CommandConfigurationException("Invoking AddCommand returned null."); - } - - return result; - } - - IBranchConfigurator IUnsafeConfigurator.AddBranch(string name, Type settings, Action action) - { - var command = ConfiguredCommand.FromBranch(settings, name); - - // Create the configurator. - var configuratorType = typeof(Configurator<>).MakeGenericType(settings); - if (!(Activator.CreateInstance(configuratorType, new object?[] { command, _registrar }) is IUnsafeBranchConfigurator configurator)) - { - throw new CommandConfigurationException("Could not create configurator by reflection."); - } - - action(configurator); - var added = _command.Children.AddAndReturn(command); - return new BranchConfigurator(added); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/ConfiguredCommand.cs b/src/Spectre.Console.Cli/Internal/Configuration/ConfiguredCommand.cs deleted file mode 100644 index 75ad9ddba..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/ConfiguredCommand.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class ConfiguredCommand -{ - public string Name { get; } - public HashSet Aliases { get; } - public string? Description { get; set; } - public object? Data { get; set; } - public Type? CommandType { get; } - public Type SettingsType { get; } - public Func>? Delegate { get; } - public bool IsDefaultCommand { get; } - public bool IsHidden { get; set; } - - public IList Children { get; } - public IList Examples { get; } - - private ConfiguredCommand( - string name, - Type? commandType, - Type settingsType, - Func>? @delegate, - bool isDefaultCommand) - { - Name = name; - Aliases = new HashSet(StringComparer.OrdinalIgnoreCase); - CommandType = commandType; - SettingsType = settingsType; - Delegate = @delegate; - IsDefaultCommand = isDefaultCommand; - - // Default commands are always created as hidden. - IsHidden = IsDefaultCommand; - - Children = new List(); - Examples = new List(); - } - - public static ConfiguredCommand FromBranch(Type settings, string name) - { - return new ConfiguredCommand(name, null, settings, null, false); - } - - public static ConfiguredCommand FromBranch(string name) - where TSettings : CommandSettings - { - return new ConfiguredCommand(name, null, typeof(TSettings), null, false); - } - - public static ConfiguredCommand FromType(string name, bool isDefaultCommand = false) - where TCommand : class, ICommand - { - var settingsType = ConfigurationHelper.GetSettingsType(typeof(TCommand)); - if (settingsType == null) - { - throw CommandRuntimeException.CouldNotGetSettingsType(typeof(TCommand)); - } - - return new ConfiguredCommand(name, typeof(TCommand), settingsType, null, isDefaultCommand); - } - - public static ConfiguredCommand FromDelegate( - string name, Func>? @delegate = null) - where TSettings : CommandSettings - { - return new ConfiguredCommand(name, null, typeof(TSettings), @delegate, false); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/DefaultCommandConfigurator.cs b/src/Spectre.Console.Cli/Internal/Configuration/DefaultCommandConfigurator.cs deleted file mode 100644 index a11432bb6..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/DefaultCommandConfigurator.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace Spectre.Console.Cli.Internal.Configuration; - -/// -/// Fluent configurator for the default command. -/// -public sealed class DefaultCommandConfigurator -{ - private readonly ConfiguredCommand _defaultCommand; - - internal DefaultCommandConfigurator(ConfiguredCommand defaultCommand) - { - _defaultCommand = defaultCommand; - } - - /// - /// Sets the description of the default command. - /// - /// The default command description. - /// The same instance so that multiple calls can be chained. - public DefaultCommandConfigurator WithDescription(string description) - { - _defaultCommand.Description = description; - return this; - } - - /// - /// Sets data that will be passed to the command via the . - /// - /// The data to pass to the default command. - /// The same instance so that multiple calls can be chained. - public DefaultCommandConfigurator WithData(object data) - { - _defaultCommand.Data = data; - return this; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/IConfiguration.cs b/src/Spectre.Console.Cli/Internal/Configuration/IConfiguration.cs deleted file mode 100644 index 8aca96985..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/IConfiguration.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a configuration. -/// -internal interface IConfiguration -{ - /// - /// Gets the configured commands. - /// - IList Commands { get; } - - /// - /// Gets the settings for the configuration. - /// - CommandAppSettings Settings { get; } - - /// - /// Gets the default command for the configuration. - /// - ConfiguredCommand? DefaultCommand { get; } - - /// - /// Gets all examples for the configuration. - /// - IList Examples { get; } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/TemplateParser.cs b/src/Spectre.Console.Cli/Internal/Configuration/TemplateParser.cs deleted file mode 100644 index 6eb7c2000..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/TemplateParser.cs +++ /dev/null @@ -1,146 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class TemplateParser -{ - public sealed class ArgumentResult - { - public string Value { get; set; } - public bool IsRequired { get; set; } - - public ArgumentResult(string value, bool isRequired) - { - Value = value; - IsRequired = isRequired; - } - } - - public sealed class OptionResult - { - public List LongNames { get; set; } - public List ShortNames { get; set; } - public string? Value { get; set; } - public bool ValueIsOptional { get; set; } - - public OptionResult() - { - ShortNames = new List(); - LongNames = new List(); - } - } - - public static ArgumentResult ParseArgumentTemplate(string template) - { - var valueName = default(string); - var required = false; - foreach (var token in TemplateTokenizer.Tokenize(template)) - { - if (token.TokenKind == TemplateToken.Kind.ShortName || - token.TokenKind == TemplateToken.Kind.LongName) - { - throw CommandTemplateException.ArgumentCannotContainOptions(template, token); - } - - if (token.TokenKind == TemplateToken.Kind.OptionalValue || - token.TokenKind == TemplateToken.Kind.RequiredValue) - { - if (!string.IsNullOrWhiteSpace(valueName)) - { - throw CommandTemplateException.MultipleValuesAreNotSupported(template, token); - } - - if (string.IsNullOrWhiteSpace(token.Value)) - { - throw CommandTemplateException.ValuesMustHaveName(template, token); - } - - valueName = token.Value; - required = token.TokenKind == TemplateToken.Kind.RequiredValue; - } - } - - if (valueName == null) - { - throw CommandTemplateException.ArgumentsMustHaveValueName(template); - } - - return new ArgumentResult(valueName, required); - } - - public static OptionResult ParseOptionTemplate(string template) - { - var result = new OptionResult(); - - foreach (var token in TemplateTokenizer.Tokenize(template)) - { - if (token.TokenKind == TemplateToken.Kind.LongName || token.TokenKind == TemplateToken.Kind.ShortName) - { - if (string.IsNullOrWhiteSpace(token.Value)) - { - throw CommandTemplateException.OptionsMustHaveName(template, token); - } - - if (char.IsDigit(token.Value[0])) - { - throw CommandTemplateException.OptionNamesCannotStartWithDigit(template, token); - } - - foreach (var character in token.Value) - { - if (!char.IsLetterOrDigit(character) && character != '-' && character != '_' && character != '?') - { - throw CommandTemplateException.InvalidCharacterInOptionName(template, token, character); - } - } - } - - if (token.TokenKind == TemplateToken.Kind.LongName) - { - if (token.Value.Length == 1) - { - throw CommandTemplateException.LongOptionMustHaveMoreThanOneCharacter(template, token); - } - - result.LongNames.Add(token.Value); - } - - if (token.TokenKind == TemplateToken.Kind.ShortName) - { - if (token.Value.Length > 1) - { - throw CommandTemplateException.ShortOptionMustOnlyBeOneCharacter(template, token); - } - - result.ShortNames.Add(token.Value); - } - - if (token.TokenKind == TemplateToken.Kind.RequiredValue || - token.TokenKind == TemplateToken.Kind.OptionalValue) - { - if (!string.IsNullOrWhiteSpace(result.Value)) - { - throw CommandTemplateException.MultipleOptionValuesAreNotSupported(template, token); - } - - foreach (var character in token.Value) - { - if (!char.IsLetterOrDigit(character) && - character != '=' && character != '-' && character != '_' && character != '|') - { - throw CommandTemplateException.InvalidCharacterInValueName(template, token, character); - } - } - - result.Value = token.Value.ToUpperInvariant(); - result.ValueIsOptional = token.TokenKind == TemplateToken.Kind.OptionalValue; - } - } - - if (result.LongNames.Count == 0 && - result.ShortNames.Count == 0) - { - throw CommandTemplateException.MissingLongAndShortName(template, null); - } - - return result; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/TemplateToken.cs b/src/Spectre.Console.Cli/Internal/Configuration/TemplateToken.cs deleted file mode 100644 index a5f7a4878..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/TemplateToken.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class TemplateToken -{ - public Kind TokenKind { get; } - public int Position { get; } - public string Value { get; } - public string Representation { get; } - - public TemplateToken(Kind kind, int position, string value, string representation) - { - TokenKind = kind; - Position = position; - Value = value; - Representation = representation; - } - - public enum Kind - { - Unknown = 0, - LongName, - ShortName, - RequiredValue, - OptionalValue, - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/TemplateTokenizer.cs b/src/Spectre.Console.Cli/Internal/Configuration/TemplateTokenizer.cs deleted file mode 100644 index 932a37ba6..000000000 --- a/src/Spectre.Console.Cli/Internal/Configuration/TemplateTokenizer.cs +++ /dev/null @@ -1,131 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class TemplateTokenizer -{ - public static IReadOnlyList Tokenize(string template) - { - using var buffer = new TextBuffer(template); - var result = new List(); - - while (!buffer.ReachedEnd) - { - EatWhitespace(buffer); - - if (!buffer.TryPeek(out var character)) - { - break; - } - - if (character == '-') - { - result.Add(ReadOption(buffer)); - } - else if (character == '|') - { - buffer.Consume('|'); - } - else if (character == '<') - { - result.Add(ReadValue(buffer, true)); - } - else if (character == '[') - { - result.Add(ReadValue(buffer, false)); - } - else - { - throw CommandTemplateException.UnexpectedCharacter(buffer.Original, buffer.Position, character); - } - } - - return result; - } - - private static void EatWhitespace(TextBuffer buffer) - { - while (!buffer.ReachedEnd) - { - var character = buffer.Peek(); - if (!char.IsWhiteSpace(character)) - { - break; - } - - buffer.Read(); - } - } - - private static TemplateToken ReadOption(TextBuffer buffer) - { - var position = buffer.Position; - - buffer.Consume('-'); - if (buffer.IsNext('-')) - { - buffer.Consume('-'); - var longValue = ReadOptionName(buffer); - return new TemplateToken(TemplateToken.Kind.LongName, position, longValue, $"--{longValue}"); - } - - var shortValue = ReadOptionName(buffer); - return new TemplateToken(TemplateToken.Kind.ShortName, position, shortValue, $"-{shortValue}"); - } - - private static string ReadOptionName(TextBuffer buffer) - { - var builder = new StringBuilder(); - while (!buffer.ReachedEnd) - { - var character = buffer.Peek(); - if (char.IsWhiteSpace(character) || character == '|') - { - break; - } - - builder.Append(buffer.Read()); - } - - return builder.ToString(); - } - - private static TemplateToken ReadValue(TextBuffer buffer, bool required) - { - var start = required ? '<' : '['; - var end = required ? '>' : ']'; - - var position = buffer.Position; - var kind = required ? TemplateToken.Kind.RequiredValue : TemplateToken.Kind.OptionalValue; - - // Consume start of value character (< or [). - buffer.Consume(start); - - var builder = new StringBuilder(); - while (!buffer.ReachedEnd) - { - var character = buffer.Peek(); - if (character == end) - { - break; - } - - buffer.Read(); - builder.Append(character); - } - - if (buffer.ReachedEnd) - { - var name = builder.ToString(); - var token = new TemplateToken(kind, position, name, $"{start}{name}"); - throw CommandTemplateException.UnterminatedValueName(buffer.Original, token); - } - - // Consume end of value character (> or ]). - buffer.Consume(end); - - // Get the value (the text within the brackets). - var value = builder.ToString(); - - // Create a token and return it. - return new TemplateToken(kind, position, value, required ? $"<{value}>" : $"[{value}]"); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Constants.cs b/src/Spectre.Console.Cli/Internal/Constants.cs deleted file mode 100644 index 661af7c1e..000000000 --- a/src/Spectre.Console.Cli/Internal/Constants.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CliConstants -{ - public const string DefaultCommandName = "__default_command"; - public const string True = "true"; - public const string False = "false"; - public const string DumpHelpOpenCliOption = "--help-dump-opencli"; - - public static string[] AcceptedBooleanValues { get; } = new string[] - { - True, - False, - }; - - public static class Commands - { - public const string Branch = "cli"; - public const string Version = "version"; - public const string XmlDoc = "xmldoc"; - public const string Explain = "explain"; - public const string OpenCli = "opencli"; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/DefaultPairDeconstructor.cs b/src/Spectre.Console.Cli/Internal/DefaultPairDeconstructor.cs deleted file mode 100644 index 8d1e73ebe..000000000 --- a/src/Spectre.Console.Cli/Internal/DefaultPairDeconstructor.cs +++ /dev/null @@ -1,71 +0,0 @@ -namespace Spectre.Console.Cli; - -[SuppressMessage("Performance", "CA1812: Avoid uninstantiated internal classes")] -internal sealed class DefaultPairDeconstructor : IPairDeconstructor -{ - /// - (object? Key, object? Value) IPairDeconstructor.Deconstruct( - ITypeResolver resolver, - Type keyType, - Type valueType, - string? value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - var parts = value.Split(new[] { '=' }, StringSplitOptions.None); - if (parts.Length < 1 || parts.Length > 2) - { - throw CommandParseException.ValueIsNotInValidFormat(value); - } - - var stringkey = parts[0]; - var stringValue = parts.Length == 2 ? parts[1] : null; - if (stringValue == null) - { - // Got a default constructor? - if (valueType.IsValueType) - { - // Get the string variant of a default instance. - // Should not get null here, but compiler doesn't know that. - stringValue = Activator.CreateInstance(valueType)?.ToString() ?? string.Empty; - } - else - { - // Try with an empty string. - // Hopefully, the type converter knows how to convert it. - stringValue = string.Empty; - } - } - - return (Parse(stringkey, keyType), - Parse(stringValue, valueType)); - } - - private static object? Parse(string value, Type targetType) - { - try - { - var converter = GetConverter(targetType); - return converter.ConvertFrom(value); - } - catch - { - // Can't convert something. Just give up and tell the user. - throw CommandParseException.ValueIsNotInValidFormat(value); - } - } - - private static TypeConverter GetConverter(Type type) - { - var converter = TypeDescriptor.GetConverter(type); - if (converter != null) - { - return converter; - } - - throw new CommandConfigurationException($"Could find a type converter for '{type.FullName}'."); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/DelegateCommand.cs b/src/Spectre.Console.Cli/Internal/DelegateCommand.cs deleted file mode 100644 index 30825bcb0..000000000 --- a/src/Spectre.Console.Cli/Internal/DelegateCommand.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class DelegateCommand : ICommand -{ - private readonly Func> _func; - - public DelegateCommand(Func> func) - { - _func = func; - } - - public Task ExecuteAsync(CommandContext context, CommandSettings settings, CancellationToken cancellationToken) - { - return _func(context, settings, cancellationToken); - } - - public ValidationResult Validate(CommandContext context, CommandSettings settings) - { - return ValidationResult.Success(); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Exceptions/CommandLineParseExceptionFactory.cs b/src/Spectre.Console.Cli/Internal/Exceptions/CommandLineParseExceptionFactory.cs deleted file mode 100644 index 20542065f..000000000 --- a/src/Spectre.Console.Cli/Internal/Exceptions/CommandLineParseExceptionFactory.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandLineParseExceptionFactory -{ - internal static CommandParseException Create(string arguments, CommandTreeToken token, string message, string details) - { - return new CommandParseException(message, CreatePrettyMessage(arguments, token, message, details)); - } - - internal static CommandParseException Create(IEnumerable arguments, CommandTreeToken token, string message, string details) - { - return new CommandParseException(message, CreatePrettyMessage(string.Join(" ", arguments), token, message, details)); - } - - private static IRenderable CreatePrettyMessage(string arguments, CommandTreeToken token, string message, string details) - { - var composer = new Composer(); - - var position = token?.Position ?? 0; - var value = token?.Representation ?? arguments; - - // Header - composer.LineBreak(); - composer.Style("red", "Error:"); - composer.Space().Text(message.EscapeMarkup()); - composer.LineBreak(); - - // Template - composer.LineBreak(); - composer.Spaces(7).Text(arguments.EscapeMarkup()); - - // Error - composer.LineBreak(); - composer.Spaces(7).Spaces(position); - - composer.Style("red", error => - { - error.Repeat('^', value.Length); - error.Space(); - error.Text(details.TrimEnd('.').EscapeMarkup()); - error.LineBreak(); - }); - - composer.LineBreak(); - - return composer; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Exceptions/CommandLineTemplateExceptionFactory.cs b/src/Spectre.Console.Cli/Internal/Exceptions/CommandLineTemplateExceptionFactory.cs deleted file mode 100644 index 3e8d8a58f..000000000 --- a/src/Spectre.Console.Cli/Internal/Exceptions/CommandLineTemplateExceptionFactory.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandLineTemplateExceptionFactory -{ - internal static CommandTemplateException Create(string template, TemplateToken? token, string message, string details) - { - return new CommandTemplateException(message, template, CreatePrettyMessage(template, token, message, details)); - } - - private static IRenderable CreatePrettyMessage(string template, TemplateToken? token, string message, string details) - { - var composer = new Composer(); - - var position = token?.Position ?? 0; - var value = token?.Representation ?? template; - - // Header - composer.LineBreak(); - composer.Style("red", "Error:"); - composer.Space().Text("An error occured when parsing template."); - composer.LineBreak(); - composer.Spaces(7).Style("yellow", message.EscapeMarkup()); - composer.LineBreak(); - - if (string.IsNullOrWhiteSpace(template)) - { - // Error - composer.LineBreak(); - composer.Style("red", message.EscapeMarkup()); - composer.LineBreak(); - } - else - { - // Template - composer.LineBreak(); - composer.Spaces(7).Text(template.EscapeMarkup()); - - // Error - composer.LineBreak(); - composer.Spaces(7).Spaces(position); - composer.Style("red", error => - { - error.Repeat('^', value.Length); - error.Space(); - error.Text(details.TrimEnd('.').EscapeMarkup()); - error.LineBreak(); - }); - } - - composer.LineBreak(); - - return composer; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Extensions/AnsiConsoleExtensions.cs b/src/Spectre.Console.Cli/Internal/Extensions/AnsiConsoleExtensions.cs deleted file mode 100644 index 2e92f32b3..000000000 --- a/src/Spectre.Console.Cli/Internal/Extensions/AnsiConsoleExtensions.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class AnsiConsoleExtensions -{ - private static readonly Lazy _console; - - static AnsiConsoleExtensions() - { - _console = new Lazy(() => AnsiConsole.Console); - } - - public static IAnsiConsole GetConsole(this IAnsiConsole? console) - { - return console ?? _console.Value; - } - - public static void SafeRender(this IAnsiConsole? console, IRenderable? renderable) - { - if (renderable != null) - { - console ??= _console.Value; - console.Write(renderable); - } - } - - public static void SafeRender(this IAnsiConsole? console, IEnumerable renderables) - { - console ??= _console.Value; - foreach (var renderable in renderables) - { - if (renderable != null) - { - console.Write(renderable); - } - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Extensions/CaseSensitivityExtensions.cs b/src/Spectre.Console.Cli/Internal/Extensions/CaseSensitivityExtensions.cs deleted file mode 100644 index 1411618a5..000000000 --- a/src/Spectre.Console.Cli/Internal/Extensions/CaseSensitivityExtensions.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CaseSensitivityExtensions -{ - public static StringComparison GetStringComparison(this CaseSensitivity caseSensitivity, CommandPart part) - { - if (part == CommandPart.CommandName && (caseSensitivity & CaseSensitivity.Commands) == 0) - { - return StringComparison.OrdinalIgnoreCase; - } - else if (part == CommandPart.LongOption && (caseSensitivity & CaseSensitivity.LongOptions) == 0) - { - return StringComparison.OrdinalIgnoreCase; - } - - return StringComparison.Ordinal; - } - - public static StringComparer GetStringComparer(this CaseSensitivity caseSensitivity, CommandPart part) - { - if (part == CommandPart.CommandName && (caseSensitivity & CaseSensitivity.Commands) == 0) - { - return StringComparer.OrdinalIgnoreCase; - } - else if (part == CommandPart.LongOption && (caseSensitivity & CaseSensitivity.LongOptions) == 0) - { - return StringComparer.OrdinalIgnoreCase; - } - - return StringComparer.Ordinal; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Extensions/EnumerableExtensions.cs b/src/Spectre.Console.Cli/Internal/Extensions/EnumerableExtensions.cs deleted file mode 100644 index ea775cff5..000000000 --- a/src/Spectre.Console.Cli/Internal/Extensions/EnumerableExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class EnumerableExtensions -{ - public static IReadOnlyList ToSafeReadOnlyList(this IEnumerable source) - { - return source switch - { - null => new List(), - IReadOnlyList list => list, - _ => source.ToList(), - }; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Extensions/ListExtensions.cs b/src/Spectre.Console.Cli/Internal/Extensions/ListExtensions.cs deleted file mode 100644 index 0c6d3583c..000000000 --- a/src/Spectre.Console.Cli/Internal/Extensions/ListExtensions.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class ListExtensions -{ - public static void ForEach(this IEnumerable source, Action action) - { - if (source != null && action != null) - { - foreach (var item in source) - { - action(item); - } - } - } - - public static T AddAndReturn(this IList source, T item) - where T : class - { - source.Add(item); - return item; - } - - public static void AddIfNotNull(this IList source, T? item) - where T : class - { - if (item != null) - { - source.Add(item); - } - } - - public static void AddRangeIfNotNull(this IList source, IEnumerable items) - where T : class - { - foreach (var item in items) - { - if (item != null) - { - source.Add(item); - } - } - } - - public static void AddRange(this IList source, IEnumerable items) - { - foreach (var item in items) - { - source.Add(item); - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Extensions/OpenCliExtensions.cs b/src/Spectre.Console.Cli/Internal/Extensions/OpenCliExtensions.cs deleted file mode 100644 index 7856a106b..000000000 --- a/src/Spectre.Console.Cli/Internal/Extensions/OpenCliExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -#if NETSTANDARD2_0 -namespace System.IO; - -// Polyfills needed for OpenCli. -// This can be removed once me migrate over to the Polyfill library. -internal static class OpenCliExtensions -{ - public static Task ReadToEndAsync(this StreamReader reader, CancellationToken cancellationToken) - { - return reader.ReadToEndAsync(); - } -} -#endif \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Extensions/StringExtensions.cs b/src/Spectre.Console.Cli/Internal/Extensions/StringExtensions.cs deleted file mode 100644 index 2119e106d..000000000 --- a/src/Spectre.Console.Cli/Internal/Extensions/StringExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class StringExtensions -{ - internal static int OrdinalIndexOf(this string text, char token) - { -#if NETSTANDARD2_0 - return text.IndexOf(token); -#else - return text.IndexOf(token, System.StringComparison.Ordinal); -#endif - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Extensions/TypeExtensions.cs b/src/Spectre.Console.Cli/Internal/Extensions/TypeExtensions.cs deleted file mode 100644 index 543a37026..000000000 --- a/src/Spectre.Console.Cli/Internal/Extensions/TypeExtensions.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class TypeExtensions -{ - public static bool IsPairDeconstructable(this Type type) - { - if (type.IsGenericType) - { - if (type.GetGenericTypeDefinition() == typeof(ILookup<,>) || - type.GetGenericTypeDefinition() == typeof(IDictionary<,>) || - type.GetGenericTypeDefinition() == typeof(IReadOnlyDictionary<,>)) - { - return true; - } - } - - return false; - } - - // Taken from https://github.com/dotnet/sdk/blob/main/src/Cli/Microsoft.DotNet.Cli.Utils/Extensions/TypeExtensions.cs#L15 - // Licensed under MIT - public static string ToCliTypeString(this Type type) - { - var typeName = type.FullName ?? string.Empty; - if (!type.IsGenericType) - { - return typeName; - } - - var genericTypeName = typeName.Substring(0, typeName.IndexOf('`')); - var genericTypes = string.Join(", ", type.GenericTypeArguments.Select(generic => generic.ToCliTypeString())); - return $"{genericTypeName}<{genericTypes}>"; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Extensions/TypeRegistrarExtensions.cs b/src/Spectre.Console.Cli/Internal/Extensions/TypeRegistrarExtensions.cs deleted file mode 100644 index b2b149954..000000000 --- a/src/Spectre.Console.Cli/Internal/Extensions/TypeRegistrarExtensions.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class TypeRegistrarExtensions -{ - public static void RegisterDependencies(this ITypeRegistrar registrar, CommandModel model) - { - var stack = new Stack(); - model.Commands.ForEach(c => stack.Push(c)); - - while (stack.Count > 0) - { - var command = stack.Pop(); - - if (command.SettingsType == null) - { - // TODO: Error message - throw new InvalidOperationException("Command setting type cannot be null."); - } - - if (command.SettingsType is { IsAbstract: false, IsClass: true }) - { - // Register the settings type - registrar?.Register(command.SettingsType, command.SettingsType); - } - - if (command.CommandType != null) - { - registrar?.Register(command.CommandType, command.CommandType); - } - - foreach (var parameter in command.Parameters) - { - var pairDeconstructor = parameter?.PairDeconstructor?.Type; - if (pairDeconstructor != null) - { - registrar?.Register(pairDeconstructor, pairDeconstructor); - } - - var typeConverterTypeName = parameter?.Converter?.ConverterTypeName; - if (!string.IsNullOrWhiteSpace(typeConverterTypeName)) - { - var typeConverterType = Type.GetType(typeConverterTypeName); - Debug.Assert(typeConverterType != null, "Could not create type"); - registrar?.Register(typeConverterType, typeConverterType); - } - } - - foreach (var child in command.Children) - { - stack.Push(child); - } - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Extensions/XmlElementExtensions.cs b/src/Spectre.Console.Cli/Internal/Extensions/XmlElementExtensions.cs deleted file mode 100644 index a3b662674..000000000 --- a/src/Spectre.Console.Cli/Internal/Extensions/XmlElementExtensions.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class XmlElementExtensions -{ - public static void SetNullableAttribute(this XmlElement element, string name, string? value) - { - element.SetAttribute(name, value ?? "NULL"); - } - - public static void SetNullableAttribute(this XmlElement element, string name, IEnumerable? values) - { - if (values?.Any() != true) - { - element.SetAttribute(name, "NULL"); - } - - element.SetAttribute(name, string.Join(",", values ?? Enumerable.Empty())); - } - - public static void SetBooleanAttribute(this XmlElement element, string name, bool value) - { - element.SetAttribute(name, value ? "true" : "false"); - } - - public static void SetEnumAttribute(this XmlElement element, string name, Enum value) - { - var field = value.GetType().GetField(value.ToString()); - if (field != null) - { - var attribute = field.GetCustomAttribute(false); - if (attribute == null) - { - throw new InvalidOperationException("Enum is missing description."); - } - - element.SetAttribute(name, attribute.Description); - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/IPairDeconstructor.cs b/src/Spectre.Console.Cli/Internal/IPairDeconstructor.cs deleted file mode 100644 index de6fa4543..000000000 --- a/src/Spectre.Console.Cli/Internal/IPairDeconstructor.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a pair deconstructor. -/// -internal interface IPairDeconstructor -{ - /// - /// Deconstructs the specified value into its components. - /// - /// The type resolver to use. - /// The key type. - /// The value type. - /// The value to deconstruct. - /// A deconstructed value. - (object? Key, object? Value) Deconstruct( - ITypeResolver resolver, - Type keyType, - Type valueType, - string? value); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/CommandArgument.cs b/src/Spectre.Console.Cli/Internal/Modelling/CommandArgument.cs deleted file mode 100644 index c6b555baf..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/CommandArgument.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandArgument : CommandParameter, ICommandArgument -{ - public string Value { get; } - public int Position { get; set; } - - public CommandArgument( - Type parameterType, ParameterKind parameterKind, PropertyInfo property, string? description, - TypeConverterAttribute? converter, DefaultValueAttribute? defaultValue, - CommandArgumentAttribute argument, ParameterValueProviderAttribute? valueProvider, - IEnumerable validators) - : base(parameterType, parameterKind, property, description, converter, defaultValue, - null, valueProvider, validators, argument.IsRequired, false) - { - Value = argument.ValueName; - Position = argument.Position; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/CommandContainerExtensions.cs b/src/Spectre.Console.Cli/Internal/Modelling/CommandContainerExtensions.cs deleted file mode 100644 index cebcbc5fb..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/CommandContainerExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandContainerExtensions -{ - public static CommandInfo? FindCommand(this ICommandContainer root, string name, CaseSensitivity sensitivity) - { - var result = root.Commands.FirstOrDefault( - c => c.Name.Equals(name, sensitivity.GetStringComparison(CommandPart.CommandName))); - - if (result == null) - { - result = root.Commands.FirstOrDefault( - c => c.Aliases.Contains(name, sensitivity.GetStringComparer(CommandPart.CommandName))); - } - - return result; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/CommandInfo.cs b/src/Spectre.Console.Cli/Internal/Modelling/CommandInfo.cs deleted file mode 100644 index e96ed3393..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/CommandInfo.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandInfo : ICommandContainer, ICommandInfo -{ - public string Name { get; } - public HashSet Aliases { get; } - public string? Description { get; } - public object? Data { get; } - public Type? CommandType { get; } - public Type SettingsType { get; } - public Func>? Delegate { get; } - public bool IsDefaultCommand { get; } - public CommandInfo? Parent { get; } - public IList Children { get; } - public IList Parameters { get; } - public IList Examples { get; } - - public bool IsBranch => CommandType == null && Delegate == null; - IList ICommandContainer.Commands => Children; - - // only branches can have a default command - public CommandInfo? DefaultCommand => IsBranch ? Children.FirstOrDefault(c => c.IsDefaultCommand) : null; - public bool IsHidden { get; } - - IReadOnlyList Help.ICommandContainer.Commands => Children.Cast().ToList(); - ICommandInfo? Help.ICommandContainer.DefaultCommand => DefaultCommand; - IReadOnlyList ICommandInfo.Parameters => Parameters.Cast().ToList(); - ICommandInfo? ICommandInfo.Parent => Parent; - IReadOnlyList Help.ICommandContainer.Examples => (IReadOnlyList)Examples; - - public CommandInfo(CommandInfo? parent, ConfiguredCommand prototype) - { - Parent = parent; - - Name = prototype.Name; - Aliases = new HashSet(prototype.Aliases); - Description = prototype.Description; - Data = prototype.Data; - CommandType = prototype.CommandType; - SettingsType = prototype.SettingsType; - Delegate = prototype.Delegate; - IsDefaultCommand = prototype.IsDefaultCommand; - IsHidden = prototype.IsHidden; - - Children = new List(); - Parameters = new List(); - Examples = prototype.Examples ?? new List(); - - if (CommandType != null && string.IsNullOrWhiteSpace(Description)) - { - var description = CommandType.GetCustomAttribute(); - if (description != null) - { - Description = description.Description; - } - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/CommandInfoExtensions.cs b/src/Spectre.Console.Cli/Internal/Modelling/CommandInfoExtensions.cs deleted file mode 100644 index 140fe2904..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/CommandInfoExtensions.cs +++ /dev/null @@ -1,86 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandInfoExtensions -{ - public static IEnumerable? GetArguments(this CommandInfo? command) - { - return command?.Parameters.OfType(); - } - - public static IEnumerable? GetOptions(this CommandInfo? command) - { - return command?.Parameters.OfType(); - } - - public static bool HaveParentWithOption(this CommandInfo command, CommandOption option) - { - var parent = command?.Parent; - while (parent != null) - { - foreach (var parentOption in parent.Parameters.OfType()) - { - if (option.HaveSameBackingPropertyAs(parentOption)) - { - return true; - } - } - - parent = parent.Parent; - } - - return false; - } - - public static bool AllowParentOption(this CommandInfo command, CommandOption option) - { - // Got an immediate parent? - if (command?.Parent != null) - { - // Is the current node's settings type the same as the previous one? - if (command.SettingsType == command.Parent.SettingsType) - { - var parameters = command.Parent.Parameters.OfType().ToArray(); - if (parameters.Length > 0) - { - foreach (var parentOption in parameters) - { - // Is this the same one? - if (option.HaveSameBackingPropertyAs(parentOption)) - { - // Is it part of the same settings class. - if (option.Property.DeclaringType == command.SettingsType) - { - // Allow it. - return true; - } - - // Don't allow it. - return false; - } - } - } - } - } - - return false; - } - - public static bool HaveParentWithArgument(this CommandInfo command, CommandArgument argument) - { - var parent = command?.Parent; - while (parent != null) - { - foreach (var parentOption in parent.Parameters.OfType()) - { - if (argument.HaveSameBackingPropertyAs(parentOption)) - { - return true; - } - } - - parent = parent.Parent; - } - - return false; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/CommandModel.cs b/src/Spectre.Console.Cli/Internal/Modelling/CommandModel.cs deleted file mode 100644 index 721960bd3..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/CommandModel.cs +++ /dev/null @@ -1,61 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandModel : ICommandContainer, ICommandModel -{ - public string? ApplicationName { get; } - public string? ApplicationVersion { get; } - public ParsingMode ParsingMode { get; } - public IList Commands { get; } - public IList Examples { get; } - - public CommandInfo? DefaultCommand => Commands.FirstOrDefault(c => c.IsDefaultCommand); - - string ICommandModel.ApplicationName => GetApplicationName(ApplicationName); - IReadOnlyList Help.ICommandContainer.Commands => Commands.Cast().ToList(); - ICommandInfo? Help.ICommandContainer.DefaultCommand => DefaultCommand; - IReadOnlyList Help.ICommandContainer.Examples => (IReadOnlyList)Examples; - - public CommandModel( - CommandAppSettings settings, - IEnumerable commands, - IEnumerable examples) - { - ApplicationName = settings.ApplicationName; - ApplicationVersion = settings.ApplicationVersion; - ParsingMode = settings.ParsingMode; - Commands = new List(commands); - Examples = new List(examples); - } - - /// - /// Gets the name of the application. - /// If the provided is not null or empty, - /// it is returned. Otherwise the name of the current application - /// is determined based on the executable file's name. - /// - /// The optional name of the application. - /// - /// The name of the application, or a default value of "?" if no valid application name can be determined. - /// - private static string GetApplicationName(string? applicationName) - { - return - applicationName ?? - Path.GetFileName(GetApplicationFile()) ?? // null is propagated by GetFileName - "?"; - } - - private static string? GetApplicationFile() - { - var location = Assembly.GetEntryAssembly()?.Location; - - if (string.IsNullOrWhiteSpace(location)) - { - // this is special case for single file executable - // (Assembly.Location returns empty string) - return Process.GetCurrentProcess().MainModule?.FileName; - } - - return location; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/CommandModelBuilder.cs b/src/Spectre.Console.Cli/Internal/Modelling/CommandModelBuilder.cs deleted file mode 100644 index 4845ab05e..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/CommandModelBuilder.cs +++ /dev/null @@ -1,247 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandModelBuilder -{ - // Consider removing this in favor for value tuples at some point. - private sealed class OrderedProperties - { - public int Level { get; } - public int SortOrder { get; } - public PropertyInfo[] Properties { get; } - - public OrderedProperties(int level, int sortOrder, PropertyInfo[] properties) - { - Level = level; - SortOrder = sortOrder; - Properties = properties; - } - } - - public static CommandModel Build(IConfiguration configuration) - { - var result = new List(); - foreach (var command in configuration.Commands) - { - result.Add(Build(null, command)); - } - - if (configuration.DefaultCommand != null) - { - // Add the examples from the configuration to the default command. - configuration.DefaultCommand.Examples.AddRange(configuration.Examples); - - // Build the default command. - var defaultCommand = Build(null, configuration.DefaultCommand); - - result.Add(defaultCommand); - } - - // Create the command model and validate it. - var model = new CommandModel(configuration.Settings, result, configuration.Examples); - CommandModelValidator.Validate(model, configuration.Settings); - - return model; - } - - private static CommandInfo Build(CommandInfo? parent, ConfiguredCommand command) - { - var info = new CommandInfo(parent, command); - - foreach (var parameter in GetParameters(info)) - { - info.Parameters.Add(parameter); - } - - foreach (var childCommand in command.Children) - { - var child = Build(info, childCommand); - info.Children.Add(child); - } - - // Normalize argument positions. - var index = 0; - foreach (var argument in info.Parameters.OfType() - .OrderBy(argument => argument.Position)) - { - argument.Position = index; - index++; - } - - return info; - } - - private static IEnumerable GetParameters(CommandInfo command) - { - var result = new List(); - var argumentPosition = 0; - - // We need to get parameters in order of the class where they were defined. - // We assign each inheritance level a value that is used to properly sort the - // arguments when iterating over them. - IEnumerable GetPropertiesInOrder() - { - var current = command.SettingsType; - var level = 0; - var sortOrder = 0; - while (current.BaseType != null) - { - yield return new OrderedProperties(level, sortOrder, current.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)); - current = current.BaseType; - - // Things get a little bit complicated now. - // Only consider a setting's base type part of the - // setting, if there isn't a parent command that implements - // the setting's base type. This might come back to bite us :) - var currentCommand = command.Parent; - while (currentCommand != null) - { - if (currentCommand.SettingsType == current) - { - level--; - break; - } - - currentCommand = currentCommand.Parent; - } - - sortOrder--; - } - } - - var groups = GetPropertiesInOrder(); - foreach (var group in groups.OrderBy(x => x.Level).ThenBy(x => x.SortOrder)) - { - var parameters = new List(); - - foreach (var property in group.Properties) - { - if (property.IsDefined(typeof(CommandOptionAttribute))) - { - var attribute = property.GetCustomAttribute(); - if (attribute != null) - { - var option = BuildOptionParameter(property, attribute); - - // Any previous command has this option defined? - if (command.HaveParentWithOption(option)) - { - // Do we allow it to exist on this command as well? - if (command.AllowParentOption(option)) - { - option.IsShadowed = true; - parameters.Add(option); - } - } - else - { - // No parent have this option. - parameters.Add(option); - } - } - } - else if (property.IsDefined(typeof(CommandArgumentAttribute))) - { - var attribute = property.GetCustomAttribute(); - if (attribute != null) - { - var argument = BuildArgumentParameter(property, attribute); - - // Any previous command has this argument defined? - // In that case, we should not assign the parameter to this command. - if (!command.HaveParentWithArgument(argument)) - { - parameters.Add(argument); - } - } - } - } - - // Update the position for the parameters. - foreach (var argument in parameters.OfType().OrderBy(x => x.Position)) - { - argument.Position = argumentPosition++; - } - - // Add all parameters to the result. - foreach (var groupResult in parameters) - { - result.Add(groupResult); - } - } - - return result; - } - - private static CommandOption BuildOptionParameter(PropertyInfo property, CommandOptionAttribute attribute) - { - var description = property.GetCustomAttribute(); - var converter = property.GetCustomAttribute(); - var deconstructor = property.GetCustomAttribute(); - var valueProvider = property.GetCustomAttribute(); - var validators = property.GetCustomAttributes(true); - var defaultValue = property.GetCustomAttribute(); - - var kind = GetOptionKind(property.PropertyType, attribute, deconstructor, converter); - - if (defaultValue == null && property.PropertyType == typeof(bool)) - { - defaultValue = new DefaultValueAttribute(false); - } - - return new CommandOption(property.PropertyType, kind, - property, description?.Description, converter, deconstructor, - attribute, valueProvider, validators, defaultValue, - attribute.ValueIsOptional); - } - - private static CommandArgument BuildArgumentParameter(PropertyInfo property, CommandArgumentAttribute attribute) - { - var description = property.GetCustomAttribute(); - var converter = property.GetCustomAttribute(); - var defaultValue = property.GetCustomAttribute(); - var valueProvider = property.GetCustomAttribute(); - var validators = property.GetCustomAttributes(true); - - var kind = GetParameterKind(property.PropertyType); - - return new CommandArgument( - property.PropertyType, kind, property, - description?.Description, converter, - defaultValue, attribute, valueProvider, - validators); - } - - private static ParameterKind GetOptionKind( - Type type, - CommandOptionAttribute attribute, - PairDeconstructorAttribute? deconstructor, - TypeConverterAttribute? converter) - { - if (attribute.ValueIsOptional) - { - return ParameterKind.FlagWithValue; - } - - if (type.IsPairDeconstructable() && (deconstructor != null || converter == null)) - { - return ParameterKind.Pair; - } - - return GetParameterKind(type); - } - - private static ParameterKind GetParameterKind(Type type) - { - if (type == typeof(bool) || type == typeof(bool?)) - { - return ParameterKind.Flag; - } - - if (type.IsArray) - { - return ParameterKind.Vector; - } - - return ParameterKind.Scalar; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/CommandModelValidator.cs b/src/Spectre.Console.Cli/Internal/Modelling/CommandModelValidator.cs deleted file mode 100644 index a98c25299..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/CommandModelValidator.cs +++ /dev/null @@ -1,188 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandModelValidator -{ - public static void Validate(CommandModel model, CommandAppSettings settings) - { - if (model is null) - { - throw new ArgumentNullException(nameof(model)); - } - - if (settings is null) - { - throw new ArgumentNullException(nameof(settings)); - } - - if (model.Commands.Count == 0) - { - throw CommandConfigurationException.NoCommandConfigured(); - } - - foreach (var command in model.Commands) - { - // Alias collision? - foreach (var alias in command.Aliases) - { - if (model.Commands.Any(x => x.Name.Equals(alias, StringComparison.OrdinalIgnoreCase))) - { - throw CommandConfigurationException.CommandNameConflict(command, alias); - } - } - } - - foreach (var command in model.Commands) - { - Validate(command); - } - - if (settings.ValidateExamples) - { - ValidateExamples(model, settings); - } - } - - private static void Validate(CommandInfo? command) - { - if (command == null) - { - return; - } - - // Get duplicate options for command. - var duplicateOptions = GetDuplicates(command); - if (duplicateOptions.Length > 0) - { - throw CommandConfigurationException.DuplicateOption(command, duplicateOptions); - } - - // No children? - if (command.IsBranch && command.Children.Count == 0) - { - throw CommandConfigurationException.BranchHasNoChildren(command); - } - - var arguments = command.Parameters - .OfType() - .OrderBy(x => x.Position) - .ToList(); - - // vector arguments? - if (arguments.Any(x => x.ParameterKind == ParameterKind.Vector)) - { - // Multiple vector arguments for command? - if (arguments.Count(x => x.ParameterKind == ParameterKind.Vector) > 1) - { - throw CommandConfigurationException.TooManyVectorArguments(command); - } - - // Make sure that the vector argument is specified last. - if (arguments.Last().ParameterKind != ParameterKind.Vector) - { - throw CommandConfigurationException.VectorArgumentNotSpecifiedLast(command); - } - } - - // Arguments - foreach (var argument in arguments) - { - if (argument.IsRequired && argument.DefaultValue != null) - { - throw CommandConfigurationException.RequiredArgumentsCannotHaveDefaultValue(argument); - } - } - - // Options - var options = command.Parameters.OfType(); - foreach (var option in options) - { - // Pair deconstructable? - if (option.Property.PropertyType.IsPairDeconstructable()) - { - if (option.PairDeconstructor != null && option.Converter != null) - { - throw CommandConfigurationException.OptionBothHasPairDeconstructorAndTypeParameter(option); - } - } - else if (option.PairDeconstructor != null) - { - throw CommandConfigurationException.OptionTypeDoesNotSupportDeconstruction(option); - } - - // Optional options that are not flags? - if (option.ParameterKind == ParameterKind.FlagWithValue && !option.IsFlagValue()) - { - throw CommandConfigurationException.OptionalOptionValueMustBeFlagWithValue(option); - } - } - - // Validate child commands. - foreach (var childCommand in command.Children) - { - Validate(childCommand); - } - } - - private static void ValidateExamples(CommandModel model, CommandAppSettings settings) - { - var examples = new List(); - examples.AddRangeIfNotNull(model.Examples); - - // Get all examples. - var queue = new Queue(new[] { model }); - while (queue.Count > 0) - { - var current = queue.Dequeue(); - - foreach (var command in current.Commands) - { - examples.AddRangeIfNotNull(command.Examples); - queue.Enqueue(command); - } - } - - // Validate all examples. - foreach (var example in examples) - { - try - { - var parser = new CommandTreeParser(model, settings.CaseSensitivity, ParsingMode.Strict); - parser.Parse(example); - } - catch (Exception ex) - { - throw new CommandConfigurationException("Validation of examples failed.", ex); - } - } - } - - private static string[] GetDuplicates(CommandInfo command) - { - var result = new Dictionary(StringComparer.Ordinal); - - void AddToResult(IEnumerable keys) - { - foreach (var key in keys) - { - if (!string.IsNullOrWhiteSpace(key)) - { - if (!result.ContainsKey(key)) - { - result.Add(key, 0); - } - - result[key]++; - } - } - } - - foreach (var option in command.Parameters.OfType()) - { - AddToResult(option.ShortNames); - AddToResult(option.LongNames); - } - - return result.Where(x => x.Value > 1) - .Select(x => x.Key).ToArray(); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/CommandOption.cs b/src/Spectre.Console.Cli/Internal/Modelling/CommandOption.cs deleted file mode 100644 index f2d6a9c9c..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/CommandOption.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandOption : CommandParameter, ICommandOption -{ - public IReadOnlyList LongNames { get; } - public IReadOnlyList ShortNames { get; } - public string? ValueName { get; } - public bool ValueIsOptional { get; } - public bool IsShadowed { get; set; } - - public CommandOption( - Type parameterType, ParameterKind parameterKind, PropertyInfo property, string? description, - TypeConverterAttribute? converter, PairDeconstructorAttribute? deconstructor, - CommandOptionAttribute optionAttribute, ParameterValueProviderAttribute? valueProvider, - IEnumerable validators, - DefaultValueAttribute? defaultValue, bool valueIsOptional) - : base(parameterType, parameterKind, property, description, converter, - defaultValue, deconstructor, valueProvider, validators, - optionAttribute.IsRequired, optionAttribute.IsHidden) - { - LongNames = optionAttribute.LongNames; - ShortNames = optionAttribute.ShortNames; - ValueName = optionAttribute.ValueName; - ValueIsOptional = valueIsOptional; - } - - public string GetOptionName() - { - return LongNames.Count > 0 ? LongNames[0] : ShortNames[0]; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/CommandParameter.cs b/src/Spectre.Console.Cli/Internal/Modelling/CommandParameter.cs deleted file mode 100644 index a854abf0a..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/CommandParameter.cs +++ /dev/null @@ -1,151 +0,0 @@ -namespace Spectre.Console.Cli; - -internal abstract class CommandParameter : ICommandParameterInfo, ICommandParameter -{ - public Guid Id { get; } - public Type ParameterType { get; } - public ParameterKind ParameterKind { get; } - public PropertyInfo Property { get; } - public string? Description { get; } - public DefaultValueAttribute? DefaultValue { get; } - public TypeConverterAttribute? Converter { get; } - public PairDeconstructorAttribute? PairDeconstructor { get; } - public List Validators { get; } - public ParameterValueProviderAttribute? ValueProvider { get; } - public bool IsRequired { get; set; } - public bool IsHidden { get; } - public string PropertyName => Property.Name; - - public virtual bool WantRawValue => ParameterType.IsPairDeconstructable() - && (PairDeconstructor != null || Converter == null); - - public bool IsFlag => ParameterKind == ParameterKind.Flag; - - protected CommandParameter( - Type parameterType, ParameterKind parameterKind, PropertyInfo property, - string? description, TypeConverterAttribute? converter, - DefaultValueAttribute? defaultValue, - PairDeconstructorAttribute? deconstructor, - ParameterValueProviderAttribute? valueProvider, - IEnumerable validators, bool required, bool isHidden) - { - Id = Guid.NewGuid(); - ParameterType = parameterType; - ParameterKind = parameterKind; - Property = property; - Description = description; - Converter = converter; - DefaultValue = defaultValue; - PairDeconstructor = deconstructor; - ValueProvider = valueProvider; - Validators = new List(validators ?? []); - IsRequired = required; - IsHidden = isHidden; - } - - public bool IsFlagValue() - { - return ParameterType.GetInterfaces().Any(i => i == typeof(IFlagValue)); - } - - public bool HaveSameBackingPropertyAs(CommandParameter other) - { - return CommandParameterComparer.ByBackingProperty.Equals(this, other); - } - - public void Assign(CommandSettings settings, ITypeResolver resolver, object? value) - { - // Is the property pair deconstructable? - // TODO: This needs to be better defined - if (Property.PropertyType.IsPairDeconstructable() && WantRawValue) - { - var genericTypes = Property.PropertyType.GetGenericArguments(); - - var multimap = (IMultiMap?)Property.GetValue(settings); - if (multimap == null) - { - multimap = Activator.CreateInstance(typeof(MultiMap<,>).MakeGenericType(genericTypes[0], genericTypes[1])) as IMultiMap; - if (multimap == null) - { - throw new InvalidOperationException("Could not create multimap"); - } - } - - // Create deconstructor. - var deconstructorType = PairDeconstructor?.Type ?? typeof(DefaultPairDeconstructor); - if (!(resolver.Resolve(deconstructorType) is IPairDeconstructor deconstructor)) - { - if (!(Activator.CreateInstance(deconstructorType) is IPairDeconstructor activatedDeconstructor)) - { - throw new InvalidOperationException($"Could not create pair deconstructor."); - } - - deconstructor = activatedDeconstructor; - } - - // Deconstruct and add to multimap. - var pair = deconstructor.Deconstruct(resolver, genericTypes[0], genericTypes[1], value as string); - if (pair.Key != null) - { - multimap.Add(pair); - } - - value = multimap; - } - else if (Property.PropertyType.IsArray) - { - // Add a new item to the array - var array = (Array?)Property.GetValue(settings); - Array newArray; - - var elementType = Property.PropertyType.GetElementType(); - if (elementType == null) - { - throw new InvalidOperationException("Could not get property type."); - } - - if (array == null) - { - newArray = Array.CreateInstance(elementType, 1); - } - else - { - newArray = Array.CreateInstance(elementType, array.Length + 1); - array.CopyTo(newArray, 0); - } - - newArray.SetValue(value, newArray.Length - 1); - value = newArray; - } - else if (IsFlagValue()) - { - var flagValue = (IFlagValue?)Property.GetValue(settings); - if (flagValue == null) - { - flagValue = (IFlagValue?)Activator.CreateInstance(ParameterType); - if (flagValue == null) - { - throw new InvalidOperationException("Could not create flag value."); - } - } - - if (value != null) - { - // Null means set, but not with a valid value. - flagValue.Value = value; - } - - // If the parameter was mapped, then it's set. - flagValue.IsSet = true; - - value = flagValue; - } - - Property.SetValue(settings, value); - } - - public object? Get(CommandSettings settings) - { - return Property.GetValue(settings); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/CommandParameterComparer.cs b/src/Spectre.Console.Cli/Internal/Modelling/CommandParameterComparer.cs deleted file mode 100644 index 6997b8bfa..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/CommandParameterComparer.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandParameterComparer -{ - public static readonly ByBackingPropertyComparer ByBackingProperty = new ByBackingPropertyComparer(); - - public sealed class ByBackingPropertyComparer : IEqualityComparer - { - public bool Equals(CommandParameter? x, CommandParameter? y) - { - if (x is null || y is null) - { - return false; - } - - if (ReferenceEquals(x, y)) - { - return true; - } - - return x.Property.MetadataToken == y.Property.MetadataToken; - } - - public int GetHashCode(CommandParameter? obj) - { - return obj?.Property?.MetadataToken.GetHashCode() ?? 0; - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/ICommandContainer.cs b/src/Spectre.Console.Cli/Internal/Modelling/ICommandContainer.cs deleted file mode 100644 index 8685ecf66..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/ICommandContainer.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Represents a command container. -/// -internal interface ICommandContainer -{ - /// - /// Gets all commands in the container. - /// - IList Commands { get; } - - /// - /// Gets the default command for the container. - /// - /// - /// Returns null if a default command has not been set. - /// - CommandInfo? DefaultCommand { get; } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Modelling/ParameterKind.cs b/src/Spectre.Console.Cli/Internal/Modelling/ParameterKind.cs deleted file mode 100644 index f1fbaa1c8..000000000 --- a/src/Spectre.Console.Cli/Internal/Modelling/ParameterKind.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Spectre.Console.Cli; - -internal enum ParameterKind -{ - [Description("flag")] - Flag = 0, - - [Description("scalar")] - Scalar = 1, - - [Description("vector")] - Vector = 2, - - [Description("flagvalue")] - FlagWithValue = 3, - - [Description("pair")] - Pair = 4, -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Parsing/CommandTree.cs b/src/Spectre.Console.Cli/Internal/Parsing/CommandTree.cs deleted file mode 100644 index edee26852..000000000 --- a/src/Spectre.Console.Cli/Internal/Parsing/CommandTree.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandTree -{ - public CommandInfo Command { get; } - public List Mapped { get; } - public List Unmapped { get; } - public CommandTree? Parent { get; } - public CommandTree? Next { get; set; } - public bool ShowHelp { get; set; } - - public CommandTree(CommandTree? parent, CommandInfo command) - { - Parent = parent; - Command = command; - Mapped = new List(); - Unmapped = new List(); - } - - public ICommand CreateCommand(ITypeResolver resolver) - { - if (Command.Delegate != null) - { - return new DelegateCommand(Command.Delegate); - } - - if (resolver.Resolve(Command.CommandType) is ICommand command) - { - return command; - } - - throw CommandParseException.CouldNotCreateCommand(Command.CommandType); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeExtensions.cs b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeExtensions.cs deleted file mode 100644 index e7cb225b9..000000000 --- a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeExtensions.cs +++ /dev/null @@ -1,66 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandTreeExtensions -{ - public static CommandTree? GetRootCommand(this CommandTree node) - { - while (node.Parent != null) - { - node = node.Parent; - } - - return node; - } - - public static CommandTree GetLeafCommand(this CommandTree node) - { - while (node.Next != null) - { - node = node.Next; - } - - return node; - } - - public static bool HasArguments(this CommandTree tree) - { - return tree.Command.Parameters.OfType().Any(); - } - - public static CommandArgument? FindArgument(this CommandTree tree, int position) - { - return tree.Command.Parameters - .OfType() - .FirstOrDefault(c => c.Position == position); - } - - public static CommandOption? FindOption(this CommandTree tree, string name, bool longOption, CaseSensitivity sensitivity) - { - return tree.Command.Parameters - .OfType() - .FirstOrDefault(o => longOption - ? o.LongNames.Contains(name, sensitivity.GetStringComparer(CommandPart.LongOption)) - : o.ShortNames.Contains(name, StringComparer.Ordinal)); - } - - public static bool IsOptionMappedWithParent(this CommandTree tree, string name, bool longOption) - { - var node = tree.Parent; - while (node != null) - { - var option = node.Command?.Parameters.OfType() - .FirstOrDefault(o => longOption - ? o.LongNames.Contains(name, StringComparer.Ordinal) - : o.ShortNames.Contains(name, StringComparer.Ordinal)); - - if (option != null) - { - return node.Mapped.Any(p => p.Parameter == option); - } - - node = node.Parent; - } - - return false; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParser.cs b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParser.cs deleted file mode 100644 index d985dcbd2..000000000 --- a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParser.cs +++ /dev/null @@ -1,419 +0,0 @@ -using static Spectre.Console.Cli.CommandTreeTokenizer; - -namespace Spectre.Console.Cli; - -internal class CommandTreeParser -{ - private readonly CommandModel _configuration; - private readonly ParsingMode _parsingMode; - private readonly CommandOptionAttribute _help; - private readonly bool _convertFlagsToRemainingArguments; - - public CaseSensitivity CaseSensitivity { get; } - - public enum State - { - Normal = 0, - Remaining = 1, - } - - public CommandTreeParser(CommandModel configuration, CaseSensitivity caseSensitivity, ParsingMode? parsingMode = null, bool? convertFlagsToRemainingArguments = null) - { - _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); - _parsingMode = parsingMode ?? _configuration.ParsingMode; - _help = new CommandOptionAttribute("-?|-h|--help"); - _convertFlagsToRemainingArguments = convertFlagsToRemainingArguments ?? false; - - CaseSensitivity = caseSensitivity; - } - - public CommandTreeParserResult Parse(IEnumerable args) - { - var parserContext = new CommandTreeParserContext(args, _parsingMode); - var tokenizerResult = CommandTreeTokenizer.Tokenize(args); - - return Parse(parserContext, tokenizerResult); - } - - public CommandTreeParserResult Parse(CommandTreeParserContext context, CommandTreeTokenizerResult tokenizerResult) - { - var tokens = tokenizerResult.Tokens; - var rawRemaining = tokenizerResult.Remaining; - - var result = default(CommandTree); - if (tokens.Count > 0) - { - // Not a command? - var token = tokens.Current; - if (token == null) - { - // Should not happen, but the compiler isn't - // smart enough to realize this... - throw new CommandRuntimeException("Could not get current token."); - } - - if (token.TokenKind != CommandTreeToken.Kind.String) - { - // Got a default command? - if (_configuration.DefaultCommand != null) - { - result = ParseCommandParameters(context, _configuration.DefaultCommand, null, tokens); - return new CommandTreeParserResult( - result, new RemainingArguments(context.GetRemainingArguments(), rawRemaining)); - } - - // Show help? - if (_help?.IsMatch(token.Value) == true) - { - return new CommandTreeParserResult( - null, new RemainingArguments(context.GetRemainingArguments(), rawRemaining)); - } - - // Unexpected option. - throw CommandParseException.UnexpectedOption(context.Arguments, token); - } - - // Does the token value match a command? - var command = _configuration.FindCommand(token.Value, CaseSensitivity); - if (command == null) - { - if (_configuration.DefaultCommand != null) - { - result = ParseCommandParameters(context, _configuration.DefaultCommand, null, tokens); - return new CommandTreeParserResult( - result, new RemainingArguments(context.GetRemainingArguments(), rawRemaining)); - } - } - - // Parse the command. - result = ParseCommand(context, _configuration, null, tokens); - } - else - { - // Is there a default command? - if (_configuration.DefaultCommand != null) - { - result = ParseCommandParameters(context, _configuration.DefaultCommand, null, tokens); - } - } - - return new CommandTreeParserResult( - result, new RemainingArguments(context.GetRemainingArguments(), rawRemaining)); - } - - private CommandTree ParseCommand( - CommandTreeParserContext context, - ICommandContainer current, - CommandTree? parent, - CommandTreeTokenStream stream) - { - // Find the command. - var commandToken = stream.Consume(CommandTreeToken.Kind.String); - if (commandToken == null) - { - throw new CommandRuntimeException("Could not consume token when parsing command."); - } - - var command = current.FindCommand(commandToken.Value, CaseSensitivity); - if (command == null) - { - throw CommandParseException.UnknownCommand(_configuration, parent, context.Arguments, commandToken); - } - - return ParseCommandParameters(context, command, parent, stream); - } - - private CommandTree ParseCommandParameters( - CommandTreeParserContext context, - CommandInfo command, - CommandTree? parent, - CommandTreeTokenStream stream) - { - context.ResetArgumentPosition(); - - var node = new CommandTree(parent, command); - while (stream.Peek() != null) - { - var token = stream.Peek(); - if (token == null) - { - // Should not happen, but the compiler isn't - // smart enough to realize this... - throw new CommandRuntimeException("Could not get the next token."); - } - - switch (token.TokenKind) - { - case CommandTreeToken.Kind.LongOption: - // Long option - ParseOption(context, stream, token, node, true); - break; - case CommandTreeToken.Kind.ShortOption: - // Short option - ParseOption(context, stream, token, node, false); - break; - case CommandTreeToken.Kind.String: - // Command - ParseString(context, stream, node); - break; - case CommandTreeToken.Kind.Remaining: - // Remaining - stream.Consume(CommandTreeToken.Kind.Remaining); - context.State = State.Remaining; - break; - default: - throw new InvalidOperationException($"Encountered unknown token ({token.TokenKind})."); - } - } - - // Add unmapped parameters. - foreach (var parameter in node.Command.Parameters) - { - if (node.Mapped.All(m => m.Parameter != parameter)) - { - node.Unmapped.Add(parameter); - } - } - - return node; - } - - private void ParseString( - CommandTreeParserContext context, - CommandTreeTokenStream stream, - CommandTree node) - { - if (context.State == State.Remaining) - { - stream.Consume(CommandTreeToken.Kind.String); - return; - } - - var token = stream.Expect(CommandTreeToken.Kind.String); - - // Command? - var command = node.Command.FindCommand(token.Value, CaseSensitivity); - if (command != null) - { - if (context.State == State.Normal) - { - node.Next = ParseCommand(context, node.Command, node, stream); - } - - return; - } - - // Current command has no arguments? - if (!node.HasArguments()) - { - throw CommandParseException.UnknownCommand(_configuration, node, context.Arguments, token); - } - - // Argument? - var parameter = node.FindArgument(context.CurrentArgumentPosition); - if (parameter == null) - { - // No parameters left. Any commands after this? - if (node.Command.Children.Count > 0 || node.Command.IsDefaultCommand) - { - throw CommandParseException.UnknownCommand(_configuration, node, context.Arguments, token); - } - - throw CommandParseException.CouldNotMatchArgument(context.Arguments, token); - } - - // Yes, this was an argument. - if (parameter.ParameterKind == ParameterKind.Vector) - { - // Vector - var current = stream.Current; - while (current?.TokenKind == CommandTreeToken.Kind.String) - { - var value = stream.Consume(CommandTreeToken.Kind.String)?.Value; - node.Mapped.Add(new MappedCommandParameter(parameter, value)); - current = stream.Current; - } - } - else - { - // Scalar - var value = stream.Consume(CommandTreeToken.Kind.String)?.Value; - node.Mapped.Add(new MappedCommandParameter(parameter, value)); - context.IncreaseArgumentPosition(); - } - } - - private void ParseOption( - CommandTreeParserContext context, - CommandTreeTokenStream stream, - CommandTreeToken token, - CommandTree node, - bool isLongOption) - { - // Consume the option token. - stream.Consume(isLongOption ? CommandTreeToken.Kind.LongOption : CommandTreeToken.Kind.ShortOption); - - if (context.State == State.Normal) - { - // Find the option. - var option = node.FindOption(token.Value, isLongOption, CaseSensitivity); - if (option != null) - { - ParseOptionValue(context, stream, token, node, option); - return; - } - - // Help? - if (_help?.IsMatch(token.Value) == true) - { - node.ShowHelp = true; - return; - } - } - - if (context.State == State.Remaining) - { - ParseOptionValue(context, stream, token, node); - return; - } - - if (context.ParsingMode == ParsingMode.Strict) - { - throw CommandParseException.UnknownOption(context.Arguments, token); - } - else - { - ParseOptionValue(context, stream, token, node); - } - } - - private void ParseOptionValue( - CommandTreeParserContext context, - CommandTreeTokenStream stream, - CommandTreeToken token, - CommandTree current, - CommandParameter? parameter = null) - { - bool addToMappedCommandParameters = parameter != null; - - var value = default(string); - - // Parse the value of the token (if any). - var valueToken = stream.Peek(); - if (valueToken?.TokenKind == CommandTreeToken.Kind.String) - { - bool parseValue = token is not { TokenKind: CommandTreeToken.Kind.ShortOption, IsGrouped: true }; - - if (context.State == State.Normal && parseValue) - { - // Is this a command? - if (current.Command.FindCommand(valueToken.Value, CaseSensitivity) == null) - { - if (parameter != null) - { - if (parameter.ParameterKind == ParameterKind.Flag) - { - if (!CliConstants.AcceptedBooleanValues.Contains(valueToken.Value, StringComparer.OrdinalIgnoreCase)) - { - if (!valueToken.HadSeparator) - { - // Do nothing - // - assume valueToken is unrelated to the flag parameter (ie. we've parsed it unnecessarily) - // - rely on the "No value?" code below to set the flag to its default value - // - valueToken will be handled on the next pass of the parser - } - else - { - // Flags cannot be assigned a value. - if (_convertFlagsToRemainingArguments) - { - value = stream.Consume(CommandTreeToken.Kind.String)?.Value; - - context.AddRemainingArgument(token.Representation, value); - - // Prevent the option and it's non-boolean value from being added to - // mapped parameters (otherwise an exception will be thrown later - // when binding the value to the flag in the comand settings) - addToMappedCommandParameters = false; - } - else - { - throw CommandParseException.CannotAssignValueToFlag(context.Arguments, token); - } - } - } - else - { - value = stream.Consume(CommandTreeToken.Kind.String)?.Value; - } - } - else - { - value = stream.Consume(CommandTreeToken.Kind.String)?.Value; - } - } - else - { - // Unknown parameter value. - value = stream.Consume(CommandTreeToken.Kind.String)?.Value; - - // In relaxed parsing mode? - if (context.ParsingMode == ParsingMode.Relaxed) - { - context.AddRemainingArgument(token.Representation, value); - } - } - } - } - else - { - context.AddRemainingArgument(token.Representation, parseValue ? valueToken.Value : null); - } - } - else - { - if (parameter == null && // Only add tokens which have not been matched to a command parameter - (context.State == State.Remaining || context.ParsingMode == ParsingMode.Relaxed)) - { - context.AddRemainingArgument(token.Representation, null); - } - } - - // No value? - if (context.State == State.Normal) - { - if (value == null && parameter != null) - { - if (parameter.ParameterKind == ParameterKind.Flag) - { - value = "true"; - } - else - { - if (parameter is CommandOption option) - { - if (parameter.IsFlagValue()) - { - value = null; - } - else - { - throw CommandParseException.OptionHasNoValue(context.Arguments, token, option); - } - } - else - { - // This should not happen at all. If it does, it's because we've added a new - // option type which isn't a CommandOption for some reason. - throw new InvalidOperationException($"Found invalid parameter type '{parameter.GetType().FullName}'."); - } - } - } - } - - if (parameter != null && addToMappedCommandParameters) - { - current.Mapped.Add(new MappedCommandParameter(parameter, value)); - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParserContext.cs b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParserContext.cs deleted file mode 100644 index bce771870..000000000 --- a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParserContext.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace Spectre.Console.Cli; - -internal class CommandTreeParserContext -{ - private readonly List _args; - private readonly Dictionary> _remaining; - - public IReadOnlyList Arguments => _args; - public int CurrentArgumentPosition { get; private set; } - public CommandTreeParser.State State { get; set; } - public ParsingMode ParsingMode { get; } - - public CommandTreeParserContext(IEnumerable args, ParsingMode parsingMode) - { - _args = new List(args); - _remaining = new Dictionary>(StringComparer.Ordinal); - - ParsingMode = parsingMode; - } - - public void ResetArgumentPosition() - { - CurrentArgumentPosition = 0; - } - - public void IncreaseArgumentPosition() - { - CurrentArgumentPosition++; - } - - public void AddRemainingArgument(string key, string? value) - { - if (!_remaining.ContainsKey(key)) - { - _remaining.Add(key, new List()); - } - - _remaining[key].Add(value); - } - - [SuppressMessage("Style", "IDE0004:Remove Unnecessary Cast", Justification = "Bug in analyzer?")] - public ILookup GetRemainingArguments() - { - return _remaining - .SelectMany(pair => pair.Value, (pair, value) => new { pair.Key, value }) - .ToLookup(pair => pair.Key, pair => (string?)pair.value); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParserResult.cs b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParserResult.cs deleted file mode 100644 index 3e5213fe0..000000000 --- a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParserResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Spectre.Console.Cli; - -// Consider removing this in favor for value tuples at some point. -internal sealed class CommandTreeParserResult -{ - public CommandTree? Tree { get; } - public IRemainingArguments Remaining { get; } - - public CommandTreeParserResult(CommandTree? tree, IRemainingArguments remaining) - { - Tree = tree; - Remaining = remaining; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeToken.cs b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeToken.cs deleted file mode 100644 index f6ea26cfe..000000000 --- a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeToken.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandTreeToken -{ - public Kind TokenKind { get; } - public int Position { get; } - public string Value { get; } - public string Representation { get; } - public bool IsGrouped { get; set; } - - /// - /// Gets or sets a value indicating whether a separater was encountered immediately before the . - /// - public bool HadSeparator { get; set; } - - public enum Kind - { - String, - LongOption, - ShortOption, - Remaining, - } - - public CommandTreeToken(Kind kind, int position, string value, string representation) - { - TokenKind = kind; - Position = position; - Value = value; - Representation = representation; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenStream.cs b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenStream.cs deleted file mode 100644 index e1c2f1df4..000000000 --- a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenStream.cs +++ /dev/null @@ -1,86 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandTreeTokenStream : IReadOnlyList -{ - private readonly List _tokens; - private int _position; - - public int Count => _tokens.Count; - public int Position => _position; - - public CommandTreeToken this[int index] => _tokens[index]; - - public CommandTreeToken? Current - { - get - { - if (_position >= Count) - { - return null; - } - - return _tokens[_position]; - } - } - - public CommandTreeTokenStream(IEnumerable tokens) - { - _tokens = new List(tokens ?? Enumerable.Empty()); - _position = 0; - } - - public CommandTreeToken? Peek(int index = 0) - { - var position = _position + index; - if (position >= Count) - { - return null; - } - - return _tokens[position]; - } - - public CommandTreeToken? Consume() - { - if (_position >= Count) - { - return null; - } - - var token = _tokens[_position]; - _position++; - return token; - } - - public CommandTreeToken? Consume(CommandTreeToken.Kind type) - { - Expect(type); - return Consume(); - } - - public CommandTreeToken Expect(CommandTreeToken.Kind expected) - { - if (Current == null) - { - throw CommandParseException.ExpectedTokenButFoundNull(expected); - } - - var found = Current.TokenKind; - if (expected != found) - { - throw CommandParseException.ExpectedTokenButFoundOther(expected, found); - } - - return Current; - } - - public IEnumerator GetEnumerator() - { - return _tokens.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizer.cs b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizer.cs deleted file mode 100644 index 840b072c7..000000000 --- a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizer.cs +++ /dev/null @@ -1,276 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class CommandTreeTokenizer -{ - public enum Mode - { - Normal = 0, - Remaining = 1, - } - - // Consider removing this in favor for value tuples at some point. - public sealed class CommandTreeTokenizerResult - { - public CommandTreeTokenStream Tokens { get; } - public IReadOnlyList Remaining { get; } - - public CommandTreeTokenizerResult(CommandTreeTokenStream tokens, IReadOnlyList remaining) - { - Tokens = tokens; - Remaining = remaining; - } - } - - public static CommandTreeTokenizerResult Tokenize(IEnumerable args) - { - var tokens = new List(); - var position = 0; - var previousReader = default(TextBuffer); - var context = new CommandTreeTokenizerContext(); - - foreach (var arg in args) - { - if (string.IsNullOrEmpty(arg)) - { - // Null strings in the args array are still represented as tokens - tokens.Add(new CommandTreeToken(CommandTreeToken.Kind.String, position, string.Empty, string.Empty)); - continue; - } - - var start = position; - var reader = new TextBuffer(previousReader, arg); - - // Parse the token. - position = ParseToken(context, reader, position, start, tokens); - context.FlushRemaining(); - - previousReader = reader; - } - - previousReader?.Dispose(); - - return new CommandTreeTokenizerResult( - new CommandTreeTokenStream(tokens), - context.Remaining); - } - - private static int ParseToken(CommandTreeTokenizerContext context, TextBuffer reader, int position, int start, List tokens) - { - if (!reader.ReachedEnd && reader.Peek() == '-') - { - // Option - tokens.AddRange(ScanOptions(context, reader)); - } - else - { - // Command or argument - while (reader.Peek() != -1) - { - if (reader.ReachedEnd) - { - position += reader.Position - start; - break; - } - - tokens.Add(ScanString(context, reader)); - - // Flush remaining tokens - context.FlushRemaining(); - } - } - - return position; - } - - private static CommandTreeToken ScanString( - CommandTreeTokenizerContext context, - TextBuffer reader, - char[]? stop = null) - { - var position = reader.Position; - var builder = new StringBuilder(); - while (!reader.ReachedEnd) - { - var current = reader.Peek(); - if (stop?.Contains(current) ?? false) - { - break; - } - - reader.Read(); // Consume - context.AddRemaining(current); - builder.Append(current); - } - - var value = builder.ToString(); - return new CommandTreeToken(CommandTreeToken.Kind.String, position, value, value); - } - - private static IEnumerable ScanOptions(CommandTreeTokenizerContext context, TextBuffer reader) - { - var result = new List(); - - var position = reader.Position; - - reader.Consume('-'); - context.AddRemaining('-'); - - if (!reader.TryPeek(out var character) || character == ' ') - { - var token = new CommandTreeToken(CommandTreeToken.Kind.ShortOption, position, "-", "-"); - throw CommandParseException.OptionHasNoName(reader.Original, token); - } - - switch (character) - { - case '-': - var option = ScanLongOption(context, reader, position); - if (option != null) - { - result.Add(option); - } - - break; - default: - result.AddRange(ScanShortOptions(context, reader, position)); - break; - } - - if (reader.TryPeek(out character)) - { - // Encountered a separator? - if (character == '=' || character == ':') - { - reader.Read(); // Consume - context.AddRemaining(character); - - if (!reader.TryPeek(out _)) - { - var token = new CommandTreeToken(CommandTreeToken.Kind.String, reader.Position, "=", "="); - throw CommandParseException.OptionValueWasExpected(reader.Original, token); - } - - var tokenValue = ScanString(context, reader); - tokenValue.HadSeparator = true; - result.Add(tokenValue); - } - } - - return result; - } - - private static IEnumerable ScanShortOptions(CommandTreeTokenizerContext context, TextBuffer reader, int position) - { - var result = new List(); - while (!reader.ReachedEnd) - { - var current = reader.Peek(); - if (char.IsWhiteSpace(current)) - { - break; - } - - // Encountered a separator? - if (current is '=' or ':') - { - break; - } - - if (char.IsLetter(current) || current is '?') - { - context.AddRemaining(current); - reader.Read(); // Consume - - var value = current.ToString(CultureInfo.InvariantCulture); - result.Add(result.Count == 0 - ? new CommandTreeToken(CommandTreeToken.Kind.ShortOption, position, value, $"-{value}") - : new CommandTreeToken(CommandTreeToken.Kind.ShortOption, position + result.Count, value, $"-{value}")); - } - else if (result.Count == 0 && char.IsDigit(current)) - { - // We require short options to be named with letters. Short options that start with a number - // ("-1", "-2ab", "-3..7") may actually mean values (either for options or arguments) and will - // be tokenized as strings. This block handles parsing those cases, but we only allow this - // when the digit is the first character in the token (i.e. "-a1" is always an error), hence the - // result.Count == 0 check above. - string value = string.Empty; - - while (!reader.ReachedEnd) - { - char c = reader.Peek(); - - if (char.IsWhiteSpace(c)) - { - break; - } - - value += c.ToString(CultureInfo.InvariantCulture); - reader.Read(); - } - - value = "-" + value; // Prefix with the minus sign that we originally thought to mean a short option - result.Add(new CommandTreeToken(CommandTreeToken.Kind.String, position, value, value)); - } - else - { - // Create a token representing the short option. - var representation = current.ToString(CultureInfo.InvariantCulture); - var tokenPosition = position + 1 + result.Count; - var token = new CommandTreeToken(CommandTreeToken.Kind.ShortOption, tokenPosition, representation, representation); - - throw CommandParseException.InvalidShortOptionName(reader.Original, token); - } - } - - if (result.Count > 1) - { - foreach (var item in result) - { - item.IsGrouped = true; - } - } - - return result; - } - - private static CommandTreeToken ScanLongOption(CommandTreeTokenizerContext context, TextBuffer reader, int position) - { - reader.Consume('-'); - context.AddRemaining('-'); - - if (reader.ReachedEnd) - { - // Rest of the arguments are remaining ones. - context.Mode = Mode.Remaining; - return new CommandTreeToken(CommandTreeToken.Kind.Remaining, position, "--", "--"); - } - - var name = ScanString(context, reader, new[] { '=', ':' }); - - // Perform validation of the name. - if (name.Value == " ") - { - throw CommandParseException.LongOptionNameIsMissing(reader, position); - } - - if (name.Value.Length == 1) - { - throw CommandParseException.LongOptionNameIsOneCharacter(reader, position, name.Value); - } - - if (char.IsDigit(name.Value[0])) - { - throw CommandParseException.LongOptionNameStartWithDigit(reader, position, name.Value); - } - - for (var index = 0; index < name.Value.Length; index++) - { - if (!char.IsLetterOrDigit(name.Value[index]) && name.Value[index] != '-' && name.Value[index] != '_') - { - throw CommandParseException.LongOptionNameContainSymbol(reader, position + 2 + index, name.Value[index]); - } - } - - return new CommandTreeToken(CommandTreeToken.Kind.LongOption, position, name.Value, $"--{name.Value}"); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizerContext.cs b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizerContext.cs deleted file mode 100644 index b8adf1318..000000000 --- a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizerContext.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandTreeTokenizerContext -{ - private readonly StringBuilder _builder; - private readonly List _remaining; - - public CommandTreeTokenizer.Mode Mode { get; set; } - public IReadOnlyList Remaining => _remaining; - - public CommandTreeTokenizerContext() - { - _builder = new StringBuilder(); - _remaining = new List(); - } - - public void AddRemaining(char character) - { - if (Mode == CommandTreeTokenizer.Mode.Remaining) - { - _builder.Append(character); - } - } - - public void AddRemaining(string text) - { - if (Mode == CommandTreeTokenizer.Mode.Remaining) - { - _builder.Append(text); - } - } - - public void FlushRemaining() - { - if (Mode == CommandTreeTokenizer.Mode.Remaining) - { - if (_builder.Length > 0) - { - _remaining.Add(_builder.ToString()); - _builder.Clear(); - } - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Parsing/MappedCommandParameter.cs b/src/Spectre.Console.Cli/Internal/Parsing/MappedCommandParameter.cs deleted file mode 100644 index 0cd98fb46..000000000 --- a/src/Spectre.Console.Cli/Internal/Parsing/MappedCommandParameter.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Spectre.Console.Cli; - -// Consider removing this in favor for value tuples at some point. -internal sealed class MappedCommandParameter -{ - public CommandParameter Parameter { get; } - public string? Value { get; } - - public MappedCommandParameter(CommandParameter parameter, string? value) - { - Parameter = parameter; - Value = value; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/ParsingMode.cs b/src/Spectre.Console.Cli/Internal/ParsingMode.cs deleted file mode 100644 index ab5ca4e6b..000000000 --- a/src/Spectre.Console.Cli/Internal/ParsingMode.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Spectre.Console.Cli; - -internal enum ParsingMode -{ - Relaxed = 0, - Strict = 1, -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/RemainingArguments.cs b/src/Spectre.Console.Cli/Internal/RemainingArguments.cs deleted file mode 100644 index 092eaa5a9..000000000 --- a/src/Spectre.Console.Cli/Internal/RemainingArguments.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class RemainingArguments : IRemainingArguments -{ - public IReadOnlyList Raw { get; } - public ILookup Parsed { get; } - - public RemainingArguments( - ILookup remaining, - IReadOnlyList raw) - { - Parsed = remaining; - Raw = raw; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/StringWriterWithEncoding.cs b/src/Spectre.Console.Cli/Internal/StringWriterWithEncoding.cs deleted file mode 100644 index a366f65d9..000000000 --- a/src/Spectre.Console.Cli/Internal/StringWriterWithEncoding.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class StringWriterWithEncoding : StringWriter -{ - public override Encoding Encoding { get; } - - public StringWriterWithEncoding(Encoding encoding) - { - Encoding = encoding ?? throw new ArgumentNullException(nameof(encoding)); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/TextBuffer.cs b/src/Spectre.Console.Cli/Internal/TextBuffer.cs deleted file mode 100644 index cd704bffe..000000000 --- a/src/Spectre.Console.Cli/Internal/TextBuffer.cs +++ /dev/null @@ -1,89 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class TextBuffer : IDisposable -{ - // There is some kind of bug - private readonly StringReader _reader; - - public bool ReachedEnd => _reader.Peek() == -1; - public string Original { get; } - public int Position { get; private set; } - - public TextBuffer(string text) - { - _reader = new StringReader(text); - Original = text; - Position = 0; - } - - public TextBuffer(TextBuffer? buffer, string text) - { - _reader = new StringReader(text); - Original = buffer != null ? buffer.Original + " " + text : text; - Position = buffer?.Position + 1 ?? 0; - } - - public void Dispose() - { - _reader.Dispose(); - } - - public char Peek() - { - return (char)_reader.Peek(); - } - - public bool TryPeek(out char character) - { - var value = _reader.Peek(); - if (value == -1) - { - character = '\0'; - return false; - } - - character = (char)value; - return true; - } - - public void Consume() - { - EnsureNotAtEnd(); - Read(); - } - - public void Consume(char character) - { - EnsureNotAtEnd(); - if (Read() != character) - { - throw new InvalidOperationException($"Expected '{character}' token."); - } - } - - public bool IsNext(char character) - { - if (TryPeek(out var result)) - { - return result == character; - } - - return false; - } - - public char Read() - { - EnsureNotAtEnd(); - var result = (char)_reader.Read(); - Position++; - return result; - } - - private void EnsureNotAtEnd() - { - if (ReachedEnd) - { - throw new InvalidOperationException("Can't read past the end of the buffer."); - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/TypeRegistrar.cs b/src/Spectre.Console.Cli/Internal/TypeRegistrar.cs deleted file mode 100644 index 1fc0445cc..000000000 --- a/src/Spectre.Console.Cli/Internal/TypeRegistrar.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class TypeRegistrar : ITypeRegistrarFrontend -{ - private readonly ITypeRegistrar _registrar; - - internal TypeRegistrar(ITypeRegistrar registrar) - { - _registrar = registrar ?? throw new ArgumentNullException(nameof(registrar)); - } - - public void Register() - where TImplementation : TService - { - _registrar.Register(typeof(TService), typeof(TImplementation)); - } - - public void RegisterInstance(TImplementation instance) - { - if (instance == null) - { - throw new ArgumentNullException(nameof(instance)); - } - - _registrar.RegisterInstance(typeof(TImplementation), instance); - } - - public void RegisterInstance(TImplementation instance) - where TImplementation : TService - { - if (instance == null) - { - throw new ArgumentNullException(nameof(instance)); - } - - _registrar.RegisterInstance(typeof(TService), instance); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/TypeResolverAdapter.cs b/src/Spectre.Console.Cli/Internal/TypeResolverAdapter.cs deleted file mode 100644 index c2cc3603c..000000000 --- a/src/Spectre.Console.Cli/Internal/TypeResolverAdapter.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace Spectre.Console.Cli; - -internal sealed class TypeResolverAdapter : ITypeResolver, IDisposable -{ - private readonly ITypeResolver? _resolver; - - public TypeResolverAdapter(ITypeResolver? resolver) - { - _resolver = resolver; - } - - public object? Resolve(Type? type) - { - if (type == null) - { - throw new CommandRuntimeException("Cannot resolve null type."); - } - - try - { - var obj = _resolver?.Resolve(type); - if (obj != null) - { - return obj; - } - - // Fall back to use the activator. - return Activator.CreateInstance(type); - } - catch (CommandAppException) - { - throw; - } - catch (Exception ex) - { - throw CommandRuntimeException.CouldNotResolveType(type, ex); - } - } - - public void Dispose() - { - if (_resolver is IDisposable disposable) - { - disposable.Dispose(); - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/VersionHelper.cs b/src/Spectre.Console.Cli/Internal/VersionHelper.cs deleted file mode 100644 index 692662769..000000000 --- a/src/Spectre.Console.Cli/Internal/VersionHelper.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Spectre.Console.Cli; - -internal static class VersionHelper -{ - public static string GetVersion(Assembly? assembly) - { - return assembly? - .GetCustomAttribute()? - .InformationalVersion ?? "?"; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/PairDeconstructor.cs b/src/Spectre.Console.Cli/PairDeconstructor.cs deleted file mode 100644 index 318c32829..000000000 --- a/src/Spectre.Console.Cli/PairDeconstructor.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace Spectre.Console.Cli; - -/// -/// Base class for a pair deconstructor. -/// -/// The key type. -/// The value type. -public abstract class PairDeconstructor : IPairDeconstructor -{ - /// - /// Deconstructs the provided into a pair. - /// - /// The string to deconstruct into a pair. - /// The deconstructed pair. - protected abstract (TKey Key, TValue Value) Deconstruct(string? value); - - /// - (object? Key, object? Value) IPairDeconstructor.Deconstruct(ITypeResolver resolver, Type keyType, Type valueType, string? value) - { - if (!keyType.IsAssignableFrom(typeof(TKey)) || !valueType.IsAssignableFrom(typeof(TValue))) - { - throw new InvalidOperationException("Pair destructor is not compatible."); - } - - return Deconstruct(value); - } -} - -/// -/// Base class for a pair deconstructor. -/// -/// The key type. -/// The value type. -/// This class is misspelled, use instead. -[Obsolete("Use PairDeconstructor instead")] -public abstract class PairDeconstuctor : PairDeconstructor -{ -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Properties/Usings.cs b/src/Spectre.Console.Cli/Properties/Usings.cs deleted file mode 100644 index 4cd53971a..000000000 --- a/src/Spectre.Console.Cli/Properties/Usings.cs +++ /dev/null @@ -1,17 +0,0 @@ -global using System; -global using System.Collections; -global using System.Collections.Generic; -global using System.ComponentModel; -global using System.Diagnostics; -global using System.Diagnostics.CodeAnalysis; -global using System.Globalization; -global using System.IO; -global using System.Linq; -global using System.Reflection; -global using System.Text; -global using System.Threading; -global using System.Threading.Tasks; -global using System.Xml; -global using Spectre.Console.Cli.Help; -global using Spectre.Console.Cli.Unsafe; -global using Spectre.Console.Rendering; \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.Designer.cs b/src/Spectre.Console.Cli/Resources/HelpProvider.Designer.cs deleted file mode 100644 index f00dd5623..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.Designer.cs +++ /dev/null @@ -1,153 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Spectre.Console.Cli.Resources { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class HelpProvider { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal HelpProvider() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Spectre.Console.Cli.Resources.HelpProvider", typeof(HelpProvider).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to ARGUMENTS. - /// - internal static string Arguments { - get { - return ResourceManager.GetString("Arguments", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to COMMAND. - /// - internal static string Command { - get { - return ResourceManager.GetString("Command", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to COMMANDS. - /// - internal static string Commands { - get { - return ResourceManager.GetString("Commands", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DEFAULT. - /// - internal static string Default { - get { - return ResourceManager.GetString("Default", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DESCRIPTION. - /// - internal static string Description { - get { - return ResourceManager.GetString("Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to EXAMPLES. - /// - internal static string Examples { - get { - return ResourceManager.GetString("Examples", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to OPTIONS. - /// - internal static string Options { - get { - return ResourceManager.GetString("Options", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Prints help information.. - /// - internal static string PrintHelpDescription { - get { - return ResourceManager.GetString("PrintHelpDescription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Prints version information.. - /// - internal static string PrintVersionDescription { - get { - return ResourceManager.GetString("PrintVersionDescription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to USAGE. - /// - internal static string Usage { - get { - return ResourceManager.GetString("Usage", resourceCulture); - } - } - } -} diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.de.resx b/src/Spectre.Console.Cli/Resources/HelpProvider.de.resx deleted file mode 100644 index 865313871..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.de.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ARGUMENTE - - - KOMMANDO - - - KOMMANDOS - - - STANDARDWERT - - - BESCHREIBUNG - - - BEISPIELE - - - OPTIONEN - - - Zeigt Hilfe an. - - - Zeigt Versionsinformationen an. - - - VERWENDUNG - - \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.es.resx b/src/Spectre.Console.Cli/Resources/HelpProvider.es.resx deleted file mode 100644 index 11515ecdd..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.es.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ARGUMENTOS - - - COMANDO - - - COMMANDOS - - - POR DEFECTO - - - DESCRIPCION - - - EJEMPLOS - - - OPCIONES - - - Imprime información de ayuda. - - - Imprime información de versión. - - - USO - - \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.fr.resx b/src/Spectre.Console.Cli/Resources/HelpProvider.fr.resx deleted file mode 100644 index 2c1658943..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.fr.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ARGUMENTS - - - COMMANDE - - - COMMANDES - - - DÉFAUT - - - DESCRIPTION - - - EXEMPLES - - - OPTIONS - - - Affiche l'aide. - - - Affiche la version. - - - UTILISATION - - \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.it.resx b/src/Spectre.Console.Cli/Resources/HelpProvider.it.resx deleted file mode 100644 index bfe82758e..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.it.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ARGOMENTI - - - COMANDO - - - COMANDI - - - PREDEFINITO - - - DESCRIZIONE - - - ESEMPI - - - OPZIONI - - - Visualizza le informazioni di aiuto. - - - Visualizza le informazioni sulla versione. - - - USO - - \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.ja.resx b/src/Spectre.Console.Cli/Resources/HelpProvider.ja.resx deleted file mode 100644 index bbe54d037..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.ja.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 引数 - - - コマンド - - - コマンド群 - - - デフォルト - - - 説明 - - - - - - オプション - - - ヘルプ情報を表示 - - - バージョン情報を表示 - - - 使用法 - - \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.ko.resx b/src/Spectre.Console.Cli/Resources/HelpProvider.ko.resx deleted file mode 100644 index fab73bcec..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.ko.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 인수 - - - 명령 - - - 명령어 - - - 기본값 - - - 설명 - - - 예시 - - - 옵션 - - - 도움말 정보를 출력 - - - 버전 정보를 출력 - - - 사용법 - - \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.pt.resx b/src/Spectre.Console.Cli/Resources/HelpProvider.pt.resx deleted file mode 100644 index 67d4a0a21..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.pt.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ARGUMENTOS - - - COMANDO - - - COMANDOS - - - PADRÃO - - - DESCRIÇÃO - - - EXEMPLOS - - - OPÇÕES - - - Exibe informações de ajuda. - - - Exibe informações de versão. - - - USO - - \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.resx b/src/Spectre.Console.Cli/Resources/HelpProvider.resx deleted file mode 100644 index 5fdb89885..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ARGUMENTS - - - COMMAND - - - COMMANDS - - - DEFAULT - - - DESCRIPTION - - - EXAMPLES - - - OPTIONS - - - Prints help information. - - - Prints version information. - - - USAGE - - \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.ru.resx b/src/Spectre.Console.Cli/Resources/HelpProvider.ru.resx deleted file mode 100644 index 3c1f14212..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.ru.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - АРГУМЕНТЫ - - - КОМАНДА - - - КОМАНДЫ - - - ПО УМОЛЧАНИЮ - - - ОПИСАНИЕ - - - ПРИМЕРЫ - - - ОПЦИИ - - - Выводит информацию о помощи. - - - Выводит информацию о версии. - - - ИСПОЛЬЗОВАНИЕ - - \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.sv.resx b/src/Spectre.Console.Cli/Resources/HelpProvider.sv.resx deleted file mode 100644 index 4717d689c..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.sv.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ARGUMENT - - - KOMMANDO - - - KOMMANDON - - - STANDARD - - - BESKRIVNING - - - EXEMPEL - - - VAL - - - Skriver ut hjälpinformation. - - - Skriver ut versionsnummer. - - - ANVÄNDING - - \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Resources/HelpProvider.zh-Hans.resx b/src/Spectre.Console.Cli/Resources/HelpProvider.zh-Hans.resx deleted file mode 100644 index 737ad9b43..000000000 --- a/src/Spectre.Console.Cli/Resources/HelpProvider.zh-Hans.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 参数 - - - 命令 - - - 命令列表 - - - 默认 - - - 描述 - - - 示例 - - - 选项 - - - 显示帮助信息 - - - 显示版本信息 - - - 用法 - - \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Spectre.Console.Cli.csproj b/src/Spectre.Console.Cli/Spectre.Console.Cli.csproj deleted file mode 100644 index 3fcd0e083..000000000 --- a/src/Spectre.Console.Cli/Spectre.Console.Cli.csproj +++ /dev/null @@ -1,52 +0,0 @@ - - - - net9.0;net8.0;netstandard2.0 - true - false - false - $(DefineConstants);OPENCLI_VISIBILITY_INTERNAL - - - - - - - - 3.0.0 - False - - - - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - - - - - True - True - HelpProvider.resx - - - - - - ResXFileCodeGenerator - HelpProvider.Designer.cs - - - - - - - - diff --git a/src/Spectre.Console.Cli/Unsafe/IUnsafeBranchConfigurator.cs b/src/Spectre.Console.Cli/Unsafe/IUnsafeBranchConfigurator.cs deleted file mode 100644 index 29c6d413a..000000000 --- a/src/Spectre.Console.Cli/Unsafe/IUnsafeBranchConfigurator.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Spectre.Console.Cli.Unsafe; - -/// -/// Represents an unsafe configurator for a branch. -/// -public interface IUnsafeBranchConfigurator : IUnsafeConfigurator -{ - /// - /// Sets the description of the branch. - /// - /// The description of the branch. - void SetDescription(string description); - - /// - /// Adds an example of how to use the branch. - /// - /// The example arguments. - void AddExample(string[] args); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Unsafe/IUnsafeConfigurator.cs b/src/Spectre.Console.Cli/Unsafe/IUnsafeConfigurator.cs deleted file mode 100644 index dd8904372..000000000 --- a/src/Spectre.Console.Cli/Unsafe/IUnsafeConfigurator.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Spectre.Console.Cli.Unsafe; - -/// -/// Represents an unsafe configurator. -/// -public interface IUnsafeConfigurator -{ - /// - /// Adds a command. - /// - /// The name of the command. - /// The command type. - /// A command configurator that can be used to configure the command further. - ICommandConfigurator AddCommand(string name, Type command); - - /// - /// Adds a command branch. - /// - /// The name of the command branch. - /// The command setting type. - /// The command branch configurator. - /// A branch configurator that can be used to configure the branch further. - IBranchConfigurator AddBranch(string name, Type settings, Action action); -} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Unsafe/UnsafeConfiguratorExtensions.cs b/src/Spectre.Console.Cli/Unsafe/UnsafeConfiguratorExtensions.cs deleted file mode 100644 index 6d24ed8f3..000000000 --- a/src/Spectre.Console.Cli/Unsafe/UnsafeConfiguratorExtensions.cs +++ /dev/null @@ -1,80 +0,0 @@ -namespace Spectre.Console.Cli.Unsafe; - -/// -/// Contains unsafe extensions for . -/// -public static class UnsafeConfiguratorExtensions -{ - /// - /// Gets an that allows - /// composition of commands without type safety. - /// - /// The configurator. - /// An . - public static IUnsafeConfigurator SafetyOff(this IConfigurator configurator) - { - if (!(configurator is IUnsafeConfigurator @unsafe)) - { - throw new CommandConfigurationException("Configurator does not support manual configuration"); - } - - return @unsafe; - } - - /// - /// Converts an to - /// a configurator with type safety. - /// - /// The configurator. - /// An . - public static IConfigurator SafetyOn(this IUnsafeConfigurator configurator) - { - if (!(configurator is IConfigurator safe)) - { - throw new CommandConfigurationException("Configurator cannot be converted to a safe configurator."); - } - - return safe; - } - - /// - /// Gets an that allows - /// composition of commands without type safety. - /// - /// The command settings. - /// The configurator. - /// An . - public static IUnsafeConfigurator SafetyOff(this IConfigurator configurator) - where TSettings : CommandSettings - { - if (!(configurator is IUnsafeConfigurator @unsafe)) - { - throw new CommandConfigurationException("Configurator does not support manual configuration"); - } - - return @unsafe; - } - - /// - /// Converts an to - /// a configurator with type safety. - /// - /// The command settings. - /// The configurator. - /// An . - public static IConfigurator SafetyOn(this IUnsafeBranchConfigurator configurator) - where TSettings : CommandSettings - { - if (!(configurator is IConfigurator safe)) - { - throw new CommandConfigurationException($"Configurator cannot be converted to a safe configurator of type '{typeof(TSettings).Name}'."); - } - - if (safe.GetType().GetGenericArguments().First() != typeof(TSettings)) - { - throw new CommandConfigurationException($"Configurator cannot be converted to a safe configurator of type '{typeof(TSettings).Name}'."); - } - - return safe; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Testing/Cli/CallbackCommandInterceptor.cs b/src/Spectre.Console.Testing/Cli/CallbackCommandInterceptor.cs deleted file mode 100644 index d2c610c42..000000000 --- a/src/Spectre.Console.Testing/Cli/CallbackCommandInterceptor.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Spectre.Console.Testing; - -/// -/// A that triggers a callback when invoked. -/// -public sealed class CallbackCommandInterceptor : ICommandInterceptor -{ - private readonly Action _callback; - - /// - /// Initializes a new instance of the class. - /// - /// The callback to call when the interceptor is invoked. - public CallbackCommandInterceptor(Action callback) - { - _callback = callback ?? throw new ArgumentNullException(nameof(callback)); - } - - /// - public void Intercept(CommandContext context, CommandSettings settings) - { - _callback(context, settings); - } - -#if NETSTANDARD2_0 - /// - public void InterceptResult(CommandContext context, CommandSettings settings, ref int result) - { - } -#endif -} \ No newline at end of file diff --git a/src/Spectre.Console.Testing/Cli/CommandAppFailure.cs b/src/Spectre.Console.Testing/Cli/CommandAppFailure.cs deleted file mode 100644 index 611cdd0e5..000000000 --- a/src/Spectre.Console.Testing/Cli/CommandAppFailure.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Spectre.Console.Testing; - -/// -/// Represents a runtime failure. -/// -public sealed class CommandAppFailure -{ - /// - /// Gets the exception that was thrown. - /// - public Exception Exception { get; } - - /// - /// Gets the console output. - /// - public string Output { get; } - - internal CommandAppFailure(Exception exception, string output) - { - Exception = exception ?? throw new ArgumentNullException(nameof(exception)); - Output = output.NormalizeLineEndings() - .TrimLines() - .Trim(); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Testing/Cli/CommandAppResult.cs b/src/Spectre.Console.Testing/Cli/CommandAppResult.cs deleted file mode 100644 index ebc30f0a7..000000000 --- a/src/Spectre.Console.Testing/Cli/CommandAppResult.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace Spectre.Console.Testing; - -/// -/// Represents the result of a completed run. -/// -public sealed class CommandAppResult -{ - /// - /// Gets the exit code. - /// - public int ExitCode { get; } - - /// - /// Gets the console output. - /// - public string Output { get; } - - /// - /// Gets the command context. - /// - public CommandContext? Context { get; } - - /// - /// Gets the command settings. - /// - public CommandSettings? Settings { get; } - - internal CommandAppResult(int exitCode, string output, CommandContext? context, CommandSettings? settings) - { - ExitCode = exitCode; - Output = output ?? string.Empty; - Context = context; - Settings = settings; - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Testing/Cli/CommandAppTester.cs b/src/Spectre.Console.Testing/Cli/CommandAppTester.cs deleted file mode 100644 index f2156e951..000000000 --- a/src/Spectre.Console.Testing/Cli/CommandAppTester.cs +++ /dev/null @@ -1,178 +0,0 @@ -namespace Spectre.Console.Testing; - -/// -/// A test harness. -/// -public sealed class CommandAppTester -{ - private Action? _appConfiguration; - private Action? _configuration; - - /// - /// Gets the test console used by both the CommandAppTester and CommandApp. - /// - public TestConsole Console { get; } - - /// - /// Gets or sets the Registrar to use in the CommandApp. - /// - public ITypeRegistrar? Registrar { get; set; } - - /// - /// Gets or sets the settings for the . - /// - public CommandAppTesterSettings TestSettings { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The registrar. - /// The settings. - /// The test console that overrides the default one. - public CommandAppTester( - ITypeRegistrar? registrar = null, - CommandAppTesterSettings? settings = null, - TestConsole? console = null) - { - Registrar = registrar; - TestSettings = settings ?? new CommandAppTesterSettings(); - Console = console ?? new TestConsole().Width(int.MaxValue); - } - - /// - /// Initializes a new instance of the class. - /// - /// The settings. - public CommandAppTester(CommandAppTesterSettings settings) - { - TestSettings = settings; - Console = new TestConsole().Width(int.MaxValue); - } - - /// - /// Sets the default command. - /// - /// The optional default command description. - /// The optional default command data. - /// The default command type. - public void SetDefaultCommand(string? description = null, object? data = null) - where T : class, ICommand - { - _appConfiguration = (app) => - { - var defaultCommandBuilder = app.SetDefaultCommand(); - if (description != null) - { - defaultCommandBuilder.WithDescription(description); - } - - if (data != null) - { - defaultCommandBuilder.WithData(data); - } - }; - } - - /// - /// Configures the command application. - /// - /// The configuration action. - public void Configure(Action action) - { - if (_configuration != null) - { - throw new InvalidOperationException("The command app harnest have already been configured."); - } - - _configuration = action; - } - - /// - /// Runs the command application and expects an exception of a specific type to be thrown. - /// - /// The expected exception type. - /// The arguments. - /// The information about the failure. - public CommandAppFailure RunAndCatch(params string[] args) - where T : Exception - { - try - { - RunAsync(args, Console, c => c.PropagateExceptions()).GetAwaiter().GetResult(); - throw new InvalidOperationException("Expected an exception to be thrown, but there was none."); - } - catch (T ex) - { - if (ex is CommandAppException commandAppException && commandAppException.Pretty != null) - { - Console.Write(commandAppException.Pretty); - } - else - { - Console.WriteLine(ex.Message); - } - - return new CommandAppFailure(ex, Console.Output); - } - catch (Exception ex) - { - throw new InvalidOperationException( - $"Expected an exception of type '{typeof(T).FullName}' to be thrown, " - + $"but received {ex.GetType().FullName}."); - } - } - - /// - /// Runs the command application. - /// - /// The arguments. - /// The result. - public CommandAppResult Run(params string[] args) - { - return RunAsync(args, Console).GetAwaiter().GetResult(); - } - - /// - /// Runs the command application asynchronously. - /// - /// The arguments. - /// The token to monitor for cancellation requests. - /// The result. - public async Task RunAsync(string[]? args = null, CancellationToken cancellationToken = default) - { - return await RunAsync(args ?? [], Console, cancellationToken: cancellationToken); - } - - private async Task RunAsync(string[] args, TestConsole console, Action? config = null, CancellationToken cancellationToken = default) - { - CommandContext? context = null; - CommandSettings? settings = null; - - var app = new CommandApp(Registrar); - _appConfiguration?.Invoke(app); - - if (_configuration != null) - { - app.Configure(_configuration); - } - - if (config != null) - { - app.Configure(config); - } - - app.Configure(c => c.ConfigureConsole(console)); - app.Configure(c => c.SetInterceptor(new CallbackCommandInterceptor((ctx, s) => - { - context = ctx; - settings = s; - }))); - - var result = await app.RunAsync(args, cancellationToken); - - var output = console.Output.NormalizeLineEndings(); - output = TestSettings.TrimConsoleOutput ? output.TrimLines().Trim() : output; - - return new CommandAppResult(result, output, context, settings); - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Testing/Cli/CommandAppTesterSettings.cs b/src/Spectre.Console.Testing/Cli/CommandAppTesterSettings.cs deleted file mode 100644 index c4d149d1d..000000000 --- a/src/Spectre.Console.Testing/Cli/CommandAppTesterSettings.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Spectre.Console.Testing; - -/// -/// Represents the configuration settings for the class. -/// -public sealed class CommandAppTesterSettings -{ - /// - /// Gets or sets a value indicating whether whitespace should be trimmed from the console output. - /// - /// - /// When enabled, leading and trailing whitespace from the console output and trailing whitespace from each line will be trimmed. - /// - public bool TrimConsoleOutput { get; set; } = true; -} \ No newline at end of file diff --git a/src/Spectre.Console.Testing/Cli/TypeRegistrarBaseTests.cs b/src/Spectre.Console.Testing/Cli/TypeRegistrarBaseTests.cs deleted file mode 100644 index 723dfcb19..000000000 --- a/src/Spectre.Console.Testing/Cli/TypeRegistrarBaseTests.cs +++ /dev/null @@ -1,271 +0,0 @@ -namespace Spectre.Console.Testing; - -/// -/// This is a utility class for implementors of -/// and corresponding . -/// -public sealed class TypeRegistrarBaseTests -{ - private readonly Func _registrarFactory; - - /// - /// Initializes a new instance of the class. - /// - /// The factory to create a new, clean to be used for each test. - public TypeRegistrarBaseTests(Func registrarFactory) - { - _registrarFactory = registrarFactory; - } - - /// - /// Runs all tests. - /// - /// This exception is raised, if a test fails. - public void RunAllTests() - { - var testCases = new[] - { - RegistrationsCanBeResolved, - InstanceRegistrationsCanBeResolved, - LazyRegistrationsCanBeResolved, - ResolvingNotRegisteredServiceReturnsNull, - ResolvingNullTypeReturnsNull, - ResolvingSingleInstanceOfMultipleRegistrationsResolvesTheFirstOne, - ResolvingAnEnumerableOfInstancesDoesNotReturnNull, - ResolvingAnEnumerableOfInstancesOfMultipleRegistrationsResolvesAllRegistrations, - }; - - foreach (var test in testCases) - { - test(_registrarFactory()); - } - } - - private void ResolvingAnEnumerableOfInstancesDoesNotReturnNull(ITypeRegistrar registrar) - { - // Given - var resolver = registrar.Build(); - - // When - var actual = resolver.Resolve(typeof(IEnumerable)) as IEnumerable; - - // Then - if (actual == null) - { - throw new TestFailedException( - "Expected an IEnumerable never to resolve to null."); - } - } - - private void ResolvingAnEnumerableOfInstancesOfMultipleRegistrationsResolvesAllRegistrations(ITypeRegistrar registrar) - { - // Given - var theLastRegistration = new AnotherMockService("last"); - registrar.RegisterLazy(typeof(IMockService), () => new AnotherMockService("first")); - registrar.Register(typeof(IMockService), typeof(MockService)); - registrar.RegisterInstance(typeof(IMockService), theLastRegistration); - var resolver = registrar.Build(); - - // When - var actual = (resolver.Resolve(typeof(IEnumerable)) as IEnumerable)!.ToList(); - - // Then - if (actual.Count != 3) - { - throw new TestFailedException( - "Expected the resolver to resolve a list with exactly 3 elements."); - } - - if (actual.Count(x => x.GetType() == typeof(AnotherMockService)) != 2) - { - throw new TestFailedException( - $"Expected the resolver to resolve a list with exactly 2 elements of type {nameof(AnotherMockService)}."); - } - - if (actual.Count(x => x.GetType() == typeof(MockService)) != 1) - { - throw new TestFailedException( - $"Expected the resolver to resolve a list with exactly one element of type {nameof(MockService)}."); - } - - if (!actual.Contains(theLastRegistration)) - { - throw new TestFailedException( - "Expected the resolver to resolve the known instance that was registered."); - } - } - - private void ResolvingSingleInstanceOfMultipleRegistrationsResolvesTheFirstOne(ITypeRegistrar registrar) - { - // Given - var theLastRegistration = new AnotherMockService("last"); - registrar.RegisterLazy(typeof(IMockService), () => new AnotherMockService("first")); - registrar.Register(typeof(IMockService), typeof(MockService)); - registrar.RegisterInstance(typeof(IMockService), theLastRegistration); - var resolver = registrar.Build(); - - // When - var actual = resolver.Resolve(typeof(IMockService)); - - // Then - if (!ReferenceEquals(actual, theLastRegistration)) - { - throw new TestFailedException( - "Expected the resolver to resolve the first registered instance of multiple registrations."); - } - } - - private static void ResolvingNullTypeReturnsNull(ITypeRegistrar registrar) - { - // Given no registration - var resolver = registrar.Build(); - - try - { - // When - var actual = resolver.Resolve(null); - - // Then - if (actual != null) - { - throw new TestFailedException( - $"Expected the resolver to resolve null, since null was requested as the service type. Actually resolved {actual.GetType().Name}."); - } - } - catch (Exception ex) - { - throw new TestFailedException( - $"Expected the resolver not to throw, but caught {ex.GetType().Name}.", ex); - } - } - - private static void ResolvingNotRegisteredServiceReturnsNull(ITypeRegistrar registrar) - { - // Given no registration - var resolver = registrar.Build(); - - try - { - // When - var actual = resolver.Resolve(typeof(IMockService)); - - // Then - if (actual != null) - { - throw new TestFailedException( - $"Expected the resolver to resolve null, since no service was registered. Actually resolved {actual.GetType().Name}."); - } - } - catch (Exception ex) - { - throw new TestFailedException( - $"Expected the resolver not to throw, but caught {ex.GetType().Name}.", ex); - } - } - - private static void RegistrationsCanBeResolved(ITypeRegistrar registrar) - { - // Given - registrar.Register(typeof(IMockService), typeof(MockService)); - var resolver = registrar.Build(); - - // When - var actual = resolver.Resolve(typeof(IMockService)); - - // Then - if (actual == null) - { - throw new TestFailedException( - $"Expected the resolver to resolve an instance of {nameof(MockService)}. Actually resolved null."); - } - - if (actual is not MockService) - { - throw new TestFailedException( - $"Expected the resolver to resolve an instance of {nameof(MockService)}. Actually resolved {actual.GetType().Name}."); - } - } - - private static void InstanceRegistrationsCanBeResolved(ITypeRegistrar registrar) - { - // Given - var instance = new MockService(); - registrar.RegisterInstance(typeof(IMockService), instance); - var resolver = registrar.Build(); - - // When - var actual = resolver.Resolve(typeof(IMockService)); - - // Then - if (!ReferenceEquals(actual, instance)) - { - throw new TestFailedException( - "Expected the resolver to resolve exactly the registered instance."); - } - } - - private static void LazyRegistrationsCanBeResolved(ITypeRegistrar registrar) - { - // Given - var instance = new MockService(); - var factoryCalled = false; - registrar.RegisterLazy(typeof(IMockService), () => - { - factoryCalled = true; - return instance; - }); - var resolver = registrar.Build(); - - // When - var actual = resolver.Resolve(typeof(IMockService)); - - // Then - if (!factoryCalled) - { - throw new TestFailedException( - "Expected the factory to be called, to resolve the lazy registration."); - } - - if (!ReferenceEquals(actual, instance)) - { - throw new TestFailedException( - "Expected the resolver to return exactly the result of the lazy-registered factory."); - } - } - - /// - /// internal use only. - /// - private interface IMockService - { - } - - private class MockService : IMockService - { - } - - private class AnotherMockService : IMockService - { - public AnotherMockService(string ignore) - { - } - } - - /// - /// Exception, to be raised when a test fails. - /// - public sealed class TestFailedException : Exception - { - /// - public TestFailedException(string message) - : base(message) - { - } - - /// - public TestFailedException(string message, Exception inner) - : base(message, inner) - { - } - } -} \ No newline at end of file diff --git a/src/Spectre.Console.Testing/Extensions/ShouldlyExtensions.cs b/src/Spectre.Console.Testing/Extensions/ShouldlyExtensions.cs index fbdb2e0a3..4f1d81729 100644 --- a/src/Spectre.Console.Testing/Extensions/ShouldlyExtensions.cs +++ b/src/Spectre.Console.Testing/Extensions/ShouldlyExtensions.cs @@ -26,4 +26,4 @@ public static T And(this T item, Action action) action(item); return item; } -} +} \ No newline at end of file diff --git a/src/Spectre.Console.Testing/FakeTypeRegistrar.cs b/src/Spectre.Console.Testing/FakeTypeRegistrar.cs deleted file mode 100644 index 124477a1d..000000000 --- a/src/Spectre.Console.Testing/FakeTypeRegistrar.cs +++ /dev/null @@ -1,76 +0,0 @@ -namespace Spectre.Console.Testing; - -/// -/// A fake type registrar suitable for testing. -/// -public sealed class FakeTypeRegistrar : ITypeRegistrar -{ - /// - /// Gets all registrations. - /// - public Dictionary> Registrations { get; } - - /// - /// Gets all singleton registrations. - /// - public Dictionary> Instances { get; } - - /// - /// Initializes a new instance of the class. - /// - public FakeTypeRegistrar() - { - Registrations = new Dictionary>(); - Instances = new Dictionary>(); - } - - /// - public void Register(Type service, Type implementation) - { - if (!Registrations.ContainsKey(service)) - { - Registrations.Add(service, new List { implementation }); - } - else - { - Registrations[service].Add(implementation); - } - } - - /// - public void RegisterInstance(Type service, object implementation) - { - if (!Instances.ContainsKey(service)) - { - Instances.Add(service, new List { implementation }); - } - else - { - Instances[service].Add(implementation); - } - } - - /// - public void RegisterLazy(Type service, Func factory) - { - if (factory is null) - { - throw new ArgumentNullException(nameof(factory)); - } - - if (!Instances.ContainsKey(service)) - { - Instances.Add(service, new List { factory() }); - } - else - { - Instances[service].Add(factory()); - } - } - - /// - public ITypeResolver Build() - { - return new FakeTypeResolver(Registrations, Instances); - } -} diff --git a/src/Spectre.Console.Testing/FakeTypeResolver.cs b/src/Spectre.Console.Testing/FakeTypeResolver.cs deleted file mode 100644 index d6e85727f..000000000 --- a/src/Spectre.Console.Testing/FakeTypeResolver.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.Collections; - -namespace Spectre.Console.Testing; - -/// -/// A fake type resolver suitable for testing. -/// -public sealed class FakeTypeResolver : ITypeResolver -{ - private readonly Dictionary> _registrations; - private readonly Dictionary> _instances; - - /// - /// Initializes a new instance of the class. - /// - /// The registrations. - /// The singleton registrations. - public FakeTypeResolver( - Dictionary> registrations, - Dictionary> instances) - { - _registrations = registrations ?? throw new ArgumentNullException(nameof(registrations)); - _instances = instances ?? throw new ArgumentNullException(nameof(instances)); - } - - /// - public object? Resolve(Type? type) - { - if (type == null) - { - return null; - } - - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) - { - // return all registrations - type = type.GenericTypeArguments[0]; - var allRegistrations = Activator.CreateInstance(typeof(List<>).MakeGenericType(type)); - var castList = allRegistrations as IList; - - if (_instances.TryGetValue(type, out var listInstances)) - { - listInstances.ForEach(i => castList!.Add(i)); - } - - if (_registrations.TryGetValue(type, out var listRegistrations)) - { - listRegistrations - .Select(x => Activator.CreateInstance(x)!) - .ToList() - .ForEach(i => castList!.Add(i)); - } - - return allRegistrations; - } - - if (_instances.TryGetValue(type, out var instances)) - { - return instances.LastOrDefault(); - } - - if (_registrations.TryGetValue(type, out var registrations)) - { - // The type might be an interface, but the registration should be a class. - // So call CreateInstance on the first registration rather than the type. - return registrations.Count == 0 - ? null - : Activator.CreateInstance(registrations.Last()); - } - - return null; - } -} diff --git a/src/Spectre.Console.Testing/Properties/Usings.cs b/src/Spectre.Console.Testing/Properties/Usings.cs index 4f5f1e958..5956fa8b7 100644 --- a/src/Spectre.Console.Testing/Properties/Usings.cs +++ b/src/Spectre.Console.Testing/Properties/Usings.cs @@ -2,9 +2,6 @@ global using System.Collections.Generic; global using System.Diagnostics; global using System.IO; -global using System.Linq; -global using System.Text.RegularExpressions; global using System.Threading; global using System.Threading.Tasks; -global using Spectre.Console.Cli; global using Spectre.Console.Rendering; \ No newline at end of file diff --git a/src/Spectre.Console.Testing/Spectre.Console.Testing.csproj b/src/Spectre.Console.Testing/Spectre.Console.Testing.csproj index 13d443409..ad92a3536 100644 --- a/src/Spectre.Console.Testing/Spectre.Console.Testing.csproj +++ b/src/Spectre.Console.Testing/Spectre.Console.Testing.csproj @@ -8,7 +8,6 @@ - diff --git a/src/Tests/Spectre.Console.Tests/Data/Exceptions.cs b/src/Spectre.Console.Tests/Data/Exceptions.cs similarity index 95% rename from src/Tests/Spectre.Console.Tests/Data/Exceptions.cs rename to src/Spectre.Console.Tests/Data/Exceptions.cs index a7e066eee..15c4e5687 100644 --- a/src/Tests/Spectre.Console.Tests/Data/Exceptions.cs +++ b/src/Spectre.Console.Tests/Data/Exceptions.cs @@ -6,7 +6,7 @@ public static class TestExceptions public static bool GenericMethodThatThrows(int? number) => throw new InvalidOperationException("Throwing!"); - public static bool MethodThatThrowsGenericException() => throw new GenericException("Throwing!", default); + public static bool MethodThatThrowsGenericException() => throw new GenericException("Throwing!", default!); public static void ThrowWithInnerException() { @@ -46,4 +46,4 @@ public static (string Key, List Values) GetTuplesWithInnerException((int F } #pragma warning disable CS9113 // Parameter is unread. -public class GenericException(string message, T value) : Exception(message); +public class GenericException(string message, T value) : Exception(message); \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Data/example.json b/src/Spectre.Console.Tests/Data/example.json similarity index 100% rename from src/Tests/Spectre.Console.Tests/Data/example.json rename to src/Spectre.Console.Tests/Data/example.json diff --git a/src/Tests/Spectre.Console.Tests/Data/poison.flf b/src/Spectre.Console.Tests/Data/poison.flf similarity index 100% rename from src/Tests/Spectre.Console.Tests/Data/poison.flf rename to src/Spectre.Console.Tests/Data/poison.flf diff --git a/src/Tests/Spectre.Console.Tests/Data/starwars.flf b/src/Spectre.Console.Tests/Data/starwars.flf similarity index 100% rename from src/Tests/Spectre.Console.Tests/Data/starwars.flf rename to src/Spectre.Console.Tests/Data/starwars.flf diff --git a/src/Tests/Spectre.Console.Tests/Expectations/AlternateScreen/Show.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/AlternateScreen/Show.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/AlternateScreen/Show.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/AlternateScreen/Show.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/ArgumentCannotContainOptions.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/ArgumentCannotContainOptions.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/ArgumentCannotContainOptions.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/ArgumentCannotContainOptions.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/InvalidCharacterInOptionName.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInOptionName.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/InvalidCharacterInOptionName.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInOptionName.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/InvalidCharacterInValueName.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInValueName.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/InvalidCharacterInValueName.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInValueName.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/LongOptionMustHaveMoreThanOneCharacter.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/LongOptionMustHaveMoreThanOneCharacter.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/LongOptionMustHaveMoreThanOneCharacter.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/LongOptionMustHaveMoreThanOneCharacter.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/MissingLongAndShortName.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/MissingLongAndShortName.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/MissingLongAndShortName.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/MissingLongAndShortName.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/MultipleOptionValuesAreNotSupported.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleOptionValuesAreNotSupported.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/MultipleOptionValuesAreNotSupported.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleOptionValuesAreNotSupported.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/MultipleValuesAreNotSupported.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleValuesAreNotSupported.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/MultipleValuesAreNotSupported.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleValuesAreNotSupported.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/OptionNamesCannotStartWithDigit.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionNamesCannotStartWithDigit.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/OptionNamesCannotStartWithDigit.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionNamesCannotStartWithDigit.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/OptionsMustHaveName.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionsMustHaveName.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/OptionsMustHaveName.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionsMustHaveName.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/ShortOptionMustOnlyBeOneCharacter.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/ShortOptionMustOnlyBeOneCharacter.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/ShortOptionMustOnlyBeOneCharacter.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/ShortOptionMustOnlyBeOneCharacter.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/UnexpectedCharacter.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/UnexpectedCharacter.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/UnexpectedCharacter.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/UnexpectedCharacter.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/UnterminatedValueName.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/UnterminatedValueName.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/UnterminatedValueName.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/UnterminatedValueName.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/ValuesMustHaveName.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Arguments/ValuesMustHaveName.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Arguments/ValuesMustHaveName.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Arguments/ValuesMustHaveName.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/ArgumentOrder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/ArgumentOrder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/ArgumentOrder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/ArgumentOrder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Command.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/Command.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Command.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/Command.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/CommandExamples.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/CommandExamples.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/CommandExamples.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/CommandExamples.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Default.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/Default.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Default.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/Default.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/DefaultExamples.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/DefaultExamples.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/DefaultExamples.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/DefaultExamples.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Hidden_Command_Options.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/Hidden_Command_Options.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Hidden_Command_Options.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/Hidden_Command_Options.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Hidden_Commands.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/Hidden_Commands.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Hidden_Commands.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/Hidden_Commands.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Leaf.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/Leaf.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Leaf.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/Leaf.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/NoDescription.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/NoDescription.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/NoDescription.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/NoDescription.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Root.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/Root.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/Root.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/Root.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples_Children.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples_Children.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples_Children.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples_Children.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples_Leafs.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples_Leafs.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples_Leafs.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Help/RootExamples_Leafs.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/CannotAssignValueToFlag/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/CannotAssignValueToFlag/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/CannotAssignValueToFlag/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/CannotAssignValueToFlag/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/CannotAssignValueToFlag/Test_2.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/CannotAssignValueToFlag/Test_2.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/CannotAssignValueToFlag/Test_2.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/CannotAssignValueToFlag/Test_2.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/InvalidShortOptionName/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/InvalidShortOptionName/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/InvalidShortOptionName/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/InvalidShortOptionName/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/LongOptionNameContainSymbol/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameContainSymbol/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/LongOptionNameContainSymbol/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameContainSymbol/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/LongOptionNameIsMissing/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsMissing/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/LongOptionNameIsMissing/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsMissing/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/LongOptionNameIsOneCharacter/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsOneCharacter/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/LongOptionNameIsOneCharacter/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsOneCharacter/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/LongOptionNameStartWithDigit/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameStartWithDigit/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/LongOptionNameStartWithDigit/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameStartWithDigit/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/NoMatchingArgument/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/NoMatchingArgument/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/NoMatchingArgument/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/NoMatchingArgument/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/NoValueForOption/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/NoValueForOption/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/NoValueForOption/Test_2.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_2.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/NoValueForOption/Test_2.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_2.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/OptionWithoutName/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/OptionWithoutName/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/OptionWithoutName/Test_2.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_2.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/OptionWithoutName/Test_2.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_2.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/OptionWithoutName/Test_3.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_3.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/OptionWithoutName/Test_3.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_3.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/OptionWithoutName/Test_4.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_4.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/OptionWithoutName/Test_4.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_4.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/OptionWithoutName/Test_5.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_5.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/OptionWithoutName/Test_5.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_5.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnexpectedOption/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnexpectedOption/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnexpectedOption/Test_2.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_2.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnexpectedOption/Test_2.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_2.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_2.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_2.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_2.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_2.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_3.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_3.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_3.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_3.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_4.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_4.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_4.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_4.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_5.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_5.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_5.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_5.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_6.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_6.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_6.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_6.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_7.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_7.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_7.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_7.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_8.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_8.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownCommand/Test_8.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_8.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownOption/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownOption/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownOption/Test_2.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_2.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/UnknownOption/Test_2.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_2.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Hidden_Command_Options.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Xml/Hidden_Command_Options.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Hidden_Command_Options.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Xml/Hidden_Command_Options.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_1.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_1.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_1.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_1.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_2.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_2.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_2.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_2.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_3.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_3.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_3.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_3.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_4.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_4.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_4.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_4.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_5.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_5.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_5.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_5.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_6.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_6.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_6.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Cli/Xml/Test_6.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Exception/CallSite.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/CallSite.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Exception/CallSite.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Exception/CallSite.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Exception/Default.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/Default.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Exception/Default.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Exception/Default.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=Default.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=Default.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=Default.verified.txt rename to src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=Default.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenTypes.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenTypes.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenTypes.verified.txt rename to src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenTypes.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Exception/InnerException.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/InnerException.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Exception/InnerException.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Exception/InnerException.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Exception/NoStackTrace.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/NoStackTrace.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Exception/NoStackTrace.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Exception/NoStackTrace.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Exception/OutParam.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/OutParam.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Exception/OutParam.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Exception/OutParam.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Exception/ShortenedMethods.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/ShortenedMethods.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Exception/ShortenedMethods.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Exception/ShortenedMethods.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Exception/ShortenedTypes.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/ShortenedTypes.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Exception/ShortenedTypes.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Exception/ShortenedTypes.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Exception/Tuple.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/Tuple.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Exception/Tuple.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Exception/Tuple.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Live/Progress/Render_ReduceWidth.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Live/Progress/Render_ReduceWidth.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Live/Progress/Render_ReduceWidth.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Live/Progress/Render_ReduceWidth.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Live/Status/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Live/Status/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Live/Status/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Live/Status/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/AcceptChoice.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/AcceptChoice.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/AcceptChoice.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/AcceptChoice.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_BestMatch.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_BestMatch.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_BestMatch.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_BestMatch.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_Empty.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_Empty.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_Empty.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_Empty.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_NextChoice.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_NextChoice.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_NextChoice.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_NextChoice.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_PreviousChoice.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_PreviousChoice.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_PreviousChoice.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/AutoComplete_PreviousChoice.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/ChoicesStyleNotSet.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/ChoicesStyleNotSet.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/ChoicesStyleNotSet.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/ChoicesStyleNotSet.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/ChoicesStyleSet.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/ChoicesStyleSet.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/ChoicesStyleSet.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/ChoicesStyleSet.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/ConversionError.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/ConversionError.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/ConversionError.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/ConversionError.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/CustomConverter.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/CustomConverter.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/CustomConverter.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/CustomConverter.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/CustomValidation.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/CustomValidation.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/CustomValidation.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/CustomValidation.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValue.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValue.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValue.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValue.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValueStyleNotSet.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValueStyleNotSet.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValueStyleNotSet.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValueStyleNotSet.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValueStyleSet.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValueStyleSet.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValueStyleSet.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/DefaultValueStyleSet.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/InvalidChoice.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/InvalidChoice.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/InvalidChoice.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/InvalidChoice.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/NoSuffix.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/NoSuffix.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/NoSuffix.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/NoSuffix.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValue.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValue.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValue.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValue.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValueCustomMask.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValueCustomMask.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValueCustomMask.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValueCustomMask.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValueNullMask.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValueNullMask.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValueNullMask.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/SecretDefaultValueNullMask.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/SecretValueBackspaceNullMask.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Prompts/Text/SecretValueBackspaceNullMask.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Prompts/Text/SecretValueBackspaceNullMask.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Prompts/Text/SecretValueBackspaceNullMask.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/AsciiBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/AsciiBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/AsciiBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/AsciiBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/DoubleBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/DoubleBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/DoubleBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/DoubleBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/HeavyBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/HeavyBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/HeavyBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/HeavyBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder_With_Header.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder_With_Header.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder_With_Header.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder_With_Header.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/RoundedBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/RoundedBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/RoundedBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/RoundedBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/SquareBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/SquareBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/SquareBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/SquareBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/Ascii2Border.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/Ascii2Border.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/Ascii2Border.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/Ascii2Border.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/AsciiBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/AsciiBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/AsciiBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/AsciiBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/AsciiDoubleHeadBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/AsciiDoubleHeadBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/AsciiDoubleHeadBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/AsciiDoubleHeadBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/DoubleBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/DoubleBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/DoubleBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/DoubleBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/DoubleEdgeBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/DoubleEdgeBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/DoubleEdgeBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/DoubleEdgeBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyEdgeBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyEdgeBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyEdgeBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyEdgeBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyHeadBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyHeadBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyHeadBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HeavyHeadBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HorizontalBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HorizontalBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HorizontalBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/HorizontalBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_Centered.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_Centered.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_Centered.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_Centered.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_LeftAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_LeftAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_LeftAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_LeftAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_RightAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_RightAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_RightAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MarkdownBorder_RightAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalDoubleHeadBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalDoubleHeadBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalDoubleHeadBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalDoubleHeadBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalHeavyHeadBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalHeavyHeadBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalHeavyHeadBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/MinimalHeavyHeadBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/NoBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/NoBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/NoBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/NoBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/RoundedBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/RoundedBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/RoundedBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/RoundedBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SimpleBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SimpleBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SimpleBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SimpleBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SimpleHeavyBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SimpleHeavyBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SimpleHeavyBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SimpleHeavyBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SquareBorder.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SquareBorder.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SquareBorder.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Rendering/Borders/Table/SquareBorder.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row.verified.txt b/src/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row.verified.txt rename to src/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_Renderable.verified.txt b/src/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_Renderable.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_Renderable.verified.txt rename to src/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_Renderable.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_String.verified.txt b/src/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_String.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_String.verified.txt rename to src/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_String.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Bottom.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Bottom.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Bottom.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Bottom.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Middle.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Middle.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Middle.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Middle.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Top.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Top.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Top.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Align/Center_Top.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Bottom.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Bottom.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Bottom.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Bottom.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Middle.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Middle.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Middle.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Middle.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Top.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Top.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Top.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Align/Left_Top.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Bottom.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Bottom.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Bottom.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Bottom.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Middle.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Middle.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Middle.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Middle.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Top.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Top.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Top.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Align/Right_Top.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BarChart/Fixed_Max_Value.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BarChart/Fixed_Max_Value.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BarChart/Fixed_Max_Value.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BarChart/Fixed_Max_Value.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BarChart/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BarChart/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BarChart/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BarChart/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BarChart/Zero_Value.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BarChart/Zero_Value.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BarChart/Zero_Value.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BarChart/Zero_Value.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Ansi.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Ansi.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Ansi.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Ansi.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Culture.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Culture.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Culture.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Culture.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Default.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Default.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Default.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Default.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/FullSize.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/FullSize.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/FullSize.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/FullSize.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/HideTagValues.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/HideTagValues.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/HideTagValues.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/HideTagValues.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/HideTags.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/HideTags.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/HideTags.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/HideTags.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/TagFormat.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/TagFormat.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/TagFormat.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/TagFormat.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/ValueColor.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/ValueColor.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/ValueColor.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/ValueColor.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Width.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Width.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Width.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/BreakdownChart/Width.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Calendar/Centered.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Calendar/Centered.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Calendar/Centered.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Calendar/Centered.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Calendar/Culture.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Calendar/Culture.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Calendar/Culture.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Calendar/Culture.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Calendar/LeftAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Calendar/LeftAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Calendar/LeftAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Calendar/LeftAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Calendar/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Calendar/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Calendar/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Calendar/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Calendar/RightAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Calendar/RightAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Calendar/RightAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Calendar/RightAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_MaxWidth.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_MaxWidth.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_MaxWidth.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_MaxWidth.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_NarrowTerminal.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_NarrowTerminal.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_NarrowTerminal.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_NarrowTerminal.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_Nested.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_Nested.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_Nested.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Canvas/Render_Nested.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Columns/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Columns/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Columns/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Columns/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Load_Stream.Output_fontfile=poison.flf.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Load_Stream.Output_fontfile=poison.flf.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Load_Stream.Output_fontfile=poison.flf.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Load_Stream.Output_fontfile=poison.flf.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Load_Stream.Output_fontfile=starwars.flf.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Load_Stream.Output_fontfile=starwars.flf.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Load_Stream.Output_fontfile=starwars.flf.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Load_Stream.Output_fontfile=starwars.flf.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_Centered.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_Centered.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_Centered.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_Centered.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_LeftAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_LeftAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_LeftAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_LeftAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_RightAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_RightAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_RightAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_RightAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_Wrapped.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_Wrapped.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_Wrapped.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Figlet/Render_Wrapped.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/AddEmptyRow/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Grid/AddEmptyRow/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/AddEmptyRow/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Grid/AddEmptyRow/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_2.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_2.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_2.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_2.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Alignment.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Alignment.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Alignment.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Alignment.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_ExplicitPadding.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_ExplicitPadding.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_ExplicitPadding.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_ExplicitPadding.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Padding.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Padding.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Padding.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Padding.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Json/Render_Json.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Json/Render_Json.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Json/Render_Json.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Json/Render_Json.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Empty_Layout.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Empty_Layout.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Empty_Layout.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Empty_Layout.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Fallback_Layout.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Fallback_Layout.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Fallback_Layout.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Fallback_Layout.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Columns.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Columns.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Columns.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Columns.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Columns.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Columns.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Columns.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Columns.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Rows.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Rows.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Rows.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Rows.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Rows_And_Columns.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Rows_And_Columns.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Rows_And_Columns.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Rows_And_Columns.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_17.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_17.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_17.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_17.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_20.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_20.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_20.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_20.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_23.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_23.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_23.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_23.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_28.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_28.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_28.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_28.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_30.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_30.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_30.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_30.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_31.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_31.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_31.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Nested_Three_Rows_In_One_Column.Output_31.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Minimum_Size.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Minimum_Size.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Minimum_Size.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Minimum_Size.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Ratio.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Ratio.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Ratio.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Ratio.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Size.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Size.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Size.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Respect_To_Size.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Rows.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Rows.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Rows.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_With_Rows.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_Without_Invisible_Children.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_Without_Invisible_Children.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_Without_Invisible_Children.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Layout/Render_Layout_Without_Invisible_Children.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Padder/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Padder/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Padder/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Padder/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Padder/Render_Expanded.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Padder/Render_Expanded.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Padder/Render_Expanded.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Padder/Render_Expanded.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Padder/Render_Nested.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Padder/Render_Nested.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Padder/Render_Nested.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Padder/Render_Nested.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_CJK.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_CJK.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_CJK.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_CJK.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_Centered.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_Centered.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_Centered.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_Centered.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_Panel.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_Panel.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_Panel.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_Panel.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_RightAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_RightAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_RightAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Child_RightAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Expand.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Expand.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Expand.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Expand.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_Centered.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_Centered.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_Centered.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_Centered.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_Collapse.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_Collapse.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_Collapse.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_Collapse.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_LeftAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_LeftAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_LeftAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_LeftAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_RightAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_RightAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_RightAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Header_RightAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Height.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Height.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Height.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Height.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_LineEndings.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_LineEndings.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_LineEndings.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_LineEndings.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Multiline.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Multiline.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Multiline.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Multiline.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Padding.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Padding.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Padding.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Padding.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Unicode.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Unicode.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Unicode.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Unicode.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width_Height.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width_Height.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width_Height.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width_Height.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width_MaxWidth.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width_MaxWidth.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width_MaxWidth.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Width_MaxWidth.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Wrap.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Wrap.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Wrap.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Wrap.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_ZeroPadding.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_ZeroPadding.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_ZeroPadding.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_ZeroPadding.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/ProgressBar/Formatted.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/ProgressBar/Formatted.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/ProgressBar/Formatted.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/ProgressBar/Formatted.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/ProgressBar/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/ProgressBar/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/ProgressBar/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/ProgressBar/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Recorder/Html.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Recorder/Html.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Recorder/Html.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Recorder/Html.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Recorder/Text.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Recorder/Text.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Recorder/Text.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Recorder/Text.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rows/GH-1188-Rows.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rows/GH-1188-Rows.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rows/GH-1188-Rows.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rows/GH-1188-Rows.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rows/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rows/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rows/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rows/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Empty.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Empty.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Empty.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Empty.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Expanded_And_Nested.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Expanded_And_Nested.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Expanded_And_Nested.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Expanded_And_Nested.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Nested.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Nested.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Nested.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rows/Render_Nested.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Border_Header.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Border_Header.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Border_Header.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Border_Header.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Border_NoHeader.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Border_NoHeader.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Border_NoHeader.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Border_NoHeader.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_DefaultAlignment.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_DefaultAlignment.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_DefaultAlignment.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_DefaultAlignment.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_LeftAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_LeftAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_LeftAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_LeftAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_RightAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_RightAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_RightAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Header_RightAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Linebreaks.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Linebreaks.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Linebreaks.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Linebreaks.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Truncate.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Truncate.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Truncate.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Rule/Render_Truncate.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/AddEmptyRow.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/AddEmptyRow.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/AddEmptyRow.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/AddEmptyRow.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_CellPadding.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_CellPadding.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_CellPadding.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_CellPadding.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Centered.Align_Widget.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Centered.Align_Widget.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Centered.Align_Widget.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Centered.Align_Widget.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Centered.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Centered.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Centered.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Centered.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_ColumnJustification.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_ColumnJustification.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_ColumnJustification.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_ColumnJustification.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_EA_Character.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_EA_Character.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_EA_Character.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_EA_Character.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Empty_Column.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Empty_Column.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Empty_Column.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Empty_Column.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Expand.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Expand.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Expand.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Expand.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Fold.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Fold.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Fold.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Fold.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Footers.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Footers.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Footers.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Footers.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Impossible.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Impossible.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Impossible.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Impossible.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_LeftAligned.Align_Widget.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_LeftAligned.Align_Widget.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_LeftAligned.Align_Widget.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_LeftAligned.Align_Widget.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_LeftAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_LeftAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_LeftAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_LeftAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Multiline.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Multiline.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Multiline.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Multiline.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Nested.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Nested.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Nested.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Nested.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_NoRows.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_NoRows.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_NoRows.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_NoRows.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_RightAligned.Align_Widget.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_RightAligned.Align_Widget.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_RightAligned.Align_Widget.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_RightAligned.Align_Widget.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_RightAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_RightAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_RightAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_RightAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators_No_Header.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators_No_Header.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators_No_Header.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators_No_Header.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_Centered.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_Centered.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_Centered.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_Centered.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_LeftAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_LeftAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_LeftAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_LeftAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_LowerCase.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_LowerCase.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_LowerCase.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_LowerCase.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_RightAligned.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_RightAligned.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_RightAligned.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Title_Caption_RightAligned.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Add.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Add.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Add.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Add.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Add.Renderables.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Add.Renderables.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Add.Renderables.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Add.Renderables.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Add.Strings.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Add.Strings.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Add.Strings.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Add.Strings.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Insert.Renderables.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Insert.Renderables.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Insert.Renderables.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Insert.Renderables.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Insert.Strings.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Insert.Strings.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Insert.Strings.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Insert.Strings.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Remove.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Remove.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Remove.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Extensions/Remove.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Insert.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Insert.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Insert.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Insert.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Remove.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Remove.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Remove.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Table/Rows/Remove.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/TextPath/GH-1307.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/TextPath/GH-1307.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/TextPath/GH-1307.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/TextPath/GH-1307.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Tree/Render.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Tree/Render.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Tree/Render.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Tree/Render.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Tree/Render_NoChildren.Output.verified.txt b/src/Spectre.Console.Tests/Expectations/Widgets/Tree/Render_NoChildren.Output.verified.txt similarity index 100% rename from src/Tests/Spectre.Console.Tests/Expectations/Widgets/Tree/Render_NoChildren.Output.verified.txt rename to src/Spectre.Console.Tests/Expectations/Widgets/Tree/Render_NoChildren.Output.verified.txt diff --git a/src/Tests/Spectre.Console.Tests/Extensions/ConsoleKeyExtensions.cs b/src/Spectre.Console.Tests/Extensions/ConsoleKeyExtensions.cs similarity index 100% rename from src/Tests/Spectre.Console.Tests/Extensions/ConsoleKeyExtensions.cs rename to src/Spectre.Console.Tests/Extensions/ConsoleKeyExtensions.cs diff --git a/src/Tests/Spectre.Console.Tests/Extensions/StreamExtensions.cs b/src/Spectre.Console.Tests/Extensions/StreamExtensions.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Extensions/StreamExtensions.cs rename to src/Spectre.Console.Tests/Extensions/StreamExtensions.cs index 805b50350..0eed3b87a 100644 --- a/src/Tests/Spectre.Console.Tests/Extensions/StreamExtensions.cs +++ b/src/Spectre.Console.Tests/Extensions/StreamExtensions.cs @@ -14,4 +14,4 @@ public static string ReadText(this Stream stream) return reader.ReadToEnd(); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Properties/Usings.cs b/src/Spectre.Console.Tests/Properties/Usings.cs similarity index 100% rename from src/Tests/Spectre.Console.Tests/Properties/Usings.cs rename to src/Spectre.Console.Tests/Properties/Usings.cs diff --git a/src/Tests/Spectre.Console.Tests/Spectre.Console.Tests.csproj b/src/Spectre.Console.Tests/Spectre.Console.Tests.csproj similarity index 74% rename from src/Tests/Spectre.Console.Tests/Spectre.Console.Tests.csproj rename to src/Spectre.Console.Tests/Spectre.Console.Tests.csproj index d93410e17..8b1569287 100644 --- a/src/Tests/Spectre.Console.Tests/Spectre.Console.Tests.csproj +++ b/src/Spectre.Console.Tests/Spectre.Console.Tests.csproj @@ -2,6 +2,7 @@ net9.0;net8.0 + false @@ -26,9 +27,9 @@ - - - + + + diff --git a/src/Tests/Spectre.Console.Tests/Unit/AlternateScreenTests.cs b/src/Spectre.Console.Tests/Unit/AlternateScreenTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/AlternateScreenTests.cs rename to src/Spectre.Console.Tests/Unit/AlternateScreenTests.cs index 841105ba1..d2619a07c 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/AlternateScreenTests.cs +++ b/src/Spectre.Console.Tests/Unit/AlternateScreenTests.cs @@ -67,4 +67,4 @@ public async Task Should_Write_To_Alternate_Screen() // Then await Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs rename to src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs index 9c1282c76..f18f563b2 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs +++ b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs @@ -52,4 +52,4 @@ public void Should_Return_Ansi_For_Renderable() result.ShouldBe("Hello World!"); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Colors.cs b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Colors.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Colors.cs rename to src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Colors.cs index 329d09d1f..f04fc18c8 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Colors.cs +++ b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Colors.cs @@ -239,4 +239,4 @@ public void Should_Estimate_TrueColor_To_Nearest_Three_Bit_Color( console.Output.ShouldBe(expected); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Cursor.cs b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Cursor.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Cursor.cs rename to src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Cursor.cs index 6fe8e4168..8d63c28e1 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Cursor.cs +++ b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Cursor.cs @@ -44,4 +44,4 @@ public void Should_Return_Correct_Ansi_Code() } } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Markup.cs b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Markup.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Markup.cs rename to src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Markup.cs index 01bbfa6ce..4d40666f4 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Markup.cs +++ b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Markup.cs @@ -175,4 +175,4 @@ public void Should_Not_Fail_As_In_GH1024(string markup, string expected) console.Output.ShouldBe(expected); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.MarkupInterpolated.cs b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.MarkupInterpolated.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.MarkupInterpolated.cs rename to src/Spectre.Console.Tests/Unit/AnsiConsoleTests.MarkupInterpolated.cs index 07b4f9856..df6854b21 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.MarkupInterpolated.cs +++ b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.MarkupInterpolated.cs @@ -37,4 +37,4 @@ public void Should_Not_Throw_Error_On_Links_Brackets() console.Output.ShouldMatch($"\\]8;id=[0-9]+;{pathAsRegEx}\\\\{pathAsRegEx}\\]8;;\\\\"); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs rename to src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs index dc512b436..20a7e567d 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs +++ b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Prompt.cs @@ -81,4 +81,4 @@ public async Task Should_Return_Correct_DateTime_When_Asked_US_Culture(bool asyn dateTime.ShouldBe(new DateTime(1998, 2, 1)); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Style.cs b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Style.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Style.cs rename to src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Style.cs index 93504a1a0..127a721f0 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.Style.cs +++ b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Style.cs @@ -40,4 +40,4 @@ public void Should_Write_Text_With_Multiple_Decorations_Correctly(Decoration dec // Then console.Output.ShouldBe(expected); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs rename to src/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs index 95ff65767..a05b59bc2 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs +++ b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs @@ -159,4 +159,4 @@ public void Should_Not_Throw_If_Exception_Has_No_StackTrace() Should.NotThrow(When); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/ColorSystemTests.cs b/src/Spectre.Console.Tests/Unit/ColorSystemTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/ColorSystemTests.cs rename to src/Spectre.Console.Tests/Unit/ColorSystemTests.cs index 200a2de09..13c362033 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/ColorSystemTests.cs +++ b/src/Spectre.Console.Tests/Unit/ColorSystemTests.cs @@ -16,4 +16,4 @@ public void Should_Be_Analog_To_ColorSystemSupport(ColorSystem colors, ColorSyst // Then result.ShouldBe((int)support); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/ColorTests.cs b/src/Spectre.Console.Tests/Unit/ColorTests.cs similarity index 97% rename from src/Tests/Spectre.Console.Tests/Unit/ColorTests.cs rename to src/Spectre.Console.Tests/Unit/ColorTests.cs index cae3cb54a..978b21d18 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/ColorTests.cs +++ b/src/Spectre.Console.Tests/Unit/ColorTests.cs @@ -1,5 +1,3 @@ -using System.Drawing; - namespace Spectre.Console.Tests.Unit; public sealed class ColorTests @@ -43,10 +41,10 @@ public void Should_Consider_Color_And_Color_Try_From_Hex_Equal(string color) [InlineData("#")] [InlineData("#80")] [InlineData("FOO")] - public void Should_Not_Parse_Non_Color_From_Hex(string noncolor) + public void Should_Not_Parse_Non_Color_From_Hex(string? input) { // Given, When - var result = Record.Exception(() => Color.FromHex(noncolor)); + var result = Record.Exception(() => Color.FromHex(input!)); // Then result.ShouldBeAssignableTo(); @@ -58,10 +56,10 @@ public void Should_Not_Parse_Non_Color_From_Hex(string noncolor) [InlineData("#")] [InlineData("#80")] [InlineData("FOO")] - public void Should_Not_Parse_Non_Color_Try_From_Hex(string noncolor) + public void Should_Not_Parse_Non_Color_Try_From_Hex(string? input) { // Given, When - var result = Color.TryFromHex(noncolor, out var color); + var result = Color.TryFromHex(input!, out var color); // Then result.ShouldBeFalse(); @@ -358,4 +356,4 @@ public void Should_Return_Hex_String_For_Unknown_Colors() name.ShouldBe("#800080 (RGB=128,0,128)"); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/EmojiTests.cs b/src/Spectre.Console.Tests/Unit/EmojiTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/EmojiTests.cs rename to src/Spectre.Console.Tests/Unit/EmojiTests.cs index 6aa67a12d..520608492 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/EmojiTests.cs +++ b/src/Spectre.Console.Tests/Unit/EmojiTests.cs @@ -88,4 +88,4 @@ public void Unknown_emojis_should_remain_unchanged() console.Output.ShouldBe("Hello :globe_showing_flat_earth:!"); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/ExceptionTests.cs b/src/Spectre.Console.Tests/Unit/ExceptionTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/ExceptionTests.cs rename to src/Spectre.Console.Tests/Unit/ExceptionTests.cs index 2bc90de56..86c8c654a 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/ExceptionTests.cs +++ b/src/Spectre.Console.Tests/Unit/ExceptionTests.cs @@ -153,4 +153,4 @@ public static Exception GetException(Action action) throw new InvalidOperationException("Exception harness failed"); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/HighlightTests.cs b/src/Spectre.Console.Tests/Unit/HighlightTests.cs similarity index 100% rename from src/Tests/Spectre.Console.Tests/Unit/HighlightTests.cs rename to src/Spectre.Console.Tests/Unit/HighlightTests.cs diff --git a/src/Tests/Spectre.Console.Tests/Unit/Internal/FileSizeTests.cs b/src/Spectre.Console.Tests/Unit/Internal/FileSizeTests.cs similarity index 100% rename from src/Tests/Spectre.Console.Tests/Unit/Internal/FileSizeTests.cs rename to src/Spectre.Console.Tests/Unit/Internal/FileSizeTests.cs diff --git a/src/Tests/Spectre.Console.Tests/Unit/Live/Progress/DownloadedColumnTests.cs b/src/Spectre.Console.Tests/Unit/Live/Progress/DownloadedColumnTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Live/Progress/DownloadedColumnTests.cs rename to src/Spectre.Console.Tests/Unit/Live/Progress/DownloadedColumnTests.cs index 452eaad3a..487e131b7 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Live/Progress/DownloadedColumnTests.cs +++ b/src/Spectre.Console.Tests/Unit/Live/Progress/DownloadedColumnTests.cs @@ -78,4 +78,4 @@ public void Decimal_Unit_In_Bits_Should_Return_Expected(double value, double tot // Then result.ShouldBe(expected); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Live/Progress/ProgressColumnFixture.cs b/src/Spectre.Console.Tests/Unit/Live/Progress/ProgressColumnFixture.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Live/Progress/ProgressColumnFixture.cs rename to src/Spectre.Console.Tests/Unit/Live/Progress/ProgressColumnFixture.cs index 9a2fac258..225f67e6f 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Live/Progress/ProgressColumnFixture.cs +++ b/src/Spectre.Console.Tests/Unit/Live/Progress/ProgressColumnFixture.cs @@ -20,4 +20,4 @@ public string Render() console.Write(Column.Render(context, Task, TimeSpan.Zero)); return console.Output; } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Live/Progress/ProgressTests.cs b/src/Spectre.Console.Tests/Unit/Live/Progress/ProgressTests.cs similarity index 98% rename from src/Tests/Spectre.Console.Tests/Unit/Live/Progress/ProgressTests.cs rename to src/Spectre.Console.Tests/Unit/Live/Progress/ProgressTests.cs index e8be9eca3..1a96f187c 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Live/Progress/ProgressTests.cs +++ b/src/Spectre.Console.Tests/Unit/Live/Progress/ProgressTests.cs @@ -114,6 +114,7 @@ public void Setting_Max_Value_Should_Set_The_MaxValue_And_Cap_Value() }); // Then + task.ShouldNotBeNull(); task.MaxValue.ShouldBe(20); task.Value.ShouldBe(20); } @@ -139,6 +140,7 @@ public void Setting_Max_Value_To_Zero_Should_Make_Percentage_OneHundred() }); // Then + task.ShouldNotBeNull(); task.Value.ShouldBe(0); task.Percentage.ShouldBe(100); } @@ -165,6 +167,7 @@ public void Setting_Value_Should_Override_Incremented_Value() }); // Then + task.ShouldNotBeNull(); task.MaxValue.ShouldBe(100); task.Value.ShouldBe(20); } @@ -190,6 +193,7 @@ public void Setting_Value_To_MaxValue_Should_Finish_Task() }); // Then + task.ShouldNotBeNull(); task.IsFinished.ShouldBe(true); } @@ -215,6 +219,7 @@ public void Should_Increment_Manually_Set_Value() }); // Then + task.ShouldNotBeNull(); task.Value.ShouldBe(60); } @@ -286,6 +291,7 @@ public void Should_Report_Max_Remaining_Time_For_Extremely_Small_Progress() }); // Then + task.ShouldNotBeNull(); task.RemainingTime.ShouldBe(TimeSpan.MaxValue); } @@ -366,4 +372,4 @@ public void Should_Render_Tasks_At_Specified_Indexes_Correctly() "[?25h", }); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Live/StatusTests.cs b/src/Spectre.Console.Tests/Unit/Live/StatusTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Live/StatusTests.cs rename to src/Spectre.Console.Tests/Unit/Live/StatusTests.cs index a9510ad89..5bec6cfcd 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Live/StatusTests.cs +++ b/src/Spectre.Console.Tests/Unit/Live/StatusTests.cs @@ -48,4 +48,4 @@ public Task Should_Render_Status_Correctly() // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Prompts/ListPromptStateTests.cs b/src/Spectre.Console.Tests/Unit/Prompts/ListPromptStateTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Prompts/ListPromptStateTests.cs rename to src/Spectre.Console.Tests/Unit/Prompts/ListPromptStateTests.cs index ff03df29b..90bc0f824 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Prompts/ListPromptStateTests.cs +++ b/src/Spectre.Console.Tests/Unit/Prompts/ListPromptStateTests.cs @@ -174,4 +174,4 @@ public void Should_Jump_Back_To_First_Item_When_Clearing_Search_Term() // Then state.Index.ShouldBe(0); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs b/src/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs similarity index 89% rename from src/Tests/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs rename to src/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs index 43b1d5c36..26f65ae25 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs +++ b/src/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs @@ -128,7 +128,8 @@ public void Should_Throw_When_Getting_Parents_Of_Non_Existing_Node() action.ShouldThrow(); } - [Fact] public void Should_Throw_Meaningful_Exception_For_Empty_Prompt() + [Fact] + public void Should_Throw_Meaningful_Exception_For_Empty_Prompt() { // Given var console = new TestConsole(); @@ -142,7 +143,8 @@ [Fact] public void Should_Throw_Meaningful_Exception_For_Empty_Prompt() // Then var exception = action.ShouldThrow(); - exception.Message.ShouldBe("Cannot show an empty selection prompt. Please call the AddChoice() method to configure the prompt."); + exception.Message.ShouldBe( + "Cannot show an empty selection prompt. Please call the AddChoice() method to configure the prompt."); } } @@ -153,8 +155,18 @@ file sealed class CustomItem public class Comparer : IEqualityComparer { - public bool Equals(CustomItem x, CustomItem y) + public bool Equals(CustomItem? x, CustomItem? y) { + if (x == null && y == null) + { + return true; + } + + if (x == null || y == null) + { + return false; + } + return x.X == y.X && x.Y == y.Y; } @@ -163,4 +175,4 @@ public int GetHashCode(CustomItem obj) throw new NotSupportedException(); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Prompts/SelectionPromptTests.cs b/src/Spectre.Console.Tests/Unit/Prompts/SelectionPromptTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Prompts/SelectionPromptTests.cs rename to src/Spectre.Console.Tests/Unit/Prompts/SelectionPromptTests.cs index a91aea598..86d2b9719 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Prompts/SelectionPromptTests.cs +++ b/src/Spectre.Console.Tests/Unit/Prompts/SelectionPromptTests.cs @@ -167,4 +167,4 @@ public CustomSelectionItem(int value, string name) Value = value; Name = name ?? throw new ArgumentNullException(nameof(name)); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Prompts/TextPromptTests.cs b/src/Spectre.Console.Tests/Unit/Prompts/TextPromptTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Prompts/TextPromptTests.cs rename to src/Spectre.Console.Tests/Unit/Prompts/TextPromptTests.cs index c358b9be3..c0698697a 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Prompts/TextPromptTests.cs +++ b/src/Spectre.Console.Tests/Unit/Prompts/TextPromptTests.cs @@ -410,4 +410,4 @@ public Task Uses_the_specified_choices_style() // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/RecorderTests.cs b/src/Spectre.Console.Tests/Unit/RecorderTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/RecorderTests.cs rename to src/Spectre.Console.Tests/Unit/RecorderTests.cs index a340b82c3..78ea2667e 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/RecorderTests.cs +++ b/src/Spectre.Console.Tests/Unit/RecorderTests.cs @@ -43,4 +43,4 @@ public Task Should_Export_Html_Text_As_Expected() // Then return Verifier.Verify(result); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Rendering/Borders/BoxBorderTests.cs b/src/Spectre.Console.Tests/Unit/Rendering/Borders/BoxBorderTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Rendering/Borders/BoxBorderTests.cs rename to src/Spectre.Console.Tests/Unit/Rendering/Borders/BoxBorderTests.cs index e66890a97..119a91d5f 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Rendering/Borders/BoxBorderTests.cs +++ b/src/Spectre.Console.Tests/Unit/Rendering/Borders/BoxBorderTests.cs @@ -207,4 +207,4 @@ public static Panel GetPanel() .Header("Greeting"); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Rendering/Borders/TableBorderTests.cs b/src/Spectre.Console.Tests/Unit/Rendering/Borders/TableBorderTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Rendering/Borders/TableBorderTests.cs rename to src/Spectre.Console.Tests/Unit/Rendering/Borders/TableBorderTests.cs index beb1b089f..d1fe954ce 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Rendering/Borders/TableBorderTests.cs +++ b/src/Spectre.Console.Tests/Unit/Rendering/Borders/TableBorderTests.cs @@ -798,4 +798,4 @@ public static Table GetTable(Justify? header1 = null, Justify? header2 = null) return table; } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Rendering/RenderHookTests.cs b/src/Spectre.Console.Tests/Unit/Rendering/RenderHookTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Rendering/RenderHookTests.cs rename to src/Spectre.Console.Tests/Unit/Rendering/RenderHookTests.cs index 6be28da46..9c0cfab62 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Rendering/RenderHookTests.cs +++ b/src/Spectre.Console.Tests/Unit/Rendering/RenderHookTests.cs @@ -24,4 +24,4 @@ public void Should_Inject_Renderable_Before_Writing_To_Console() console.Lines[0].ShouldBe("Hello"); console.Lines[1].ShouldBe("World"); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Rendering/SegmentTests.cs b/src/Spectre.Console.Tests/Unit/Rendering/SegmentTests.cs similarity index 98% rename from src/Tests/Spectre.Console.Tests/Unit/Rendering/SegmentTests.cs rename to src/Spectre.Console.Tests/Unit/Rendering/SegmentTests.cs index 94c36de24..645fb7fda 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Rendering/SegmentTests.cs +++ b/src/Spectre.Console.Tests/Unit/Rendering/SegmentTests.cs @@ -26,7 +26,7 @@ public sealed class TheSplitMethod [InlineData("Foo 测试 Bar", 10, "Foo 测试 B", "ar")] [InlineData("Foo 测试 Bar", 11, "Foo 测试 Ba", "r")] [InlineData("Foo 测试 Bar", 12, "Foo 测试 Bar", null)] - public void Should_Split_Segment_Correctly(string text, int offset, string expectedFirst, string expectedSecond) + public void Should_Split_Segment_Correctly(string text, int offset, string expectedFirst, string? expectedSecond) { // Given var style = new Style(Color.Red, Color.Green, Decoration.Bold); @@ -138,4 +138,4 @@ public void Should_Split_Segments_With_Linebreak_In_Text() lines[3][0].Text.ShouldBe("Corgi"); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/StyleTests.cs b/src/Spectre.Console.Tests/Unit/StyleTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/StyleTests.cs rename to src/Spectre.Console.Tests/Unit/StyleTests.cs index 4d6d999a5..ea31dfeea 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/StyleTests.cs +++ b/src/Spectre.Console.Tests/Unit/StyleTests.cs @@ -410,7 +410,7 @@ public void Should_Return_Expected_Markup_For_Style_With_Only_Background_Color() public void Should_Return_Expected_Markup_For_Style_With_Only_Link() { // Given - var style = new Style(link:"https://spectreconsole.net/"); + var style = new Style(link: "https://spectreconsole.net/"); // When var result = style.ToMarkup(); @@ -432,4 +432,4 @@ public void Should_Return_Expected_Markup_For_Style_With_Background_And_Link() result.ShouldBe("default on blue link=https://spectreconsole.net/"); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/AlignTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/AlignTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/AlignTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/AlignTests.cs index e40dce470..2b0163f08 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/AlignTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/AlignTests.cs @@ -148,4 +148,4 @@ public Task Should_Render_Panel_Right_Aligned_At_Bottom() return Verifier.Verify(console.Output); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/BarChartTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/BarChartTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/BarChartTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/BarChartTests.cs index 26619e905..adc2de35b 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/BarChartTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/BarChartTests.cs @@ -60,4 +60,4 @@ public async Task Should_Render_Correctly_3() // Then await Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/BreakdownChartTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/BreakdownChartTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/BreakdownChartTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/BreakdownChartTests.cs index 81ca27c1f..0f9a5e0dd 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/BreakdownChartTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/BreakdownChartTests.cs @@ -154,4 +154,4 @@ public static BreakdownChart GetChart() .AddItem("Shell", 0.1, Color.Aqua); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/CalendarTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/CalendarTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/CalendarTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/CalendarTests.cs index 14d5a2c32..b07390c2d 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/CalendarTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/CalendarTests.cs @@ -96,4 +96,4 @@ public Task Should_Render_Calendar_Correctly_For_Specific_Culture() // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/CanvasTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/CanvasTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/CanvasTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/CanvasTests.cs index a223627ae..cd6891e25 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/CanvasTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/CanvasTests.cs @@ -130,4 +130,4 @@ public void Should_Not_Render_Canvas_If_Canvas_Cannot_Be_Scaled_Down() // Then console.Output.ShouldBeEmpty(); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/ColumnsTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/ColumnsTests.cs similarity index 90% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/ColumnsTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/ColumnsTests.cs index b595fa26d..ae720d23f 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/ColumnsTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/ColumnsTests.cs @@ -5,8 +5,8 @@ public sealed class ColumnsTests { private sealed class User { - public string Name { get; set; } - public string Country { get; set; } + public required string Name { get; init; } + public required string Country { get; init; } } [Fact] @@ -36,4 +36,4 @@ public Task Should_Render_Columns_Correctly() // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/FigletTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/FigletTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/FigletTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/FigletTests.cs index 5fc668409..666170ee8 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/FigletTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/FigletTests.cs @@ -99,4 +99,4 @@ public async Task Should_Render_Right_Aligned_Text_Correctly() // Then await Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/GridTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/GridTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/GridTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/GridTests.cs index 3a25db3f7..ba0877eb4 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/GridTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/GridTests.cs @@ -31,7 +31,7 @@ public void Should_Throw_If_Rows_Are_Null() var grid = new Grid(); // When - var result = Record.Exception(() => grid.AddRow(null)); + var result = Record.Exception(() => grid.AddRow(null!)); // Then result.ShouldBeOfType() @@ -292,4 +292,4 @@ public Task Should_Respect_Cell_Content_Overflow_With_NoWrap_Column() // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/JsonTextTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/JsonTextTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/JsonTextTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/JsonTextTests.cs index a54531943..a9a2d4494 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/JsonTextTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/JsonTextTests.cs @@ -19,4 +19,4 @@ public Task Should_Render_Json() // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/LayoutTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/LayoutTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/LayoutTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/LayoutTests.cs index 54182e12c..3fd5205cf 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/LayoutTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/LayoutTests.cs @@ -293,4 +293,4 @@ public Task Should_Fall_Back_To_Parent_Layout_If_All_Children_Are_Invisible() // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/MarkupTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/MarkupTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/MarkupTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/MarkupTests.cs index aad415c0d..0c4c8c3e0 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/MarkupTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/MarkupTests.cs @@ -174,4 +174,4 @@ public void Can_Use_Interpolated_Markup_As_IRenderable() └─────────────────┘ ".NormalizeLineEndings()); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/PadderTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/PadderTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/PadderTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/PadderTests.cs index dddd06238..fb30472e6 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/PadderTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/PadderTests.cs @@ -64,4 +64,4 @@ public Task Should_Render_Padded_Object_Correctly_When_Nested_Within_Other_Objec // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs index e698aecb2..a643745e1 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs @@ -491,4 +491,4 @@ public Task Should_Respect_Text_Overflow_In_Nested_Panel() // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/ProgressBarTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/ProgressBarTests.cs similarity index 100% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/ProgressBarTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/ProgressBarTests.cs diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/RowsTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/RowsTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/RowsTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/RowsTests.cs index 0278bacd3..0f4cd731f 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/RowsTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/RowsTests.cs @@ -113,4 +113,4 @@ public Task Should_Render_Rows_Correctly_Inside_Other_Widget_When_Expanded() // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/RuleTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/RuleTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/RuleTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/RuleTests.cs index 9db45d39c..81d71bd8d 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/RuleTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/RuleTests.cs @@ -146,4 +146,4 @@ public void Should_Truncate_Too_Long_Title(int width, string input, string expec console.Lines.Count.ShouldBe(1); console.Lines[0].ShouldBe(expected); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionExtensionsTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionExtensionsTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionExtensionsTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionExtensionsTests.cs index 69d31b89c..912599328 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionExtensionsTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionExtensionsTests.cs @@ -112,4 +112,4 @@ public Task Should_Remove_Row() return Verifier.Verify(console.Output); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionTests.cs index cb97b6ba0..6e1dc77ab 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionTests.cs @@ -12,7 +12,7 @@ public void Should_Throw_If_Columns_Are_Null() var table = new Table(); // When - var result = Record.Exception(() => table.Rows.Add(null)); + var result = Record.Exception(() => table.Rows.Add(null!)); // Then result.ShouldBeOfType() @@ -77,7 +77,7 @@ public void Should_Throw_If_Columns_Are_Null() var table = new Table(); // When - var result = Record.Exception(() => table.Rows.Insert(0, null)); + var result = Record.Exception(() => table.Rows.Insert(0, null!)); // Then result.ShouldBeOfType() @@ -346,4 +346,4 @@ public void Should_Throw_If_Index_Column_Is_Negative() .Message.ShouldBe("Table column index cannot be negative."); } } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs index 4c26b7aa0..f2e5caeb4 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs @@ -12,7 +12,7 @@ public void Should_Throw_If_Column_Is_Null() var table = new Table(); // When - var result = Record.Exception(() => table.AddColumn((string)null)); + var result = Record.Exception(() => table.AddColumn((string)null!)); // Then result.ShouldBeOfType() @@ -45,7 +45,7 @@ public void Should_Throw_If_Columns_Are_Null() var table = new Table(); // When - var result = Record.Exception(() => table.AddColumns((string[])null)); + var result = Record.Exception(() => table.AddColumns((string[])null!)); // Then result.ShouldBeOfType() @@ -62,7 +62,7 @@ public void Should_Throw_If_String_Rows_Are_Null() var table = new Table(); // When - var result = Record.Exception(() => table.AddRow((string[])null)); + var result = Record.Exception(() => table.AddRow((string[])null!)); // Then result.ShouldBeOfType() @@ -757,4 +757,4 @@ public Task Should_Respect_Cell_Content_Overflow_With_NoWrap_Column() // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/TextPathTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/TextPathTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/TextPathTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/TextPathTests.cs index b3eb0572a..c7f60638f 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/TextPathTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/TextPathTests.cs @@ -93,4 +93,4 @@ public Task Should_Behave_As_Expected_When_Rendering_Inside_Panel_Columns() // Then return Verifier.Verify(console.Output); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/TextTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/TextTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/TextTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/TextTests.cs index 6b0bdfdb5..2f0f9da9d 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/TextTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/TextTests.cs @@ -153,4 +153,4 @@ public void Should_Overflow_Text_Correctly(Overflow overflow, string expected) .NormalizeLineEndings() .ShouldBe(expected); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/TreeTests.cs b/src/Spectre.Console.Tests/Unit/Widgets/TreeTests.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Unit/Widgets/TreeTests.cs rename to src/Spectre.Console.Tests/Unit/Widgets/TreeTests.cs index 73912a037..9a4f96251 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/TreeTests.cs +++ b/src/Spectre.Console.Tests/Unit/Widgets/TreeTests.cs @@ -125,4 +125,4 @@ public void Should_Render_Tree_With_No_Child_If_Route_Collapsed_Correctly() string.Empty, }); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Utilities/EmbeddedResourceReader.cs b/src/Spectre.Console.Tests/Utilities/EmbeddedResourceReader.cs similarity index 61% rename from src/Tests/Spectre.Console.Tests/Utilities/EmbeddedResourceReader.cs rename to src/Spectre.Console.Tests/Utilities/EmbeddedResourceReader.cs index 5246b5eaa..8d74d9e63 100644 --- a/src/Tests/Spectre.Console.Tests/Utilities/EmbeddedResourceReader.cs +++ b/src/Spectre.Console.Tests/Utilities/EmbeddedResourceReader.cs @@ -12,7 +12,13 @@ public static Stream LoadResourceStream(string resourceName) var assembly = Assembly.GetCallingAssembly(); resourceName = resourceName.Replace("/", "."); - return assembly.GetManifestResourceStream(resourceName); + var stream = assembly.GetManifestResourceStream(resourceName); + if (stream == null) + { + throw new InvalidOperationException($"Could not load embedded resource '{resourceName}'"); + } + + return stream; } public static Stream LoadResourceStream(Assembly assembly, string resourceName) @@ -28,6 +34,12 @@ public static Stream LoadResourceStream(Assembly assembly, string resourceName) } resourceName = resourceName.Replace("/", "."); - return assembly.GetManifestResourceStream(resourceName); + var stream = assembly.GetManifestResourceStream(resourceName); + if (stream == null) + { + throw new InvalidOperationException($"Could not load embedded resource '{resourceName}'"); + } + + return stream; } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Utilities/GitHubIssueAttribute.cs b/src/Spectre.Console.Tests/Utilities/GitHubIssueAttribute.cs similarity index 100% rename from src/Tests/Spectre.Console.Tests/Utilities/GitHubIssueAttribute.cs rename to src/Spectre.Console.Tests/Utilities/GitHubIssueAttribute.cs diff --git a/src/Tests/Spectre.Console.Cli.Tests/Utilities/ModuleInitializerAttribute.cs b/src/Spectre.Console.Tests/Utilities/ModuleInitializerAttribute.cs similarity index 100% rename from src/Tests/Spectre.Console.Cli.Tests/Utilities/ModuleInitializerAttribute.cs rename to src/Spectre.Console.Tests/Utilities/ModuleInitializerAttribute.cs diff --git a/src/Tests/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs b/src/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs similarity index 99% rename from src/Tests/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs rename to src/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs index 8617ebca2..d471a4163 100644 --- a/src/Tests/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs +++ b/src/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs @@ -38,4 +38,4 @@ public static string NormalizeStackTrace(string text) // Finally normalize any remaining path separators return _pathSeparatorRegex.Replace(text, "/"); } -} +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/VerifyConfiguration.cs b/src/Spectre.Console.Tests/VerifyConfiguration.cs similarity index 99% rename from src/Tests/Spectre.Console.Cli.Tests/VerifyConfiguration.cs rename to src/Spectre.Console.Tests/VerifyConfiguration.cs index b3261c23f..d404c856a 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/VerifyConfiguration.cs +++ b/src/Spectre.Console.Tests/VerifyConfiguration.cs @@ -7,4 +7,4 @@ public static void Init() { Verifier.DerivePathInfo(Expectations.Initialize); } -} +} \ No newline at end of file diff --git a/src/Spectre.Console.slnx b/src/Spectre.Console.slnx index 25d17f023..0b8f9dbb7 100644 --- a/src/Spectre.Console.slnx +++ b/src/Spectre.Console.slnx @@ -9,23 +9,29 @@ - - + + + + + + + + + + + + - - - - + - \ No newline at end of file diff --git a/src/Spectre.Console/AnsiConsole.Prompt.cs b/src/Spectre.Console/AnsiConsole.Prompt.cs index 11657d0a7..d51577c69 100644 --- a/src/Spectre.Console/AnsiConsole.Prompt.cs +++ b/src/Spectre.Console/AnsiConsole.Prompt.cs @@ -1,5 +1,3 @@ -using System.Threading.Tasks; - namespace Spectre.Console; /// diff --git a/src/Spectre.Console/Color.Generated.cs b/src/Spectre.Console/Color.Generated.cs index 2a8208fda..23856f79d 100644 --- a/src/Spectre.Console/Color.Generated.cs +++ b/src/Spectre.Console/Color.Generated.cs @@ -68,6 +68,11 @@ internal Color(byte number, byte red, byte green, byte blue, bool isDefault = fa /// public static Color Grey { get; } = new Color(8, 128, 128, 128); + /// + /// Gets the color "Gray" (RGB 128,128,128). + /// + public static Color Gray { get; } = new Color(8, 128, 128, 128); + /// /// Gets the color "Red" (RGB 255,0,0). /// @@ -93,11 +98,21 @@ internal Color(byte number, byte red, byte green, byte blue, bool isDefault = fa /// public static Color Fuchsia { get; } = new Color(13, 255, 0, 255); + /// + /// Gets the color "Magenta" (RGB 255,0,255). + /// + public static Color Magenta { get; } = new Color(13, 255, 0, 255); + /// /// Gets the color "Aqua" (RGB 0,255,255). /// public static Color Aqua { get; } = new Color(14, 0, 255, 255); + /// + /// Gets the color "Cyan" (RGB 0,255,255). + /// + public static Color Cyan { get; } = new Color(14, 0, 255, 255); + /// /// Gets the color "White" (RGB 255,255,255). /// @@ -108,6 +123,11 @@ internal Color(byte number, byte red, byte green, byte blue, bool isDefault = fa /// public static Color Grey0 { get; } = new Color(16, 0, 0, 0); + /// + /// Gets the color "Gray0" (RGB 0,0,0). + /// + public static Color Gray0 { get; } = new Color(16, 0, 0, 0); + /// /// Gets the color "NavyBlue" (RGB 0,0,95). /// @@ -331,6 +351,11 @@ internal Color(byte number, byte red, byte green, byte blue, bool isDefault = fa /// public static Color Grey37 { get; } = new Color(59, 95, 95, 95); + /// + /// Gets the color "Gray37" (RGB 95,95,95). + /// + public static Color Gray37 { get; } = new Color(59, 95, 95, 95); + /// /// Gets the color "MediumPurple4" (RGB 95,95,135). /// @@ -558,6 +583,11 @@ internal Color(byte number, byte red, byte green, byte blue, bool isDefault = fa /// public static Color Grey53 { get; } = new Color(102, 135, 135, 135); + /// + /// Gets the color "Gray53" (RGB 135,135,135). + /// + public static Color Gray53 { get; } = new Color(102, 135, 135, 135); + /// /// Gets the color "LightSlateGrey" (RGB 135,135,175). /// @@ -753,6 +783,11 @@ internal Color(byte number, byte red, byte green, byte blue, bool isDefault = fa /// public static Color Grey63 { get; } = new Color(139, 175, 135, 175); + /// + /// Gets the color "Gray63" (RGB 175,135,175). + /// + public static Color Gray63 { get; } = new Color(139, 175, 135, 175); + /// /// Gets the color "MediumPurple2_1" (RGB 175,135,215). /// @@ -784,6 +819,11 @@ internal Color(byte number, byte red, byte green, byte blue, bool isDefault = fa /// public static Color Grey69 { get; } = new Color(145, 175, 175, 175); + /// + /// Gets the color "Gray69" (RGB 175,175,175). + /// + public static Color Gray69 { get; } = new Color(145, 175, 175, 175); + /// /// Gets the color "LightSteelBlue3" (RGB 175,175,215). /// @@ -1013,6 +1053,11 @@ internal Color(byte number, byte red, byte green, byte blue, bool isDefault = fa /// public static Color Grey84 { get; } = new Color(188, 215, 215, 215); + /// + /// Gets the color "Gray84" (RGB 215,215,215). + /// + public static Color Gray84 { get; } = new Color(188, 215, 215, 215); + /// /// Gets the color "LightSteelBlue1" (RGB 215,215,255). /// @@ -1237,124 +1282,249 @@ internal Color(byte number, byte red, byte green, byte blue, bool isDefault = fa /// public static Color Grey100 { get; } = new Color(231, 255, 255, 255); + /// + /// Gets the color "Gray100" (RGB 255,255,255). + /// + public static Color Gray100 { get; } = new Color(231, 255, 255, 255); + /// /// Gets the color "Grey3" (RGB 8,8,8). /// public static Color Grey3 { get; } = new Color(232, 8, 8, 8); + /// + /// Gets the color "Gray3" (RGB 8,8,8). + /// + public static Color Gray3 { get; } = new Color(232, 8, 8, 8); + /// /// Gets the color "Grey7" (RGB 18,18,18). /// public static Color Grey7 { get; } = new Color(233, 18, 18, 18); + /// + /// Gets the color "Gray7" (RGB 18,18,18). + /// + public static Color Gray7 { get; } = new Color(233, 18, 18, 18); + /// /// Gets the color "Grey11" (RGB 28,28,28). /// public static Color Grey11 { get; } = new Color(234, 28, 28, 28); + /// + /// Gets the color "Gray11" (RGB 28,28,28). + /// + public static Color Gray11 { get; } = new Color(234, 28, 28, 28); + /// /// Gets the color "Grey15" (RGB 38,38,38). /// public static Color Grey15 { get; } = new Color(235, 38, 38, 38); + /// + /// Gets the color "Gray15" (RGB 38,38,38). + /// + public static Color Gray15 { get; } = new Color(235, 38, 38, 38); + /// /// Gets the color "Grey19" (RGB 48,48,48). /// public static Color Grey19 { get; } = new Color(236, 48, 48, 48); + /// + /// Gets the color "Gray19" (RGB 48,48,48). + /// + public static Color Gray19 { get; } = new Color(236, 48, 48, 48); + /// /// Gets the color "Grey23" (RGB 58,58,58). /// public static Color Grey23 { get; } = new Color(237, 58, 58, 58); + /// + /// Gets the color "Gray23" (RGB 58,58,58). + /// + public static Color Gray23 { get; } = new Color(237, 58, 58, 58); + /// /// Gets the color "Grey27" (RGB 68,68,68). /// public static Color Grey27 { get; } = new Color(238, 68, 68, 68); + /// + /// Gets the color "Gray27" (RGB 68,68,68). + /// + public static Color Gray27 { get; } = new Color(238, 68, 68, 68); + /// /// Gets the color "Grey30" (RGB 78,78,78). /// public static Color Grey30 { get; } = new Color(239, 78, 78, 78); + /// + /// Gets the color "Gray30" (RGB 78,78,78). + /// + public static Color Gray30 { get; } = new Color(239, 78, 78, 78); + /// /// Gets the color "Grey35" (RGB 88,88,88). /// public static Color Grey35 { get; } = new Color(240, 88, 88, 88); + /// + /// Gets the color "Gray35" (RGB 88,88,88). + /// + public static Color Gray35 { get; } = new Color(240, 88, 88, 88); + /// /// Gets the color "Grey39" (RGB 98,98,98). /// public static Color Grey39 { get; } = new Color(241, 98, 98, 98); + /// + /// Gets the color "Gray39" (RGB 98,98,98). + /// + public static Color Gray39 { get; } = new Color(241, 98, 98, 98); + /// /// Gets the color "Grey42" (RGB 108,108,108). /// public static Color Grey42 { get; } = new Color(242, 108, 108, 108); + /// + /// Gets the color "Gray42" (RGB 108,108,108). + /// + public static Color Gray42 { get; } = new Color(242, 108, 108, 108); + /// /// Gets the color "Grey46" (RGB 118,118,118). /// public static Color Grey46 { get; } = new Color(243, 118, 118, 118); + /// + /// Gets the color "Gray46" (RGB 118,118,118). + /// + public static Color Gray46 { get; } = new Color(243, 118, 118, 118); + /// /// Gets the color "Grey50" (RGB 128,128,128). /// public static Color Grey50 { get; } = new Color(244, 128, 128, 128); + /// + /// Gets the color "Gray50" (RGB 128,128,128). + /// + public static Color Gray50 { get; } = new Color(244, 128, 128, 128); + /// /// Gets the color "Grey54" (RGB 138,138,138). /// public static Color Grey54 { get; } = new Color(245, 138, 138, 138); + /// + /// Gets the color "Gray54" (RGB 138,138,138). + /// + public static Color Gray54 { get; } = new Color(245, 138, 138, 138); + /// /// Gets the color "Grey58" (RGB 148,148,148). /// public static Color Grey58 { get; } = new Color(246, 148, 148, 148); + /// + /// Gets the color "Gray58" (RGB 148,148,148). + /// + public static Color Gray58 { get; } = new Color(246, 148, 148, 148); + /// /// Gets the color "Grey62" (RGB 158,158,158). /// public static Color Grey62 { get; } = new Color(247, 158, 158, 158); + /// + /// Gets the color "Gray62" (RGB 158,158,158). + /// + public static Color Gray62 { get; } = new Color(247, 158, 158, 158); + /// /// Gets the color "Grey66" (RGB 168,168,168). /// public static Color Grey66 { get; } = new Color(248, 168, 168, 168); + /// + /// Gets the color "Gray66" (RGB 168,168,168). + /// + public static Color Gray66 { get; } = new Color(248, 168, 168, 168); + /// /// Gets the color "Grey70" (RGB 178,178,178). /// public static Color Grey70 { get; } = new Color(249, 178, 178, 178); + /// + /// Gets the color "Gray70" (RGB 178,178,178). + /// + public static Color Gray70 { get; } = new Color(249, 178, 178, 178); + /// /// Gets the color "Grey74" (RGB 188,188,188). /// public static Color Grey74 { get; } = new Color(250, 188, 188, 188); + /// + /// Gets the color "Gray74" (RGB 188,188,188). + /// + public static Color Gray74 { get; } = new Color(250, 188, 188, 188); + /// /// Gets the color "Grey78" (RGB 198,198,198). /// public static Color Grey78 { get; } = new Color(251, 198, 198, 198); + /// + /// Gets the color "Gray78" (RGB 198,198,198). + /// + public static Color Gray78 { get; } = new Color(251, 198, 198, 198); + /// /// Gets the color "Grey82" (RGB 208,208,208). /// public static Color Grey82 { get; } = new Color(252, 208, 208, 208); + /// + /// Gets the color "Gray82" (RGB 208,208,208). + /// + public static Color Gray82 { get; } = new Color(252, 208, 208, 208); + /// /// Gets the color "Grey85" (RGB 218,218,218). /// public static Color Grey85 { get; } = new Color(253, 218, 218, 218); + /// + /// Gets the color "Gray85" (RGB 218,218,218). + /// + public static Color Gray85 { get; } = new Color(253, 218, 218, 218); + /// /// Gets the color "Grey89" (RGB 228,228,228). /// public static Color Grey89 { get; } = new Color(254, 228, 228, 228); + /// + /// Gets the color "Gray89" (RGB 228,228,228). + /// + public static Color Gray89 { get; } = new Color(254, 228, 228, 228); + /// /// Gets the color "Grey93" (RGB 238,238,238). /// public static Color Grey93 { get; } = new Color(255, 238, 238, 238); + + /// + /// Gets the color "Gray93" (RGB 238,238,238). + /// + public static Color Gray93 { get; } = new Color(255, 238, 238, 238); } } \ No newline at end of file diff --git a/src/Spectre.Console/Extensions/AlignExtensions.cs b/src/Spectre.Console/Extensions/AlignExtensions.cs index f2c700eea..ad0413b7f 100644 --- a/src/Spectre.Console/Extensions/AlignExtensions.cs +++ b/src/Spectre.Console/Extensions/AlignExtensions.cs @@ -103,4 +103,4 @@ public static Align BottomAligned(this Align align) align.Vertical = Console.VerticalAlignment.Bottom; return align; } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Extensions/AlignableExtensions.cs b/src/Spectre.Console/Extensions/AlignableExtensions.cs index 8039f313f..4efc934ac 100644 --- a/src/Spectre.Console/Extensions/AlignableExtensions.cs +++ b/src/Spectre.Console/Extensions/AlignableExtensions.cs @@ -77,4 +77,4 @@ public static T RightAligned(this T obj) obj.Alignment = Justify.Right; return obj; } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Prompt.cs b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Prompt.cs index 450f35a98..d3e885759 100644 --- a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Prompt.cs +++ b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Prompt.cs @@ -1,5 +1,3 @@ -using System.Threading.Tasks; - namespace Spectre.Console; /// diff --git a/src/Spectre.Console/Extensions/LayoutExtensions.cs b/src/Spectre.Console/Extensions/LayoutExtensions.cs index 6acea7b17..995e6f09e 100644 --- a/src/Spectre.Console/Extensions/LayoutExtensions.cs +++ b/src/Spectre.Console/Extensions/LayoutExtensions.cs @@ -55,4 +55,4 @@ public static Layout MinimumSize(this Layout layout, int size) layout.MinimumSize = size; return layout; } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Extensions/RenderOptionsExtensions.cs b/src/Spectre.Console/Extensions/RenderOptionsExtensions.cs index 6e501dab1..a8a721eb4 100644 --- a/src/Spectre.Console/Extensions/RenderOptionsExtensions.cs +++ b/src/Spectre.Console/Extensions/RenderOptionsExtensions.cs @@ -7,4 +7,4 @@ public static BoxBorder GetSafeBorder(this RenderOptions options, T border) { return BoxExtensions.GetSafeBorder(border.Border, !options.Unicode && border.UseSafeBorder); } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Extensions/TextPathExtensions.cs b/src/Spectre.Console/Extensions/TextPathExtensions.cs index 26200bdcc..4f98267b3 100644 --- a/src/Spectre.Console/Extensions/TextPathExtensions.cs +++ b/src/Spectre.Console/Extensions/TextPathExtensions.cs @@ -116,4 +116,4 @@ public static TextPath LeafColor(this TextPath obj, Color color) { return LeafStyle(obj, new Style(foreground: color)); } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/HorizontalAlignment.cs b/src/Spectre.Console/HorizontalAlignment.cs index 97b7c1398..8f252956f 100644 --- a/src/Spectre.Console/HorizontalAlignment.cs +++ b/src/Spectre.Console/HorizontalAlignment.cs @@ -19,4 +19,4 @@ public enum HorizontalAlignment /// Right aligned. /// Right, -} +} \ No newline at end of file diff --git a/src/Spectre.Console/IAlignable.cs b/src/Spectre.Console/IAlignable.cs index 6207bfa1f..1f4f0c0a7 100644 --- a/src/Spectre.Console/IAlignable.cs +++ b/src/Spectre.Console/IAlignable.cs @@ -9,4 +9,4 @@ public interface IAlignable /// Gets or sets the alignment. /// Justify? Alignment { get; set; } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Internal/Backends/Ansi/AnsiDetector.cs b/src/Spectre.Console/Internal/Backends/Ansi/AnsiDetector.cs index 40419a7d0..e55e8ca3a 100644 --- a/src/Spectre.Console/Internal/Backends/Ansi/AnsiDetector.cs +++ b/src/Spectre.Console/Internal/Backends/Ansi/AnsiDetector.cs @@ -133,4 +133,4 @@ public static bool SupportsAnsi(bool upgrade, bool stdError, out bool isLegacy) } } } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Internal/Cell.cs b/src/Spectre.Console/Internal/Cell.cs index 78037a071..2111a28e4 100644 --- a/src/Spectre.Console/Internal/Cell.cs +++ b/src/Spectre.Console/Internal/Cell.cs @@ -13,14 +13,14 @@ internal static class Cell static Cell() { - #if !NETSTANDARD2_0 +#if !NETSTANDARD2_0 Array.Fill(_runeWidthCache, Sentinel); - #else +#else for (var i = 0; i < _runeWidthCache.Length; i++) { _runeWidthCache[i] = Sentinel; } - #endif +#endif } public static int GetCellLength(string text) diff --git a/src/Spectre.Console/Internal/IRatioResolvable.cs b/src/Spectre.Console/Internal/IRatioResolvable.cs index 83d89d09a..2dd83bb25 100644 --- a/src/Spectre.Console/Internal/IRatioResolvable.cs +++ b/src/Spectre.Console/Internal/IRatioResolvable.cs @@ -19,4 +19,4 @@ internal interface IRatioResolvable /// Gets the minimum size. /// int MinimumSize { get; } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Internal/Polyfill/CancellationToken.cs b/src/Spectre.Console/Internal/Polyfill/CancellationToken.cs index 4d0e62cd1..d5b764788 100644 --- a/src/Spectre.Console/Internal/Polyfill/CancellationToken.cs +++ b/src/Spectre.Console/Internal/Polyfill/CancellationToken.cs @@ -1,13 +1,12 @@ #if NETSTANDARD2_0 -namespace Spectre.Console +namespace Spectre.Console; + +internal static class CancellationTokenHelpers { - internal static class CancellationTokenHelpers + public static Task CancelAsync(this CancellationTokenSource cts) { - public static Task CancelAsync(this CancellationTokenSource cts) - { - cts.Cancel(); - return Task.CompletedTask; - } + cts.Cancel(); + return Task.CompletedTask; } } #endif \ No newline at end of file diff --git a/src/Spectre.Console/Internal/Polyfill/EnumHelpers.cs b/src/Spectre.Console/Internal/Polyfill/EnumHelpers.cs index b1db26bf6..7753143a7 100644 --- a/src/Spectre.Console/Internal/Polyfill/EnumHelpers.cs +++ b/src/Spectre.Console/Internal/Polyfill/EnumHelpers.cs @@ -1,4 +1,4 @@ -namespace Spectre.Console; +namespace Spectre.Console; internal static class EnumUtils { diff --git a/src/Spectre.Console/Internal/Polyfill/IsExternalInit.cs b/src/Spectre.Console/Internal/Polyfill/IsExternalInit.cs index e152620ce..6fd1162cf 100644 --- a/src/Spectre.Console/Internal/Polyfill/IsExternalInit.cs +++ b/src/Spectre.Console/Internal/Polyfill/IsExternalInit.cs @@ -1,15 +1,12 @@ #if NETSTANDARD2_0 -using System.ComponentModel; +namespace System.Runtime.CompilerServices; -namespace System.Runtime.CompilerServices +/// +/// Reserved to be used by the compiler for tracking metadata. +/// This class should not be used by developers in source code. +/// +[EditorBrowsable(EditorBrowsableState.Never)] +internal static class IsExternalInit { - /// - /// Reserved to be used by the compiler for tracking metadata. - /// This class should not be used by developers in source code. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - internal static class IsExternalInit - { - } } #endif \ No newline at end of file diff --git a/src/Spectre.Console/Internal/TypeConverterHelper.cs b/src/Spectre.Console/Internal/TypeConverterHelper.cs index da08d2b77..c6f1f4b34 100644 --- a/src/Spectre.Console/Internal/TypeConverterHelper.cs +++ b/src/Spectre.Console/Internal/TypeConverterHelper.cs @@ -128,14 +128,14 @@ static TypeConverterHelper() [typeof(Array)] = _ => new ArrayConverter(), [typeof(ICollection)] = _ => new CollectionConverter(), [typeof(Enum)] = CreateEnumConverter(), - #if !NETSTANDARD2_0 +#if !NETSTANDARD2_0 [typeof(Int128)] = _ => new Int128Converter(), [typeof(Half)] = _ => new HalfConverter(), [typeof(UInt128)] = _ => new UInt128Converter(), [typeof(DateOnly)] = _ => new DateOnlyConverter(), [typeof(TimeOnly)] = _ => new TimeOnlyConverter(), [typeof(Version)] = _ => new VersionConverter(), - #endif +#endif }; } diff --git a/src/Spectre.Console/Live/Progress/ProgressContext.cs b/src/Spectre.Console/Live/Progress/ProgressContext.cs index 6736a35bd..51963051d 100644 --- a/src/Spectre.Console/Live/Progress/ProgressContext.cs +++ b/src/Spectre.Console/Live/Progress/ProgressContext.cs @@ -199,4 +199,4 @@ internal IReadOnlyList GetTasks() return new List(_tasks); } } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Properties/Usings.cs b/src/Spectre.Console/Properties/Usings.cs index 304b18971..a082d9373 100644 --- a/src/Spectre.Console/Properties/Usings.cs +++ b/src/Spectre.Console/Properties/Usings.cs @@ -15,7 +15,6 @@ global using System.Text.RegularExpressions; global using System.Threading; global using System.Threading.Tasks; -global using System.Xml; global using Spectre.Console.Enrichment; global using Spectre.Console.Internal; global using Spectre.Console.Rendering; diff --git a/src/Spectre.Console/Rendering/RenderOptions.cs b/src/Spectre.Console/Rendering/RenderOptions.cs index 3dcf04a5a..3fc2899ee 100644 --- a/src/Spectre.Console/Rendering/RenderOptions.cs +++ b/src/Spectre.Console/Rendering/RenderOptions.cs @@ -60,4 +60,4 @@ public static RenderOptions Create(IAnsiConsole console, IReadOnlyCapabilities? SingleLine = false, }; } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Rendering/Segment.cs b/src/Spectre.Console/Rendering/Segment.cs index a757d6fdc..9c95bd7b4 100644 --- a/src/Spectre.Console/Rendering/Segment.cs +++ b/src/Spectre.Console/Rendering/Segment.cs @@ -641,4 +641,4 @@ public void Reset(Segment segment) _originalSegment = segment; } } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Size.cs b/src/Spectre.Console/Size.cs index 5a074c850..3864848cc 100644 --- a/src/Spectre.Console/Size.cs +++ b/src/Spectre.Console/Size.cs @@ -26,4 +26,4 @@ public Size(int width, int height) Width = width; Height = height; } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/VerticalAlignment.cs b/src/Spectre.Console/VerticalAlignment.cs index 5d983c31c..0b88630d5 100644 --- a/src/Spectre.Console/VerticalAlignment.cs +++ b/src/Spectre.Console/VerticalAlignment.cs @@ -19,4 +19,4 @@ public enum VerticalAlignment /// Bottom aligned. /// Bottom, -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Widgets/Align.cs b/src/Spectre.Console/Widgets/Align.cs index 725b784ea..86f9ab8bb 100644 --- a/src/Spectre.Console/Widgets/Align.cs +++ b/src/Spectre.Console/Widgets/Align.cs @@ -143,4 +143,4 @@ protected override IEnumerable Render(RenderOptions options, int maxWid return new SegmentLineEnumerator(lines); } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Widgets/Layout/Layout.cs b/src/Spectre.Console/Widgets/Layout/Layout.cs index f3bc0c4d3..fc25e3eda 100644 --- a/src/Spectre.Console/Widgets/Layout/Layout.cs +++ b/src/Spectre.Console/Widgets/Layout/Layout.cs @@ -308,4 +308,4 @@ private Dictionary MakeRenderMap(RenderOptions options, in return result.ReverseEnumerable(); } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Widgets/Layout/LayoutPlaceholder.cs b/src/Spectre.Console/Widgets/Layout/LayoutPlaceholder.cs index 46b959aab..93b824f3f 100644 --- a/src/Spectre.Console/Widgets/Layout/LayoutPlaceholder.cs +++ b/src/Spectre.Console/Widgets/Layout/LayoutPlaceholder.cs @@ -28,4 +28,4 @@ protected override IEnumerable Render(RenderOptions options, int maxWid return ((IRenderable)panel).Render(options, maxWidth); } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Widgets/Layout/LayoutSplitter.cs b/src/Spectre.Console/Widgets/Layout/LayoutSplitter.cs index 6be913cd0..9f4bdfa68 100644 --- a/src/Spectre.Console/Widgets/Layout/LayoutSplitter.cs +++ b/src/Spectre.Console/Widgets/Layout/LayoutSplitter.cs @@ -45,4 +45,4 @@ private sealed class RowSplitter : LayoutSplitter } } } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Widgets/Paragraph.cs b/src/Spectre.Console/Widgets/Paragraph.cs index f06d6c17c..d0b0683d5 100644 --- a/src/Spectre.Console/Widgets/Paragraph.cs +++ b/src/Spectre.Console/Widgets/Paragraph.cs @@ -280,4 +280,4 @@ private List SplitLines(int maxWidth) return lines; } -} +} \ No newline at end of file diff --git a/src/Spectre.Console/Widgets/TextPath.cs b/src/Spectre.Console/Widgets/TextPath.cs index fafafb7b1..47739d4e7 100644 --- a/src/Spectre.Console/Widgets/TextPath.cs +++ b/src/Spectre.Console/Widgets/TextPath.cs @@ -187,4 +187,4 @@ private string[] Fit(RenderOptions options, int maxWidth) return new[] { string.Concat(ellipsis, last.Substring(start, take)) }; } -} +} \ No newline at end of file diff --git a/src/Tests/.editorconfig b/src/Tests/.editorconfig deleted file mode 100644 index 6b1075839..000000000 --- a/src/Tests/.editorconfig +++ /dev/null @@ -1,107 +0,0 @@ -root = false - -[*.cs] -# Default severity for analyzer diagnostics with category 'StyleCop.CSharp.DocumentationRules' -dotnet_analyzer_diagnostic.category-StyleCop.CSharp.DocumentationRules.severity = none - -# IDE0055: Fix formatting -dotnet_diagnostic.IDE0055.severity = warning - -# SA1101: Prefix local calls with this -dotnet_diagnostic.SA1101.severity = none - -# SA1633: File should have header -dotnet_diagnostic.SA1633.severity = none - -# SA1201: Elements should appear in the correct order -dotnet_diagnostic.SA1201.severity = none - -# SA1202: Public members should come before private members -dotnet_diagnostic.SA1202.severity = none - -# SA1309: Field names should not begin with underscore -dotnet_diagnostic.SA1309.severity = none - -# SA1404: Code analysis suppressions should have justification -dotnet_diagnostic.SA1404.severity = none - -# SA1516: Elements should be separated by a blank line -dotnet_diagnostic.SA1516.severity = none - -# CA1303: Do not pass literals as localized parameters -dotnet_diagnostic.CA1303.severity = none - -# CSA1204: Static members should appear before non-static members -dotnet_diagnostic.SA1204.severity = none - -# IDE0052: Remove unread private members -dotnet_diagnostic.IDE0052.severity = warning - -# IDE0063: Use simple 'using' statement -csharp_prefer_simple_using_statement = false:suggestion - -# IDE0018: Variable declaration can be inlined -dotnet_diagnostic.IDE0018.severity = warning - -# SA1625: Element documenation should not be copied and pasted -dotnet_diagnostic.SA1625.severity = none - -# IDE0005: Using directive is unnecessary -dotnet_diagnostic.IDE0005.severity = warning - -# SA1117: Parameters should be on same line or separate lines -dotnet_diagnostic.SA1117.severity = none - -# SA1404: Code analysis suppression should have justification -dotnet_diagnostic.SA1404.severity = none - -# SA1101: Prefix local calls with this -dotnet_diagnostic.SA1101.severity = none - -# SA1633: File should have header -dotnet_diagnostic.SA1633.severity = none - -# SA1649: File name should match first type name -dotnet_diagnostic.SA1649.severity = none - -# SA1402: File may only contain a single type -dotnet_diagnostic.SA1402.severity = none - -# CA1814: Prefer jagged arrays over multidimensional -dotnet_diagnostic.CA1814.severity = none - -# RCS1194: Implement exception constructors. -dotnet_diagnostic.RCS1194.severity = none - -# CA1032: Implement standard exception constructors -dotnet_diagnostic.CA1032.severity = none - -# CA1826: Do not use Enumerable methods on indexable collections. Instead use the collection directly -dotnet_diagnostic.CA1826.severity = none - -# RCS1079: Throwing of new NotImplementedException. -dotnet_diagnostic.RCS1079.severity = warning - -# RCS1057: Add empty line between declarations. -dotnet_diagnostic.RCS1057.severity = none - -# RCS1057: Validate arguments correctly -dotnet_diagnostic.RCS1227.severity = none - -# IDE0004: Remove Unnecessary Cast -dotnet_diagnostic.IDE0004.severity = warning - -# CA1810: Initialize reference type static fields inline -dotnet_diagnostic.CA1810.severity = none - -# IDE0044: Add readonly modifier -dotnet_diagnostic.IDE0044.severity = warning - -# RCS1047: Non-asynchronous method name should not end with 'Async'. -dotnet_diagnostic.RCS1047.severity = none - -# RCS1090: Call 'ConfigureAwait(false)'. -dotnet_diagnostic.RCS1090.severity = warning - -# CS1591: Missing XML comment for publicly visible type or member -dotnet_diagnostic.CS1591.severity = none \ No newline at end of file diff --git a/src/Tests/Directory.Build.props b/src/Tests/Directory.Build.props deleted file mode 100644 index 9932e25e0..000000000 --- a/src/Tests/Directory.Build.props +++ /dev/null @@ -1,13 +0,0 @@ - - - 12 - false - true - true - $(MSBuildThisFileDirectory)\..\..\resources\spectre.snk - - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Constants.cs b/src/Tests/Spectre.Console.Cli.Tests/Constants.cs deleted file mode 100644 index 914854f0a..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Constants.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Spectre.Console.Tests; - -public static class Constants -{ - public static string[] VersionCommand { get; } = - [ - CliConstants.Commands.Branch, - CliConstants.Commands.Version - ]; - - public static string[] XmlDocCommand { get; } = - [ - CliConstants.Commands.Branch, - CliConstants.Commands.XmlDoc - ]; - - public static string[] OpenCliOption { get; } = - [CliConstants.DumpHelpOpenCliOption]; -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AnimalCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AnimalCommand.cs deleted file mode 100644 index dceaa35ba..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AnimalCommand.cs +++ /dev/null @@ -1,8 +0,0 @@ -using SystemConsole = System.Console; - -namespace Spectre.Console.Tests.Data; - -public abstract class AnimalCommand : Command - where TSettings : CommandSettings -{ -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AsynchronousCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AsynchronousCommand.cs deleted file mode 100644 index 891d1ce9b..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/AsynchronousCommand.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class AsynchronousCommand : AsyncCommand -{ - private readonly IAnsiConsole _console; - - public AsynchronousCommand(IAnsiConsole console) - { - _console = console; - } - - public async override Task ExecuteAsync(CommandContext context, AsynchronousCommandSettings settings, CancellationToken cancellationToken) - { - // Simulate a long running asynchronous task - await Task.Delay(200, cancellationToken); - - if (settings.ThrowException) - { - throw new Exception($"Throwing exception asynchronously"); - } - else - { - _console.Write($"Finished executing asynchronously"); - } - - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/CatCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/CatCommand.cs deleted file mode 100644 index 97eb2b432..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/CatCommand.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class CatCommand : AnimalCommand -{ - public override int Execute(CommandContext context, CatSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DogCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DogCommand.cs deleted file mode 100644 index 9361fdae0..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DogCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -[Description("The dog command.")] -public class DogCommand : AnimalCommand -{ - public override ValidationResult Validate(CommandContext context, DogSettings settings) - { - if (context is null) - { - throw new System.ArgumentNullException(nameof(context)); - } - - if (settings is null) - { - throw new System.ArgumentNullException(nameof(settings)); - } - - if (settings.Age > 100 && !context.Remaining.Raw.Contains("zombie")) - { - return ValidationResult.Error("Dog is too old..."); - } - - return base.Validate(context, settings); - } - - public override int Execute(CommandContext context, DogSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DumpRemainingCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DumpRemainingCommand.cs deleted file mode 100644 index b848787de..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/DumpRemainingCommand.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class DumpRemainingCommand : Command -{ - private readonly IAnsiConsole _console; - - public DumpRemainingCommand(IAnsiConsole console) - { - _console = console; - } - - public override int Execute(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) - { - if (context.Remaining.Raw.Count > 0) - { - _console.WriteLine("# Raw"); - foreach (var item in context.Remaining.Raw) - { - _console.WriteLine(item); - } - } - - if (context.Remaining.Parsed.Count > 0) - { - _console.WriteLine("# Parsed"); - foreach (var item in context.Remaining.Parsed) - { - _console.WriteLine(string.Format("{0}={1}", item.Key, string.Join(",", item.Select(x => x)))); - } - } - - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/EmptyCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/EmptyCommand.cs deleted file mode 100644 index 498884e28..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/EmptyCommand.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class EmptyCommand : Command -{ - public override int Execute(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GenericCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GenericCommand.cs deleted file mode 100644 index 0353508a4..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GenericCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class GenericCommand : Command - where TSettings : CommandSettings -{ - public override int Execute(CommandContext context, TSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GiraffeCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GiraffeCommand.cs deleted file mode 100644 index e6569ae3a..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GiraffeCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -[Description("The giraffe command.")] -public sealed class GiraffeCommand : Command -{ - public override int Execute(CommandContext context, GiraffeSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GreeterCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GreeterCommand.cs deleted file mode 100644 index 03ff8eaed..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/GreeterCommand.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Spectre.Console; - -public class GreeterCommand : Command -{ - private readonly IAnsiConsole _console; - - public GreeterCommand(IAnsiConsole console) - { - _console = console; - } - - public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings, CancellationToken cancellationToken) - { - _console.WriteLine(settings.Greeting); - return 0; - } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HiddenOptionsCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HiddenOptionsCommand.cs deleted file mode 100644 index 15dcfb606..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HiddenOptionsCommand.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class HiddenOptionsCommand : Command -{ - public override int Execute(CommandContext context, HiddenOptionSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HorseCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HorseCommand.cs deleted file mode 100644 index 7e7e89e65..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/HorseCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -[Description("The horse command.")] -public class HorseCommand : AnimalCommand -{ - public override int Execute(CommandContext context, HorseSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/InvalidCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/InvalidCommand.cs deleted file mode 100644 index ef2cf1a5b..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/InvalidCommand.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class InvalidCommand : Command -{ - public override int Execute(CommandContext context, InvalidSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/LionCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/LionCommand.cs deleted file mode 100644 index bd415d696..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/LionCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -[Description("The lion command.")] -public class LionCommand : AnimalCommand -{ - public override int Execute(CommandContext context, LionSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/NoDescriptionCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/NoDescriptionCommand.cs deleted file mode 100644 index 1a7d064bf..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/NoDescriptionCommand.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class NoDescriptionCommand : Command -{ - [CommandOption("-f|--foo ")] - public int Foo { get; set; } - - public override int Execute(CommandContext context, EmptyCommandSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/OptionVectorCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/OptionVectorCommand.cs deleted file mode 100644 index bfb76e787..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/OptionVectorCommand.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class OptionVectorCommand : Command -{ - public override int Execute(CommandContext context, OptionVectorSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/ThrowingCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/ThrowingCommand.cs deleted file mode 100644 index 493c3f14a..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/ThrowingCommand.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class ThrowingCommand : Command -{ - public override int Execute(CommandContext context, ThrowingCommandSettings settings, CancellationToken cancellationToken) - { - throw new InvalidOperationException("W00t?"); - } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/TurtleCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/TurtleCommand.cs deleted file mode 100644 index 957671a54..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/TurtleCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -[Description("The turtle command.")] -public class TurtleCommand : AnimalCommand -{ - public override int Execute(CommandContext context, TurtleSettings settings, CancellationToken cancellationToken) - { - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/VersionCommand.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/VersionCommand.cs deleted file mode 100644 index 8c7c33033..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Commands/VersionCommand.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class VersionCommand : Command -{ - private readonly IAnsiConsole _console; - - public VersionCommand(IAnsiConsole console) - { - _console = console; - } - - public override int Execute(CommandContext context, VersionSettings settings, CancellationToken cancellationToken) - { - _console.WriteLine($"VersionCommand ran, Version: {settings.Version ?? string.Empty}"); - - return 0; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Converters/CatAgilityConverter.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Converters/CatAgilityConverter.cs deleted file mode 100644 index 043b82cb0..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Converters/CatAgilityConverter.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class CatAgilityConverter : TypeConverter -{ - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is string stringValue) - { - return stringValue.Length; - } - - return base.ConvertFrom(context, culture, value); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Converters/StringToIntegerConverter.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Converters/StringToIntegerConverter.cs deleted file mode 100644 index dc30c09d4..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Converters/StringToIntegerConverter.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class StringToIntegerConverter : TypeConverter -{ - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is string stringValue) - { - return int.Parse(stringValue, CultureInfo.InvariantCulture); - } - - return base.ConvertFrom(context, culture, value); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Help/CustomHelpProvider.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Help/CustomHelpProvider.cs deleted file mode 100644 index a7be2267a..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Help/CustomHelpProvider.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Spectre.Console.Rendering; - -namespace Spectre.Console.Cli.Tests.Data.Help; - -internal class CustomHelpProvider : HelpProvider -{ - private readonly string version; - - public CustomHelpProvider(ICommandAppSettings settings, string version) - : base(settings) - { - this.version = version; - } - - public override IEnumerable GetHeader(ICommandModel model, ICommandInfo command) - { - return new IRenderable[] - { - new Text("--------------------------------------"), Text.NewLine, - new Text("--- CUSTOM HELP PROVIDER ---"), Text.NewLine, - new Text("--------------------------------------"), Text.NewLine, - Text.NewLine, - }; - } - - public override IEnumerable GetFooter(ICommandModel model, ICommandInfo command) - { - return new IRenderable[] - { - Text.NewLine, - new Text($"Version {version}"), - }; - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Help/RedirectHelpProvider.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Help/RedirectHelpProvider.cs deleted file mode 100644 index b8c191962..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Help/RedirectHelpProvider.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Spectre.Console.Rendering; - -namespace Spectre.Console.Cli.Tests.Data.Help; - -internal class RedirectHelpProvider : IHelpProvider -{ - public virtual IEnumerable Write(ICommandModel model) - { - return Write(model, null); - } -#nullable enable - public virtual IEnumerable Write(ICommandModel model, ICommandInfo? command) -#nullable disable - { - return new[] - { - new Text("Help has moved online. Please see: http://www.example.com"), - Text.NewLine, - }; - } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Help/RenderMarkupHelpProvider.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Help/RenderMarkupHelpProvider.cs deleted file mode 100644 index a2941bfaf..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Help/RenderMarkupHelpProvider.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Spectre.Console.Cli.Tests.Data.Help; - -internal class RenderMarkupHelpProvider : HelpProvider -{ - protected override bool RenderMarkupInline { get; } = true; - - public RenderMarkupHelpProvider(ICommandAppSettings settings) - : base(settings) - { - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/AnimalSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/AnimalSettings.cs deleted file mode 100644 index 0e077a47a..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/AnimalSettings.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public abstract class AnimalSettings : CommandSettings -{ - [CommandOption("-a|--alive|--not-dead")] - [Description("Indicates whether or not the animal is alive.")] - public bool IsAlive { get; set; } - - [CommandArgument(1, "[LEGS]")] - [Description("The number of legs.")] - [EvenNumberValidator("Animals must have an even number of legs.")] - [PositiveNumberValidator("Number of legs must be greater than 0.")] - public int Legs { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ArgumentOrderSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ArgumentOrderSettings.cs deleted file mode 100644 index cc56b9127..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ArgumentOrderSettings.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class ArgumentOrderSettings : CommandSettings -{ - [CommandArgument(0, "[QUX]")] - public int Qux { get; set; } - - [CommandArgument(3, "")] - public int Corgi { get; set; } - - [CommandArgument(1, "")] - public int Bar { get; set; } - - [CommandArgument(2, "")] - public int Baz { get; set; } - - [CommandArgument(0, "")] - public int Foo { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ArgumentVectorSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ArgumentVectorSettings.cs deleted file mode 100644 index 63b7f48e0..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ArgumentVectorSettings.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class ArgumentVectorSettings : CommandSettings -{ - [CommandArgument(0, "")] - public string[] Foo { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/AsynchronousCommandSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/AsynchronousCommandSettings.cs deleted file mode 100644 index b41e10d59..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/AsynchronousCommandSettings.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class AsynchronousCommandSettings : CommandSettings -{ - [CommandOption("--ThrowException")] - [DefaultValue(false)] - public bool ThrowException { get; set; } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/BarCommandSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/BarCommandSettings.cs deleted file mode 100644 index 27f94d5a2..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/BarCommandSettings.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class BarCommandSettings : FooCommandSettings -{ - [CommandArgument(0, "")] - [Description("The corgi value.")] - public string Corgi { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/CatSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/CatSettings.cs deleted file mode 100644 index 64c911bed..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/CatSettings.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class CatSettings : MammalSettings -{ - [CommandOption("--agility ")] - [TypeConverter(typeof(CatAgilityConverter))] - [DefaultValue(10)] - [Description("The agility between 0 and 100.")] - [PositiveNumberValidator("Agility cannot be negative.")] - public int Agility { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/DogSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/DogSettings.cs deleted file mode 100644 index b5c3cf8ac..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/DogSettings.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class DogSettings : MammalSettings -{ - [CommandArgument(0, "")] - public int Age { get; set; } - - [CommandOption("-g|--good-boy")] - public bool GoodBoy { get; set; } - - public override ValidationResult Validate() - { - if (Name == "Tiger") - { - return ValidationResult.Error("Tiger is not a dog name!"); - } - - return ValidationResult.Success(); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/FooSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/FooSettings.cs deleted file mode 100644 index 542f205a4..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/FooSettings.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class FooCommandSettings : CommandSettings -{ - [CommandArgument(0, "[QUX]")] - [Description("The qux value.")] - public string Qux { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/GiraffeSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/GiraffeSettings.cs deleted file mode 100644 index c46e521a3..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/GiraffeSettings.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class GiraffeSettings : MammalSettings -{ - [CommandArgument(0, "")] - [Description("The option description.")] - public int Length { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/HiddenOptionSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/HiddenOptionSettings.cs deleted file mode 100644 index 209d56b91..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/HiddenOptionSettings.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class HiddenOptionSettings : CommandSettings -{ - [CommandArgument(0, "")] - [Description("Dummy argument FOO")] - public int Foo { get; set; } - - [CommandOption("--bar", IsHidden = true)] - [Description("You should not be able to read this unless you used the 'cli explain' command with the '--hidden' option")] - public int Bar { get; set; } - - [CommandOption("--baz")] - [Description("Dummy option BAZ")] - public int Baz { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/HorseSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/HorseSettings.cs deleted file mode 100644 index 46dcff1e3..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/HorseSettings.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.IO; - -namespace Spectre.Console.Tests.Data; - -public class HorseSettings : MammalSettings -{ - [CommandOption("-d|--day ")] - public DayOfWeek Day { get; set; } - - [CommandOption("--file")] - [DefaultValue("food.txt")] - public FileInfo File { get; set; } - - [CommandOption("--directory")] - public DirectoryInfo Directory { get; set; } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/InvalidSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/InvalidSettings.cs deleted file mode 100644 index 419183854..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/InvalidSettings.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class InvalidSettings : CommandSettings -{ - [CommandOption("-f|--foo [BAR]")] - public string Value { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/LionSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/LionSettings.cs deleted file mode 100644 index 543ea3541..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/LionSettings.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class LionSettings : CatSettings -{ - [CommandArgument(0, "")] - [Description("The number of teeth the lion has.")] - public int Teeth { get; set; } - - [CommandOption("-c ")] - [Description("The number of children the lion has.")] - public int Children { get; set; } - - [CommandOption("-d ")] - [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 Weight { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/MammalSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/MammalSettings.cs deleted file mode 100644 index 7b1c45532..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/MammalSettings.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class MammalSettings : AnimalSettings -{ - [CommandOption("-n|-p|--name|--pet-name ")] - public string Name { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/MultipleArgumentVectorSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/MultipleArgumentVectorSettings.cs deleted file mode 100644 index 2dda29c1f..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/MultipleArgumentVectorSettings.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class MultipleArgumentVectorSettings : CommandSettings -{ - [CommandArgument(0, "")] - public string[] Foo { get; set; } - - [CommandArgument(0, "")] - public string[] Bar { get; set; } -} - -public class MultipleArgumentVectorSpecifiedFirstSettings : CommandSettings -{ - [CommandArgument(1, "[Bar]")] - public string Bar { get; set; } - - [CommandArgument(0, "")] - public string[] Foo { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/OptionVectorSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/OptionVectorSettings.cs deleted file mode 100644 index 138b359f0..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/OptionVectorSettings.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class OptionVectorSettings : CommandSettings -{ - [CommandOption("--foo")] - public string[] Foo { get; set; } - - [CommandOption("--bar")] - public int[] Bar { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/OptionalArgumentWithDefaultValueSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/OptionalArgumentWithDefaultValueSettings.cs deleted file mode 100644 index ae0e15504..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/OptionalArgumentWithDefaultValueSettings.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class OptionalArgumentWithDefaultValueSettings : CommandSettings -{ - [CommandArgument(0, "[GREETING]")] - [DefaultValue("Hello World")] - public string Greeting { get; set; } -} - -public sealed class OptionalArgumentWithPropertyInitializerSettings : CommandSettings -{ - [CommandArgument(0, "[NAMES]")] - public string[] Names { get; set; } = Array.Empty(); - - [CommandOption("-c")] - public int Count { get; set; } = 1; - - [CommandOption("--value")] - public int Value { get; set; } = 0; -} - -public sealed class OptionalArgumentWithDefaultValueAndTypeConverterSettings : CommandSettings -{ - [CommandArgument(0, "[GREETING]")] - [DefaultValue("5")] - [TypeConverter(typeof(StringToIntegerConverter))] - public int Greeting { get; set; } -} - -public sealed class RequiredArgumentWithDefaultValueSettings : CommandSettings -{ - [CommandArgument(0, "")] - [DefaultValue("Hello World")] - public string Greeting { get; set; } -} - -public sealed class OptionWithArrayOfEnumDefaultValueSettings : CommandSettings -{ - [CommandOption("--days")] - [DefaultValue(new[] { DayOfWeek.Sunday, DayOfWeek.Saturday })] - public DayOfWeek[] Days { get; set; } -} - -public sealed class OptionWithArrayOfStringDefaultValueAndTypeConverterSettings : CommandSettings -{ - [CommandOption("--numbers")] - [DefaultValue(new[] { "2", "3" })] - [TypeConverter(typeof(StringToIntegerConverter))] - public int[] Numbers { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ReptileSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ReptileSettings.cs deleted file mode 100644 index 04b6f458e..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ReptileSettings.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class ReptileSettings : AnimalSettings -{ - [CommandOption("-n|-p|--name|--pet-name ")] - public string Name { get; set; } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/RequiredOptionsSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/RequiredOptionsSettings.cs deleted file mode 100644 index f05b92cbd..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/RequiredOptionsSettings.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public class RequiredOptionsSettings : CommandSettings -{ - [CommandOption("--foo ", true)] - [Description("Foos the bars")] - public string Foo { get; set; } -} - -public class RequiredOptionsWithoutDescriptionSettings : CommandSettings -{ - [CommandOption("--foo ", true)] - public string Foo { get; set; } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/StringOptionSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/StringOptionSettings.cs deleted file mode 100644 index 272383df2..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/StringOptionSettings.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class StringOptionSettings : CommandSettings -{ - [CommandOption("-f|--foo")] - public string Foo { get; set; } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ThrowingCommandSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ThrowingCommandSettings.cs deleted file mode 100644 index 4d0c0ea74..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/ThrowingCommandSettings.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class ThrowingCommandSettings : CommandSettings -{ -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/TurtleSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/TurtleSettings.cs deleted file mode 100644 index 34b99a3aa..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/TurtleSettings.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class TurtleSettings : ReptileSettings -{ - public TurtleSettings(string name) - { - Name = name; - } - - public override ValidationResult Validate() - { - return Name != "Lonely George" - ? ValidationResult.Error("Only 'Lonely George' is valid name for a turtle!") - : ValidationResult.Success(); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/VersionSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/VersionSettings.cs deleted file mode 100644 index e84c9e79e..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/VersionSettings.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -public sealed class VersionSettings : CommandSettings -{ - [CommandOption("-v|--version")] - [Description("The command version")] - public string Version { get; set; } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Validators/EvenNumberValidatorAttribute.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Validators/EvenNumberValidatorAttribute.cs deleted file mode 100644 index 01601f4e5..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Validators/EvenNumberValidatorAttribute.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] -public sealed class EvenNumberValidatorAttribute : ParameterValidationAttribute -{ - public EvenNumberValidatorAttribute(string errorMessage) - : base(errorMessage) - { - } - - public override ValidationResult Validate(CommandParameterContext context) - { - if (context.Value is int integer) - { - if (integer % 2 == 0) - { - return ValidationResult.Success(); - } - - return ValidationResult.Error($"Number is not even ({context.Parameter.PropertyName})."); - } - - throw new InvalidOperationException($"Parameter is not a number ({context.Parameter.PropertyName})."); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Validators/PositiveNumberValidatorAttribute.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Validators/PositiveNumberValidatorAttribute.cs deleted file mode 100644 index 94bab60c6..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Validators/PositiveNumberValidatorAttribute.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Spectre.Console.Tests.Data; - -[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] -public sealed class PositiveNumberValidatorAttribute : ParameterValidationAttribute -{ - public PositiveNumberValidatorAttribute(string errorMessage) - : base(errorMessage) - { - } - - public override ValidationResult Validate(CommandParameterContext context) - { - if (context.Value is int integer) - { - if (integer > 0) - { - return ValidationResult.Success(); - } - - return ValidationResult.Error($"Number is not greater than 0 ({context.Parameter.PropertyName})."); - } - - throw new InvalidOperationException($"Parameter is not a number ({context.Parameter.PropertyName})."); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/ArgumentOrder.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/ArgumentOrder.Output.verified.txt deleted file mode 100644 index 9a82776df..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/ArgumentOrder.Output.verified.txt +++ /dev/null @@ -1,12 +0,0 @@ -USAGE: - myapp [QUX] [OPTIONS] - -ARGUMENTS: - - - - - [QUX] - -OPTIONS: - -h, --help Prints help information \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch.Output.verified.txt deleted file mode 100644 index 2efdb4c9a..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch.Output.verified.txt +++ /dev/null @@ -1,18 +0,0 @@ -DESCRIPTION: -Contains settings for a cat - -USAGE: - myapp cat [LEGS] [OPTIONS] - -ARGUMENTS: - [LEGS] The number of legs - -OPTIONS: - DEFAULT - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -COMMANDS: - lion The lion command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Called_Without_Help.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Called_Without_Help.Output.verified.txt deleted file mode 100644 index 821812368..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Called_Without_Help.Output.verified.txt +++ /dev/null @@ -1,18 +0,0 @@ -DESCRIPTION: -Contains settings for a cat - -USAGE: - myapp cat [LEGS] [OPTIONS] - -ARGUMENTS: - [LEGS] The number of legs - -OPTIONS: - DEFAULT - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -COMMANDS: - lion The lion command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Default_Greeter.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Default_Greeter.Output.verified.txt deleted file mode 100644 index e51ef5fea..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Default_Greeter.Output.verified.txt +++ /dev/null @@ -1,11 +0,0 @@ -USAGE: - myapp branch [GREETING] [OPTIONS] [COMMAND] - -ARGUMENTS: - [GREETING] - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - greeter \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Examples.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Examples.Output.verified.txt deleted file mode 100644 index 97851a34e..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Branch_Examples.Output.verified.txt +++ /dev/null @@ -1,30 +0,0 @@ -DESCRIPTION: -The animal command - -USAGE: - myapp animal [LEGS] [OPTIONS] - -EXAMPLES: - myapp animal dog --name Rufus --age 12 --good-boy - myapp animal dog --name Luna - myapp animal dog --name Charlie - myapp animal dog --name Bella - myapp animal dog --name Daisy - myapp animal dog --name Milo - myapp animal horse --name Brutus - myapp animal horse --name Sugar --IsAlive false - myapp animal horse --name Cash - myapp animal horse --name Dakota - myapp animal horse --name Cisco - myapp animal horse --name Spirit - -ARGUMENTS: - [LEGS] The number of legs - -OPTIONS: - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -COMMANDS: - dog The dog command - horse The horse command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Command_Hide_Default.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Command_Hide_Default.Output.verified.txt deleted file mode 100644 index 102ef3a39..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Command_Hide_Default.Output.verified.txt +++ /dev/null @@ -1,17 +0,0 @@ -DESCRIPTION: -Contains settings for a cat - -USAGE: - myapp cat [LEGS] [OPTIONS] - -ARGUMENTS: - [LEGS] The number of legs - -OPTIONS: - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility The agility between 0 and 100 - -COMMANDS: - lion The lion command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Configured_By_Instance.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Configured_By_Instance.Output.verified.txt deleted file mode 100644 index f2bd53972..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Configured_By_Instance.Output.verified.txt +++ /dev/null @@ -1,14 +0,0 @@ --------------------------------------- ---- CUSTOM HELP PROVIDER --- --------------------------------------- - -USAGE: - myapp [OPTIONS] - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - dog The dog command - -Version 1.0 \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Configured_By_Type.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Configured_By_Type.Output.verified.txt deleted file mode 100644 index c21811355..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Configured_By_Type.Output.verified.txt +++ /dev/null @@ -1 +0,0 @@ -Help has moved online. Please see: http://www.example.com \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Registered_By_Instance.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Registered_By_Instance.Output.verified.txt deleted file mode 100644 index f2bd53972..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Registered_By_Instance.Output.verified.txt +++ /dev/null @@ -1,14 +0,0 @@ --------------------------------------- ---- CUSTOM HELP PROVIDER --- --------------------------------------- - -USAGE: - myapp [OPTIONS] - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - dog The dog command - -Version 1.0 \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Registered_By_Type.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Registered_By_Type.Output.verified.txt deleted file mode 100644 index c21811355..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Registered_By_Type.Output.verified.txt +++ /dev/null @@ -1 +0,0 @@ -Help has moved online. Please see: http://www.example.com \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default.Output.verified.txt deleted file mode 100644 index 5f9add482..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default.Output.verified.txt +++ /dev/null @@ -1,19 +0,0 @@ -DESCRIPTION: -The lion command - -USAGE: - myapp [LEGS] [OPTIONS] - -ARGUMENTS: - The number of teeth the lion has - [LEGS] The number of legs - -OPTIONS: - DEFAULT - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Custom_Help_Provider.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Custom_Help_Provider.Output.verified.txt deleted file mode 100644 index ad99fbb63..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Custom_Help_Provider.Output.verified.txt +++ /dev/null @@ -1,15 +0,0 @@ --------------------------------------- ---- CUSTOM HELP PROVIDER --- --------------------------------------- - -USAGE: - myapp [OPTIONS] - -OPTIONS: - -h, --help Prints help information - -v, --version Prints version information - -COMMANDS: - dog The dog command - -Version 1.0 \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Examples.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Examples.Output.verified.txt deleted file mode 100644 index b9082ea89..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Examples.Output.verified.txt +++ /dev/null @@ -1,23 +0,0 @@ -DESCRIPTION: -The dog command - -USAGE: - myapp [LEGS] [OPTIONS] - -EXAMPLES: - myapp --name Rufus --age 12 --good-boy - myapp --name Luna - myapp --name Charlie - myapp --name Bella - myapp --name Daisy - myapp --name Milo - -ARGUMENTS: - - [LEGS] The number of legs - -OPTIONS: - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -n, --name - -g, --good-boy \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Greeter.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Greeter.Output.verified.txt deleted file mode 100644 index 5e1c309da..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Greeter.Output.verified.txt +++ /dev/null @@ -1 +0,0 @@ -Hello World \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args.Output.verified.txt deleted file mode 100644 index 5f9add482..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args.Output.verified.txt +++ /dev/null @@ -1,19 +0,0 @@ -DESCRIPTION: -The lion command - -USAGE: - myapp [LEGS] [OPTIONS] - -ARGUMENTS: - The number of teeth the lion has - [LEGS] The number of legs - -OPTIONS: - DEFAULT - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_DE.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_DE.verified.txt deleted file mode 100644 index ccceba616..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_DE.verified.txt +++ /dev/null @@ -1,26 +0,0 @@ -BESCHREIBUNG: -The lion command - -VERWENDUNG: - myapp [LEGS] [OPTIONEN] [KOMMANDO] - -BEISPIELE: - myapp 20 --alive - -ARGUMENTE: - The number of teeth the lion has - [LEGS] The number of legs - -OPTIONEN: - STANDARDWERT - -h, --help Zeigt Hilfe an - -v, --version Zeigt Versionsinformationen an - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs - -KOMMANDOS: - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_EN.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_EN.verified.txt deleted file mode 100644 index 020ef9559..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_EN.verified.txt +++ /dev/null @@ -1,26 +0,0 @@ -DESCRIPTION: -The lion command - -USAGE: - myapp [LEGS] [OPTIONS] [COMMAND] - -EXAMPLES: - myapp 20 --alive - -ARGUMENTS: - 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 - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs - -COMMANDS: - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_FR.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_FR.verified.txt deleted file mode 100644 index 07654b837..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_FR.verified.txt +++ /dev/null @@ -1,26 +0,0 @@ -DESCRIPTION: -The lion command - -UTILISATION: - myapp [LEGS] [OPTIONS] [COMMANDE] - -EXEMPLES: - myapp 20 --alive - -ARGUMENTS: - The number of teeth the lion has - [LEGS] The number of legs - -OPTIONS: - DÉFAUT - -h, --help Affiche l'aide - -v, --version Affiche la version - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs - -COMMANDES: - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_IT.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_IT.verified.txt deleted file mode 100644 index 919af8cbe..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_IT.verified.txt +++ /dev/null @@ -1,26 +0,0 @@ -DESCRIZIONE: -The lion command - -USO: - myapp [LEGS] [OPZIONI] [COMANDO] - -ESEMPI: - myapp 20 --alive - -ARGOMENTI: - The number of teeth the lion has - [LEGS] The number of legs - -OPZIONI: - PREDEFINITO - -h, --help Visualizza le informazioni di aiuto - -v, --version Visualizza le informazioni sulla versione - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs - -COMANDI: - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_JA.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_JA.verified.txt deleted file mode 100644 index 0dcf7ca1f..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_JA.verified.txt +++ /dev/null @@ -1,26 +0,0 @@ -説明: -The lion command - -使用法: - myapp [LEGS] [オプション] [コマンド] - -例: - myapp 20 --alive - -引数: - The number of teeth the lion has - [LEGS] The number of legs - -オプション: - デフォルト - -h, --help ヘルプ情報を表示 - -v, --version バージョン情報を表示 - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs - -コマンド群: - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_KO.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_KO.verified.txt deleted file mode 100644 index c998efe84..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_KO.verified.txt +++ /dev/null @@ -1,26 +0,0 @@ -설명: -The lion command - -사용법: - myapp [LEGS] [옵션] [명령] - -예시: - myapp 20 --alive - -인수: - The number of teeth the lion has - [LEGS] The number of legs - -옵션: - 기본값 - -h, --help 도움말 정보를 출력 - -v, --version 버전 정보를 출력 - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs - -명령어: - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_PT.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_PT.verified.txt deleted file mode 100644 index 682a7a3ae..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_PT.verified.txt +++ /dev/null @@ -1,26 +0,0 @@ -DESCRIÇÃO: -The lion command - -USO: - myapp [LEGS] [OPÇÕES] [COMANDO] - -EXEMPLOS: - myapp 20 --alive - -ARGUMENTOS: - The number of teeth the lion has - [LEGS] The number of legs - -OPÇÕES: - PADRÃO - -h, --help Exibe informações de ajuda - -v, --version Exibe informações de versão - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs - -COMANDOS: - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_RU.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_RU.verified.txt deleted file mode 100644 index 140c5c6dc..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_RU.verified.txt +++ /dev/null @@ -1,26 +0,0 @@ -ОПИСАНИЕ: -The lion command - -ИСПОЛЬЗОВАНИЕ: - myapp [LEGS] [ОПЦИИ] [КОМАНДА] - -ПРИМЕРЫ: - myapp 20 --alive - -АРГУМЕНТЫ: - The number of teeth the lion has - [LEGS] The number of legs - -ОПЦИИ: - ПО УМОЛЧАНИЮ - -h, --help Выводит информацию о помощи - -v, --version Выводит информацию о версии - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs - -КОМАНДЫ: - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_SV.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_SV.verified.txt deleted file mode 100644 index baa423c0c..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_SV.verified.txt +++ /dev/null @@ -1,26 +0,0 @@ -BESKRIVNING: -The lion command - -ANVÄNDING: - myapp [LEGS] [VAL] [KOMMANDO] - -EXEMPEL: - myapp 20 --alive - -ARGUMENT: - The number of teeth the lion has - [LEGS] The number of legs - -VAL: - STANDARD - -h, --help Skriver ut hjälpinformation - -v, --version Skriver ut versionsnummer - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs - -KOMMANDON: - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_ZH-HANS.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_ZH-HANS.verified.txt deleted file mode 100644 index bd380b1e4..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional.Output_ZH-HANS.verified.txt +++ /dev/null @@ -1,26 +0,0 @@ -描述: -The lion command - -用法: - myapp [LEGS] [选项] [命令] - -示例: - myapp 20 --alive - -参数: - The number of teeth the lion has - [LEGS] The number of legs - -选项: - 默认 - -h, --help 显示帮助信息 - -v, --version 显示版本信息 - -a, --alive Indicates whether or not the animal is alive - -n, --name - --agility 10 The agility between 0 and 100 - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs - -命令列表: - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_BoldHeadings.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_BoldHeadings.Output.verified.txt deleted file mode 100644 index 200809108..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_BoldHeadings.Output.verified.txt +++ /dev/null @@ -1,25 +0,0 @@ -[bold]DESCRIPTION:[/] -The lion command - -[bold]USAGE:[/] - myapp [][/] [][[LEGS]][/] [][[OPTIONS]][/] [][[COMMAND]][/] - -[bold]EXAMPLES:[/] - myapp []20 --alive[/] - -[bold]ARGUMENTS:[/] - [][/] The number of teeth the lion has - [][[LEGS]][/] The number of legs - -[]OPTIONS:[/] - []DEFAULT[/] - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -n, --name [][/] - --agility [][/] []10[/] The agility between 0 and 100 - -c [][/] The number of children the lion has - -d [][/] []Monday[/], []Thursday[/] The days the lion goes hunting - -w, --weight [][[WEIGHT]][/] The weight of the lion, in kgs - -[bold]COMMANDS:[/] - []giraffe[/] [][/] The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_Default.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_Default.Output.verified.txt deleted file mode 100644 index 863382794..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_Default.Output.verified.txt +++ /dev/null @@ -1,25 +0,0 @@ -[yellow]DESCRIPTION:[/] -The lion command - -[yellow]USAGE:[/] - myapp [aqua][/] [silver][[LEGS]][/] [grey][[OPTIONS]][/] [aqua][[COMMAND]][/] - -[yellow]EXAMPLES:[/] - myapp [grey]20 --alive[/] - -[yellow]ARGUMENTS:[/] - [silver][/] The number of teeth the lion has - [silver][[LEGS]][/] The number of legs - -[yellow]OPTIONS:[/] - [lime]DEFAULT[/] - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -n, --name [silver][/] - --agility [silver][/] [bold]10[/] The agility between 0 and 100 - -c [silver][/] The number of children the lion has - -d [silver][/] [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][/] The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_None.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_None.Output.verified.txt deleted file mode 100644 index 512508aa4..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args_Additional_Style_None.Output.verified.txt +++ /dev/null @@ -1,25 +0,0 @@ -[]DESCRIPTION:[/] -The lion command - -[]USAGE:[/] - myapp [][/] [][[LEGS]][/] [][[OPTIONS]][/] [][[COMMAND]][/] - -[]EXAMPLES:[/] - myapp []20 --alive[/] - -[]ARGUMENTS:[/] - [][/] The number of teeth the lion has - [][[LEGS]][/] The number of legs - -[]OPTIONS:[/] - []DEFAULT[/] - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -n, --name [][/] - --agility [][/] []10[/] The agility between 0 and 100 - -c [][/] The number of children the lion has - -d [][/] []Monday[/], []Thursday[/] The days the lion goes hunting - -w, --weight [][[WEIGHT]][/] The weight of the lion, in kgs - -[]COMMANDS:[/] - []giraffe[/] [][/] The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Description_No_Trailing_Period.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Description_No_Trailing_Period.Output.verified.txt deleted file mode 100644 index b38fc5acf..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Description_No_Trailing_Period.Output.verified.txt +++ /dev/null @@ -1,15 +0,0 @@ -DESCRIPTION: -The dog command. - -USAGE: - myapp dog [LEGS] [OPTIONS] - -ARGUMENTS: - - [LEGS] The number of legs. - -OPTIONS: - -h, --help Prints help information. - -a, --alive Indicates whether or not the animal is alive. - -n, --name - -g, --good-boy \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Hidden_Command_Options.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Hidden_Command_Options.Output.verified.txt deleted file mode 100644 index b96464bf4..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Hidden_Command_Options.Output.verified.txt +++ /dev/null @@ -1,9 +0,0 @@ -USAGE: - myapp [OPTIONS] - -ARGUMENTS: - Dummy argument FOO - -OPTIONS: - -h, --help Prints help information - --baz Dummy option BAZ \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Hidden_Commands.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Hidden_Commands.Output.verified.txt deleted file mode 100644 index 212276974..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Hidden_Commands.Output.verified.txt +++ /dev/null @@ -1,9 +0,0 @@ -USAGE: - myapp [OPTIONS] - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - dog The dog command - horse The horse command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Leaf.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Leaf.Output.verified.txt deleted file mode 100644 index 7f7ad2d33..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Leaf.Output.verified.txt +++ /dev/null @@ -1,15 +0,0 @@ -DESCRIPTION: -The lion command - -USAGE: - myapp cat [LEGS] lion [OPTIONS] - -ARGUMENTS: - The number of teeth the lion has - -OPTIONS: - DEFAULT - -h, --help Prints help information - -c The number of children the lion has - -d Monday, Thursday The days the lion goes hunting - -w, --weight [WEIGHT] The weight of the lion, in kgs \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/NoDescription.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/NoDescription.Output.verified.txt deleted file mode 100644 index 7e3e079cd..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/NoDescription.Output.verified.txt +++ /dev/null @@ -1,8 +0,0 @@ -USAGE: - myapp [OPTIONS] - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - bar \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/NoVersion.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/NoVersion.Output.verified.txt deleted file mode 100644 index 9a82776df..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/NoVersion.Output.verified.txt +++ /dev/null @@ -1,12 +0,0 @@ -USAGE: - myapp [QUX] [OPTIONS] - -ARGUMENTS: - - - - - [QUX] - -OPTIONS: - -h, --help Prints help information \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Required_Options.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Required_Options.Output.verified.txt deleted file mode 100644 index 0ac93aed9..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Required_Options.Output.verified.txt +++ /dev/null @@ -1,6 +0,0 @@ -USAGE: - myapp [OPTIONS] - -OPTIONS: - -h, --help Prints help information - --foo Foos the bars. Required \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Required_Options_No_Description.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Required_Options_No_Description.Output.verified.txt deleted file mode 100644 index 4f7fe31fb..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Required_Options_No_Description.Output.verified.txt +++ /dev/null @@ -1,6 +0,0 @@ -USAGE: - myapp [OPTIONS] - -OPTIONS: - -h, --help Prints help information - --foo Required \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root.Output.verified.txt deleted file mode 100644 index aa3dcc3bf..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root.Output.verified.txt +++ /dev/null @@ -1,10 +0,0 @@ -USAGE: - myapp [OPTIONS] - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - dog The dog command - horse The horse command - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root.QuestionMark.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root.QuestionMark.verified.txt deleted file mode 100644 index 0432fe41a..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root.QuestionMark.verified.txt +++ /dev/null @@ -1,10 +0,0 @@ -USAGE: - myapp [OPTIONS] - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - dog The dog command - horse The horse command - giraffe The giraffe command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Command.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Command.Output.verified.txt deleted file mode 100644 index a4d8d5104..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Command.Output.verified.txt +++ /dev/null @@ -1,17 +0,0 @@ -DESCRIPTION: -The horse command - -USAGE: - myapp horse [LEGS] [OPTIONS] - -ARGUMENTS: - [LEGS] The number of legs - -OPTIONS: - DEFAULT - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -n, --name - -d, --day - --file food.txt - --directory \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Command.QuestionMark.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Command.QuestionMark.verified.txt deleted file mode 100644 index 2fd292358..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Command.QuestionMark.verified.txt +++ /dev/null @@ -1,17 +0,0 @@ -DESCRIPTION: -The horse command - -USAGE: - myapp horse [LEGS] [OPTIONS] - -ARGUMENTS: - [LEGS] The number of legs - -OPTIONS: - DEFAULT - -h, --help Prints help information - -a, --alive Indicates whether or not the animal is alive - -n, --name - -d, --day - --file food.txt - --directory \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples.Output.verified.txt deleted file mode 100644 index 82ba4675d..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples.Output.verified.txt +++ /dev/null @@ -1,23 +0,0 @@ -USAGE: - myapp [OPTIONS] - -EXAMPLES: - myapp dog --name Rufus --age 12 --good-boy - myapp dog --name Luna - myapp dog --name Charlie - myapp dog --name Bella - myapp dog --name Daisy - myapp dog --name Milo - myapp horse --name Brutus - myapp horse --name Sugar --IsAlive false - myapp horse --name Cash - myapp horse --name Dakota - myapp horse --name Cisco - myapp horse --name Spirit - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - dog The dog command - horse The horse command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children.Output.verified.txt deleted file mode 100644 index e2b67c8a3..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children.Output.verified.txt +++ /dev/null @@ -1,16 +0,0 @@ -USAGE: - myapp [OPTIONS] - -EXAMPLES: - myapp dog --name Rufus --age 12 --good-boy - myapp dog --name Luna - myapp dog --name Charlie - myapp dog --name Bella - myapp dog --name Daisy - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - dog The dog command - horse The horse command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_Eight.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_Eight.Output.verified.txt deleted file mode 100644 index 7b486e1fe..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_Eight.Output.verified.txt +++ /dev/null @@ -1,19 +0,0 @@ -USAGE: - myapp [OPTIONS] - -EXAMPLES: - myapp dog --name Rufus --age 12 --good-boy - myapp dog --name Luna - myapp dog --name Charlie - myapp dog --name Bella - myapp dog --name Daisy - myapp dog --name Milo - myapp horse --name Brutus - myapp horse --name Sugar --IsAlive false - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - dog The dog command - horse The horse command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_None.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_None.Output.verified.txt deleted file mode 100644 index 212276974..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_None.Output.verified.txt +++ /dev/null @@ -1,9 +0,0 @@ -USAGE: - myapp [OPTIONS] - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - dog The dog command - horse The horse command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_Twelve.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_Twelve.Output.verified.txt deleted file mode 100644 index 82ba4675d..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Children_Twelve.Output.verified.txt +++ /dev/null @@ -1,23 +0,0 @@ -USAGE: - myapp [OPTIONS] - -EXAMPLES: - myapp dog --name Rufus --age 12 --good-boy - myapp dog --name Luna - myapp dog --name Charlie - myapp dog --name Bella - myapp dog --name Daisy - myapp dog --name Milo - myapp horse --name Brutus - myapp horse --name Sugar --IsAlive false - myapp horse --name Cash - myapp horse --name Dakota - myapp horse --name Cisco - myapp horse --name Spirit - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - dog The dog command - horse The horse command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs.Output.verified.txt deleted file mode 100644 index 088dd1b82..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs.Output.verified.txt +++ /dev/null @@ -1,15 +0,0 @@ -USAGE: - myapp [OPTIONS] - -EXAMPLES: - myapp animal dog --name Rufus --age 12 --good-boy - myapp animal dog --name Luna - myapp animal dog --name Charlie - myapp animal dog --name Bella - myapp animal dog --name Daisy - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - animal The animal command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_Eight.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_Eight.Output.verified.txt deleted file mode 100644 index e236c9b54..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_Eight.Output.verified.txt +++ /dev/null @@ -1,18 +0,0 @@ -USAGE: - myapp [OPTIONS] - -EXAMPLES: - myapp animal dog --name Rufus --age 12 --good-boy - myapp animal dog --name Luna - myapp animal dog --name Charlie - myapp animal dog --name Bella - myapp animal dog --name Daisy - myapp animal dog --name Milo - myapp animal horse --name Brutus - myapp animal horse --name Sugar --IsAlive false - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - animal The animal command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_None.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_None.Output.verified.txt deleted file mode 100644 index 75de3a148..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_None.Output.verified.txt +++ /dev/null @@ -1,8 +0,0 @@ -USAGE: - myapp [OPTIONS] - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - animal The animal command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_Twelve.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_Twelve.Output.verified.txt deleted file mode 100644 index b6b89b68a..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Root_Examples_Leafs_Twelve.Output.verified.txt +++ /dev/null @@ -1,22 +0,0 @@ -USAGE: - myapp [OPTIONS] - -EXAMPLES: - myapp animal dog --name Rufus --age 12 --good-boy - myapp animal dog --name Luna - myapp animal dog --name Charlie - myapp animal dog --name Bella - myapp animal dog --name Daisy - myapp animal dog --name Milo - myapp animal horse --name Brutus - myapp animal horse --name Sugar --IsAlive false - myapp animal horse --name Cash - myapp animal horse --name Dakota - myapp animal horse --name Cisco - myapp animal horse --name Spirit - -OPTIONS: - -h, --help Prints help information - -COMMANDS: - animal The animal command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Version.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Version.Output.verified.txt deleted file mode 100644 index a07a26663..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Help/Version.Output.verified.txt +++ /dev/null @@ -1,13 +0,0 @@ -USAGE: - myapp [QUX] [OPTIONS] - -ARGUMENTS: - - - - - [QUX] - -OPTIONS: - -h, --help Prints help information - -v, --version Prints version information \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/OpenCli/Generate.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/OpenCli/Generate.Output.verified.txt deleted file mode 100644 index 3cb036e00..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/OpenCli/Generate.Output.verified.txt +++ /dev/null @@ -1,190 +0,0 @@ -{ - "opencli": "0.1-draft", - "info": { - "title": "my-app", - "version": "1.2.3" - }, - "commands": [ - { - "name": "animals", - "commands": [ - { - "name": "cat", - "options": [ - { - "name": "--agility", - "required": false, - "arguments": [ - { - "name": "VALUE", - "required": true, - "arity": { - "minimum": 1, - "maximum": 1 - }, - "metadata": [ - { - "name": "ClrType", - "value": "System.Int32" - } - ] - } - ], - "description": "The agility between 0 and 100.", - "recursive": false, - "hidden": false - }, - { - "name": "--alive", - "required": false, - "aliases": [ - "--not-dead", - "-a" - ], - "description": "Indicates whether or not the animal is alive.", - "recursive": false, - "hidden": false - }, - { - "name": "--name", - "required": false, - "aliases": [ - "--pet-name", - "-n", - "-p" - ], - "arguments": [ - { - "name": "VALUE", - "required": true, - "arity": { - "minimum": 1, - "maximum": 1 - }, - "metadata": [ - { - "name": "ClrType", - "value": "System.String" - } - ] - } - ], - "recursive": false, - "hidden": false - } - ], - "arguments": [ - { - "name": "LEGS", - "required": false, - "arity": { - "minimum": 1, - "maximum": 1 - }, - "description": "The number of legs.", - "hidden": false, - "metadata": [ - { - "name": "ClrType", - "value": "System.Int32" - } - ] - } - ], - "hidden": false, - "examples": [] - }, - { - "name": "dog", - "options": [ - { - "name": "--alive", - "required": false, - "aliases": [ - "--not-dead", - "-a" - ], - "description": "Indicates whether or not the animal is alive.", - "recursive": false, - "hidden": false - }, - { - "name": "--good-boy", - "required": false, - "aliases": [ - "-g" - ], - "recursive": false, - "hidden": false - }, - { - "name": "--name", - "required": false, - "aliases": [ - "--pet-name", - "-n", - "-p" - ], - "arguments": [ - { - "name": "VALUE", - "required": true, - "arity": { - "minimum": 1, - "maximum": 1 - }, - "metadata": [ - { - "name": "ClrType", - "value": "System.String" - } - ] - } - ], - "recursive": false, - "hidden": false - } - ], - "arguments": [ - { - "name": "LEGS", - "required": false, - "arity": { - "minimum": 1, - "maximum": 1 - }, - "description": "The number of legs.", - "hidden": false, - "metadata": [ - { - "name": "ClrType", - "value": "System.Int32" - } - ] - }, - { - "name": "AGE", - "required": true, - "arity": { - "minimum": 1, - "maximum": 1 - }, - "hidden": false, - "metadata": [ - { - "name": "ClrType", - "value": "System.Int32" - } - ] - } - ], - "description": "The dog command.", - "hidden": false, - "examples": [] - } - ], - "hidden": false, - "examples": [] - } - ] -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/CannotAssignValueToFlag/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/CannotAssignValueToFlag/Test_1.Output.verified.txt deleted file mode 100644 index 609a7a654..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/CannotAssignValueToFlag/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Flags cannot be assigned a value. - - dog --alive=indeterminate foo - ^^^^^^^ Can't assign value \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/CannotAssignValueToFlag/Test_2.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/CannotAssignValueToFlag/Test_2.Output.verified.txt deleted file mode 100644 index 8027f610f..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Parsing/CannotAssignValueToFlag/Test_2.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Flags cannot be assigned a value. - - dog -a=indeterminate foo - ^^ Can't assign value \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_1.Output.verified.txt deleted file mode 100644 index e92f683de..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_1.Output.verified.txt +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - The number of legs. - - - - - - - - - - - - - - The dog command. - - - - - - - The horse command. - - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_10.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_10.Output.verified.txt deleted file mode 100644 index 2c89d04a7..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_10.Output.verified.txt +++ /dev/null @@ -1,26 +0,0 @@ - - - - - The dog command. - - - The number of legs. - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_2.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_2.Output.verified.txt deleted file mode 100644 index 29098b822..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_2.Output.verified.txt +++ /dev/null @@ -1,22 +0,0 @@ - - - - - The dog command. - - - The number of legs. - - - - - - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_3.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_3.Output.verified.txt deleted file mode 100644 index ffb491802..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_3.Output.verified.txt +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - The number of legs. - - - - - - - - - - The dog command. - - - - - - - The horse command. - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_4.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_4.Output.verified.txt deleted file mode 100644 index 07b9dcd35..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_4.Output.verified.txt +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - The number of legs. - - - - - - - - - - The dog command. - - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_6.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_6.Output.verified.txt deleted file mode 100644 index 92b2aba93..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_6.Output.verified.txt +++ /dev/null @@ -1,42 +0,0 @@ - - - - - The dog command. - - - The number of legs. - - - - - - - - - - - - The horse command. - - - The number of legs. - - - - - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_7.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_7.Output.verified.txt deleted file mode 100644 index 69699701d..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_7.Output.verified.txt +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - The number of legs. - - - - - - - - - - - - - - The horse command. - - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_8.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_8.Output.verified.txt deleted file mode 100644 index 5ccfbd01a..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_8.Output.verified.txt +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - The number of legs. - - - - - - - - - - The dog command. - - - - - - - The horse command. - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_9.Output.verified.txt b/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_9.Output.verified.txt deleted file mode 100644 index 7c2396bb0..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Expectations/Xml/Test_9.Output.verified.txt +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - The number of legs. - - - - - - - - - - The dog command. - - - - - - - The horse command. - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Properties/Usings.cs b/src/Tests/Spectre.Console.Cli.Tests/Properties/Usings.cs deleted file mode 100644 index 6b28670a5..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Properties/Usings.cs +++ /dev/null @@ -1,18 +0,0 @@ -global using System; -global using System.Collections.Generic; -global using System.ComponentModel; -global using System.Diagnostics.CodeAnalysis; -global using System.Globalization; -global using System.Linq; -global using System.Runtime.CompilerServices; -global using System.Threading; -global using System.Threading.Tasks; -global using Shouldly; -global using Spectre.Console.Cli; -global using Spectre.Console.Cli.Help; -global using Spectre.Console.Cli.Unsafe; -global using Spectre.Console.Testing; -global using Spectre.Console.Tests.Data; -global using VerifyTests; -global using VerifyXunit; -global using Xunit; \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Spectre.Console.Cli.Tests.csproj b/src/Tests/Spectre.Console.Cli.Tests/Spectre.Console.Cli.Tests.csproj deleted file mode 100644 index f8f1d8df7..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Spectre.Console.Cli.Tests.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - net9.0;net8.0 - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandArgumentAttributeTests.Rendering.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandArgumentAttributeTests.Rendering.cs deleted file mode 100644 index 6a5efde60..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandArgumentAttributeTests.Rendering.cs +++ /dev/null @@ -1,85 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli.Annotations; - -[ExpectationPath("Arguments")] -public sealed partial class CommandArgumentAttributeTests -{ - public sealed class ArgumentCannotContainOptions - { - public sealed class Settings : CommandSettings - { - [CommandArgument(0, "--foo ")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("ArgumentCannotContainOptions")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - return Verifier.Verify(result); - } - } - - public sealed class MultipleValuesAreNotSupported - { - public sealed class Settings : CommandSettings - { - [CommandArgument(0, " ")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("MultipleValuesAreNotSupported")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - return Verifier.Verify(result); - } - } - - public sealed class ValuesMustHaveName - { - public sealed class Settings : CommandSettings - { - [CommandArgument(0, "<>")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("ValuesMustHaveName")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - return Verifier.Verify(result); - } - } - - private static class Fixture - { - public static string Run(params string[] args) - where TSettings : CommandSettings - { - using (var writer = new TestConsole()) - { - var app = new CommandApp(); - app.Configure(c => c.ConfigureConsole(writer)); - app.Configure(c => c.AddCommand>("foo")); - app.Run(args); - - return writer.Output - .NormalizeLineEndings() - .TrimLines() - .Trim(); - } - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandArgumentAttributeTests.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandArgumentAttributeTests.cs deleted file mode 100644 index 6b39c1e6c..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandArgumentAttributeTests.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli.Annotations; - -public sealed partial class CommandArgumentAttributeTests -{ - [Fact] - public void Should_Not_Contain_Options() - { - // Given, When - var result = Record.Exception(() => new CommandArgumentAttribute(0, "--foo ")); - - // Then - result.ShouldNotBe(null); - result.ShouldBeOfType().And(exception => - exception.Message.ShouldBe("Arguments can not contain options.")); - } - - [Theory] - [InlineData(" ")] - [InlineData("[FOO] [BAR]")] - [InlineData("[FOO] ")] - [InlineData(" [BAR]")] - public void Should_Not_Contain_Multiple_Value_Names(string template) - { - // Given, When - var result = Record.Exception(() => new CommandArgumentAttribute(0, template)); - - // Then - result.ShouldNotBe(null); - result.ShouldBeOfType().And(exception => - exception.Message.ShouldBe("Multiple values are not supported.")); - } - - [Theory] - [InlineData("<>")] - [InlineData("[]")] - public void Should_Not_Contain_Empty_Value_Name(string template) - { - // Given, When - var result = Record.Exception(() => new CommandArgumentAttribute(0, template)); - - // Then - result.ShouldNotBe(null); - result.ShouldBeOfType().And(exception => - exception.Message.ShouldBe("Values without name are not allowed.")); - } - - [Theory] - [InlineData("", true)] - [InlineData("[FOO]", false)] - public void Should_Parse_Valid_Options(string template, bool required) - { - // Given, When - var result = new CommandArgumentAttribute(0, template); - - // Then - result.ValueName.ShouldBe("FOO"); - result.IsRequired.ShouldBe(required); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandOptionAttributeTests.Rendering.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandOptionAttributeTests.Rendering.cs deleted file mode 100644 index 5358993ff..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandOptionAttributeTests.Rendering.cs +++ /dev/null @@ -1,230 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli.Annotations; - -[ExpectationPath("Arguments")] -public sealed partial class CommandOptionAttributeTests -{ - public sealed class UnexpectedCharacter - { - public sealed class Settings : CommandSettings - { - [CommandOption(" $ ")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("UnexpectedCharacter")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - result.Exception.Message.ShouldBe("Encountered unexpected character '$'."); - return Verifier.Verify(result.Output); - } - } - - public sealed class UnterminatedValueName - { - public sealed class Settings : CommandSettings - { - [CommandOption("--foo|-f (); - - // Then - result.Exception.Message.ShouldBe("Encountered unterminated value name 'BAR'."); - return Verifier.Verify(result.Output); - } - } - - public sealed class OptionsMustHaveName - { - public sealed class Settings : CommandSettings - { - [CommandOption("--foo|-")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("OptionsMustHaveName")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - result.Exception.Message.ShouldBe("Options without name are not allowed."); - return Verifier.Verify(result.Output); - } - } - - public sealed class OptionNamesCannotStartWithDigit - { - public sealed class Settings : CommandSettings - { - [CommandOption("--1foo")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("OptionNamesCannotStartWithDigit")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - result.Exception.Message.ShouldBe("Option names cannot start with a digit."); - return Verifier.Verify(result.Output); - } - } - - public sealed class InvalidCharacterInOptionName - { - public sealed class Settings : CommandSettings - { - [CommandOption("--f$oo")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("InvalidCharacterInOptionName")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - result.Exception.Message.ShouldBe("Encountered invalid character '$' in option name."); - return Verifier.Verify(result.Output); - } - } - - public sealed class LongOptionMustHaveMoreThanOneCharacter - { - public sealed class Settings : CommandSettings - { - [CommandOption("--f")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("LongOptionMustHaveMoreThanOneCharacter")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - result.Exception.Message.ShouldBe("Long option names must consist of more than one character."); - return Verifier.Verify(result.Output); - } - } - - public sealed class ShortOptionMustOnlyBeOneCharacter - { - public sealed class Settings : CommandSettings - { - [CommandOption("--foo|-bar")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("ShortOptionMustOnlyBeOneCharacter")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - result.Exception.Message.ShouldBe("Short option names can not be longer than one character."); - return Verifier.Verify(result.Output); - } - } - - public sealed class MultipleOptionValuesAreNotSupported - { - public sealed class Settings : CommandSettings - { - [CommandOption("-f|--foo ")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("MultipleOptionValuesAreNotSupported")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - result.Exception.Message.ShouldBe("Multiple option values are not supported."); - return Verifier.Verify(result.Output); - } - } - - public sealed class InvalidCharacterInValueName - { - public sealed class Settings : CommandSettings - { - [CommandOption("-f|--foo ")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("InvalidCharacterInValueName")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - result.Exception.Message.ShouldBe("Encountered invalid character '$' in value name."); - return Verifier.Verify(result.Output); - } - } - - public sealed class MissingLongAndShortName - { - public sealed class Settings : CommandSettings - { - [CommandOption("")] - public string Foo { get; set; } - } - - [Fact] - [Expectation("MissingLongAndShortName")] - public Task Should_Return_Correct_Text() - { - // Given, When - var result = Fixture.Run(); - - // Then - result.Exception.Message.ShouldBe("No long or short name for option has been specified."); - return Verifier.Verify(result.Output); - } - } - - private static class Fixture - { - public static CommandAppFailure Run(params string[] args) - where TSettings : CommandSettings - { - var app = new CommandAppTester(); - app.Configure(c => - { - c.AddCommand>("foo"); - }); - - return app.RunAndCatch(args); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandOptionAttributeTests.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandOptionAttributeTests.cs deleted file mode 100644 index 778e152b0..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/Annotations/CommandOptionAttributeTests.cs +++ /dev/null @@ -1,214 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli.Annotations; - -public sealed partial class CommandOptionAttributeTests -{ - [Fact] - public void Should_Parse_Short_Name_Correctly() - { - // Given, When - var option = new CommandOptionAttribute("-o|--option "); - - // Then - option.ShortNames.ShouldContain("o"); - } - - [Fact] - public void Should_Parse_Long_Name_Correctly() - { - // Given, When - var option = new CommandOptionAttribute("-o|--option "); - - // Then - option.LongNames.ShouldContain("option"); - } - - [Theory] - [InlineData("", "VALUE")] - [InlineData("", "VALUE1")] - [InlineData("", "VALUE1|VALUE2")] - public void Should_Parse_Value_Correctly(string value, string expected) - { - // Given, When - var option = new CommandOptionAttribute($"-o|--option {value}"); - - // Then - option.ValueName.ShouldBe(expected); - } - - [Fact] - public void Should_Parse_Only_Short_Name() - { - // Given, When - var option = new CommandOptionAttribute("-o"); - - // Then - option.ShortNames.ShouldContain("o"); - } - - [Fact] - public void Should_Parse_Only_Long_Name() - { - // Given, When - var option = new CommandOptionAttribute("--option"); - - // Then - option.LongNames.ShouldContain("option"); - } - - [Theory] - [InlineData("")] - [InlineData("")] - public void Should_Throw_If_Template_Is_Empty(string value) - { - // Given, When - var option = Record.Exception(() => new CommandOptionAttribute(value)); - - // Then - option.ShouldBeOfType().And(e => - e.Message.ShouldBe("No long or short name for option has been specified.")); - } - - [Theory] - [InlineData("--bar|-foo")] - [InlineData("--bar|-f-b")] - public void Should_Throw_If_Short_Name_Is_Invalid(string value) - { - // Given, When - var option = Record.Exception(() => new CommandOptionAttribute(value)); - - // Then - option.ShouldBeOfType().And(e => - e.Message.ShouldBe("Short option names can not be longer than one character.")); - } - - [Theory] - [InlineData("--o")] - public void Should_Throw_If_Long_Name_Is_Invalid(string value) - { - // Given, When - var option = Record.Exception(() => new CommandOptionAttribute(value)); - - // Then - option.ShouldBeOfType().And(e => - e.Message.ShouldBe("Long option names must consist of more than one character.")); - } - - [Theory] - [InlineData("-")] - [InlineData("--")] - public void Should_Throw_If_Option_Have_No_Name(string template) - { - // Given, When - var option = Record.Exception(() => new CommandOptionAttribute(template)); - - // Then - option.ShouldBeOfType().And(e => - e.Message.ShouldBe("Options without name are not allowed.")); - } - - [Theory] - [InlineData("--foo|-foo[b", '[')] - [InlineData("--foo|-f€b", '€')] - [InlineData("--foo|-foo@b", '@')] - public void Should_Throw_If_Option_Contains_Invalid_Name(string template, char invalid) - { - // Given, When - var result = Record.Exception(() => new CommandOptionAttribute(template)); - - // Then - result.ShouldBeOfType().And(e => - { - e.Message.ShouldBe($"Encountered invalid character '{invalid}' in option name."); - e.Template.ShouldBe(template); - }); - } - - [Theory] - [InlineData("--foo ", "HELLO-WORLD")] - [InlineData("--foo ", "HELLO_WORLD")] - public void Should_Accept_Dash_And_Underscore_In_Value_Name(string template, string name) - { - // Given, When - var result = new CommandOptionAttribute(template); - - // Then - result.ValueName.ShouldBe(name); - } - - [Theory] - [InlineData("--foo|-1")] - public void Should_Throw_If_First_Letter_Of_An_Option_Name_Is_A_Digit(string template) - { - // Given, When - var result = Record.Exception(() => new CommandOptionAttribute(template)); - - // Then - result.ShouldBeOfType().And(e => - { - e.Message.ShouldBe("Option names cannot start with a digit."); - e.Template.ShouldBe(template); - }); - } - - [Fact] - public void Multiple_Short_Options_Are_Supported() - { - // Given, When - var result = new CommandOptionAttribute("-f|-b"); - - // Then - result.ShortNames.Count.ShouldBe(2); - result.ShortNames.ShouldContain("f"); - result.ShortNames.ShouldContain("b"); - } - - [Fact] - public void Multiple_Long_Options_Are_Supported() - { - // Given, When - var result = new CommandOptionAttribute("--foo|--bar"); - - // Then - result.LongNames.Count.ShouldBe(2); - result.LongNames.ShouldContain("foo"); - result.LongNames.ShouldContain("bar"); - } - - [Theory] - [InlineData("-f|--foo ")] - [InlineData("--foo|-f ")] - [InlineData(" --foo|-f")] - [InlineData(" -f|--foo")] - [InlineData("-f --foo")] - [InlineData("--foo -f")] - public void Template_Parts_Can_Appear_In_Any_Order(string template) - { - // Given, When - var result = new CommandOptionAttribute(template); - - // Then - result.LongNames.ShouldContain("foo"); - result.ShortNames.ShouldContain("f"); - result.ValueName.ShouldBe("BAR"); - } - - [Fact] - public void Is_Not_Hidden_From_Help_By_Default() - { - // Given, When - var result = new CommandOptionAttribute("--foo"); - - // Then - result.IsHidden.ShouldBeFalse(); - } - - [Fact] - public void Can_Indicate_That_It_Must_Be_Hidden_From_Help_Text() - { - // Given, When - var result = new CommandOptionAttribute("--foo") { IsHidden = true }; - - // Then - result.IsHidden.ShouldBeTrue(); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Async.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Async.cs deleted file mode 100644 index 892a3b31c..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Async.cs +++ /dev/null @@ -1,124 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class Async - { - [Fact] - public async Task Should_Execute_Command_Asynchronously() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = await app.RunAsync(); - - // Then - result.ExitCode.ShouldBe(0); - result.Output.ShouldBe("Finished executing asynchronously"); - } - - [Fact] - public async Task Should_Handle_Exception_Asynchronously() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand(); - - // When - var result = await app.RunAsync(new[] - { - "--ThrowException", - "true", - }); - - // Then - result.ExitCode.ShouldBe(-1); - } - - [Fact] - public async Task Should_Throw_Exception_Asynchronously() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var exception = await Record.ExceptionAsync(async () => - await app.RunAsync(new[] - { - "--ThrowException", - "true", - })); - - // Then - exception.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("Throwing exception asynchronously"); - }); - } - - [Fact] - public async Task Should_Throw_OperationCanceledException_When_Propagated_And_Cancelled() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var exception = await Record.ExceptionAsync(async () => - await app.RunAsync(cancellationToken: new CancellationToken(canceled: true))); - - // Then - exception.ShouldNotBeNull(); - exception.ShouldBeAssignableTo(); - } - - [Fact] - public async Task Should_Return_Default_Exit_Code_When_Cancelled() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand(); - - // When - var result = await app.RunAsync(cancellationToken: new CancellationToken(canceled: true)); - - // Then - result.ExitCode.ShouldBe(130); - result.Output.ShouldBeEmpty(); - } - - [Fact] - public async Task Should_Return_Custom_Exit_Code_When_Cancelled() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand(); - app.Configure(config => - { - config.CancellationExitCode(123); - }); - - // When - var result = await app.RunAsync(cancellationToken: new CancellationToken(canceled: true)); - - // Then - result.ExitCode.ShouldBe(123); - result.Output.ShouldBeEmpty(); - } - } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Branches.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Branches.cs deleted file mode 100644 index 9f51d80e2..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Branches.cs +++ /dev/null @@ -1,381 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class Branches - { - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Should_Run_The_Default_Command_On_Branch(bool strictParsing) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.Settings.StrictParsing = strictParsing; - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.SetDefaultCommand(); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType(); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Should_Throw_When_No_Default_Command_On_Branch(bool strictParsing) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.Settings.StrictParsing = strictParsing; - config.PropagateExceptions(); - config.AddBranch("animal", animal => { }); - }); - - // When - var result = Record.Exception(() => - { - app.Run(new[] - { - "animal", "4", - }); - }); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("The branch 'animal' does not define any commands."); - }); - } - - [Fact] - public void Should_Parse_Branch_And_Default_Command_Arguments_Relaxed_Parsing() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.SetDefaultCommand(); - }); - }); - - // When - var result = app.Run(new[] - { - // The CommandTreeParser should determine which command line arguments - // belong to the branch and which belong to the branch's default command. - "animal", "4", "-a", "false", "--name", "Kitty", "--agility", "four", "--nick-name", "Felix" - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(cat => - { - cat.IsAlive.ShouldBeFalse(); - cat.Legs.ShouldBe(4); - cat.Name.ShouldBe("Kitty"); - cat.Agility.ShouldBe(4); - }); - result.Context.Remaining.Parsed.Count.ShouldBe(1); - result.Context.ShouldHaveRemainingArgument("--nick-name", values: new[] { "Felix" }); - result.Context.Remaining.Raw.Count.ShouldBe(0); - } - - [Fact] - public void Should_Parse_Branch_And_Default_Command_Arguments_Strict_Parsing() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.UseStrictParsing(); - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.SetDefaultCommand(); - }); - }); - - // When - var result = app.Run(new[] - { - // The CommandTreeParser should determine which command line arguments - // belong to the branch and which belong to the branch's default command. - "animal", "4", "-a", "false", "--name", "Kitty", "--agility", "four", "--", "--nick-name", "Felix" - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(cat => - { - cat.IsAlive.ShouldBeFalse(); - cat.Legs.ShouldBe(4); - cat.Name.ShouldBe("Kitty"); - cat.Agility.ShouldBe(4); - }); - result.Context.Remaining.Parsed.Count.ShouldBe(1); - result.Context.ShouldHaveRemainingArgument("--nick-name", values: new[] { "Felix" }); - result.Context.Remaining.Raw.Count.ShouldBe(2); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Should_Run_The_Default_Command_On_Branch_On_Branch(bool strictParsing) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.Settings.StrictParsing = strictParsing; - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddBranch("mammal", mammal => - { - mammal.SetDefaultCommand(); - }); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "mammal", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType(); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Should_Run_The_Default_Command_On_Branch_On_Branch_With_Arguments(bool strictParsing) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.Settings.StrictParsing = strictParsing; - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddBranch("mammal", mammal => - { - mammal.SetDefaultCommand(); - }); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "mammal", "--name", "Kitty", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(cat => - { - cat.Legs.ShouldBe(4); - cat.Name.ShouldBe("Kitty"); - }); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Should_Run_The_Default_Command_Not_The_Named_Command_On_Branch(bool strictParsing) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.Settings.StrictParsing = strictParsing; - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - - animal.SetDefaultCommand(); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType(); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Should_Run_The_Named_Command_Not_The_Default_Command_On_Branch(bool strictParsing) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.Settings.StrictParsing = strictParsing; - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - - animal.SetDefaultCommand(); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", "--good-boy", "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Legs.ShouldBe(4); - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - }); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Should_Allow_Multiple_Branches_Multiple_Commands(bool strictParsing) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.Settings.StrictParsing = strictParsing; - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddBranch("mammal", mammal => - { - mammal.AddCommand("dog"); - mammal.AddCommand("cat"); - }); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "--alive", "mammal", "--name", - "Rufus", "dog", "12", "--good-boy", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - dog.IsAlive.ShouldBe(true); - }); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Should_Allow_Single_Branch_Multiple_Commands(bool strictParsing) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.Settings.StrictParsing = strictParsing; - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - animal.AddCommand("cat"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "dog", "12", "--good-boy", - "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - dog.IsAlive.ShouldBe(false); - }); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Should_Allow_Single_Branch_Single_Command(bool strictParsing) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.Settings.StrictParsing = strictParsing; - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", "--good-boy", - "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Legs.ShouldBe(4); - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.IsAlive.ShouldBe(false); - dog.Name.ShouldBe("Rufus"); - }); - } - } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Constructor.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Constructor.cs deleted file mode 100644 index 2385a01c5..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Constructor.cs +++ /dev/null @@ -1,104 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public class NullableSettings : CommandSettings - { - public NullableSettings(bool? detailed, string[] extra) - { - Detailed = detailed; - Extra = extra; - } - - [CommandOption("-d")] - public bool? Detailed { get; } - - [CommandArgument(0, "[extra]")] - public string[] Extra { get; } - } - - public class NullableWithInitSettings : CommandSettings - { - [CommandOption("-d")] - public bool? Detailed { get; init; } - - [CommandArgument(0, "[extra]")] - public string[] Extra { get; init; } - } - - public class NullableCommand : Command - { - public override int Execute(CommandContext context, NullableSettings settings, CancellationToken cancellationToken) => 0; - } - - public class NullableWithInitCommand : Command - { - public override int Execute(CommandContext context, NullableWithInitSettings settings, CancellationToken cancellationToken) => 0; - } - - [Fact] - public void Should_Populate_Nullable_Objects_In_Settings() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddCommand("null"); - }); - - // When - var result = fixture.Run("null"); - - // Then - result.Settings.ShouldBeOfType().And(settings => - { - settings.Detailed.ShouldBeNull(); - settings.Extra.ShouldBeNull(); - }); - } - - [Fact] - public void Should_Populate_Nullable_Objects_With_Init_In_Settings() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddCommand("null"); - }); - - // When - var result = fixture.Run("null"); - - // Then - result.Settings.ShouldBeOfType().And(settings => - { - settings.Detailed.ShouldBeNull(); - settings.Extra.ShouldBeNull(); - }); - } - - [Fact] - public void Should_Populate_Regular_Settings() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddCommand("null"); - }); - - // When - var result = fixture.Run("null", "-d", "true", "first-item"); - - // Then - result.Settings.ShouldBeOfType().And(settings => - { - settings.Detailed.ShouldBe(true); - settings.Extra.ShouldBe(new[] { "first-item" }); - }); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Context.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Context.cs deleted file mode 100644 index ec88fd135..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Context.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - [Fact] - [Expectation("Should_Expose_Raw_Arguments")] - public void Should_Return_Correct_Text_When_Command_Is_Unknown() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("test"); - }); - - // When - var result = app.Run("test", "--foo", "32", "--lol"); - - // Then - result.Context.ShouldNotBeNull(); - result.Context.Arguments.ShouldBe(new[] { "test", "--foo", "32", "--lol" }); - } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Exceptions.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Exceptions.cs deleted file mode 100644 index 77b48533d..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Exceptions.cs +++ /dev/null @@ -1,136 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class Exception_Handling - { - [Fact] - public void Should_Not_Propagate_Runtime_Exceptions_If_Not_Explicitly_Told_To_Do_So() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - animal.AddCommand("horse"); - }); - }); - - // When - var result = app.Run(new[] { "animal", "4", "dog", "101", "--name", "Rufus" }); - - // Then - result.ExitCode.ShouldBe(-1); - } - - [Fact] - public void Should_Not_Propagate_Exceptions_If_Not_Explicitly_Told_To_Do_So() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("throw"); - }); - - // When - var result = app.Run(new[] { "throw" }); - - // Then - result.ExitCode.ShouldBe(-1); - } - - [Fact] - public void Should_Handle_Exceptions_If_ExceptionHandler_Is_Set_Using_Action() - { - // Given - var exceptionHandled = false; - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("throw"); - config.SetExceptionHandler((_, _) => - { - exceptionHandled = true; - }); - }); - - // When - var result = app.Run(new[] { "throw" }); - - // Then - result.ExitCode.ShouldBe(-1); - exceptionHandled.ShouldBeTrue(); - } - - [Fact] - public void Should_Handle_Exceptions_If_ExceptionHandler_Is_Set_Using_Function() - { - // Given - var exceptionHandled = false; - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("throw"); - config.SetExceptionHandler((_, _) => - { - exceptionHandled = true; - return -99; - }); - }); - - // When - var result = app.Run(new[] { "throw" }); - - // Then - result.ExitCode.ShouldBe(-99); - exceptionHandled.ShouldBeTrue(); - } - - [Fact] - public void Should_Have_Resolver_Set_When_Exception_Occurs_In_Command_Execution() - { - // Given - ITypeResolver resolver = null; - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("throw"); - config.SetExceptionHandler((_, r) => - { - resolver = r; - }); - }); - - // When - app.Run(new[] { "throw" }); - - // Then - resolver.ShouldNotBeNull(); - } - - [Fact] - public void Should_Not_Have_Resolver_Set_When_Exception_Occurs_Before_Command_Execution() - { - // Given - ITypeResolver resolver = null; - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("Лайка"); - config.SetExceptionHandler((_, r) => - { - resolver = r; - }); - }); - - // When - app.Run(new[] { "throw", "on", "arg", "parsing" }); - - // Then - resolver.ShouldBeNull(); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.FlagValues.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.FlagValues.cs deleted file mode 100644 index 65745be31..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.FlagValues.cs +++ /dev/null @@ -1,214 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class FlagValues - { - [SuppressMessage("Performance", "CA1812", Justification = "It's OK")] - private sealed class FlagSettings : CommandSettings - { - [CommandOption("--serve [PORT]")] - public FlagValue Serve { get; set; } - } - - [SuppressMessage("Performance", "CA1812", Justification = "It's OK")] - private sealed class FlagSettingsWithNullableValueType : CommandSettings - { - [CommandOption("--serve [PORT]")] - public FlagValue Serve { get; set; } - } - - [SuppressMessage("Performance", "CA1812", Justification = "It's OK")] - private sealed class FlagSettingsWithOptionalOptionButNoFlagValue : CommandSettings - { - [CommandOption("--serve [PORT]")] - public int Serve { get; set; } - } - - [SuppressMessage("Performance", "CA1812", Justification = "It's OK")] - private sealed class FlagSettingsWithDefaultValue : CommandSettings - { - [CommandOption("--serve [PORT]")] - [DefaultValue(987)] - public FlagValue Serve { get; set; } - } - - [Fact] - public void Should_Throw_If_Command_Option_Value_Is_Optional_But_Type_Is_Not_A_Flag_Value() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("foo"); - }); - - // When - var result = Record.Exception(() => app.Run(new[] { "foo", "--serve", "123" })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("The option 'serve' has an optional value but does not implement IFlagValue."); - }); - } - - [Fact] - public void Should_Set_Flag_And_Value_If_Both_Were_Provided() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("foo"); - }); - - // When - var result = app.Run(new[] { "foo", "--serve", "123", }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(flag => - { - flag.Serve.IsSet.ShouldBeTrue(); - flag.Serve.Value.ShouldBe(123); - }); - } - - [Fact] - public void Should_Only_Set_Flag_If_No_Value_Was_Provided() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("foo"); - }); - - // When - var result = app.Run(new[] { "foo", "--serve" }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(flag => - { - flag.Serve.IsSet.ShouldBeTrue(); - flag.Serve.Value.ShouldBe(0); - }); - } - - [Fact] - public void Should_Set_Value_To_Default_Value_If_None_Was_Explicitly_Set() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("foo"); - }); - - // When - var result = app.Run(new[] { "foo", "--serve" }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(flag => - { - flag.Serve.IsSet.ShouldBeTrue(); - flag.Serve.Value.ShouldBe(987); - }); - } - - [Fact] - public void Should_Create_Unset_Instance_If_Flag_Was_Not_Set() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("foo"); - }); - - // When - var result = app.Run(new[] { "foo" }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(flag => - { - flag.Serve.IsSet.ShouldBeFalse(); - flag.Serve.Value.ShouldBe(0); - }); - } - - [Fact] - public void Should_Create_Unset_Instance_With_Null_For_Nullable_Value_Type_If_Flag_Was_Not_Set() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("foo"); - }); - - // When - var result = app.Run(new[] { "foo" }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(flag => - { - flag.Serve.IsSet.ShouldBeFalse(); - flag.Serve.Value.ShouldBeNull(); - }); - } - - [Theory] - [InlineData("Foo", true, "Set=True, Value=Foo")] - [InlineData("Bar", false, "Set=False, Value=Bar")] - public void Should_Return_Correct_String_Representation_From_ToString( - string value, - bool isSet, - string expected) - { - // Given - var flag = new FlagValue - { - Value = value, - IsSet = isSet, - }; - - // When - var result = flag.ToString(); - - // Then - result.ShouldBe(expected); - } - - [Theory] - [InlineData(true, "Set=True")] - [InlineData(false, "Set=False")] - public void Should_Return_Correct_String_Representation_From_ToString_If_Value_Is_Not_Set( - bool isSet, - string expected) - { - // Given - var flag = new FlagValue - { - IsSet = isSet, - }; - - // When - var result = flag.ToString(); - - // Then - result.ShouldBe(expected); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Help.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Help.cs deleted file mode 100644 index 81b434b1f..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Help.cs +++ /dev/null @@ -1,1103 +0,0 @@ -using Spectre.Console.Cli.Tests.Data.Help; - -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - [ExpectationPath("Help")] - public class Help - { - [Fact] - [Expectation("Root")] - public Task Should_Output_Root_Correctly() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddCommand("dog"); - configurator.AddCommand("horse"); - configurator.AddCommand("giraffe"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root", "QuestionMark")] - public Task Should_Output_Root_Correctly_QuestionMark() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddCommand("dog"); - configurator.AddCommand("horse"); - configurator.AddCommand("giraffe"); - }); - - // When - var result = fixture.Run("-?"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root_Command")] - public Task Should_Output_Root_Command_Correctly() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddCommand("dog"); - configurator.AddCommand("horse"); - configurator.AddCommand("giraffe"); - }); - - // When - var result = fixture.Run("horse", "--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root_Command", "QuestionMark")] - public Task Should_Output_Root_Command_Correctly_QuestionMark() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddCommand("dog"); - configurator.AddCommand("horse"); - configurator.AddCommand("giraffe"); - }); - - // When - var result = fixture.Run("horse", "-?"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Hidden_Commands")] - public Task Should_Skip_Hidden_Commands() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddCommand("dog"); - configurator.AddCommand("horse"); - configurator.AddCommand("giraffe") - .WithExample("giraffe", "123") - .IsHidden(); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Description_No_Trailing_Period")] - public Task Should_Not_Trim_Description_Trailing_Period() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddCommand("dog"); - configurator.AddCommand("horse"); - configurator.AddCommand("giraffe") - .WithExample("giraffe", "123") - .IsHidden(); - configurator.TrimTrailingPeriods(false); - }); - - // When - var result = fixture.Run("dog", "--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Branch")] - public Task Should_Output_Branch_Correctly() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddBranch("cat", animal => - { - animal.SetDescription("Contains settings for a cat."); - animal.AddCommand("lion"); - }); - }); - - // When - var result = fixture.Run("cat", "--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Branch_Called_Without_Help")] - public Task Should_Output_Branch_When_Called_Without_Help_Option() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddBranch("cat", animal => - { - animal.SetDescription("Contains settings for a cat."); - animal.AddCommand("lion"); - }); - }); - - // When - var result = fixture.Run("cat"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Branch_Default_Greeter")] - public Task Should_Output_Branch_With_Default_Correctly() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddBranch("branch", animal => - { - animal.SetDefaultCommand(); - animal.AddCommand("greeter"); - }); - }); - - // When - var result = fixture.Run("branch", "--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Command_Hide_Default")] - public Task Should_Not_Print_Default_Column() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddBranch("cat", animal => - { - animal.SetDescription("Contains settings for a cat."); - animal.AddCommand("lion"); - }); - configurator.HideOptionDefaultValues(); - }); - - // When - var result = fixture.Run("cat", "--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Leaf")] - public Task Should_Output_Leaf_Correctly() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddBranch("cat", animal => - { - animal.SetDescription("Contains settings for a cat."); - animal.AddCommand("lion"); - }); - }); - - // When - var result = fixture.Run("cat", "lion", "--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Default")] - public Task Should_Output_Default_Command_Correctly() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Default_Without_Args")] - public Task Should_Output_Default_Command_When_Command_Has_Required_Parameters_And_Is_Called_Without_Args() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - }); - - // When - var result = fixture.Run(); - - // Then - return Verifier.Verify(result.Output); - } - - [Theory] - [InlineData(null, "EN")] - [InlineData("", "EN")] - [InlineData("en", "EN")] - [InlineData("en-EN", "EN")] - [InlineData("fr", "FR")] - [InlineData("fr-FR", "FR")] - [InlineData("sv", "SV")] - [InlineData("sv-SE", "SV")] - [InlineData("de", "DE")] - [InlineData("de-DE", "DE")] - [InlineData("it", "IT")] - [InlineData("it-IT", "IT")] - [InlineData("ja", "JA")] - [InlineData("ja-JP", "JA")] - [InlineData("ko", "KO")] - [InlineData("ko-KR", "KO")] - [InlineData("pt", "PT")] - [InlineData("pt-BR", "PT")] - [InlineData("ru", "RU")] - [InlineData("ru-RU", "RU")] - [InlineData("zh-Hans", "ZH-HANS")] - [InlineData("zh-Hans-CN", "ZH-HANS")] - [Expectation("Default_Without_Args_Additional")] - public Task Should_Output_Default_Command_And_Additional_Commands_When_Default_Command_Has_Required_Parameters_And_Is_Called_Without_Args_Localised(string culture, string expectationPrefix) - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - fixture.Configure(configurator => - { - configurator.AddExample("20", "--alive"); - configurator.SetApplicationCulture(string.IsNullOrEmpty(culture) ? null : new CultureInfo(culture)); - configurator.SetApplicationName("myapp"); - configurator.SetApplicationVersion("1.0.0"); - configurator.AddCommand("giraffe"); - }); - - // When - var result = fixture.Run(); - - // Then - var settings = new VerifySettings(); - settings.DisableRequireUniquePrefix(); - 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(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp") - .SetHelpProvider(new RenderMarkupHelpProvider(configurator.Settings)) - .AddExample("20", "--alive") - .AddCommand("giraffe"); - }); - - // 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(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddExample("20", "--alive"); - configurator.AddCommand("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(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddExample("20", "--alive"); - configurator.AddCommand("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() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - }); - - // When - var result = fixture.Run(); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Custom_Help_Registered_By_Instance")] - public Task Should_Output_Custom_Help_When_Registered_By_Instance() - { - var registrar = new DefaultTypeRegistrar(); - - // Given - var fixture = new CommandAppTester(registrar); - fixture.Configure(configurator => - { - // Create the custom help provider - var helpProvider = new CustomHelpProvider(configurator.Settings, "1.0"); - - // Register the custom help provider instance - registrar.RegisterInstance(typeof(IHelpProvider), helpProvider); - - configurator.SetApplicationName("myapp"); - configurator.AddCommand("dog"); - }); - - // When - var result = fixture.Run(); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Custom_Help_Registered_By_Type")] - public Task Should_Output_Custom_Help_When_Registered_By_Type() - { - var registrar = new DefaultTypeRegistrar(); - - // Given - var fixture = new CommandAppTester(registrar); - fixture.Configure(configurator => - { - // Register the custom help provider type - registrar.Register(typeof(IHelpProvider), typeof(RedirectHelpProvider)); - - configurator.SetApplicationName("myapp"); - configurator.AddCommand("dog"); - }); - - // When - var result = fixture.Run(); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Custom_Help_Configured_By_Instance")] - public Task Should_Output_Custom_Help_When_Configured_By_Instance() - { - var registrar = new DefaultTypeRegistrar(); - - // Given - var fixture = new CommandAppTester(registrar); - fixture.Configure(configurator => - { - // Configure the custom help provider instance - configurator.SetHelpProvider(new CustomHelpProvider(configurator.Settings, "1.0")); - - configurator.SetApplicationName("myapp"); - configurator.AddCommand("dog"); - }); - - // When - var result = fixture.Run(); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Custom_Help_Configured_By_Type")] - public Task Should_Output_Custom_Help_When_Configured_By_Type() - { - var registrar = new DefaultTypeRegistrar(); - - // Given - var fixture = new CommandAppTester(registrar); - fixture.Configure(configurator => - { - // Configure the custom help provider type - configurator.SetHelpProvider() - .SetApplicationName("myapp") - .AddCommand("dog"); - }); - - // When - var result = fixture.Run(); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root_Examples")] - public Task Should_Output_Examples_Defined_On_Root() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - - // All root examples should be shown - configurator.AddExample("dog", "--name", "Rufus", "--age", "12", "--good-boy"); - configurator.AddExample("dog", "--name", "Luna"); - configurator.AddExample("dog", "--name", "Charlie"); - configurator.AddExample("dog", "--name", "Bella"); - configurator.AddExample("dog", "--name", "Daisy"); - configurator.AddExample("dog", "--name", "Milo"); - configurator.AddExample("horse", "--name", "Brutus"); - configurator.AddExample("horse", "--name", "Sugar", "--IsAlive", "false"); - configurator.AddExample("horse", "--name", "Cash"); - configurator.AddExample("horse", "--name", "Dakota"); - configurator.AddExample("horse", "--name", "Cisco"); - configurator.AddExample("horse", "--name", "Spirit"); - - configurator.AddCommand("dog"); - configurator.AddCommand("horse"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root_Examples_Children")] - [SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1512:SingleLineCommentsMustNotBeFollowedByBlankLine", Justification = "Single line comment is relevant to several code blocks that follow.")] - public Task Should_Output_Examples_Defined_On_Direct_Children_If_Root_Has_No_Examples() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - - // It should be capped to the first 5 examples by default - - configurator.AddCommand("dog") - .WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy") - .WithExample("dog", "--name", "Luna") - .WithExample("dog", "--name", "Charlie") - .WithExample("dog", "--name", "Bella") - .WithExample("dog", "--name", "Daisy") - .WithExample("dog", "--name", "Milo"); - - configurator.AddCommand("horse") - .WithExample("horse", "--name", "Brutus") - .WithExample("horse", "--name", "Sugar", "--IsAlive", "false") - .WithExample("horse", "--name", "Cash") - .WithExample("horse", "--name", "Dakota") - .WithExample("horse", "--name", "Cisco") - .WithExample("horse", "--name", "Spirit"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root_Examples_Children_Eight")] - public Task Should_Output_Eight_Examples_Defined_On_Direct_Children_If_Root_Has_No_Examples() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - - // Show the first 8 examples defined on the direct children - configurator.Settings.MaximumIndirectExamples = 8; - - configurator.AddCommand("dog") - .WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy") - .WithExample("dog", "--name", "Luna") - .WithExample("dog", "--name", "Charlie") - .WithExample("dog", "--name", "Bella") - .WithExample("dog", "--name", "Daisy") - .WithExample("dog", "--name", "Milo"); - - configurator.AddCommand("horse") - .WithExample("horse", "--name", "Brutus") - .WithExample("horse", "--name", "Sugar", "--IsAlive", "false") - .WithExample("horse", "--name", "Cash") - .WithExample("horse", "--name", "Dakota") - .WithExample("horse", "--name", "Cisco") - .WithExample("horse", "--name", "Spirit"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root_Examples_Children_Twelve")] - public Task Should_Output_All_Examples_Defined_On_Direct_Children_If_Root_Has_No_Examples() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - - // Show all examples defined on the direct children - configurator.Settings.MaximumIndirectExamples = int.MaxValue; - - configurator.AddCommand("dog") - .WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy") - .WithExample("dog", "--name", "Luna") - .WithExample("dog", "--name", "Charlie") - .WithExample("dog", "--name", "Bella") - .WithExample("dog", "--name", "Daisy") - .WithExample("dog", "--name", "Milo"); - - configurator.AddCommand("horse") - .WithExample("horse", "--name", "Brutus") - .WithExample("horse", "--name", "Sugar", "--IsAlive", "false") - .WithExample("horse", "--name", "Cash") - .WithExample("horse", "--name", "Dakota") - .WithExample("horse", "--name", "Cisco") - .WithExample("horse", "--name", "Spirit"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root_Examples_Children_None")] - public Task Should_Not_Output_Examples_Defined_On_Direct_Children_If_Root_Has_No_Examples() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - - // Do not show examples defined on the direct children - configurator.Settings.MaximumIndirectExamples = 0; - - configurator.AddCommand("dog") - .WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy") - .WithExample("dog", "--name", "Luna") - .WithExample("dog", "--name", "Charlie") - .WithExample("dog", "--name", "Bella") - .WithExample("dog", "--name", "Daisy") - .WithExample("dog", "--name", "Milo"); - - configurator.AddCommand("horse") - .WithExample("horse", "--name", "Brutus") - .WithExample("horse", "--name", "Sugar", "--IsAlive", "false") - .WithExample("horse", "--name", "Cash") - .WithExample("horse", "--name", "Dakota") - .WithExample("horse", "--name", "Cisco") - .WithExample("horse", "--name", "Spirit"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root_Examples_Leafs")] - [SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1512:SingleLineCommentsMustNotBeFollowedByBlankLine", Justification = "Single line comment is relevant to several code blocks that follow.")] - public Task Should_Output_Examples_Defined_On_Leaves_If_No_Other_Examples_Are_Found() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddBranch("animal", animal => - { - animal.SetDescription("The animal command."); - - // It should be capped to the first 5 examples by default - - animal.AddCommand("dog") - .WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy") - .WithExample("animal", "dog", "--name", "Luna") - .WithExample("animal", "dog", "--name", "Charlie") - .WithExample("animal", "dog", "--name", "Bella") - .WithExample("animal", "dog", "--name", "Daisy") - .WithExample("animal", "dog", "--name", "Milo"); - - animal.AddCommand("horse") - .WithExample("animal", "horse", "--name", "Brutus") - .WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false") - .WithExample("animal", "horse", "--name", "Cash") - .WithExample("animal", "horse", "--name", "Dakota") - .WithExample("animal", "horse", "--name", "Cisco") - .WithExample("animal", "horse", "--name", "Spirit"); - }); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root_Examples_Leafs_Eight")] - public Task Should_Output_Eight_Examples_Defined_On_Leaves_If_No_Other_Examples_Are_Found() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddBranch("animal", animal => - { - animal.SetDescription("The animal command."); - - // Show the first 8 examples defined on the direct children - configurator.Settings.MaximumIndirectExamples = 8; - - animal.AddCommand("dog") - .WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy") - .WithExample("animal", "dog", "--name", "Luna") - .WithExample("animal", "dog", "--name", "Charlie") - .WithExample("animal", "dog", "--name", "Bella") - .WithExample("animal", "dog", "--name", "Daisy") - .WithExample("animal", "dog", "--name", "Milo"); - - animal.AddCommand("horse") - .WithExample("animal", "horse", "--name", "Brutus") - .WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false") - .WithExample("animal", "horse", "--name", "Cash") - .WithExample("animal", "horse", "--name", "Dakota") - .WithExample("animal", "horse", "--name", "Cisco") - .WithExample("animal", "horse", "--name", "Spirit"); - }); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root_Examples_Leafs_Twelve")] - public Task Should_Output_All_Examples_Defined_On_Leaves_If_No_Other_Examples_Are_Found() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddBranch("animal", animal => - { - animal.SetDescription("The animal command."); - - // Show all examples defined on the direct children - configurator.Settings.MaximumIndirectExamples = int.MaxValue; - - animal.AddCommand("dog") - .WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy") - .WithExample("animal", "dog", "--name", "Luna") - .WithExample("animal", "dog", "--name", "Charlie") - .WithExample("animal", "dog", "--name", "Bella") - .WithExample("animal", "dog", "--name", "Daisy") - .WithExample("animal", "dog", "--name", "Milo"); - - animal.AddCommand("horse") - .WithExample("animal", "horse", "--name", "Brutus") - .WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false") - .WithExample("animal", "horse", "--name", "Cash") - .WithExample("animal", "horse", "--name", "Dakota") - .WithExample("animal", "horse", "--name", "Cisco") - .WithExample("animal", "horse", "--name", "Spirit"); - }); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Root_Examples_Leafs_None")] - public Task Should_Not_Output_Examples_Defined_On_Leaves_If_No_Other_Examples_Are_Found() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddBranch("animal", animal => - { - animal.SetDescription("The animal command."); - - // Do not show examples defined on the direct children - configurator.Settings.MaximumIndirectExamples = 0; - - animal.AddCommand("dog") - .WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy") - .WithExample("animal", "dog", "--name", "Luna") - .WithExample("animal", "dog", "--name", "Charlie") - .WithExample("animal", "dog", "--name", "Bella") - .WithExample("animal", "dog", "--name", "Daisy") - .WithExample("animal", "dog", "--name", "Milo"); - - animal.AddCommand("horse") - .WithExample("animal", "horse", "--name", "Brutus") - .WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false") - .WithExample("animal", "horse", "--name", "Cash") - .WithExample("animal", "horse", "--name", "Dakota") - .WithExample("animal", "horse", "--name", "Cisco") - .WithExample("animal", "horse", "--name", "Spirit"); - }); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Branch_Examples")] - public Task Should_Output_Examples_Defined_On_Branch() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddBranch("animal", animal => - { - animal.SetDescription("The animal command."); - - // All branch examples should be shown - animal.AddExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy"); - animal.AddExample("animal", "dog", "--name", "Luna"); - animal.AddExample("animal", "dog", "--name", "Charlie"); - animal.AddExample("animal", "dog", "--name", "Bella"); - animal.AddExample("animal", "dog", "--name", "Daisy"); - animal.AddExample("animal", "dog", "--name", "Milo"); - animal.AddExample("animal", "horse", "--name", "Brutus"); - animal.AddExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false"); - animal.AddExample("animal", "horse", "--name", "Cash"); - animal.AddExample("animal", "horse", "--name", "Dakota"); - animal.AddExample("animal", "horse", "--name", "Cisco"); - animal.AddExample("animal", "horse", "--name", "Spirit"); - - animal.AddCommand("dog") - .WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy"); - animal.AddCommand("horse") - .WithExample("animal", "horse", "--name", "Brutus"); - }); - }); - - // When - var result = fixture.Run("animal", "--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Default_Examples")] - public Task Should_Output_Examples_Defined_On_Root_If_Default_Command_Is_Specified() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - - // All root examples should be shown - configurator.AddExample("--name", "Rufus", "--age", "12", "--good-boy") - .AddExample("--name", "Luna") - .AddExample("--name", "Charlie") - .AddExample("--name", "Bella") - .AddExample("--name", "Daisy") - .AddExample("--name", "Milo"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("NoDescription")] - public Task Should_Not_Show_Truncated_Command_Table_If_Commands_Are_Missing_Description() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - configurator.AddCommand("bar"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("ArgumentOrder")] - public Task Should_List_Arguments_In_Correct_Order() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand>(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("NoVersion")] - public Task Should_Not_Include_Application_Version_If_Not_Set() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand>(); - fixture.Configure(config => - { - config.SetApplicationName("myapp"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Version")] - public Task Should_Include_Application_Version_If_Set() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand>(); - fixture.Configure(config => - { - config.SetApplicationName("myapp"); - config.SetApplicationVersion("0.49.1"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Hidden_Command_Options")] - public Task Should_Not_Show_Hidden_Command_Options() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand>(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Required_Options")] - public Task Should_Show_Required_Options() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand>(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Required_Options_No_Description")] - public Task Should_Show_Required_Options_Without_Description() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand>(); - fixture.Configure(configurator => - { - configurator.SetApplicationName("myapp"); - }); - - // When - var result = fixture.Run("--help"); - - // Then - return Verifier.Verify(result.Output); - } - } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.Settings.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.Settings.cs deleted file mode 100644 index b151cce2e..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.Settings.cs +++ /dev/null @@ -1,116 +0,0 @@ -#nullable enable - -using Microsoft.Extensions.DependencyInjection; - -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed partial class Injection - { - public sealed class Settings - { - public sealed class CustomInheritedCommand : Command - { - private readonly SomeFakeDependency _dep; - - public CustomInheritedCommand(SomeFakeDependency dep) - { - _dep = dep; - } - - public override int Execute(CommandContext context, CustomInheritedCommandSettings settings, CancellationToken cancellationToken) - { - return 0; - } - } - - public sealed class SomeFakeDependency - { - } - - public abstract class CustomBaseCommandSettings : CommandSettings - { - } - - public sealed class CustomInheritedCommandSettings : CustomBaseCommandSettings - { - } - - private sealed class CustomTypeRegistrar : ITypeRegistrar - { - private readonly IServiceCollection _services; - - public CustomTypeRegistrar(IServiceCollection services) - { - _services = services; - } - - public ITypeResolver Build() - { - return new CustomTypeResolver(_services.BuildServiceProvider()); - } - - public void Register(Type service, Type implementation) - { - _services.AddSingleton(service, implementation); - } - - public void RegisterInstance(Type service, object implementation) - { - _services.AddSingleton(service, implementation); - } - - public void RegisterLazy(Type service, Func func) - { - _services.AddSingleton(service, provider => func()); - } - } - - public sealed class CustomTypeResolver : ITypeResolver - { - private readonly IServiceProvider _provider; - - public CustomTypeResolver(IServiceProvider provider) - { - _provider = provider ?? throw new ArgumentNullException(nameof(provider)); - } - - public object? Resolve(Type? type) - { - ArgumentNullException.ThrowIfNull(type); - return _provider.GetRequiredService(type); - } - } - - [Fact] - public void Should_Inject_Settings() - { - static CustomTypeRegistrar BootstrapServices() - { - var services = new ServiceCollection(); - services.AddSingleton(); - return new CustomTypeRegistrar(services); - } - - // Given - var app = new CommandAppTester(BootstrapServices()); - - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("foo", b => - { - b.AddCommand("bar"); - }); - }); - - // When - var result = app.Run("foo", "bar"); - - // Then - result.ExitCode.ShouldBe(0); - } - } - } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.cs deleted file mode 100644 index 23ef6b72f..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Injection.cs +++ /dev/null @@ -1,94 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed partial class Injection - { - public sealed class FakeDependency - { - } - - public abstract class BaseInjectSettings : CommandSettings - { - } - - public sealed class InjectSettings : BaseInjectSettings - { - public FakeDependency Fake { get; set; } - - [CommandOption("--name ")] - public string Name { get; } - - [CommandOption("--age ")] - public int Age { get; set; } - - public InjectSettings(FakeDependency fake, string name) - { - Fake = fake; - Name = "Hello " + name; - } - } - - [Fact] - public void Should_Inject_Parameters() - { - // Given - var app = new CommandAppTester(); - var dependency = new FakeDependency(); - - app.SetDefaultCommand>(); - app.Configure(config => - { - config.Settings.Registrar.RegisterInstance(dependency); - config.PropagateExceptions(); - }); - - // When - var result = app.Run(new[] - { - "--name", "foo", - "--age", "35", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(injected => - { - injected.ShouldNotBeNull(); - injected.Fake.ShouldBeSameAs(dependency); - injected.Name.ShouldBe("Hello foo"); - injected.Age.ShouldBe(35); - }); - } - - [Fact] - public void Should_Inject_Dependency_Using_A_Given_Registrar() - { - // Given - var dependency = new FakeDependency(); - var registrar = new FakeTypeRegistrar(); - registrar.RegisterInstance(typeof(FakeDependency), dependency); - var app = new CommandAppTester(registrar); - - app.SetDefaultCommand>(); - app.Configure(config => config.PropagateExceptions()); - - // When - var result = app.Run(new[] - { - "--name", "foo", - "--age", "35", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(injected => - { - injected.ShouldNotBeNull(); - injected.Fake.ShouldBeSameAs(dependency); - injected.Name.ShouldBe("Hello foo"); - injected.Age.ShouldBe(35); - }); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Interceptor.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Interceptor.cs deleted file mode 100644 index 13ad0b9c8..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Interceptor.cs +++ /dev/null @@ -1,90 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class Interceptor - { - public sealed class NoCommand : Command - { - public sealed class Settings : CommandSettings - { - } - - public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken) - { - return 0; - } - } - - public sealed class MyInterceptor : ICommandInterceptor - { - private readonly Action _action; - - public MyInterceptor(Action action) - { - _action = action; - } - - public void Intercept(CommandContext context, CommandSettings settings) - { - _action(context, settings); - } - } - - public sealed class MyResultInterceptor : ICommandInterceptor - { - private readonly Func _function; - - public MyResultInterceptor(Func function) - { - _function = function; - } - - public void InterceptResult(CommandContext context, CommandSettings settings, ref int result) - { - result = _function(context, settings, result); - } - } - - [Fact] - public void Should_Run_The_Interceptor() - { - // Given - var count = 0; - var app = new CommandApp(); - var interceptor = new MyInterceptor((_, _) => - { - count += 1; - }); - app.Configure(config => config.SetInterceptor(interceptor)); - - // When - app.Run(Array.Empty()); - - // Then - count.ShouldBe(1); // to be sure - } - - [Fact] - public void Should_Run_The_ResultInterceptor() - { - // Given - var count = 0; - const int Expected = 123; - var app = new CommandApp(); - var interceptor = new MyResultInterceptor((_, _, _) => - { - count += 1; - return Expected; - }); - app.Configure(config => config.SetInterceptor(interceptor)); - - // When - var actual = app.Run(Array.Empty()); - - // Then - count.ShouldBe(1); - actual.ShouldBe(Expected); - } - } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.OpenCli.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.OpenCli.cs deleted file mode 100644 index 3baa327c0..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.OpenCli.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - [ExpectationPath("OpenCli")] - public sealed partial class OpenCli - { - [Fact] - [Expectation("Generate")] - public Task Should_Output_OpenCli_Description() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(config => - { - config.SetApplicationName("my-app"); - config.SetApplicationVersion("1.2.3"); - - config.AddBranch("animals", animals => - { - animals.AddCommand("dog"); - animals.AddCommand("cat"); - }); - }); - - // When - var result = fixture.Run(Constants.OpenCliOption); - - // Then - return Verifier.Verify(result.Output); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Options.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Options.cs deleted file mode 100644 index 4dde1d3fb..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Options.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class Options - { - [Fact] - public void Should_Throw_If_Required_Option_Is_Missing() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(config => - { - config.AddCommand>("test"); - config.PropagateExceptions(); - }); - - // When - var result = Record.Exception(() => fixture.Run("test")); - - // Then - result.ShouldBeOfType() - .And(ex => - ex.Message.ShouldBe("Command 'test' is missing required argument 'foo'.")); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Pairs.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Pairs.cs deleted file mode 100644 index 944891db1..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Pairs.cs +++ /dev/null @@ -1,316 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class Pairs - { - public sealed class AmbiguousSettings : CommandSettings - { - [CommandOption("--var ")] - [PairDeconstructor(typeof(StringIntDeconstructor))] - [TypeConverter(typeof(CatAgilityConverter))] - public ILookup Values { get; set; } - } - - public sealed class NotDeconstructableSettings : CommandSettings - { - [CommandOption("--var ")] - [PairDeconstructor(typeof(StringIntDeconstructor))] - public string Values { get; set; } - } - - public sealed class DefaultPairDeconstructorSettings : CommandSettings - { - [CommandOption("--var ")] - public IDictionary Values { get; set; } - } - - public sealed class DefaultPairDeconstructorEnumValueSettings : CommandSettings - { - [CommandOption("--var ")] - public IDictionary Values { get; set; } - } - - public sealed class LookupSettings : CommandSettings - { - [CommandOption("--var ")] - [PairDeconstructor(typeof(StringIntDeconstructor))] - public ILookup Values { get; set; } - } - - public sealed class DictionarySettings : CommandSettings - { - [CommandOption("--var ")] - [PairDeconstructor(typeof(StringIntDeconstructor))] - public IDictionary Values { get; set; } - } - - public sealed class ReadOnlyDictionarySettings : CommandSettings - { - [CommandOption("--var ")] - [PairDeconstructor(typeof(StringIntDeconstructor))] - public IReadOnlyDictionary Values { get; set; } - } - - public sealed class StringIntDeconstructor : PairDeconstructor - { - protected override (string Key, string Value) Deconstruct(string value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - var parts = value.Split(new[] { '=' }); - if (parts.Length != 2) - { - throw new InvalidOperationException("Could not parse pair"); - } - - return (parts[0], parts[1]); - } - } - - [Fact] - public void Should_Throw_If_Option_Has_Pair_Deconstructor_And_Type_Converter() - { - // Given - var app = new CommandApp>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = Record.Exception(() => app.Run(new[] - { - "--var", "foo=bar", - "--var", "foo=qux", - })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("The option 'var' is both marked as pair deconstructable and convertable."); - }); - } - - [Fact] - public void Should_Throw_If_Option_Has_Pair_Deconstructor_But_Type_Is_Not_Deconstructable() - { - // Given - var app = new CommandApp>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = Record.Exception(() => app.Run(new[] - { - "--var", "foo=bar", - "--var", "foo=qux", - })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("The option 'var' is marked as pair deconstructable, but the underlying type does not support that."); - }); - } - - [Fact] - public void Should_Map_Pairs_To_Pair_Deconstructable_Collection_Using_Default_Deconstructort() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(new[] - { - "--var", "foo=1", - "--var", "foo=3", - "--var", "bar=4", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(pair => - { - pair.Values.ShouldNotBeNull(); - pair.Values.Count.ShouldBe(2); - pair.Values["foo"].ShouldBe(3); - pair.Values["bar"].ShouldBe(4); - }); - } - - [Fact] - public void Should_Map_Pairs_With_Enum_Value_To_Pair_Deconstructable_Collection_Using_Default_Deconstructor() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(new[] - { - "--var", "foo=Monday", - "--var", "bar=Tuesday", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(pair => - { - pair.Values.ShouldNotBeNull(); - pair.Values.Count.ShouldBe(2); - pair.Values["foo"].ShouldBe(DayOfWeek.Monday); - pair.Values["bar"].ShouldBe(DayOfWeek.Tuesday); - }); - } - - [Theory] - [InlineData("foo=1=2", "Error: The value 'foo=1=2' is not in a correct format")] - [InlineData("foo=1=2=3", "Error: The value 'foo=1=2=3' is not in a correct format")] - public void Should_Throw_If_Value_Is_Not_In_A_Valid_Format_Using_Default_Deconstructor( - string input, string expected) - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - - // When - var result = app.Run(new[] - { - "--var", input, - }); - - // Then - result.ExitCode.ShouldBe(-1); - result.Output.ShouldBe(expected); - } - - [Fact] - public void Should_Map_Lookup_Values() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(new[] - { - "--var", "foo=bar", - "--var", "foo=qux", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(pair => - { - pair.Values.ShouldNotBeNull(); - pair.Values.Count.ShouldBe(1); - pair.Values["foo"].ToList().Count.ShouldBe(2); - }); - } - - [Fact] - public void Should_Map_Dictionary_Values() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(new[] - { - "--var", "foo=bar", - "--var", "baz=qux", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(pair => - { - pair.Values.ShouldNotBeNull(); - pair.Values.Count.ShouldBe(2); - pair.Values["foo"].ShouldBe("bar"); - pair.Values["baz"].ShouldBe("qux"); - }); - } - - [Fact] - public void Should_Map_Latest_Value_Of_Same_Key_When_Mapping_To_Dictionary() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(new[] - { - "--var", "foo=bar", - "--var", "foo=qux", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(pair => - { - pair.Values.ShouldNotBeNull(); - pair.Values.Count.ShouldBe(1); - pair.Values["foo"].ShouldBe("qux"); - }); - } - - [Fact] - public void Should_Map_ReadOnly_Dictionary_Values() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(new[] - { - "--var", "foo=bar", - "--var", "baz=qux", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(pair => - { - pair.Values.ShouldNotBeNull(); - pair.Values.Count.ShouldBe(2); - pair.Values["foo"].ShouldBe("bar"); - pair.Values["baz"].ShouldBe("qux"); - }); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Parsing.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Parsing.cs deleted file mode 100644 index d7f6fa078..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Parsing.cs +++ /dev/null @@ -1,600 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - [ExpectationPath("Parsing")] - public sealed class Parsing - { - [ExpectationPath("UnknownCommand")] - public sealed class UnknownCommand - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text_When_Command_Is_Unknown() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("dog"); - }); - - // When - var result = app.Run("cat", "14"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_2")] - public Task Should_Return_Correct_Text_For_Unknown_Command_When_Current_Command_Has_No_Arguments() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("empty"); - }); - - // When - var result = app.Run("empty", "other"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_3")] - public Task Should_Return_Correct_Text_With_Suggestion_When_Command_Followed_By_Argument_Is_Unknown_And_Distance_Is_Small() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddBranch("dog", a => - { - a.AddCommand("cat"); - }); - }); - - // When - var result = app.Run("dog", "bat", "14"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_4")] - public Task Should_Return_Correct_Text_With_Suggestion_When_Root_Command_Followed_By_Argument_Is_Unknown_And_Distance_Is_Small() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("cat"); - }); - - // When - var result = app.Run("bat", "14"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_5")] - public Task Should_Return_Correct_Text_With_Suggestion_And_No_Arguments_When_Root_Command_Is_Unknown_And_Distance_Is_Small() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.AddCommand>("cat"); - }); - - // When - var result = app.Run("bat"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_6")] - public Task Should_Return_Correct_Text_With_Suggestion_And_No_Arguments_When_Command_Is_Unknown_And_Distance_Is_Small() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(configurator => - { - configurator.AddBranch("dog", a => - { - a.AddCommand("cat"); - }); - }); - - // When - var result = app.Run("dog", "bat"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_7")] - public Task Should_Return_Correct_Text_With_Suggestion_When_Root_Command_After_Argument_Is_Unknown_And_Distance_Is_Small() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(configurator => - { - configurator.AddCommand>("bar"); - }); - - // When - var result = app.Run("qux", "bat"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_8")] - public Task Should_Return_Correct_Text_With_Suggestion_When_Command_After_Argument_Is_Unknown_And_Distance_Is_Small() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddBranch("foo", a => - { - a.AddCommand>("bar"); - }); - }); - - // When - var result = app.Run("foo", "qux", "bat"); - - // Then - return Verifier.Verify(result.Output); - } - } - - [ExpectationPath("CannotAssignValueToFlag")] - public sealed class CannotAssignValueToFlag - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text_For_Long_Option() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", "--alive=indeterminate", "foo"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_2")] - public Task Should_Return_Correct_Text_For_Short_Option() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", "-a=indeterminate", "foo"); - - // Then - return Verifier.Verify(result.Output); - } - } - - [ExpectationPath("NoValueForOption")] - public sealed class NoValueForOption - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text_For_Long_Option() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", "--name"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_2")] - public Task Should_Return_Correct_Text_For_Short_Option() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", "-n"); - - // Then - return Verifier.Verify(result.Output); - } - } - - [ExpectationPath("NoMatchingArgument")] - public sealed class NoMatchingArgument - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("giraffe"); - }); - - // When - var result = app.Run("giraffe", "foo", "bar", "baz"); - - // Then - return Verifier.Verify(result.Output); - } - } - - [ExpectationPath("UnexpectedOption")] - public sealed class UnexpectedOption - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text_For_Long_Option() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("--foo"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_2")] - public Task Should_Return_Correct_Text_For_Short_Option() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("-f"); - - // Then - return Verifier.Verify(result.Output); - } - } - - [ExpectationPath("UnknownOption")] - public sealed class UnknownOption - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text_For_Long_Option_If_Strict_Mode_Is_Enabled() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.UseStrictParsing(); - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", "--unknown"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_2")] - public Task Should_Return_Correct_Text_For_Short_Option_If_Strict_Mode_Is_Enabled() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.UseStrictParsing(); - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", "-u"); - - // Then - return Verifier.Verify(result.Output); - } - } - - [ExpectationPath("OptionWithoutName")] - public sealed class OptionWithoutName - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text_For_Short_Option() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", "-", " "); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_2")] - public Task Should_Return_Correct_Text_For_Missing_Long_Option_Value_With_Equality_Separator() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", $"--foo="); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_3")] - public Task Should_Return_Correct_Text_For_Missing_Long_Option_Value_With_Colon_Separator() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", $"--foo:"); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_4")] - public Task Should_Return_Correct_Text_For_Missing_Short_Option_Value_With_Equality_Separator() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", $"-f="); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_5")] - public Task Should_Return_Correct_Text_For_Missing_Short_Option_Value_With_Colon_Separator() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", $"-f:"); - - // Then - return Verifier.Verify(result.Output); - } - } - - [ExpectationPath("InvalidShortOptionName")] - public sealed class InvalidShortOptionName - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", $"-f0o"); - - // Then - return Verifier.Verify(result.Output); - } - } - - [ExpectationPath("LongOptionNameIsOneCharacter")] - public sealed class LongOptionNameIsOneCharacter - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", $"--f"); - - // Then - return Verifier.Verify(result.Output); - } - } - - [ExpectationPath("LongOptionNameIsMissing")] - public sealed class LongOptionNameIsMissing - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", $"-- "); - - // Then - return Verifier.Verify(result.Output); - } - } - - [ExpectationPath("LongOptionNameStartWithDigit")] - public sealed class LongOptionNameStartWithDigit - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", $"--1foo"); - - // Then - return Verifier.Verify(result.Output); - } - } - - [ExpectationPath("LongOptionNameContainSymbol")] - public sealed class LongOptionNameContainSymbol - { - [Fact] - [Expectation("Test_1")] - public Task Should_Return_Correct_Text() - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", $"--f€oo"); - - // Then - return Verifier.Verify(result.Output); - } - - [Theory] - [InlineData("--f-oo")] - [InlineData("--f-o-o")] - [InlineData("--f_oo")] - [InlineData("--f_o_o")] - public void Should_Allow_Special_Symbols_In_Name(string option) - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("dog"); - }); - - // When - var result = app.Run("dog", option); - - // Then - result.Output.ShouldBe("Error: Command 'dog' is missing required argument 'AGE'."); - } - } - - /// - /// -v or --version switches should result in the Version option being set - /// on VersionSettings, and then VersionCommand.Execute(...) being called - /// - [Theory] - [InlineData("-v")] - [InlineData("--version")] - public void Should_Run_Custom_Version_Command(string versionOption) - { - // Given - var app = new CommandAppTester(); - app.Configure(configurator => - { - configurator.AddCommand("CustomVersionCommand"); - }); - - // When - var result = app.Run("CustomVersionCommand", versionOption, "1.2.5"); - - // Then - result.Output.ShouldBe("VersionCommand ran, Version: 1.2.5"); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Remaining.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Remaining.cs deleted file mode 100644 index 19d855ae1..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Remaining.cs +++ /dev/null @@ -1,411 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class Remaining - { - [Fact] - public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Default_Command() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand(); - - // When - var result = app.Run("--felix"); - - // Then - result.Output.ShouldBe(string.Empty); - result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null }); - } - - [Fact] - public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Command() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("empty"); - }); - - // When - var result = app.Run("empty", "--felix"); - - // Then - result.Output.ShouldBe(string.Empty); - result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null }); - } - - [Fact] - public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Branch_Default_Command() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddBranch("branch", branch => - { - branch.SetDefaultCommand(); - }); - }); - - // When - var result = app.Run("branch", "--felix"); - - // Then - result.Output.ShouldBe(string.Empty); - result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null }); - } - - [Fact] - public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Branch_Command() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddBranch("branch", branch => - { - branch.AddCommand("hello"); - }); - }); - - // When - var result = app.Run("branch", "hello", "--felix"); - - // Then - result.Output.ShouldBe(string.Empty); - result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null }); - } - - [Fact] - public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Branch_Branch_Default_Command() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddBranch("branch", branch => - { - branch.AddBranch("hello", hello => - { - hello.SetDefaultCommand(); - }); - }); - }); - - // When - var result = app.Run("branch", "hello", "--felix"); - - // Then - result.Output.ShouldBe(string.Empty); - result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null }); - } - - [Fact] - public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Branch_Branch_Command() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddBranch("branch", branch => - { - branch.AddBranch("hello", hello => - { - hello.AddCommand("world"); - }); - }); - }); - - // When - var result = app.Run("branch", "hello", "world", "--felix"); - - // Then - result.Output.ShouldBe(string.Empty); - result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null }); - } - - [Theory] - [InlineData("-a")] - [InlineData("--alive")] - public void Should_Not_Add_Known_Flags_To_Remaining_Arguments_RelaxedParsing(string knownFlag) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] - { - "dog", "12", "4", - knownFlag, - }); - - // Then - result.Settings.ShouldBeOfType().And(dog => - { - dog.IsAlive.ShouldBe(true); - }); - - result.Context.Remaining.Parsed.Count.ShouldBe(0); - result.Context.Remaining.Raw.Count.ShouldBe(0); - } - - [Theory] - [InlineData("-r")] - [InlineData("--romeo")] - public void Should_Add_Unknown_Flags_To_Remaining_Arguments_RelaxedParsing(string unknownFlag) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] - { - "dog", "12", "4", - unknownFlag, - }); - - // Then - result.Context.Remaining.Parsed.Count.ShouldBe(1); - result.Context.ShouldHaveRemainingArgument(unknownFlag, values: new[] { (string)null }); - result.Context.Remaining.Raw.Count.ShouldBe(0); - } - - [Fact] - public void Should_Add_Unknown_Flags_When_Grouped_To_Remaining_Arguments_RelaxedParsing() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] - { - "dog", "12", "4", - "-agr", - }); - - // Then - result.Context.Remaining.Parsed.Count.ShouldBe(1); - result.Context.ShouldHaveRemainingArgument("-r", values: new[] { (string)null }); - result.Context.Remaining.Raw.Count.ShouldBe(0); - } - - [Theory] - [InlineData("-a")] - [InlineData("--alive")] - public void Should_Not_Add_Known_Flags_To_Remaining_Arguments_StrictParsing(string knownFlag) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.UseStrictParsing(); - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] - { - "dog", "12", "4", - knownFlag, - }); - - // Then - result.Context.Remaining.Parsed.Count.ShouldBe(0); - result.Context.Remaining.Raw.Count.ShouldBe(0); - } - - [Theory] - [InlineData("-r")] - [InlineData("--romeo")] - public void Should_Not_Add_Unknown_Flags_To_Remaining_Arguments_StrictParsing(string unknownFlag) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.UseStrictParsing(); - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = Record.Exception(() => app.Run(new[] - { - "dog", "12", "4", - unknownFlag, - })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe($"Unknown option '{unknownFlag.TrimStart('-')}'."); - }); - } - - [Fact] - public void Should_Not_Add_Unknown_Flags_When_Grouped_To_Remaining_Arguments_StrictParsing() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.UseStrictParsing(); - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = Record.Exception(() => app.Run(new[] - { - "dog", "12", "4", - "-agr", - })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe($"Unknown option 'r'."); - }); - } - - [Fact] - public void Should_Register_Remaining_Parsed_Arguments_With_Context() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", "--", - "--foo", "bar", "--foo", "baz", - "-bar", "\"baz\"", "qux", - "foo bar baz qux", - }); - - // Then - result.Context.Remaining.Parsed.Count.ShouldBe(4); - result.Context.ShouldHaveRemainingArgument("--foo", values: new[] { "bar", "baz" }); - result.Context.ShouldHaveRemainingArgument("-b", values: new[] { (string)null }); - result.Context.ShouldHaveRemainingArgument("-a", values: new[] { (string)null }); - result.Context.ShouldHaveRemainingArgument("-r", values: new[] { (string)null }); - } - - [Fact] - public void Should_Register_Remaining_Raw_Arguments_With_Context() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", "--", - "--foo", "bar", "-bar", "\"baz\"", "qux", - "foo bar baz qux", - }); - - // Then - result.Context.Remaining.Raw.Count.ShouldBe(6); - result.Context.Remaining.Raw[0].ShouldBe("--foo"); - result.Context.Remaining.Raw[1].ShouldBe("bar"); - result.Context.Remaining.Raw[2].ShouldBe("-bar"); - result.Context.Remaining.Raw[3].ShouldBe("\"baz\""); - result.Context.Remaining.Raw[4].ShouldBe("qux"); - result.Context.Remaining.Raw[5].ShouldBe("foo bar baz qux"); - } - - [Fact] - public void Should_Preserve_Quotes_Hyphen_Delimiters() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", "--", - "/c", "\"set && pause\"", - "Name=\" -Rufus --' ", - }); - - // Then - result.Context.Remaining.Raw.Count.ShouldBe(3); - result.Context.Remaining.Raw[0].ShouldBe("/c"); - result.Context.Remaining.Raw[1].ShouldBe("\"set && pause\""); - result.Context.Remaining.Raw[2].ShouldBe("Name=\" -Rufus --' "); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Should_Convert_Flags_To_Remaining_Arguments_If_Cannot_Be_Assigned(bool strictParsing) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.Settings.ConvertFlagsToRemainingArguments = true; - config.Settings.StrictParsing = strictParsing; - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] - { - "dog", "12", "4", - "--good-boy=Please be good Rufus!", - }); - - // Then - result.Context.Remaining.Parsed.Count.ShouldBe(1); - result.Context.ShouldHaveRemainingArgument("--good-boy", values: new[] { "Please be good Rufus!" }); - - result.Context.Remaining.Raw.Count.ShouldBe(0); // nb. there are no "raw" remaining arguments on the command line - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Sensitivity.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Sensitivity.cs deleted file mode 100644 index 7c819acb0..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Sensitivity.cs +++ /dev/null @@ -1,111 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - [Fact] - public void Should_Treat_Commands_As_Case_Sensitive_If_Specified() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.UseStrictParsing(); - config.PropagateExceptions(); - config.CaseSensitivity(CaseSensitivity.Commands); - config.AddCommand>("command"); - }); - - // When - var result = Record.Exception(() => app.Run(new[] - { - "Command", "--foo", "bar", - })); - - // Then - result.ShouldNotBeNull(); - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("Unknown command 'Command'."); - }); - } - - [Fact] - public void Should_Treat_Long_Options_As_Case_Sensitive_If_Specified() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.UseStrictParsing(); - config.PropagateExceptions(); - config.CaseSensitivity(CaseSensitivity.LongOptions); - config.AddCommand>("command"); - }); - - // When - var result = Record.Exception(() => app.Run(new[] - { - "command", "--Foo", "bar", - })); - - // Then - result.ShouldNotBeNull(); - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("Unknown option 'Foo'."); - }); - } - - [Fact] - public void Should_Treat_Short_Options_As_Case_Sensitive() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.UseStrictParsing(); - config.PropagateExceptions(); - config.AddCommand>("command"); - }); - - // When - var result = Record.Exception(() => app.Run(new[] - { - "command", "-F", "bar", - })); - - // Then - result.ShouldNotBeNull(); - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("Unknown option 'F'."); - }); - } - - [Fact] - public void Should_Suppress_Case_Sensitivity_If_Specified() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.UseStrictParsing(); - config.PropagateExceptions(); - config.CaseSensitivity(CaseSensitivity.None); - config.AddCommand>("command"); - }); - - // When - var result = app.Run(new[] - { - "Command", "--Foo", "bar", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(vec => - { - vec.Foo.ShouldBe("bar"); - }); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Settings.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Settings.cs deleted file mode 100644 index effeb16f3..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Settings.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - [Fact] - public void Should_Apply_Case_Sensitivity_For_Everything_By_Default() - { - // Given - var app = new CommandApp(); - - // When - var defaultSensitivity = CaseSensitivity.None; - app.Configure(config => - { - defaultSensitivity = config.Settings.CaseSensitivity; - }); - - // Then - defaultSensitivity.ShouldBe(CaseSensitivity.All); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.TypeConverters.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.TypeConverters.cs deleted file mode 100644 index 38a089247..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.TypeConverters.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.IO; - -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class TypeConverters - { - [Fact] - public void Should_Bind_Using_Custom_Type_Converter_If_Specified() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("cat"); - }); - - // When - var result = app.Run(new[] - { - "cat", "--name", "Tiger", - "--agility", "FOOBAR", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(cat => - { - cat.Agility.ShouldBe(6); - }); - } - - [Fact] - public void Should_Convert_Enum_Ignoring_Case() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("horse"); - }); - - // When - var result = app.Run(new[] { "horse", "--day", "friday" }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(horse => - { - horse.Day.ShouldBe(DayOfWeek.Friday); - }); - } - - [Fact] - public void Should_List_All_Valid_Enum_Values_On_Conversion_Error() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("horse"); - }); - - // When - var result = app.Run(new[] { "horse", "--day", "heimday" }); - - // Then - result.ExitCode.ShouldBe(-1); - result.Output.ShouldStartWith("Error"); - result.Output.ShouldContain("heimday"); - result.Output.ShouldContain(nameof(DayOfWeek.Sunday)); - result.Output.ShouldContain(nameof(DayOfWeek.Monday)); - result.Output.ShouldContain(nameof(DayOfWeek.Tuesday)); - result.Output.ShouldContain(nameof(DayOfWeek.Wednesday)); - result.Output.ShouldContain(nameof(DayOfWeek.Thursday)); - result.Output.ShouldContain(nameof(DayOfWeek.Friday)); - result.Output.ShouldContain(nameof(DayOfWeek.Saturday)); - } - - [Fact] - public void Should_Convert_FileInfo_And_DirectoryInfo() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.AddCommand("horse"); - }); - - // When - var result = app.Run(new[] { "horse", "--file", "ntp.conf", "--directory", "etc" }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(horse => - { - horse.File.Name.ShouldBe("ntp.conf"); - horse.Directory.Name.ShouldBe("etc"); - }); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Unsafe.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Unsafe.cs deleted file mode 100644 index 95f188677..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Unsafe.cs +++ /dev/null @@ -1,291 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class SafetyOff - { - [Fact] - public void Can_Mix_Safe_And_Unsafe_Configurators() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - - config.AddBranch("animal", animal => - { - animal.SafetyOff().AddBranch("mammal", typeof(MammalSettings), mammal => - { - mammal.AddCommand("dog", typeof(DogCommand)); - mammal.AddCommand("horse", typeof(HorseCommand)); - }); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "--alive", "mammal", "--name", - "Rufus", "dog", "12", "--good-boy", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - dog.IsAlive.ShouldBe(true); - }); - } - - [Fact] - public void Can_Turn_Safety_On_After_Turning_It_Off_For_Branch() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - - config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal => - { - animal.SafetyOn() - .AddBranch("mammal", mammal => - { - mammal.SafetyOff().AddCommand("dog", typeof(DogCommand)); - mammal.AddCommand("horse"); - }); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "--alive", "mammal", "--name", - "Rufus", "dog", "12", "--good-boy", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - dog.IsAlive.ShouldBe(true); - }); - } - - [Fact] - public void Should_Throw_If_Trying_To_Convert_Unsafe_Branch_Configurator_To_Safe_Version_With_Wrong_Type() - { - // Given - var app = new CommandApp(); - - // When - var result = Record.Exception(() => app.Configure(config => - { - config.PropagateExceptions(); - - config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal => - { - animal.SafetyOn().AddCommand("dog"); - }); - })); - - // Then - result.ShouldBeOfType(); - result.Message.ShouldBe("Configurator cannot be converted to a safe configurator of type 'MammalSettings'."); - } - - [Fact] - public void Should_Pass_Case_1() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - - config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal => - { - animal.AddBranch("mammal", typeof(MammalSettings), mammal => - { - mammal.AddCommand("dog", typeof(DogCommand)); - mammal.AddCommand("horse", typeof(HorseCommand)); - }); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "--alive", "mammal", "--name", - "Rufus", "dog", "12", "--good-boy", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - dog.IsAlive.ShouldBe(true); - }); - } - - [Fact] - public void Should_Pass_Case_2() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.SafetyOff().AddCommand("dog", typeof(DogCommand)); - }); - - // When - var result = app.Run(new[] - { - "dog", "12", "4", "--good-boy", - "--name", "Rufus", "--alive", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Legs.ShouldBe(12); - dog.Age.ShouldBe(4); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - dog.IsAlive.ShouldBe(true); - }); - } - - [Fact] - public void Should_Pass_Case_3() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal => - { - animal.AddCommand("dog", typeof(DogCommand)); - animal.AddCommand("horse", typeof(HorseCommand)); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "dog", "12", "--good-boy", - "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - dog.IsAlive.ShouldBe(false); - }); - } - - [Fact] - public void Should_Pass_Case_4() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal => - { - animal.AddCommand("dog", typeof(DogCommand)); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", - "--good-boy", "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Legs.ShouldBe(4); - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.IsAlive.ShouldBe(false); - dog.Name.ShouldBe("Rufus"); - }); - } - - [Fact] - public void Should_Pass_Case_5() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.SafetyOff().AddCommand("multi", typeof(OptionVectorCommand)); - }); - - // When - var result = app.Run(new[] - { - "multi", "--foo", "a", "--foo", "b", "--bar", "1", "--foo", "c", "--bar", "2", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(vec => - { - vec.Foo.Length.ShouldBe(3); - vec.Foo.ShouldBe(new[] { "a", "b", "c" }); - vec.Bar.Length.ShouldBe(2); - vec.Bar.ShouldBe(new[] { 1, 2 }); - }); - } - - [Fact] - public void Should_Pass_Case_6() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("multi"); - }); - - // When - var result = app.Run(new[] - { - "multi", "a", "b", "c", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(vec => - { - vec.Foo.Length.ShouldBe(3); - vec.Foo.ShouldBe(new[] { "a", "b", "c" }); - }); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Validation.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Validation.cs deleted file mode 100644 index 06eac9206..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Validation.cs +++ /dev/null @@ -1,106 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class Validation - { - [Fact] - public void Should_Throw_If_Attribute_Validation_Fails() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - animal.AddCommand("horse"); - }); - }); - - // When - var result = Record.Exception(() => app.Run(new[] { "animal", "3", "dog", "7", "--name", "Rufus" })); - - // Then - result.ShouldBeOfType().And(e => - { - e.Message.ShouldBe("Animals must have an even number of legs."); - }); - } - - [Fact] - public void Should_Throw_If_Settings_Validation_Fails() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - animal.AddCommand("horse"); - }); - }); - - // When - var result = Record.Exception(() => app.Run(new[] { "animal", "4", "dog", "7", "--name", "Tiger" })); - - // Then - result.ShouldBeOfType().And(e => - { - e.Message.ShouldBe("Tiger is not a dog name!"); - }); - } - - [Fact] - public void Should_Throw_If_Settings_Validation_Fails_On_Settings_With_ctor() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("turtle"); - }); - }); - - // When - var result = Record.Exception(() => app.Run(new[] { "animal", "4", "turtle", "--name", "Klaus" })); - - // Then - result.ShouldBeOfType().And(e => - { - e.Message.ShouldBe("Only 'Lonely George' is valid name for a turtle!"); - }); - } - - [Fact] - public void Should_Throw_If_Command_Validation_Fails() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - animal.AddCommand("horse"); - }); - }); - - // When - var result = Record.Exception(() => app.Run(new[] { "animal", "4", "dog", "101", "--name", "Rufus" })); - - // Then - result.ShouldBeOfType().And(e => - { - e.Message.ShouldBe("Dog is too old..."); - }); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.ValueProviders.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.ValueProviders.cs deleted file mode 100644 index 7f29e9e8e..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.ValueProviders.cs +++ /dev/null @@ -1,88 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class ValueProviders - { - public sealed class ValueProviderSettings : CommandSettings - { - [CommandOption("-f|--foo ")] - [IntegerValueProvider(32)] - [TypeConverter(typeof(HexConverter))] - public string Foo { get; set; } - } - - public sealed class IntegerValueProvider : ParameterValueProviderAttribute - { - private readonly int _value; - - public IntegerValueProvider(int value) - { - _value = value; - } - - public override bool TryGetValue(CommandParameterContext context, out object result) - { - if (context.Value == null) - { - result = _value; - return true; - } - - result = null; - return false; - } - } - - public sealed class HexConverter : TypeConverter - { - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is int integer) - { - return integer.ToString("X"); - } - - return value is string stringValue && int.TryParse(stringValue, out var intValue) - ? intValue.ToString("X") - : base.ConvertFrom(context, culture, value); - } - } - - [Fact] - public void Should_Use_Provided_Value_If_No_Value_Was_Specified() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => config.PropagateExceptions()); - - // When - var result = app.Run(); - - // Then - result.Settings.ShouldBeOfType().And(settings => - { - settings.Foo.ShouldBe("20"); // 32 is 0x20 - }); - } - - [Fact] - public void Should_Not_Override_Value_If_Value_Was_Specified() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => config.PropagateExceptions()); - - // When - var result = app.Run("--foo", "12"); - - // Then - result.Settings.ShouldBeOfType().And(settings => - { - settings.Foo.ShouldBe("C"); // 12 is 0xC - }); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Vectors.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Vectors.cs deleted file mode 100644 index f56d99064..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Vectors.cs +++ /dev/null @@ -1,104 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed class Vectors - { - [Fact] - public void Should_Throw_If_A_Single_Command_Has_Multiple_Argument_Vectors() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("multi"); - }); - - // When - var result = Record.Exception(() => app.Run(new[] { "multi", "a", "b", "c" })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("The command 'multi' specifies more than one vector argument."); - }); - } - - [Fact] - public void Should_Throw_If_An_Argument_Vector_Is_Not_Specified_Last() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("multi"); - }); - - // When - var result = Record.Exception(() => app.Run(new[] { "multi", "a", "b", "c" })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("The command 'multi' specifies an argument vector that is not the last argument."); - }); - } - - [Fact] - public void Should_Assign_Values_To_Argument_Vector() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("multi"); - }); - - // When - var result = app.Run(new[] - { - "multi", "a", "b", "c", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(vec => - { - vec.Foo.Length.ShouldBe(3); - vec.Foo[0].ShouldBe("a"); - vec.Foo[1].ShouldBe("b"); - vec.Foo[2].ShouldBe("c"); - }); - } - - [Fact] - public void Should_Assign_Values_To_Option_Vector() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("cmd"); - }); - - // When - var result = app.Run(new[] - { - "cmd", "--foo", "red", - "--bar", "4", "--foo", "blue", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(vec => - { - vec.Foo.ShouldBe(new string[] { "red", "blue" }); - vec.Bar.ShouldBe(new int[] { 4 }); - }); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.Help.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.Help.cs deleted file mode 100644 index b2cdec014..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.Help.cs +++ /dev/null @@ -1,236 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed partial class Version - { - public sealed class Help - { - [Theory] - [InlineData("-?")] - [InlineData("-h")] - [InlineData("--help")] - public void Help_Should_Include_Application_Version_Flag_With_No_Command(string helpOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - }); - - // When - var result = fixture.Run(helpOption); - - // Then - result.Output.ShouldContain("-v, --version Prints version information"); - } - - [Theory] - [InlineData("-?")] - [InlineData("-h")] - [InlineData("--help")] - public void Help_Should_Not_Include_Application_Version_Flag_If_Not_Specified(string helpOption) - { - // Given - var fixture = new CommandAppTester(); - - // When - var result = fixture.Run(helpOption); - - // Then - result.Output.ShouldNotContain("-v, --version Prints version information"); - } - - [Theory] - [InlineData("-?")] - [InlineData("-h")] - [InlineData("--help")] - public void Help_Should_Include_Application_Version_Flag_For_Default_Command(string helpOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - }); - - // When - var result = fixture.Run(helpOption); - - // Then - result.Output.ShouldContain("-v, --version Prints version information"); - } - - [Theory] - [InlineData("-?")] - [InlineData("-h")] - [InlineData("--help")] - public void Help_Should_Not_Include_Application_Version_Flag_For_Command(string helpOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - configurator.AddCommand("empty"); - }); - - // When - var result = fixture.Run("empty", helpOption); - - // Then - result.Output.ShouldNotContain("-v, --version Prints version information"); - } - - [Theory] - [InlineData("-?")] - [InlineData("-h")] - [InlineData("--help")] - public void Help_Should_Not_Include_Application_Version_Flag_For_Branch_Default_Command(string helpOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - configurator.AddBranch("branch", branch => - { - branch.SetDefaultCommand(); - }); - }); - - // When - var result = fixture.Run("branch", helpOption); - - // Then - result.Output.ShouldNotContain("-v, --version Prints version information"); - } - - [Theory] - [InlineData("-?")] - [InlineData("-h")] - [InlineData("--help")] - public void Help_Should_Not_Include_Application_Version_Flag_For_Branch_Command(string helpOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - configurator.AddBranch("branch", branch => - { - branch.AddCommand("empty"); - }); - }); - - // When - var result = fixture.Run("branch", "empty", helpOption); - - // Then - result.Output.ShouldNotContain("-v, --version Prints version information"); - } - - /// - /// When a command with a version flag in the settings is set as the application default command, - /// then override the in-built Application Version flag with the command version flag instead. - /// Rationale: This behaviour makes the most sense because the other flags for the default command - /// will be shown in the help output and the user can set any of these when executing the application. - /// - [Theory] - [InlineData("-?")] - [InlineData("-h")] - [InlineData("--help")] - public void Help_Should_Include_Command_Version_Flag_For_Default_Command(string helpOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - }); - - // When - var result = fixture.Run(helpOption); - - // Then - result.Output.ShouldContain("-v, --version The command version"); - result.Output.ShouldNotContain("-v, --version Prints version information"); - } - - [Theory] - [InlineData("-?")] - [InlineData("-h")] - [InlineData("--help")] - public void Help_Should_Include_Command_Version_Flag_For_Command(string helpOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - configurator.AddCommand("hello"); - }); - - // When - var result = fixture.Run("hello", helpOption); - - // Then - result.Output.ShouldContain("-v, --version The command version"); - result.Output.ShouldNotContain("-v, --version Prints version information"); - } - - [Theory] - [InlineData("-?")] - [InlineData("-h")] - [InlineData("--help")] - public void Help_Should_Include_Command_Version_Flag_For_Branch_Default_Command(string helpOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - configurator.AddBranch("branch", branch => - { - branch.SetDefaultCommand(); - }); - }); - - // When - var result = fixture.Run("branch", helpOption); - - // Then - result.Output.ShouldContain("-v, --version The command version"); - result.Output.ShouldNotContain("-v, --version Prints version information"); - } - - [Theory] - [InlineData("-?")] - [InlineData("-h")] - [InlineData("--help")] - public void Help_Should_Include_Command_Version_Flag_For_Branch_Command(string helpOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - configurator.AddBranch("branch", branch => - { - branch.AddCommand("hello"); - }); - }); - - // When - var result = fixture.Run("branch", "hello", helpOption); - - // Then - result.Output.ShouldContain("-v, --version The command version"); - result.Output.ShouldNotContain("-v, --version Prints version information"); - } - } - } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.cs deleted file mode 100644 index 8b2cb020e..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.cs +++ /dev/null @@ -1,290 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - public sealed partial class Version - { - [Theory] - [InlineData(false)] - [InlineData(true)] - public void Should_Output_CLI_Version_To_The_Console(bool strictParsing) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.Settings.StrictParsing = strictParsing; - }); - - // When - var result = fixture.Run(Constants.VersionCommand); - - // Then - result.Output.ShouldStartWith("Spectre.Cli version "); - } - - [Theory] - [InlineData("-v", false)] - [InlineData("-v", true)] - [InlineData("--version", false)] - [InlineData("--version", true)] - public void Should_Output_Application_Version_To_The_Console_With_No_Command(string versionOption, bool strictParsing) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.Settings.StrictParsing = strictParsing; - configurator.SetApplicationVersion("1.0"); - }); - - // When - var result = fixture.Run(versionOption); - - // Then - result.Output.ShouldBe("1.0"); - } - - [Theory] - [InlineData("-v", false)] - [InlineData("-v", true)] - [InlineData("--version", false)] - [InlineData("--version", true)] - public void Should_Not_Display_Version_If_Not_Specified(string versionOption, bool strictParsing) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.Settings.StrictParsing = strictParsing; - }); - - // When - var result = fixture.Run(versionOption); - - // Then - result.ExitCode.ShouldNotBe(0); - result.Output.ShouldStartWith($"Error: Unexpected option '{versionOption.Replace("-", "")}'"); - } - - [Theory] - [InlineData("-v", false)] - [InlineData("-v", true)] - [InlineData("--version", false)] - [InlineData("--version", true)] - public void Should_Output_Application_Version_To_The_Console_With_Default_Command(string versionOption, bool strictParsing) - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - fixture.Configure(configurator => - { - configurator.Settings.StrictParsing = strictParsing; - configurator.SetApplicationVersion("1.0"); - }); - - // When - var result = fixture.Run(versionOption); - - // Then - result.Output.ShouldBe("1.0"); - } - - [Theory] - [InlineData("-v")] - [InlineData("--version")] - public void Should_Execute_Command_Not_Output_Application_Version_To_The_Console_Relaxed_Parsing(string versionOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - configurator.AddCommand("empty"); - }); - - // When - var result = fixture.Run("empty", versionOption); - - // Then - result.Output.ShouldBe(string.Empty); - result.Context.ShouldHaveRemainingArgument(versionOption, new[] { (string)null }); - } - - [Theory] - [InlineData("-v", false)] - [InlineData("-v", true)] - [InlineData("--version", false)] - [InlineData("--version", true)] - public void Should_Output_Application_Version_To_The_Console_With_Branch_Default_Command(string versionOption, bool strictParsing) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.Settings.StrictParsing = strictParsing; - configurator.SetApplicationVersion("1.0"); - configurator.AddBranch("branch", branch => - { - branch.SetDefaultCommand(); - }); - }); - - // When - var result = fixture.Run(versionOption); - - // Then - result.Output.ShouldBe("1.0"); - } - - [Theory] - [InlineData("-v")] - [InlineData("--version")] - public void Should_Execute_Branch_Default_Command_Not_Output_Application_Version_To_The_Console_Relaxed_Parsing(string versionOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - configurator.AddBranch("branch", branch => - { - branch.SetDefaultCommand(); - }); - }); - - // When - var result = fixture.Run("branch", versionOption); - - // Then - result.Output.ShouldBe(string.Empty); - result.Context.ShouldHaveRemainingArgument(versionOption, new[] { (string)null }); - } - - [Theory] - [InlineData("-v")] - [InlineData("--version")] - public void Should_Execute_Branch_Command_Not_Output_Application_Version_To_The_Console_Relaxed_Parsing(string versionOption) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.SetApplicationVersion("1.0"); - configurator.AddBranch("branch", branch => - { - branch.AddCommand("empty"); - }); - }); - - // When - var result = fixture.Run("branch", "empty", versionOption); - - // Then - result.Output.ShouldBe(string.Empty); - result.Context.ShouldHaveRemainingArgument(versionOption, new[] { (string)null }); - } - - /// - /// When a command with a version option in the settings is set as the application default command, - /// then execute this command instead of displaying the explicitly set Application Version. - /// - [Theory] - [InlineData("-v", false)] - [InlineData("-v", true)] - [InlineData("--version", false)] - [InlineData("--version", true)] - public void Should_Execute_Default_VersionCommand_Not_Output_Application_Version_To_The_Console(string versionOption, bool strictParsing) - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - fixture.Configure(configurator => - { - configurator.Settings.StrictParsing = strictParsing; - configurator.SetApplicationVersion("1.0"); - }); - - // When - var result = fixture.Run(versionOption, "X.Y.Z"); - - // Then - result.Output.ShouldBe("VersionCommand ran, Version: X.Y.Z"); - } - - [Theory] - [InlineData("-v", false)] - [InlineData("-v", true)] - [InlineData("--version", false)] - [InlineData("--version", true)] - public void Should_Execute_VersionCommand_Not_Output_Application_Version_To_The_Console(string versionOption, bool strictParsing) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.Settings.StrictParsing = strictParsing; - configurator.SetApplicationVersion("1.0"); - configurator.AddCommand("hello"); - }); - - // When - var result = fixture.Run("hello", versionOption, "X.Y.Z"); - - // Then - result.Output.ShouldBe("VersionCommand ran, Version: X.Y.Z"); - } - - [Theory] - [InlineData("-v", false)] - [InlineData("-v", true)] - [InlineData("--version", false)] - [InlineData("--version", true)] - public void Should_Execute_Branch_Default_VersionCommand_Not_Output_Application_Version_To_The_Console(string versionOption, bool strictParsing) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.Settings.StrictParsing = strictParsing; - configurator.SetApplicationVersion("1.0"); - configurator.AddBranch("branch", branch => - { - branch.SetDefaultCommand(); - }); - }); - - // When - var result = fixture.Run("branch", versionOption, "X.Y.Z"); - - // Then - result.Output.ShouldBe("VersionCommand ran, Version: X.Y.Z"); - } - - [Theory] - [InlineData("-v", false)] - [InlineData("-v", true)] - [InlineData("--version", false)] - [InlineData("--version", true)] - public void Should_Execute_Branch_VersionCommand_Not_Output_Application_Version_To_The_Console(string versionOption, bool strictParsing) - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configurator => - { - configurator.Settings.StrictParsing = strictParsing; - configurator.SetApplicationVersion("1.0"); - configurator.AddBranch("branch", branch => - { - branch.AddCommand("hello"); - }); - }); - - // When - var result = fixture.Run("branch", "hello", versionOption, "X.Y.Z"); - - // Then - result.Output.ShouldBe("VersionCommand ran, Version: X.Y.Z"); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Xml.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Xml.cs deleted file mode 100644 index 8a6348b9e..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Xml.cs +++ /dev/null @@ -1,238 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - [ExpectationPath("Xml")] - public sealed class Xml - { - [Fact] - [Expectation("Test_1")] - public Task Should_Dump_Correct_Model_For_Case_1() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddBranch("mammal", mammal => - { - mammal.AddCommand("dog"); - mammal.AddCommand("horse"); - }); - }); - }); - - // When - var result = fixture.Run(Constants.XmlDocCommand); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_2")] - public Task Should_Dump_Correct_Model_For_Case_2() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(config => - { - config.AddCommand("dog"); - }); - - // When - var result = fixture.Run(Constants.XmlDocCommand); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_3")] - public Task Should_Dump_Correct_Model_For_Case_3() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(config => - { - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - animal.AddCommand("horse"); - }); - }); - - // When - var result = fixture.Run(Constants.XmlDocCommand); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_4")] - public Task Should_Dump_Correct_Model_For_Case_4() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(config => - { - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - }); - }); - - // When - var result = fixture.Run(Constants.XmlDocCommand); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_5")] - public Task Should_Dump_Correct_Model_For_Case_5() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(config => - { - config.AddCommand("cmd"); - }); - - // When - var result = fixture.Run(Constants.XmlDocCommand); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_10")] - public Task Should_Dump_Correct_Model_For_Case_6() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(config => - { - config.AddCommand("dog") - .WithExample("dog -g") - .WithExample("dog --good-boy"); - }); - - // When - var result = fixture.Run(Constants.XmlDocCommand); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_6")] - public Task Should_Dump_Correct_Model_For_Model_With_Default_Command() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - fixture.Configure(config => - { - config.AddCommand("horse"); - }); - - // When - var result = fixture.Run(Constants.XmlDocCommand); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_7")] - public Task Should_Dump_Correct_Model_For_Model_With_Single_Branch_Single_Branch_Default_Command() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configuration => - { - configuration.AddBranch("animal", animal => - { - animal.AddBranch("mammal", mammal => - { - mammal.SetDefaultCommand(); - }); - }); - }); - - // When - var result = fixture.Run(Constants.XmlDocCommand); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_8")] - public Task Should_Dump_Correct_Model_For_Model_With_Single_Branch_Single_Command_Default_Command() - { - // Given - var fixture = new CommandAppTester(); - fixture.Configure(configuration => - { - configuration.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - - animal.SetDefaultCommand(); - }); - }); - - // When - var result = fixture.Run(Constants.XmlDocCommand); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Test_9")] - public Task Should_Dump_Correct_Model_For_Model_With_Default_Command_Single_Branch_Single_Command_Default_Command() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - fixture.Configure(configuration => - { - configuration.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - - animal.SetDefaultCommand(); - }); - }); - - // When - var result = fixture.Run(Constants.XmlDocCommand); - - // Then - return Verifier.Verify(result.Output); - } - - [Fact] - [Expectation("Hidden_Command_Options")] - public Task Should_Not_Dump_Hidden_Options_On_A_Command() - { - // Given - var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); - - // When - var result = fixture.Run(Constants.XmlDocCommand); - - // Then - return Verifier.Verify(result.Output); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs deleted file mode 100644 index 0f024025c..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs +++ /dev/null @@ -1,1279 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed partial class CommandAppTests -{ - [Fact] - public void Should_Pass_Case_1() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] - { - "dog", "12", "4", "--good-boy", - "--name", "Rufus", "--alive", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Legs.ShouldBe(12); - dog.Age.ShouldBe(4); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - dog.IsAlive.ShouldBe(true); - }); - } - - [Fact] - public void Should_Pass_Case_2() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - animal.AddCommand("horse"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "dog", "12", "--good-boy", - "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - dog.IsAlive.ShouldBe(false); - }); - } - - [Fact] - public void Should_Pass_Case_4() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", "--good-boy", - "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Legs.ShouldBe(4); - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.IsAlive.ShouldBe(false); - dog.Name.ShouldBe("Rufus"); - }); - } - - [Fact] - public void Should_Pass_Case_5() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "--alive", "4", "dog", "--good-boy", "12", - "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Legs.ShouldBe(4); - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.IsAlive.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - }); - } - - [Fact] - public void Should_Pass_Case_6() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("multi"); - }); - - // When - var result = app.Run(new[] - { - "multi", "--foo", "a", "--foo", "b", - "--bar", "1", "--foo", "c", "--bar", "2", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(vec => - { - vec.Foo.Length.ShouldBe(3); - vec.Foo.ShouldBe(new[] { "a", "b", "c" }); - vec.Bar.Length.ShouldBe(2); - vec.Bar.ShouldBe(new[] { 1, 2 }); - }); - } - - [Fact] - public void Should_Pass_Case_3() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("multi"); - }); - - // When - var result = app.Run(new[] - { - "multi", "a", "b", "c", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(vec => - { - vec.Foo.Length.ShouldBe(3); - vec.Foo.ShouldBe(new[] { "a", "b", "c" }); - }); - } - - [Fact] - public void Should_Preserve_Quotes_Hyphen_Delimiters_Spaces() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] - { - "dog", "12", "4", - "--name=\" -Rufus --' ", - "--", - "--order-by", "\"-size\"", - "--order-by", " ", - "--order-by", string.Empty, - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Name.ShouldBe("\" -Rufus --' "); - }); - result.Context.Remaining.Parsed.Count.ShouldBe(1); - result.Context.ShouldHaveRemainingArgument("--order-by", values: new[] { "\"-size\"", " ", string.Empty }); - } - - [Fact] - public void Should_Be_Able_To_Use_Command_Alias() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("multi").WithAlias("multiple"); - }); - - // When - var result = app.Run(new[] - { - "multiple", "--foo", "a", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(vec => - { - vec.Foo.Length.ShouldBe(1); - vec.Foo.ShouldBe(new[] { "a" }); - }); - } - - [Fact] - public void Should_Be_Able_To_Use_Branch_Alias() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - animal.AddCommand("horse"); - }).WithAlias("a"); - }); - - // When - var result = app.Run(new[] - { - "a", "dog", "12", "--good-boy", - "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - dog.IsAlive.ShouldBe(false); - }); - } - - [Fact] - public void Should_Throw_If_Branch_Alias_Conflicts_With_Another_Command() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("a"); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - animal.AddCommand("horse"); - }).WithAlias("a"); - }); - - // When - var result = Record.Exception(() => app.Run(new[] { "a", "0", "12" })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("The alias 'a' for 'animal' conflicts with another command."); - }); - } - - [Fact] - public void Should_Assign_Default_Value_To_Optional_Argument() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(Array.Empty()); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.Greeting.ShouldBe("Hello World"); - }); - } - - [Fact] - public void Should_Assign_Property_Initializer_To_Optional_Argument() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(Array.Empty()); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings - .ShouldBeOfType() - .And(settings => settings.Count.ShouldBe(1)) - .And(settings => settings.Value.ShouldBe(0)) - .And(settings => settings.Names.ShouldNotBeNull()) - .And(settings => settings.Names.ShouldNotBeNull()) - .And(settings => settings.Names.ShouldBeEmpty()); - } - - [Fact] - public void Should_Overwrite_Property_Initializer_With_Argument_Value() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run("-c", "0", "--value", "50", "ABBA", "Herreys"); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings - .ShouldBeOfType() - .And(settings => settings.Count.ShouldBe(0)) - .And(settings => settings.Value.ShouldBe(50)) - .And(settings => settings.Names.ShouldContain("ABBA")) - .And(settings => settings.Names.ShouldContain("Herreys")); - } - - [Fact] - public void Should_Assign_Default_Value_To_Optional_Argument_Using_Converter_If_Necessary() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(Array.Empty()); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.Greeting.ShouldBe(5); - }); - } - - [Fact] - public void Should_Assign_Array_Default_Value_To_Command_Option() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(Array.Empty()); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.Days.ShouldBe(new[] { DayOfWeek.Sunday, DayOfWeek.Saturday }); - }); - } - - [Fact] - public void Should_Assign_Array_Default_Value_To_Command_Option_Using_Converter_If_Necessary() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(Array.Empty()); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.Numbers.ShouldBe(new[] { 2, 3 }); - }); - } - - [Fact] - public void Should_Throw_If_Required_Argument_Have_Default_Value() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand>(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = Record.Exception(() => app.Run(Array.Empty())); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("The required argument 'GREETING' cannot have a default value."); - }); - } - - [Fact] - public void Should_Throw_If_Alias_Conflicts_With_Another_Command() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog").WithAlias("cat"); - config.AddCommand("cat"); - }); - - // When - var result = Record.Exception(() => app.Run(new[] { "dog", "4", "12" })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("The alias 'cat' for 'dog' conflicts with another command."); - }); - } - - [Fact] - public void Should_Register_Commands_When_Configuring_Application() - { - // Given - var registrar = new FakeTypeRegistrar(); - var app = new CommandApp(registrar); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand>("foo"); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - animal.AddCommand("horse"); - }); - }); - - // When - app.Run(new[] - { - "animal", "4", "dog", "12", - }); - - // Then - registrar.Registrations.ContainsKey(typeof(GenericCommand)).ShouldBeTrue(); - registrar.Registrations.ContainsKey(typeof(DogCommand)).ShouldBeTrue(); - registrar.Registrations.ContainsKey(typeof(HorseCommand)).ShouldBeTrue(); - registrar.Registrations[typeof(GenericCommand)].ShouldContain(typeof(GenericCommand)); - registrar.Registrations[typeof(DogCommand)].ShouldContain(typeof(DogCommand)); - registrar.Registrations[typeof(HorseCommand)].ShouldContain(typeof(HorseCommand)); - } - - [Fact] - public void Should_Register_Default_Command_When_Configuring_Application() - { - // Given - var registrar = new FakeTypeRegistrar(); - var app = new CommandApp(registrar); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - app.Run(new[] - { - "12", "4", - }); - - // Then - registrar.Registrations.ContainsKey(typeof(DogCommand)).ShouldBeTrue(); - registrar.Registrations[typeof(DogCommand)].ShouldContain(typeof(DogCommand)); - } - - [Fact] - public void Can_Register_Default_Command_Settings_When_Configuring_Application() - { - // Given - var registrar = new FakeTypeRegistrar(); - registrar.Register(typeof(DogSettings), typeof(DogSettings)); - var app = new CommandApp(registrar); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - app.Run(new[] - { - "12", "4", - }); - - // Then - registrar.Registrations.ContainsKey(typeof(DogSettings)).ShouldBeTrue(); - registrar.Registrations[typeof(DogSettings)].Count.ShouldBe(2); - registrar.Registrations[typeof(DogSettings)].ShouldContain(typeof(DogSettings)); - } - - [Fact] - public void Can_Register_Command_Settings_When_Configuring_Application() - { - // Given - var registrar = new FakeTypeRegistrar(); - registrar.Register(typeof(DogSettings), typeof(DogSettings)); - registrar.Register(typeof(MammalSettings), typeof(MammalSettings)); - var app = new CommandApp(registrar); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - animal.AddCommand("horse"); - }); - }); - - // When - app.Run(new[] - { - "animal", "4", "dog", "12", - }); - - // Then - registrar.Registrations.ContainsKey(typeof(DogSettings)).ShouldBeTrue(); - registrar.Registrations[typeof(DogSettings)].Count.ShouldBe(2); - registrar.Registrations[typeof(DogSettings)].ShouldContain(typeof(DogSettings)); - registrar.Registrations.ContainsKey(typeof(MammalSettings)).ShouldBeTrue(); - registrar.Registrations[typeof(MammalSettings)].Count.ShouldBe(1); - registrar.Registrations[typeof(MammalSettings)].ShouldContain(typeof(MammalSettings)); - } - - [Theory] - [InlineData("true", true)] - [InlineData("True", true)] - [InlineData("false", false)] - [InlineData("False", false)] - public void Should_Accept_Explicit_Boolan_Flag(string value, bool expected) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] - { - "dog", "12", "4", "--alive", value, - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.IsAlive.ShouldBe(expected); - }); - } - - [Fact] - public void Should_Set_Short_Option_Before_Argument() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] { "dog", "-a", "-n=Rufus", "4", "12", }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.IsAlive.ShouldBeTrue(); - settings.Name.ShouldBe("Rufus"); - settings.Legs.ShouldBe(4); - settings.Age.ShouldBe(12); - }); - } - - [Theory] - [InlineData("true", true)] - [InlineData("True", true)] - [InlineData("false", false)] - [InlineData("False", false)] - public void Should_Set_Short_Option_With_Explicit_Boolan_Flag_Before_Argument(string value, bool expected) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] { "dog", "-a", value, "4", "12", }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.IsAlive.ShouldBe(expected); - settings.Legs.ShouldBe(4); - settings.Age.ShouldBe(12); - }); - } - - [Fact] - public void Should_Set_Long_Option_Before_Argument() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] { "dog", "--alive", "--name=Rufus", "4", "12" }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.IsAlive.ShouldBeTrue(); - settings.Name.ShouldBe("Rufus"); - settings.Legs.ShouldBe(4); - settings.Age.ShouldBe(12); - }); - } - - [Theory] - [InlineData("true", true)] - [InlineData("True", true)] - [InlineData("false", false)] - [InlineData("False", false)] - public void Should_Set_Long_Option_With_Explicit_Boolan_Flag_Before_Argument(string value, bool expected) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] { "dog", "--alive", value, "4", "12", }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.IsAlive.ShouldBe(expected); - settings.Legs.ShouldBe(4); - settings.Age.ShouldBe(12); - }); - } - - [Theory] - - // Long options - [InlineData("dog --alive 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog --alive=true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog --alive:true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog --alive --good-boy 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog --alive=true --good-boy=true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog --alive:true --good-boy:true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog --alive --good-boy --name Rufus 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog --alive=true --good-boy=true --name Rufus 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog --alive:true --good-boy:true --name Rufus 4 12", 4, 12, true, true, "Rufus")] - - // Short options - [InlineData("dog -a 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog -a=true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog -a:true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog -a --good-boy 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog -a=true -g=true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog -a:true -g:true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog -a -g --name Rufus 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog -a=true -g=true --name Rufus 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog -a:true -g:true --name Rufus 4 12", 4, 12, true, true, "Rufus")] - - // Switch around ordering of the options - [InlineData("dog --good-boy:true --name Rufus --alive:true 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog --name Rufus --alive:true --good-boy:true 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog --name Rufus --good-boy:true --alive:true 4 12", 4, 12, true, true, "Rufus")] - - // Inject the command arguments in between the options - [InlineData("dog 4 12 --good-boy:true --name Rufus --alive:true", 4, 12, true, true, "Rufus")] - [InlineData("dog 4 --good-boy:true 12 --name Rufus --alive:true", 4, 12, true, true, "Rufus")] - [InlineData("dog --good-boy:true 4 12 --name Rufus --alive:true", 4, 12, true, true, "Rufus")] - [InlineData("dog --good-boy:true 4 --name Rufus 12 --alive:true", 4, 12, true, true, "Rufus")] - [InlineData("dog --name Rufus --alive:true 4 12 --good-boy:true", 4, 12, true, true, "Rufus")] - [InlineData("dog --name Rufus --alive:true 4 --good-boy:true 12", 4, 12, true, true, "Rufus")] - - // Inject the command arguments in between the options (all flag values set to false) - [InlineData("dog 4 12 --good-boy:false --name Rufus --alive:false", 4, 12, false, false, "Rufus")] - [InlineData("dog 4 --good-boy:false 12 --name Rufus --alive:false", 4, 12, false, false, "Rufus")] - [InlineData("dog --good-boy:false 4 12 --name Rufus --alive:false", 4, 12, false, false, "Rufus")] - [InlineData("dog --good-boy:false 4 --name Rufus 12 --alive:false", 4, 12, false, false, "Rufus")] - [InlineData("dog --name Rufus --alive:false 4 12 --good-boy:false", 4, 12, false, false, "Rufus")] - [InlineData("dog --name Rufus --alive:false 4 --good-boy:false 12", 4, 12, false, false, "Rufus")] - public void Should_Set_Option_Before_Argument(string arguments, int legs, int age, bool goodBoy, bool isAlive, string name) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(arguments.Split(' ')); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.Legs.ShouldBe(legs); - settings.Age.ShouldBe(age); - settings.GoodBoy.ShouldBe(goodBoy); - settings.IsAlive.ShouldBe(isAlive); - settings.Name.ShouldBe(name); - }); - } - - [Fact] - public void Should_Throw_When_Encountering_Unknown_Option_In_Strict_Mode() - { - // Given - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.UseStrictParsing(); - config.AddCommand("dog"); - }); - - // When - var result = Record.Exception(() => app.Run(new[] { "dog", "--foo" })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("Unknown option 'foo'."); - }); - } - - [Fact] - public void Should_Add_Unknown_Option_To_Remaining_Arguments_In_Relaxed_Mode() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", - "--foo", "bar", - }); - - // Then - result.Context.ShouldNotBeNull(); - result.Context.Remaining.Parsed.Count.ShouldBe(1); - result.Context.ShouldHaveRemainingArgument("--foo", values: new[] { "bar" }); - } - - [Fact] - public void Should_Add_Unknown_Option_To_Remaining_Arguments_In_Strict_Mode() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.UseStrictParsing(); - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", - "--", - "--foo", "bar", - "-f", "baz", - "qux", - }); - - // Then - result.Context.ShouldNotBeNull(); - result.Context.Remaining.Parsed.Count.ShouldBe(2); - result.Context.ShouldHaveRemainingArgument("--foo", values: new[] { "bar" }); - result.Context.ShouldHaveRemainingArgument("-f", values: new[] { "baz" }); - result.Context.Remaining.Raw.Count.ShouldBe(5); - result.Context.Remaining.Raw.ShouldBe(new[] - { - "--foo", "bar", - "-f", "baz", - "qux", - }); - } - - [Fact] - public void Should_Add_Unknown_Boolean_Option_To_Remaining_Arguments_In_Relaxed_Mode() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", "--foo", - }); - - // Then - result.Context.ShouldNotBeNull(); - result.Context.Remaining.Parsed.Count.ShouldBe(1); - result.Context.ShouldHaveRemainingArgument("--foo", values: new[] { (string)null }); - } - - [Fact] - public void Should_Run_The_Default_Command() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand(); - - // When - var result = app.Run(new[] - { - "4", "12", "--good-boy", "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Legs.ShouldBe(4); - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - }); - } - - [Fact] - public void Should_Run_The_Default_Command_Not_The_Named_Command() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("horse"); - }); - app.SetDefaultCommand(); - - // When - var result = app.Run(new[] - { - "4", "12", "--good-boy", "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Legs.ShouldBe(4); - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - }); - } - - [Fact] - public void Should_Run_The_Named_Command_Not_The_Default_Command() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("horse"); - }); - app.SetDefaultCommand(); - - // When - var result = app.Run(new[] - { - "horse", "4", "--name", "Arkle", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(horse => - { - horse.Legs.ShouldBe(4); - horse.Name.ShouldBe("Arkle"); - horse.File.Name.ShouldBe("food.txt"); - }); - } - - [Fact] - public void Should_Set_Command_Name_In_Context() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog"); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", - }); - - // Then - result.Context.ShouldNotBeNull(); - result.Context.Name.ShouldBe("dog"); - } - - [Fact] - public void Should_Pass_Command_Data_In_Context() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("animal", animal => - { - animal.AddCommand("dog").WithData(123); - }); - }); - - // When - var result = app.Run(new[] - { - "animal", "4", "dog", "12", - }); - - // Then - result.Context.ShouldNotBeNull(); - result.Context.Data.ShouldBe(123); - } - - public sealed class Default_Command - { - [Fact] - public void Should_Be_Able_To_Set_The_Default_Command() - { - // Given - var app = new CommandAppTester(); - app.SetDefaultCommand(); - - // When - var result = app.Run(new[] - { - "4", "12", "--good-boy", "--name", "Rufus", - }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(dog => - { - dog.Legs.ShouldBe(4); - dog.Age.ShouldBe(12); - dog.GoodBoy.ShouldBe(true); - dog.Name.ShouldBe("Rufus"); - }); - } - - [Fact] - public void Should_Set_The_Default_Command_Description_Data_CommandApp() - { - // Given - var app = new CommandApp(); - app.SetDefaultCommand() - .WithDescription("The default command") - .WithData(new string[] { "foo", "bar" }); - - // When - - // Then - app.GetConfigurator().DefaultCommand.ShouldNotBeNull(); - app.GetConfigurator().DefaultCommand.Description.ShouldBe("The default command"); - app.GetConfigurator().DefaultCommand.Data.ShouldBe(new string[] { "foo", "bar" }); - } - - [Fact] - public void Should_Set_The_Default_Command_Description_Data_CommandAppOfT() - { - // Given - var app = new CommandApp() - .WithDescription("The default command") - .WithData(new string[] { "foo", "bar" }); - - // When - - // Then - app.GetConfigurator().DefaultCommand.ShouldNotBeNull(); - app.GetConfigurator().DefaultCommand.Description.ShouldBe("The default command"); - app.GetConfigurator().DefaultCommand.Data.ShouldBe(new string[] { "foo", "bar" }); - } - } - - public sealed class Delegate_Commands - { - [Fact] - public void Should_Execute_Delegate_Command_At_Root_Level() - { - // Given - var dog = default(DogSettings); - var data = 0; - - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddDelegate( - "foo", (context, settings, _) => - { - dog = settings; - data = (int)context.Data; - return 1; - }).WithData(2); - }); - - // When - var result = app.Run(new[] { "foo", "4", "12" }); - - // Then - result.ShouldBe(1); - dog.ShouldNotBeNull(); - dog.Age.ShouldBe(12); - dog.Legs.ShouldBe(4); - data.ShouldBe(2); - } - - [Fact] - public void Should_Execute_Nested_Delegate_Empty_Command() - { - // Given - var app = new CommandAppTester(); - app.Configure(cfg => - { - cfg.AddBranch("a", d => - { - d.AddDelegate("b", (_, _) => 0); - }); - }); - - // When - var result = app.Run([ - "a", "b" - ]); - - // Then - result.ExitCode.ShouldBe(0); - } - - [Fact] - public void Should_Execute_Delegate_Empty_Command_At_Root_Level() - { - // Given - var app = new CommandAppTester(); - app.Configure(cfg => - { - cfg.AddDelegate("a", (_, _) => 0); - }); - - // When - var result = app.Run([ - "a" - ]); - - // Then - result.ExitCode.ShouldBe(0); - } - - [Fact] - public async Task Should_Execute_Async_Delegate_Command_At_Root_Level() - { - // Given - var dog = default(DogSettings); - var data = 0; - - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddAsyncDelegate( - "foo", (context, settings, _) => - { - dog = settings; - data = (int)context.Data; - return Task.FromResult(1); - }).WithData(2); - }); - - // When - var result = await app.RunAsync(new[] { "foo", "4", "12" }); - - // Then - result.ShouldBe(1); - dog.ShouldNotBeNull(); - dog.Age.ShouldBe(12); - dog.Legs.ShouldBe(4); - data.ShouldBe(2); - } - - [Fact] - public void Should_Execute_Nested_Delegate_Command() - { - // Given - var dog = default(DogSettings); - var data = 0; - - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("foo", foo => - { - foo.AddDelegate( - "bar", (context, settings, _) => - { - dog = settings; - data = (int)context.Data; - return 1; - }).WithData(2); - }); - }); - - // When - var result = app.Run(new[] { "foo", "4", "bar", "12" }); - - // Then - result.ShouldBe(1); - dog.ShouldNotBeNull(); - dog.Age.ShouldBe(12); - dog.Legs.ShouldBe(4); - data.ShouldBe(2); - } - - [Fact] - public async Task Should_Execute_Nested_Async_Delegate_Command() - { - // Given - var dog = default(DogSettings); - var data = 0; - - var app = new CommandApp(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddBranch("foo", foo => - { - foo.AddAsyncDelegate( - "bar", (context, settings, _) => - { - dog = settings; - data = (int)context.Data; - return Task.FromResult(1); - }).WithData(2); - }); - }); - - // When - var result = await app.RunAsync(new[] { "foo", "4", "bar", "12" }); - - // Then - result.ShouldBe(1); - dog.ShouldNotBeNull(); - dog.Age.ShouldBe(12); - dog.Legs.ShouldBe(4); - data.ShouldBe(2); - } - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/DefaultTypeRegistrarTests.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/DefaultTypeRegistrarTests.cs deleted file mode 100644 index 6cd2256bf..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/DefaultTypeRegistrarTests.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed class DefaultTypeRegistrarTests -{ - [Fact] - public void Should_Pass_Base_Registrar_Tests() - { - var harness = new TypeRegistrarBaseTests(() => new DefaultTypeRegistrar()); - harness.RunAllTests(); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/Parsing/CommandTreeTokenizerTests.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/Parsing/CommandTreeTokenizerTests.cs deleted file mode 100644 index b5d25e423..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/Parsing/CommandTreeTokenizerTests.cs +++ /dev/null @@ -1,314 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli.Parsing; - -public class CommandTreeTokenizerTests -{ - public sealed class ScanString - { - [Theory] - [InlineData("")] - [InlineData(" ")] - [InlineData(" ")] - [InlineData("\t")] - [InlineData("\r\n\t")] - [InlineData("👋🏻")] - [InlineData("🐎👋🏻🔥❤️")] - [InlineData("\"🐎👋🏻🔥❤️\" is an emoji sequence")] - public void Should_Preserve_Edgecase_Inputs(string actualAndExpected) - { - // Given - - // When - var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected }); - - // Then - result.Tokens.Count.ShouldBe(1); - result.Tokens[0].Value.ShouldBe(actualAndExpected); - result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String); - } - - [Theory] - - // Double-quote handling - [InlineData("\"")] - [InlineData("\"\"")] - [InlineData("\"Rufus\"")] - [InlineData("\" Rufus\"")] - [InlineData("\"-R\"")] - [InlineData("\"-Rufus\"")] - [InlineData("\" -Rufus\"")] - - // Single-quote handling - [InlineData("'")] - [InlineData("''")] - [InlineData("'Rufus'")] - [InlineData("' Rufus'")] - [InlineData("'-R'")] - [InlineData("'-Rufus'")] - [InlineData("' -Rufus'")] - public void Should_Preserve_Quotes(string actualAndExpected) - { - // Given - - // When - var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected }); - - // Then - result.Tokens.Count.ShouldBe(1); - result.Tokens[0].Value.ShouldBe(actualAndExpected); - result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String); - } - - [Theory] - [InlineData("Rufus-")] - [InlineData("Rufus--")] - [InlineData("R-u-f-u-s")] - public void Should_Preserve_Hyphen_Delimiters(string actualAndExpected) - { - // Given - - // When - var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected }); - - // Then - result.Tokens.Count.ShouldBe(1); - result.Tokens[0].Value.ShouldBe(actualAndExpected); - result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String); - } - - [Theory] - [InlineData(" Rufus")] - [InlineData("Rufus ")] - [InlineData(" Rufus ")] - public void Should_Preserve_Spaces(string actualAndExpected) - { - // Given - - // When - var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected }); - - // Then - result.Tokens.Count.ShouldBe(1); - result.Tokens[0].Value.ShouldBe(actualAndExpected); - result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String); - } - - [Theory] - [InlineData(" \" -Rufus -- ")] - [InlineData("Name=\" -Rufus --' ")] - public void Should_Preserve_Quotes_Hyphen_Delimiters_Spaces(string actualAndExpected) - { - // Given - - // When - var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected }); - - // Then - result.Tokens.Count.ShouldBe(1); - result.Tokens[0].Value.ShouldBe(actualAndExpected); - result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String); - } - } - - public sealed class ScanLongOption - { - [Theory] - [InlineData("--Name-", "Name-")] - [InlineData("--Name_", "Name_")] - public void Should_Allow_Hyphens_And_Underscores_In_Option_Name(string actual, string expected) - { - // Given - - // When - var result = CommandTreeTokenizer.Tokenize(new string[] { actual }); - - // Then - result.Tokens.Count.ShouldBe(1); - result.Tokens[0].Value.ShouldBe(expected); - result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.LongOption); - } - - [Theory] - [InlineData("-- ")] - [InlineData("--Name ")] - [InlineData("--Name\"")] - [InlineData("--Nam\"e")] - public void Should_Throw_On_Invalid_Option_Name(string actual) - { - // Given - - // When - var result = Record.Exception(() => CommandTreeTokenizer.Tokenize(new string[] { actual })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("Invalid long option name."); - }); - } - } - - public sealed class ScanShortOptions - { - [Fact] - public void Should_Accept_Option_Without_Value() - { - // Given - - // When - var result = CommandTreeTokenizer.Tokenize(new[] { "-a" }); - - // Then - result.Remaining.ShouldBeEmpty(); - result.Tokens.ShouldHaveSingleItem(); - - var t = result.Tokens[0]; - t.TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption); - t.IsGrouped.ShouldBe(false); - t.Position.ShouldBe(0); - t.Value.ShouldBe("a"); - t.Representation.ShouldBe("-a"); - } - - [Theory] - [InlineData("-a:foo")] - [InlineData("-a=foo")] - public void Should_Accept_Option_With_Value(string param) - { - // Given - - // When - var result = CommandTreeTokenizer.Tokenize(new[] { param }); - - // Then - result.Remaining.ShouldBeEmpty(); - result.Tokens.Count.ShouldBe(2); - - var t = result.Tokens.Consume(); - t.TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption); - t.IsGrouped.ShouldBe(false); - t.Position.ShouldBe(0); - t.Value.ShouldBe("a"); - t.Representation.ShouldBe("-a"); - - t = result.Tokens.Consume(); - t.TokenKind.ShouldBe(CommandTreeToken.Kind.String); - t.IsGrouped.ShouldBe(false); - t.Position.ShouldBe(3); - t.Value.ShouldBe("foo"); - t.Representation.ShouldBe("foo"); - } - - [Theory] - - // Positive values - [InlineData("-a:1.5", null, "1.5")] - [InlineData("-a=1.5", null, "1.5")] - [InlineData("-a", "1.5", "1.5")] - - // Negative values - [InlineData("-a:-1.5", null, "-1.5")] - [InlineData("-a=-1.5", null, "-1.5")] - [InlineData("-a", "-1.5", "-1.5")] - public void Should_Accept_Option_With_Numeric_Value(string firstArg, string secondArg, string expectedValue) - { - // Given - List args = new List(); - args.Add(firstArg); - if (secondArg != null) - { - args.Add(secondArg); - } - - // When - var result = CommandTreeTokenizer.Tokenize(args); - - // Then - result.Remaining.ShouldBeEmpty(); - result.Tokens.Count.ShouldBe(2); - - var t = result.Tokens.Consume(); - t.TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption); - t.IsGrouped.ShouldBe(false); - t.Position.ShouldBe(0); - t.Value.ShouldBe("a"); - t.Representation.ShouldBe("-a"); - - t = result.Tokens.Consume(); - t.TokenKind.ShouldBe(CommandTreeToken.Kind.String); - t.IsGrouped.ShouldBe(false); - t.Position.ShouldBe(3); - t.Value.ShouldBe(expectedValue); - t.Representation.ShouldBe(expectedValue); - } - - [Fact] - public void Should_Accept_Option_With_Negative_Numeric_Prefixed_String_Value() - { - // Given - - // When - var result = CommandTreeTokenizer.Tokenize(new[] { "-6..2 " }); - - // Then - result.Remaining.ShouldBeEmpty(); - result.Tokens.ShouldHaveSingleItem(); - - var t = result.Tokens[0]; - t.TokenKind.ShouldBe(CommandTreeToken.Kind.String); - t.IsGrouped.ShouldBe(false); - t.Position.ShouldBe(0); - t.Value.ShouldBe("-6..2"); - t.Representation.ShouldBe("-6..2"); - } - - [Theory] - [InlineData("-N ", "N")] - public void Should_Remove_Trailing_Spaces_In_Option_Name(string actual, string expected) - { - // Given - - // When - var result = CommandTreeTokenizer.Tokenize(new string[] { actual }); - - // Then - result.Tokens.Count.ShouldBe(1); - result.Tokens[0].Value.ShouldBe(expected); - result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption); - } - - [Theory] - [InlineData("-N-")] - [InlineData("-N\"")] - [InlineData("-a1")] - public void Should_Throw_On_Invalid_Option_Name(string actual) - { - // Given - - // When - var result = Record.Exception(() => CommandTreeTokenizer.Tokenize(new string[] { actual })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("Short option does not have a valid name."); - }); - } - } - - [Theory] - [InlineData("-")] - [InlineData("- ")] - public void Should_Throw_On_Missing_Option_Name(string actual) - { - // Given - - // When - var result = Record.Exception(() => CommandTreeTokenizer.Tokenize(new string[] { actual })); - - // Then - result.ShouldBeOfType().And(ex => - { - ex.Message.ShouldBe("Option does not have a name."); - }); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/CommandAppTesterTests.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/CommandAppTesterTests.cs deleted file mode 100644 index 284054025..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/CommandAppTesterTests.cs +++ /dev/null @@ -1,83 +0,0 @@ - -using System; - -namespace Spectre.Console.Tests.Unit.Cli.Testing; - -public sealed class CommandAppTesterTests -{ - private class CommandAppTesterCommand : Command - { - private readonly IAnsiConsole _console; - - public CommandAppTesterCommand(IAnsiConsole console) - { - _console = console; - } - - public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings, CancellationToken cancellationToken) - { - _console.Write(settings.Greeting); - return 0; - } - } - - [Theory] - [InlineData(false, " Hello ", " Hello ")] - [InlineData(true, " Hello ", "Hello")] - [InlineData(false, " Hello \n World ", " Hello \n World ")] - [InlineData(true, " Hello \n World ", "Hello\n World")] - public void Should_Respect_Trim_Setting(bool trim, string actual, string expected) - { - // Given - var settings = new CommandAppTesterSettings { TrimConsoleOutput = trim }; - - var app = new CommandAppTester(settings); - app.SetDefaultCommand(); - app.Configure(config => - { - config.PropagateExceptions(); - }); - - // When - var result = app.Run(actual); - - // Then - result.Output.ShouldBe(expected); - } - - [Fact] - public void DefaultCtor_WithoutParameters_CreatesDefaultConsole() - { - // Given, When - CommandAppTester app = new(); - - // Then - app.Console.ShouldNotBeNull(); - app.Console.Profile.Width.ShouldBe(int.MaxValue); - } - - [Fact] - public void DefaultCtor_WithCustomConsole_UsesProvidedInstance() - { - // Given - TestConsole console = new(); - - // When - CommandAppTester app = new(null, new CommandAppTesterSettings(), console); - - // Then - app.Console.ShouldNotBeNull(); - app.Console.ShouldBeSameAs(console); - } - - [Fact] - public void Ctor_WithSettings_CreatesDefaultConsole() - { - // Given, When - CommandAppTester app = new(new CommandAppTesterSettings()); - - // Then - app.Console.ShouldNotBeNull(); - app.Console.Profile.Width.ShouldBe(int.MaxValue); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/FakeTypeRegistrarTests.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/FakeTypeRegistrarTests.cs deleted file mode 100644 index 61ae88d0d..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/FakeTypeRegistrarTests.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli.Testing; - -public class FakeTypeRegistrarTests -{ - [Fact] - public void TheFakeTypeRegistrarPassesAllTheTestsForARegistrar() - { - ITypeRegistrar Factory() => new FakeTypeRegistrar(); - var tester = new TypeRegistrarBaseTests(Factory); - tester.RunAllTests(); - } -} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/InteractiveCommandTests.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/InteractiveCommandTests.cs deleted file mode 100644 index 20a4a6ae1..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/InteractiveCommandTests.cs +++ /dev/null @@ -1,111 +0,0 @@ -namespace Spectre.Console.Tests.Unit.Cli; - -public sealed class InteractiveCommandTests -{ - private sealed class InteractiveCommand : Command - { - private readonly IAnsiConsole _console; - - public InteractiveCommand(IAnsiConsole console) - { - _console = console; - } - - public override int Execute(CommandContext context, CancellationToken cancellationToken) - { - var fruits = _console.Prompt( - new MultiSelectionPrompt() - .Title("What are your [green]favorite fruits[/]?") - .NotRequired() // Not required to have a favorite fruit - .PageSize(10) - .MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]") - .InstructionsText( - "[grey](Press [blue][/] to toggle a fruit, " + - "[green][/] to accept)[/]") - .AddChoices(new[] { - "Apple", "Apricot", "Avocado", - "Banana", "Blackcurrant", "Blueberry", - "Cherry", "Cloudberry", "Coconut", - })); - - var fruit = _console.Prompt( - new SelectionPrompt() - .Title("What's your [green]favorite fruit[/]?") - .PageSize(10) - .MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]") - .AddChoices(new[] { - "Apple", "Apricot", "Avocado", - "Banana", "Blackcurrant", "Blueberry", - "Cherry", "Cloudberry", "Cocunut", - })); - - var name = _console.Ask("What's your name?"); - - _console.WriteLine($"[{string.Join(',', fruits)};{fruit};{name}]"); - - return 0; - } - } - - [Fact] - public void InteractiveCommand_WithMockedUserInputs_ProducesExpectedOutput() - { - // Given - TestConsole console = new(); - console.Interactive(); - - // Your mocked inputs must always end with "Enter" for each prompt! - - // Multi selection prompt: Choose first option - console.Input.PushKey(ConsoleKey.Spacebar); - console.Input.PushKey(ConsoleKey.Enter); - - // Selection prompt: Choose second option - console.Input.PushKey(ConsoleKey.DownArrow); - console.Input.PushKey(ConsoleKey.Enter); - - // Ask text prompt: Enter name - console.Input.PushTextWithEnter("Spectre Console"); - - var app = new CommandAppTester(null, new CommandAppTesterSettings(), console); - app.SetDefaultCommand(); - - // When - var result = app.Run(); - - // Then - result.ExitCode.ShouldBe(0); - result.Output.EndsWith("[Apple;Apricot;Spectre Console]"); - } - - [Fact] - public void InteractiveCommand_WithMockedUserInputs_VimMotions_ProducesExpectedOutput() - { - // Given - TestConsole console = new(); - console.Interactive(); - - // Your mocked inputs must always end with "Enter" for each prompt! - - // Multi selection prompt: Choose first option - console.Input.PushKey(ConsoleKey.Spacebar); - console.Input.PushKey(ConsoleKey.Enter); - - // Selection prompt: Choose second option - console.Input.PushKey(ConsoleKey.J); - console.Input.PushKey(ConsoleKey.Enter); - - // Ask text prompt: Enter name - console.Input.PushTextWithEnter("Spectre Console"); - - var app = new CommandAppTester(null, new CommandAppTesterSettings(), console); - app.SetDefaultCommand(); - - // When - var result = app.Run(); - - // Then - result.ExitCode.ShouldBe(0); - result.Output.EndsWith("[Apple;Apricot;Spectre Console]"); - } -} diff --git a/src/Tests/Spectre.Console.Cli.Tests/Utilities/CommandContextExtensions.cs b/src/Tests/Spectre.Console.Cli.Tests/Utilities/CommandContextExtensions.cs deleted file mode 100644 index 6809cd2a8..000000000 --- a/src/Tests/Spectre.Console.Cli.Tests/Utilities/CommandContextExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Spectre.Console.Cli; - -public static class CommandContextExtensions -{ - public static void ShouldHaveRemainingArgument(this CommandContext context, string name, string[] values) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (values == null) - { - throw new ArgumentNullException(nameof(values)); - } - - context.Remaining.Parsed.Contains(name).ShouldBeTrue(); - context.Remaining.Parsed[name].Count().ShouldBe(values.Length); - - foreach (var value in values) - { - context.Remaining.Parsed[name].ShouldContain(value); - } - } -} diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/ArgumentCannotContainOptions.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/ArgumentCannotContainOptions.Output.verified.txt deleted file mode 100644 index fbfd4d77e..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/ArgumentCannotContainOptions.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - Arguments can not contain options. - - --foo - ^^^^^ Not permitted \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInOptionName.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInOptionName.Output.verified.txt deleted file mode 100644 index 87989bd44..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInOptionName.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - Encountered invalid character '$' in option name. - - --f$oo - ^ Invalid character \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInValueName.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInValueName.Output.verified.txt deleted file mode 100644 index 6d40834c5..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/InvalidCharacterInValueName.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - Encountered invalid character '$' in value name. - - -f|--foo - ^ Invalid character \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/LongOptionMustHaveMoreThanOneCharacter.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/LongOptionMustHaveMoreThanOneCharacter.Output.verified.txt deleted file mode 100644 index 1f72ae651..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/LongOptionMustHaveMoreThanOneCharacter.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - Long option names must consist of more than one character. - - --f - ^ Invalid option name \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MissingLongAndShortName.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MissingLongAndShortName.Output.verified.txt deleted file mode 100644 index 0c411901f..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MissingLongAndShortName.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - No long or short name for option has been specified. - - - ^^^^^ Missing option. Was this meant to be an argument? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleOptionValuesAreNotSupported.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleOptionValuesAreNotSupported.Output.verified.txt deleted file mode 100644 index e27e657cd..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleOptionValuesAreNotSupported.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - Multiple option values are not supported. - - -f|--foo - ^^^^^ Too many option values \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleValuesAreNotSupported.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleValuesAreNotSupported.Output.verified.txt deleted file mode 100644 index 413d1291a..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/MultipleValuesAreNotSupported.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - Multiple values are not supported. - - - ^^^^^ Too many values \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionNamesCannotStartWithDigit.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionNamesCannotStartWithDigit.Output.verified.txt deleted file mode 100644 index ff5ff300a..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionNamesCannotStartWithDigit.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - Option names cannot start with a digit. - - --1foo - ^^^^ Invalid option name \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionsMustHaveName.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionsMustHaveName.Output.verified.txt deleted file mode 100644 index 3e277d93a..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/OptionsMustHaveName.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - Options without name are not allowed. - - --foo|- - ^ Missing option name \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/ShortOptionMustOnlyBeOneCharacter.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/ShortOptionMustOnlyBeOneCharacter.Output.verified.txt deleted file mode 100644 index d7986d9b9..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/ShortOptionMustOnlyBeOneCharacter.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - Short option names can not be longer than one character. - - --foo|-bar - ^^^ Invalid option name \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/UnexpectedCharacter.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/UnexpectedCharacter.Output.verified.txt deleted file mode 100644 index ed7e61469..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/UnexpectedCharacter.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - Encountered unexpected character '$'. - - $ - ^ Unexpected character \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/UnterminatedValueName.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/UnterminatedValueName.Output.verified.txt deleted file mode 100644 index b245f7765..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Arguments/UnterminatedValueName.Output.verified.txt +++ /dev/null @@ -1,5 +0,0 @@ -Error: An error occured when parsing template. - Encountered unterminated value name 'BAR'. - - --foo|-f - ^^ Missing value name \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/InvalidShortOptionName/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/InvalidShortOptionName/Test_1.Output.verified.txt deleted file mode 100644 index b6efb4d9d..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/InvalidShortOptionName/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Short option does not have a valid name. - - dog -f0o - ^ Not a valid name for a short option \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameContainSymbol/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameContainSymbol/Test_1.Output.verified.txt deleted file mode 100644 index aced6670e..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameContainSymbol/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Invalid long option name. - - dog --f€oo - ^ Invalid character \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsMissing/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsMissing/Test_1.Output.verified.txt deleted file mode 100644 index 62f3c00fe..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsMissing/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Invalid long option name. - - dog -- - ^^ Did you forget the option name? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsOneCharacter/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsOneCharacter/Test_1.Output.verified.txt deleted file mode 100644 index 22a567235..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameIsOneCharacter/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Invalid long option name. - - dog --f - ^^^ Did you mean -f? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameStartWithDigit/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameStartWithDigit/Test_1.Output.verified.txt deleted file mode 100644 index 295fe902b..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/LongOptionNameStartWithDigit/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Invalid long option name. - - dog --1foo - ^^^^^^ Option names cannot start with a digit \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoMatchingArgument/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoMatchingArgument/Test_1.Output.verified.txt deleted file mode 100644 index 1873f4975..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoMatchingArgument/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Could not match 'baz' with an argument. - - giraffe foo bar baz - ^^^ Could not match to argument \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_1.Output.verified.txt deleted file mode 100644 index 346f4d475..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Option 'name' is defined but no value has been provided. - - dog --name - ^^^^^^ No value provided \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_2.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_2.Output.verified.txt deleted file mode 100644 index 97e0cbd0c..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/NoValueForOption/Test_2.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Option 'name' is defined but no value has been provided. - - dog -n - ^^ No value provided \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_1.Output.verified.txt deleted file mode 100644 index 8733f9d24..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Option does not have a name. - - dog - - ^ Did you forget the option name? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_2.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_2.Output.verified.txt deleted file mode 100644 index 52d5bcbbc..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_2.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Expected an option value. - - dog --foo= - ^ Did you forget the option value? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_3.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_3.Output.verified.txt deleted file mode 100644 index 5ae49a695..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_3.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Expected an option value. - - dog --foo: - ^ Did you forget the option value? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_4.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_4.Output.verified.txt deleted file mode 100644 index bd61abc84..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_4.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Expected an option value. - - dog -f= - ^ Did you forget the option value? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_5.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_5.Output.verified.txt deleted file mode 100644 index 2dafc0465..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/OptionWithoutName/Test_5.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Expected an option value. - - dog -f: - ^ Did you forget the option value? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_1.Output.verified.txt deleted file mode 100644 index 67b7cff3a..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unexpected option 'foo'. - - --foo - ^^^^^ Did you forget the command? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_2.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_2.Output.verified.txt deleted file mode 100644 index 437196761..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnexpectedOption/Test_2.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unexpected option 'f'. - - -f - ^^ Did you forget the command? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_1.Output.verified.txt deleted file mode 100644 index 8a61b3319..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unknown command 'cat'. - - cat 14 - ^^^ No such command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_2.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_2.Output.verified.txt deleted file mode 100644 index ac7a69d5e..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_2.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unknown command 'other'. - - empty other - ^^^^^ No such command \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_3.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_3.Output.verified.txt deleted file mode 100644 index cbea5ea94..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_3.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unknown command 'bat'. - - dog bat 14 - ^^^ Did you mean 'cat'? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_4.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_4.Output.verified.txt deleted file mode 100644 index bc8a096c2..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_4.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unknown command 'bat'. - - bat 14 - ^^^ Did you mean 'cat'? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_5.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_5.Output.verified.txt deleted file mode 100644 index 225f86e82..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_5.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unknown command 'bat'. - - bat - ^^^ Did you mean 'cat'? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_6.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_6.Output.verified.txt deleted file mode 100644 index cdabe2829..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_6.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unknown command 'bat'. - - dog bat - ^^^ Did you mean 'cat'? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_7.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_7.Output.verified.txt deleted file mode 100644 index d9eacbb4c..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_7.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unknown command 'bat'. - - qux bat - ^^^ Did you mean 'bar'? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_8.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_8.Output.verified.txt deleted file mode 100644 index 94f805b55..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownCommand/Test_8.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unknown command 'bat'. - - foo qux bat - ^^^ Did you mean 'bar'? \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_1.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_1.Output.verified.txt deleted file mode 100644 index d23f5a6ca..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_1.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unknown option 'unknown'. - - dog --unknown - ^^^^^^^^^ Unknown option \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_2.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_2.Output.verified.txt deleted file mode 100644 index d86e8ec0c..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Parsing/UnknownOption/Test_2.Output.verified.txt +++ /dev/null @@ -1,4 +0,0 @@ -Error: Unknown option 'u'. - - dog -u - ^^ Unknown option \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Hidden_Command_Options.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Hidden_Command_Options.Output.verified.txt deleted file mode 100644 index d2f2d0b14..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Hidden_Command_Options.Output.verified.txt +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - Dummy argument FOO - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_5.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_5.Output.verified.txt deleted file mode 100644 index 2b4469505..000000000 --- a/src/Tests/Spectre.Console.Tests/Expectations/Cli/Xml/Test_5.Output.verified.txt +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/Utilities/ModuleInitializerAttribute.cs b/src/Tests/Spectre.Console.Tests/Utilities/ModuleInitializerAttribute.cs deleted file mode 100644 index 5b84da221..000000000 --- a/src/Tests/Spectre.Console.Tests/Utilities/ModuleInitializerAttribute.cs +++ /dev/null @@ -1,8 +0,0 @@ -#if !NET6_0_OR_GREATER -namespace System.Runtime.CompilerServices; - -[AttributeUsage(AttributeTargets.Method, Inherited = false)] -public sealed class ModuleInitializerAttribute : Attribute -{ -} -#endif \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Tests/VerifyConfiguration.cs b/src/Tests/Spectre.Console.Tests/VerifyConfiguration.cs deleted file mode 100644 index b3261c23f..000000000 --- a/src/Tests/Spectre.Console.Tests/VerifyConfiguration.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Spectre.Console.Tests; - -public static class VerifyConfiguration -{ - [ModuleInitializer] - public static void Init() - { - Verifier.DerivePathInfo(Expectations.Initialize); - } -} diff --git a/src/stylecop.json b/src/stylecop.json deleted file mode 100644 index 4a7219f5e..000000000 --- a/src/stylecop.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", - "settings": { - "documentationRules": { - "documentExposedElements": true, - "documentInternalElements": false, - "documentPrivateElements": false, - "documentPrivateFields": false - }, - "layoutRules": { - "newlineAtEndOfFile": "allow", - "allowConsecutiveUsings": true - }, - "orderingRules": { - "usingDirectivesPlacement": "outsideNamespace", - "systemUsingDirectivesFirst": true, - "elementOrder": [ - "kind", - "accessibility", - "constant", - "static", - "readonly" - ] - } - } -} \ No newline at end of file From 0da5113b82372d10dc37d7e2b90ff7e9c31d1f34 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Wed, 12 Nov 2025 21:20:13 +0100 Subject: [PATCH 13/22] Fix docs generation bug --- docs/src/Constants.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/Constants.cs b/docs/src/Constants.cs index 42b2e487a..2cfa2fc8a 100644 --- a/docs/src/Constants.cs +++ b/docs/src/Constants.cs @@ -29,7 +29,7 @@ public static class Emojis public static class Colors { - public const string Url = "https://raw.githubusercontent.com/spectreconsole/spectre.console/main/resources/scripts/Generator/Data/colors.json"; + public const string Url = "https://raw.githubusercontent.com/spectreconsole/spectre.console/main/src/Generator/Data/colors.json"; public const string Root = "COLORS_ROOT"; } From c6e9501f49bf0d9c5956f5a7f85bd70c5121a231 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Wed, 12 Nov 2025 21:39:25 +0100 Subject: [PATCH 14/22] Add net10.0 tfm, and update to non-rc SDK --- global.json | 2 +- .../Spectre.Console.ImageSharp.csproj | 2 +- src/Extensions/Spectre.Console.Json/Spectre.Console.Json.csproj | 2 +- src/Generator/Generator.csproj | 2 +- src/Spectre.Console.Testing/Spectre.Console.Testing.csproj | 2 +- src/Spectre.Console.Tests/Spectre.Console.Tests.csproj | 2 +- src/Spectre.Console/Spectre.Console.csproj | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/global.json b/global.json index ca25c41e5..d789af363 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "$schema": "http://json.schemastore.org/global", "sdk": { - "version": "10.0.100-rc.2.25502.107", + "version": "10.0.100", "rollForward": "latestFeature" } } diff --git a/src/Extensions/Spectre.Console.ImageSharp/Spectre.Console.ImageSharp.csproj b/src/Extensions/Spectre.Console.ImageSharp/Spectre.Console.ImageSharp.csproj index fff59971e..ed1299d43 100644 --- a/src/Extensions/Spectre.Console.ImageSharp/Spectre.Console.ImageSharp.csproj +++ b/src/Extensions/Spectre.Console.ImageSharp/Spectre.Console.ImageSharp.csproj @@ -1,7 +1,7 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 true A library that extends Spectre.Console with ImageSharp superpowers. diff --git a/src/Extensions/Spectre.Console.Json/Spectre.Console.Json.csproj b/src/Extensions/Spectre.Console.Json/Spectre.Console.Json.csproj index 6c43198fe..13c4279f4 100644 --- a/src/Extensions/Spectre.Console.Json/Spectre.Console.Json.csproj +++ b/src/Extensions/Spectre.Console.Json/Spectre.Console.Json.csproj @@ -1,7 +1,7 @@ - net9.0;net8.0;netstandard2.0 + net10.0;net9.0;net8.0;netstandard2.0 true true A library that extends Spectre.Console with JSON superpowers. diff --git a/src/Generator/Generator.csproj b/src/Generator/Generator.csproj index b8bfc5ccb..64fac0860 100644 --- a/src/Generator/Generator.csproj +++ b/src/Generator/Generator.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 false $(NoWarn);CS8002 diff --git a/src/Spectre.Console.Testing/Spectre.Console.Testing.csproj b/src/Spectre.Console.Testing/Spectre.Console.Testing.csproj index ad92a3536..367360f46 100644 --- a/src/Spectre.Console.Testing/Spectre.Console.Testing.csproj +++ b/src/Spectre.Console.Testing/Spectre.Console.Testing.csproj @@ -1,7 +1,7 @@  - net9.0;net8.0;netstandard2.0 + net10.0;net9.0;net8.0;netstandard2.0 false true Contains testing utilities for Spectre.Console. diff --git a/src/Spectre.Console.Tests/Spectre.Console.Tests.csproj b/src/Spectre.Console.Tests/Spectre.Console.Tests.csproj index 8b1569287..6a0dc6d77 100644 --- a/src/Spectre.Console.Tests/Spectre.Console.Tests.csproj +++ b/src/Spectre.Console.Tests/Spectre.Console.Tests.csproj @@ -1,7 +1,7 @@  - net9.0;net8.0 + net10.0;net9.0;net8.0 false diff --git a/src/Spectre.Console/Spectre.Console.csproj b/src/Spectre.Console/Spectre.Console.csproj index bb56ec607..5a9e1615f 100644 --- a/src/Spectre.Console/Spectre.Console.csproj +++ b/src/Spectre.Console/Spectre.Console.csproj @@ -1,7 +1,7 @@ - net9.0;net8.0;netstandard2.0 + net10.0;net9.0;net8.0;netstandard2.0 true $(DefineConstants)TRACE;WCWIDTH_VISIBILITY_INTERNAL From c8c72b9d727b84c4250b344f818acec7f2ddebcb Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Wed, 12 Nov 2025 21:39:37 +0100 Subject: [PATCH 15/22] Fix build script warning --- build.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/build.cs b/build.cs index cda564fc9..ee098d4fe 100644 --- a/build.cs +++ b/build.cs @@ -1,7 +1,6 @@ #:sdk Cake.Sdk@5.1.25296.94-beta var solution = "./src/Spectre.Console.slnx"; -var generatorSolution = "./resources/scripts/Generator/Generator.slnx"; var testProject = "./src/Spectre.Console.Tests/Spectre.Console.Tests.csproj"; //////////////////////////////////////////////////////////////// From b2f961a1970bcfee3eb4c13ac69df5744375193d Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Wed, 12 Nov 2025 21:43:53 +0100 Subject: [PATCH 16/22] Add support for using C# 14 in solution --- src/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index bd6a369a6..3bf348424 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,7 @@  true - 12 + 14 true embedded true From 1640f23b287f1341cbebff3d1f43cce2e7c226b7 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Wed, 12 Nov 2025 21:44:02 +0100 Subject: [PATCH 17/22] Update dependencies --- src/Directory.Packages.props | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 2b66bc8b6..2ba3a7361 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -3,26 +3,26 @@ true - + - + - + - + - - + + all From 8ac0e518a50770c03ebcddf6441adb59d59641bc Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Wed, 12 Nov 2025 22:15:13 +0100 Subject: [PATCH 18/22] Update exception rendering tests --- ...Exception.Output_exceptionFormats=Default.verified.txt | 8 ++++---- ...Output_exceptionFormats=ShortenEverything.verified.txt | 4 ++++ ...on.Output_exceptionFormats=ShortenMethods.verified.txt | 4 ++++ ...tion.Output_exceptionFormats=ShortenTypes.verified.txt | 8 ++++---- src/Spectre.Console.Tests/Unit/ExceptionTests.cs | 6 ++++-- .../Utilities/TestConsoleExtensions.cs | 3 ++- 6 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenEverything.verified.txt create mode 100644 src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenMethods.verified.txt diff --git a/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=Default.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=Default.verified.txt index 08cbf0782..c9b6b1ec8 100644 --- a/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=Default.verified.txt +++ b/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=Default.verified.txt @@ -1,4 +1,4 @@ -Spectre.Console.Tests.Data.GenericException: Throwing! - at bool Spectre.Console.Tests.Data.TestExceptions.MethodThatThrowsGenericException() in {ProjectDirectory}Data/Exceptions.cs:9 - at void Spectre.Console.Tests.Unit.ExceptionTests.<>c.b__8_0() in {ProjectDirectory}Unit/ExceptionTests.cs:134 - at Exception Spectre.Console.Tests.Unit.ExceptionTests.GetException(Action action) in {ProjectDirectory}Unit/ExceptionTests.cs:147 +Spectre.Console.Tests.Data.GenericException: Throwing! + at bool Spectre.Console.Tests.Data.TestExceptions.MethodThatThrowsGenericException() in /xyz/Exceptions.cs:nn + at void Spectre.Console.Tests.Unit.ExceptionTests.<>c.b__8_0() in /xyz/ExceptionTests.cs:nn + at Exception Spectre.Console.Tests.Unit.ExceptionTests.GetException(Action action) in /xyz/ExceptionTests.cs:nn diff --git a/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenEverything.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenEverything.verified.txt new file mode 100644 index 000000000..07f6a7b7e --- /dev/null +++ b/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenEverything.verified.txt @@ -0,0 +1,4 @@ +GenericException: Throwing! + at bool MethodThatThrowsGenericException() in /xyz/ in Exceptions.cs:nn + at void b__8_0() in /xyz/ in ExceptionTests.cs:nn + at Exception GetException(Action action) in /xyz/ in ExceptionTests.cs:nn diff --git a/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenMethods.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenMethods.verified.txt new file mode 100644 index 000000000..612171096 --- /dev/null +++ b/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenMethods.verified.txt @@ -0,0 +1,4 @@ +Spectre.Console.Tests.Data.GenericException: Throwing! + at bool MethodThatThrowsGenericException() in /xyz/Exceptions.cs:nn + at void b__8_0() in /xyz/ExceptionTests.cs:nn + at Exception GetException(Action action) in /xyz/ExceptionTests.cs:nn diff --git a/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenTypes.verified.txt b/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenTypes.verified.txt index 8da66ac38..045d77711 100644 --- a/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenTypes.verified.txt +++ b/src/Spectre.Console.Tests/Expectations/Exception/GenericException.Output_exceptionFormats=ShortenTypes.verified.txt @@ -1,4 +1,4 @@ -GenericException: Throwing! - at bool Spectre.Console.Tests.Data.TestExceptions.MethodThatThrowsGenericException() in {ProjectDirectory}Data/Exceptions.cs:9 - at void Spectre.Console.Tests.Unit.ExceptionTests.<>c.b__8_0() in {ProjectDirectory}Unit/ExceptionTests.cs:134 - at Exception Spectre.Console.Tests.Unit.ExceptionTests.GetException(Action action) in {ProjectDirectory}Unit/ExceptionTests.cs:147 +GenericException: Throwing! + at bool Spectre.Console.Tests.Data.TestExceptions.MethodThatThrowsGenericException() in /xyz/Exceptions.cs:nn + at void Spectre.Console.Tests.Unit.ExceptionTests.<>c.b__8_0() in /xyz/ExceptionTests.cs:nn + at Exception Spectre.Console.Tests.Unit.ExceptionTests.GetException(Action action) in /xyz/ExceptionTests.cs:nn diff --git a/src/Spectre.Console.Tests/Unit/ExceptionTests.cs b/src/Spectre.Console.Tests/Unit/ExceptionTests.cs index 86c8c654a..0a58f755f 100644 --- a/src/Spectre.Console.Tests/Unit/ExceptionTests.cs +++ b/src/Spectre.Console.Tests/Unit/ExceptionTests.cs @@ -114,7 +114,7 @@ public Task Should_Write_Exception_With_No_StackTrace() { // Given var console = new TestConsole().Width(1024); - var dex = GetException(() => TestExceptions.ThrowWithInnerException()); + var dex = GetException(TestExceptions.ThrowWithInnerException); // When var result = console.WriteNormalizedException(dex, ExceptionFormats.NoStackTrace); @@ -126,11 +126,13 @@ public Task Should_Write_Exception_With_No_StackTrace() [Theory] [InlineData(ExceptionFormats.Default)] [InlineData(ExceptionFormats.ShortenTypes)] + [InlineData(ExceptionFormats.ShortenMethods)] + [InlineData(ExceptionFormats.ShortenEverything)] [Expectation("GenericException")] public Task Should_Write_GenericException(ExceptionFormats exceptionFormats) { // Given - var console = new TestConsole { EmitAnsiSequences = true }.Width(1024); + var console = new TestConsole().Width(1024); var dex = GetException(() => TestExceptions.MethodThatThrowsGenericException()); // When diff --git a/src/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs b/src/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs index d471a4163..9e020fa3d 100644 --- a/src/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs +++ b/src/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs @@ -14,9 +14,10 @@ public static string WriteNormalizedException(this TestConsole console, Exceptio } console.WriteException(ex, formats); + return string.Join("\n", NormalizeStackTrace(console.Output) .NormalizeLineEndings() - .Split(new char[] { '\n' }) + .Split(['\n']) .Select(line => line.TrimEnd())); } From ace1b313838918b6a2b91ff33c5a51923730e4e7 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Wed, 12 Nov 2025 22:15:29 +0100 Subject: [PATCH 19/22] Only do style linting --- build.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cs b/build.cs index ee098d4fe..cca49206f 100644 --- a/build.cs +++ b/build.cs @@ -21,7 +21,7 @@ Task("Lint") .Does(ctx => { - ctx.DotNetFormat(solution, new DotNetFormatSettings + ctx.DotNetFormatStyle(solution, new DotNetFormatSettings { VerifyNoChanges = true, }); From 03d34371b899f8ed710cc5b1334ae715f79ef892 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Wed, 12 Nov 2025 23:10:25 +0100 Subject: [PATCH 20/22] Add (long overdue) blog post about the 0.53 release --- .../2025-10-26-spectre-console-0.53-released.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docs/input/blog/posts/2025-10-26-spectre-console-0.53-released.md diff --git a/docs/input/blog/posts/2025-10-26-spectre-console-0.53-released.md b/docs/input/blog/posts/2025-10-26-spectre-console-0.53-released.md new file mode 100644 index 000000000..6f6179e90 --- /dev/null +++ b/docs/input/blog/posts/2025-10-26-spectre-console-0.53-released.md @@ -0,0 +1,15 @@ +Title: Spectre.Console 0.53.0 released! +Description: Someone said CancellationToken? +Published: 2025-10-26 +Category: Release Notes +Excluded: false +--- + +Version `0.53.0` of Spectre.Console has been released! + +## What's Changed + +* Add top-level CancellationToken support to Spectre.Console.Cli by [@0xced](https://github.com/0xced) in [#1911](https://github.com/spectreconsole/spectre.console/pull/1911) +* Update the Spectre.Console.Cli documentation with CancellationToken by [@0xced](https://github.com/0xced) in [#1920](https://github.com/spectreconsole/spectre.console/pull/1920) + +**Full Changelog**: https://github.com/spectreconsole/spectre.console/compare/0.52.0...0.53.0 \ No newline at end of file From 6288d90bc5094e6b6be558b935a8f18aad8acfa2 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Wed, 12 Nov 2025 23:30:52 +0100 Subject: [PATCH 21/22] Update to Cake.Sdk@6.0.0 --- build.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cs b/build.cs index cca49206f..3a64cc622 100644 --- a/build.cs +++ b/build.cs @@ -1,4 +1,4 @@ -#:sdk Cake.Sdk@5.1.25296.94-beta +#:sdk Cake.Sdk@6.0.0 var solution = "./src/Spectre.Console.slnx"; var testProject = "./src/Spectre.Console.Tests/Spectre.Console.Tests.csproj"; From e097281ca8a50268b1022453fe6efd9112123a28 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Wed, 12 Nov 2025 23:48:32 +0100 Subject: [PATCH 22/22] Add Discord link in docs --- .github/funding.yml | 1 - docs/input/_layout.cshtml | 13 +++++++------ docs/input/sponsors.md | 21 --------------------- 3 files changed, 7 insertions(+), 28 deletions(-) delete mode 100644 .github/funding.yml delete mode 100644 docs/input/sponsors.md diff --git a/.github/funding.yml b/.github/funding.yml deleted file mode 100644 index 49ca39c48..000000000 --- a/.github/funding.yml +++ /dev/null @@ -1 +0,0 @@ -github: patriksvensson \ No newline at end of file diff --git a/docs/input/_layout.cshtml b/docs/input/_layout.cshtml index b0a94d71c..632a86083 100644 --- a/docs/input/_layout.cshtml +++ b/docs/input/_layout.cshtml @@ -125,16 +125,17 @@ c-9 -4 -271 61 -315 78 -29 11 -28 12 79 55 59 24 111 46 114 49 3 3 33 -36
  • - - - Sponsor - + + + Discord + - +
  • - + GitHub icon diff --git a/docs/input/sponsors.md b/docs/input/sponsors.md deleted file mode 100644 index 6309aed41..000000000 --- a/docs/input/sponsors.md +++ /dev/null @@ -1,21 +0,0 @@ -Title: Sponsors -Order: 10 -Description: The longevity of *Spectre.Console* is thanks to the support of our sponsors. ---- - -The following people are [sponsoring](https://github.com/sponsors/patriksvensson) -Spectre.Console to show their support and to ensure the longevity of the project. - -* [Rodney Littles II](https://github.com/RLittlesII) -* [Martin Björkström](https://github.com/bjorkstromm) -* [Dave Glick](https://github.com/daveaglick) -* [Kim Gunnarsson](https://github.com/kimgunnarsson) -* [Andrew McClenaghan](https://github.com/andymac4182) -* [C. Augusto Proiete](https://github.com/augustoproiete) -* [Viktor Elofsson](https://github.com/vktr) -* [Steven Knox](https://github.com/stevenknox) -* [David Pendray](https://github.com/dpen2000) -* [Elmah.io](https://github.com/elmahio) - -I really appreciate it. -**Thank you very much!**