mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-10-31 09:09:25 +08:00 
			
		
		
		
	Use file scoped namespace declarations
This commit is contained in:
		 Patrik Svensson
					Patrik Svensson
				
			
				
					committed by
					
						 Phil Scott
						Phil Scott
					
				
			
			
				
	
			
			
			 Phil Scott
						Phil Scott
					
				
			
						parent
						
							1dbaf50935
						
					
				
				
					commit
					ec1188b837
				
			| @@ -30,6 +30,9 @@ trim_trailing_whitespace = false | ||||
| end_of_line = lf | ||||
|  | ||||
| [*.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 | ||||
|   | ||||
| @@ -1,16 +1,15 @@ | ||||
| using System.ComponentModel; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static partial class Program | ||||
| { | ||||
|     public static partial class Program | ||||
|     public sealed class BarSettings : CommandSettings | ||||
|     { | ||||
|         public sealed class BarSettings : CommandSettings | ||||
|         { | ||||
|             [CommandOption("--count")] | ||||
|             [Description("The number of bars to print")] | ||||
|             [DefaultValue(1)] | ||||
|             public int Count { get; set; } | ||||
|         } | ||||
|         [CommandOption("--count")] | ||||
|         [Description("The number of bars to print")] | ||||
|         [DefaultValue(1)] | ||||
|         public int Count { get; set; } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,38 +1,37 @@ | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static partial class Program | ||||
| { | ||||
|     public static partial class Program | ||||
|     public static int Main(string[] args) | ||||
|     { | ||||
|         public static int Main(string[] args) | ||||
|         var app = new CommandApp(); | ||||
|         app.Configure(config => | ||||
|         { | ||||
|             var app = new CommandApp(); | ||||
|             app.Configure(config => | ||||
|             { | ||||
|                 config.AddDelegate("foo", Foo) | ||||
|                     .WithDescription("Foos the bars"); | ||||
|             config.AddDelegate("foo", Foo) | ||||
|                 .WithDescription("Foos the bars"); | ||||
|  | ||||
|                 config.AddDelegate<BarSettings>("bar", Bar) | ||||
|                     .WithDescription("Bars the foos"); ; | ||||
|             }); | ||||
|             config.AddDelegate<BarSettings>("bar", Bar) | ||||
|                 .WithDescription("Bars the foos"); ; | ||||
|         }); | ||||
|  | ||||
|             return app.Run(args); | ||||
|         return app.Run(args); | ||||
|     } | ||||
|  | ||||
|     private static int Foo(CommandContext context) | ||||
|     { | ||||
|         AnsiConsole.WriteLine("Foo"); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     private static int Bar(CommandContext context, BarSettings settings) | ||||
|     { | ||||
|         for (var index = 0; index < settings.Count; index++) | ||||
|         { | ||||
|             AnsiConsole.WriteLine("Bar"); | ||||
|         } | ||||
|  | ||||
|         private static int Foo(CommandContext context) | ||||
|         { | ||||
|             AnsiConsole.WriteLine("Foo"); | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         private static int Bar(CommandContext context, BarSettings settings) | ||||
|         { | ||||
|             for (var index = 0; index < settings.Count; index++) | ||||
|             { | ||||
|                 AnsiConsole.WriteLine("Bar"); | ||||
|             } | ||||
|  | ||||
|             return 0; | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,46 +2,45 @@ using System.ComponentModel; | ||||
| using Demo.Utilities; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Demo.Commands | ||||
| namespace Demo.Commands; | ||||
|  | ||||
| [Description("Add a NuGet package reference to the project.")] | ||||
| public sealed class AddPackageCommand : Command<AddPackageCommand.Settings> | ||||
| { | ||||
|     [Description("Add a NuGet package reference to the project.")] | ||||
|     public sealed class AddPackageCommand : Command<AddPackageCommand.Settings> | ||||
|     public sealed class Settings : AddSettings | ||||
|     { | ||||
|         public sealed class Settings : AddSettings | ||||
|         { | ||||
|             [CommandArgument(0, "<PACKAGENAME>")] | ||||
|             [Description("The package reference to add.")] | ||||
|             public string PackageName { get; set; } | ||||
|         [CommandArgument(0, "<PACKAGENAME>")] | ||||
|         [Description("The package reference to add.")] | ||||
|         public string PackageName { get; set; } | ||||
|  | ||||
|             [CommandOption("-v|--version <VERSION>")] | ||||
|             [Description("The version of the package to add.")] | ||||
|             public string Version { get; set; } | ||||
|         [CommandOption("-v|--version <VERSION>")] | ||||
|         [Description("The version of the package to add.")] | ||||
|         public string Version { get; set; } | ||||
|  | ||||
|             [CommandOption("-f|--framework <FRAMEWORK>")] | ||||
|             [Description("Add the reference only when targeting a specific framework.")] | ||||
|             public string Framework { get; set; } | ||||
|         [CommandOption("-f|--framework <FRAMEWORK>")] | ||||
|         [Description("Add the reference only when targeting a specific framework.")] | ||||
|         public string Framework { get; set; } | ||||
|  | ||||
|             [CommandOption("--no-restore")] | ||||
|             [Description("Add the reference without performing restore preview and compatibility check.")] | ||||
|             public bool NoRestore { get; set; } | ||||
|         [CommandOption("--no-restore")] | ||||
|         [Description("Add the reference without performing restore preview and compatibility check.")] | ||||
|         public bool NoRestore { get; set; } | ||||
|  | ||||
|             [CommandOption("--source <SOURCE>")] | ||||
|             [Description("The NuGet package source to use during the restore.")] | ||||
|             public string Source { get; set; } | ||||
|         [CommandOption("--source <SOURCE>")] | ||||
|         [Description("The NuGet package source to use during the restore.")] | ||||
|         public string Source { get; set; } | ||||
|  | ||||
|             [CommandOption("--package-directory <PACKAGEDIR>")] | ||||
|             [Description("The directory to restore packages to.")] | ||||
|             public string PackageDirectory { get; set; } | ||||
|         [CommandOption("--package-directory <PACKAGEDIR>")] | ||||
|         [Description("The directory to restore packages to.")] | ||||
|         public string PackageDirectory { get; set; } | ||||
|  | ||||
|             [CommandOption("--interactive")] | ||||
|             [Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")] | ||||
|             public bool Interactive { get; set; } | ||||
|         } | ||||
|         [CommandOption("--interactive")] | ||||
|         [Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")] | ||||
|         public bool Interactive { get; set; } | ||||
|     } | ||||
|  | ||||
|         public override int Execute(CommandContext context, Settings settings) | ||||
|         { | ||||
|             SettingsDumper.Dump(settings); | ||||
|             return 0; | ||||
|         } | ||||
|     public override int Execute(CommandContext context, Settings settings) | ||||
|     { | ||||
|         SettingsDumper.Dump(settings); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,29 +2,28 @@ using System.ComponentModel; | ||||
| using Demo.Utilities; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Demo.Commands | ||||
| namespace Demo.Commands; | ||||
|  | ||||
| public sealed class AddReferenceCommand : Command<AddReferenceCommand.Settings> | ||||
| { | ||||
|     public sealed class AddReferenceCommand : Command<AddReferenceCommand.Settings> | ||||
|     public sealed class Settings : AddSettings | ||||
|     { | ||||
|         public sealed class Settings : AddSettings | ||||
|         { | ||||
|             [CommandArgument(0, "<PROJECTPATH>")] | ||||
|             [Description("The package reference to add.")] | ||||
|             public string ProjectPath { get; set; } | ||||
|         [CommandArgument(0, "<PROJECTPATH>")] | ||||
|         [Description("The package reference to add.")] | ||||
|         public string ProjectPath { get; set; } | ||||
|  | ||||
|             [CommandOption("-f|--framework <FRAMEWORK>")] | ||||
|             [Description("Add the reference only when targeting a specific framework.")] | ||||
|             public string Framework { get; set; } | ||||
|         [CommandOption("-f|--framework <FRAMEWORK>")] | ||||
|         [Description("Add the reference only when targeting a specific framework.")] | ||||
|         public string Framework { get; set; } | ||||
|  | ||||
|             [CommandOption("--interactive")] | ||||
|             [Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")] | ||||
|             public bool Interactive { get; set; } | ||||
|         } | ||||
|         [CommandOption("--interactive")] | ||||
|         [Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")] | ||||
|         public bool Interactive { get; set; } | ||||
|     } | ||||
|  | ||||
|         public override int Execute(CommandContext context, Settings settings) | ||||
|         { | ||||
|             SettingsDumper.Dump(settings); | ||||
|             return 0; | ||||
|         } | ||||
|     public override int Execute(CommandContext context, Settings settings) | ||||
|     { | ||||
|         SettingsDumper.Dump(settings); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,12 +1,11 @@ | ||||
| using System.ComponentModel; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Demo.Commands | ||||
| namespace Demo.Commands; | ||||
|  | ||||
| public abstract class AddSettings : CommandSettings | ||||
| { | ||||
|     public abstract class AddSettings : CommandSettings | ||||
|     { | ||||
|         [CommandArgument(0, "<PROJECT>")] | ||||
|         [Description("The project file to operate on. If a file is not specified, the command will search the current directory for one.")] | ||||
|         public string Project { get; set; } | ||||
|     } | ||||
|     [CommandArgument(0, "<PROJECT>")] | ||||
|     [Description("The project file to operate on. If a file is not specified, the command will search the current directory for one.")] | ||||
|     public string Project { get; set; } | ||||
| } | ||||
|   | ||||
| @@ -2,69 +2,68 @@ using System.ComponentModel; | ||||
| using Demo.Utilities; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Demo.Commands | ||||
| namespace Demo.Commands; | ||||
|  | ||||
| [Description("Build and run a .NET project output.")] | ||||
| public sealed class RunCommand : Command<RunCommand.Settings> | ||||
| { | ||||
|     [Description("Build and run a .NET project output.")] | ||||
|     public sealed class RunCommand : Command<RunCommand.Settings> | ||||
|     public sealed class Settings : CommandSettings | ||||
|     { | ||||
|         public sealed class Settings : CommandSettings | ||||
|         { | ||||
|             [CommandOption("-c|--configuration <CONFIGURATION>")] | ||||
|             [Description("The configuration to run for. The default for most projects is '[grey]Debug[/]'.")] | ||||
|             [DefaultValue("Debug")] | ||||
|             public string Configuration { get; set; } | ||||
|         [CommandOption("-c|--configuration <CONFIGURATION>")] | ||||
|         [Description("The configuration to run for. The default for most projects is '[grey]Debug[/]'.")] | ||||
|         [DefaultValue("Debug")] | ||||
|         public string Configuration { get; set; } | ||||
|  | ||||
|             [CommandOption("-f|--framework <FRAMEWORK>")] | ||||
|             [Description("The target framework to run for. The target framework must also be specified in the project file.")] | ||||
|             public string Framework { get; set; } | ||||
|         [CommandOption("-f|--framework <FRAMEWORK>")] | ||||
|         [Description("The target framework to run for. The target framework must also be specified in the project file.")] | ||||
|         public string Framework { get; set; } | ||||
|  | ||||
|             [CommandOption("-r|--runtime <RUNTIMEIDENTIFIER>")] | ||||
|             [Description("The target runtime to run for.")] | ||||
|             public string RuntimeIdentifier { get; set; } | ||||
|         [CommandOption("-r|--runtime <RUNTIMEIDENTIFIER>")] | ||||
|         [Description("The target runtime to run for.")] | ||||
|         public string RuntimeIdentifier { get; set; } | ||||
|  | ||||
|             [CommandOption("-p|--project <PROJECTPATH>")] | ||||
|             [Description("The path to the project file to run (defaults to the current directory if there is only one project).")] | ||||
|             public string ProjectPath { get; set; } | ||||
|         [CommandOption("-p|--project <PROJECTPATH>")] | ||||
|         [Description("The path to the project file to run (defaults to the current directory if there is only one project).")] | ||||
|         public string ProjectPath { get; set; } | ||||
|  | ||||
|             [CommandOption("--launch-profile <LAUNCHPROFILE>")] | ||||
|             [Description("The name of the launch profile (if any) to use when launching the application.")] | ||||
|             public string LaunchProfile { get; set; } | ||||
|         [CommandOption("--launch-profile <LAUNCHPROFILE>")] | ||||
|         [Description("The name of the launch profile (if any) to use when launching the application.")] | ||||
|         public string LaunchProfile { get; set; } | ||||
|  | ||||
|             [CommandOption("--no-launch-profile")] | ||||
|             [Description("Do not attempt to use [grey]launchSettings.json[/] to configure the application.")] | ||||
|             public bool NoLaunchProfile { get; set; } | ||||
|         [CommandOption("--no-launch-profile")] | ||||
|         [Description("Do not attempt to use [grey]launchSettings.json[/] to configure the application.")] | ||||
|         public bool NoLaunchProfile { get; set; } | ||||
|  | ||||
|             [CommandOption("--no-build")] | ||||
|             [Description("Do not build the project before running. Implies [grey]--no-restore[/].")] | ||||
|             public bool NoBuild { get; set; } | ||||
|         [CommandOption("--no-build")] | ||||
|         [Description("Do not build the project before running. Implies [grey]--no-restore[/].")] | ||||
|         public bool NoBuild { get; set; } | ||||
|  | ||||
|             [CommandOption("--interactive")] | ||||
|             [Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")] | ||||
|             public string Interactive { get; set; } | ||||
|         [CommandOption("--interactive")] | ||||
|         [Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")] | ||||
|         public string Interactive { get; set; } | ||||
|  | ||||
|             [CommandOption("--no-restore")] | ||||
|             [Description("Do not restore the project before building.")] | ||||
|             public bool NoRestore { get; set; } | ||||
|         [CommandOption("--no-restore")] | ||||
|         [Description("Do not restore the project before building.")] | ||||
|         public bool NoRestore { get; set; } | ||||
|  | ||||
|             [CommandOption("--verbosity <VERBOSITY>")] | ||||
|             [Description("Set the MSBuild verbosity level. Allowed values are q[grey]uiet[/], m[grey]inimal[/], n[grey]ormal[/], d[grey]etailed[/], and diag[grey]nostic[/].")] | ||||
|             [TypeConverter(typeof(VerbosityConverter))] | ||||
|             [DefaultValue(Verbosity.Normal)] | ||||
|             public Verbosity Verbosity { get; set; } | ||||
|         [CommandOption("--verbosity <VERBOSITY>")] | ||||
|         [Description("Set the MSBuild verbosity level. Allowed values are q[grey]uiet[/], m[grey]inimal[/], n[grey]ormal[/], d[grey]etailed[/], and diag[grey]nostic[/].")] | ||||
|         [TypeConverter(typeof(VerbosityConverter))] | ||||
|         [DefaultValue(Verbosity.Normal)] | ||||
|         public Verbosity Verbosity { get; set; } | ||||
|  | ||||
|             [CommandOption("--no-dependencies")] | ||||
|             [Description("Do not restore project-to-project references and only restore the specified project.")] | ||||
|             public bool NoDependencies { get; set; } | ||||
|         [CommandOption("--no-dependencies")] | ||||
|         [Description("Do not restore project-to-project references and only restore the specified project.")] | ||||
|         public bool NoDependencies { get; set; } | ||||
|  | ||||
|             [CommandOption("--force")] | ||||
|             [Description("Force all dependencies to be resolved even if the last restore was successful. This is equivalent to deleting [grey]project.assets.json[/].")] | ||||
|             public bool Force { get; set; } | ||||
|         } | ||||
|         [CommandOption("--force")] | ||||
|         [Description("Force all dependencies to be resolved even if the last restore was successful. This is equivalent to deleting [grey]project.assets.json[/].")] | ||||
|         public bool Force { get; set; } | ||||
|     } | ||||
|  | ||||
|         public override int Execute(CommandContext context, Settings settings) | ||||
|         { | ||||
|             SettingsDumper.Dump(settings); | ||||
|             return 0; | ||||
|         } | ||||
|     public override int Execute(CommandContext context, Settings settings) | ||||
|     { | ||||
|         SettingsDumper.Dump(settings); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,39 +3,38 @@ using System.ComponentModel; | ||||
| using Demo.Utilities; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Demo.Commands | ||||
| namespace Demo.Commands; | ||||
|  | ||||
| [Description("Launches a web server in the current working directory and serves all files in it.")] | ||||
| public sealed class ServeCommand : Command<ServeCommand.Settings> | ||||
| { | ||||
|     [Description("Launches a web server in the current working directory and serves all files in it.")] | ||||
|     public sealed class ServeCommand : Command<ServeCommand.Settings> | ||||
|     public sealed class Settings : CommandSettings | ||||
|     { | ||||
|         public sealed class Settings : CommandSettings | ||||
|         { | ||||
|             [CommandOption("-p|--port <PORT>")] | ||||
|             [Description("Port to use. Defaults to [grey]8080[/]. Use [grey]0[/] for a dynamic port.")] | ||||
|             public int Port { get; set; } | ||||
|         [CommandOption("-p|--port <PORT>")] | ||||
|         [Description("Port to use. Defaults to [grey]8080[/]. Use [grey]0[/] for a dynamic port.")] | ||||
|         public int Port { get; set; } | ||||
|  | ||||
|             [CommandOption("-o|--open-browser [BROWSER]")] | ||||
|             [Description("Open a web browser when the server starts. You can also specify which browser to use. If none is specified, the default one will be used.")] | ||||
|             public FlagValue<string> OpenBrowser { get; set; } | ||||
|         } | ||||
|         [CommandOption("-o|--open-browser [BROWSER]")] | ||||
|         [Description("Open a web browser when the server starts. You can also specify which browser to use. If none is specified, the default one will be used.")] | ||||
|         public FlagValue<string> OpenBrowser { get; set; } | ||||
|     } | ||||
|  | ||||
|         public override int Execute(CommandContext context, Settings settings) | ||||
|     public override int Execute(CommandContext context, Settings settings) | ||||
|     { | ||||
|         if (settings.OpenBrowser.IsSet) | ||||
|         { | ||||
|             if (settings.OpenBrowser.IsSet) | ||||
|             var browser = settings.OpenBrowser.Value; | ||||
|             if (browser != null) | ||||
|             { | ||||
|                 var browser = settings.OpenBrowser.Value; | ||||
|                 if (browser != null) | ||||
|                 { | ||||
|                     Console.WriteLine($"Open in {browser}"); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     Console.WriteLine($"Open in default browser."); | ||||
|                 } | ||||
|                 Console.WriteLine($"Open in {browser}"); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 Console.WriteLine($"Open in default browser."); | ||||
|             } | ||||
|  | ||||
|             SettingsDumper.Dump(settings); | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         SettingsDumper.Dump(settings); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,37 +1,36 @@ | ||||
| using Demo.Commands; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Demo | ||||
| namespace Demo; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static int Main(string[] args) | ||||
|     { | ||||
|         public static int Main(string[] args) | ||||
|         var app = new CommandApp(); | ||||
|         app.Configure(config => | ||||
|         { | ||||
|             var app = new CommandApp(); | ||||
|             app.Configure(config => | ||||
|             { | ||||
|                 config.SetApplicationName("fake-dotnet"); | ||||
|                 config.ValidateExamples(); | ||||
|                 config.AddExample(new[] { "run", "--no-build" }); | ||||
|             config.SetApplicationName("fake-dotnet"); | ||||
|             config.ValidateExamples(); | ||||
|             config.AddExample(new[] { "run", "--no-build" }); | ||||
|  | ||||
|                 // Run | ||||
|                 config.AddCommand<RunCommand>("run"); | ||||
|  | ||||
|                 // Add | ||||
|                 config.AddBranch<AddSettings>("add", add => | ||||
|                 { | ||||
|                     add.SetDescription("Add a package or reference to a .NET project"); | ||||
|                     add.AddCommand<AddPackageCommand>("package"); | ||||
|                     add.AddCommand<AddReferenceCommand>("reference"); | ||||
|                 }); | ||||
|             { | ||||
|                 add.SetDescription("Add a package or reference to a .NET project"); | ||||
|                 add.AddCommand<AddPackageCommand>("package"); | ||||
|                 add.AddCommand<AddReferenceCommand>("reference"); | ||||
|             }); | ||||
|  | ||||
|                 // Serve | ||||
|                 config.AddCommand<ServeCommand>("serve") | ||||
|                     .WithExample(new[] { "serve", "-o", "firefox" }) | ||||
|                     .WithExample(new[] { "serve", "--port", "80", "-o", "firefox" }); | ||||
|             }); | ||||
|                 .WithExample(new[] { "serve", "-o", "firefox" }) | ||||
|                 .WithExample(new[] { "serve", "--port", "80", "-o", "firefox" }); | ||||
|         }); | ||||
|  | ||||
|             return app.Run(args); | ||||
|         } | ||||
|         return app.Run(args); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,29 +1,28 @@ | ||||
| using Spectre.Console; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Demo.Utilities | ||||
| namespace Demo.Utilities; | ||||
|  | ||||
| public static class SettingsDumper | ||||
| { | ||||
|     public static class SettingsDumper | ||||
|     public static void Dump(CommandSettings settings) | ||||
|     { | ||||
|         public static void Dump(CommandSettings settings) | ||||
|         var table = new Table().RoundedBorder(); | ||||
|         table.AddColumn("[grey]Name[/]"); | ||||
|         table.AddColumn("[grey]Value[/]"); | ||||
|  | ||||
|         var properties = settings.GetType().GetProperties(); | ||||
|         foreach (var property in properties) | ||||
|         { | ||||
|             var table = new Table().RoundedBorder(); | ||||
|             table.AddColumn("[grey]Name[/]"); | ||||
|             table.AddColumn("[grey]Value[/]"); | ||||
|             var value = property.GetValue(settings) | ||||
|                 ?.ToString() | ||||
|                 ?.Replace("[", "[["); | ||||
|  | ||||
|             var properties = settings.GetType().GetProperties(); | ||||
|             foreach (var property in properties) | ||||
|             { | ||||
|                 var value = property.GetValue(settings) | ||||
|                     ?.ToString() | ||||
|                     ?.Replace("[", "[["); | ||||
|  | ||||
|                 table.AddRow( | ||||
|                     property.Name, | ||||
|                     value ?? "[grey]null[/]"); | ||||
|             } | ||||
|  | ||||
|             AnsiConsole.Write(table); | ||||
|             table.AddRow( | ||||
|                 property.Name, | ||||
|                 value ?? "[grey]null[/]"); | ||||
|         } | ||||
|  | ||||
|         AnsiConsole.Write(table); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,24 +3,24 @@ using System.Collections.Generic; | ||||
| using System.ComponentModel; | ||||
| using System.Globalization; | ||||
|  | ||||
| namespace Demo | ||||
| namespace Demo; | ||||
|  | ||||
| public enum Verbosity | ||||
| { | ||||
|     public enum Verbosity | ||||
|     { | ||||
|         Quiet, | ||||
|         Minimal, | ||||
|         Normal, | ||||
|         Detailed, | ||||
|         Diagnostic | ||||
|     } | ||||
|     Quiet, | ||||
|     Minimal, | ||||
|     Normal, | ||||
|     Detailed, | ||||
|     Diagnostic | ||||
| } | ||||
|  | ||||
|     public sealed class VerbosityConverter : TypeConverter | ||||
|     { | ||||
|         private readonly Dictionary<string, Verbosity> _lookup; | ||||
| public sealed class VerbosityConverter : TypeConverter | ||||
| { | ||||
|     private readonly Dictionary<string, Verbosity> _lookup; | ||||
|  | ||||
|         public VerbosityConverter() | ||||
|         { | ||||
|             _lookup = new Dictionary<string, Verbosity>(StringComparer.OrdinalIgnoreCase) | ||||
|     public VerbosityConverter() | ||||
|     { | ||||
|         _lookup = new Dictionary<string, Verbosity>(StringComparer.OrdinalIgnoreCase) | ||||
|             { | ||||
|                 { "q", Verbosity.Quiet }, | ||||
|                 { "quiet", Verbosity.Quiet }, | ||||
| @@ -33,22 +33,21 @@ namespace Demo | ||||
|                 { "diag", Verbosity.Diagnostic }, | ||||
|                 { "diagnostic", Verbosity.Diagnostic } | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) | ||||
|     public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) | ||||
|     { | ||||
|         if (value is string stringValue) | ||||
|         { | ||||
|             if (value is string stringValue) | ||||
|             var result = _lookup.TryGetValue(stringValue, out var verbosity); | ||||
|             if (!result) | ||||
|             { | ||||
|                 var result = _lookup.TryGetValue(stringValue, out var verbosity); | ||||
|                 if (!result) | ||||
|                 { | ||||
|                     const string format = "The value '{0}' is not a valid verbosity."; | ||||
|                     var message = string.Format(CultureInfo.InvariantCulture, format, value); | ||||
|                     throw new InvalidOperationException(message); | ||||
|                 } | ||||
|                 return verbosity; | ||||
|                 const string format = "The value '{0}' is not a valid verbosity."; | ||||
|                 var message = string.Format(CultureInfo.InvariantCulture, format, value); | ||||
|                 throw new InvalidOperationException(message); | ||||
|             } | ||||
|             throw new NotSupportedException("Can't convert value to verbosity."); | ||||
|             return verbosity; | ||||
|         } | ||||
|         throw new NotSupportedException("Can't convert value to verbosity."); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,20 +1,19 @@ | ||||
| using System; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| { | ||||
|     public sealed class MyCommand : Command | ||||
|     { | ||||
|         public override int Execute(CommandContext context) | ||||
|         { | ||||
|             if (!(context.Data is int data)) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Command has no associated data."); | ||||
|                  | ||||
|             } | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public sealed class MyCommand : Command | ||||
| { | ||||
|     public override int Execute(CommandContext context) | ||||
|     { | ||||
|         if (!(context.Data is int data)) | ||||
|         { | ||||
|             throw new InvalidOperationException("Command has no associated data."); | ||||
|  | ||||
|             AnsiConsole.WriteLine("Value = {0}", data); | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         AnsiConsole.WriteLine("Value = {0}", data); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,24 +1,23 @@ | ||||
| using System.Linq; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| { | ||||
|     public static class Program | ||||
|     { | ||||
|         public static int Main(string[] args) | ||||
|         { | ||||
|             var app = new CommandApp(); | ||||
|             app.Configure(config => | ||||
|             { | ||||
|                 foreach(var index in Enumerable.Range(1, 10)) | ||||
|                 { | ||||
|                     config.AddCommand<MyCommand>($"c{index}") | ||||
|                         .WithDescription($"Prints the number {index}") | ||||
|                         .WithData(index); | ||||
|                 } | ||||
|             }); | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
|             return app.Run(args); | ||||
|         } | ||||
| public static class Program | ||||
| { | ||||
|     public static int Main(string[] args) | ||||
|     { | ||||
|         var app = new CommandApp(); | ||||
|         app.Configure(config => | ||||
|         { | ||||
|             foreach (var index in Enumerable.Range(1, 10)) | ||||
|             { | ||||
|                 config.AddCommand<MyCommand>($"c{index}") | ||||
|                     .WithDescription($"Prints the number {index}") | ||||
|                     .WithData(index); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         return app.Run(args); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,29 +2,28 @@ using System; | ||||
| using System.ComponentModel; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public sealed class DefaultCommand : Command<DefaultCommand.Settings> | ||||
| { | ||||
|     public sealed class DefaultCommand : Command<DefaultCommand.Settings> | ||||
|     private readonly IGreeter _greeter; | ||||
|  | ||||
|     public sealed class Settings : CommandSettings | ||||
|     { | ||||
|         private readonly IGreeter _greeter; | ||||
|         [CommandOption("-n|--name <NAME>")] | ||||
|         [Description("The person or thing to greet.")] | ||||
|         [DefaultValue("World")] | ||||
|         public string Name { get; set; } | ||||
|     } | ||||
|  | ||||
|         public sealed class Settings : CommandSettings | ||||
|         { | ||||
|             [CommandOption("-n|--name <NAME>")] | ||||
|             [Description("The person or thing to greet.")] | ||||
|             [DefaultValue("World")] | ||||
|             public string Name { get; set; } | ||||
|         } | ||||
|     public DefaultCommand(IGreeter greeter) | ||||
|     { | ||||
|         _greeter = greeter ?? throw new ArgumentNullException(nameof(greeter)); | ||||
|     } | ||||
|  | ||||
|         public DefaultCommand(IGreeter greeter) | ||||
|         { | ||||
|             _greeter = greeter ?? throw new ArgumentNullException(nameof(greeter)); | ||||
|         } | ||||
|  | ||||
|         public override int Execute(CommandContext context, Settings settings) | ||||
|         { | ||||
|             _greeter.Greet(settings.Name); | ||||
|             return 0; | ||||
|         } | ||||
|     public override int Execute(CommandContext context, Settings settings) | ||||
|     { | ||||
|         _greeter.Greet(settings.Name); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,15 +1,14 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| { | ||||
|     public interface IGreeter | ||||
|     { | ||||
|         void Greet(string name); | ||||
|     } | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
|     public sealed class HelloWorldGreeter : IGreeter | ||||
| public interface IGreeter | ||||
| { | ||||
|     void Greet(string name); | ||||
| } | ||||
|  | ||||
| public sealed class HelloWorldGreeter : IGreeter | ||||
| { | ||||
|     public void Greet(string name) | ||||
|     { | ||||
|         public void Greet(string name) | ||||
|         { | ||||
|             AnsiConsole.WriteLine($"Hello {name}!"); | ||||
|         } | ||||
|         AnsiConsole.WriteLine($"Hello {name}!"); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,40 +2,39 @@ using System; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public sealed class TypeRegistrar : ITypeRegistrar | ||||
| { | ||||
|     public sealed class TypeRegistrar : ITypeRegistrar | ||||
|     private readonly IServiceCollection _builder; | ||||
|  | ||||
|     public TypeRegistrar(IServiceCollection builder) | ||||
|     { | ||||
|         private readonly IServiceCollection _builder; | ||||
|         _builder = builder; | ||||
|     } | ||||
|  | ||||
|         public TypeRegistrar(IServiceCollection builder) | ||||
|     public ITypeResolver Build() | ||||
|     { | ||||
|         return new TypeResolver(_builder.BuildServiceProvider()); | ||||
|     } | ||||
|  | ||||
|     public void Register(Type service, Type implementation) | ||||
|     { | ||||
|         _builder.AddSingleton(service, implementation); | ||||
|     } | ||||
|  | ||||
|     public void RegisterInstance(Type service, object implementation) | ||||
|     { | ||||
|         _builder.AddSingleton(service, implementation); | ||||
|     } | ||||
|  | ||||
|     public void RegisterLazy(Type service, Func<object> func) | ||||
|     { | ||||
|         if (func is null) | ||||
|         { | ||||
|             _builder = builder; | ||||
|             throw new ArgumentNullException(nameof(func)); | ||||
|         } | ||||
|  | ||||
|         public ITypeResolver Build() | ||||
|         { | ||||
|             return new TypeResolver(_builder.BuildServiceProvider()); | ||||
|         } | ||||
|  | ||||
|         public void Register(Type service, Type implementation) | ||||
|         { | ||||
|             _builder.AddSingleton(service, implementation); | ||||
|         } | ||||
|  | ||||
|         public void RegisterInstance(Type service, object implementation) | ||||
|         { | ||||
|             _builder.AddSingleton(service, implementation); | ||||
|         } | ||||
|  | ||||
|         public void RegisterLazy(Type service, Func<object> func) | ||||
|         { | ||||
|             if (func is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(func)); | ||||
|             } | ||||
|  | ||||
|             _builder.AddSingleton(service, (provider) => func()); | ||||
|         } | ||||
|         _builder.AddSingleton(service, (provider) => func()); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,33 +2,32 @@ using System; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public sealed class TypeResolver : ITypeResolver, IDisposable | ||||
| { | ||||
|     public sealed class TypeResolver : ITypeResolver, IDisposable | ||||
|     private readonly IServiceProvider _provider; | ||||
|  | ||||
|     public TypeResolver(IServiceProvider provider) | ||||
|     { | ||||
|         private readonly IServiceProvider _provider; | ||||
|         _provider = provider ?? throw new ArgumentNullException(nameof(provider)); | ||||
|     } | ||||
|  | ||||
|         public TypeResolver(IServiceProvider provider) | ||||
|     public object Resolve(Type type) | ||||
|     { | ||||
|         if (type == null) | ||||
|         { | ||||
|             _provider = provider ?? throw new ArgumentNullException(nameof(provider)); | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         public object Resolve(Type type) | ||||
|         { | ||||
|             if (type == null) | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
|         return _provider.GetService(type); | ||||
|     } | ||||
|  | ||||
|             return _provider.GetService(type); | ||||
|         } | ||||
|  | ||||
|         public void Dispose() | ||||
|     public void Dispose() | ||||
|     { | ||||
|         if (_provider is IDisposable disposable) | ||||
|         { | ||||
|             if (_provider is IDisposable disposable) | ||||
|             { | ||||
|                 disposable.Dispose(); | ||||
|             } | ||||
|             disposable.Dispose(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,22 +1,21 @@ | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| { | ||||
|     public class Program | ||||
|     { | ||||
|         public static int Main(string[] args) | ||||
|         { | ||||
|             // Create a type registrar and register any dependencies. | ||||
|             // A type registrar is an adapter for a DI framework. | ||||
|             var registrations = new ServiceCollection(); | ||||
|             registrations.AddSingleton<IGreeter, HelloWorldGreeter>(); | ||||
|             var registrar = new TypeRegistrar(registrations); | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
|             // Create a new command app with the registrar | ||||
|             // and run it with the provided arguments. | ||||
|             var app = new CommandApp<DefaultCommand>(registrar); | ||||
|             return app.Run(args); | ||||
|         } | ||||
| public class Program | ||||
| { | ||||
|     public static int Main(string[] args) | ||||
|     { | ||||
|         // Create a type registrar and register any dependencies. | ||||
|         // A type registrar is an adapter for a DI framework. | ||||
|         var registrations = new ServiceCollection(); | ||||
|         registrations.AddSingleton<IGreeter, HelloWorldGreeter>(); | ||||
|         var registrar = new TypeRegistrar(registrations); | ||||
|  | ||||
|         // Create a new command app with the registrar | ||||
|         // and run it with the provided arguments. | ||||
|         var app = new CommandApp<DefaultCommand>(registrar); | ||||
|         return app.Run(args); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,34 +1,33 @@ | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public class HelloCommand : Command<HelloCommand.Settings> | ||||
| { | ||||
|     public class HelloCommand : Command<HelloCommand.Settings> | ||||
|     private ILogger<HelloCommand> _logger; | ||||
|     private IAnsiConsole _console; | ||||
|  | ||||
|     public HelloCommand(IAnsiConsole console, ILogger<HelloCommand> logger) | ||||
|     { | ||||
|         private ILogger<HelloCommand> _logger; | ||||
|         private IAnsiConsole _console; | ||||
|  | ||||
|         public HelloCommand(IAnsiConsole console, ILogger<HelloCommand> logger) | ||||
|         { | ||||
|             _console = console; | ||||
|             _logger = logger; | ||||
|             _logger.LogDebug("{0} initialized", nameof(HelloCommand)); | ||||
|         } | ||||
|  | ||||
|         public class Settings : LogCommandSettings | ||||
|         { | ||||
|             [CommandArgument(0, "[Name]")] | ||||
|             public string Name { get; set; } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public override int Execute(CommandContext context, Settings settings) | ||||
|         { | ||||
|             _logger.LogInformation("Starting my command"); | ||||
|             AnsiConsole.MarkupLine($"Hello, [blue]{settings.Name}[/]"); | ||||
|             _logger.LogInformation("Completed my command"); | ||||
|  | ||||
|             return 0; | ||||
|         } | ||||
|         _console = console; | ||||
|         _logger = logger; | ||||
|         _logger.LogDebug("{0} initialized", nameof(HelloCommand)); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     public class Settings : LogCommandSettings | ||||
|     { | ||||
|         [CommandArgument(0, "[Name]")] | ||||
|         public string Name { get; set; } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public override int Execute(CommandContext context, Settings settings) | ||||
|     { | ||||
|         _logger.LogInformation("Starting my command"); | ||||
|         AnsiConsole.MarkupLine($"Hello, [blue]{settings.Name}[/]"); | ||||
|         _logger.LogInformation("Completed my command"); | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -5,28 +5,28 @@ using System.Globalization; | ||||
| using Serilog.Events; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public class LogCommandSettings : CommandSettings | ||||
| { | ||||
|     public class LogCommandSettings : CommandSettings | ||||
|     [CommandOption("--logFile")] | ||||
|     [Description("Path and file name for logging")] | ||||
|     public string LogFile { get; set; } | ||||
|  | ||||
|     [CommandOption("--logLevel")] | ||||
|     [Description("Minimum level for logging")] | ||||
|     [TypeConverter(typeof(VerbosityConverter))] | ||||
|     [DefaultValue(LogEventLevel.Information)] | ||||
|     public LogEventLevel LogLevel { get; set; } | ||||
| } | ||||
|  | ||||
| public sealed class VerbosityConverter : TypeConverter | ||||
| { | ||||
|     private readonly Dictionary<string, LogEventLevel> _lookup; | ||||
|  | ||||
|     public VerbosityConverter() | ||||
|     { | ||||
|         [CommandOption("--logFile")] | ||||
|         [Description("Path and file name for logging")] | ||||
|         public string LogFile { get; set; } | ||||
|  | ||||
|         [CommandOption("--logLevel")] | ||||
|         [Description("Minimum level for logging")] | ||||
|         [TypeConverter(typeof(VerbosityConverter))] | ||||
|         [DefaultValue(LogEventLevel.Information)] | ||||
|         public LogEventLevel LogLevel { get; set; } | ||||
|     } | ||||
|  | ||||
|     public sealed class VerbosityConverter : TypeConverter | ||||
|     { | ||||
|         private readonly Dictionary<string, LogEventLevel> _lookup; | ||||
|  | ||||
|         public VerbosityConverter() | ||||
|         { | ||||
|             _lookup = new Dictionary<string, LogEventLevel>(StringComparer.OrdinalIgnoreCase) | ||||
|         _lookup = new Dictionary<string, LogEventLevel>(StringComparer.OrdinalIgnoreCase) | ||||
|             { | ||||
|                 {"d", LogEventLevel.Debug}, | ||||
|                 {"v", LogEventLevel.Verbose}, | ||||
| @@ -35,22 +35,21 @@ namespace Spectre.Console.Examples | ||||
|                 {"e", LogEventLevel.Error}, | ||||
|                 {"f", LogEventLevel.Fatal} | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) | ||||
|         { | ||||
|             if (value is string stringValue) | ||||
|             { | ||||
|                 var result = _lookup.TryGetValue(stringValue, out var verbosity); | ||||
|                 if (!result) | ||||
|                 { | ||||
|                     const string format = "The value '{0}' is not a valid verbosity."; | ||||
|                     var message = string.Format(CultureInfo.InvariantCulture, format, value); | ||||
|                     throw new InvalidOperationException(message); | ||||
|                 } | ||||
|                 return verbosity; | ||||
|             } | ||||
|             throw new NotSupportedException("Can't convert value to verbosity."); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|     public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) | ||||
|     { | ||||
|         if (value is string stringValue) | ||||
|         { | ||||
|             var result = _lookup.TryGetValue(stringValue, out var verbosity); | ||||
|             if (!result) | ||||
|             { | ||||
|                 const string format = "The value '{0}' is not a valid verbosity."; | ||||
|                 var message = string.Format(CultureInfo.InvariantCulture, format, value); | ||||
|                 throw new InvalidOperationException(message); | ||||
|             } | ||||
|             return verbosity; | ||||
|         } | ||||
|         throw new NotSupportedException("Can't convert value to verbosity."); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,19 +1,18 @@ | ||||
| using Serilog.Core; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| { | ||||
|     public class LogInterceptor : ICommandInterceptor | ||||
|     { | ||||
|         public static readonly LoggingLevelSwitch LogLevel = new(); | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
|         public void Intercept(CommandContext context, CommandSettings settings) | ||||
| public class LogInterceptor : ICommandInterceptor | ||||
| { | ||||
|     public static readonly LoggingLevelSwitch LogLevel = new(); | ||||
|  | ||||
|     public void Intercept(CommandContext context, CommandSettings settings) | ||||
|     { | ||||
|         if (settings is LogCommandSettings logSettings) | ||||
|         { | ||||
|             if (settings is LogCommandSettings logSettings) | ||||
|             { | ||||
|                 LoggingEnricher.Path = logSettings.LogFile ?? "application.log"; | ||||
|                 LogLevel.MinimumLevel = logSettings.LogLevel; | ||||
|             } | ||||
|             LoggingEnricher.Path = logSettings.LogFile ?? "application.log"; | ||||
|             LogLevel.MinimumLevel = logSettings.LogLevel; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,38 +1,37 @@ | ||||
| using Serilog.Core; | ||||
| using Serilog.Events; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| internal class LoggingEnricher : ILogEventEnricher | ||||
| { | ||||
|     internal class LoggingEnricher : ILogEventEnricher | ||||
|     private string _cachedLogFilePath; | ||||
|     private LogEventProperty _cachedLogFilePathProperty; | ||||
|  | ||||
|     // this path and level will be set by the LogInterceptor.cs after parsing the settings | ||||
|     public static string Path = string.Empty; | ||||
|  | ||||
|     public const string LogFilePathPropertyName = "LogFilePath"; | ||||
|  | ||||
|     public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) | ||||
|     { | ||||
|         private string _cachedLogFilePath; | ||||
|         private LogEventProperty _cachedLogFilePathProperty; | ||||
|         // the settings might not have a path or we might not be within a command in which case | ||||
|         // we won't have the setting so a default value for the log file will be required | ||||
|         LogEventProperty logFilePathProperty; | ||||
|  | ||||
|         // this path and level will be set by the LogInterceptor.cs after parsing the settings | ||||
|         public static string Path = string.Empty; | ||||
|  | ||||
|         public const string LogFilePathPropertyName = "LogFilePath"; | ||||
|  | ||||
|         public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) | ||||
|         if (_cachedLogFilePathProperty != null && Path.Equals(_cachedLogFilePath)) | ||||
|         { | ||||
|             // the settings might not have a path or we might not be within a command in which case | ||||
|             // we won't have the setting so a default value for the log file will be required | ||||
|             LogEventProperty logFilePathProperty; | ||||
|  | ||||
|             if (_cachedLogFilePathProperty != null && Path.Equals(_cachedLogFilePath)) | ||||
|             { | ||||
|                 // Path hasn't changed, so let's use the cached property | ||||
|                 logFilePathProperty = _cachedLogFilePathProperty; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // We've got a new path for the log. Let's create a new property | ||||
|                 // and cache it for future log events to use | ||||
|                 _cachedLogFilePath = Path; | ||||
|                 _cachedLogFilePathProperty = logFilePathProperty = propertyFactory.CreateProperty(LogFilePathPropertyName, Path); | ||||
|             } | ||||
|  | ||||
|             logEvent.AddPropertyIfAbsent(logFilePathProperty); | ||||
|             // Path hasn't changed, so let's use the cached property | ||||
|             logFilePathProperty = _cachedLogFilePathProperty; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // We've got a new path for the log. Let's create a new property | ||||
|             // and cache it for future log events to use | ||||
|             _cachedLogFilePath = Path; | ||||
|             _cachedLogFilePathProperty = logFilePathProperty = propertyFactory.CreateProperty(LogFilePathPropertyName, Path); | ||||
|         } | ||||
|  | ||||
|         logEvent.AddPropertyIfAbsent(logFilePathProperty); | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -2,40 +2,39 @@ using System; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public sealed class TypeRegistrar : ITypeRegistrar | ||||
| { | ||||
|     public sealed class TypeRegistrar : ITypeRegistrar | ||||
|     private readonly IServiceCollection _builder; | ||||
|  | ||||
|     public TypeRegistrar(IServiceCollection builder) | ||||
|     { | ||||
|         private readonly IServiceCollection _builder; | ||||
|  | ||||
|         public TypeRegistrar(IServiceCollection builder) | ||||
|         { | ||||
|             _builder = builder; | ||||
|         } | ||||
|  | ||||
|         public ITypeResolver Build() | ||||
|         { | ||||
|             return new TypeResolver(_builder.BuildServiceProvider()); | ||||
|         } | ||||
|  | ||||
|         public void Register(Type service, Type implementation) | ||||
|         { | ||||
|             _builder.AddSingleton(service, implementation); | ||||
|         } | ||||
|  | ||||
|         public void RegisterInstance(Type service, object implementation) | ||||
|         { | ||||
|             _builder.AddSingleton(service, implementation); | ||||
|         } | ||||
|  | ||||
|         public void RegisterLazy(Type service, Func<object> func) | ||||
|         { | ||||
|             if (func is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(func)); | ||||
|             } | ||||
|  | ||||
|             _builder.AddSingleton(service, _ => func()); | ||||
|         } | ||||
|         _builder = builder; | ||||
|     } | ||||
| } | ||||
|  | ||||
|     public ITypeResolver Build() | ||||
|     { | ||||
|         return new TypeResolver(_builder.BuildServiceProvider()); | ||||
|     } | ||||
|  | ||||
|     public void Register(Type service, Type implementation) | ||||
|     { | ||||
|         _builder.AddSingleton(service, implementation); | ||||
|     } | ||||
|  | ||||
|     public void RegisterInstance(Type service, object implementation) | ||||
|     { | ||||
|         _builder.AddSingleton(service, implementation); | ||||
|     } | ||||
|  | ||||
|     public void RegisterLazy(Type service, Func<object> func) | ||||
|     { | ||||
|         if (func is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(func)); | ||||
|         } | ||||
|  | ||||
|         _builder.AddSingleton(service, _ => func()); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,20 +2,19 @@ using System; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public sealed class TypeResolver : ITypeResolver | ||||
| { | ||||
|     public sealed class TypeResolver : ITypeResolver | ||||
|     private readonly IServiceProvider _provider; | ||||
|  | ||||
|     public TypeResolver(IServiceProvider provider) | ||||
|     { | ||||
|         private readonly IServiceProvider _provider; | ||||
|  | ||||
|         public TypeResolver(IServiceProvider provider) | ||||
|         { | ||||
|             _provider = provider ?? throw new ArgumentNullException(nameof(provider)); | ||||
|         } | ||||
|  | ||||
|         public object Resolve(Type type) | ||||
|         { | ||||
|             return _provider.GetRequiredService(type); | ||||
|         } | ||||
|         _provider = provider ?? throw new ArgumentNullException(nameof(provider)); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     public object Resolve(Type type) | ||||
|     { | ||||
|         return _provider.GetRequiredService(type); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -12,42 +12,41 @@ using Spectre.Console.Cli; | ||||
|  * Spectre.Console CommandInterceptor | ||||
|  */ | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public class Program | ||||
| { | ||||
|     public class Program | ||||
|     static int Main(string[] args) | ||||
|     { | ||||
|         static int Main(string[] args) | ||||
|         // to retrieve the log file name, we must first parse the command settings | ||||
|         // this will require us to delay setting the file path for the file writer. | ||||
|         // With serilog we can use an enricher and Serilog.Sinks.Map to dynamically | ||||
|         // pull this setting. | ||||
|         var serviceCollection = new ServiceCollection() | ||||
|             .AddLogging(configure => | ||||
|                 configure.AddSerilog(new LoggerConfiguration() | ||||
|                     // log level will be dynamically be controlled by our log interceptor upon running | ||||
|                     .MinimumLevel.ControlledBy(LogInterceptor.LogLevel) | ||||
|                     // the log enricher will add a new property with the log file path from the settings | ||||
|                     // that we can use to set the path dynamically | ||||
|                     .Enrich.With<LoggingEnricher>() | ||||
|                     // serilog.sinks.map will defer the configuration of the sink to be ondemand | ||||
|                     // allowing us to look at the properties set by the enricher to set the path appropriately | ||||
|                     .WriteTo.Map(LoggingEnricher.LogFilePathPropertyName, | ||||
|                         (logFilePath, wt) => wt.File($"{logFilePath}"), 1) | ||||
|                     .CreateLogger() | ||||
|                 ) | ||||
|             ); | ||||
|  | ||||
|         var registrar = new TypeRegistrar(serviceCollection); | ||||
|         var app = new CommandApp(registrar); | ||||
|  | ||||
|         app.Configure(config => | ||||
|         { | ||||
|             // to retrieve the log file name, we must first parse the command settings | ||||
|             // this will require us to delay setting the file path for the file writer. | ||||
|             // With serilog we can use an enricher and Serilog.Sinks.Map to dynamically | ||||
|             // pull this setting. | ||||
|             var serviceCollection = new ServiceCollection() | ||||
|                 .AddLogging(configure => | ||||
|                     configure.AddSerilog(new LoggerConfiguration() | ||||
|                         // log level will be dynamically be controlled by our log interceptor upon running | ||||
|                         .MinimumLevel.ControlledBy(LogInterceptor.LogLevel) | ||||
|                         // the log enricher will add a new property with the log file path from the settings | ||||
|                         // that we can use to set the path dynamically | ||||
|                         .Enrich.With<LoggingEnricher>() | ||||
|                         // serilog.sinks.map will defer the configuration of the sink to be ondemand | ||||
|                         // allowing us to look at the properties set by the enricher to set the path appropriately | ||||
|                         .WriteTo.Map(LoggingEnricher.LogFilePathPropertyName, | ||||
|                             (logFilePath, wt) => wt.File($"{logFilePath}"), 1) | ||||
|                         .CreateLogger() | ||||
|                     ) | ||||
|                 ); | ||||
|  | ||||
|             var registrar = new TypeRegistrar(serviceCollection); | ||||
|             var app = new CommandApp(registrar); | ||||
|  | ||||
|             app.Configure(config => | ||||
|             { | ||||
|                 config.SetInterceptor(new LogInterceptor()); // add the interceptor | ||||
|             config.SetInterceptor(new LogInterceptor()); // add the interceptor | ||||
|                 config.AddCommand<HelloCommand>("hello"); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|             return app.Run(args); | ||||
|         } | ||||
|         return app.Run(args); | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,32 +1,32 @@ | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| { | ||||
|     public static class Program | ||||
|     { | ||||
|         public static void Main() | ||||
|         { | ||||
|             // Render panel borders | ||||
|             HorizontalRule("PANEL BORDERS"); | ||||
|             PanelBorders(); | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
|             // Render table borders | ||||
|             HorizontalRule("TABLE BORDERS"); | ||||
|             TableBorders(); | ||||
| public static class Program | ||||
| { | ||||
|     public static void Main() | ||||
|     { | ||||
|         // Render panel borders | ||||
|         HorizontalRule("PANEL BORDERS"); | ||||
|         PanelBorders(); | ||||
|  | ||||
|         // Render table borders | ||||
|         HorizontalRule("TABLE BORDERS"); | ||||
|         TableBorders(); | ||||
|     } | ||||
|  | ||||
|     private static void PanelBorders() | ||||
|     { | ||||
|         static IRenderable CreatePanel(string name, BoxBorder border) | ||||
|         { | ||||
|             return new Panel($"This is a panel with\nthe [yellow]{name}[/] border.") | ||||
|                 .Header($" [blue]{name}[/] ", Justify.Center) | ||||
|                 .Border(border) | ||||
|                 .BorderStyle(Style.Parse("grey")); | ||||
|         } | ||||
|  | ||||
|         private static void PanelBorders() | ||||
|         var items = new[] | ||||
|         { | ||||
|             static IRenderable CreatePanel(string name, BoxBorder border) | ||||
|             { | ||||
|                 return new Panel($"This is a panel with\nthe [yellow]{name}[/] border.") | ||||
|                     .Header($" [blue]{name}[/] ", Justify.Center) | ||||
|                     .Border(border) | ||||
|                     .BorderStyle(Style.Parse("grey")); | ||||
|             } | ||||
|  | ||||
|             var items = new[] | ||||
|             { | ||||
|                 CreatePanel("Ascii", BoxBorder.Ascii), | ||||
|                 CreatePanel("Square", BoxBorder.Square), | ||||
|                 CreatePanel("Rounded", BoxBorder.Rounded), | ||||
| @@ -35,29 +35,29 @@ namespace Spectre.Console.Examples | ||||
|                 CreatePanel("None", BoxBorder.None), | ||||
|             }; | ||||
|  | ||||
|             AnsiConsole.Write( | ||||
|                 new Padder( | ||||
|                     new Columns(items).PadRight(2), | ||||
|                     new Padding(2,0,0,0))); | ||||
|         AnsiConsole.Write( | ||||
|             new Padder( | ||||
|                 new Columns(items).PadRight(2), | ||||
|                 new Padding(2, 0, 0, 0))); | ||||
|     } | ||||
|  | ||||
|     private static void TableBorders() | ||||
|     { | ||||
|         static IRenderable CreateTable(string name, TableBorder border) | ||||
|         { | ||||
|             var table = new Table().Border(border); | ||||
|             table.AddColumn("[yellow]Header 1[/]", c => c.Footer("[grey]Footer 1[/]")); | ||||
|             table.AddColumn("[yellow]Header 2[/]", col => col.Footer("[grey]Footer 2[/]").RightAligned()); | ||||
|             table.AddRow("Cell", "Cell"); | ||||
|             table.AddRow("Cell", "Cell"); | ||||
|  | ||||
|             return new Panel(table) | ||||
|                 .Header($" [blue]{name}[/] ", Justify.Center) | ||||
|                 .NoBorder(); | ||||
|         } | ||||
|  | ||||
|         private static void TableBorders() | ||||
|         var items = new[] | ||||
|         { | ||||
|             static IRenderable CreateTable(string name, TableBorder border) | ||||
|             { | ||||
|                 var table = new Table().Border(border); | ||||
|                 table.AddColumn("[yellow]Header 1[/]", c => c.Footer("[grey]Footer 1[/]")); | ||||
|                 table.AddColumn("[yellow]Header 2[/]", col => col.Footer("[grey]Footer 2[/]").RightAligned()); | ||||
|                 table.AddRow("Cell", "Cell"); | ||||
|                 table.AddRow("Cell", "Cell"); | ||||
|  | ||||
|                 return new Panel(table) | ||||
|                     .Header($" [blue]{name}[/] ", Justify.Center) | ||||
|                     .NoBorder(); | ||||
|             } | ||||
|  | ||||
|             var items = new[] | ||||
|             { | ||||
|                 CreateTable("Ascii", TableBorder.Ascii), | ||||
|                 CreateTable("Ascii2", TableBorder.Ascii2), | ||||
|                 CreateTable("AsciiDoubleHead", TableBorder.AsciiDoubleHead), | ||||
| @@ -77,14 +77,13 @@ namespace Spectre.Console.Examples | ||||
|                 CreateTable("Markdown", TableBorder.Markdown), | ||||
|             }; | ||||
|  | ||||
|             AnsiConsole.Write(new Columns(items).Collapse()); | ||||
|         } | ||||
|         AnsiConsole.Write(new Columns(items).Collapse()); | ||||
|     } | ||||
|  | ||||
|         private static void HorizontalRule(string title) | ||||
|         { | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(new Rule($"[white bold]{title}[/]").RuleStyle("grey").LeftAligned()); | ||||
|             AnsiConsole.WriteLine(); | ||||
|         } | ||||
|     private static void HorizontalRule(string title) | ||||
|     { | ||||
|         AnsiConsole.WriteLine(); | ||||
|         AnsiConsole.Write(new Rule($"[white bold]{title}[/]").RuleStyle("grey").LeftAligned()); | ||||
|         AnsiConsole.WriteLine(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,17 +1,16 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main(string[] args) | ||||
|     { | ||||
|         public static void Main(string[] args) | ||||
|         { | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(new Calendar(2020, 10) | ||||
|                     .RoundedBorder() | ||||
|                     .HighlightStyle(Style.Parse("red")) | ||||
|                     .HeaderStyle(Style.Parse("yellow")) | ||||
|                     .AddCalendarEvent("An event", 2020, 9, 22) | ||||
|                     .AddCalendarEvent("Another event", 2020, 10, 2) | ||||
|                     .AddCalendarEvent("A third event", 2020, 10, 13)); | ||||
|         } | ||||
|         AnsiConsole.WriteLine(); | ||||
|         AnsiConsole.Write(new Calendar(2020, 10) | ||||
|                 .RoundedBorder() | ||||
|                 .HighlightStyle(Style.Parse("red")) | ||||
|                 .HeaderStyle(Style.Parse("yellow")) | ||||
|                 .AddCalendarEvent("An event", 2020, 9, 22) | ||||
|                 .AddCalendarEvent("Another event", 2020, 10, 2) | ||||
|                 .AddCalendarEvent("A third event", 2020, 10, 13)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -5,82 +5,81 @@ Licensed under GNU Free Documentation License 1.2 | ||||
|  | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Mandelbrot | ||||
| { | ||||
|     public static class Mandelbrot | ||||
|     private const double MaxValueExtent = 2.0; | ||||
|  | ||||
|     private struct ComplexNumber | ||||
|     { | ||||
|         private const double MaxValueExtent = 2.0; | ||||
|         public double Real { get; } | ||||
|         public double Imaginary { get; } | ||||
|  | ||||
|         private struct ComplexNumber | ||||
|         public ComplexNumber(double real, double imaginary) | ||||
|         { | ||||
|             public double Real { get; } | ||||
|             public double Imaginary { get; } | ||||
|  | ||||
|             public ComplexNumber(double real, double imaginary) | ||||
|             { | ||||
|                 Real = real; | ||||
|                 Imaginary = imaginary; | ||||
|             } | ||||
|  | ||||
|             public static ComplexNumber operator +(ComplexNumber x, ComplexNumber y) | ||||
|             { | ||||
|                 return new ComplexNumber(x.Real + y.Real, x.Imaginary + y.Imaginary); | ||||
|             } | ||||
|  | ||||
|             public static ComplexNumber operator *(ComplexNumber x, ComplexNumber y) | ||||
|             { | ||||
|                 return new ComplexNumber(x.Real * y.Real - x.Imaginary * y.Imaginary, | ||||
|                     x.Real * y.Imaginary + x.Imaginary * y.Real); | ||||
|             } | ||||
|  | ||||
|             public double Abs() | ||||
|             { | ||||
|                 return Real * Real + Imaginary * Imaginary; | ||||
|             } | ||||
|             Real = real; | ||||
|             Imaginary = imaginary; | ||||
|         } | ||||
|  | ||||
|         public static Canvas Generate(int width, int height) | ||||
|         public static ComplexNumber operator +(ComplexNumber x, ComplexNumber y) | ||||
|         { | ||||
|             var canvas = new Canvas(width, height); | ||||
|  | ||||
|             var scale = 2 * MaxValueExtent / Math.Min(canvas.Width, canvas.Height); | ||||
|             for (var i = 0; i < canvas.Height; i++) | ||||
|             { | ||||
|                 var y = (canvas.Height / 2 - i) * scale; | ||||
|                 for (var j = 0; j < canvas.Width; j++) | ||||
|                 { | ||||
|                     var x = (j - canvas.Width / 2) * scale; | ||||
|                     var value = Calculate(new ComplexNumber(x, y)); | ||||
|                     canvas.SetPixel(j, i, GetColor(value)); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return canvas; | ||||
|             return new ComplexNumber(x.Real + y.Real, x.Imaginary + y.Imaginary); | ||||
|         } | ||||
|  | ||||
|         private static double Calculate(ComplexNumber c) | ||||
|         public static ComplexNumber operator *(ComplexNumber x, ComplexNumber y) | ||||
|         { | ||||
|             const int MaxIterations = 1000; | ||||
|             const double MaxNorm = MaxValueExtent * MaxValueExtent; | ||||
|  | ||||
|             var iteration = 0; | ||||
|             var z = new ComplexNumber(); | ||||
|             do | ||||
|             { | ||||
|                 z = z * z + c; | ||||
|                 iteration++; | ||||
|             } while (z.Abs() < MaxNorm && iteration < MaxIterations); | ||||
|  | ||||
|             return iteration < MaxIterations | ||||
|                 ? (double)iteration / MaxIterations | ||||
|                 : 0; | ||||
|             return new ComplexNumber(x.Real * y.Real - x.Imaginary * y.Imaginary, | ||||
|                 x.Real * y.Imaginary + x.Imaginary * y.Real); | ||||
|         } | ||||
|  | ||||
|         private static Color GetColor(double value) | ||||
|         public double Abs() | ||||
|         { | ||||
|             const double MaxColor = 256; | ||||
|             const double ContrastValue = 0.2; | ||||
|             return new Color(0, 0, (byte)(MaxColor * Math.Pow(value, ContrastValue))); | ||||
|             return Real * Real + Imaginary * Imaginary; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static Canvas Generate(int width, int height) | ||||
|     { | ||||
|         var canvas = new Canvas(width, height); | ||||
|  | ||||
|         var scale = 2 * MaxValueExtent / Math.Min(canvas.Width, canvas.Height); | ||||
|         for (var i = 0; i < canvas.Height; i++) | ||||
|         { | ||||
|             var y = (canvas.Height / 2 - i) * scale; | ||||
|             for (var j = 0; j < canvas.Width; j++) | ||||
|             { | ||||
|                 var x = (j - canvas.Width / 2) * scale; | ||||
|                 var value = Calculate(new ComplexNumber(x, y)); | ||||
|                 canvas.SetPixel(j, i, GetColor(value)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return canvas; | ||||
|     } | ||||
|  | ||||
|     private static double Calculate(ComplexNumber c) | ||||
|     { | ||||
|         const int MaxIterations = 1000; | ||||
|         const double MaxNorm = MaxValueExtent * MaxValueExtent; | ||||
|  | ||||
|         var iteration = 0; | ||||
|         var z = new ComplexNumber(); | ||||
|         do | ||||
|         { | ||||
|             z = z * z + c; | ||||
|             iteration++; | ||||
|         } while (z.Abs() < MaxNorm && iteration < MaxIterations); | ||||
|  | ||||
|         return iteration < MaxIterations | ||||
|             ? (double)iteration / MaxIterations | ||||
|             : 0; | ||||
|     } | ||||
|  | ||||
|     private static Color GetColor(double value) | ||||
|     { | ||||
|         const double MaxColor = 256; | ||||
|         const double ContrastValue = 0.2; | ||||
|         return new Color(0, 0, (byte)(MaxColor * Math.Pow(value, ContrastValue))); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,45 +3,44 @@ using System.Reflection; | ||||
| using SixLabors.ImageSharp.Processing; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         // Draw a mandelbrot set using a Canvas | ||||
|         var mandelbrot = Mandelbrot.Generate(32, 32); | ||||
|         Render(mandelbrot, "Mandelbrot"); | ||||
|  | ||||
|         // Draw an image using CanvasImage powered by ImageSharp. | ||||
|         // This requires the "Spectre.Console.ImageSharp" NuGet package. | ||||
|         var image = new CanvasImage("cake.png"); | ||||
|         image.BilinearResampler(); | ||||
|         image.MaxWidth(16); | ||||
|         Render(image, "Image from file (16 wide)"); | ||||
|  | ||||
|         // Draw image again, but without render width | ||||
|         image.NoMaxWidth(); | ||||
|         image.Mutate(ctx => ctx.Grayscale().Rotate(-45).EntropyCrop()); | ||||
|         Render(image, "Image from file (fit, greyscale, rotated)"); | ||||
|  | ||||
|         // Draw image again, but load from embedded resource rather than file | ||||
|         using (var fileStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Canvas.cake.png")) | ||||
|         { | ||||
|             // Draw a mandelbrot set using a Canvas | ||||
|             var mandelbrot = Mandelbrot.Generate(32, 32); | ||||
|             Render(mandelbrot, "Mandelbrot"); | ||||
|  | ||||
|             // Draw an image using CanvasImage powered by ImageSharp. | ||||
|             // This requires the "Spectre.Console.ImageSharp" NuGet package. | ||||
|             var image = new CanvasImage("cake.png"); | ||||
|             image.BilinearResampler(); | ||||
|             image.MaxWidth(16); | ||||
|             Render(image, "Image from file (16 wide)"); | ||||
|  | ||||
|             // Draw image again, but without render width | ||||
|             image.NoMaxWidth(); | ||||
|             image.Mutate(ctx => ctx.Grayscale().Rotate(-45).EntropyCrop()); | ||||
|             Render(image, "Image from file (fit, greyscale, rotated)"); | ||||
|  | ||||
|             // Draw image again, but load from embedded resource rather than file | ||||
|             using (var fileStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Canvas.cake.png")) | ||||
|             { | ||||
|                 Debug.Assert(fileStream != null); | ||||
|                 var embeddedImage = new CanvasImage(fileStream); | ||||
|                 embeddedImage.BilinearResampler(); | ||||
|                 embeddedImage.MaxWidth(16); | ||||
|                 Render(embeddedImage, "Image from embedded resource (16 wide)"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private static void Render(IRenderable canvas, string title) | ||||
|         { | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(new Rule($"[yellow]{title}[/]").LeftAligned().RuleStyle("grey")); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(canvas); | ||||
|             Debug.Assert(fileStream != null); | ||||
|             var embeddedImage = new CanvasImage(fileStream); | ||||
|             embeddedImage.BilinearResampler(); | ||||
|             embeddedImage.MaxWidth(16); | ||||
|             Render(embeddedImage, "Image from embedded resource (16 wide)"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static void Render(IRenderable canvas, string title) | ||||
|     { | ||||
|         AnsiConsole.WriteLine(); | ||||
|         AnsiConsole.Write(new Rule($"[yellow]{title}[/]").LeftAligned().RuleStyle("grey")); | ||||
|         AnsiConsole.WriteLine(); | ||||
|         AnsiConsole.Write(canvas); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,41 +1,40 @@ | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         { | ||||
|             // Render a bar chart | ||||
|             AnsiConsole.WriteLine(); | ||||
|             Render("Fruits per month", 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)); | ||||
|         // Render a bar chart | ||||
|         AnsiConsole.WriteLine(); | ||||
|         Render("Fruits per month", 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)); | ||||
|  | ||||
|             // Render a breakdown chart | ||||
|             AnsiConsole.WriteLine(); | ||||
|             Render("Languages used", new BreakdownChart() | ||||
|                 .FullSize() | ||||
|                 .Width(60) | ||||
|                 .ShowPercentage() | ||||
|                 .AddItem("SCSS", 37, 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)); | ||||
|         } | ||||
|         // Render a breakdown chart | ||||
|         AnsiConsole.WriteLine(); | ||||
|         Render("Languages used", new BreakdownChart() | ||||
|             .FullSize() | ||||
|             .Width(60) | ||||
|             .ShowPercentage() | ||||
|             .AddItem("SCSS", 37, 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)); | ||||
|     } | ||||
|  | ||||
|         private static void Render(string title, IRenderable chart) | ||||
|         { | ||||
|             AnsiConsole.Write( | ||||
|                 new Panel(chart) | ||||
|                     .Padding(1, 1) | ||||
|                     .Header(title)); | ||||
|         } | ||||
|     private static void Render(string title, IRenderable chart) | ||||
|     { | ||||
|         AnsiConsole.Write( | ||||
|             new Panel(chart) | ||||
|                 .Padding(1, 1) | ||||
|                 .Header(title)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,103 +1,102 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         ///////////////////////////////////////////////////////////////// | ||||
|         // No colors | ||||
|         ///////////////////////////////////////////////////////////////// | ||||
|         if (AnsiConsole.Profile.Capabilities.ColorSystem == ColorSystem.NoColors) | ||||
|         { | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             // No colors | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             if (AnsiConsole.Profile.Capabilities.ColorSystem == ColorSystem.NoColors) | ||||
|             { | ||||
|                 AnsiConsole.WriteLine("No colors are supported."); | ||||
|                 return; | ||||
|             } | ||||
|             AnsiConsole.WriteLine("No colors are supported."); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             // 3-BIT | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             if (AnsiConsole.Profile.Supports(ColorSystem.Legacy)) | ||||
|         ///////////////////////////////////////////////////////////////// | ||||
|         // 3-BIT | ||||
|         ///////////////////////////////////////////////////////////////// | ||||
|         if (AnsiConsole.Profile.Supports(ColorSystem.Legacy)) | ||||
|         { | ||||
|             AnsiConsole.ResetColors(); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(new Rule("[yellow bold underline]3-bit Colors[/]").RuleStyle("grey").LeftAligned()); | ||||
|             AnsiConsole.WriteLine(); | ||||
|  | ||||
|             for (var i = 0; i < 8; i++) | ||||
|             { | ||||
|                 AnsiConsole.Background = Color.FromInt32(i); | ||||
|                 AnsiConsole.Foreground = AnsiConsole.Background.GetInvertedColor(); | ||||
|                 AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString())); | ||||
|                 AnsiConsole.ResetColors(); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|                 AnsiConsole.Write(new Rule("[yellow bold underline]3-bit Colors[/]").RuleStyle("grey").LeftAligned()); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|  | ||||
|                 for (var i = 0; i < 8; i++) | ||||
|                 if ((i + 1) % 8 == 0) | ||||
|                 { | ||||
|                     AnsiConsole.Background = Color.FromInt32(i); | ||||
|                     AnsiConsole.WriteLine(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         ///////////////////////////////////////////////////////////////// | ||||
|         // 4-BIT | ||||
|         ///////////////////////////////////////////////////////////////// | ||||
|         if (AnsiConsole.Profile.Supports(ColorSystem.Standard)) | ||||
|         { | ||||
|             AnsiConsole.ResetColors(); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(new Rule("[yellow bold underline]4-bit Colors[/]").RuleStyle("grey").LeftAligned()); | ||||
|             AnsiConsole.WriteLine(); | ||||
|  | ||||
|             for (var i = 0; i < 16; i++) | ||||
|             { | ||||
|                 AnsiConsole.Background = Color.FromInt32(i); | ||||
|                 AnsiConsole.Foreground = AnsiConsole.Background.GetInvertedColor(); | ||||
|                 AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString())); | ||||
|                 AnsiConsole.ResetColors(); | ||||
|                 if ((i + 1) % 8 == 0) | ||||
|                 { | ||||
|                     AnsiConsole.WriteLine(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         ///////////////////////////////////////////////////////////////// | ||||
|         // 8-BIT | ||||
|         ///////////////////////////////////////////////////////////////// | ||||
|         if (AnsiConsole.Profile.Supports(ColorSystem.EightBit)) | ||||
|         { | ||||
|             AnsiConsole.ResetColors(); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(new Rule("[yellow bold underline]8-bit Colors[/]").RuleStyle("grey").LeftAligned()); | ||||
|             AnsiConsole.WriteLine(); | ||||
|  | ||||
|             for (var i = 0; i < 16; i++) | ||||
|             { | ||||
|                 for (var j = 0; j < 16; j++) | ||||
|                 { | ||||
|                     var number = i * 16 + j; | ||||
|                     AnsiConsole.Background = Color.FromInt32(number); | ||||
|                     AnsiConsole.Foreground = AnsiConsole.Background.GetInvertedColor(); | ||||
|                     AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString())); | ||||
|                     AnsiConsole.Write(string.Format(" {0,-4}", number)); | ||||
|                     AnsiConsole.ResetColors(); | ||||
|                     if ((i + 1) % 8 == 0) | ||||
|                     if ((number + 1) % 16 == 0) | ||||
|                     { | ||||
|                         AnsiConsole.WriteLine(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             // 4-BIT | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             if (AnsiConsole.Profile.Supports(ColorSystem.Standard)) | ||||
|             { | ||||
|                 AnsiConsole.ResetColors(); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|                 AnsiConsole.Write(new Rule("[yellow bold underline]4-bit Colors[/]").RuleStyle("grey").LeftAligned()); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|         ///////////////////////////////////////////////////////////////// | ||||
|         // 24-BIT | ||||
|         ///////////////////////////////////////////////////////////////// | ||||
|         if (AnsiConsole.Profile.Supports(ColorSystem.TrueColor)) | ||||
|         { | ||||
|             AnsiConsole.ResetColors(); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(new Rule("[yellow bold underline]24-bit Colors[/]").RuleStyle("grey").LeftAligned()); | ||||
|             AnsiConsole.WriteLine(); | ||||
|  | ||||
|                 for (var i = 0; i < 16; i++) | ||||
|                 { | ||||
|                     AnsiConsole.Background = Color.FromInt32(i); | ||||
|                     AnsiConsole.Foreground = AnsiConsole.Background.GetInvertedColor(); | ||||
|                     AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString())); | ||||
|                     AnsiConsole.ResetColors(); | ||||
|                     if ((i + 1) % 8 == 0) | ||||
|                     { | ||||
|                         AnsiConsole.WriteLine(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             // 8-BIT | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             if (AnsiConsole.Profile.Supports(ColorSystem.EightBit)) | ||||
|             { | ||||
|                 AnsiConsole.ResetColors(); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|                 AnsiConsole.Write(new Rule("[yellow bold underline]8-bit Colors[/]").RuleStyle("grey").LeftAligned()); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|  | ||||
|                 for (var i = 0; i < 16; i++) | ||||
|                 { | ||||
|                     for (var j = 0; j < 16; j++) | ||||
|                     { | ||||
|                         var number = i * 16 + j; | ||||
|                         AnsiConsole.Background = Color.FromInt32(number); | ||||
|                         AnsiConsole.Foreground = AnsiConsole.Background.GetInvertedColor(); | ||||
|                         AnsiConsole.Write(string.Format(" {0,-4}", number)); | ||||
|                         AnsiConsole.ResetColors(); | ||||
|                         if ((number + 1) % 16 == 0) | ||||
|                         { | ||||
|                             AnsiConsole.WriteLine(); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             // 24-BIT | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             if (AnsiConsole.Profile.Supports(ColorSystem.TrueColor)) | ||||
|             { | ||||
|                 AnsiConsole.ResetColors(); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|                 AnsiConsole.Write(new Rule("[yellow bold underline]24-bit Colors[/]").RuleStyle("grey").LeftAligned()); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|  | ||||
|                 AnsiConsole.Write(new ColorBox(width: 80, height: 15)); | ||||
|             } | ||||
|             AnsiConsole.Write(new ColorBox(width: 80, height: 15)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,30 +1,29 @@ | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         var cards = new List<Panel>(); | ||||
|         foreach (var user in User.LoadUsers()) | ||||
|         { | ||||
|             var cards = new List<Panel>(); | ||||
|             foreach(var user in User.LoadUsers()) | ||||
|             { | ||||
|                 cards.Add( | ||||
|                     new Panel(GetCardContent(user)) | ||||
|                         .Header($"{user.Country}") | ||||
|                         .RoundedBorder().Expand()); | ||||
|             } | ||||
|  | ||||
|             // Render all cards in columns | ||||
|             AnsiConsole.Write(new Columns(cards)); | ||||
|             cards.Add( | ||||
|                 new Panel(GetCardContent(user)) | ||||
|                     .Header($"{user.Country}") | ||||
|                     .RoundedBorder().Expand()); | ||||
|         } | ||||
|  | ||||
|         private static string GetCardContent(User user) | ||||
|         { | ||||
|             var name = $"{user.FirstName} {user.LastName}"; | ||||
|             var city = $"{user.City}"; | ||||
|         // Render all cards in columns | ||||
|         AnsiConsole.Write(new Columns(cards)); | ||||
|     } | ||||
|  | ||||
|             return $"[b]{name}[/]\n[yellow]{city}[/]"; | ||||
|         } | ||||
|     private static string GetCardContent(User user) | ||||
|     { | ||||
|         var name = $"{user.FirstName} {user.LastName}"; | ||||
|         var city = $"{user.City}"; | ||||
|  | ||||
|         return $"[b]{name}[/]\n[yellow]{city}[/]"; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,17 +1,17 @@ | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| { | ||||
|     public sealed class User | ||||
|     { | ||||
|         public string FirstName { get; set; } | ||||
|         public string LastName { get; set; } | ||||
|         public string City { get; set; } | ||||
|         public string Country { get; set; } | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
|         public static List<User> LoadUsers() | ||||
|         { | ||||
|             return new List<User> | ||||
| public sealed class User | ||||
| { | ||||
|     public string FirstName { get; set; } | ||||
|     public string LastName { get; set; } | ||||
|     public string City { get; set; } | ||||
|     public string Country { get; set; } | ||||
|  | ||||
|     public static List<User> LoadUsers() | ||||
|     { | ||||
|         return new List<User> | ||||
|             { | ||||
|                 new User | ||||
|                 { | ||||
| @@ -84,6 +84,5 @@ namespace Spectre.Console.Examples | ||||
|                     Country = "Ireland", | ||||
|                 }, | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,18 +1,17 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main(string[] args) | ||||
|     { | ||||
|         public static void Main(string[] args) | ||||
|         { | ||||
|             AnsiConsole.Write("Hello"); | ||||
|         AnsiConsole.Write("Hello"); | ||||
|  | ||||
|             // Move the cursor 3 cells to the right | ||||
|             AnsiConsole.Cursor.Move(CursorDirection.Right, 3); | ||||
|             AnsiConsole.Write("World"); | ||||
|         // Move the cursor 3 cells to the right | ||||
|         AnsiConsole.Cursor.Move(CursorDirection.Right, 3); | ||||
|         AnsiConsole.Write("World"); | ||||
|  | ||||
|             // Move the cursor 5 cells to the left. | ||||
|             AnsiConsole.Cursor.Move(CursorDirection.Left, 5); | ||||
|             AnsiConsole.WriteLine("Universe"); | ||||
|         } | ||||
|         // Move the cursor 5 cells to the left. | ||||
|         AnsiConsole.Cursor.Move(CursorDirection.Left, 5); | ||||
|         AnsiConsole.WriteLine("Universe"); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,22 +1,21 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main(string[] args) | ||||
|     { | ||||
|         public static void Main(string[] args) | ||||
|         { | ||||
|             // Show a known emoji | ||||
|             RenderEmoji(); | ||||
|         // Show a known emoji | ||||
|         RenderEmoji(); | ||||
|  | ||||
|             // Show a remapped emoji | ||||
|             Emoji.Remap("globe_showing_europe_africa", Emoji.Known.GrinningFaceWithSmilingEyes); | ||||
|             RenderEmoji(); | ||||
|         } | ||||
|         // Show a remapped emoji | ||||
|         Emoji.Remap("globe_showing_europe_africa", Emoji.Known.GrinningFaceWithSmilingEyes); | ||||
|         RenderEmoji(); | ||||
|     } | ||||
|  | ||||
|         private static void RenderEmoji() | ||||
|         { | ||||
|             AnsiConsole.Write( | ||||
|                 new Panel("[yellow]Hello :globe_showing_europe_africa:![/]") | ||||
|                     .RoundedBorder()); | ||||
|         } | ||||
|     private static void RenderEmoji() | ||||
|     { | ||||
|         AnsiConsole.Write( | ||||
|             new Panel("[yellow]Hello :globe_showing_europe_africa:![/]") | ||||
|                 .RoundedBorder()); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,65 +1,64 @@ | ||||
| using System; | ||||
| using System.Security.Authentication; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main(string[] args) | ||||
|     { | ||||
|         public static void Main(string[] args) | ||||
|         try | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 DoMagic(42, null); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 AnsiConsole.WriteLine(); | ||||
|                 AnsiConsole.Write(new Rule("Default").LeftAligned()); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|                 AnsiConsole.WriteException(ex); | ||||
|             DoMagic(42, null); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(new Rule("Default").LeftAligned()); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.WriteException(ex); | ||||
|  | ||||
|                 AnsiConsole.WriteLine(); | ||||
|                 AnsiConsole.Write(new Rule("Compact").LeftAligned()); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|                 AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(new Rule("Compact").LeftAligned()); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks); | ||||
|  | ||||
|                 AnsiConsole.WriteLine(); | ||||
|                 AnsiConsole.Write(new Rule("Compact + Custom colors").LeftAligned()); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|                 AnsiConsole.WriteException(ex, new ExceptionSettings | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(new Rule("Compact + Custom colors").LeftAligned()); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.WriteException(ex, new ExceptionSettings | ||||
|             { | ||||
|                 Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks, | ||||
|                 Style = new ExceptionStyle | ||||
|                 { | ||||
|                     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."); | ||||
|                     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."); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,12 +1,11 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main(string[] args) | ||||
|     { | ||||
|         public static void Main(string[] args) | ||||
|         { | ||||
|             AnsiConsole.Write(new FigletText("Left aligned").LeftAligned().Color(Color.Red)); | ||||
|             AnsiConsole.Write(new FigletText("Centered").Centered().Color(Color.Green)); | ||||
|             AnsiConsole.Write(new FigletText("Right aligned").RightAligned().Color(Color.Blue)); | ||||
|         } | ||||
|         AnsiConsole.Write(new FigletText("Left aligned").LeftAligned().Color(Color.Red)); | ||||
|         AnsiConsole.Write(new FigletText("Centered").Centered().Color(Color.Green)); | ||||
|         AnsiConsole.Write(new FigletText("Right aligned").RightAligned().Color(Color.Blue)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,22 +1,21 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         { | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options]] [[[[--]] <additional arguments>...]]]][/]"); | ||||
|             AnsiConsole.WriteLine(); | ||||
|         AnsiConsole.WriteLine(); | ||||
|         AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options]] [[[[--]] <additional arguments>...]]]][/]"); | ||||
|         AnsiConsole.WriteLine(); | ||||
|  | ||||
|             var grid = new Grid(); | ||||
|             grid.AddColumn(new GridColumn().NoWrap()); | ||||
|             grid.AddColumn(new GridColumn().PadLeft(2)); | ||||
|             grid.AddRow("Options:"); | ||||
|             grid.AddRow("  [blue]-h[/], [blue]--help[/]", "Show command line help."); | ||||
|             grid.AddRow("  [blue]-c[/], [blue]--configuration[/] <CONFIGURATION>", "The configuration to run for."); | ||||
|             grid.AddRow("  [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "Set the [grey]MSBuild[/] verbosity level."); | ||||
|         var grid = new Grid(); | ||||
|         grid.AddColumn(new GridColumn().NoWrap()); | ||||
|         grid.AddColumn(new GridColumn().PadLeft(2)); | ||||
|         grid.AddRow("Options:"); | ||||
|         grid.AddRow("  [blue]-h[/], [blue]--help[/]", "Show command line help."); | ||||
|         grid.AddRow("  [blue]-c[/], [blue]--configuration[/] <CONFIGURATION>", "The configuration to run for."); | ||||
|         grid.AddRow("  [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "Set the [grey]MSBuild[/] verbosity level."); | ||||
|  | ||||
|             AnsiConsole.Write(grid); | ||||
|         } | ||||
|         AnsiConsole.Write(grid); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,32 +1,31 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         { | ||||
|             var grid = new Grid() | ||||
|                 .AddColumn(new GridColumn().NoWrap().PadRight(4)) | ||||
|                 .AddColumn() | ||||
|                 .AddRow("[b]Enrichers[/]", string.Join(", ", AnsiConsole.Profile.Enrichers)) | ||||
|                 .AddRow("[b]Color system[/]", $"{AnsiConsole.Profile.Capabilities.ColorSystem}") | ||||
|                 .AddRow("[b]Unicode?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Unicode)}") | ||||
|                 .AddRow("[b]Supports ansi?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Ansi)}") | ||||
|                 .AddRow("[b]Supports links?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Links)}") | ||||
|                 .AddRow("[b]Legacy console?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Legacy)}") | ||||
|                 .AddRow("[b]Interactive?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Interactive)}") | ||||
|                 .AddRow("[b]Terminal?[/]", $"{YesNo(AnsiConsole.Profile.Out.IsTerminal)}") | ||||
|                 .AddRow("[b]Buffer width[/]", $"{AnsiConsole.Console.Profile.Width}") | ||||
|                 .AddRow("[b]Buffer height[/]", $"{AnsiConsole.Console.Profile.Height}") | ||||
|                 .AddRow("[b]Encoding[/]", $"{AnsiConsole.Console.Profile.Encoding.EncodingName}"); | ||||
|         var grid = new Grid() | ||||
|             .AddColumn(new GridColumn().NoWrap().PadRight(4)) | ||||
|             .AddColumn() | ||||
|             .AddRow("[b]Enrichers[/]", string.Join(", ", AnsiConsole.Profile.Enrichers)) | ||||
|             .AddRow("[b]Color system[/]", $"{AnsiConsole.Profile.Capabilities.ColorSystem}") | ||||
|             .AddRow("[b]Unicode?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Unicode)}") | ||||
|             .AddRow("[b]Supports ansi?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Ansi)}") | ||||
|             .AddRow("[b]Supports links?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Links)}") | ||||
|             .AddRow("[b]Legacy console?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Legacy)}") | ||||
|             .AddRow("[b]Interactive?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Interactive)}") | ||||
|             .AddRow("[b]Terminal?[/]", $"{YesNo(AnsiConsole.Profile.Out.IsTerminal)}") | ||||
|             .AddRow("[b]Buffer width[/]", $"{AnsiConsole.Console.Profile.Width}") | ||||
|             .AddRow("[b]Buffer height[/]", $"{AnsiConsole.Console.Profile.Height}") | ||||
|             .AddRow("[b]Encoding[/]", $"{AnsiConsole.Console.Profile.Encoding.EncodingName}"); | ||||
|  | ||||
|             AnsiConsole.Write( | ||||
|                 new Panel(grid) | ||||
|                     .Header("Information")); | ||||
|         } | ||||
|         AnsiConsole.Write( | ||||
|             new Panel(grid) | ||||
|                 .Header("Information")); | ||||
|     } | ||||
|  | ||||
|         private static string YesNo(bool value) | ||||
|         { | ||||
|             return value ? "Yes" : "No"; | ||||
|         } | ||||
|     private static string YesNo(bool value) | ||||
|     { | ||||
|         return value ? "Yes" : "No"; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,19 +1,18 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         if (AnsiConsole.Profile.Capabilities.Links) | ||||
|         { | ||||
|             if (AnsiConsole.Profile.Capabilities.Links) | ||||
|             { | ||||
|                 AnsiConsole.MarkupLine("[link=https://patriksvensson.se]Click to visit my blog[/]!"); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 AnsiConsole.MarkupLine("[red]It looks like your terminal doesn't support links[/]"); | ||||
|                 AnsiConsole.WriteLine(); | ||||
|                 AnsiConsole.MarkupLine("[yellow](╯°□°)╯[/]︵ [blue]┻━┻[/]"); | ||||
|             } | ||||
|             AnsiConsole.MarkupLine("[link=https://patriksvensson.se]Click to visit my blog[/]!"); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             AnsiConsole.MarkupLine("[red]It looks like your terminal doesn't support links[/]"); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.MarkupLine("[yellow](╯°□°)╯[/]︵ [blue]┻━┻[/]"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,81 +1,80 @@ | ||||
| using System; | ||||
| using System.Threading; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| { | ||||
|     public static class Program | ||||
|     { | ||||
|         public static void Main() | ||||
|         { | ||||
|             var table = new Table().Centered(); | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
|             // Animate | ||||
|             AnsiConsole.Live(table) | ||||
|                 .AutoClear(false) | ||||
|                 .Overflow(VerticalOverflow.Ellipsis) | ||||
|                 .Cropping(VerticalOverflowCropping.Top) | ||||
|                 .Start(ctx => | ||||
| public static class Program | ||||
| { | ||||
|     public static void Main() | ||||
|     { | ||||
|         var table = new Table().Centered(); | ||||
|  | ||||
|         // Animate | ||||
|         AnsiConsole.Live(table) | ||||
|             .AutoClear(false) | ||||
|             .Overflow(VerticalOverflow.Ellipsis) | ||||
|             .Cropping(VerticalOverflowCropping.Top) | ||||
|             .Start(ctx => | ||||
|             { | ||||
|                 void Update(int delay, Action action) | ||||
|                 { | ||||
|                     void Update(int delay, Action action) | ||||
|                     { | ||||
|                         action(); | ||||
|                         ctx.Refresh(); | ||||
|                         Thread.Sleep(delay); | ||||
|                     } | ||||
|                     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")); | ||||
|                 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")); | ||||
|                 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")); | ||||
|                 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()); | ||||
|                 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[/]")); | ||||
|                 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[/]")); | ||||
|                 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[/] ]]")); | ||||
|                 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()); | ||||
|                 Update(230, () => table.MinimalBorder()); | ||||
|                 Update(230, () => table.SimpleBorder()); | ||||
|                 Update(230, () => table.SimpleHeavyBorder()); | ||||
|  | ||||
|                     // Caption | ||||
|                     Update(400, () => table.Caption("[[ [blue]THE END[/] ]]")); | ||||
|                 }); | ||||
|         } | ||||
|             }); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,15 +2,15 @@ using System; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| { | ||||
|     public static class Program | ||||
|     { | ||||
|         private const int NumberOfRows = 10; | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
|         private static readonly Random _random = new(); | ||||
|         private static readonly string[] _exchanges = new string[] | ||||
|         { | ||||
| public static class Program | ||||
| { | ||||
|     private const int NumberOfRows = 10; | ||||
|  | ||||
|     private static readonly Random _random = new(); | ||||
|     private static readonly string[] _exchanges = new string[] | ||||
|     { | ||||
|             "SGD", "SEK", "PLN", | ||||
|             "MYR", "EUR", "USD", | ||||
|             "AUD", "JPY", "CNH", | ||||
| @@ -18,69 +18,68 @@ namespace Spectre.Console.Examples | ||||
|             "DKK", "GBP", "RUB", | ||||
|             "NZD", "MXN", "IDR", | ||||
|             "TWD", "THB", "VND", | ||||
|         }; | ||||
|     }; | ||||
|  | ||||
|         public static async Task Main(string[] args) | ||||
|         { | ||||
|             var table = new Table().Expand().BorderColor(Color.Grey); | ||||
|             table.AddColumn("[yellow]Source currency[/]"); | ||||
|             table.AddColumn("[yellow]Destination currency[/]"); | ||||
|             table.AddColumn("[yellow]Exchange rate[/]"); | ||||
|     public static async Task Main(string[] args) | ||||
|     { | ||||
|         var table = new Table().Expand().BorderColor(Color.Grey); | ||||
|         table.AddColumn("[yellow]Source currency[/]"); | ||||
|         table.AddColumn("[yellow]Destination currency[/]"); | ||||
|         table.AddColumn("[yellow]Exchange rate[/]"); | ||||
|  | ||||
|             AnsiConsole.MarkupLine("Press [yellow]CTRL+C[/] to exit"); | ||||
|         AnsiConsole.MarkupLine("Press [yellow]CTRL+C[/] to exit"); | ||||
|  | ||||
|             await AnsiConsole.Live(table) | ||||
|                 .AutoClear(false) | ||||
|                 .Overflow(VerticalOverflow.Ellipsis) | ||||
|                 .Cropping(VerticalOverflowCropping.Bottom) | ||||
|                 .StartAsync(async ctx => | ||||
|                 { | ||||
|         await AnsiConsole.Live(table) | ||||
|             .AutoClear(false) | ||||
|             .Overflow(VerticalOverflow.Ellipsis) | ||||
|             .Cropping(VerticalOverflowCropping.Bottom) | ||||
|             .StartAsync(async ctx => | ||||
|             { | ||||
|                     // Add some initial rows | ||||
|                     foreach (var _ in Enumerable.Range(0, NumberOfRows)) | ||||
|                     { | ||||
|                         AddExchangeRateRow(table); | ||||
|                     } | ||||
|                 { | ||||
|                     AddExchangeRateRow(table); | ||||
|                 } | ||||
|  | ||||
|                     // Continously update the table | ||||
|                     while (true) | ||||
|                     { | ||||
|                 { | ||||
|                         // More rows than we want? | ||||
|                         if (table.Rows.Count > NumberOfRows) | ||||
|                         { | ||||
|                     { | ||||
|                             // Remove the first one | ||||
|                             table.Rows.RemoveAt(0); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                         // Add a new row | ||||
|                         AddExchangeRateRow(table); | ||||
|  | ||||
|                         // Refresh and wait for a while | ||||
|                         ctx.Refresh(); | ||||
|                         await Task.Delay(400); | ||||
|                     } | ||||
|                 }); | ||||
|         } | ||||
|                     await Task.Delay(400); | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|         private static void AddExchangeRateRow(Table table) | ||||
|     private static void AddExchangeRateRow(Table table) | ||||
|     { | ||||
|         var (source, destination, rate) = GetExchangeRate(); | ||||
|         table.AddRow( | ||||
|             source, destination, | ||||
|             _random.NextDouble() > 0.35D ? $"[green]{rate}[/]" : $"[red]{rate}[/]"); | ||||
|     } | ||||
|  | ||||
|     private static (string Source, string Destination, double Rate) GetExchangeRate() | ||||
|     { | ||||
|         var source = _exchanges[_random.Next(0, _exchanges.Length)]; | ||||
|         var dest = _exchanges[_random.Next(0, _exchanges.Length)]; | ||||
|         var rate = 200 / ((_random.NextDouble() * 320) + 1); | ||||
|  | ||||
|         while (source == dest) | ||||
|         { | ||||
|             var (source, destination, rate) = GetExchangeRate(); | ||||
|             table.AddRow( | ||||
|                 source, destination, | ||||
|                 _random.NextDouble() > 0.35D ? $"[green]{rate}[/]" : $"[red]{rate}[/]"); | ||||
|             dest = _exchanges[_random.Next(0, _exchanges.Length)]; | ||||
|         } | ||||
|  | ||||
|         private static (string Source, string Destination, double Rate) GetExchangeRate() | ||||
|         { | ||||
|             var source = _exchanges[_random.Next(0, _exchanges.Length)]; | ||||
|             var dest = _exchanges[_random.Next(0, _exchanges.Length)]; | ||||
|             var rate = 200 / ((_random.NextDouble() * 320) + 1); | ||||
|  | ||||
|             while (source == dest) | ||||
|             { | ||||
|                 dest = _exchanges[_random.Next(0, _exchanges.Length)]; | ||||
|             } | ||||
|  | ||||
|             return (source, dest, rate); | ||||
|         } | ||||
|         return (source, dest, rate); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -9,5 +9,4 @@ Write(new Table() | ||||
|     .RoundedBorder() | ||||
|     .AddColumns("[red]Greeting[/]", "[red]Subject[/]") | ||||
|     .AddRow("[yellow]Hello[/]", "World") | ||||
|     .AddRow("[green]Oh hi[/]", "[blue u]Mark[/]")); | ||||
|  | ||||
|     .AddRow("[green]Oh hi[/]", "[blue u]Mark[/]")); | ||||
| @@ -1,40 +1,39 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         { | ||||
|             var content = new Markup( | ||||
|                 "[underline]I[/] heard [underline on blue]you[/] like panels\n\n\n\n" + | ||||
|                 "So I put a panel in a panel").Centered(); | ||||
|         var content = new Markup( | ||||
|             "[underline]I[/] heard [underline on blue]you[/] like panels\n\n\n\n" + | ||||
|             "So I put a panel in a panel").Centered(); | ||||
|  | ||||
|             AnsiConsole.Write( | ||||
|                 new Panel( | ||||
|                     new Panel(content) | ||||
|                         .Border(BoxBorder.Rounded))); | ||||
|         AnsiConsole.Write( | ||||
|             new Panel( | ||||
|                 new Panel(content) | ||||
|                     .Border(BoxBorder.Rounded))); | ||||
|  | ||||
|             // Left adjusted panel with text | ||||
|             AnsiConsole.Write( | ||||
|                 new Panel(new Text("Left adjusted\nLeft").LeftAligned()) | ||||
|                     .Expand() | ||||
|                     .SquareBorder() | ||||
|                     .Header("[red]Left[/]")); | ||||
|         // Left adjusted panel with text | ||||
|         AnsiConsole.Write( | ||||
|             new Panel(new Text("Left adjusted\nLeft").LeftAligned()) | ||||
|                 .Expand() | ||||
|                 .SquareBorder() | ||||
|                 .Header("[red]Left[/]")); | ||||
|  | ||||
|             // Centered ASCII panel with text | ||||
|             AnsiConsole.Write( | ||||
|                 new Panel(new Text("Centered\nCenter").Centered()) | ||||
|                     .Expand() | ||||
|                     .AsciiBorder() | ||||
|                     .Header("[green]Center[/]") | ||||
|                     .HeaderAlignment(Justify.Center)); | ||||
|         // Centered ASCII panel with text | ||||
|         AnsiConsole.Write( | ||||
|             new Panel(new Text("Centered\nCenter").Centered()) | ||||
|                 .Expand() | ||||
|                 .AsciiBorder() | ||||
|                 .Header("[green]Center[/]") | ||||
|                 .HeaderAlignment(Justify.Center)); | ||||
|  | ||||
|             // Right adjusted, rounded panel with text | ||||
|             AnsiConsole.Write( | ||||
|                 new Panel(new Text("Right adjusted\nRight").RightAligned()) | ||||
|                     .Expand() | ||||
|                     .RoundedBorder() | ||||
|                     .Header("[blue]Right[/]") | ||||
|                     .HeaderAlignment(Justify.Right)); | ||||
|         } | ||||
|         // Right adjusted, rounded panel with text | ||||
|         AnsiConsole.Write( | ||||
|             new Panel(new Text("Right adjusted\nRight").RightAligned()) | ||||
|                 .Expand() | ||||
|                 .RoundedBorder() | ||||
|                 .Header("[blue]Right[/]") | ||||
|                 .HeaderAlignment(Justify.Right)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,45 +1,44 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class DescriptionGenerator | ||||
| { | ||||
|     public static class DescriptionGenerator | ||||
|     private static readonly string[] _verbs = new[] { "Downloading", "Rerouting", "Retriculating", "Collapsing", "Folding", "Solving", "Colliding", "Measuring" }; | ||||
|     private static readonly string[] _nouns = new[] { "internet", "splines", "space", "capacitators", "quarks", "algorithms", "data structures", "spacetime" }; | ||||
|  | ||||
|     private static readonly Random _random; | ||||
|     private static readonly HashSet<string> _used; | ||||
|  | ||||
|     static DescriptionGenerator() | ||||
|     { | ||||
|         private static readonly string[] _verbs = new[] { "Downloading", "Rerouting", "Retriculating", "Collapsing", "Folding", "Solving", "Colliding", "Measuring" }; | ||||
|         private static readonly string[] _nouns = new[] { "internet", "splines", "space", "capacitators", "quarks", "algorithms", "data structures", "spacetime" }; | ||||
|         _random = new Random(DateTime.Now.Millisecond); | ||||
|         _used = new HashSet<string>(); | ||||
|     } | ||||
|  | ||||
|         private static readonly Random _random; | ||||
|         private static readonly HashSet<string> _used; | ||||
|  | ||||
|         static DescriptionGenerator() | ||||
|     public static bool TryGenerate(out string name) | ||||
|     { | ||||
|         var iterations = 0; | ||||
|         while (iterations < 25) | ||||
|         { | ||||
|             _random = new Random(DateTime.Now.Millisecond); | ||||
|             _used = new HashSet<string>(); | ||||
|         } | ||||
|  | ||||
|         public static bool TryGenerate(out string name) | ||||
|         { | ||||
|             var iterations = 0; | ||||
|             while (iterations < 25) | ||||
|             name = Generate(); | ||||
|             if (!_used.Contains(name)) | ||||
|             { | ||||
|                 name = Generate(); | ||||
|                 if (!_used.Contains(name)) | ||||
|                 { | ||||
|                     _used.Add(name); | ||||
|                     return true; | ||||
|                 } | ||||
|  | ||||
|                 iterations++; | ||||
|                 _used.Add(name); | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             name = Generate(); | ||||
|             return false; | ||||
|             iterations++; | ||||
|         } | ||||
|  | ||||
|         public static string Generate() | ||||
|         { | ||||
|             return _verbs[_random.Next(0, _verbs.Length)] | ||||
|                 + " " + _nouns[_random.Next(0, _nouns.Length)]; | ||||
|         } | ||||
|         name = Generate(); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     public static string Generate() | ||||
|     { | ||||
|         return _verbs[_random.Next(0, _verbs.Length)] | ||||
|             + " " + _nouns[_random.Next(0, _nouns.Length)]; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,88 +2,87 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| { | ||||
|     public static class Program | ||||
|     { | ||||
|         public static void Main() | ||||
|         { | ||||
|             AnsiConsole.MarkupLine("[yellow]Initializing warp drive[/]..."); | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
|             // Show progress | ||||
|             AnsiConsole.Progress() | ||||
|                 .AutoClear(false) | ||||
|                 .Columns(new ProgressColumn[] | ||||
|                 { | ||||
| public static class Program | ||||
| { | ||||
|     public static void Main() | ||||
|     { | ||||
|         AnsiConsole.MarkupLine("[yellow]Initializing warp drive[/]..."); | ||||
|  | ||||
|         // Show progress | ||||
|         AnsiConsole.Progress() | ||||
|             .AutoClear(false) | ||||
|             .Columns(new ProgressColumn[] | ||||
|             { | ||||
|                     new TaskDescriptionColumn(),    // Task description | ||||
|                     new ProgressBarColumn(),        // Progress bar | ||||
|                     new PercentageColumn(),         // Percentage | ||||
|                     new RemainingTimeColumn(),      // Remaining time | ||||
|                     new SpinnerColumn(),            // Spinner | ||||
|                 }) | ||||
|                 .Start(ctx => | ||||
|                 { | ||||
|                     var random = new Random(DateTime.Now.Millisecond); | ||||
|             }) | ||||
|             .Start(ctx => | ||||
|             { | ||||
|                 var random = new Random(DateTime.Now.Millisecond); | ||||
|  | ||||
|                     // Create some tasks | ||||
|                     var tasks = CreateTasks(ctx, random); | ||||
|                     var warpTask = ctx.AddTask("Going to warp", autoStart: false).IsIndeterminate(); | ||||
|                 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); | ||||
|                         } | ||||
|                     { | ||||
|                         task.Increment(random.NextDouble() * increment); | ||||
|                     } | ||||
|  | ||||
|                         // Write some random things to the terminal | ||||
|                         if (random.NextDouble() < 0.1) | ||||
|                         { | ||||
|                             WriteLogMessage(); | ||||
|                         } | ||||
|                     { | ||||
|                         WriteLogMessage(); | ||||
|                     } | ||||
|  | ||||
|                         // Simulate some delay | ||||
|                         Thread.Sleep(100); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                     // Now start the "warp" task | ||||
|                     warpTask.StartTask(); | ||||
|                     warpTask.IsIndeterminate(false); | ||||
|                     while (!ctx.IsFinished) | ||||
|                     { | ||||
|                         warpTask.Increment(12 * random.NextDouble()); | ||||
|                 warpTask.IsIndeterminate(false); | ||||
|                 while (!ctx.IsFinished) | ||||
|                 { | ||||
|                     warpTask.Increment(12 * random.NextDouble()); | ||||
|  | ||||
|                         // Simulate some delay | ||||
|                         Thread.Sleep(100); | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|             // Done | ||||
|             AnsiConsole.MarkupLine("[green]Done![/]"); | ||||
|         } | ||||
|  | ||||
|         private static List<(ProgressTask Task, int Delay)> CreateTasks(ProgressContext progress, Random random) | ||||
|         { | ||||
|             var tasks = new List<(ProgressTask, int)>(); | ||||
|             while (tasks.Count < 5) | ||||
|             { | ||||
|                 if (DescriptionGenerator.TryGenerate(out var name)) | ||||
|                 { | ||||
|                     tasks.Add((progress.AddTask(name), random.Next(2, 10))); | ||||
|                 } | ||||
|             } | ||||
|             }); | ||||
|  | ||||
|             return tasks; | ||||
|         } | ||||
|         // Done | ||||
|         AnsiConsole.MarkupLine("[green]Done![/]"); | ||||
|     } | ||||
|  | ||||
|         private static void WriteLogMessage() | ||||
|     private static List<(ProgressTask Task, int Delay)> CreateTasks(ProgressContext progress, Random random) | ||||
|     { | ||||
|         var tasks = new List<(ProgressTask, int)>(); | ||||
|         while (tasks.Count < 5) | ||||
|         { | ||||
|             AnsiConsole.MarkupLine( | ||||
|                 "[grey]LOG:[/] " + | ||||
|                 DescriptionGenerator.Generate() + | ||||
|                 "[grey]...[/]"); | ||||
|             if (DescriptionGenerator.TryGenerate(out var name)) | ||||
|             { | ||||
|                 tasks.Add((progress.AddTask(name), random.Next(2, 10))); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return tasks; | ||||
|     } | ||||
|  | ||||
|     private static void WriteLogMessage() | ||||
|     { | ||||
|         AnsiConsole.MarkupLine( | ||||
|             "[grey]LOG:[/] " + | ||||
|             DescriptionGenerator.Generate() + | ||||
|             "[grey]...[/]"); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -142,4 +142,4 @@ namespace Spectre.Console.Examples | ||||
|                     .AllowEmpty()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
| @@ -1,41 +1,40 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main(string[] args) | ||||
|     { | ||||
|         public static void Main(string[] args) | ||||
|         { | ||||
|             // No title | ||||
|             Render( | ||||
|                 new Rule() | ||||
|                     .RuleStyle(Style.Parse("yellow")) | ||||
|                     .AsciiBorder() | ||||
|                     .LeftAligned()); | ||||
|         // No title | ||||
|         Render( | ||||
|             new Rule() | ||||
|                 .RuleStyle(Style.Parse("yellow")) | ||||
|                 .AsciiBorder() | ||||
|                 .LeftAligned()); | ||||
|  | ||||
|             // Left aligned title | ||||
|             Render( | ||||
|                 new Rule("[blue]Left aligned[/]") | ||||
|                     .RuleStyle(Style.Parse("red")) | ||||
|                     .DoubleBorder() | ||||
|                     .LeftAligned()); | ||||
|         // Left aligned title | ||||
|         Render( | ||||
|             new Rule("[blue]Left aligned[/]") | ||||
|                 .RuleStyle(Style.Parse("red")) | ||||
|                 .DoubleBorder() | ||||
|                 .LeftAligned()); | ||||
|  | ||||
|             // Centered title | ||||
|             Render( | ||||
|                 new Rule("[green]Centered[/]") | ||||
|                     .RuleStyle(Style.Parse("green")) | ||||
|                     .HeavyBorder() | ||||
|                     .Centered()); | ||||
|         // Centered title | ||||
|         Render( | ||||
|             new Rule("[green]Centered[/]") | ||||
|                 .RuleStyle(Style.Parse("green")) | ||||
|                 .HeavyBorder() | ||||
|                 .Centered()); | ||||
|  | ||||
|             // Right aligned title | ||||
|             Render( | ||||
|                 new Rule("[red]Right aligned[/]") | ||||
|                     .RuleStyle(Style.Parse("blue")) | ||||
|                     .RightAligned()); | ||||
|         } | ||||
|         // Right aligned title | ||||
|         Render( | ||||
|             new Rule("[red]Right aligned[/]") | ||||
|                 .RuleStyle(Style.Parse("blue")) | ||||
|                 .RightAligned()); | ||||
|     } | ||||
|  | ||||
|         private static void Render(Rule rule) | ||||
|         { | ||||
|             AnsiConsole.Write(rule); | ||||
|             AnsiConsole.WriteLine(); | ||||
|         } | ||||
|     private static void Render(Rule rule) | ||||
|     { | ||||
|         AnsiConsole.Write(rule); | ||||
|         AnsiConsole.WriteLine(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,30 +1,29 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class ExceptionGenerator | ||||
| { | ||||
|     public static class ExceptionGenerator | ||||
|     public static Exception GenerateException() | ||||
|     { | ||||
|         public static Exception GenerateException() | ||||
|         try | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 SomeOperation(); | ||||
|                 throw new InvalidOperationException(); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 return ex; | ||||
|             } | ||||
|             SomeOperation(); | ||||
|             throw new InvalidOperationException(); | ||||
|         } | ||||
|  | ||||
|         private static void SomeOperation() | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             SomeOperationGoingWrong(); | ||||
|         } | ||||
|  | ||||
|         private static void SomeOperationGoingWrong() | ||||
|         { | ||||
|             throw new InvalidOperationException("Something went very wrong!"); | ||||
|             return ex; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static void SomeOperation() | ||||
|     { | ||||
|         SomeOperationGoingWrong(); | ||||
|     } | ||||
|  | ||||
|     private static void SomeOperationGoingWrong() | ||||
|     { | ||||
|         throw new InvalidOperationException("Something went very wrong!"); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,153 +1,152 @@ | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static partial class Program | ||||
| { | ||||
|     public static partial class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         { | ||||
|             var table = new Table().HideHeaders().NoBorder(); | ||||
|             table.Title("[u][yellow]Spectre.Console[/] [b]Features[/][/]"); | ||||
|             table.AddColumn("Feature", c => c.NoWrap().RightAligned().Width(10).PadRight(3)); | ||||
|             table.AddColumn("Demonstration", c => c.PadRight(0)); | ||||
|             table.AddEmptyRow(); | ||||
|         var table = new Table().HideHeaders().NoBorder(); | ||||
|         table.Title("[u][yellow]Spectre.Console[/] [b]Features[/][/]"); | ||||
|         table.AddColumn("Feature", c => c.NoWrap().RightAligned().Width(10).PadRight(3)); | ||||
|         table.AddColumn("Demonstration", c => c.PadRight(0)); | ||||
|         table.AddEmptyRow(); | ||||
|  | ||||
|             // Colors | ||||
|             table.AddRow( | ||||
|                 new Markup("[red]Colors[/]"), | ||||
|                 GetColorTable()); | ||||
|         // Colors | ||||
|         table.AddRow( | ||||
|             new Markup("[red]Colors[/]"), | ||||
|             GetColorTable()); | ||||
|  | ||||
|             // Styles | ||||
|             table.AddEmptyRow(); | ||||
|             table.AddRow( | ||||
|                 new Markup("[red]OS[/]"), | ||||
|                 new Grid().Expand().AddColumns(3) | ||||
|                 .AddRow( | ||||
|                     "[bold green]Windows[/]", | ||||
|                     "[bold blue]macOS[/]", | ||||
|                     "[bold yellow]Linux[/]")); | ||||
|         // Styles | ||||
|         table.AddEmptyRow(); | ||||
|         table.AddRow( | ||||
|             new Markup("[red]OS[/]"), | ||||
|             new Grid().Expand().AddColumns(3) | ||||
|             .AddRow( | ||||
|                 "[bold green]Windows[/]", | ||||
|                 "[bold blue]macOS[/]", | ||||
|                 "[bold yellow]Linux[/]")); | ||||
|  | ||||
|             // Styles | ||||
|             table.AddEmptyRow(); | ||||
|             table.AddRow( | ||||
|                 "[red]Styles[/]", | ||||
|                 "All ansi styles: [bold]bold[/], [dim]dim[/], [italic]italic[/], [underline]underline[/], " | ||||
|                     + "[strikethrough]strikethrough[/], [reverse]reverse[/], and even [blink]blink[/]."); | ||||
|         // Styles | ||||
|         table.AddEmptyRow(); | ||||
|         table.AddRow( | ||||
|             "[red]Styles[/]", | ||||
|             "All ansi styles: [bold]bold[/], [dim]dim[/], [italic]italic[/], [underline]underline[/], " | ||||
|                 + "[strikethrough]strikethrough[/], [reverse]reverse[/], and even [blink]blink[/]."); | ||||
|  | ||||
|             // Text | ||||
|             table.AddEmptyRow(); | ||||
|             table.AddRow( | ||||
|                 new Markup("[red]Text[/]"), | ||||
|                 new Markup("Word wrap text. Justify [green]left[/], [yellow]center[/] or [blue]right[/].")); | ||||
|         // Text | ||||
|         table.AddEmptyRow(); | ||||
|         table.AddRow( | ||||
|             new Markup("[red]Text[/]"), | ||||
|             new Markup("Word wrap text. Justify [green]left[/], [yellow]center[/] or [blue]right[/].")); | ||||
|  | ||||
|             table.AddEmptyRow(); | ||||
|             table.AddRow( | ||||
|                 Text.Empty, | ||||
|                 GetTextGrid()); | ||||
|         table.AddEmptyRow(); | ||||
|         table.AddRow( | ||||
|             Text.Empty, | ||||
|             GetTextGrid()); | ||||
|  | ||||
|             // Markup | ||||
|             table.AddEmptyRow(); | ||||
|             table.AddRow( | ||||
|                 "[red]Markup[/]", | ||||
|                 "[bold purple]Spectre.Console[/] supports a simple [i]bbcode[/] like " | ||||
|                     + "[b]markup[/] for [yellow]color[/], [underline]style[/], and emoji! " | ||||
|                     + ":thumbs_up: :red_apple: :ant: :bear: :baguette_bread: :bus:"); | ||||
|         // Markup | ||||
|         table.AddEmptyRow(); | ||||
|         table.AddRow( | ||||
|             "[red]Markup[/]", | ||||
|             "[bold purple]Spectre.Console[/] supports a simple [i]bbcode[/] like " | ||||
|                 + "[b]markup[/] for [yellow]color[/], [underline]style[/], and emoji! " | ||||
|                 + ":thumbs_up: :red_apple: :ant: :bear: :baguette_bread: :bus:"); | ||||
|  | ||||
|             // Trees and tables | ||||
|             table.AddEmptyRow(); | ||||
|             table.AddRow( | ||||
|                 new Markup("[red]Tables and Trees[/]"), | ||||
|                 GetTreeTable()); | ||||
|         // Trees and tables | ||||
|         table.AddEmptyRow(); | ||||
|         table.AddRow( | ||||
|             new Markup("[red]Tables and Trees[/]"), | ||||
|             GetTreeTable()); | ||||
|  | ||||
|             // Charts | ||||
|             table.AddRow( | ||||
|                 new Markup("[red]Charts[/]"), | ||||
|                 new Grid().Collapse().AddColumns(2).AddRow( | ||||
|                     new Panel(GetBreakdownChart()).BorderColor(Color.Grey), | ||||
|                     new Panel(GetBarChart()).BorderColor(Color.Grey))); | ||||
|         // Charts | ||||
|         table.AddRow( | ||||
|             new Markup("[red]Charts[/]"), | ||||
|             new Grid().Collapse().AddColumns(2).AddRow( | ||||
|                 new Panel(GetBreakdownChart()).BorderColor(Color.Grey), | ||||
|                 new Panel(GetBarChart()).BorderColor(Color.Grey))); | ||||
|  | ||||
|  | ||||
|             // Exceptions | ||||
|             table.AddEmptyRow(); | ||||
|             table.AddRow( | ||||
|                 new Markup("[red]Exceptions[/]"), | ||||
|                 ExceptionGenerator.GenerateException().GetRenderable()); | ||||
|         // Exceptions | ||||
|         table.AddEmptyRow(); | ||||
|         table.AddRow( | ||||
|             new Markup("[red]Exceptions[/]"), | ||||
|             ExceptionGenerator.GenerateException().GetRenderable()); | ||||
|  | ||||
|             // Much more | ||||
|             table.AddEmptyRow(); | ||||
|             table.AddRow( | ||||
|                 "[red]+ Much more![/]", | ||||
|                 "Tables, Grids, Trees, Progress bars, Status, Bar charts, Calendars, Figlet, Images, Text prompts, " | ||||
|                     + "List boxes, Separators, Pretty exceptions, Canvas, CLI parsing"); | ||||
|             table.AddEmptyRow(); | ||||
|         // Much more | ||||
|         table.AddEmptyRow(); | ||||
|         table.AddRow( | ||||
|             "[red]+ Much more![/]", | ||||
|             "Tables, Grids, Trees, Progress bars, Status, Bar charts, Calendars, Figlet, Images, Text prompts, " | ||||
|                 + "List boxes, Separators, Pretty exceptions, Canvas, CLI parsing"); | ||||
|         table.AddEmptyRow(); | ||||
|  | ||||
|             // Render the table | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.Write(table); | ||||
|         } | ||||
|         // Render the table | ||||
|         AnsiConsole.WriteLine(); | ||||
|         AnsiConsole.Write(table); | ||||
|     } | ||||
|  | ||||
|         private static IRenderable GetColorTable() | ||||
|         { | ||||
|             var colorTable = new Table().Collapse().HideHeaders().NoBorder(); | ||||
|             colorTable.AddColumn("Desc", c => c.PadRight(3)).AddColumn("Colors", c => c.PadRight(0)); | ||||
|             colorTable.AddRow( | ||||
|                 new Markup( | ||||
|                     "✓ [bold grey]NO_COLOR support[/]\n" + | ||||
|                     "✓ [bold green]3-bit color[/]\n" + | ||||
|                     "✓ [bold blue]4-bit color[/]\n" + | ||||
|                     "✓ [bold purple]8-bit color[/]\n" + | ||||
|                     "✓ [bold yellow]Truecolor (16.7 million)[/]\n" + | ||||
|                     "✓ [bold aqua]Automatic color conversion[/]"), | ||||
|                 new ColorBox(height: 6)); | ||||
|     private static IRenderable GetColorTable() | ||||
|     { | ||||
|         var colorTable = new Table().Collapse().HideHeaders().NoBorder(); | ||||
|         colorTable.AddColumn("Desc", c => c.PadRight(3)).AddColumn("Colors", c => c.PadRight(0)); | ||||
|         colorTable.AddRow( | ||||
|             new Markup( | ||||
|                 "✓ [bold grey]NO_COLOR support[/]\n" + | ||||
|                 "✓ [bold green]3-bit color[/]\n" + | ||||
|                 "✓ [bold blue]4-bit color[/]\n" + | ||||
|                 "✓ [bold purple]8-bit color[/]\n" + | ||||
|                 "✓ [bold yellow]Truecolor (16.7 million)[/]\n" + | ||||
|                 "✓ [bold aqua]Automatic color conversion[/]"), | ||||
|             new ColorBox(height: 6)); | ||||
|  | ||||
|             return colorTable; | ||||
|         } | ||||
|         return colorTable; | ||||
|     } | ||||
|  | ||||
|         private static IRenderable GetTextGrid() | ||||
|         { | ||||
|             var loremTable = new Grid(); | ||||
|             var lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque in metus sed sapien ultricies pretium a at justo. Maecenas luctus velit et auctor maximus."; | ||||
|             loremTable.AddColumn(new GridColumn().LeftAligned()); | ||||
|             loremTable.AddColumn(new GridColumn().Centered()); | ||||
|             loremTable.AddColumn(new GridColumn().RightAligned()); | ||||
|             loremTable.AddRow($"[green]{lorem}[/]", $"[yellow]{lorem}[/]", $"[blue]{lorem}[/]"); | ||||
|             return loremTable; | ||||
|         } | ||||
|     private static IRenderable GetTextGrid() | ||||
|     { | ||||
|         var loremTable = new Grid(); | ||||
|         var lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque in metus sed sapien ultricies pretium a at justo. Maecenas luctus velit et auctor maximus."; | ||||
|         loremTable.AddColumn(new GridColumn().LeftAligned()); | ||||
|         loremTable.AddColumn(new GridColumn().Centered()); | ||||
|         loremTable.AddColumn(new GridColumn().RightAligned()); | ||||
|         loremTable.AddRow($"[green]{lorem}[/]", $"[yellow]{lorem}[/]", $"[blue]{lorem}[/]"); | ||||
|         return loremTable; | ||||
|     } | ||||
|  | ||||
|         private static IRenderable GetTreeTable() | ||||
|         { | ||||
|             var tree = new Tree("📁 src"); | ||||
|             tree.AddNode("📁 foo").AddNode("📄 bar.cs"); | ||||
|             tree.AddNode("📁 baz").AddNode("📁 qux").AddNode("📄 corgi.txt"); | ||||
|             tree.AddNode("📄 waldo.xml"); | ||||
|     private static IRenderable GetTreeTable() | ||||
|     { | ||||
|         var tree = new Tree("📁 src"); | ||||
|         tree.AddNode("📁 foo").AddNode("📄 bar.cs"); | ||||
|         tree.AddNode("📁 baz").AddNode("📁 qux").AddNode("📄 corgi.txt"); | ||||
|         tree.AddNode("📄 waldo.xml"); | ||||
|  | ||||
|             var table = new Table().SimpleBorder().BorderColor(Color.Grey); | ||||
|             table.AddColumn(new TableColumn("Overview")); | ||||
|             table.AddColumn(new TableColumn("").Footer("[grey]3 Files, 225 KiB[/]")); | ||||
|             table.AddRow(new Markup("[yellow]Files[/]"), tree); | ||||
|         var table = new Table().SimpleBorder().BorderColor(Color.Grey); | ||||
|         table.AddColumn(new TableColumn("Overview")); | ||||
|         table.AddColumn(new TableColumn("").Footer("[grey]3 Files, 225 KiB[/]")); | ||||
|         table.AddRow(new Markup("[yellow]Files[/]"), tree); | ||||
|  | ||||
|             return new Table().RoundedBorder().Collapse().BorderColor(Color.Yellow) | ||||
|                 .AddColumn("Foo").AddColumn("Bar") | ||||
|                 .AddRow(new Text("Baz"), table) | ||||
|                 .AddRow("Qux", "Corgi"); | ||||
|         } | ||||
|         return new Table().RoundedBorder().Collapse().BorderColor(Color.Yellow) | ||||
|             .AddColumn("Foo").AddColumn("Bar") | ||||
|             .AddRow(new Text("Baz"), table) | ||||
|             .AddRow("Qux", "Corgi"); | ||||
|     } | ||||
|  | ||||
|         private static IRenderable GetBarChart() | ||||
|         { | ||||
|             return new BarChart() | ||||
|                 .AddItem("Apple", 32, Color.Green) | ||||
|                 .AddItem("Oranges", 13, Color.Orange1) | ||||
|                 .AddItem("Bananas", 22, Color.Yellow); | ||||
|         } | ||||
|     private static IRenderable GetBarChart() | ||||
|     { | ||||
|         return new BarChart() | ||||
|             .AddItem("Apple", 32, Color.Green) | ||||
|             .AddItem("Oranges", 13, Color.Orange1) | ||||
|             .AddItem("Bananas", 22, Color.Yellow); | ||||
|     } | ||||
|  | ||||
|         private static IRenderable GetBreakdownChart() | ||||
|         { | ||||
|             return new BreakdownChart() | ||||
|                 .ShowPercentage() | ||||
|                 .FullSize() | ||||
|                 .AddItem("C#", 82, Color.Green) | ||||
|                 .AddItem("PowerShell", 13, Color.Red) | ||||
|                 .AddItem("Bash", 5, Color.Blue); | ||||
|         } | ||||
|     private static IRenderable GetBreakdownChart() | ||||
|     { | ||||
|         return new BreakdownChart() | ||||
|             .ShowPercentage() | ||||
|             .FullSize() | ||||
|             .AddItem("C#", 82, Color.Green) | ||||
|             .AddItem("PowerShell", 13, Color.Red) | ||||
|             .AddItem("Bash", 5, Color.Blue); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,69 +1,68 @@ | ||||
| using System.Threading; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         { | ||||
|             AnsiConsole.Status() | ||||
|                 .AutoRefresh(true) | ||||
|                 .Spinner(Spinner.Known.Default) | ||||
|                 .Start("[yellow]Initializing warp drive[/]", ctx => | ||||
|                 { | ||||
|         AnsiConsole.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"); | ||||
|                 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[/]"); | ||||
|                 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[/]"); | ||||
|                 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[/]"); | ||||
|                 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); | ||||
|                     } | ||||
|                 }); | ||||
|                 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[/]"); | ||||
|         } | ||||
|         // Done | ||||
|         AnsiConsole.MarkupLine("[bold green]Crusing at Warp 9.8[/]"); | ||||
|     } | ||||
|  | ||||
|         private static void WriteLogMessage(string message) | ||||
|         { | ||||
|             AnsiConsole.MarkupLine($"[grey]LOG:[/] {message}[grey]...[/]"); | ||||
|         } | ||||
|     private static void WriteLogMessage(string message) | ||||
|     { | ||||
|         AnsiConsole.MarkupLine($"[grey]LOG:[/] {message}[grey]...[/]"); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,45 +1,44 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         { | ||||
|             AnsiConsole.Write(CreateTable()); | ||||
|         } | ||||
|         AnsiConsole.Write(CreateTable()); | ||||
|     } | ||||
|  | ||||
|         private static Table CreateTable() | ||||
|         { | ||||
|             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![/]", ""); | ||||
|     private static Table CreateTable() | ||||
|     { | ||||
|         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 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![/]", ""); | ||||
|  | ||||
|             return 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); | ||||
|         } | ||||
|         return 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); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,43 +1,42 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public static class Program | ||||
| { | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         public static void Main() | ||||
|         { | ||||
|             AnsiConsole.WriteLine(); | ||||
|         AnsiConsole.WriteLine(); | ||||
|  | ||||
|             // Render the tree | ||||
|             var tree = BuildTree(); | ||||
|             AnsiConsole.Write(tree); | ||||
|         } | ||||
|         // Render the tree | ||||
|         var tree = BuildTree(); | ||||
|         AnsiConsole.Write(tree); | ||||
|     } | ||||
|  | ||||
|         private static Tree BuildTree() | ||||
|         { | ||||
|             // Create the tree | ||||
|             var tree = new Tree("Root") | ||||
|                 .Style(Style.Parse("red")) | ||||
|                 .Guide(TreeGuide.Line); | ||||
|     private static Tree BuildTree() | ||||
|     { | ||||
|         // Create the tree | ||||
|         var tree = new Tree("Root") | ||||
|             .Style(Style.Parse("red")) | ||||
|             .Guide(TreeGuide.Line); | ||||
|  | ||||
|             // Add some nodes | ||||
|             var foo = tree.AddNode("[yellow]Foo[/]"); | ||||
|             var table = foo.AddNode(new Table() | ||||
|                 .RoundedBorder() | ||||
|                 .AddColumn("First") | ||||
|                 .AddColumn("Second") | ||||
|                 .AddRow("1", "2") | ||||
|                 .AddRow("3", "4") | ||||
|                 .AddRow("5", "6")); | ||||
|         // Add some nodes | ||||
|         var foo = tree.AddNode("[yellow]Foo[/]"); | ||||
|         var table = foo.AddNode(new Table() | ||||
|             .RoundedBorder() | ||||
|             .AddColumn("First") | ||||
|             .AddColumn("Second") | ||||
|             .AddRow("1", "2") | ||||
|             .AddRow("3", "4") | ||||
|             .AddRow("5", "6")); | ||||
|  | ||||
|             table.AddNode("[blue]Baz[/]"); | ||||
|             foo.AddNode("Qux"); | ||||
|         table.AddNode("[blue]Baz[/]"); | ||||
|         foo.AddNode("Qux"); | ||||
|  | ||||
|             var bar = tree.AddNode("[yellow]Bar[/]"); | ||||
|             bar.AddNode(new Calendar(2020, 12) | ||||
|                 .AddCalendarEvent(2020, 12, 12) | ||||
|                 .HideHeader()); | ||||
|         var bar = tree.AddNode("[yellow]Bar[/]"); | ||||
|         bar.AddNode(new Calendar(2020, 12) | ||||
|             .AddCalendarEvent(2020, 12, 12) | ||||
|             .HideHeader()); | ||||
|  | ||||
|             // Return the tree | ||||
|             return tree; | ||||
|         } | ||||
|         // Return the tree | ||||
|         return tree; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,123 +2,122 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console.Examples | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
| public sealed class ColorBox : Renderable | ||||
| { | ||||
|     public sealed class ColorBox : Renderable | ||||
|     private readonly int _height; | ||||
|     private int? _width; | ||||
|  | ||||
|     public ColorBox(int height) | ||||
|     { | ||||
|         private readonly int _height; | ||||
|         private int? _width; | ||||
|         _height = height; | ||||
|     } | ||||
|  | ||||
|         public ColorBox(int height) | ||||
|     public ColorBox(int width, int height) | ||||
|         : this(height) | ||||
|     { | ||||
|         _width = width; | ||||
|     } | ||||
|  | ||||
|     protected override Measurement Measure(RenderContext context, int maxWidth) | ||||
|     { | ||||
|         return new Measurement(1, GetWidth(maxWidth)); | ||||
|     } | ||||
|  | ||||
|     protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth) | ||||
|     { | ||||
|         maxWidth = GetWidth(maxWidth); | ||||
|  | ||||
|         for (var y = 0; y < _height; y++) | ||||
|         { | ||||
|             _height = height; | ||||
|             for (var x = 0; x < maxWidth; x++) | ||||
|             { | ||||
|                 var h = x / (float)maxWidth; | ||||
|                 var l = 0.1f + ((y / (float)_height) * 0.7f); | ||||
|                 var (r1, g1, b1) = ColorFromHSL(h, l, 1.0f); | ||||
|                 var (r2, g2, b2) = ColorFromHSL(h, l + (0.7f / 10), 1.0f); | ||||
|  | ||||
|                 var background = new Color((byte)(r1 * 255), (byte)(g1 * 255), (byte)(b1 * 255)); | ||||
|                 var foreground = new Color((byte)(r2 * 255), (byte)(g2 * 255), (byte)(b2 * 255)); | ||||
|  | ||||
|                 yield return new Segment("▄", new Style(foreground, background)); | ||||
|             } | ||||
|  | ||||
|             yield return Segment.LineBreak; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private int GetWidth(int maxWidth) | ||||
|     { | ||||
|         var width = maxWidth; | ||||
|         if (_width != null) | ||||
|         { | ||||
|             width = Math.Min(_width.Value, width); | ||||
|         } | ||||
|  | ||||
|         public ColorBox(int width, int height) | ||||
|             : this(height) | ||||
|         return width; | ||||
|     } | ||||
|  | ||||
|     private static (float, float, float) ColorFromHSL(double h, double l, double s) | ||||
|     { | ||||
|         double r = 0, g = 0, b = 0; | ||||
|         if (l != 0) | ||||
|         { | ||||
|             _width = width; | ||||
|         } | ||||
|  | ||||
|         protected override Measurement Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             return new Measurement(1, GetWidth(maxWidth)); | ||||
|         } | ||||
|  | ||||
|         protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             maxWidth = GetWidth(maxWidth); | ||||
|  | ||||
|             for (var y = 0; y < _height; y++) | ||||
|             if (s == 0) | ||||
|             { | ||||
|                 for (var x = 0; x < maxWidth; x++) | ||||
|                 { | ||||
|                     var h = x / (float)maxWidth; | ||||
|                     var l = 0.1f + ((y / (float)_height) * 0.7f); | ||||
|                     var (r1, g1, b1) = ColorFromHSL(h, l, 1.0f); | ||||
|                     var (r2, g2, b2) = ColorFromHSL(h, l + (0.7f / 10), 1.0f); | ||||
|  | ||||
|                     var background = new Color((byte)(r1 * 255), (byte)(g1 * 255), (byte)(b1 * 255)); | ||||
|                     var foreground = new Color((byte)(r2 * 255), (byte)(g2 * 255), (byte)(b2 * 255)); | ||||
|  | ||||
|                     yield return new Segment("▄", new Style(foreground, background)); | ||||
|                 } | ||||
|  | ||||
|                 yield return Segment.LineBreak; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private int GetWidth(int maxWidth) | ||||
|         { | ||||
|             var width = maxWidth; | ||||
|             if (_width != null) | ||||
|             { | ||||
|                 width = Math.Min(_width.Value, width); | ||||
|             } | ||||
|  | ||||
|             return width; | ||||
|         } | ||||
|  | ||||
|         private static (float, float, float) ColorFromHSL(double h, double l, double s) | ||||
|         { | ||||
|             double r = 0, g = 0, b = 0; | ||||
|             if (l != 0) | ||||
|             { | ||||
|                 if (s == 0) | ||||
|                 { | ||||
|                     r = g = b = l; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     double temp2; | ||||
|                     if (l < 0.5) | ||||
|                     { | ||||
|                         temp2 = l * (1.0 + s); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         temp2 = l + s - (l * s); | ||||
|                     } | ||||
|  | ||||
|                     var temp1 = 2.0 * l - temp2; | ||||
|  | ||||
|                     r = GetColorComponent(temp1, temp2, h + 1.0 / 3.0); | ||||
|                     g = GetColorComponent(temp1, temp2, h); | ||||
|                     b = GetColorComponent(temp1, temp2, h - 1.0 / 3.0); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return ((float)r, (float)g, (float)b); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         private static double GetColorComponent(double temp1, double temp2, double temp3) | ||||
|         { | ||||
|             if (temp3 < 0.0) | ||||
|             { | ||||
|                 temp3 += 1.0; | ||||
|             } | ||||
|             else if (temp3 > 1.0) | ||||
|             { | ||||
|                 temp3 -= 1.0; | ||||
|             } | ||||
|  | ||||
|             if (temp3 < 1.0 / 6.0) | ||||
|             { | ||||
|                 return temp1 + (temp2 - temp1) * 6.0 * temp3; | ||||
|             } | ||||
|             else if (temp3 < 0.5) | ||||
|             { | ||||
|                 return temp2; | ||||
|             } | ||||
|             else if (temp3 < 2.0 / 3.0) | ||||
|             { | ||||
|                 return temp1 + ((temp2 - temp1) * ((2.0 / 3.0) - temp3) * 6.0); | ||||
|                 r = g = b = l; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return temp1; | ||||
|                 double temp2; | ||||
|                 if (l < 0.5) | ||||
|                 { | ||||
|                     temp2 = l * (1.0 + s); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     temp2 = l + s - (l * s); | ||||
|                 } | ||||
|  | ||||
|                 var temp1 = 2.0 * l - temp2; | ||||
|  | ||||
|                 r = GetColorComponent(temp1, temp2, h + 1.0 / 3.0); | ||||
|                 g = GetColorComponent(temp1, temp2, h); | ||||
|                 b = GetColorComponent(temp1, temp2, h - 1.0 / 3.0); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return ((float)r, (float)g, (float)b); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     private static double GetColorComponent(double temp1, double temp2, double temp3) | ||||
|     { | ||||
|         if (temp3 < 0.0) | ||||
|         { | ||||
|             temp3 += 1.0; | ||||
|         } | ||||
|         else if (temp3 > 1.0) | ||||
|         { | ||||
|             temp3 -= 1.0; | ||||
|         } | ||||
|  | ||||
|         if (temp3 < 1.0 / 6.0) | ||||
|         { | ||||
|             return temp1 + (temp2 - temp1) * 6.0 * temp3; | ||||
|         } | ||||
|         else if (temp3 < 0.5) | ||||
|         { | ||||
|             return temp2; | ||||
|         } | ||||
|         else if (temp3 < 2.0 / 3.0) | ||||
|         { | ||||
|             return temp1 + ((temp2 - temp1) * ((2.0 / 3.0) - temp3) * 6.0); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return temp1; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,15 +1,14 @@ | ||||
| namespace Spectre.Console.Examples | ||||
| { | ||||
|     public static class ColorExtensions | ||||
|     { | ||||
|         public static Color GetInvertedColor(this Color color) | ||||
|         { | ||||
|             return GetLuminance(color) < 140 ? Color.White : Color.Black; | ||||
|         } | ||||
| namespace Spectre.Console.Examples; | ||||
|  | ||||
|         private static float GetLuminance(this Color color) | ||||
|         { | ||||
|             return (float)((0.2126 * color.R) + (0.7152 * color.G) + (0.0722 * color.B)); | ||||
|         } | ||||
| public static class ColorExtensions | ||||
| { | ||||
|     public static Color GetInvertedColor(this Color color) | ||||
|     { | ||||
|         return GetLuminance(color) < 140 ? Color.White : Color.Black; | ||||
|     } | ||||
|  | ||||
|     private static float GetLuminance(this Color color) | ||||
|     { | ||||
|         return (float)((0.2126 * color.R) + (0.7152 * color.G) + (0.0722 * color.B)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <Project> | ||||
|   <PropertyGroup Label="Settings"> | ||||
|     <Deterministic>true</Deterministic> | ||||
|     <LangVersion>9.0</LangVersion> | ||||
|     <LangVersion>10</LangVersion> | ||||
|     <DebugSymbols>true</DebugSymbols> | ||||
|     <DebugType>embedded</DebugType> | ||||
|     <MinVerSkip Condition="'$(Configuration)' == 'Debug'">true</MinVerSkip> | ||||
|   | ||||
| @@ -1,16 +1,15 @@ | ||||
| namespace Spectre.Console.Analyzer.Sandbox | ||||
| namespace Spectre.Console.Analyzer.Sandbox; | ||||
|  | ||||
| /// <summary> | ||||
| /// Sample sandbox for testing out analyzers. | ||||
| /// </summary> | ||||
| public static class Program | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Sample sandbox for testing out analyzers. | ||||
|     /// The program's entry point. | ||||
|     /// </summary> | ||||
|     public static class Program | ||||
|     public static void Main() | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// The program's entry point. | ||||
|         /// </summary> | ||||
|         public static void Main() | ||||
|         { | ||||
|             AnsiConsole.WriteLine("Project is set up with a reference to Spectre.Console.Analyzer"); | ||||
|         } | ||||
|         AnsiConsole.WriteLine("Project is set up with a reference to Spectre.Console.Analyzer"); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -6,90 +6,89 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; | ||||
| using Microsoft.CodeAnalysis.Diagnostics; | ||||
| using Microsoft.CodeAnalysis.Operations; | ||||
|  | ||||
| namespace Spectre.Console.Analyzer | ||||
| namespace Spectre.Console.Analyzer; | ||||
|  | ||||
| /// <summary> | ||||
| /// Analyzer to suggest using available instances of AnsiConsole over the static methods. | ||||
| /// </summary> | ||||
| [DiagnosticAnalyzer(LanguageNames.CSharp)] | ||||
| public class FavorInstanceAnsiConsoleOverStaticAnalyzer : SpectreAnalyzer | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Analyzer to suggest using available instances of AnsiConsole over the static methods. | ||||
|     /// </summary> | ||||
|     [DiagnosticAnalyzer(LanguageNames.CSharp)] | ||||
|     public class FavorInstanceAnsiConsoleOverStaticAnalyzer : SpectreAnalyzer | ||||
|     private static readonly DiagnosticDescriptor _diagnosticDescriptor = | ||||
|         Descriptors.S1010_FavorInstanceAnsiConsoleOverStatic; | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => | ||||
|         ImmutableArray.Create(_diagnosticDescriptor); | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     protected override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext) | ||||
|     { | ||||
|         private static readonly DiagnosticDescriptor _diagnosticDescriptor = | ||||
|             Descriptors.S1010_FavorInstanceAnsiConsoleOverStatic; | ||||
|         compilationStartContext.RegisterOperationAction( | ||||
|             context => | ||||
|             { | ||||
|                 var ansiConsoleType = context.Compilation.GetTypeByMetadataName("Spectre.Console.AnsiConsole"); | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => | ||||
|             ImmutableArray.Create(_diagnosticDescriptor); | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         protected override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext) | ||||
|         { | ||||
|             compilationStartContext.RegisterOperationAction( | ||||
|                 context => | ||||
|                 // if this operation isn't an invocation against one of the System.Console methods | ||||
|                 // defined in _methods then we can safely stop analyzing and return; | ||||
|                 var invocationOperation = (IInvocationOperation)context.Operation; | ||||
|                 if (!Equals(invocationOperation.TargetMethod.ContainingType, ansiConsoleType)) | ||||
|                 { | ||||
|                     var ansiConsoleType = context.Compilation.GetTypeByMetadataName("Spectre.Console.AnsiConsole"); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                     // if this operation isn't an invocation against one of the System.Console methods | ||||
|                     // defined in _methods then we can safely stop analyzing and return; | ||||
|                     var invocationOperation = (IInvocationOperation)context.Operation; | ||||
|                     if (!Equals(invocationOperation.TargetMethod.ContainingType, ansiConsoleType)) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 // if we aren't in a method then it might be too complex for us to handle. | ||||
|                 if (!invocationOperation.Syntax.Ancestors().OfType<MethodDeclarationSyntax>().Any()) | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                     // if we aren't in a method then it might be too complex for us to handle. | ||||
|                     if (!invocationOperation.Syntax.Ancestors().OfType<MethodDeclarationSyntax>().Any()) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 if (!HasFieldAnsiConsole(invocationOperation.Syntax) && | ||||
|                     !HasParameterAnsiConsole(invocationOperation.Syntax)) | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                     if (!HasFieldAnsiConsole(invocationOperation.Syntax) && | ||||
|                         !HasParameterAnsiConsole(invocationOperation.Syntax)) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 var methodSymbol = invocationOperation.TargetMethod; | ||||
|  | ||||
|                     var methodSymbol = invocationOperation.TargetMethod; | ||||
|                 var displayString = SymbolDisplay.ToDisplayString( | ||||
|                     methodSymbol, | ||||
|                     SymbolDisplayFormat.CSharpShortErrorMessageFormat | ||||
|                         .WithParameterOptions(SymbolDisplayParameterOptions.None) | ||||
|                         .WithGenericsOptions(SymbolDisplayGenericsOptions.None)); | ||||
|  | ||||
|                     var displayString = SymbolDisplay.ToDisplayString( | ||||
|                         methodSymbol, | ||||
|                         SymbolDisplayFormat.CSharpShortErrorMessageFormat | ||||
|                             .WithParameterOptions(SymbolDisplayParameterOptions.None) | ||||
|                             .WithGenericsOptions(SymbolDisplayGenericsOptions.None)); | ||||
|  | ||||
|                     context.ReportDiagnostic( | ||||
|                         Diagnostic.Create( | ||||
|                             _diagnosticDescriptor, | ||||
|                             invocationOperation.Syntax.GetLocation(), | ||||
|                             displayString)); | ||||
|                 }, OperationKind.Invocation); | ||||
|         } | ||||
|  | ||||
|         private static bool HasParameterAnsiConsole(SyntaxNode syntaxNode) | ||||
|         { | ||||
|             return syntaxNode | ||||
|                 .Ancestors().OfType<MethodDeclarationSyntax>() | ||||
|                 .First() | ||||
|                 .ParameterList.Parameters | ||||
|                 .Any(i => i.Type.NormalizeWhitespace().ToString() == "IAnsiConsole"); | ||||
|         } | ||||
|  | ||||
|         private static bool HasFieldAnsiConsole(SyntaxNode syntaxNode) | ||||
|         { | ||||
|             var isStatic = syntaxNode | ||||
|                 .Ancestors() | ||||
|                 .OfType<MethodDeclarationSyntax>() | ||||
|                 .First() | ||||
|                 .Modifiers.Any(i => i.Kind() == SyntaxKind.StaticKeyword); | ||||
|  | ||||
|             return syntaxNode | ||||
|                 .Ancestors().OfType<ClassDeclarationSyntax>() | ||||
|                 .First() | ||||
|                 .Members | ||||
|                 .OfType<FieldDeclarationSyntax>() | ||||
|                 .Any(i => | ||||
|                     i.Declaration.Type.NormalizeWhitespace().ToString() == "IAnsiConsole" && | ||||
|                     (!isStatic ^ i.Modifiers.Any(modifier => modifier.Kind() == SyntaxKind.StaticKeyword))); | ||||
|         } | ||||
|                 context.ReportDiagnostic( | ||||
|                     Diagnostic.Create( | ||||
|                         _diagnosticDescriptor, | ||||
|                         invocationOperation.Syntax.GetLocation(), | ||||
|                         displayString)); | ||||
|             }, OperationKind.Invocation); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     private static bool HasParameterAnsiConsole(SyntaxNode syntaxNode) | ||||
|     { | ||||
|         return syntaxNode | ||||
|             .Ancestors().OfType<MethodDeclarationSyntax>() | ||||
|             .First() | ||||
|             .ParameterList.Parameters | ||||
|             .Any(i => i.Type.NormalizeWhitespace().ToString() == "IAnsiConsole"); | ||||
|     } | ||||
|  | ||||
|     private static bool HasFieldAnsiConsole(SyntaxNode syntaxNode) | ||||
|     { | ||||
|         var isStatic = syntaxNode | ||||
|             .Ancestors() | ||||
|             .OfType<MethodDeclarationSyntax>() | ||||
|             .First() | ||||
|             .Modifiers.Any(i => i.Kind() == SyntaxKind.StaticKeyword); | ||||
|  | ||||
|         return syntaxNode | ||||
|             .Ancestors().OfType<ClassDeclarationSyntax>() | ||||
|             .First() | ||||
|             .Members | ||||
|             .OfType<FieldDeclarationSyntax>() | ||||
|             .Any(i => | ||||
|                 i.Declaration.Type.NormalizeWhitespace().ToString() == "IAnsiConsole" && | ||||
|                 (!isStatic ^ i.Modifiers.Any(modifier => modifier.Kind() == SyntaxKind.StaticKeyword))); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -7,72 +7,71 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; | ||||
| using Microsoft.CodeAnalysis.Diagnostics; | ||||
| using Microsoft.CodeAnalysis.Operations; | ||||
|  | ||||
| namespace Spectre.Console.Analyzer | ||||
| namespace Spectre.Console.Analyzer; | ||||
|  | ||||
| /// <summary> | ||||
| /// Analyzer to detect calls to live renderables within a live renderable context. | ||||
| /// </summary> | ||||
| [DiagnosticAnalyzer(LanguageNames.CSharp)] | ||||
| [Shared] | ||||
| public class NoConcurrentLiveRenderablesAnalyzer : SpectreAnalyzer | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Analyzer to detect calls to live renderables within a live renderable context. | ||||
|     /// </summary> | ||||
|     [DiagnosticAnalyzer(LanguageNames.CSharp)] | ||||
|     [Shared] | ||||
|     public class NoConcurrentLiveRenderablesAnalyzer : SpectreAnalyzer | ||||
|     private static readonly DiagnosticDescriptor _diagnosticDescriptor = | ||||
|         Descriptors.S1020_AvoidConcurrentCallsToMultipleLiveRenderables; | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => | ||||
|         ImmutableArray.Create(_diagnosticDescriptor); | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     protected override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext) | ||||
|     { | ||||
|         private static readonly DiagnosticDescriptor _diagnosticDescriptor = | ||||
|             Descriptors.S1020_AvoidConcurrentCallsToMultipleLiveRenderables; | ||||
|         compilationStartContext.RegisterOperationAction( | ||||
|             context => | ||||
|             { | ||||
|                 var invocationOperation = (IInvocationOperation)context.Operation; | ||||
|                 var methodSymbol = invocationOperation.TargetMethod; | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => | ||||
|             ImmutableArray.Create(_diagnosticDescriptor); | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         protected override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext) | ||||
|         { | ||||
|             compilationStartContext.RegisterOperationAction( | ||||
|                 context => | ||||
|                 const string StartMethod = "Start"; | ||||
|                 if (methodSymbol.Name != StartMethod) | ||||
|                 { | ||||
|                     var invocationOperation = (IInvocationOperation)context.Operation; | ||||
|                     var methodSymbol = invocationOperation.TargetMethod; | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                     const string StartMethod = "Start"; | ||||
|                     if (methodSymbol.Name != StartMethod) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 var liveTypes = Constants.LiveRenderables | ||||
|                     .Select(i => context.Compilation.GetTypeByMetadataName(i)) | ||||
|                     .ToImmutableArray(); | ||||
|  | ||||
|                     var liveTypes = Constants.LiveRenderables | ||||
|                         .Select(i => context.Compilation.GetTypeByMetadataName(i)) | ||||
|                         .ToImmutableArray(); | ||||
|                 if (liveTypes.All(i => !Equals(i, methodSymbol.ContainingType))) | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                     if (liveTypes.All(i => !Equals(i, methodSymbol.ContainingType))) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 var model = context.Compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree); | ||||
|                 var parentInvocations = invocationOperation | ||||
|                     .Syntax.Ancestors() | ||||
|                     .OfType<InvocationExpressionSyntax>() | ||||
|                     .Select(i => model.GetOperation(i)) | ||||
|                     .OfType<IInvocationOperation>() | ||||
|                     .ToList(); | ||||
|  | ||||
|                     var model = context.Compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree); | ||||
|                     var parentInvocations = invocationOperation | ||||
|                         .Syntax.Ancestors() | ||||
|                         .OfType<InvocationExpressionSyntax>() | ||||
|                         .Select(i => model.GetOperation(i)) | ||||
|                         .OfType<IInvocationOperation>() | ||||
|                         .ToList(); | ||||
|                 if (parentInvocations.All(parent => | ||||
|                     parent.TargetMethod.Name != StartMethod || !liveTypes.Contains(parent.TargetMethod.ContainingType))) | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                     if (parentInvocations.All(parent => | ||||
|                         parent.TargetMethod.Name != StartMethod || !liveTypes.Contains(parent.TargetMethod.ContainingType))) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 var displayString = SymbolDisplay.ToDisplayString( | ||||
|                     methodSymbol, | ||||
|                     SymbolDisplayFormat.CSharpShortErrorMessageFormat | ||||
|                         .WithParameterOptions(SymbolDisplayParameterOptions.None) | ||||
|                         .WithGenericsOptions(SymbolDisplayGenericsOptions.None)); | ||||
|  | ||||
|                     var displayString = SymbolDisplay.ToDisplayString( | ||||
|                         methodSymbol, | ||||
|                         SymbolDisplayFormat.CSharpShortErrorMessageFormat | ||||
|                             .WithParameterOptions(SymbolDisplayParameterOptions.None) | ||||
|                             .WithGenericsOptions(SymbolDisplayGenericsOptions.None)); | ||||
|  | ||||
|                     context.ReportDiagnostic( | ||||
|                         Diagnostic.Create( | ||||
|                             _diagnosticDescriptor, | ||||
|                             invocationOperation.Syntax.GetLocation(), | ||||
|                             displayString)); | ||||
|                 }, OperationKind.Invocation); | ||||
|         } | ||||
|                 context.ReportDiagnostic( | ||||
|                     Diagnostic.Create( | ||||
|                         _diagnosticDescriptor, | ||||
|                         invocationOperation.Syntax.GetLocation(), | ||||
|                         displayString)); | ||||
|             }, OperationKind.Invocation); | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -7,78 +7,77 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; | ||||
| using Microsoft.CodeAnalysis.Diagnostics; | ||||
| using Microsoft.CodeAnalysis.Operations; | ||||
|  | ||||
| namespace Spectre.Console.Analyzer | ||||
| namespace Spectre.Console.Analyzer; | ||||
|  | ||||
| /// <summary> | ||||
| /// Analyzer to detect calls to live renderables within a live renderable context. | ||||
| /// </summary> | ||||
| [DiagnosticAnalyzer(LanguageNames.CSharp)] | ||||
| [Shared] | ||||
| public class NoPromptsDuringLiveRenderablesAnalyzer : SpectreAnalyzer | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Analyzer to detect calls to live renderables within a live renderable context. | ||||
|     /// </summary> | ||||
|     [DiagnosticAnalyzer(LanguageNames.CSharp)] | ||||
|     [Shared] | ||||
|     public class NoPromptsDuringLiveRenderablesAnalyzer : SpectreAnalyzer | ||||
|     private static readonly DiagnosticDescriptor _diagnosticDescriptor = | ||||
|         Descriptors.S1021_AvoidPromptCallsDuringLiveRenderables; | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => | ||||
|         ImmutableArray.Create(_diagnosticDescriptor); | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     protected override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext) | ||||
|     { | ||||
|         private static readonly DiagnosticDescriptor _diagnosticDescriptor = | ||||
|             Descriptors.S1021_AvoidPromptCallsDuringLiveRenderables; | ||||
|         compilationStartContext.RegisterOperationAction( | ||||
|             context => | ||||
|             { | ||||
|                 // if this operation isn't an invocation against one of the System.Console methods | ||||
|                 // defined in _methods then we can safely stop analyzing and return; | ||||
|                 var invocationOperation = (IInvocationOperation)context.Operation; | ||||
|                 var methodSymbol = invocationOperation.TargetMethod; | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => | ||||
|             ImmutableArray.Create(_diagnosticDescriptor); | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         protected override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext) | ||||
|         { | ||||
|             compilationStartContext.RegisterOperationAction( | ||||
|                 context => | ||||
|                 var promptMethods = ImmutableArray.Create("Ask", "Confirm", "Prompt"); | ||||
|                 if (!promptMethods.Contains(methodSymbol.Name)) | ||||
|                 { | ||||
|                     // if this operation isn't an invocation against one of the System.Console methods | ||||
|                     // defined in _methods then we can safely stop analyzing and return; | ||||
|                     var invocationOperation = (IInvocationOperation)context.Operation; | ||||
|                     var methodSymbol = invocationOperation.TargetMethod; | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                     var promptMethods = ImmutableArray.Create("Ask", "Confirm", "Prompt"); | ||||
|                     if (!promptMethods.Contains(methodSymbol.Name)) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 var ansiConsoleType = context.Compilation.GetTypeByMetadataName("Spectre.Console.AnsiConsole"); | ||||
|                 var ansiConsoleExtensionsType = context.Compilation.GetTypeByMetadataName("Spectre.Console.AnsiConsoleExtensions"); | ||||
|  | ||||
|                     var ansiConsoleType = context.Compilation.GetTypeByMetadataName("Spectre.Console.AnsiConsole"); | ||||
|                     var ansiConsoleExtensionsType = context.Compilation.GetTypeByMetadataName("Spectre.Console.AnsiConsoleExtensions"); | ||||
|                 if (!Equals(methodSymbol.ContainingType, ansiConsoleType) && !Equals(methodSymbol.ContainingType, ansiConsoleExtensionsType)) | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                     if (!Equals(methodSymbol.ContainingType, ansiConsoleType) && !Equals(methodSymbol.ContainingType, ansiConsoleExtensionsType)) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 var model = context.Compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree); | ||||
|                 var parentInvocations = invocationOperation | ||||
|                     .Syntax.Ancestors() | ||||
|                     .OfType<InvocationExpressionSyntax>() | ||||
|                     .Select(i => model.GetOperation(i)) | ||||
|                     .OfType<IInvocationOperation>() | ||||
|                     .ToList(); | ||||
|  | ||||
|                     var model = context.Compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree); | ||||
|                     var parentInvocations = invocationOperation | ||||
|                         .Syntax.Ancestors() | ||||
|                         .OfType<InvocationExpressionSyntax>() | ||||
|                         .Select(i => model.GetOperation(i)) | ||||
|                         .OfType<IInvocationOperation>() | ||||
|                         .ToList(); | ||||
|                 var liveTypes = Constants.LiveRenderables | ||||
|                     .Select(i => context.Compilation.GetTypeByMetadataName(i)) | ||||
|                     .ToImmutableArray(); | ||||
|  | ||||
|                     var liveTypes = Constants.LiveRenderables | ||||
|                         .Select(i => context.Compilation.GetTypeByMetadataName(i)) | ||||
|                         .ToImmutableArray(); | ||||
|                 if (parentInvocations.All(parent => | ||||
|                     parent.TargetMethod.Name != "Start" || | ||||
|                     !liveTypes.Contains(parent.TargetMethod.ContainingType))) | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                     if (parentInvocations.All(parent => | ||||
|                         parent.TargetMethod.Name != "Start" || | ||||
|                         !liveTypes.Contains(parent.TargetMethod.ContainingType))) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 var displayString = SymbolDisplay.ToDisplayString( | ||||
|                     methodSymbol, | ||||
|                     SymbolDisplayFormat.CSharpShortErrorMessageFormat | ||||
|                         .WithParameterOptions(SymbolDisplayParameterOptions.None) | ||||
|                         .WithGenericsOptions(SymbolDisplayGenericsOptions.None)); | ||||
|  | ||||
|                     var displayString = SymbolDisplay.ToDisplayString( | ||||
|                         methodSymbol, | ||||
|                         SymbolDisplayFormat.CSharpShortErrorMessageFormat | ||||
|                             .WithParameterOptions(SymbolDisplayParameterOptions.None) | ||||
|                             .WithGenericsOptions(SymbolDisplayGenericsOptions.None)); | ||||
|  | ||||
|                     context.ReportDiagnostic( | ||||
|                         Diagnostic.Create( | ||||
|                             _diagnosticDescriptor, | ||||
|                             invocationOperation.Syntax.GetLocation(), | ||||
|                             displayString)); | ||||
|                 }, OperationKind.Invocation); | ||||
|         } | ||||
|                 context.ReportDiagnostic( | ||||
|                     Diagnostic.Create( | ||||
|                         _diagnosticDescriptor, | ||||
|                         invocationOperation.Syntax.GetLocation(), | ||||
|                         displayString)); | ||||
|             }, OperationKind.Invocation); | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,25 +1,24 @@ | ||||
| using Microsoft.CodeAnalysis.Diagnostics; | ||||
|  | ||||
| namespace Spectre.Console.Analyzer | ||||
| namespace Spectre.Console.Analyzer; | ||||
|  | ||||
| /// <summary> | ||||
| /// Base class for Spectre analyzers. | ||||
| /// </summary> | ||||
| public abstract class SpectreAnalyzer : DiagnosticAnalyzer | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Base class for Spectre analyzers. | ||||
|     /// </summary> | ||||
|     public abstract class SpectreAnalyzer : DiagnosticAnalyzer | ||||
|     /// <inheritdoc /> | ||||
|     public override void Initialize(AnalysisContext context) | ||||
|     { | ||||
|         /// <inheritdoc /> | ||||
|         public override void Initialize(AnalysisContext context) | ||||
|         { | ||||
|             context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); | ||||
|             context.EnableConcurrentExecution(); | ||||
|         context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); | ||||
|         context.EnableConcurrentExecution(); | ||||
|  | ||||
|             context.RegisterCompilationStartAction(AnalyzeCompilation); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Analyze compilation. | ||||
|         /// </summary> | ||||
|         /// <param name="compilationStartContext">Compilation Start Analysis Context.</param> | ||||
|         protected abstract void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext); | ||||
|         context.RegisterCompilationStartAction(AnalyzeCompilation); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Analyze compilation. | ||||
|     /// </summary> | ||||
|     /// <param name="compilationStartContext">Compilation Start Analysis Context.</param> | ||||
|     protected abstract void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext); | ||||
| } | ||||
|   | ||||
| @@ -4,60 +4,59 @@ using Microsoft.CodeAnalysis.CSharp; | ||||
| using Microsoft.CodeAnalysis.Diagnostics; | ||||
| using Microsoft.CodeAnalysis.Operations; | ||||
|  | ||||
| namespace Spectre.Console.Analyzer | ||||
| namespace Spectre.Console.Analyzer; | ||||
|  | ||||
| /// <summary> | ||||
| /// Analyzer to enforce the use of AnsiConsole over System.Console for known methods. | ||||
| /// </summary> | ||||
| [DiagnosticAnalyzer(LanguageNames.CSharp)] | ||||
| public class UseSpectreInsteadOfSystemConsoleAnalyzer : SpectreAnalyzer | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Analyzer to enforce the use of AnsiConsole over System.Console for known methods. | ||||
|     /// </summary> | ||||
|     [DiagnosticAnalyzer(LanguageNames.CSharp)] | ||||
|     public class UseSpectreInsteadOfSystemConsoleAnalyzer : SpectreAnalyzer | ||||
|     private static readonly DiagnosticDescriptor _diagnosticDescriptor = | ||||
|         Descriptors.S1000_UseAnsiConsoleOverSystemConsole; | ||||
|  | ||||
|     private static readonly string[] _methods = { "WriteLine", "Write" }; | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => | ||||
|         ImmutableArray.Create(_diagnosticDescriptor); | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     protected override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext) | ||||
|     { | ||||
|         private static readonly DiagnosticDescriptor _diagnosticDescriptor = | ||||
|             Descriptors.S1000_UseAnsiConsoleOverSystemConsole; | ||||
|         compilationStartContext.RegisterOperationAction( | ||||
|             context => | ||||
|             { | ||||
|                 // if this operation isn't an invocation against one of the System.Console methods | ||||
|                 // defined in _methods then we can safely stop analyzing and return; | ||||
|                 var invocationOperation = (IInvocationOperation)context.Operation; | ||||
|  | ||||
|         private static readonly string[] _methods = { "WriteLine", "Write" }; | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => | ||||
|             ImmutableArray.Create(_diagnosticDescriptor); | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         protected override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext) | ||||
|         { | ||||
|             compilationStartContext.RegisterOperationAction( | ||||
|                 context => | ||||
|                 var methodName = System.Array.Find(_methods, i => i.Equals(invocationOperation.TargetMethod.Name)); | ||||
|                 if (methodName == null) | ||||
|                 { | ||||
|                     // if this operation isn't an invocation against one of the System.Console methods | ||||
|                     // defined in _methods then we can safely stop analyzing and return; | ||||
|                     var invocationOperation = (IInvocationOperation)context.Operation; | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                     var methodName = System.Array.Find(_methods, i => i.Equals(invocationOperation.TargetMethod.Name)); | ||||
|                     if (methodName == null) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 var systemConsoleType = context.Compilation.GetTypeByMetadataName("System.Console"); | ||||
|  | ||||
|                     var systemConsoleType = context.Compilation.GetTypeByMetadataName("System.Console"); | ||||
|                 if (!Equals(invocationOperation.TargetMethod.ContainingType, systemConsoleType)) | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                     if (!Equals(invocationOperation.TargetMethod.ContainingType, systemConsoleType)) | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 var methodSymbol = invocationOperation.TargetMethod; | ||||
|  | ||||
|                     var methodSymbol = invocationOperation.TargetMethod; | ||||
|                 var displayString = SymbolDisplay.ToDisplayString( | ||||
|                     methodSymbol, | ||||
|                     SymbolDisplayFormat.CSharpShortErrorMessageFormat | ||||
|                         .WithParameterOptions(SymbolDisplayParameterOptions.None) | ||||
|                         .WithGenericsOptions(SymbolDisplayGenericsOptions.None)); | ||||
|  | ||||
|                     var displayString = SymbolDisplay.ToDisplayString( | ||||
|                         methodSymbol, | ||||
|                         SymbolDisplayFormat.CSharpShortErrorMessageFormat | ||||
|                             .WithParameterOptions(SymbolDisplayParameterOptions.None) | ||||
|                             .WithGenericsOptions(SymbolDisplayGenericsOptions.None)); | ||||
|  | ||||
|                     context.ReportDiagnostic( | ||||
|                         Diagnostic.Create( | ||||
|                             _diagnosticDescriptor, | ||||
|                             invocationOperation.Syntax.GetLocation(), | ||||
|                             displayString)); | ||||
|                 }, OperationKind.Invocation); | ||||
|         } | ||||
|                 context.ReportDiagnostic( | ||||
|                     Diagnostic.Create( | ||||
|                         _diagnosticDescriptor, | ||||
|                         invocationOperation.Syntax.GetLocation(), | ||||
|                         displayString)); | ||||
|             }, OperationKind.Invocation); | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,15 +1,14 @@ | ||||
| namespace Spectre.Console.Analyzer | ||||
| { | ||||
|     internal static class Constants | ||||
|     { | ||||
|         internal const string StaticInstance = "AnsiConsole"; | ||||
|         internal const string SpectreConsole = "Spectre.Console"; | ||||
| namespace Spectre.Console.Analyzer; | ||||
|  | ||||
|         internal static readonly string[] LiveRenderables = | ||||
|         { | ||||
|             "Spectre.Console.LiveDisplay", | ||||
|             "Spectre.Console.Progress", | ||||
|             "Spectre.Console.Status", | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| internal static class Constants | ||||
| { | ||||
|     internal const string StaticInstance = "AnsiConsole"; | ||||
|     internal const string SpectreConsole = "Spectre.Console"; | ||||
|  | ||||
|     internal static readonly string[] LiveRenderables = | ||||
|     { | ||||
|         "Spectre.Console.LiveDisplay", | ||||
|         "Spectre.Console.Progress", | ||||
|         "Spectre.Console.Status", | ||||
|     }; | ||||
| } | ||||
|   | ||||
| @@ -3,77 +3,76 @@ using Microsoft.CodeAnalysis; | ||||
| using static Microsoft.CodeAnalysis.DiagnosticSeverity; | ||||
| using static Spectre.Console.Analyzer.Descriptors.Category; | ||||
|  | ||||
| namespace Spectre.Console.Analyzer | ||||
| namespace Spectre.Console.Analyzer; | ||||
|  | ||||
| /// <summary> | ||||
| /// Code analysis descriptors. | ||||
| /// </summary> | ||||
| public static class Descriptors | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Code analysis descriptors. | ||||
|     /// </summary> | ||||
|     public static class Descriptors | ||||
|     internal enum Category | ||||
|     { | ||||
|         internal enum Category | ||||
|         { | ||||
|             Usage, // 1xxx | ||||
|         } | ||||
|  | ||||
|         private static readonly ConcurrentDictionary<Category, string> _categoryMapping = new(); | ||||
|  | ||||
|         private static DiagnosticDescriptor Rule(string id, string title, Category category, DiagnosticSeverity defaultSeverity, string messageFormat, string? description = null) | ||||
|         { | ||||
|             var helpLink = $"https://spectreconsole.net/analyzer/rules/{id.ToLowerInvariant()}"; | ||||
|             const bool IsEnabledByDefault = true; | ||||
|             return new DiagnosticDescriptor( | ||||
|                 id, | ||||
|                 title, | ||||
|                 messageFormat, | ||||
|                 _categoryMapping.GetOrAdd(category, c => c.ToString()), | ||||
|                 defaultSeverity, | ||||
|                 IsEnabledByDefault, | ||||
|                 description, | ||||
|                 helpLink); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets definitions of diagnostics Spectre1000. | ||||
|         /// </summary> | ||||
|         public static DiagnosticDescriptor S1000_UseAnsiConsoleOverSystemConsole { get; } = | ||||
|             Rule( | ||||
|                 "Spectre1000", | ||||
|                 "Use AnsiConsole instead of System.Console", | ||||
|                 Usage, | ||||
|                 Warning, | ||||
|                 "Use AnsiConsole instead of System.Console"); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets definitions of diagnostics Spectre1010. | ||||
|         /// </summary> | ||||
|         public static DiagnosticDescriptor S1010_FavorInstanceAnsiConsoleOverStatic { get; } = | ||||
|             Rule( | ||||
|                 "Spectre1010", | ||||
|                 "Favor the use of the instance of AnsiConsole over the static helper.", | ||||
|                 Usage, | ||||
|                 Info, | ||||
|                 "Favor the use of the instance of AnsiConsole over the static helper."); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets definitions of diagnostics Spectre1020. | ||||
|         /// </summary> | ||||
|         public static DiagnosticDescriptor S1020_AvoidConcurrentCallsToMultipleLiveRenderables { get; } = | ||||
|             Rule( | ||||
|                 "Spectre1020", | ||||
|                 "Avoid calling other live renderables while a current renderable is running.", | ||||
|                 Usage, | ||||
|                 Warning, | ||||
|                 "Avoid calling other live renderables while a current renderable is running."); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets definitions of diagnostics Spectre1020. | ||||
|         /// </summary> | ||||
|         public static DiagnosticDescriptor S1021_AvoidPromptCallsDuringLiveRenderables { get; } = | ||||
|             Rule( | ||||
|                 "Spectre1021", | ||||
|                 "Avoid prompting for input while a current renderable is running.", | ||||
|                 Usage, | ||||
|                 Warning, | ||||
|                 "Avoid prompting for input while a current renderable is running."); | ||||
|         Usage, // 1xxx | ||||
|     } | ||||
| } | ||||
|  | ||||
|     private static readonly ConcurrentDictionary<Category, string> _categoryMapping = new(); | ||||
|  | ||||
|     private static DiagnosticDescriptor Rule(string id, string title, Category category, DiagnosticSeverity defaultSeverity, string messageFormat, string? description = null) | ||||
|     { | ||||
|         var helpLink = $"https://spectreconsole.net/analyzer/rules/{id.ToLowerInvariant()}"; | ||||
|         const bool IsEnabledByDefault = true; | ||||
|         return new DiagnosticDescriptor( | ||||
|             id, | ||||
|             title, | ||||
|             messageFormat, | ||||
|             _categoryMapping.GetOrAdd(category, c => c.ToString()), | ||||
|             defaultSeverity, | ||||
|             IsEnabledByDefault, | ||||
|             description, | ||||
|             helpLink); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets definitions of diagnostics Spectre1000. | ||||
|     /// </summary> | ||||
|     public static DiagnosticDescriptor S1000_UseAnsiConsoleOverSystemConsole { get; } = | ||||
|         Rule( | ||||
|             "Spectre1000", | ||||
|             "Use AnsiConsole instead of System.Console", | ||||
|             Usage, | ||||
|             Warning, | ||||
|             "Use AnsiConsole instead of System.Console"); | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets definitions of diagnostics Spectre1010. | ||||
|     /// </summary> | ||||
|     public static DiagnosticDescriptor S1010_FavorInstanceAnsiConsoleOverStatic { get; } = | ||||
|         Rule( | ||||
|             "Spectre1010", | ||||
|             "Favor the use of the instance of AnsiConsole over the static helper.", | ||||
|             Usage, | ||||
|             Info, | ||||
|             "Favor the use of the instance of AnsiConsole over the static helper."); | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets definitions of diagnostics Spectre1020. | ||||
|     /// </summary> | ||||
|     public static DiagnosticDescriptor S1020_AvoidConcurrentCallsToMultipleLiveRenderables { get; } = | ||||
|         Rule( | ||||
|             "Spectre1020", | ||||
|             "Avoid calling other live renderables while a current renderable is running.", | ||||
|             Usage, | ||||
|             Warning, | ||||
|             "Avoid calling other live renderables while a current renderable is running."); | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets definitions of diagnostics Spectre1020. | ||||
|     /// </summary> | ||||
|     public static DiagnosticDescriptor S1021_AvoidPromptCallsDuringLiveRenderables { get; } = | ||||
|         Rule( | ||||
|             "Spectre1021", | ||||
|             "Avoid prompting for input while a current renderable is running.", | ||||
|             Usage, | ||||
|             Warning, | ||||
|             "Avoid prompting for input while a current renderable is running."); | ||||
| } | ||||
|   | ||||
| @@ -7,110 +7,109 @@ using Microsoft.CodeAnalysis.CSharp; | ||||
| using Microsoft.CodeAnalysis.CSharp.Syntax; | ||||
| using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; | ||||
|  | ||||
| namespace Spectre.Console.Analyzer.CodeActions | ||||
| namespace Spectre.Console.Analyzer.CodeActions; | ||||
|  | ||||
| /// <summary> | ||||
| /// Code action to change calls to System.Console to AnsiConsole. | ||||
| /// </summary> | ||||
| public class SwitchToAnsiConsoleAction : CodeAction | ||||
| { | ||||
|     private readonly Document _document; | ||||
|     private readonly InvocationExpressionSyntax _originalInvocation; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Code action to change calls to System.Console to AnsiConsole. | ||||
|     /// Initializes a new instance of the <see cref="SwitchToAnsiConsoleAction"/> class. | ||||
|     /// </summary> | ||||
|     public class SwitchToAnsiConsoleAction : CodeAction | ||||
|     /// <param name="document">Document to change.</param> | ||||
|     /// <param name="originalInvocation">The method to change.</param> | ||||
|     /// <param name="title">Title of the fix.</param> | ||||
|     public SwitchToAnsiConsoleAction(Document document, InvocationExpressionSyntax originalInvocation, string title) | ||||
|     { | ||||
|         private readonly Document _document; | ||||
|         private readonly InvocationExpressionSyntax _originalInvocation; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="SwitchToAnsiConsoleAction"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="document">Document to change.</param> | ||||
|         /// <param name="originalInvocation">The method to change.</param> | ||||
|         /// <param name="title">Title of the fix.</param> | ||||
|         public SwitchToAnsiConsoleAction(Document document, InvocationExpressionSyntax originalInvocation, string title) | ||||
|         { | ||||
|             _document = document; | ||||
|             _originalInvocation = originalInvocation; | ||||
|             Title = title; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         public override string Title { get; } | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         public override string EquivalenceKey => Title; | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         protected override async Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken) | ||||
|         { | ||||
|             var originalCaller = ((MemberAccessExpressionSyntax)_originalInvocation.Expression).Name.ToString(); | ||||
|  | ||||
|             var syntaxTree = await _document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); | ||||
|             var root = (CompilationUnitSyntax)await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); | ||||
|  | ||||
|             // If there is an ansiConsole passed into the method then we'll use it. | ||||
|             // otherwise we'll check for a field level instance. | ||||
|             // if neither of those exist we'll fall back to the static param. | ||||
|             var ansiConsoleParameterDeclaration = GetAnsiConsoleParameterDeclaration(); | ||||
|             var ansiConsoleFieldIdentifier = GetAnsiConsoleFieldDeclaration(); | ||||
|             var ansiConsoleIdentifier = ansiConsoleParameterDeclaration ?? | ||||
|                                         ansiConsoleFieldIdentifier ?? | ||||
|                                         Constants.StaticInstance; | ||||
|  | ||||
|             // Replace the System.Console call with a call to the identifier above. | ||||
|             var newRoot = root.ReplaceNode( | ||||
|                 _originalInvocation, | ||||
|                 GetImportedSpectreCall(originalCaller, ansiConsoleIdentifier)); | ||||
|  | ||||
|             // If we are calling the static instance and Spectre isn't imported yet we should do so. | ||||
|             if (ansiConsoleIdentifier == Constants.StaticInstance && root.Usings.ToList().All(i => i.Name.ToString() != Constants.SpectreConsole)) | ||||
|             { | ||||
|                 newRoot = newRoot.AddUsings(Syntax.SpectreUsing); | ||||
|             } | ||||
|  | ||||
|             return _document.WithSyntaxRoot(newRoot); | ||||
|         } | ||||
|  | ||||
|         private string? GetAnsiConsoleParameterDeclaration() | ||||
|         { | ||||
|             return _originalInvocation | ||||
|                 .Ancestors().OfType<MethodDeclarationSyntax>() | ||||
|                 .First() | ||||
|                 .ParameterList.Parameters | ||||
|                 .FirstOrDefault(i => i.Type.NormalizeWhitespace().ToString() == "IAnsiConsole") | ||||
|                 ?.Identifier.Text; | ||||
|         } | ||||
|  | ||||
|         private string? GetAnsiConsoleFieldDeclaration() | ||||
|         { | ||||
|             // let's look to see if our call is in a static method. | ||||
|             // if so we'll only want to look for static IAnsiConsoles | ||||
|             // and vice-versa if we aren't. | ||||
|             var isStatic = _originalInvocation | ||||
|                 .Ancestors() | ||||
|                 .OfType<MethodDeclarationSyntax>() | ||||
|                 .First() | ||||
|                 .Modifiers.Any(i => i.Kind() == SyntaxKind.StaticKeyword); | ||||
|  | ||||
|             return _originalInvocation | ||||
|                 .Ancestors().OfType<ClassDeclarationSyntax>() | ||||
|                 .First() | ||||
|                 .Members | ||||
|                 .OfType<FieldDeclarationSyntax>() | ||||
|                 .FirstOrDefault(i => | ||||
|                     i.Declaration.Type.NormalizeWhitespace().ToString() == "IAnsiConsole" && | ||||
|                     (!isStatic ^ i.Modifiers.Any(modifier => modifier.Kind() == SyntaxKind.StaticKeyword))) | ||||
|                 ?.Declaration.Variables.First().Identifier.Text; | ||||
|         } | ||||
|  | ||||
|         private ExpressionSyntax GetImportedSpectreCall(string originalCaller, string ansiConsoleIdentifier) | ||||
|         { | ||||
|             return ExpressionStatement( | ||||
|                     InvocationExpression( | ||||
|                             MemberAccessExpression( | ||||
|                                 SyntaxKind.SimpleMemberAccessExpression, | ||||
|                                 IdentifierName(ansiConsoleIdentifier), | ||||
|                                 IdentifierName(originalCaller))) | ||||
|                         .WithArgumentList(_originalInvocation.ArgumentList) | ||||
|                         .WithTrailingTrivia(_originalInvocation.GetTrailingTrivia()) | ||||
|                         .WithLeadingTrivia(_originalInvocation.GetLeadingTrivia())) | ||||
|             .Expression; | ||||
|         } | ||||
|         _document = document; | ||||
|         _originalInvocation = originalInvocation; | ||||
|         Title = title; | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public override string Title { get; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public override string EquivalenceKey => Title; | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     protected override async Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken) | ||||
|     { | ||||
|         var originalCaller = ((MemberAccessExpressionSyntax)_originalInvocation.Expression).Name.ToString(); | ||||
|  | ||||
|         var syntaxTree = await _document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); | ||||
|         var root = (CompilationUnitSyntax)await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); | ||||
|  | ||||
|         // If there is an ansiConsole passed into the method then we'll use it. | ||||
|         // otherwise we'll check for a field level instance. | ||||
|         // if neither of those exist we'll fall back to the static param. | ||||
|         var ansiConsoleParameterDeclaration = GetAnsiConsoleParameterDeclaration(); | ||||
|         var ansiConsoleFieldIdentifier = GetAnsiConsoleFieldDeclaration(); | ||||
|         var ansiConsoleIdentifier = ansiConsoleParameterDeclaration ?? | ||||
|                                     ansiConsoleFieldIdentifier ?? | ||||
|                                     Constants.StaticInstance; | ||||
|  | ||||
|         // Replace the System.Console call with a call to the identifier above. | ||||
|         var newRoot = root.ReplaceNode( | ||||
|             _originalInvocation, | ||||
|             GetImportedSpectreCall(originalCaller, ansiConsoleIdentifier)); | ||||
|  | ||||
|         // If we are calling the static instance and Spectre isn't imported yet we should do so. | ||||
|         if (ansiConsoleIdentifier == Constants.StaticInstance && root.Usings.ToList().All(i => i.Name.ToString() != Constants.SpectreConsole)) | ||||
|         { | ||||
|             newRoot = newRoot.AddUsings(Syntax.SpectreUsing); | ||||
|         } | ||||
|  | ||||
|         return _document.WithSyntaxRoot(newRoot); | ||||
|     } | ||||
|  | ||||
|     private string? GetAnsiConsoleParameterDeclaration() | ||||
|     { | ||||
|         return _originalInvocation | ||||
|             .Ancestors().OfType<MethodDeclarationSyntax>() | ||||
|             .First() | ||||
|             .ParameterList.Parameters | ||||
|             .FirstOrDefault(i => i.Type.NormalizeWhitespace().ToString() == "IAnsiConsole") | ||||
|             ?.Identifier.Text; | ||||
|     } | ||||
|  | ||||
|     private string? GetAnsiConsoleFieldDeclaration() | ||||
|     { | ||||
|         // let's look to see if our call is in a static method. | ||||
|         // if so we'll only want to look for static IAnsiConsoles | ||||
|         // and vice-versa if we aren't. | ||||
|         var isStatic = _originalInvocation | ||||
|             .Ancestors() | ||||
|             .OfType<MethodDeclarationSyntax>() | ||||
|             .First() | ||||
|             .Modifiers.Any(i => i.Kind() == SyntaxKind.StaticKeyword); | ||||
|  | ||||
|         return _originalInvocation | ||||
|             .Ancestors().OfType<ClassDeclarationSyntax>() | ||||
|             .First() | ||||
|             .Members | ||||
|             .OfType<FieldDeclarationSyntax>() | ||||
|             .FirstOrDefault(i => | ||||
|                 i.Declaration.Type.NormalizeWhitespace().ToString() == "IAnsiConsole" && | ||||
|                 (!isStatic ^ i.Modifiers.Any(modifier => modifier.Kind() == SyntaxKind.StaticKeyword))) | ||||
|             ?.Declaration.Variables.First().Identifier.Text; | ||||
|     } | ||||
|  | ||||
|     private ExpressionSyntax GetImportedSpectreCall(string originalCaller, string ansiConsoleIdentifier) | ||||
|     { | ||||
|         return ExpressionStatement( | ||||
|                 InvocationExpression( | ||||
|                         MemberAccessExpression( | ||||
|                             SyntaxKind.SimpleMemberAccessExpression, | ||||
|                             IdentifierName(ansiConsoleIdentifier), | ||||
|                             IdentifierName(originalCaller))) | ||||
|                     .WithArgumentList(_originalInvocation.ArgumentList) | ||||
|                     .WithTrailingTrivia(_originalInvocation.GetTrailingTrivia()) | ||||
|                     .WithLeadingTrivia(_originalInvocation.GetLeadingTrivia())) | ||||
|         .Expression; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -6,30 +6,29 @@ using Microsoft.CodeAnalysis.CodeFixes; | ||||
| using Microsoft.CodeAnalysis.CSharp.Syntax; | ||||
| using Spectre.Console.Analyzer.CodeActions; | ||||
|  | ||||
| namespace Spectre.Console.Analyzer.FixProviders | ||||
| namespace Spectre.Console.Analyzer.FixProviders; | ||||
|  | ||||
| /// <summary> | ||||
| /// Fix provider to change System.Console calls to AnsiConsole calls. | ||||
| /// </summary> | ||||
| [ExportCodeFixProvider(LanguageNames.CSharp)] | ||||
| [Shared] | ||||
| public class StaticAnsiConsoleToInstanceFix : CodeFixProvider | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Fix provider to change System.Console calls to AnsiConsole calls. | ||||
|     /// </summary> | ||||
|     [ExportCodeFixProvider(LanguageNames.CSharp)] | ||||
|     [Shared] | ||||
|     public class StaticAnsiConsoleToInstanceFix : CodeFixProvider | ||||
|     /// <inheritdoc /> | ||||
|     public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create( | ||||
|         Descriptors.S1010_FavorInstanceAnsiConsoleOverStatic.Id); | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public override async Task RegisterCodeFixesAsync(CodeFixContext context) | ||||
|     { | ||||
|         /// <inheritdoc /> | ||||
|         public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create( | ||||
|             Descriptors.S1010_FavorInstanceAnsiConsoleOverStatic.Id); | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         public override async Task RegisterCodeFixesAsync(CodeFixContext context) | ||||
|         { | ||||
|             var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); | ||||
|             var methodDeclaration = root.FindNode(context.Span).FirstAncestorOrSelf<InvocationExpressionSyntax>(); | ||||
|             context.RegisterCodeFix( | ||||
|                 new SwitchToAnsiConsoleAction(context.Document, methodDeclaration, "Convert static AnsiConsole calls to local instance."), | ||||
|                 context.Diagnostics); | ||||
|         } | ||||
|         var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); | ||||
|         var methodDeclaration = root.FindNode(context.Span).FirstAncestorOrSelf<InvocationExpressionSyntax>(); | ||||
|         context.RegisterCodeFix( | ||||
|             new SwitchToAnsiConsoleAction(context.Document, methodDeclaration, "Convert static AnsiConsole calls to local instance."), | ||||
|             context.Diagnostics); | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -6,30 +6,29 @@ using Microsoft.CodeAnalysis.CodeFixes; | ||||
| using Microsoft.CodeAnalysis.CSharp.Syntax; | ||||
| using Spectre.Console.Analyzer.CodeActions; | ||||
|  | ||||
| namespace Spectre.Console.Analyzer.FixProviders | ||||
| namespace Spectre.Console.Analyzer.FixProviders; | ||||
|  | ||||
| /// <summary> | ||||
| /// Fix provider to change System.Console calls to AnsiConsole calls. | ||||
| /// </summary> | ||||
| [ExportCodeFixProvider(LanguageNames.CSharp)] | ||||
| [Shared] | ||||
| public class SystemConsoleToAnsiConsoleFix : CodeFixProvider | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Fix provider to change System.Console calls to AnsiConsole calls. | ||||
|     /// </summary> | ||||
|     [ExportCodeFixProvider(LanguageNames.CSharp)] | ||||
|     [Shared] | ||||
|     public class SystemConsoleToAnsiConsoleFix : CodeFixProvider | ||||
|     /// <inheritdoc /> | ||||
|     public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create( | ||||
|         Descriptors.S1000_UseAnsiConsoleOverSystemConsole.Id); | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public override async Task RegisterCodeFixesAsync(CodeFixContext context) | ||||
|     { | ||||
|         /// <inheritdoc /> | ||||
|         public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create( | ||||
|             Descriptors.S1000_UseAnsiConsoleOverSystemConsole.Id); | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; | ||||
|  | ||||
|         /// <inheritdoc /> | ||||
|         public override async Task RegisterCodeFixesAsync(CodeFixContext context) | ||||
|         { | ||||
|             var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); | ||||
|             var methodDeclaration = root.FindNode(context.Span).FirstAncestorOrSelf<InvocationExpressionSyntax>(); | ||||
|             context.RegisterCodeFix( | ||||
|                 new SwitchToAnsiConsoleAction(context.Document, methodDeclaration, "Convert static call to AnsiConsole to Spectre.Console.AnsiConsole"), | ||||
|                 context.Diagnostics); | ||||
|         } | ||||
|         var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); | ||||
|         var methodDeclaration = root.FindNode(context.Span).FirstAncestorOrSelf<InvocationExpressionSyntax>(); | ||||
|         context.RegisterCodeFix( | ||||
|             new SwitchToAnsiConsoleAction(context.Document, methodDeclaration, "Convert static call to AnsiConsole to Spectre.Console.AnsiConsole"), | ||||
|             context.Diagnostics); | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,10 +1,9 @@ | ||||
| using Microsoft.CodeAnalysis.CSharp.Syntax; | ||||
| using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; | ||||
|  | ||||
| namespace Spectre.Console.Analyzer | ||||
| namespace Spectre.Console.Analyzer; | ||||
|  | ||||
| internal static class Syntax | ||||
| { | ||||
|     internal static class Syntax | ||||
|     { | ||||
|         public static readonly UsingDirectiveSyntax SpectreUsing = UsingDirective(QualifiedName(IdentifierName("Spectre"), IdentifierName("Console"))); | ||||
|     } | ||||
| } | ||||
|     public static readonly UsingDirectiveSyntax SpectreUsing = UsingDirective(QualifiedName(IdentifierName("Spectre"), IdentifierName("Console"))); | ||||
| } | ||||
|   | ||||
| @@ -6,139 +6,138 @@ using SixLabors.ImageSharp.Processing; | ||||
| using SixLabors.ImageSharp.Processing.Processors.Transforms; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// Represents a renderable image. | ||||
| /// </summary> | ||||
| public sealed class CanvasImage : Renderable | ||||
| { | ||||
|     private static readonly IResampler _defaultResampler = KnownResamplers.Bicubic; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Represents a renderable image. | ||||
|     /// Gets the image width. | ||||
|     /// </summary> | ||||
|     public sealed class CanvasImage : Renderable | ||||
|     public int Width => Image.Width; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets the image height. | ||||
|     /// </summary> | ||||
|     public int Height => Image.Height; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the render width of the canvas. | ||||
|     /// </summary> | ||||
|     public int? MaxWidth { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the render width of the canvas. | ||||
|     /// </summary> | ||||
|     public int PixelWidth { get; set; } = 2; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the <see cref="IResampler"/> that should | ||||
|     /// be used when scaling the image. Defaults to bicubic sampling. | ||||
|     /// </summary> | ||||
|     public IResampler? Resampler { get; set; } | ||||
|  | ||||
|     internal SixLabors.ImageSharp.Image<Rgba32> Image { get; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Initializes a new instance of the <see cref="CanvasImage"/> class. | ||||
|     /// </summary> | ||||
|     /// <param name="filename">The image filename.</param> | ||||
|     public CanvasImage(string filename) | ||||
|     { | ||||
|         private static readonly IResampler _defaultResampler = KnownResamplers.Bicubic; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the image width. | ||||
|         /// </summary> | ||||
|         public int Width => Image.Width; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the image height. | ||||
|         /// </summary> | ||||
|         public int Height => Image.Height; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the render width of the canvas. | ||||
|         /// </summary> | ||||
|         public int? MaxWidth { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the render width of the canvas. | ||||
|         /// </summary> | ||||
|         public int PixelWidth { get; set; } = 2; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the <see cref="IResampler"/> that should | ||||
|         /// be used when scaling the image. Defaults to bicubic sampling. | ||||
|         /// </summary> | ||||
|         public IResampler? Resampler { get; set; } | ||||
|  | ||||
|         internal SixLabors.ImageSharp.Image<Rgba32> Image { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="CanvasImage"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="filename">The image filename.</param> | ||||
|         public CanvasImage(string filename) | ||||
|         { | ||||
|             Image = SixLabors.ImageSharp.Image.Load<Rgba32>(filename); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="CanvasImage"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="data">Buffer containing an image.</param> | ||||
|         public CanvasImage(ReadOnlySpan<byte> data) | ||||
|         { | ||||
|             Image = SixLabors.ImageSharp.Image.Load<Rgba32>(data); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="CanvasImage"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="data">Stream containing an image.</param> | ||||
|         public CanvasImage(Stream data) | ||||
|         { | ||||
|             Image = SixLabors.ImageSharp.Image.Load<Rgba32>(data); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override Measurement Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             if (PixelWidth < 0) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Pixel width must be greater than zero."); | ||||
|             } | ||||
|  | ||||
|             var width = MaxWidth ?? Width; | ||||
|             if (maxWidth < width * PixelWidth) | ||||
|             { | ||||
|                 return new Measurement(maxWidth, maxWidth); | ||||
|             } | ||||
|  | ||||
|             return new Measurement(width * PixelWidth, width * PixelWidth); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             var image = Image; | ||||
|  | ||||
|             var width = Width; | ||||
|             var height = Height; | ||||
|  | ||||
|             // Got a max width? | ||||
|             if (MaxWidth != null) | ||||
|             { | ||||
|                 height = (int)(height * ((float)MaxWidth.Value) / Width); | ||||
|                 width = MaxWidth.Value; | ||||
|             } | ||||
|  | ||||
|             // Exceed the max width when we take pixel width into account? | ||||
|             if (width * PixelWidth > maxWidth) | ||||
|             { | ||||
|                 height = (int)(height * (maxWidth / (float)(width * PixelWidth))); | ||||
|                 width = maxWidth / PixelWidth; | ||||
|             } | ||||
|  | ||||
|             // Need to rescale the pixel buffer? | ||||
|             if (width != Width || height != Height) | ||||
|             { | ||||
|                 var resampler = Resampler ?? _defaultResampler; | ||||
|                 image = image.Clone(); // Clone the original image | ||||
|                 image.Mutate(i => i.Resize(width, height, resampler)); | ||||
|             } | ||||
|  | ||||
|             var canvas = new Canvas(width, height) | ||||
|             { | ||||
|                 MaxWidth = MaxWidth, | ||||
|                 PixelWidth = PixelWidth, | ||||
|                 Scale = false, | ||||
|             }; | ||||
|  | ||||
|             for (var y = 0; y < image.Height; y++) | ||||
|             { | ||||
|                 for (var x = 0; x < image.Width; x++) | ||||
|                 { | ||||
|                     if (image[x, y].A == 0) | ||||
|                     { | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     canvas.SetPixel(x, y, new Color( | ||||
|                         image[x, y].R, image[x, y].G, image[x, y].B)); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return ((IRenderable)canvas).Render(context, maxWidth); | ||||
|         } | ||||
|         Image = SixLabors.ImageSharp.Image.Load<Rgba32>(filename); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Initializes a new instance of the <see cref="CanvasImage"/> class. | ||||
|     /// </summary> | ||||
|     /// <param name="data">Buffer containing an image.</param> | ||||
|     public CanvasImage(ReadOnlySpan<byte> data) | ||||
|     { | ||||
|         Image = SixLabors.ImageSharp.Image.Load<Rgba32>(data); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Initializes a new instance of the <see cref="CanvasImage"/> class. | ||||
|     /// </summary> | ||||
|     /// <param name="data">Stream containing an image.</param> | ||||
|     public CanvasImage(Stream data) | ||||
|     { | ||||
|         Image = SixLabors.ImageSharp.Image.Load<Rgba32>(data); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     protected override Measurement Measure(RenderContext context, int maxWidth) | ||||
|     { | ||||
|         if (PixelWidth < 0) | ||||
|         { | ||||
|             throw new InvalidOperationException("Pixel width must be greater than zero."); | ||||
|         } | ||||
|  | ||||
|         var width = MaxWidth ?? Width; | ||||
|         if (maxWidth < width * PixelWidth) | ||||
|         { | ||||
|             return new Measurement(maxWidth, maxWidth); | ||||
|         } | ||||
|  | ||||
|         return new Measurement(width * PixelWidth, width * PixelWidth); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth) | ||||
|     { | ||||
|         var image = Image; | ||||
|  | ||||
|         var width = Width; | ||||
|         var height = Height; | ||||
|  | ||||
|         // Got a max width? | ||||
|         if (MaxWidth != null) | ||||
|         { | ||||
|             height = (int)(height * ((float)MaxWidth.Value) / Width); | ||||
|             width = MaxWidth.Value; | ||||
|         } | ||||
|  | ||||
|         // Exceed the max width when we take pixel width into account? | ||||
|         if (width * PixelWidth > maxWidth) | ||||
|         { | ||||
|             height = (int)(height * (maxWidth / (float)(width * PixelWidth))); | ||||
|             width = maxWidth / PixelWidth; | ||||
|         } | ||||
|  | ||||
|         // Need to rescale the pixel buffer? | ||||
|         if (width != Width || height != Height) | ||||
|         { | ||||
|             var resampler = Resampler ?? _defaultResampler; | ||||
|             image = image.Clone(); // Clone the original image | ||||
|             image.Mutate(i => i.Resize(width, height, resampler)); | ||||
|         } | ||||
|  | ||||
|         var canvas = new Canvas(width, height) | ||||
|         { | ||||
|             MaxWidth = MaxWidth, | ||||
|             PixelWidth = PixelWidth, | ||||
|             Scale = false, | ||||
|         }; | ||||
|  | ||||
|         for (var y = 0; y < image.Height; y++) | ||||
|         { | ||||
|             for (var x = 0; x < image.Width; x++) | ||||
|             { | ||||
|                 if (image[x, y].A == 0) | ||||
|                 { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 canvas.SetPixel(x, y, new Color( | ||||
|                     image[x, y].R, image[x, y].G, image[x, y].B)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return ((IRenderable)canvas).Render(context, maxWidth); | ||||
|     } | ||||
| } | ||||
| @@ -1,135 +1,134 @@ | ||||
| using System; | ||||
| using SixLabors.ImageSharp.Processing; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// Contains extension methods for <see cref="CanvasImage"/>. | ||||
| /// </summary> | ||||
| public static class CanvasImageExtensions | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="CanvasImage"/>. | ||||
|     /// Sets the maximum width of the rendered image. | ||||
|     /// </summary> | ||||
|     public static class CanvasImageExtensions | ||||
|     /// <param name="image">The canvas image.</param> | ||||
|     /// <param name="maxWidth">The maximum width.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static CanvasImage MaxWidth(this CanvasImage image, int? maxWidth) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Sets the maximum width of the rendered image. | ||||
|         /// </summary> | ||||
|         /// <param name="image">The canvas image.</param> | ||||
|         /// <param name="maxWidth">The maximum width.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static CanvasImage MaxWidth(this CanvasImage image, int? maxWidth) | ||||
|         if (image is null) | ||||
|         { | ||||
|             if (image is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(image)); | ||||
|             } | ||||
|  | ||||
|             image.MaxWidth = maxWidth; | ||||
|             return image; | ||||
|             throw new ArgumentNullException(nameof(image)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Disables the maximum width of the rendered image. | ||||
|         /// </summary> | ||||
|         /// <param name="image">The canvas image.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static CanvasImage NoMaxWidth(this CanvasImage image) | ||||
|         { | ||||
|             if (image is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(image)); | ||||
|             } | ||||
|  | ||||
|             image.MaxWidth = null; | ||||
|             return image; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets the pixel width. | ||||
|         /// </summary> | ||||
|         /// <param name="image">The canvas image.</param> | ||||
|         /// <param name="width">The pixel width.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static CanvasImage PixelWidth(this CanvasImage image, int width) | ||||
|         { | ||||
|             if (image is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(image)); | ||||
|             } | ||||
|  | ||||
|             image.PixelWidth = width; | ||||
|             return image; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Mutates the underlying image. | ||||
|         /// </summary> | ||||
|         /// <param name="image">The canvas image.</param> | ||||
|         /// <param name="action">The action that mutates the underlying image.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static CanvasImage Mutate(this CanvasImage image, Action<IImageProcessingContext> action) | ||||
|         { | ||||
|             if (image is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(image)); | ||||
|             } | ||||
|  | ||||
|             if (action is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(action)); | ||||
|             } | ||||
|  | ||||
|             image.Image.Mutate(action); | ||||
|             return image; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Uses a bicubic sampler that implements the bicubic kernel algorithm W(x). | ||||
|         /// </summary> | ||||
|         /// <param name="image">The canvas image.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static CanvasImage BicubicResampler(this CanvasImage image) | ||||
|         { | ||||
|             if (image is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(image)); | ||||
|             } | ||||
|  | ||||
|             image.Resampler = KnownResamplers.Bicubic; | ||||
|             return image; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Uses a bilinear sampler. This interpolation algorithm | ||||
|         /// can be used where perfect image transformation with pixel matching is impossible, | ||||
|         /// so that one can calculate and assign appropriate intensity values to pixels. | ||||
|         /// </summary> | ||||
|         /// <param name="image">The canvas image.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static CanvasImage BilinearResampler(this CanvasImage image) | ||||
|         { | ||||
|             if (image is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(image)); | ||||
|             } | ||||
|  | ||||
|             image.Resampler = KnownResamplers.Triangle; | ||||
|             return image; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Uses a Nearest-Neighbour sampler that implements the nearest neighbor algorithm. | ||||
|         /// This uses a very fast, unscaled filter which will select the closest pixel to | ||||
|         /// the new pixels position. | ||||
|         /// </summary> | ||||
|         /// <param name="image">The canvas image.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static CanvasImage NearestNeighborResampler(this CanvasImage image) | ||||
|         { | ||||
|             if (image is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(image)); | ||||
|             } | ||||
|  | ||||
|             image.Resampler = KnownResamplers.NearestNeighbor; | ||||
|             return image; | ||||
|         } | ||||
|         image.MaxWidth = maxWidth; | ||||
|         return image; | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Disables the maximum width of the rendered image. | ||||
|     /// </summary> | ||||
|     /// <param name="image">The canvas image.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static CanvasImage NoMaxWidth(this CanvasImage image) | ||||
|     { | ||||
|         if (image is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(image)); | ||||
|         } | ||||
|  | ||||
|         image.MaxWidth = null; | ||||
|         return image; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Sets the pixel width. | ||||
|     /// </summary> | ||||
|     /// <param name="image">The canvas image.</param> | ||||
|     /// <param name="width">The pixel width.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static CanvasImage PixelWidth(this CanvasImage image, int width) | ||||
|     { | ||||
|         if (image is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(image)); | ||||
|         } | ||||
|  | ||||
|         image.PixelWidth = width; | ||||
|         return image; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Mutates the underlying image. | ||||
|     /// </summary> | ||||
|     /// <param name="image">The canvas image.</param> | ||||
|     /// <param name="action">The action that mutates the underlying image.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static CanvasImage Mutate(this CanvasImage image, Action<IImageProcessingContext> action) | ||||
|     { | ||||
|         if (image is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(image)); | ||||
|         } | ||||
|  | ||||
|         if (action is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(action)); | ||||
|         } | ||||
|  | ||||
|         image.Image.Mutate(action); | ||||
|         return image; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Uses a bicubic sampler that implements the bicubic kernel algorithm W(x). | ||||
|     /// </summary> | ||||
|     /// <param name="image">The canvas image.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static CanvasImage BicubicResampler(this CanvasImage image) | ||||
|     { | ||||
|         if (image is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(image)); | ||||
|         } | ||||
|  | ||||
|         image.Resampler = KnownResamplers.Bicubic; | ||||
|         return image; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Uses a bilinear sampler. This interpolation algorithm | ||||
|     /// can be used where perfect image transformation with pixel matching is impossible, | ||||
|     /// so that one can calculate and assign appropriate intensity values to pixels. | ||||
|     /// </summary> | ||||
|     /// <param name="image">The canvas image.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static CanvasImage BilinearResampler(this CanvasImage image) | ||||
|     { | ||||
|         if (image is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(image)); | ||||
|         } | ||||
|  | ||||
|         image.Resampler = KnownResamplers.Triangle; | ||||
|         return image; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Uses a Nearest-Neighbour sampler that implements the nearest neighbor algorithm. | ||||
|     /// This uses a very fast, unscaled filter which will select the closest pixel to | ||||
|     /// the new pixels position. | ||||
|     /// </summary> | ||||
|     /// <param name="image">The canvas image.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static CanvasImage NearestNeighborResampler(this CanvasImage image) | ||||
|     { | ||||
|         if (image is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(image)); | ||||
|         } | ||||
|  | ||||
|         image.Resampler = KnownResamplers.NearestNeighbor; | ||||
|         return image; | ||||
|     } | ||||
| } | ||||
| @@ -1,28 +1,27 @@ | ||||
| using System; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| /// <summary> | ||||
| /// A <see cref="ICommandInterceptor"/> that triggers a callback when invoked. | ||||
| /// </summary> | ||||
| public sealed class CallbackCommandInterceptor : ICommandInterceptor | ||||
| { | ||||
|     private readonly Action<CommandContext, CommandSettings> _callback; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// A <see cref="ICommandInterceptor"/> that triggers a callback when invoked. | ||||
|     /// Initializes a new instance of the <see cref="CallbackCommandInterceptor"/> class. | ||||
|     /// </summary> | ||||
|     public sealed class CallbackCommandInterceptor : ICommandInterceptor | ||||
|     /// <param name="callback">The callback to call when the interceptor is invoked.</param> | ||||
|     public CallbackCommandInterceptor(Action<CommandContext, CommandSettings> callback) | ||||
|     { | ||||
|         private readonly Action<CommandContext, CommandSettings> _callback; | ||||
|         _callback = callback ?? throw new ArgumentNullException(nameof(callback)); | ||||
|     } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="CallbackCommandInterceptor"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="callback">The callback to call when the interceptor is invoked.</param> | ||||
|         public CallbackCommandInterceptor(Action<CommandContext, CommandSettings> callback) | ||||
|         { | ||||
|             _callback = callback ?? throw new ArgumentNullException(nameof(callback)); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public void Intercept(CommandContext context, CommandSettings settings) | ||||
|         { | ||||
|             _callback(context, settings); | ||||
|         } | ||||
|     /// <inheritdoc/> | ||||
|     public void Intercept(CommandContext context, CommandSettings settings) | ||||
|     { | ||||
|         _callback(context, settings); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,29 +1,28 @@ | ||||
| using System; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| /// <summary> | ||||
| /// Represents a <see cref="CommandApp"/> runtime failure. | ||||
| /// </summary> | ||||
| public sealed class CommandAppFailure | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a <see cref="CommandApp"/> runtime failure. | ||||
|     /// Gets the exception that was thrown. | ||||
|     /// </summary> | ||||
|     public sealed class CommandAppFailure | ||||
|     public Exception Exception { get; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets the console output. | ||||
|     /// </summary> | ||||
|     public string Output { get; } | ||||
|  | ||||
|     internal CommandAppFailure(Exception exception, string output) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the exception that was thrown. | ||||
|         /// </summary> | ||||
|         public Exception Exception { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the console output. | ||||
|         /// </summary> | ||||
|         public string Output { get; } | ||||
|  | ||||
|         internal CommandAppFailure(Exception exception, string output) | ||||
|         { | ||||
|             Exception = exception ?? throw new ArgumentNullException(nameof(exception)); | ||||
|             Output = output.NormalizeLineEndings() | ||||
|                 .TrimLines() | ||||
|                 .Trim(); | ||||
|         } | ||||
|         Exception = exception ?? throw new ArgumentNullException(nameof(exception)); | ||||
|         Output = output.NormalizeLineEndings() | ||||
|             .TrimLines() | ||||
|             .Trim(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,43 +1,42 @@ | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| /// <summary> | ||||
| /// Represents the result of a completed <see cref="CommandApp"/> run. | ||||
| /// </summary> | ||||
| public sealed class CommandAppResult | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents the result of a completed <see cref="CommandApp"/> run. | ||||
|     /// Gets the exit code. | ||||
|     /// </summary> | ||||
|     public sealed class CommandAppResult | ||||
|     public int ExitCode { get; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets the console output. | ||||
|     /// </summary> | ||||
|     public string Output { get; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets the command context. | ||||
|     /// </summary> | ||||
|     public CommandContext? Context { get; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets the command settings. | ||||
|     /// </summary> | ||||
|     public CommandSettings? Settings { get; } | ||||
|  | ||||
|     internal CommandAppResult(int exitCode, string output, CommandContext? context, CommandSettings? settings) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the exit code. | ||||
|         /// </summary> | ||||
|         public int ExitCode { get; } | ||||
|         ExitCode = exitCode; | ||||
|         Output = output ?? string.Empty; | ||||
|         Context = context; | ||||
|         Settings = settings; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the console output. | ||||
|         /// </summary> | ||||
|         public string Output { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the command context. | ||||
|         /// </summary> | ||||
|         public CommandContext? Context { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the command settings. | ||||
|         /// </summary> | ||||
|         public CommandSettings? Settings { get; } | ||||
|  | ||||
|         internal CommandAppResult(int exitCode, string output, CommandContext? context, CommandSettings? settings) | ||||
|         { | ||||
|             ExitCode = exitCode; | ||||
|             Output = output ?? string.Empty; | ||||
|             Context = context; | ||||
|             Settings = settings; | ||||
|  | ||||
|             Output = Output | ||||
|                 .NormalizeLineEndings() | ||||
|                 .TrimLines() | ||||
|                 .Trim(); | ||||
|         } | ||||
|         Output = Output | ||||
|             .NormalizeLineEndings() | ||||
|             .TrimLines() | ||||
|             .Trim(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,135 +1,134 @@ | ||||
| using System; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| /// <summary> | ||||
| /// A <see cref="CommandApp"/> test harness. | ||||
| /// </summary> | ||||
| public sealed class CommandAppTester | ||||
| { | ||||
|     private Action<CommandApp>? _appConfiguration; | ||||
|     private Action<IConfigurator>? _configuration; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// A <see cref="CommandApp"/> test harness. | ||||
|     /// Initializes a new instance of the <see cref="CommandAppTester"/> class. | ||||
|     /// </summary> | ||||
|     public sealed class CommandAppTester | ||||
|     /// <param name="registrar">The registrar.</param> | ||||
|     public CommandAppTester(ITypeRegistrar? registrar = null) | ||||
|     { | ||||
|         private Action<CommandApp>? _appConfiguration; | ||||
|         private Action<IConfigurator>? _configuration; | ||||
|         Registrar = registrar; | ||||
|     } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="CommandAppTester"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="registrar">The registrar.</param> | ||||
|         public CommandAppTester(ITypeRegistrar? registrar = null) | ||||
|     /// <summary> | ||||
|     /// Gets or sets the Registrar to use in the CommandApp. | ||||
|     /// </summary> | ||||
|     public ITypeRegistrar? Registrar { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Sets the default command. | ||||
|     /// </summary> | ||||
|     /// <typeparam name="T">The default command type.</typeparam> | ||||
|     public void SetDefaultCommand<T>() | ||||
|         where T : class, ICommand | ||||
|     { | ||||
|         _appConfiguration = (app) => app.SetDefaultCommand<T>(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Configures the command application. | ||||
|     /// </summary> | ||||
|     /// <param name="action">The configuration action.</param> | ||||
|     public void Configure(Action<IConfigurator> action) | ||||
|     { | ||||
|         if (_configuration != null) | ||||
|         { | ||||
|             Registrar = registrar; | ||||
|             throw new InvalidOperationException("The command app harnest have already been configured."); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the Registrar to use in the CommandApp. | ||||
|         /// </summary> | ||||
|         public ITypeRegistrar? Registrar { get; set; } | ||||
|         _configuration = action; | ||||
|     } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets the default command. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">The default command type.</typeparam> | ||||
|         public void SetDefaultCommand<T>() | ||||
|             where T : class, ICommand | ||||
|     /// <summary> | ||||
|     /// Runs the command application and expects an exception of a specific type to be thrown. | ||||
|     /// </summary> | ||||
|     /// <typeparam name="T">The expected exception type.</typeparam> | ||||
|     /// <param name="args">The arguments.</param> | ||||
|     /// <returns>The information about the failure.</returns> | ||||
|     public CommandAppFailure RunAndCatch<T>(params string[] args) | ||||
|         where T : Exception | ||||
|     { | ||||
|         var console = new TestConsole().Width(int.MaxValue); | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             _appConfiguration = (app) => app.SetDefaultCommand<T>(); | ||||
|             Run(args, console, c => c.PropagateExceptions()); | ||||
|             throw new InvalidOperationException("Expected an exception to be thrown, but there was none."); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Configures the command application. | ||||
|         /// </summary> | ||||
|         /// <param name="action">The configuration action.</param> | ||||
|         public void Configure(Action<IConfigurator> action) | ||||
|         catch (T ex) | ||||
|         { | ||||
|             if (_configuration != null) | ||||
|             if (ex is CommandAppException commandAppException && commandAppException.Pretty != null) | ||||
|             { | ||||
|                 throw new InvalidOperationException("The command app harnest have already been configured."); | ||||
|                 console.Write(commandAppException.Pretty); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 console.WriteLine(ex.Message); | ||||
|             } | ||||
|  | ||||
|             _configuration = action; | ||||
|             return new CommandAppFailure(ex, console.Output); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Runs the command application and expects an exception of a specific type to be thrown. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">The expected exception type.</typeparam> | ||||
|         /// <param name="args">The arguments.</param> | ||||
|         /// <returns>The information about the failure.</returns> | ||||
|         public CommandAppFailure RunAndCatch<T>(params string[] args) | ||||
|             where T : Exception | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             var console = new TestConsole().Width(int.MaxValue); | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 Run(args, console, c => c.PropagateExceptions()); | ||||
|                 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}."); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Runs the command application. | ||||
|         /// </summary> | ||||
|         /// <param name="args">The arguments.</param> | ||||
|         /// <returns>The result.</returns> | ||||
|         public CommandAppResult Run(params string[] args) | ||||
|         { | ||||
|             var console = new TestConsole().Width(int.MaxValue); | ||||
|             return Run(args, console); | ||||
|         } | ||||
|  | ||||
|         private CommandAppResult Run(string[] args, TestConsole console, Action<IConfigurator>? 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() | ||||
|                 .TrimLines() | ||||
|                 .Trim(); | ||||
|  | ||||
|             return new CommandAppResult(result, output, context, settings); | ||||
|             throw new InvalidOperationException( | ||||
|                 $"Expected an exception of type '{typeof(T).FullName}' to be thrown, " | ||||
|                 + $"but received {ex.GetType().FullName}."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Runs the command application. | ||||
|     /// </summary> | ||||
|     /// <param name="args">The arguments.</param> | ||||
|     /// <returns>The result.</returns> | ||||
|     public CommandAppResult Run(params string[] args) | ||||
|     { | ||||
|         var console = new TestConsole().Width(int.MaxValue); | ||||
|         return Run(args, console); | ||||
|     } | ||||
|  | ||||
|     private CommandAppResult Run(string[] args, TestConsole console, Action<IConfigurator>? 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() | ||||
|             .TrimLines() | ||||
|             .Trim(); | ||||
|  | ||||
|         return new CommandAppResult(result, output, context, settings); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,191 +1,190 @@ | ||||
| using System; | ||||
| using Spectre.Console.Cli; | ||||
|  | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| /// <summary> | ||||
| /// This is a utility class for implementors of | ||||
| /// <see cref="ITypeRegistrar"/> and corresponding <see cref="ITypeResolver"/>. | ||||
| /// </summary> | ||||
| public sealed class TypeRegistrarBaseTests | ||||
| { | ||||
|     private readonly Func<ITypeRegistrar> _registrarFactory; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// This is a utility class for implementors of | ||||
|     /// <see cref="ITypeRegistrar"/> and corresponding <see cref="ITypeResolver"/>. | ||||
|     /// Initializes a new instance of the <see cref="TypeRegistrarBaseTests"/> class. | ||||
|     /// </summary> | ||||
|     public sealed class TypeRegistrarBaseTests | ||||
|     /// <param name="registrarFactory">The factory to create a new, clean <see cref="ITypeRegistrar"/> to be used for each test.</param> | ||||
|     public TypeRegistrarBaseTests(Func<ITypeRegistrar> registrarFactory) | ||||
|     { | ||||
|         private readonly Func<ITypeRegistrar> _registrarFactory; | ||||
|         _registrarFactory = registrarFactory; | ||||
|     } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="TypeRegistrarBaseTests"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="registrarFactory">The factory to create a new, clean <see cref="ITypeRegistrar"/> to be used for each test.</param> | ||||
|         public TypeRegistrarBaseTests(Func<ITypeRegistrar> registrarFactory) | ||||
|     /// <summary> | ||||
|     /// Runs all tests. | ||||
|     /// </summary> | ||||
|     /// <exception cref="TestFailedException">This exception is raised, if a test fails.</exception> | ||||
|     public void RunAllTests() | ||||
|     { | ||||
|         var testCases = new Action<ITypeRegistrar>[] | ||||
|         { | ||||
|             _registrarFactory = registrarFactory; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Runs all tests. | ||||
|         /// </summary> | ||||
|         /// <exception cref="TestFailedException">This exception is raised, if a test fails.</exception> | ||||
|         public void RunAllTests() | ||||
|         { | ||||
|             var testCases = new Action<ITypeRegistrar>[] | ||||
|             { | ||||
|                 RegistrationsCanBeResolved, | ||||
|                 InstanceRegistrationsCanBeResolved, | ||||
|                 LazyRegistrationsCanBeResolved, | ||||
|                 ResolvingNotRegisteredServiceReturnsNull, | ||||
|                 ResolvingNullTypeReturnsNull, | ||||
|             }; | ||||
|         }; | ||||
|  | ||||
|             foreach (var test in testCases) | ||||
|             { | ||||
|                 test(_registrarFactory()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private static void ResolvingNullTypeReturnsNull(ITypeRegistrar registrar) | ||||
|         foreach (var test in testCases) | ||||
|         { | ||||
|             // 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."); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// internal use only. | ||||
|         /// </summary> | ||||
|         private interface IMockService | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         private class MockService : IMockService | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Exception, to be raised when a test fails. | ||||
|         /// </summary> | ||||
|         public sealed class TestFailedException : Exception | ||||
|         { | ||||
|             /// <inheritdoc cref="Exception" /> | ||||
|             public TestFailedException(string message) | ||||
|                 : base(message) | ||||
|             { | ||||
|             } | ||||
|  | ||||
|             /// <inheritdoc cref="Exception" /> | ||||
|             public TestFailedException(string message, Exception inner) | ||||
|                 : base(message, inner) | ||||
|             { | ||||
|             } | ||||
|             test(_registrarFactory()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|     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."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// internal use only. | ||||
|     /// </summary> | ||||
|     private interface IMockService | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     private class MockService : IMockService | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Exception, to be raised when a test fails. | ||||
|     /// </summary> | ||||
|     public sealed class TestFailedException : Exception | ||||
|     { | ||||
|         /// <inheritdoc cref="Exception" /> | ||||
|         public TestFailedException(string message) | ||||
|             : base(message) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc cref="Exception" /> | ||||
|         public TestFailedException(string message, Exception inner) | ||||
|             : base(message, inner) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,47 +1,46 @@ | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| /// <summary> | ||||
| /// Contains extensions for <see cref="string"/>. | ||||
| /// </summary> | ||||
| public static class StringExtensions | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extensions for <see cref="string"/>. | ||||
|     /// Returns a new string with all lines trimmed of trailing whitespace. | ||||
|     /// </summary> | ||||
|     public static class StringExtensions | ||||
|     /// <param name="value">The string to trim.</param> | ||||
|     /// <returns>A new string with all lines trimmed of trailing whitespace.</returns> | ||||
|     public static string TrimLines(this string value) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Returns a new string with all lines trimmed of trailing whitespace. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The string to trim.</param> | ||||
|         /// <returns>A new string with all lines trimmed of trailing whitespace.</returns> | ||||
|         public static string TrimLines(this string value) | ||||
|         if (value is null) | ||||
|         { | ||||
|             if (value is null) | ||||
|             { | ||||
|                 return string.Empty; | ||||
|             } | ||||
|  | ||||
|             var result = new List<string>(); | ||||
|             foreach (var line in value.NormalizeLineEndings().Split(new[] { '\n' })) | ||||
|             { | ||||
|                 result.Add(line.TrimEnd()); | ||||
|             } | ||||
|  | ||||
|             return string.Join("\n", result); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Returns a new string with normalized line endings. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The string to normalize line endings for.</param> | ||||
|         /// <returns>A new string with normalized line endings.</returns> | ||||
|         public static string NormalizeLineEndings(this string value) | ||||
|         { | ||||
|             if (value != null) | ||||
|             { | ||||
|                 value = value.Replace("\r\n", "\n"); | ||||
|                 return value.Replace("\r", string.Empty); | ||||
|             } | ||||
|  | ||||
|             return string.Empty; | ||||
|         } | ||||
|  | ||||
|         var result = new List<string>(); | ||||
|         foreach (var line in value.NormalizeLineEndings().Split(new[] { '\n' })) | ||||
|         { | ||||
|             result.Add(line.TrimEnd()); | ||||
|         } | ||||
|  | ||||
|         return string.Join("\n", result); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Returns a new string with normalized line endings. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The string to normalize line endings for.</param> | ||||
|     /// <returns>A new string with normalized line endings.</returns> | ||||
|     public static string NormalizeLineEndings(this string value) | ||||
|     { | ||||
|         if (value != null) | ||||
|         { | ||||
|             value = value.Replace("\r\n", "\n"); | ||||
|             return value.Replace("\r", string.Empty); | ||||
|         } | ||||
|  | ||||
|         return string.Empty; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,25 +1,24 @@ | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| /// <summary> | ||||
| /// Contains extensions for <see cref="Style"/>. | ||||
| /// </summary> | ||||
| public static class StyleExtensions | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extensions for <see cref="Style"/>. | ||||
|     /// Sets the foreground or background color of the specified style. | ||||
|     /// </summary> | ||||
|     public static class StyleExtensions | ||||
|     /// <param name="style">The style.</param> | ||||
|     /// <param name="color">The color.</param> | ||||
|     /// <param name="foreground">Whether or not to set the foreground color.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static Style SetColor(this Style style, Color color, bool foreground) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Sets the foreground or background color of the specified style. | ||||
|         /// </summary> | ||||
|         /// <param name="style">The style.</param> | ||||
|         /// <param name="color">The color.</param> | ||||
|         /// <param name="foreground">Whether or not to set the foreground color.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static Style SetColor(this Style style, Color color, bool foreground) | ||||
|         if (foreground) | ||||
|         { | ||||
|             if (foreground) | ||||
|             { | ||||
|                 return style.Foreground(color); | ||||
|             } | ||||
|  | ||||
|             return style.Background(color); | ||||
|             return style.Foreground(color); | ||||
|         } | ||||
|  | ||||
|         return style.Background(color); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,17 +1,16 @@ | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| internal sealed class NoopCursor : IAnsiConsoleCursor | ||||
| { | ||||
|     internal sealed class NoopCursor : IAnsiConsoleCursor | ||||
|     public void Move(CursorDirection direction, int steps) | ||||
|     { | ||||
|         public void Move(CursorDirection direction, int steps) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         public void SetPosition(int column, int line) | ||||
|         { | ||||
|         } | ||||
|     public void SetPosition(int column, int line) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|         public void Show(bool show) | ||||
|         { | ||||
|         } | ||||
|     public void Show(bool show) | ||||
|     { | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,18 +1,17 @@ | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace Spectre.Console.Testing | ||||
| { | ||||
|     internal sealed class NoopExclusivityMode : IExclusivityMode | ||||
|     { | ||||
|         public T Run<T>(Func<T> func) | ||||
|         { | ||||
|             return func(); | ||||
|         } | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
|         public async Task<T> RunAsync<T>(Func<Task<T>> func) | ||||
|         { | ||||
|             return await func().ConfigureAwait(false); | ||||
|         } | ||||
| internal sealed class NoopExclusivityMode : IExclusivityMode | ||||
| { | ||||
|     public T Run<T>(Func<T> func) | ||||
|     { | ||||
|         return func(); | ||||
|     } | ||||
|  | ||||
|     public async Task<T> RunAsync<T>(Func<Task<T>> func) | ||||
|     { | ||||
|         return await func().ConfigureAwait(false); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,40 +1,39 @@ | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| /// <summary> | ||||
| /// Represents fake capabilities useful in tests. | ||||
| /// </summary> | ||||
| public sealed class TestCapabilities : IReadOnlyCapabilities | ||||
| { | ||||
|     /// <inheritdoc/> | ||||
|     public ColorSystem ColorSystem { get; set; } = ColorSystem.TrueColor; | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public bool Ansi { get; set; } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public bool Links { get; set; } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public bool Legacy { get; set; } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public bool IsTerminal { get; set; } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public bool Interactive { get; set; } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public bool Unicode { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Represents fake capabilities useful in tests. | ||||
|     /// Creates a <see cref="RenderContext"/> with the same capabilities as this instace. | ||||
|     /// </summary> | ||||
|     public sealed class TestCapabilities : IReadOnlyCapabilities | ||||
|     /// <returns>A <see cref="RenderContext"/> with the same capabilities as this instace.</returns> | ||||
|     public RenderContext CreateRenderContext() | ||||
|     { | ||||
|         /// <inheritdoc/> | ||||
|         public ColorSystem ColorSystem { get; set; } = ColorSystem.TrueColor; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool Ansi { get; set; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool Links { get; set; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool Legacy { get; set; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool IsTerminal { get; set; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool Interactive { get; set; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool Unicode { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a <see cref="RenderContext"/> with the same capabilities as this instace. | ||||
|         /// </summary> | ||||
|         /// <returns>A <see cref="RenderContext"/> with the same capabilities as this instace.</returns> | ||||
|         public RenderContext CreateRenderContext() | ||||
|         { | ||||
|             return new RenderContext(this); | ||||
|         } | ||||
|         return new RenderContext(this); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,120 +3,119 @@ using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| /// <summary> | ||||
| /// A testable console. | ||||
| /// </summary> | ||||
| public sealed class TestConsole : IAnsiConsole, IDisposable | ||||
| { | ||||
|     private readonly IAnsiConsole _console; | ||||
|     private readonly StringWriter _writer; | ||||
|     private IAnsiConsoleCursor? _cursor; | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public Profile Profile => _console.Profile; | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public IExclusivityMode ExclusivityMode => _console.ExclusivityMode; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// A testable console. | ||||
|     /// Gets the console input. | ||||
|     /// </summary> | ||||
|     public sealed class TestConsole : IAnsiConsole, IDisposable | ||||
|     public TestConsoleInput Input { get; } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public RenderPipeline Pipeline => _console.Pipeline; | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public IAnsiConsoleCursor Cursor => _cursor ?? _console.Cursor; | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     IAnsiConsoleInput IAnsiConsole.Input => Input; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets the console output. | ||||
|     /// </summary> | ||||
|     public string Output => _writer.ToString(); | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets the console output lines. | ||||
|     /// </summary> | ||||
|     public IReadOnlyList<string> Lines => Output.NormalizeLineEndings().TrimEnd('\n').Split(new char[] { '\n' }); | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets a value indicating whether or not VT/ANSI sequences | ||||
|     /// should be emitted to the console. | ||||
|     /// </summary> | ||||
|     public bool EmitAnsiSequences { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Initializes a new instance of the <see cref="TestConsole"/> class. | ||||
|     /// </summary> | ||||
|     public TestConsole() | ||||
|     { | ||||
|         private readonly IAnsiConsole _console; | ||||
|         private readonly StringWriter _writer; | ||||
|         private IAnsiConsoleCursor? _cursor; | ||||
|         _writer = new StringWriter(); | ||||
|         _cursor = new NoopCursor(); | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public Profile Profile => _console.Profile; | ||||
|         Input = new TestConsoleInput(); | ||||
|         EmitAnsiSequences = false; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IExclusivityMode ExclusivityMode => _console.ExclusivityMode; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the console input. | ||||
|         /// </summary> | ||||
|         public TestConsoleInput Input { get; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public RenderPipeline Pipeline => _console.Pipeline; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IAnsiConsoleCursor Cursor => _cursor ?? _console.Cursor; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         IAnsiConsoleInput IAnsiConsole.Input => Input; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the console output. | ||||
|         /// </summary> | ||||
|         public string Output => _writer.ToString(); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the console output lines. | ||||
|         /// </summary> | ||||
|         public IReadOnlyList<string> Lines => Output.NormalizeLineEndings().TrimEnd('\n').Split(new char[] { '\n' }); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether or not VT/ANSI sequences | ||||
|         /// should be emitted to the console. | ||||
|         /// </summary> | ||||
|         public bool EmitAnsiSequences { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="TestConsole"/> class. | ||||
|         /// </summary> | ||||
|         public TestConsole() | ||||
|         var factory = new AnsiConsoleFactory(); | ||||
|         _console = factory.Create(new AnsiConsoleSettings | ||||
|         { | ||||
|             _writer = new StringWriter(); | ||||
|             _cursor = new NoopCursor(); | ||||
|  | ||||
|             Input = new TestConsoleInput(); | ||||
|             EmitAnsiSequences = false; | ||||
|  | ||||
|             var factory = new AnsiConsoleFactory(); | ||||
|             _console = factory.Create(new AnsiConsoleSettings | ||||
|             Ansi = AnsiSupport.Yes, | ||||
|             ColorSystem = (ColorSystemSupport)ColorSystem.TrueColor, | ||||
|             Out = new AnsiConsoleOutput(_writer), | ||||
|             Interactive = InteractionSupport.No, | ||||
|             ExclusivityMode = new NoopExclusivityMode(), | ||||
|             Enrichment = new ProfileEnrichment | ||||
|             { | ||||
|                 Ansi = AnsiSupport.Yes, | ||||
|                 ColorSystem = (ColorSystemSupport)ColorSystem.TrueColor, | ||||
|                 Out = new AnsiConsoleOutput(_writer), | ||||
|                 Interactive = InteractionSupport.No, | ||||
|                 ExclusivityMode = new NoopExclusivityMode(), | ||||
|                 Enrichment = new ProfileEnrichment | ||||
|                 UseDefaultEnrichers = false, | ||||
|             }, | ||||
|         }); | ||||
|  | ||||
|         _console.Profile.Width = 80; | ||||
|         _console.Profile.Height = 24; | ||||
|         _console.Profile.Capabilities.Ansi = true; | ||||
|         _console.Profile.Capabilities.Unicode = true; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public void Dispose() | ||||
|     { | ||||
|         _writer.Dispose(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public void Clear(bool home) | ||||
|     { | ||||
|         _console.Clear(home); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public void Write(IRenderable renderable) | ||||
|     { | ||||
|         if (EmitAnsiSequences) | ||||
|         { | ||||
|             _console.Write(renderable); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             foreach (var segment in renderable.GetSegments(this)) | ||||
|             { | ||||
|                 if (segment.IsControlCode) | ||||
|                 { | ||||
|                     UseDefaultEnrichers = false, | ||||
|                 }, | ||||
|             }); | ||||
|  | ||||
|             _console.Profile.Width = 80; | ||||
|             _console.Profile.Height = 24; | ||||
|             _console.Profile.Capabilities.Ansi = true; | ||||
|             _console.Profile.Capabilities.Unicode = true; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public void Dispose() | ||||
|         { | ||||
|             _writer.Dispose(); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public void Clear(bool home) | ||||
|         { | ||||
|             _console.Clear(home); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public void Write(IRenderable renderable) | ||||
|         { | ||||
|             if (EmitAnsiSequences) | ||||
|             { | ||||
|                 _console.Write(renderable); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 foreach (var segment in renderable.GetSegments(this)) | ||||
|                 { | ||||
|                     if (segment.IsControlCode) | ||||
|                     { | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     Profile.Out.Writer.Write(segment.Text); | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         internal void SetCursor(IAnsiConsoleCursor? cursor) | ||||
|         { | ||||
|             _cursor = cursor; | ||||
|                 Profile.Out.Writer.Write(segment.Text); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     internal void SetCursor(IAnsiConsoleCursor? cursor) | ||||
|     { | ||||
|         _cursor = cursor; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,67 +1,66 @@ | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| /// <summary> | ||||
| /// Contains extensions for <see cref="TestConsole"/>. | ||||
| /// </summary> | ||||
| public static class TestConsoleExtensions | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extensions for <see cref="TestConsole"/>. | ||||
|     /// Sets the console's color system. | ||||
|     /// </summary> | ||||
|     public static class TestConsoleExtensions | ||||
|     /// <param name="console">The console.</param> | ||||
|     /// <param name="colors">The color system to use.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static TestConsole Colors(this TestConsole console, ColorSystem colors) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Sets the console's color system. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console.</param> | ||||
|         /// <param name="colors">The color system to use.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static TestConsole Colors(this TestConsole console, ColorSystem colors) | ||||
|         { | ||||
|             console.Profile.Capabilities.ColorSystem = colors; | ||||
|             return console; | ||||
|         } | ||||
|         console.Profile.Capabilities.ColorSystem = colors; | ||||
|         return console; | ||||
|     } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets whether or not ANSI is supported. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console.</param> | ||||
|         /// <param name="enable">Whether or not VT/ANSI control codes are supported.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static TestConsole SupportsAnsi(this TestConsole console, bool enable) | ||||
|         { | ||||
|             console.Profile.Capabilities.Ansi = enable; | ||||
|             return console; | ||||
|         } | ||||
|     /// <summary> | ||||
|     /// Sets whether or not ANSI is supported. | ||||
|     /// </summary> | ||||
|     /// <param name="console">The console.</param> | ||||
|     /// <param name="enable">Whether or not VT/ANSI control codes are supported.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static TestConsole SupportsAnsi(this TestConsole console, bool enable) | ||||
|     { | ||||
|         console.Profile.Capabilities.Ansi = enable; | ||||
|         return console; | ||||
|     } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Makes the console interactive. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static TestConsole Interactive(this TestConsole console) | ||||
|         { | ||||
|             console.Profile.Capabilities.Interactive = true; | ||||
|             return console; | ||||
|         } | ||||
|     /// <summary> | ||||
|     /// Makes the console interactive. | ||||
|     /// </summary> | ||||
|     /// <param name="console">The console.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static TestConsole Interactive(this TestConsole console) | ||||
|     { | ||||
|         console.Profile.Capabilities.Interactive = true; | ||||
|         return console; | ||||
|     } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets the console width. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console.</param> | ||||
|         /// <param name="width">The console width.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static TestConsole Width(this TestConsole console, int width) | ||||
|         { | ||||
|             console.Profile.Width = width; | ||||
|             return console; | ||||
|         } | ||||
|     /// <summary> | ||||
|     /// Sets the console width. | ||||
|     /// </summary> | ||||
|     /// <param name="console">The console.</param> | ||||
|     /// <param name="width">The console width.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static TestConsole Width(this TestConsole console, int width) | ||||
|     { | ||||
|         console.Profile.Width = width; | ||||
|         return console; | ||||
|     } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Turns on emitting of VT/ANSI sequences. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static TestConsole EmitAnsiSequences(this TestConsole console) | ||||
|         { | ||||
|             console.SetCursor(null); | ||||
|             console.EmitAnsiSequences = true; | ||||
|             return console; | ||||
|         } | ||||
|     /// <summary> | ||||
|     /// Turns on emitting of VT/ANSI sequences. | ||||
|     /// </summary> | ||||
|     /// <param name="console">The console.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static TestConsole EmitAnsiSequences(this TestConsole console) | ||||
|     { | ||||
|         console.SetCursor(null); | ||||
|         console.EmitAnsiSequences = true; | ||||
|         return console; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,90 +3,89 @@ using System.Collections.Generic; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace Spectre.Console.Testing | ||||
| namespace Spectre.Console.Testing; | ||||
|  | ||||
| /// <summary> | ||||
| /// Represents a testable console input mechanism. | ||||
| /// </summary> | ||||
| public sealed class TestConsoleInput : IAnsiConsoleInput | ||||
| { | ||||
|     private readonly Queue<ConsoleKeyInfo> _input; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Represents a testable console input mechanism. | ||||
|     /// Initializes a new instance of the <see cref="TestConsoleInput"/> class. | ||||
|     /// </summary> | ||||
|     public sealed class TestConsoleInput : IAnsiConsoleInput | ||||
|     public TestConsoleInput() | ||||
|     { | ||||
|         private readonly Queue<ConsoleKeyInfo> _input; | ||||
|         _input = new Queue<ConsoleKeyInfo>(); | ||||
|     } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="TestConsoleInput"/> class. | ||||
|         /// </summary> | ||||
|         public TestConsoleInput() | ||||
|     /// <summary> | ||||
|     /// Pushes the specified text to the input queue. | ||||
|     /// </summary> | ||||
|     /// <param name="input">The input string.</param> | ||||
|     public void PushText(string input) | ||||
|     { | ||||
|         if (input is null) | ||||
|         { | ||||
|             _input = new Queue<ConsoleKeyInfo>(); | ||||
|             throw new ArgumentNullException(nameof(input)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Pushes the specified text to the input queue. | ||||
|         /// </summary> | ||||
|         /// <param name="input">The input string.</param> | ||||
|         public void PushText(string input) | ||||
|         foreach (var character in input) | ||||
|         { | ||||
|             if (input is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(input)); | ||||
|             } | ||||
|  | ||||
|             foreach (var character in input) | ||||
|             { | ||||
|                 PushCharacter(character); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Pushes the specified text followed by 'Enter' to the input queue. | ||||
|         /// </summary> | ||||
|         /// <param name="input">The input.</param> | ||||
|         public void PushTextWithEnter(string input) | ||||
|         { | ||||
|             PushText(input); | ||||
|             PushKey(ConsoleKey.Enter); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Pushes the specified character to the input queue. | ||||
|         /// </summary> | ||||
|         /// <param name="input">The input.</param> | ||||
|         public void PushCharacter(char input) | ||||
|         { | ||||
|             var control = char.IsUpper(input); | ||||
|             _input.Enqueue(new ConsoleKeyInfo(input, (ConsoleKey)input, false, false, control)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Pushes the specified key to the input queue. | ||||
|         /// </summary> | ||||
|         /// <param name="input">The input.</param> | ||||
|         public void PushKey(ConsoleKey input) | ||||
|         { | ||||
|             _input.Enqueue(new ConsoleKeyInfo((char)input, input, false, false, false)); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool IsKeyAvailable() | ||||
|         { | ||||
|             return _input.Count > 0; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public ConsoleKeyInfo? ReadKey(bool intercept) | ||||
|         { | ||||
|             if (_input.Count == 0) | ||||
|             { | ||||
|                 throw new InvalidOperationException("No input available."); | ||||
|             } | ||||
|  | ||||
|             return _input.Dequeue(); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public Task<ConsoleKeyInfo?> ReadKeyAsync(bool intercept, CancellationToken cancellationToken) | ||||
|         { | ||||
|             return Task.FromResult(ReadKey(intercept)); | ||||
|             PushCharacter(character); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Pushes the specified text followed by 'Enter' to the input queue. | ||||
|     /// </summary> | ||||
|     /// <param name="input">The input.</param> | ||||
|     public void PushTextWithEnter(string input) | ||||
|     { | ||||
|         PushText(input); | ||||
|         PushKey(ConsoleKey.Enter); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Pushes the specified character to the input queue. | ||||
|     /// </summary> | ||||
|     /// <param name="input">The input.</param> | ||||
|     public void PushCharacter(char input) | ||||
|     { | ||||
|         var control = char.IsUpper(input); | ||||
|         _input.Enqueue(new ConsoleKeyInfo(input, (ConsoleKey)input, false, false, control)); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Pushes the specified key to the input queue. | ||||
|     /// </summary> | ||||
|     /// <param name="input">The input.</param> | ||||
|     public void PushKey(ConsoleKey input) | ||||
|     { | ||||
|         _input.Enqueue(new ConsoleKeyInfo((char)input, input, false, false, false)); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public bool IsKeyAvailable() | ||||
|     { | ||||
|         return _input.Count > 0; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public ConsoleKeyInfo? ReadKey(bool intercept) | ||||
|     { | ||||
|         if (_input.Count == 0) | ||||
|         { | ||||
|             throw new InvalidOperationException("No input available."); | ||||
|         } | ||||
|  | ||||
|         return _input.Dequeue(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public Task<ConsoleKeyInfo?> ReadKeyAsync(bool intercept, CancellationToken cancellationToken) | ||||
|     { | ||||
|         return Task.FromResult(ReadKey(intercept)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,30 +1,29 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// Writes an exception to the console. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     /// <param name="exception">The exception to write to the console.</param> | ||||
|     /// <param name="format">The exception format options.</param> | ||||
|     public static void WriteException(Exception exception, ExceptionFormats format = ExceptionFormats.Default) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Writes an exception to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="exception">The exception to write to the console.</param> | ||||
|         /// <param name="format">The exception format options.</param> | ||||
|         public static void WriteException(Exception exception, ExceptionFormats format = ExceptionFormats.Default) | ||||
|         { | ||||
|             Console.WriteException(exception, format); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes an exception to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="exception">The exception to write to the console.</param> | ||||
|         /// <param name="settings">The exception settings.</param> | ||||
|         public static void WriteException(Exception exception, ExceptionSettings settings) | ||||
|         { | ||||
|             Console.WriteException(exception, settings); | ||||
|         } | ||||
|         Console.WriteException(exception, format); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes an exception to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="exception">The exception to write to the console.</param> | ||||
|     /// <param name="settings">The exception settings.</param> | ||||
|     public static void WriteException(Exception exception, ExceptionSettings settings) | ||||
|     { | ||||
|         Console.WriteException(exception, settings); | ||||
|     } | ||||
| } | ||||
| @@ -1,20 +1,19 @@ | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// Creates a new <see cref="LiveDisplay"/> instance. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     /// <param name="target">The target renderable to update.</param> | ||||
|     /// <returns>A <see cref="LiveDisplay"/> instance.</returns> | ||||
|     public static LiveDisplay Live(IRenderable target) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Creates a new <see cref="LiveDisplay"/> instance. | ||||
|         /// </summary> | ||||
|         /// <param name="target">The target renderable to update.</param> | ||||
|         /// <returns>A <see cref="LiveDisplay"/> instance.</returns> | ||||
|         public static LiveDisplay Live(IRenderable target) | ||||
|         { | ||||
|             return Console.Live(target); | ||||
|         } | ||||
|         return Console.Live(target); | ||||
|     } | ||||
| } | ||||
| } | ||||
| @@ -1,70 +1,69 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// Writes the specified markup to the console. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Markup(string value) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Markup(string value) | ||||
|         { | ||||
|             Console.Markup(value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Markup(string format, params object[] args) | ||||
|         { | ||||
|             Console.Markup(format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Markup(IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             Console.Markup(provider, format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void MarkupLine(string value) | ||||
|         { | ||||
|             Console.MarkupLine(value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void MarkupLine(string format, params object[] args) | ||||
|         { | ||||
|             Console.MarkupLine(format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void MarkupLine(IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             Console.MarkupLine(provider, format, args); | ||||
|         } | ||||
|         Console.Markup(value); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified markup to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="format">A composite format string.</param> | ||||
|     /// <param name="args">An array of objects to write.</param> | ||||
|     public static void Markup(string format, params object[] args) | ||||
|     { | ||||
|         Console.Markup(format, args); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified markup to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="format">A composite format string.</param> | ||||
|     /// <param name="args">An array of objects to write.</param> | ||||
|     public static void Markup(IFormatProvider provider, string format, params object[] args) | ||||
|     { | ||||
|         Console.Markup(provider, format, args); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified markup, followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void MarkupLine(string value) | ||||
|     { | ||||
|         Console.MarkupLine(value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified markup, followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="format">A composite format string.</param> | ||||
|     /// <param name="args">An array of objects to write.</param> | ||||
|     public static void MarkupLine(string format, params object[] args) | ||||
|     { | ||||
|         Console.MarkupLine(format, args); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified markup, followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="format">A composite format string.</param> | ||||
|     /// <param name="args">An array of objects to write.</param> | ||||
|     public static void MarkupLine(IFormatProvider provider, string format, params object[] args) | ||||
|     { | ||||
|         Console.MarkupLine(provider, format, args); | ||||
|     } | ||||
| } | ||||
| @@ -1,26 +1,25 @@ | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// Creates a new <see cref="Progress"/> instance. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     /// <returns>A <see cref="Progress"/> instance.</returns> | ||||
|     public static Progress Progress() | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Creates a new <see cref="Progress"/> instance. | ||||
|         /// </summary> | ||||
|         /// <returns>A <see cref="Progress"/> instance.</returns> | ||||
|         public static Progress Progress() | ||||
|         { | ||||
|             return Console.Progress(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a new <see cref="Status"/> instance. | ||||
|         /// </summary> | ||||
|         /// <returns>A <see cref="Status"/> instance.</returns> | ||||
|         public static Status Status() | ||||
|         { | ||||
|             return Console.Status(); | ||||
|         } | ||||
|         return Console.Progress(); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Creates a new <see cref="Status"/> instance. | ||||
|     /// </summary> | ||||
|     /// <returns>A <see cref="Status"/> instance.</returns> | ||||
|     public static Status Status() | ||||
|     { | ||||
|         return Console.Status(); | ||||
|     } | ||||
| } | ||||
| @@ -1,66 +1,65 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// Displays a prompt to the user. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     /// <typeparam name="T">The prompt result type.</typeparam> | ||||
|     /// <param name="prompt">The prompt to display.</param> | ||||
|     /// <returns>The prompt input result.</returns> | ||||
|     public static T Prompt<T>(IPrompt<T> prompt) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Displays a prompt to the user. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">The prompt result type.</typeparam> | ||||
|         /// <param name="prompt">The prompt to display.</param> | ||||
|         /// <returns>The prompt input result.</returns> | ||||
|         public static T Prompt<T>(IPrompt<T> prompt) | ||||
|         if (prompt is null) | ||||
|         { | ||||
|             if (prompt is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(prompt)); | ||||
|             } | ||||
|  | ||||
|             return prompt.Show(Console); | ||||
|             throw new ArgumentNullException(nameof(prompt)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Displays a prompt to the user. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">The prompt result type.</typeparam> | ||||
|         /// <param name="prompt">The prompt markup text.</param> | ||||
|         /// <returns>The prompt input result.</returns> | ||||
|         public static T Ask<T>(string prompt) | ||||
|         { | ||||
|             return new TextPrompt<T>(prompt).Show(Console); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Displays a prompt to the user with a given default. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">The prompt result type.</typeparam> | ||||
|         /// <param name="prompt">The prompt markup text.</param> | ||||
|         /// <param name="defaultValue">The default value.</param> | ||||
|         /// <returns>The prompt input result.</returns> | ||||
|         public static T Ask<T>(string prompt, T defaultValue) | ||||
|         { | ||||
|             return new TextPrompt<T>(prompt) | ||||
|                 .DefaultValue(defaultValue) | ||||
|                 .Show(Console); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Displays a prompt with two choices, yes or no. | ||||
|         /// </summary> | ||||
|         /// <param name="prompt">The prompt markup text.</param> | ||||
|         /// <param name="defaultValue">Specifies the default answer.</param> | ||||
|         /// <returns><c>true</c> if the user selected "yes", otherwise <c>false</c>.</returns> | ||||
|         public static bool Confirm(string prompt, bool defaultValue = true) | ||||
|         { | ||||
|             return new ConfirmationPrompt(prompt) | ||||
|             { | ||||
|                 DefaultValue = defaultValue, | ||||
|             } | ||||
|             .Show(Console); | ||||
|         } | ||||
|         return prompt.Show(Console); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Displays a prompt to the user. | ||||
|     /// </summary> | ||||
|     /// <typeparam name="T">The prompt result type.</typeparam> | ||||
|     /// <param name="prompt">The prompt markup text.</param> | ||||
|     /// <returns>The prompt input result.</returns> | ||||
|     public static T Ask<T>(string prompt) | ||||
|     { | ||||
|         return new TextPrompt<T>(prompt).Show(Console); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Displays a prompt to the user with a given default. | ||||
|     /// </summary> | ||||
|     /// <typeparam name="T">The prompt result type.</typeparam> | ||||
|     /// <param name="prompt">The prompt markup text.</param> | ||||
|     /// <param name="defaultValue">The default value.</param> | ||||
|     /// <returns>The prompt input result.</returns> | ||||
|     public static T Ask<T>(string prompt, T defaultValue) | ||||
|     { | ||||
|         return new TextPrompt<T>(prompt) | ||||
|             .DefaultValue(defaultValue) | ||||
|             .Show(Console); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Displays a prompt with two choices, yes or no. | ||||
|     /// </summary> | ||||
|     /// <param name="prompt">The prompt markup text.</param> | ||||
|     /// <param name="defaultValue">Specifies the default answer.</param> | ||||
|     /// <returns><c>true</c> if the user selected "yes", otherwise <c>false</c>.</returns> | ||||
|     public static bool Confirm(string prompt, bool defaultValue = true) | ||||
|     { | ||||
|         return new ConfirmationPrompt(prompt) | ||||
|         { | ||||
|             DefaultValue = defaultValue, | ||||
|         } | ||||
|         .Show(Console); | ||||
|     } | ||||
| } | ||||
| @@ -1,70 +1,69 @@ | ||||
| using System; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// Starts recording the console output. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     public static void Record() | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Starts recording the console output. | ||||
|         /// </summary> | ||||
|         public static void Record() | ||||
|         if (_recorder == null) | ||||
|         { | ||||
|             if (_recorder == null) | ||||
|             { | ||||
|                 _recorder = new Recorder(Console); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Exports all recorded console output as text. | ||||
|         /// </summary> | ||||
|         /// <returns>The recorded output as text.</returns> | ||||
|         public static string ExportText() | ||||
|         { | ||||
|             if (_recorder == null) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Cannot export text since a recording hasn't been started."); | ||||
|             } | ||||
|  | ||||
|             return _recorder.ExportText(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Exports all recorded console output as HTML text. | ||||
|         /// </summary> | ||||
|         /// <returns>The recorded output as HTML text.</returns> | ||||
|         public static string ExportHtml() | ||||
|         { | ||||
|             if (_recorder == null) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Cannot export HTML since a recording hasn't been started."); | ||||
|             } | ||||
|  | ||||
|             return _recorder.ExportHtml(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Exports all recorded console output using a custom encoder. | ||||
|         /// </summary> | ||||
|         /// <param name="encoder">The encoder to use.</param> | ||||
|         /// <returns>The recorded output.</returns> | ||||
|         public static string ExportCustom(IAnsiConsoleEncoder encoder) | ||||
|         { | ||||
|             if (_recorder == null) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Cannot export HTML since a recording hasn't been started."); | ||||
|             } | ||||
|  | ||||
|             if (encoder is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(encoder)); | ||||
|             } | ||||
|  | ||||
|             return _recorder.Export(encoder); | ||||
|             _recorder = new Recorder(Console); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Exports all recorded console output as text. | ||||
|     /// </summary> | ||||
|     /// <returns>The recorded output as text.</returns> | ||||
|     public static string ExportText() | ||||
|     { | ||||
|         if (_recorder == null) | ||||
|         { | ||||
|             throw new InvalidOperationException("Cannot export text since a recording hasn't been started."); | ||||
|         } | ||||
|  | ||||
|         return _recorder.ExportText(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Exports all recorded console output as HTML text. | ||||
|     /// </summary> | ||||
|     /// <returns>The recorded output as HTML text.</returns> | ||||
|     public static string ExportHtml() | ||||
|     { | ||||
|         if (_recorder == null) | ||||
|         { | ||||
|             throw new InvalidOperationException("Cannot export HTML since a recording hasn't been started."); | ||||
|         } | ||||
|  | ||||
|         return _recorder.ExportHtml(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Exports all recorded console output using a custom encoder. | ||||
|     /// </summary> | ||||
|     /// <param name="encoder">The encoder to use.</param> | ||||
|     /// <returns>The recorded output.</returns> | ||||
|     public static string ExportCustom(IAnsiConsoleEncoder encoder) | ||||
|     { | ||||
|         if (_recorder == null) | ||||
|         { | ||||
|             throw new InvalidOperationException("Cannot export HTML since a recording hasn't been started."); | ||||
|         } | ||||
|  | ||||
|         if (encoder is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(encoder)); | ||||
|         } | ||||
|  | ||||
|         return _recorder.Export(encoder); | ||||
|     } | ||||
| } | ||||
| @@ -1,35 +1,34 @@ | ||||
| using System; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// Renders the specified object to the console. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     /// <param name="renderable">The object to render.</param> | ||||
|     [Obsolete("Consider using AnsiConsole.Write instead.")] | ||||
|     public static void Render(IRenderable renderable) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Renders the specified object to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="renderable">The object to render.</param> | ||||
|         [Obsolete("Consider using AnsiConsole.Write instead.")] | ||||
|         public static void Render(IRenderable renderable) | ||||
|         { | ||||
|             Write(renderable); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Renders the specified <see cref="IRenderable"/> to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="renderable">The object to render.</param> | ||||
|         public static void Write(IRenderable renderable) | ||||
|         { | ||||
|             if (renderable is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(renderable)); | ||||
|             } | ||||
|  | ||||
|             Console.Write(renderable); | ||||
|         } | ||||
|         Write(renderable); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Renders the specified <see cref="IRenderable"/> to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="renderable">The object to render.</param> | ||||
|     public static void Write(IRenderable renderable) | ||||
|     { | ||||
|         if (renderable is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(renderable)); | ||||
|         } | ||||
|  | ||||
|         Console.Write(renderable); | ||||
|     } | ||||
| } | ||||
| @@ -1,19 +1,18 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// Switches to an alternate screen buffer if the terminal supports it. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     /// <param name="action">The action to execute within the alternate screen buffer.</param> | ||||
|     public static void AlternateScreen(Action action) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Switches to an alternate screen buffer if the terminal supports it. | ||||
|         /// </summary> | ||||
|         /// <param name="action">The action to execute within the alternate screen buffer.</param> | ||||
|         public static void AlternateScreen(Action action) | ||||
|         { | ||||
|             Console.AlternateScreen(action); | ||||
|         } | ||||
|         Console.AlternateScreen(action); | ||||
|     } | ||||
| } | ||||
| } | ||||
| @@ -1,63 +1,62 @@ | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     internal static Style CurrentStyle { get; private set; } = Style.Plain; | ||||
|     internal static bool Created { get; private set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// Gets or sets the foreground color. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     public static Color Foreground | ||||
|     { | ||||
|         internal static Style CurrentStyle { get; private set; } = Style.Plain; | ||||
|         internal static bool Created { get; private set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the foreground color. | ||||
|         /// </summary> | ||||
|         public static Color Foreground | ||||
|         { | ||||
|             get => CurrentStyle.Foreground; | ||||
|             set => CurrentStyle = CurrentStyle.Foreground(value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the background color. | ||||
|         /// </summary> | ||||
|         public static Color Background | ||||
|         { | ||||
|             get => CurrentStyle.Background; | ||||
|             set => CurrentStyle = CurrentStyle.Background(value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the text decoration. | ||||
|         /// </summary> | ||||
|         public static Decoration Decoration | ||||
|         { | ||||
|             get => CurrentStyle.Decoration; | ||||
|             set => CurrentStyle = CurrentStyle.Decoration(value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Resets colors and text decorations. | ||||
|         /// </summary> | ||||
|         public static void Reset() | ||||
|         { | ||||
|             ResetColors(); | ||||
|             ResetDecoration(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Resets the current applied text decorations. | ||||
|         /// </summary> | ||||
|         public static void ResetDecoration() | ||||
|         { | ||||
|             Decoration = Decoration.None; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Resets the current applied foreground and background colors. | ||||
|         /// </summary> | ||||
|         public static void ResetColors() | ||||
|         { | ||||
|             CurrentStyle = Style.Plain; | ||||
|         } | ||||
|         get => CurrentStyle.Foreground; | ||||
|         set => CurrentStyle = CurrentStyle.Foreground(value); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the background color. | ||||
|     /// </summary> | ||||
|     public static Color Background | ||||
|     { | ||||
|         get => CurrentStyle.Background; | ||||
|         set => CurrentStyle = CurrentStyle.Background(value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the text decoration. | ||||
|     /// </summary> | ||||
|     public static Decoration Decoration | ||||
|     { | ||||
|         get => CurrentStyle.Decoration; | ||||
|         set => CurrentStyle = CurrentStyle.Decoration(value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Resets colors and text decorations. | ||||
|     /// </summary> | ||||
|     public static void Reset() | ||||
|     { | ||||
|         ResetColors(); | ||||
|         ResetDecoration(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Resets the current applied text decorations. | ||||
|     /// </summary> | ||||
|     public static void ResetDecoration() | ||||
|     { | ||||
|         Decoration = Decoration.None; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Resets the current applied foreground and background colors. | ||||
|     /// </summary> | ||||
|     public static void ResetColors() | ||||
|     { | ||||
|         CurrentStyle = Style.Plain; | ||||
|     } | ||||
| } | ||||
| @@ -1,253 +1,252 @@ | ||||
| using System; | ||||
| using System.Globalization; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// Writes the specified string value to the console. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(string value) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Writes the specified string value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(string value) | ||||
|         Write(value, CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 32-bit | ||||
|     /// signed integer value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(int value) | ||||
|     { | ||||
|         Write(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 32-bit | ||||
|     /// signed integer value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(IFormatProvider provider, int value) | ||||
|     { | ||||
|         Console.Write(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 32-bit | ||||
|     /// unsigned integer value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(uint value) | ||||
|     { | ||||
|         Write(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 32-bit | ||||
|     /// unsigned integer value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(IFormatProvider provider, uint value) | ||||
|     { | ||||
|         Console.Write(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 64-bit | ||||
|     /// signed integer value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(long value) | ||||
|     { | ||||
|         Write(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 64-bit | ||||
|     /// signed integer value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(IFormatProvider provider, long value) | ||||
|     { | ||||
|         Console.Write(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 64-bit | ||||
|     /// unsigned integer value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(ulong value) | ||||
|     { | ||||
|         Write(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 64-bit | ||||
|     /// unsigned integer value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(IFormatProvider provider, ulong value) | ||||
|     { | ||||
|         Console.Write(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified single-precision | ||||
|     /// floating-point value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(float value) | ||||
|     { | ||||
|         Write(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified single-precision | ||||
|     /// floating-point value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(IFormatProvider provider, float value) | ||||
|     { | ||||
|         Console.Write(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified double-precision | ||||
|     /// floating-point value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(double value) | ||||
|     { | ||||
|         Write(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified double-precision | ||||
|     /// floating-point value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(IFormatProvider provider, double value) | ||||
|     { | ||||
|         Console.Write(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified decimal value, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(decimal value) | ||||
|     { | ||||
|         Write(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified decimal value, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(IFormatProvider provider, decimal value) | ||||
|     { | ||||
|         Console.Write(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified boolean value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(bool value) | ||||
|     { | ||||
|         Write(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified boolean value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(IFormatProvider provider, bool value) | ||||
|     { | ||||
|         Console.Write(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified Unicode character to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(char value) | ||||
|     { | ||||
|         Write(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified Unicode character to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(IFormatProvider provider, char value) | ||||
|     { | ||||
|         Console.Write(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified array of Unicode characters to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(char[] value) | ||||
|     { | ||||
|         Write(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified array of Unicode characters to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void Write(IFormatProvider provider, char[] value) | ||||
|     { | ||||
|         if (value is null) | ||||
|         { | ||||
|             Write(value, CurrentStyle); | ||||
|             throw new ArgumentNullException(nameof(value)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(int value) | ||||
|         for (var index = 0; index < value.Length; index++) | ||||
|         { | ||||
|             Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, int value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(uint value) | ||||
|         { | ||||
|             Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, uint value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(long value) | ||||
|         { | ||||
|             Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, long value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(ulong value) | ||||
|         { | ||||
|             Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, ulong value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(float value) | ||||
|         { | ||||
|             Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, float value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(double value) | ||||
|         { | ||||
|             Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, double value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(decimal value) | ||||
|         { | ||||
|             Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, decimal value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(bool value) | ||||
|         { | ||||
|             Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, bool value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(char value) | ||||
|         { | ||||
|             Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, char value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(char[] value) | ||||
|         { | ||||
|             Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, char[] value) | ||||
|         { | ||||
|             if (value is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(value)); | ||||
|             } | ||||
|  | ||||
|             for (var index = 0; index < value.Length; index++) | ||||
|             { | ||||
|                 Console.Write(value[index].ToString(provider), CurrentStyle); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// to the console using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Write(string format, params object[] args) | ||||
|         { | ||||
|             Write(CultureInfo.CurrentCulture, format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// to the console using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Write(IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             Console.Write(string.Format(provider, format, args), CurrentStyle); | ||||
|             Console.Write(value[index].ToString(provider), CurrentStyle); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified array of objects, | ||||
|     /// to the console using the specified format information. | ||||
|     /// </summary> | ||||
|     /// <param name="format">A composite format string.</param> | ||||
|     /// <param name="args">An array of objects to write.</param> | ||||
|     public static void Write(string format, params object[] args) | ||||
|     { | ||||
|         Write(CultureInfo.CurrentCulture, format, args); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified array of objects, | ||||
|     /// to the console using the specified format information. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="format">A composite format string.</param> | ||||
|     /// <param name="args">An array of objects to write.</param> | ||||
|     public static void Write(IFormatProvider provider, string format, params object[] args) | ||||
|     { | ||||
|         Console.Write(string.Format(provider, format, args), CurrentStyle); | ||||
|     } | ||||
| } | ||||
| @@ -1,273 +1,272 @@ | ||||
| using System; | ||||
| using System.Globalization; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// Writes an empty line to the console. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     public static void WriteLine() | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Writes an empty line to the console. | ||||
|         /// </summary> | ||||
|         public static void WriteLine() | ||||
|         { | ||||
|             Console.WriteLine(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified string value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(string value) | ||||
|         { | ||||
|             Console.WriteLine(value, CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(int value) | ||||
|         { | ||||
|             WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, int value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(uint value) | ||||
|         { | ||||
|             WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, uint value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(long value) | ||||
|         { | ||||
|             WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, long value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(ulong value) | ||||
|         { | ||||
|             WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, ulong value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(float value) | ||||
|         { | ||||
|             WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, float value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(double value) | ||||
|         { | ||||
|             WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, double value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(decimal value) | ||||
|         { | ||||
|             WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, decimal value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(bool value) | ||||
|         { | ||||
|             WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, bool value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(char value) | ||||
|         { | ||||
|             WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, char value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(char[] value) | ||||
|         { | ||||
|             WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, char[] value) | ||||
|         { | ||||
|             if (value is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(value)); | ||||
|             } | ||||
|  | ||||
|             for (var index = 0; index < value.Length; index++) | ||||
|             { | ||||
|                 Console.Write(value[index].ToString(provider), CurrentStyle); | ||||
|             } | ||||
|  | ||||
|             Console.WriteLine(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// followed by the current line terminator, to the console | ||||
|         /// using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void WriteLine(string format, params object[] args) | ||||
|         { | ||||
|             WriteLine(CultureInfo.CurrentCulture, format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// followed by the current line terminator, to the console | ||||
|         /// using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             Console.WriteLine(string.Format(provider, format, args), CurrentStyle); | ||||
|         } | ||||
|         Console.WriteLine(); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified string value, followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(string value) | ||||
|     { | ||||
|         Console.WriteLine(value, CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 32-bit signed integer value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(int value) | ||||
|     { | ||||
|         WriteLine(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 32-bit signed integer value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(IFormatProvider provider, int value) | ||||
|     { | ||||
|         Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 32-bit unsigned integer value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(uint value) | ||||
|     { | ||||
|         WriteLine(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 32-bit unsigned integer value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(IFormatProvider provider, uint value) | ||||
|     { | ||||
|         Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 64-bit signed integer value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(long value) | ||||
|     { | ||||
|         WriteLine(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 64-bit signed integer value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(IFormatProvider provider, long value) | ||||
|     { | ||||
|         Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 64-bit unsigned integer value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(ulong value) | ||||
|     { | ||||
|         WriteLine(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified 64-bit unsigned integer value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(IFormatProvider provider, ulong value) | ||||
|     { | ||||
|         Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified single-precision floating-point | ||||
|     /// value, followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(float value) | ||||
|     { | ||||
|         WriteLine(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified single-precision floating-point | ||||
|     /// value, followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(IFormatProvider provider, float value) | ||||
|     { | ||||
|         Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified double-precision floating-point | ||||
|     /// value, followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(double value) | ||||
|     { | ||||
|         WriteLine(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified double-precision floating-point | ||||
|     /// value, followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(IFormatProvider provider, double value) | ||||
|     { | ||||
|         Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified decimal value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(decimal value) | ||||
|     { | ||||
|         WriteLine(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified decimal value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(IFormatProvider provider, decimal value) | ||||
|     { | ||||
|         Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified boolean value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(bool value) | ||||
|     { | ||||
|         WriteLine(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified boolean value, | ||||
|     /// followed by the current line terminator, to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(IFormatProvider provider, bool value) | ||||
|     { | ||||
|         Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified Unicode character, followed by the current | ||||
|     /// line terminator, value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(char value) | ||||
|     { | ||||
|         WriteLine(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified Unicode character, followed by the current | ||||
|     /// line terminator, value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(IFormatProvider provider, char value) | ||||
|     { | ||||
|         Console.WriteLine(value.ToString(provider), CurrentStyle); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified array of Unicode characters, followed by the current | ||||
|     /// line terminator, value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(char[] value) | ||||
|     { | ||||
|         WriteLine(CultureInfo.CurrentCulture, value); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the specified array of Unicode characters, followed by the current | ||||
|     /// line terminator, value to the console. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="value">The value to write.</param> | ||||
|     public static void WriteLine(IFormatProvider provider, char[] value) | ||||
|     { | ||||
|         if (value is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(value)); | ||||
|         } | ||||
|  | ||||
|         for (var index = 0; index < value.Length; index++) | ||||
|         { | ||||
|             Console.Write(value[index].ToString(provider), CurrentStyle); | ||||
|         } | ||||
|  | ||||
|         Console.WriteLine(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified array of objects, | ||||
|     /// followed by the current line terminator, to the console | ||||
|     /// using the specified format information. | ||||
|     /// </summary> | ||||
|     /// <param name="format">A composite format string.</param> | ||||
|     /// <param name="args">An array of objects to write.</param> | ||||
|     public static void WriteLine(string format, params object[] args) | ||||
|     { | ||||
|         WriteLine(CultureInfo.CurrentCulture, format, args); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Writes the text representation of the specified array of objects, | ||||
|     /// followed by the current line terminator, to the console | ||||
|     /// using the specified format information. | ||||
|     /// </summary> | ||||
|     /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|     /// <param name="format">A composite format string.</param> | ||||
|     /// <param name="args">An array of objects to write.</param> | ||||
|     public static void WriteLine(IFormatProvider provider, string format, params object[] args) | ||||
|     { | ||||
|         Console.WriteLine(string.Format(provider, format, args), CurrentStyle); | ||||
|     } | ||||
| } | ||||
| @@ -1,78 +1,77 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     { | ||||
|         private static Recorder? _recorder; | ||||
|         private static Lazy<IAnsiConsole> _console = new Lazy<IAnsiConsole>( | ||||
|             () => | ||||
|             { | ||||
|                 var console = Create(new AnsiConsoleSettings | ||||
|                 { | ||||
|                     Ansi = AnsiSupport.Detect, | ||||
|                     ColorSystem = ColorSystemSupport.Detect, | ||||
|                     Out = new AnsiConsoleOutput(System.Console.Out), | ||||
|                 }); | ||||
| namespace Spectre.Console; | ||||
|  | ||||
|                 Created = true; | ||||
|                 return console; | ||||
| /// <summary> | ||||
| /// A console capable of writing ANSI escape sequences. | ||||
| /// </summary> | ||||
| public static partial class AnsiConsole | ||||
| { | ||||
|     private static Recorder? _recorder; | ||||
|     private static Lazy<IAnsiConsole> _console = new Lazy<IAnsiConsole>( | ||||
|         () => | ||||
|         { | ||||
|             var console = Create(new AnsiConsoleSettings | ||||
|             { | ||||
|                 Ansi = AnsiSupport.Detect, | ||||
|                 ColorSystem = ColorSystemSupport.Detect, | ||||
|                 Out = new AnsiConsoleOutput(System.Console.Out), | ||||
|             }); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the underlying <see cref="IAnsiConsole"/>. | ||||
|         /// </summary> | ||||
|         public static IAnsiConsole Console | ||||
|             Created = true; | ||||
|             return console; | ||||
|         }); | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the underlying <see cref="IAnsiConsole"/>. | ||||
|     /// </summary> | ||||
|     public static IAnsiConsole Console | ||||
|     { | ||||
|         get | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _recorder ?? _console.Value; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 _console = new Lazy<IAnsiConsole>(() => value); | ||||
|  | ||||
|                 if (_recorder != null) | ||||
|                 { | ||||
|                     // Recreate the recorder | ||||
|                     _recorder = _recorder.Clone(value); | ||||
|                 } | ||||
|  | ||||
|                 Created = true; | ||||
|             } | ||||
|             return _recorder ?? _console.Value; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the <see cref="IAnsiConsoleCursor"/>. | ||||
|         /// </summary> | ||||
|         public static IAnsiConsoleCursor Cursor => _recorder?.Cursor ?? _console.Value.Cursor; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the console profile. | ||||
|         /// </summary> | ||||
|         public static Profile Profile => Console.Profile; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a new <see cref="IAnsiConsole"/> instance | ||||
|         /// from the provided settings. | ||||
|         /// </summary> | ||||
|         /// <param name="settings">The settings to use.</param> | ||||
|         /// <returns>An <see cref="IAnsiConsole"/> instance.</returns> | ||||
|         public static IAnsiConsole Create(AnsiConsoleSettings settings) | ||||
|         set | ||||
|         { | ||||
|             var factory = new AnsiConsoleFactory(); | ||||
|             return factory.Create(settings); | ||||
|         } | ||||
|             _console = new Lazy<IAnsiConsole>(() => value); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Clears the console. | ||||
|         /// </summary> | ||||
|         public static void Clear() | ||||
|         { | ||||
|             Console.Clear(); | ||||
|             if (_recorder != null) | ||||
|             { | ||||
|                 // Recreate the recorder | ||||
|                 _recorder = _recorder.Clone(value); | ||||
|             } | ||||
|  | ||||
|             Created = true; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets the <see cref="IAnsiConsoleCursor"/>. | ||||
|     /// </summary> | ||||
|     public static IAnsiConsoleCursor Cursor => _recorder?.Cursor ?? _console.Value.Cursor; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets the console profile. | ||||
|     /// </summary> | ||||
|     public static Profile Profile => Console.Profile; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Creates a new <see cref="IAnsiConsole"/> instance | ||||
|     /// from the provided settings. | ||||
|     /// </summary> | ||||
|     /// <param name="settings">The settings to use.</param> | ||||
|     /// <returns>An <see cref="IAnsiConsole"/> instance.</returns> | ||||
|     public static IAnsiConsole Create(AnsiConsoleSettings settings) | ||||
|     { | ||||
|         var factory = new AnsiConsoleFactory(); | ||||
|         return factory.Create(settings); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Clears the console. | ||||
|     /// </summary> | ||||
|     public static void Clear() | ||||
|     { | ||||
|         Console.Clear(); | ||||
|     } | ||||
| } | ||||
| @@ -3,110 +3,109 @@ using System.Runtime.InteropServices; | ||||
| using Spectre.Console.Enrichment; | ||||
| using Spectre.Console.Internal; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// Factory for creating an ANSI console. | ||||
| /// </summary> | ||||
| public sealed class AnsiConsoleFactory | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Factory for creating an ANSI console. | ||||
|     /// Creates an ANSI console. | ||||
|     /// </summary> | ||||
|     public sealed class AnsiConsoleFactory | ||||
|     /// <param name="settings">The settings.</param> | ||||
|     /// <returns>An implementation of <see cref="IAnsiConsole"/>.</returns> | ||||
|     public IAnsiConsole Create(AnsiConsoleSettings settings) | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Creates an ANSI console. | ||||
|         /// </summary> | ||||
|         /// <param name="settings">The settings.</param> | ||||
|         /// <returns>An implementation of <see cref="IAnsiConsole"/>.</returns> | ||||
|         public IAnsiConsole Create(AnsiConsoleSettings settings) | ||||
|         if (settings is null) | ||||
|         { | ||||
|             if (settings is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(settings)); | ||||
|             } | ||||
|  | ||||
|             var output = settings.Out ?? new AnsiConsoleOutput(System.Console.Out); | ||||
|             if (output.Writer == null) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Output writer was null"); | ||||
|             } | ||||
|  | ||||
|             // Detect if the terminal support ANSI or not | ||||
|             var (supportsAnsi, legacyConsole) = DetectAnsi(settings, output.Writer); | ||||
|  | ||||
|             // Use console encoding or fall back to provided encoding | ||||
|             var encoding = output.Writer.IsStandardOut() || output.Writer.IsStandardError() | ||||
|                 ? System.Console.OutputEncoding : output.Writer.Encoding; | ||||
|  | ||||
|             // Get the color system | ||||
|             var colorSystem = settings.ColorSystem == ColorSystemSupport.Detect | ||||
|                 ? ColorSystemDetector.Detect(supportsAnsi) | ||||
|                 : (ColorSystem)settings.ColorSystem; | ||||
|  | ||||
|             // Get whether or not we consider the terminal interactive | ||||
|             var interactive = settings.Interactive == InteractionSupport.Yes; | ||||
|             if (settings.Interactive == InteractionSupport.Detect) | ||||
|             { | ||||
|                 interactive = Environment.UserInteractive; | ||||
|             } | ||||
|  | ||||
|             var profile = new Profile(output, encoding); | ||||
|  | ||||
|             profile.Capabilities.ColorSystem = colorSystem; | ||||
|             profile.Capabilities.Ansi = supportsAnsi; | ||||
|             profile.Capabilities.Links = supportsAnsi && !legacyConsole; | ||||
|             profile.Capabilities.Legacy = legacyConsole; | ||||
|             profile.Capabilities.Interactive = interactive; | ||||
|             profile.Capabilities.Unicode = encoding.EncodingName.ContainsExact("Unicode"); | ||||
|             profile.Capabilities.AlternateBuffer = supportsAnsi && !legacyConsole; | ||||
|  | ||||
|             // Enrich the profile | ||||
|             ProfileEnricher.Enrich( | ||||
|                 profile, | ||||
|                 settings.Enrichment, | ||||
|                 settings.EnvironmentVariables); | ||||
|  | ||||
|             return new AnsiConsoleFacade( | ||||
|                 profile, | ||||
|                 settings.ExclusivityMode ?? new DefaultExclusivityMode()); | ||||
|             throw new ArgumentNullException(nameof(settings)); | ||||
|         } | ||||
|  | ||||
|         private static (bool Ansi, bool Legacy) DetectAnsi(AnsiConsoleSettings settings, System.IO.TextWriter buffer) | ||||
|         var output = settings.Out ?? new AnsiConsoleOutput(System.Console.Out); | ||||
|         if (output.Writer == null) | ||||
|         { | ||||
|             var supportsAnsi = settings.Ansi == AnsiSupport.Yes; | ||||
|             var legacyConsole = false; | ||||
|             throw new InvalidOperationException("Output writer was null"); | ||||
|         } | ||||
|  | ||||
|             if (settings.Ansi == AnsiSupport.Detect) | ||||
|         // Detect if the terminal support ANSI or not | ||||
|         var (supportsAnsi, legacyConsole) = DetectAnsi(settings, output.Writer); | ||||
|  | ||||
|         // Use console encoding or fall back to provided encoding | ||||
|         var encoding = output.Writer.IsStandardOut() || output.Writer.IsStandardError() | ||||
|             ? System.Console.OutputEncoding : output.Writer.Encoding; | ||||
|  | ||||
|         // Get the color system | ||||
|         var colorSystem = settings.ColorSystem == ColorSystemSupport.Detect | ||||
|             ? ColorSystemDetector.Detect(supportsAnsi) | ||||
|             : (ColorSystem)settings.ColorSystem; | ||||
|  | ||||
|         // Get whether or not we consider the terminal interactive | ||||
|         var interactive = settings.Interactive == InteractionSupport.Yes; | ||||
|         if (settings.Interactive == InteractionSupport.Detect) | ||||
|         { | ||||
|             interactive = Environment.UserInteractive; | ||||
|         } | ||||
|  | ||||
|         var profile = new Profile(output, encoding); | ||||
|  | ||||
|         profile.Capabilities.ColorSystem = colorSystem; | ||||
|         profile.Capabilities.Ansi = supportsAnsi; | ||||
|         profile.Capabilities.Links = supportsAnsi && !legacyConsole; | ||||
|         profile.Capabilities.Legacy = legacyConsole; | ||||
|         profile.Capabilities.Interactive = interactive; | ||||
|         profile.Capabilities.Unicode = encoding.EncodingName.ContainsExact("Unicode"); | ||||
|         profile.Capabilities.AlternateBuffer = supportsAnsi && !legacyConsole; | ||||
|  | ||||
|         // Enrich the profile | ||||
|         ProfileEnricher.Enrich( | ||||
|             profile, | ||||
|             settings.Enrichment, | ||||
|             settings.EnvironmentVariables); | ||||
|  | ||||
|         return new AnsiConsoleFacade( | ||||
|             profile, | ||||
|             settings.ExclusivityMode ?? new DefaultExclusivityMode()); | ||||
|     } | ||||
|  | ||||
|     private static (bool Ansi, bool Legacy) DetectAnsi(AnsiConsoleSettings settings, System.IO.TextWriter buffer) | ||||
|     { | ||||
|         var supportsAnsi = settings.Ansi == AnsiSupport.Yes; | ||||
|         var legacyConsole = false; | ||||
|  | ||||
|         if (settings.Ansi == AnsiSupport.Detect) | ||||
|         { | ||||
|             (supportsAnsi, legacyConsole) = AnsiDetector.Detect(buffer.IsStandardError(), true); | ||||
|  | ||||
|             // Check whether or not this is a legacy console from the existing instance (if any). | ||||
|             // We need to do this because once we upgrade the console to support ENABLE_VIRTUAL_TERMINAL_PROCESSING | ||||
|             // on Windows, there is no way of detecting whether or not we're running on a legacy console or not. | ||||
|             if (AnsiConsole.Created && !legacyConsole && (buffer.IsStandardOut() || buffer.IsStandardError()) && AnsiConsole.Profile.Capabilities.Legacy) | ||||
|             { | ||||
|                 (supportsAnsi, legacyConsole) = AnsiDetector.Detect(buffer.IsStandardError(), true); | ||||
|  | ||||
|                 // Check whether or not this is a legacy console from the existing instance (if any). | ||||
|                 // We need to do this because once we upgrade the console to support ENABLE_VIRTUAL_TERMINAL_PROCESSING | ||||
|                 // on Windows, there is no way of detecting whether or not we're running on a legacy console or not. | ||||
|                 if (AnsiConsole.Created && !legacyConsole && (buffer.IsStandardOut() || buffer.IsStandardError()) && AnsiConsole.Profile.Capabilities.Legacy) | ||||
|                 { | ||||
|                     legacyConsole = AnsiConsole.Profile.Capabilities.Legacy; | ||||
|                 } | ||||
|                 legacyConsole = AnsiConsole.Profile.Capabilities.Legacy; | ||||
|             } | ||||
|             else | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (buffer.IsStandardOut() || buffer.IsStandardError()) | ||||
|             { | ||||
|                 if (buffer.IsStandardOut() || buffer.IsStandardError()) | ||||
|                 // Are we running on Windows? | ||||
|                 if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | ||||
|                 { | ||||
|                     // Are we running on Windows? | ||||
|                     if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | ||||
|                     // Not the first console we're creating? | ||||
|                     if (AnsiConsole.Created) | ||||
|                     { | ||||
|                         // Not the first console we're creating? | ||||
|                         if (AnsiConsole.Created) | ||||
|                         { | ||||
|                             legacyConsole = AnsiConsole.Profile.Capabilities.Legacy; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             // Try detecting whether or not this is a legacy console | ||||
|                             (_, legacyConsole) = AnsiDetector.Detect(buffer.IsStandardError(), false); | ||||
|                         } | ||||
|                         legacyConsole = AnsiConsole.Profile.Capabilities.Legacy; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         // Try detecting whether or not this is a legacy console | ||||
|                         (_, legacyConsole) = AnsiDetector.Detect(buffer.IsStandardError(), false); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return (supportsAnsi, legacyConsole); | ||||
|         } | ||||
|  | ||||
|         return (supportsAnsi, legacyConsole); | ||||
|     } | ||||
| } | ||||
| } | ||||
| @@ -2,57 +2,56 @@ using System; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// Represents console output. | ||||
| /// </summary> | ||||
| public sealed class AnsiConsoleOutput : IAnsiConsoleOutput | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents console output. | ||||
|     /// </summary> | ||||
|     public sealed class AnsiConsoleOutput : IAnsiConsoleOutput | ||||
|     /// <inheritdoc/> | ||||
|     public TextWriter Writer { get; } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public bool IsTerminal | ||||
|     { | ||||
|         /// <inheritdoc/> | ||||
|         public TextWriter Writer { get; } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool IsTerminal | ||||
|         get | ||||
|         { | ||||
|             get | ||||
|             if (Writer.IsStandardOut()) | ||||
|             { | ||||
|                 if (Writer.IsStandardOut()) | ||||
|                 { | ||||
|                     return !System.Console.IsOutputRedirected; | ||||
|                 } | ||||
|  | ||||
|                 if (Writer.IsStandardError()) | ||||
|                 { | ||||
|                     return !System.Console.IsErrorRedirected; | ||||
|                 } | ||||
|  | ||||
|                 return false; | ||||
|                 return !System.Console.IsOutputRedirected; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public int Width => ConsoleHelper.GetSafeWidth(Constants.DefaultTerminalWidth); | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public int Height => ConsoleHelper.GetSafeHeight(Constants.DefaultTerminalWidth); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="AnsiConsoleOutput"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="writer">The output writer.</param> | ||||
|         public AnsiConsoleOutput(TextWriter writer) | ||||
|         { | ||||
|             Writer = writer ?? throw new ArgumentNullException(nameof(writer)); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public void SetEncoding(Encoding encoding) | ||||
|         { | ||||
|             if (Writer.IsStandardOut() || Writer.IsStandardError()) | ||||
|             if (Writer.IsStandardError()) | ||||
|             { | ||||
|                 System.Console.OutputEncoding = encoding; | ||||
|                 return !System.Console.IsErrorRedirected; | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public int Width => ConsoleHelper.GetSafeWidth(Constants.DefaultTerminalWidth); | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public int Height => ConsoleHelper.GetSafeHeight(Constants.DefaultTerminalWidth); | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Initializes a new instance of the <see cref="AnsiConsoleOutput"/> class. | ||||
|     /// </summary> | ||||
|     /// <param name="writer">The output writer.</param> | ||||
|     public AnsiConsoleOutput(TextWriter writer) | ||||
|     { | ||||
|         Writer = writer ?? throw new ArgumentNullException(nameof(writer)); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public void SetEncoding(Encoding encoding) | ||||
|     { | ||||
|         if (Writer.IsStandardOut() || Writer.IsStandardError()) | ||||
|         { | ||||
|             System.Console.OutputEncoding = encoding; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,56 +1,55 @@ | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// Settings used when building a <see cref="IAnsiConsole"/>. | ||||
| /// </summary> | ||||
| public sealed class AnsiConsoleSettings | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Settings used when building a <see cref="IAnsiConsole"/>. | ||||
|     /// Gets or sets a value indicating whether or | ||||
|     /// not ANSI escape sequences are supported. | ||||
|     /// </summary> | ||||
|     public sealed class AnsiConsoleSettings | ||||
|     public AnsiSupport Ansi { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the color system to use. | ||||
|     /// </summary> | ||||
|     public ColorSystemSupport ColorSystem { get; set; } = ColorSystemSupport.Detect; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the out buffer. | ||||
|     /// </summary> | ||||
|     public IAnsiConsoleOutput? Out { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets a value indicating whether or not the | ||||
|     /// terminal is interactive or not. | ||||
|     /// </summary> | ||||
|     public InteractionSupport Interactive { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the exclusivity mode. | ||||
|     /// </summary> | ||||
|     public IExclusivityMode? ExclusivityMode { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the profile enrichments settings. | ||||
|     /// </summary> | ||||
|     public ProfileEnrichment Enrichment { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets the environment variables. | ||||
|     /// If not value is provided the default environment variables will be used. | ||||
|     /// </summary> | ||||
|     public Dictionary<string, string>? EnvironmentVariables { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Initializes a new instance of the <see cref="AnsiConsoleSettings"/> class. | ||||
|     /// </summary> | ||||
|     public AnsiConsoleSettings() | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether or | ||||
|         /// not ANSI escape sequences are supported. | ||||
|         /// </summary> | ||||
|         public AnsiSupport Ansi { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the color system to use. | ||||
|         /// </summary> | ||||
|         public ColorSystemSupport ColorSystem { get; set; } = ColorSystemSupport.Detect; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the out buffer. | ||||
|         /// </summary> | ||||
|         public IAnsiConsoleOutput? Out { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether or not the | ||||
|         /// terminal is interactive or not. | ||||
|         /// </summary> | ||||
|         public InteractionSupport Interactive { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the exclusivity mode. | ||||
|         /// </summary> | ||||
|         public IExclusivityMode? ExclusivityMode { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the profile enrichments settings. | ||||
|         /// </summary> | ||||
|         public ProfileEnrichment Enrichment { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the environment variables. | ||||
|         /// If not value is provided the default environment variables will be used. | ||||
|         /// </summary> | ||||
|         public Dictionary<string, string>? EnvironmentVariables { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="AnsiConsoleSettings"/> class. | ||||
|         /// </summary> | ||||
|         public AnsiConsoleSettings() | ||||
|         { | ||||
|             Enrichment = new ProfileEnrichment(); | ||||
|         } | ||||
|         Enrichment = new ProfileEnrichment(); | ||||
|     } | ||||
| } | ||||
| } | ||||
| @@ -1,24 +1,23 @@ | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// Determines ANSI escape sequence support. | ||||
| /// </summary> | ||||
| public enum AnsiSupport | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Determines ANSI escape sequence support. | ||||
|     /// ANSI escape sequence support should | ||||
|     /// be detected by the system. | ||||
|     /// </summary> | ||||
|     public enum AnsiSupport | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// ANSI escape sequence support should | ||||
|         /// be detected by the system. | ||||
|         /// </summary> | ||||
|         Detect = 0, | ||||
|     Detect = 0, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// ANSI escape sequences are supported. | ||||
|         /// </summary> | ||||
|         Yes = 1, | ||||
|     /// <summary> | ||||
|     /// ANSI escape sequences are supported. | ||||
|     /// </summary> | ||||
|     Yes = 1, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// ANSI escape sequences are not supported. | ||||
|         /// </summary> | ||||
|         No = 2, | ||||
|     } | ||||
| } | ||||
|     /// <summary> | ||||
|     /// ANSI escape sequences are not supported. | ||||
|     /// </summary> | ||||
|     No = 2, | ||||
| } | ||||
| @@ -1,42 +1,41 @@ | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| namespace Spectre.Console; | ||||
|  | ||||
| /// <summary> | ||||
| /// Represents a border. | ||||
| /// </summary> | ||||
| public abstract partial class BoxBorder | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a border. | ||||
|     /// Gets an invisible border. | ||||
|     /// </summary> | ||||
|     public abstract partial class BoxBorder | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets an invisible border. | ||||
|         /// </summary> | ||||
|         public static BoxBorder None { get; } = new NoBoxBorder(); | ||||
|     public static BoxBorder None { get; } = new NoBoxBorder(); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets an ASCII border. | ||||
|         /// </summary> | ||||
|         public static BoxBorder Ascii { get; } = new AsciiBoxBorder(); | ||||
|     /// <summary> | ||||
|     /// Gets an ASCII border. | ||||
|     /// </summary> | ||||
|     public static BoxBorder Ascii { get; } = new AsciiBoxBorder(); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a double border. | ||||
|         /// </summary> | ||||
|         [SuppressMessage("Naming", "CA1720:Identifier contains type name")] | ||||
|         public static BoxBorder Double { get; } = new DoubleBoxBorder(); | ||||
|     /// <summary> | ||||
|     /// Gets a double border. | ||||
|     /// </summary> | ||||
|     [SuppressMessage("Naming", "CA1720:Identifier contains type name")] | ||||
|     public static BoxBorder Double { get; } = new DoubleBoxBorder(); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a heavy border. | ||||
|         /// </summary> | ||||
|         public static BoxBorder Heavy { get; } = new HeavyBoxBorder(); | ||||
|     /// <summary> | ||||
|     /// Gets a heavy border. | ||||
|     /// </summary> | ||||
|     public static BoxBorder Heavy { get; } = new HeavyBoxBorder(); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a rounded border. | ||||
|         /// </summary> | ||||
|         public static BoxBorder Rounded { get; } = new RoundedBoxBorder(); | ||||
|     /// <summary> | ||||
|     /// Gets a rounded border. | ||||
|     /// </summary> | ||||
|     public static BoxBorder Rounded { get; } = new RoundedBoxBorder(); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a square border. | ||||
|         /// </summary> | ||||
|         public static BoxBorder Square { get; } = new SquareBoxBorder(); | ||||
|     } | ||||
| } | ||||
|     /// <summary> | ||||
|     /// Gets a square border. | ||||
|     /// </summary> | ||||
|     public static BoxBorder Square { get; } = new SquareBoxBorder(); | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user