Initial commits

This commit is contained in:
Patrik Svensson
2024-08-05 21:20:18 +02:00
commit a3cc9f5f72
110 changed files with 4506 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
using System.ComponentModel;
using Spectre.Console.Cli;
namespace Delegates;
public static partial class Program
{
public sealed class BarSettings : CommandSettings
{
[CommandOption("--count")]
[Description("The number of bars to print")]
[DefaultValue(3)]
public int Count { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
<ExampleName>Delegates</ExampleName>
<ExampleDescription>Demonstrates how to specify commands as delegates.</ExampleDescription>
<ExampleGroup>Cli</ExampleGroup>
<ExampleVisible>false</ExampleVisible>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,61 @@
using System.Threading.Tasks;
using Spectre.Console;
using Spectre.Console.Cli;
namespace Delegates;
public static partial class Program
{
public static int Main(string[] args)
{
var app = new CommandApp();
app.Configure(config =>
{
config.AddDelegate("foo", Foo)
.WithDescription("Foos the bars");
config.AddDelegate<BarSettings>("bar", Bar)
.WithDescription("Bars the foos");
config.AddAsyncDelegate("fooAsync", FooAsync)
.WithDescription("Foos the bars asynchronously");
config.AddAsyncDelegate<BarSettings>("barAsync", BarAsync)
.WithDescription("Bars the foos asynchronously");
});
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");
}
return 0;
}
private static Task<int> FooAsync(CommandContext context)
{
AnsiConsole.WriteLine("Foo");
return Task.FromResult(0);
}
private static Task<int> BarAsync(CommandContext context, BarSettings settings)
{
for (var index = 0; index < settings.Count; index++)
{
AnsiConsole.WriteLine("Bar");
}
return Task.FromResult(0);
}
}

View File

@@ -0,0 +1,46 @@
using System.ComponentModel;
using Demo.Utilities;
using Spectre.Console.Cli;
namespace Demo.Commands.Add;
[Description("Add a NuGet package reference to the project.")]
public sealed class AddPackageCommand : Command<AddPackageCommand.Settings>
{
public sealed class Settings : AddSettings
{
[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("-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("--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("--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;
}
}

View File

@@ -0,0 +1,29 @@
using System.ComponentModel;
using Demo.Utilities;
using Spectre.Console.Cli;
namespace Demo.Commands.Add;
public sealed class AddReferenceCommand : Command<AddReferenceCommand.Settings>
{
public sealed class Settings : AddSettings
{
[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("--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;
}
}

View File

@@ -0,0 +1,11 @@
using System.ComponentModel;
using Spectre.Console.Cli;
namespace Demo.Commands.Add;
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; }
}

View File

@@ -0,0 +1,69 @@
using System.ComponentModel;
using Demo.Utilities;
using Spectre.Console.Cli;
namespace Demo.Commands.Run;
[Description("Build and run a .NET project output.")]
public sealed class RunCommand : Command<RunCommand.Settings>
{
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("-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("-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("--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("--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("--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("--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;
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.ComponentModel;
using Demo.Utilities;
using Spectre.Console.Cli;
namespace Demo.Commands.Serve;
[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
{
[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; }
}
public override int Execute(CommandContext context, Settings settings)
{
if (settings.OpenBrowser.IsSet)
{
var browser = settings.OpenBrowser.Value;
if (browser != null)
{
Console.WriteLine($"Open in {browser}");
}
else
{
Console.WriteLine($"Open in default browser.");
}
}
SettingsDumper.Dump(settings);
return 0;
}
}

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
<ExampleName>Demo</ExampleName>
<ExampleDescription>Demonstrates the most common use cases of Spectre.Cli.</ExampleDescription>
<ExampleGroup>Cli</ExampleGroup>
<ExampleVisible>false</ExampleVisible>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,39 @@
using Demo.Commands;
using Demo.Commands.Add;
using Demo.Commands.Run;
using Demo.Commands.Serve;
using Spectre.Console.Cli;
namespace Demo;
public static class Program
{
public static int Main(string[] args)
{
var app = new CommandApp();
app.Configure(config =>
{
config.SetApplicationName("fake-dotnet");
config.ValidateExamples();
config.AddExample("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");
});
// Serve
config.AddCommand<ServeCommand>("serve")
.WithExample("serve", "-o", "firefox")
.WithExample("serve", "--port", "80", "-o", "firefox");
});
return app.Run(args);
}
}

View File

@@ -0,0 +1,28 @@
using Spectre.Console;
using Spectre.Console.Cli;
namespace Demo.Utilities;
public static class SettingsDumper
{
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 value = property.GetValue(settings)
?.ToString()
?.Replace("[", "[[");
table.AddRow(
property.Name,
value ?? "[grey]null[/]");
}
AnsiConsole.Write(table);
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
namespace Demo;
public enum Verbosity
{
Quiet,
Minimal,
Normal,
Detailed,
Diagnostic
}
public sealed class VerbosityConverter : TypeConverter
{
private readonly Dictionary<string, Verbosity> _lookup;
public VerbosityConverter()
{
_lookup = new Dictionary<string, Verbosity>(StringComparer.OrdinalIgnoreCase)
{
{ "q", Verbosity.Quiet },
{ "quiet", Verbosity.Quiet },
{ "m", Verbosity.Minimal },
{ "minimal", Verbosity.Minimal },
{ "n", Verbosity.Normal },
{ "normal", Verbosity.Normal },
{ "d", Verbosity.Detailed },
{ "detailed", Verbosity.Detailed },
{ "diag", Verbosity.Diagnostic },
{ "diagnostic", Verbosity.Diagnostic }
};
}
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.");
}
}

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
<ExampleName>Dynamic</ExampleName>
<ExampleDescription>Demonstrates how to define dynamic commands.</ExampleDescription>
<ExampleGroup>Cli</ExampleGroup>
<ExampleVisible>false</ExampleVisible>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,20 @@
using System;
using Spectre.Console;
using Spectre.Console.Cli;
namespace Dynamic;
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;
}
}

View File

@@ -0,0 +1,23 @@
using System.Linq;
using Spectre.Console.Cli;
namespace Dynamic;
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);
}
}

View File

@@ -0,0 +1,30 @@
using System.Linq;
using Spectre.Console;
using Spectre.Console.Cli;
using Spectre.Console.Cli.Help;
using Spectre.Console.Rendering;
namespace Help;
/// <summary>
/// Example showing how to extend the built-in Spectre.Console help provider
/// by rendering a custom banner at the top of the help information
/// </summary>
internal class CustomHelpProvider : HelpProvider
{
public CustomHelpProvider(ICommandAppSettings settings)
: base(settings)
{
}
public override IEnumerable<IRenderable> GetHeader(ICommandModel model, ICommandInfo? command)
{
return new[]
{
new Text("--------------------------------------"), Text.NewLine,
new Text("--- CUSTOM HELP PROVIDER ---"), Text.NewLine,
new Text("--------------------------------------"), Text.NewLine,
Text.NewLine,
};
}
}

View File

@@ -0,0 +1,20 @@
using Spectre.Console;
using Spectre.Console.Cli;
namespace Help;
public sealed class DefaultCommand : Command
{
private IAnsiConsole _console;
public DefaultCommand(IAnsiConsole console)
{
_console = console;
}
public override int Execute(CommandContext context)
{
_console.WriteLine("Hello world");
return 0;
}
}

View File

@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<ExampleName>Help</ExampleName>
<ExampleDescription>Demonstrates how to extend the built-in Spectre.Console help provider to render a custom banner at the top of the help information.</ExampleDescription>
<ExampleGroup>Cli</ExampleGroup>
<ExampleVisible>false</ExampleVisible>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,23 @@
using Spectre.Console.Cli;
using Spectre.Console.Cli.Help;
namespace Help;
public static class Program
{
public static int Main(string[] args)
{
var app = new CommandApp<DefaultCommand>();
app.Configure(config =>
{
// Register the custom help provider
config.SetHelpProvider(new CustomHelpProvider(config.Settings));
// Render an unstyled help text for maximum accessibility
config.Settings.HelpProviderStyles = null;
});
return app.Run(args);
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.ComponentModel;
using Spectre.Console.Cli;
namespace Injection.Commands;
public sealed class DefaultCommand : Command<DefaultCommand.Settings>
{
private readonly IGreeter _greeter;
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 override int Execute(CommandContext context, Settings settings)
{
_greeter.Greet(settings.Name);
return 0;
}
}

View File

@@ -0,0 +1,16 @@
using Spectre.Console;
namespace Injection;
public interface IGreeter
{
void Greet(string name);
}
public sealed class HelloWorldGreeter : IGreeter
{
public void Greet(string name)
{
AnsiConsole.WriteLine($"Hello {name}!");
}
}

View File

@@ -0,0 +1,40 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Spectre.Console.Cli;
namespace Injection.Infrastructure;
public sealed class TypeRegistrar : ITypeRegistrar
{
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, (provider) => func());
}
}

View File

@@ -0,0 +1,32 @@
using System;
using Spectre.Console.Cli;
namespace Injection.Infrastructure;
public sealed class TypeResolver : ITypeResolver, IDisposable
{
private readonly IServiceProvider _provider;
public TypeResolver(IServiceProvider provider)
{
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
public object Resolve(Type type)
{
if (type == null)
{
return null;
}
return _provider.GetService(type);
}
public void Dispose()
{
if (_provider is IDisposable disposable)
{
disposable.Dispose();
}
}
}

View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
<ExampleName>Injection</ExampleName>
<ExampleDescription>Demonstrates how to use dependency injection with Spectre.Cli.</ExampleDescription>
<ExampleGroup>Cli</ExampleGroup>
<ExampleVisible>false</ExampleVisible>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,23 @@
using Injection.Commands;
using Injection.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Spectre.Console.Cli;
namespace Injection;
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);
}
}

View File

@@ -0,0 +1,34 @@
using Microsoft.Extensions.Logging;
using Spectre.Console;
using Spectre.Console.Cli;
namespace Logging.Commands;
public class HelloCommand : Command<HelloCommand.Settings>
{
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;
}
}

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using Serilog.Events;
using Spectre.Console.Cli;
namespace Logging.Commands;
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()
{
_lookup = new Dictionary<string, LogEventLevel>(StringComparer.OrdinalIgnoreCase)
{
{"d", LogEventLevel.Debug},
{"v", LogEventLevel.Verbose},
{"i", LogEventLevel.Information},
{"w", LogEventLevel.Warning},
{"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.");
}
}

View File

@@ -0,0 +1,19 @@
using Logging.Commands;
using Serilog.Core;
using Spectre.Console.Cli;
namespace Logging.Infrastructure;
public class LogInterceptor : ICommandInterceptor
{
public static readonly LoggingLevelSwitch LogLevel = new();
public void Intercept(CommandContext context, CommandSettings settings)
{
if (settings is LogCommandSettings logSettings)
{
LoggingEnricher.Path = logSettings.LogFile ?? "application.log";
LogLevel.MinimumLevel = logSettings.LogLevel;
}
}
}

View File

@@ -0,0 +1,37 @@
using Serilog.Core;
using Serilog.Events;
namespace Logging.Infrastructure;
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)
{
// 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);
}
}

View File

@@ -0,0 +1,40 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Spectre.Console.Cli;
namespace Logging.Infrastructure;
public sealed class TypeRegistrar : ITypeRegistrar
{
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());
}
}

View File

@@ -0,0 +1,24 @@
using System;
using Spectre.Console.Cli;
namespace Logging.Infrastructure;
public sealed class TypeResolver : ITypeResolver
{
private readonly IServiceProvider _provider;
public TypeResolver(IServiceProvider provider)
{
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
public object Resolve(Type type)
{
if (type == null)
{
return null;
}
return _provider.GetService(type);
}
}

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
<ExampleName>Logging</ExampleName>
<ExampleDescription>Demonstrates how to dynamically configure Serilog for logging using parameters from a command.</ExampleDescription>
<ExampleGroup>Cli</ExampleGroup>
<ExampleVisible>false</ExampleVisible>
<Nullable>disable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Serilog" Version="4.0.1" />
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.Map" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,54 @@
using Logging.Commands;
using Logging.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Spectre.Console.Cli;
/*
* Dynamically control serilog configuration via command line parameters
*
* This works around the chicken and egg situation with configuring serilog via the command line.
* The logger needs to be configured prior to executing the parser, but the logger needs the parsed values
* to be configured. By using serilog.sinks.map we can defer configuration. We use a LogLevelSwitch to control the
* logging levels dynamically, and then we use a serilog enricher that has its state populated via a
* Spectre.Console CommandInterceptor
*/
namespace Logging;
public class Program
{
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 =>
{
config.SetInterceptor(new LogInterceptor()); // add the interceptor
config.AddCommand<HelloCommand>("hello");
});
return app.Run(args);
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Screens</ExampleTitle>
<ExampleDescription>Demonstrates how to use alternate screens.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,26 @@
// Check if we can use alternate screen buffers
using Spectre.Console;
if (!AnsiConsole.Profile.Capabilities.AlternateBuffer)
{
AnsiConsole.MarkupLine(
"[red]Alternate screen buffers are not supported " +
"by your terminal[/] [yellow]:([/]");
return;
}
// Write to the terminal
AnsiConsole.Write(new Rule("[yellow]Normal universe[/]"));
AnsiConsole.Write(new Panel("Hello World!"));
AnsiConsole.MarkupLine("[grey]Press a key to continue[/]");
AnsiConsole.Console.Input.ReadKey(true);
AnsiConsole.AlternateScreen(() =>
{
// Now we're in another terminal screen buffer
AnsiConsole.Write(new Rule("[red]Mirror universe[/]"));
AnsiConsole.Write(new Panel("[red]Welcome to the upside down![/]"));
AnsiConsole.MarkupLine("[grey]Press a key to return[/]");
AnsiConsole.Console.Input.ReadKey(true);
});

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Borders</ExampleTitle>
<ExampleDescription>Demonstrates the different kind of borders.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,86 @@
using Spectre.Console;
using Spectre.Console.Rendering;
namespace Borders;
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"));
}
var items = new[]
{
CreatePanel("Ascii", BoxBorder.Ascii),
CreatePanel("Square", BoxBorder.Square),
CreatePanel("Rounded", BoxBorder.Rounded),
CreatePanel("Heavy", BoxBorder.Heavy),
CreatePanel("Double", BoxBorder.Double),
CreatePanel("None", BoxBorder.None),
};
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.ShowRowSeparators();
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)
.PadBottom(1)
.NoBorder();
}
var items = new[]
{
CreateTable("Ascii", TableBorder.Ascii), CreateTable("Ascii2", TableBorder.Ascii2),
CreateTable("AsciiDoubleHead", TableBorder.AsciiDoubleHead),
CreateTable("Horizontal", TableBorder.Horizontal), CreateTable("Simple", TableBorder.Simple),
CreateTable("SimpleHeavy", TableBorder.SimpleHeavy), CreateTable("Minimal", TableBorder.Minimal),
CreateTable("MinimalHeavyHead", TableBorder.MinimalHeavyHead),
CreateTable("MinimalDoubleHead", TableBorder.MinimalDoubleHead),
CreateTable("Square", TableBorder.Square), CreateTable("Rounded", TableBorder.Rounded),
CreateTable("Heavy", TableBorder.Heavy), CreateTable("HeavyEdge", TableBorder.HeavyEdge),
CreateTable("HeavyHead", TableBorder.HeavyHead), CreateTable("Double", TableBorder.Double),
CreateTable("DoubleEdge", TableBorder.DoubleEdge), CreateTable("Markdown", TableBorder.Markdown),
};
AnsiConsole.Write(new Columns(items).Collapse());
}
private static void HorizontalRule(string title)
{
AnsiConsole.WriteLine();
AnsiConsole.Write(new Rule($"[white bold]{title}[/]").RuleStyle("grey").LeftJustified());
AnsiConsole.WriteLine();
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Calendars</ExampleTitle>
<ExampleDescription>Demonstrates how to render calendars.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,18 @@
using Spectre.Console;
namespace Calendars;
public static class Program
{
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));
}
}

View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Canvas</ExampleTitle>
<ExampleDescription>Demonstrates how to render pixels and images.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="cake.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,43 @@
using System.Diagnostics;
using System.Reflection;
using SixLabors.ImageSharp.Processing;
using Spectre.Console;
using Spectre.Console.Rendering;
namespace Canvas;
public static class Program
{
public static void Main()
{
// 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 max 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}[/]").LeftJustified().RuleStyle("grey"));
AnsiConsole.WriteLine();
AnsiConsole.Write(canvas);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Charts</ExampleTitle>
<ExampleDescription>Demonstrates how to render charts in a console.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,42 @@
using Spectre.Console;
using Spectre.Console.Rendering;
namespace Charts;
public static class Program
{
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 breakdown chart
AnsiConsole.WriteLine();
Render("Languages used", new BreakdownChart()
.FullSize()
.Width(60)
.ShowPercentage()
.WithValueColor(Color.Orange1)
.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));
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Colors</ExampleTitle>
<ExampleDescription>Demonstrates how to use [yellow]c[/][red]o[/][green]l[/][blue]o[/][aqua]r[/][lime]s[/] in the console.</ExampleDescription>
<ExampleGroup>Misc</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,105 @@
using Spectre.Console;
using Spectre.Console.Examples;
namespace Colors;
public static class Program
{
public static void Main()
{
/////////////////////////////////////////////////////////////////
// No colors
/////////////////////////////////////////////////////////////////
if (AnsiConsole.Profile.Capabilities.ColorSystem == ColorSystem.NoColors)
{
AnsiConsole.WriteLine("No colors are supported.");
return;
}
/////////////////////////////////////////////////////////////////
// 3-BIT
/////////////////////////////////////////////////////////////////
if (AnsiConsole.Profile.Supports(ColorSystem.Legacy))
{
AnsiConsole.ResetColors();
AnsiConsole.WriteLine();
AnsiConsole.Write(new Rule("[yellow bold underline]3-bit Colors[/]").RuleStyle("grey").LeftJustified());
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();
if ((i + 1) % 8 == 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").LeftJustified());
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").LeftJustified());
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").LeftJustified());
AnsiConsole.WriteLine();
AnsiConsole.Write(new ColorBox(width: 80, height: 15));
}
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Columns</ExampleTitle>
<ExampleDescription>Demonstrates how to render data into columns.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using Spectre.Console;
namespace Columns;
public static class Program
{
public static void Main()
{
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 Spectre.Console.Columns(cards));
}
private static string GetCardContent(User user)
{
var name = $"{user.FirstName} {user.LastName}";
var city = $"{user.City}";
return $"[b]{name}[/]\n[yellow]{city}[/]";
}
}

View File

@@ -0,0 +1,88 @@
using System.Collections.Generic;
namespace Columns;
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
{
FirstName = "Andrea",
LastName = "Johansen",
City = "Hornbæk",
Country = "Denmark",
},
new User
{
FirstName = "Phil",
LastName = "Scott",
City = "Dayton",
Country = "United States",
},
new User
{
FirstName = "Patrik",
LastName = "Svensson",
City = "Stockholm",
Country = "Sweden",
},
new User
{
FirstName = "Freya",
LastName = "Thompson",
City = "Rotorua",
Country = "New Zealand",
},
new User
{
FirstName = "طاها",
LastName = "رضایی",
City = "اهواز",
Country = "Iran",
},
new User
{
FirstName = "Yara",
LastName = "Simon",
City = "Develier",
Country = "Switzerland",
},
new User
{
FirstName = "Giray",
LastName = "Erbay",
City = "Karabük",
Country = "Turkey",
},
new User
{
FirstName = "Miodrag",
LastName = "Schaffer",
City = "Möckern",
Country = "Germany",
},
new User
{
FirstName = "Carmela",
LastName = "Lo Castro",
City = "Firenze",
Country = "Italy",
},
new User
{
FirstName = "Roberto",
LastName = "Sims",
City = "Mallow",
Country = "Ireland",
},
};
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Cursor</ExampleTitle>
<ExampleDescription>Demonstrates how to move the cursor.</ExampleDescription>
<ExampleGroup>Misc</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,19 @@
using Spectre.Console;
namespace Cursor;
public static class Program
{
public static void Main(string[] args)
{
AnsiConsole.Write("Hello");
// 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");
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Decorations</ExampleTitle>
<ExampleDescription>Demonstrates how to [italic]use[/] [bold]decorations[/] [dim]in[/] the console.</ExampleDescription>
<ExampleGroup>Misc</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,29 @@
using Spectre.Console;
namespace Colors;
public static class Program
{
public static void Main()
{
AnsiConsole.ResetDecoration();
AnsiConsole.WriteLine();
if (AnsiConsole.Profile.Capabilities.Ansi)
{
AnsiConsole.Write(new Rule("[bold green]ANSI Decorations[/]"));
}
else
{
AnsiConsole.Write(new Rule("[bold red]Legacy Decorations (unsupported)[/]"));
}
var decorations = System.Enum.GetValues(typeof(Decoration));
foreach (var decoration in decorations)
{
var name = System.Enum.GetName(typeof(Decoration),decoration);
AnsiConsole.Write(name + ": ");
AnsiConsole.Write(new Markup(name+"\n", new Style(decoration: (Decoration)decoration)));
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Emojis</ExampleTitle>
<ExampleDescription>Demonstrates how to render emojis.</ExampleDescription>
<ExampleGroup>Misc</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,23 @@
using Spectre.Console;
namespace Emojis;
public static class Program
{
public static void Main(string[] args)
{
// Show a known emoji
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());
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Exceptions</ExampleTitle>
<ExampleDescription>Demonstrates how to render formatted exceptions.</ExampleDescription>
<ExampleGroup>Misc</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Authentication;
using System.Threading.Tasks;
using Spectre.Console;
namespace Exceptions;
public static class Program
{
public static async Task Main(string[] args)
{
try
{
var foo = new List<string>();
DoMagic(42, null, ref foo);
}
catch (Exception ex)
{
AnsiConsole.WriteLine();
AnsiConsole.Write(new Rule("Default").LeftJustified());
AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex);
AnsiConsole.WriteLine();
AnsiConsole.Write(new Rule("Compact").LeftJustified());
AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks);
AnsiConsole.WriteLine();
AnsiConsole.Write(new Rule("Compact + Custom colors").LeftJustified());
AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex, new ExceptionSettings
{
Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks,
Style = new ExceptionStyle
{
Exception = new Style().Foreground(Color.Grey),
Message = new Style().Foreground(Color.White),
NonEmphasized = new Style().Foreground(Color.Cornsilk1),
Parenthesis = new Style().Foreground(Color.Cornsilk1),
Method = new Style().Foreground(Color.Red),
ParameterName = new Style().Foreground(Color.Cornsilk1),
ParameterType = new Style().Foreground(Color.Red),
Path = new Style().Foreground(Color.Red),
LineNumber = new Style().Foreground(Color.Cornsilk1),
}
});
}
try
{
await DoMagicAsync<int>(42, null);
}
catch (Exception ex)
{
AnsiConsole.WriteLine();
AnsiConsole.Write(new Rule("Async").LeftJustified());
AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenPaths);
}
}
private static void DoMagic(int foo, string[,] bar, ref List<string> result)
{
try
{
CheckCredentials(foo, bar);
result = new List<string>();
}
catch (Exception ex)
{
throw new InvalidOperationException("Whaaat?", ex);
}
}
private static bool CheckCredentials(int? qux, string[,] corgi)
{
throw new InvalidCredentialException("The credentials are invalid.");
}
private static async Task DoMagicAsync<T>(T foo, string[,] bar)
{
try
{
await CheckCredentialsAsync(new[] { foo }.ToList(), new []{ foo }, bar);
}
catch (Exception ex)
{
throw new InvalidOperationException("Whaaat?", ex);
}
}
private static async Task<bool> CheckCredentialsAsync<T>(List<T> qux, T[] otherArray, string[,] corgi)
{
await Task.Delay(0);
throw new InvalidCredentialException("The credentials are invalid.");
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Figlet</ExampleTitle>
<ExampleDescription>Demonstrates how to render FIGlet text.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,13 @@
using Spectre.Console;
namespace Figlet;
public static class Program
{
public static void Main(string[] args)
{
AnsiConsole.Write(new FigletText("Left aligned").LeftJustified().Color(Color.Red));
AnsiConsole.Write(new FigletText("Centered").Centered().Color(Color.Green));
AnsiConsole.Write(new FigletText("Right aligned").RightJustified().Color(Color.Blue));
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Grids</ExampleTitle>
<ExampleDescription>Demonstrates how to render grids in a console.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,23 @@
using Spectre.Console;
namespace Grids;
public static class Program
{
public static void Main()
{
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.");
AnsiConsole.Write(grid);
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Info</ExampleTitle>
<ExampleDescription>Displays the capabilities of the current console.</ExampleDescription>
<ExampleGroup>Misc</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,33 @@
using Spectre.Console;
namespace Info;
public static class Program
{
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}");
AnsiConsole.Write(
new Panel(grid)
.Header("Information"));
}
private static string YesNo(bool value)
{
return value ? "Yes" : "No";
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Json</ExampleTitle>
<ExampleDescription>Demonstrates how to print syntax highlighted JSON.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,36 @@
using Spectre.Console;
using Spectre.Console.Json;
namespace Json;
public static class Program
{
public static void Main()
{
var json = new JsonText(
"""
{
"hello": 32,
"world": {
"foo": 21,
"bar": 255,
"baz": [
0.32, 0.33e-32,
0.42e32, 0.55e+32,
{
"hello": "world",
"lol": null
}
]
}
}
""");
AnsiConsole.Write(
new Panel(json)
.Header("Some JSON in a panel")
.Collapse()
.RoundedBorder()
.BorderColor(Color.Yellow));
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Layout</ExampleTitle>
<ExampleDescription>Demonstrates how to use layouts.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,60 @@
using System;
using Spectre.Console;
namespace Layouts;
public static class Program
{
public static void Main()
{
var layout = CreateLayout();
AnsiConsole.Write(layout);
Console.ReadKey(true);
}
private static Layout CreateLayout()
{
var layout = new Layout();
layout.SplitRows(
new Layout("Top")
.SplitColumns(
new Layout("Left")
.SplitRows(
new Layout("LeftTop"),
new Layout("LeftBottom")),
new Layout("Right").Ratio(2),
new Layout("RightRight").Size(3)),
new Layout("Bottom"));
layout["LeftBottom"].Update(
new Panel("[blink]PRESS ANY KEY TO QUIT[/]")
.Expand()
.BorderColor(Color.Yellow)
.Padding(0, 0));
layout["Right"].Update(
new Panel(
new Table()
.AddColumns("[blue]Qux[/]", "[green]Corgi[/]")
.AddRow("9", "8")
.AddRow("7", "6")
.Expand())
.Header("A [yellow]Table[/] in a [blue]Panel[/] (Ratio=2)")
.Expand());
layout["RightRight"].Update(
new Panel("Explicit-size-is-[yellow]3[/]")
.BorderColor(Color.Yellow)
.Padding(0, 0));
layout["Bottom"].Update(
new Panel(
new FigletText("Hello World"))
.Header("Some [green]Figlet[/] text")
.Expand());
return layout;
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Links</ExampleTitle>
<ExampleDescription>Demonstrates how to render links in a console.</ExampleDescription>
<ExampleGroup>Misc</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,20 @@
using Spectre.Console;
namespace Links;
public static class Program
{
public static void Main()
{
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]┻━┻[/]");
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Live</ExampleTitle>
<ExampleDescription>Demonstrates how to do live updates.</ExampleDescription>
<ExampleGroup>Live</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,81 @@
using System;
using System.Threading;
using Spectre.Console;
namespace Live;
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)
{
action();
ctx.Refresh();
Thread.Sleep(delay);
}
// Columns
Update(230, () => table.AddColumn("Release date"));
Update(230, () => table.AddColumn("Title"));
Update(230, () => table.AddColumn("Budget"));
Update(230, () => table.AddColumn("Opening Weekend"));
Update(230, () => table.AddColumn("Box office"));
// Rows
Update(70, () => table.AddRow("May 25, 1977", "[yellow]Star Wars[/] [grey]Ep.[/] [u]IV[/]", "$11,000,000", "$1,554,475", "$775,398,007"));
Update(70, () => table.AddRow("May 21, 1980", "[yellow]Star Wars[/] [grey]Ep.[/] [u]V[/]", "$18,000,000", "$4,910,483", "$547,969,004"));
Update(70, () => table.AddRow("May 25, 1983", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VI[/]", "$32,500,000", "$23,019,618", "$475,106,177"));
Update(70, () => table.AddRow("May 19, 1999", "[yellow]Star Wars[/] [grey]Ep.[/] [u]I[/]", "$115,000,000", "$64,810,870", "$1,027,044,677"));
Update(70, () => table.AddRow("May 16, 2002", "[yellow]Star Wars[/] [grey]Ep.[/] [u]II[/]", "$115,000,000", "$80,027,814", "$649,436,358"));
Update(70, () => table.AddRow("May 19, 2005", "[yellow]Star Wars[/] [grey]Ep.[/] [u]III[/]", "$113,000,000", "$108,435,841", "$850,035,635"));
Update(70, () => table.AddRow("Dec 18, 2015", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VII[/]", "$245,000,000", "$247,966,675", "$2,068,223,624"));
Update(70, () => table.AddRow("Dec 15, 2017", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VIII[/]", "$317,000,000", "$220,009,584", "$1,333,539,889"));
Update(70, () => table.AddRow("Dec 20, 2019", "[yellow]Star Wars[/] [grey]Ep.[/] [u]IX[/]", "$245,000,000", "$177,383,864", "$1,074,114,248"));
// Column footer
Update(230, () => table.Columns[2].Footer("$1,633,000,000"));
Update(230, () => table.Columns[3].Footer("$928,119,224"));
Update(400, () => table.Columns[4].Footer("$10,318,030,576"));
// Column alignment
Update(230, () => table.Columns[2].RightAligned());
Update(230, () => table.Columns[3].RightAligned());
Update(400, () => table.Columns[4].RightAligned());
// Column titles
Update(70, () => table.Columns[0].Header("[bold]Release date[/]"));
Update(70, () => table.Columns[1].Header("[bold]Title[/]"));
Update(70, () => table.Columns[2].Header("[red bold]Budget[/]"));
Update(70, () => table.Columns[3].Header("[green bold]Opening Weekend[/]"));
Update(400, () => table.Columns[4].Header("[blue bold]Box office[/]"));
// Footers
Update(70, () => table.Columns[2].Footer("[red bold]$1,633,000,000[/]"));
Update(70, () => table.Columns[3].Footer("[green bold]$928,119,224[/]"));
Update(400, () => table.Columns[4].Footer("[blue bold]$10,318,030,576[/]"));
// Title
Update(500, () => table.Title("Star Wars Movies"));
Update(400, () => table.Title("[[ [yellow]Star Wars Movies[/] ]]"));
// Borders
Update(230, () => table.BorderColor(Color.Yellow));
Update(230, () => table.MinimalBorder());
Update(230, () => table.SimpleBorder());
Update(230, () => table.SimpleHeavyBorder());
// Caption
Update(400, () => table.Caption("[[ [blue]THE END[/] ]]"));
});
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>LiveTable</ExampleTitle>
<ExampleDescription>Demonstrates how to do live updates in a table.</ExampleDescription>
<ExampleGroup>Live</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,86 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Spectre.Console;
namespace LiveTable;
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",
"HKD", "CAD", "INR",
"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[/]");
AnsiConsole.MarkupLine("Press [yellow]CTRL+C[/] to exit");
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);
}
// 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);
}
});
}
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)
{
dest = _exchanges[_random.Next(0, _exchanges.Length)];
}
return (source, dest, rate);
}
}

View File

@@ -0,0 +1,2 @@
global using Spectre.Console;
global using static Spectre.Console.AnsiConsole;

View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<ExampleTitle>Minimal</ExampleTitle>
<ExampleDescription>Demonstrates a minimal console application.</ExampleDescription>
<ExampleGroup>Live</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,12 @@
// Write a markup line to the console
MarkupLine("[yellow]Hello[/], [blue]World[/]!");
// Write text to the console
WriteLine("Hello, World!");
// Write a table to the console
Write(new Table()
.RoundedBorder()
.AddColumns("[red]Greeting[/]", "[red]Subject[/]")
.AddRow("[yellow]Hello[/]", "World")
.AddRow("[green]Oh hi[/]", "[blue u]Mark[/]"));

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Panels</ExampleTitle>
<ExampleDescription>Demonstrates how to render items in panels.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,41 @@
using Spectre.Console;
namespace Panels;
public static class Program
{
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();
AnsiConsole.Write(
new Panel(
new Panel(content)
.Border(BoxBorder.Rounded)));
// Left adjusted panel with text
AnsiConsole.Write(
new Panel(new Text("Left adjusted\nLeft").LeftJustified())
.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));
// Right adjusted, rounded panel with text
AnsiConsole.Write(
new Panel(new Text("Right adjusted\nRight").RightJustified())
.Expand()
.RoundedBorder()
.Header("[blue]Right[/]")
.HeaderAlignment(Justify.Right));
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Paths</ExampleTitle>
<ExampleDescription>Demonstrates how to render paths.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,67 @@
using System;
using System.Threading;
using Spectre.Console;
namespace Paths;
public static class Program
{
public static void Main()
{
var windowsPath = @"C:\This is\A\Super Long\Windows\Path\That\Goes\On And On\And\Never\Seems\To\Stop\But\At\Some\Point\It\Must\I\Guess.txt";
var unixPath = @"//This is/A/Super Long/Unix/Path/That/Goes/On And On/And/Never/Seems/To/Stop/But/At/Some/Point/It/Must/I/Guess.txt";
AnsiConsole.WriteLine();
WritePlain(windowsPath, unixPath);
AnsiConsole.WriteLine();
WriteColorized(windowsPath, unixPath);
AnsiConsole.WriteLine();
WriteAligned(windowsPath);
}
private static void WritePlain(string windowsPath, string unixPath)
{
var table = new Table().BorderColor(Color.Grey).Title("Plain").RoundedBorder();
table.AddColumns("[grey]OS[/]", "[grey]Path[/]");
table.AddRow(new Text("Windows"), new TextPath(windowsPath));
table.AddRow(new Text("Unix"), new TextPath(unixPath));
AnsiConsole.Write(table);
}
private static void WriteColorized(string windowsPath, string unixPath)
{
var table = new Table().BorderColor(Color.Grey).Title("Colorized").RoundedBorder();
table.AddColumns("[grey]OS[/]", "[grey]Path[/]");
table.AddRow(new Text("Windows"),
new TextPath(windowsPath)
.RootColor(Color.Blue)
.SeparatorColor(Color.Yellow)
.StemColor(Color.Red)
.LeafColor(Color.Green));
table.AddRow(new Text("Unix"),
new TextPath(unixPath)
.RootColor(Color.Blue)
.SeparatorColor(Color.Yellow)
.StemColor(Color.Red)
.LeafColor(Color.Green));
AnsiConsole.Write(table);
}
private static void WriteAligned(string path)
{
var table = new Table().BorderColor(Color.Grey).Title("Aligned").RoundedBorder();
table.AddColumns("[grey]Alignment[/]", "[grey]Path[/]");
table.AddRow(new Text("Left"), new TextPath(path).LeftJustified());
table.AddRow(new Text("Center"), new TextPath(path).Centered());
table.AddRow(new Text("Right"), new TextPath(path).RightJustified());
AnsiConsole.Write(table);
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
namespace Progress;
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()
{
_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))
{
_used.Add(name);
return true;
}
iterations++;
}
name = Generate();
return false;
}
public static string Generate()
{
return _verbs[_random.Next(0, _verbs.Length)]
+ " " + _nouns[_random.Next(0, _nouns.Length)];
}
}

View File

@@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Spectre.Console;
using Spectre.Console.Rendering;
namespace Progress;
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
})
.UseRenderHook((renderable, tasks) => RenderHook(tasks, renderable))
.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();
// 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);
}
// Write some random things to the terminal
if (random.NextDouble() < 0.1)
{
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());
// Simulate some delay
Thread.Sleep(100);
}
});
// Done
AnsiConsole.MarkupLine("[green]Done![/]");
}
private static IRenderable RenderHook(IReadOnlyList<ProgressTask> tasks, IRenderable renderable)
{
var header = new Panel("Going on a :rocket:, we're going to the :crescent_moon:").Expand().RoundedBorder();
var footer = new Rows(
new Rule(),
new Markup(
$"[blue]{tasks.Count}[/] total tasks. [green]{tasks.Count(i => i.IsFinished)}[/] complete.")
);
const string ESC = "\u001b";
string escapeSequence;
if (tasks.All(i => i.IsFinished))
{
escapeSequence = $"{ESC}]]9;4;0;100{ESC}\\";
}
else
{
var total = tasks.Sum(i => i.MaxValue);
var done = tasks.Sum(i => i.Value);
var percent = (int)(done / total * 100);
escapeSequence = $"{ESC}]]9;4;1;{percent}{ESC}\\";
}
var middleContent = new Grid().AddColumns(new GridColumn(), new GridColumn().Width(20));
middleContent.AddRow(renderable, new FigletText(tasks.Count(i => i.IsFinished == false).ToString()));
return new Rows(header, middleContent, footer, new ControlCode(escapeSequence));
}
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;
}
private static void WriteLogMessage()
{
AnsiConsole.MarkupLine(
"[grey]LOG:[/] " +
DescriptionGenerator.Generate() +
"[grey]...[/]");
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Progress</ExampleTitle>
<ExampleDescription>Demonstrates how to show progress bars.</ExampleDescription>
<ExampleGroup>Status</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,182 @@
using Spectre.Console;
namespace Prompt
{
public static class Program
{
public static void Main(string[] args)
{
// Check if we can accept key strokes
if (!AnsiConsole.Profile.Capabilities.Interactive)
{
AnsiConsole.MarkupLine("[red]Environment does not support interaction.[/]");
return;
}
// Confirmation
if (!AskConfirmation())
{
return;
}
// Ask the user for some different things
WriteDivider("Strings");
var name = AskName();
WriteDivider("Lists");
var fruit = AskFruit();
WriteDivider("Choices");
var sport = AskSport();
WriteDivider("Integers");
var age = AskAge();
WriteDivider("Secrets");
var password = AskPassword();
WriteDivider("Mask");
var mask = AskPasswordWithCustomMask();
WriteDivider("Null Mask");
var nullMask = AskPasswordWithNullMask();
WriteDivider("Optional");
var color = AskColor();
// Summary
AnsiConsole.WriteLine();
AnsiConsole.Write(new Rule("[yellow]Results[/]").RuleStyle("grey").LeftJustified());
AnsiConsole.Write(new Table().AddColumns("[grey]Question[/]", "[grey]Answer[/]")
.RoundedBorder()
.BorderColor(Color.Grey)
.AddRow("[grey]Name[/]", name)
.AddRow("[grey]Favorite fruit[/]", fruit)
.AddRow("[grey]Favorite sport[/]", sport)
.AddRow("[grey]Age[/]", age.ToString())
.AddRow("[grey]Password[/]", password)
.AddRow("[grey]Mask[/]", mask)
.AddRow("[grey]Null Mask[/]", nullMask)
.AddRow("[grey]Favorite color[/]", string.IsNullOrEmpty(color) ? "Unknown" : color));
}
private static void WriteDivider(string text)
{
AnsiConsole.WriteLine();
AnsiConsole.Write(new Rule($"[yellow]{text}[/]").RuleStyle("grey").LeftJustified());
}
public static bool AskConfirmation()
{
if (!AnsiConsole.Confirm("Run prompt example?"))
{
AnsiConsole.MarkupLine("Ok... :(");
return false;
}
return true;
}
public static string AskName()
{
var name = AnsiConsole.Ask<string>("What's your [green]name[/]?");
return name;
}
public static string AskFruit()
{
var favorites = AnsiConsole.Prompt(
new MultiSelectionPrompt<string>()
.PageSize(10)
.Title("What are your [green]favorite fruits[/]?")
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
.InstructionsText("[grey](Press [blue]<space>[/] to toggle a fruit, [green]<enter>[/] to accept)[/]")
.AddChoiceGroup("Berries", new[]
{
"Blackcurrant", "Blueberry", "Cloudberry",
"Elderberry", "Honeyberry", "Mulberry"
})
.AddChoices(new[]
{
"Apple", "Apricot", "Avocado", "Banana",
"Cherry", "Cocunut", "Date", "Dragonfruit", "Durian",
"Egg plant", "Fig", "Grape", "Guava",
"Jackfruit", "Jambul", "Kiwano", "Kiwifruit", "Lime", "Lylo",
"Lychee", "Melon", "Nectarine", "Orange", "Olive"
}));
var fruit = favorites.Count == 1 ? favorites[0] : null;
if (string.IsNullOrWhiteSpace(fruit))
{
fruit = AnsiConsole.Prompt(
new SelectionPrompt<string>()
.EnableSearch()
.Title("Ok, but if you could only choose [green]one[/]?")
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
.AddChoices(favorites));
}
AnsiConsole.MarkupLine("You selected: [yellow]{0}[/]", fruit);
return fruit;
}
public static string AskSport()
{
return AnsiConsole.Prompt(
new TextPrompt<string>("What's your [green]favorite sport[/]?")
.InvalidChoiceMessage("[red]That's not a sport![/]")
.DefaultValue("Sport?")
.AddChoice("Soccer")
.AddChoice("Hockey")
.AddChoice("Basketball"));
}
public static int AskAge()
{
return AnsiConsole.Prompt(
new TextPrompt<int>("How [green]old[/] are you?")
.PromptStyle("green")
.ValidationErrorMessage("[red]That's not a valid age[/]")
.Validate(age =>
{
return age switch
{
<= 0 => ValidationResult.Error("[red]You must at least be 1 years old[/]"),
>= 123 => ValidationResult.Error("[red]You must be younger than the oldest person alive[/]"),
_ => ValidationResult.Success(),
};
}));
}
public static string AskPassword()
{
return AnsiConsole.Prompt(
new TextPrompt<string>("Enter [green]password[/]?")
.PromptStyle("red")
.Secret());
}
public static string AskPasswordWithCustomMask()
{
return AnsiConsole.Prompt(
new TextPrompt<string>("Enter [green]password[/]?")
.PromptStyle("red")
.Secret('-'));
}
public static string AskPasswordWithNullMask()
{
return AnsiConsole.Prompt(
new TextPrompt<string>("Enter [green]password[/]?")
.PromptStyle("red")
.Secret(null));
}
public static string AskColor()
{
return AnsiConsole.Prompt(
new TextPrompt<string>("[grey][[Optional]][/] What is your [green]favorite color[/]?")
.AllowEmpty());
}
}
}

View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>9</LangVersion>
<ExampleTitle>Prompt</ExampleTitle>
<ExampleDescription>Demonstrates how to get input from a user.</ExampleDescription>
<ExampleGroup>Misc</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,42 @@
using Spectre.Console;
namespace Rules;
public static class Program
{
public static void Main(string[] args)
{
// No title
Render(
new Rule()
.RuleStyle(Style.Parse("yellow"))
.AsciiBorder()
.LeftJustified());
// Left aligned title
Render(
new Rule("[blue]Left aligned[/]")
.RuleStyle(Style.Parse("red"))
.DoubleBorder()
.LeftJustified());
// 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"))
.RightJustified());
}
private static void Render(Rule rule)
{
AnsiConsole.Write(rule);
AnsiConsole.WriteLine();
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Rules</ExampleTitle>
<ExampleDescription>Demonstrates how to render horizontal rules (lines).</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,29 @@
using System;
namespace Showcase;
public static class ExceptionGenerator
{
public static Exception GenerateException()
{
try
{
SomeOperation();
throw new InvalidOperationException();
}
catch (Exception ex)
{
return ex;
}
}
private static void SomeOperation()
{
SomeOperationGoingWrong();
}
private static void SomeOperationGoingWrong()
{
throw new InvalidOperationException("Something went very wrong!");
}
}

View File

@@ -0,0 +1,154 @@
using Spectre.Console;
using Spectre.Console.Examples;
using Spectre.Console.Rendering;
namespace Showcase;
public static partial class Program
{
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();
// 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(
"[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[/]."));
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:");
// 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)));
// 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();
// 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));
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 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);
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 GetBreakdownChart()
{
return new BreakdownChart()
.ShowPercentage()
.FullSize()
.AddItem("C#", 82, Color.Green)
.AddItem("PowerShell", 13, Color.Red)
.AddItem("Bash", 5, Color.Blue);
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Showcase</ExampleTitle>
<ExampleDescription>Demonstration of Spectre.Console.</ExampleDescription>
<ExampleGroup>Misc</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,69 @@
using System.Threading;
using Spectre.Console;
namespace Status;
public static class Program
{
public static void Main()
{
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");
// Warp nacelles
Thread.Sleep(3000);
ctx.Spinner(Spinner.Known.BouncingBar);
ctx.Status("[bold blue]Unfolding warp nacelles[/]");
WriteLogMessage("Unfolding left warp nacelle");
Thread.Sleep(2000);
WriteLogMessage("Left warp nacelle [green]online[/]");
WriteLogMessage("Unfolding right warp nacelle");
Thread.Sleep(1000);
WriteLogMessage("Right warp nacelle [green]online[/]");
// Warp bubble
Thread.Sleep(3000);
ctx.Spinner(Spinner.Known.Star2);
ctx.Status("[bold blue]Generating warp bubble[/]");
Thread.Sleep(3000);
ctx.Spinner(Spinner.Known.Star);
ctx.Status("[bold blue]Stabilizing warp bubble[/]");
// Safety
ctx.Spinner(Spinner.Known.Monkey);
ctx.Status("[bold blue]Performing safety checks[/]");
WriteLogMessage("Enabling interior dampening");
Thread.Sleep(2000);
WriteLogMessage("Interior dampening [green]enabled[/]");
// Warp!
Thread.Sleep(3000);
ctx.Spinner(Spinner.Known.Moon);
WriteLogMessage("Preparing for warp");
Thread.Sleep(1000);
for (var warp = 1; warp < 10; warp++)
{
ctx.Status($"[bold blue]Warp {warp}[/]");
Thread.Sleep(500);
}
});
// Done
AnsiConsole.MarkupLine("[bold green]Crusing at Warp 9.8[/]");
}
private static void WriteLogMessage(string message)
{
AnsiConsole.MarkupLine($"[grey]LOG:[/] {message}[grey]...[/]");
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Status</ExampleTitle>
<ExampleDescription>Demonstrates how to show status updates.</ExampleDescription>
<ExampleGroup>Status</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,46 @@
using Spectre.Console;
namespace Tables;
public static class Program
{
public static void Main()
{
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![/]", "");
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);
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Tables</ExampleTitle>
<ExampleDescription>Demonstrates how to render tables in a console.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,44 @@
using Spectre.Console;
namespace Trees;
public static class Program
{
public static void Main()
{
AnsiConsole.WriteLine();
// 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);
// 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");
var bar = tree.AddNode("[yellow]Bar[/]");
bar.AddNode(new Calendar(2020, 12)
.AddCalendarEvent(2020, 12, 12)
.HideHeader());
// Return the tree
return tree;
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ExampleTitle>Trees</ExampleTitle>
<ExampleDescription>Demonstrates how to render trees in a console.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,5 @@
<Project>
<PropertyGroup Label="Settings">
<IsPackable>false</IsPackable>
</PropertyGroup>
</Project>

540
examples/Examples.sln Normal file
View File

@@ -0,0 +1,540 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{2571F1BD-6556-4F96-B27B-B6190E1BF13A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cli", "Cli", "{4682E9B7-B54C-419D-B92F-470DA4E5674C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Delegates", "Cli\Delegates\Delegates.csproj", "{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Demo", "Cli\Demo\Demo.csproj", "{7FC2594D-55D6-4688-AB7D-C9C903414448}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dynamic", "Cli\Dynamic\Dynamic.csproj", "{6EA8F935-A230-4171-8618-FDFABA553292}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Injection", "Cli\Injection\Injection.csproj", "{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Logging", "Cli\Logging\Logging.csproj", "{37024E79-A857-4EB2-9B50-F724ED34E5EB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{DD8EC1B0-F50C-44E4-8399-2D560F95E572}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Borders", "Console\Borders\Borders.csproj", "{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Calendars", "Console\Calendars\Calendars.csproj", "{C64ADBA3-AED2-4938-8E26-8D6679C395CB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Canvas", "Console\Canvas\Canvas.csproj", "{B3393919-26F1-4200-88CD-B71EEAF0EA51}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Charts", "Console\Charts\Charts.csproj", "{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Colors", "Console\Colors\Colors.csproj", "{18562660-BF70-4EF3-A765-22713BDE2EB1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Columns", "Console\Columns\Columns.csproj", "{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cursor", "Console\Cursor\Cursor.csproj", "{95BE948B-6102-4453-982D-C7B21E51B582}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emojis", "Console\Emojis\Emojis.csproj", "{6272C7ED-432E-4286-914C-898304A1880E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Exceptions", "Console\Exceptions\Exceptions.csproj", "{20766F18-AEC7-4382-BDE2-0C846F2857AA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Figlet", "Console\Figlet\Figlet.csproj", "{1C374C51-6C82-4E71-9701-5F378BC0356C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grids", "Console\Grids\Grids.csproj", "{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Info", "Console\Info\Info.csproj", "{FBCCBA12-9DBF-403C-9FA4-222CBB080955}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Links", "Console\Links\Links.csproj", "{B9414195-69A2-40E6-B071-751DCCE95AF0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Live", "Console\Live\Live.csproj", "{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Panels", "Console\Panels\Panels.csproj", "{12E7F2CE-E91B-446F-A269-F88FB546B6A8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Progress", "Console\Progress\Progress.csproj", "{4554BDF3-0723-4076-B054-616D830942D4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prompt", "Console\Prompt\Prompt.csproj", "{85A37D38-54D9-4FA2-B311-CA48BD7AF916}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules", "Console\Rules\Rules.csproj", "{305E2CE7-9D64-43D7-A26C-11036ACE2A89}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Showcase", "Console\Showcase\Showcase.csproj", "{5BEE8076-59A0-47BB-9CC6-222EC978AE16}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Status", "Console\Status\Status.csproj", "{FCE2405B-A215-434B-A47C-32053E27A907}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tables", "Console\Tables\Tables.csproj", "{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trees", "Console\Trees\Trees.csproj", "{2BD88288-E05D-4978-B045-17937078E63C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveTable", "Console\LiveTable\LiveTable.csproj", "{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Minimal", "Console\Minimal\Minimal.csproj", "{1780A30A-397A-4CC3-B2A0-A385D9081FA2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AlternateScreen", "Console\AlternateScreen\AlternateScreen.csproj", "{8A3B636E-5828-438B-A8F4-83811D2704CD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Paths", "Console\Paths\Paths.csproj", "{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Layout", "Console\Layout\Layout.csproj", "{A9FDE73A-8452-4CA3-B366-3F900597E132}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Json", "Console\Json\Json.csproj", "{ABE3E734-0756-4D5A-B28A-E6E526D9927D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Help", "Cli\Help\Help.csproj", "{BAB490D6-FF8D-462B-B2B0-933384D629DB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Decorations", "Console\Decorations\Decorations.csproj", "{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Debug|x64.ActiveCfg = Debug|Any CPU
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Debug|x64.Build.0 = Debug|Any CPU
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Debug|x86.ActiveCfg = Debug|Any CPU
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Debug|x86.Build.0 = Debug|Any CPU
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Release|Any CPU.Build.0 = Release|Any CPU
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Release|x64.ActiveCfg = Release|Any CPU
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Release|x64.Build.0 = Release|Any CPU
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Release|x86.ActiveCfg = Release|Any CPU
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF}.Release|x86.Build.0 = Release|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Debug|x64.ActiveCfg = Debug|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Debug|x64.Build.0 = Debug|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Debug|x86.ActiveCfg = Debug|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Debug|x86.Build.0 = Debug|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Release|Any CPU.Build.0 = Release|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Release|x64.ActiveCfg = Release|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Release|x64.Build.0 = Release|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Release|x86.ActiveCfg = Release|Any CPU
{7FC2594D-55D6-4688-AB7D-C9C903414448}.Release|x86.Build.0 = Release|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Debug|x64.ActiveCfg = Debug|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Debug|x64.Build.0 = Debug|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Debug|x86.ActiveCfg = Debug|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Debug|x86.Build.0 = Debug|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Release|Any CPU.Build.0 = Release|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Release|x64.ActiveCfg = Release|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Release|x64.Build.0 = Release|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Release|x86.ActiveCfg = Release|Any CPU
{6EA8F935-A230-4171-8618-FDFABA553292}.Release|x86.Build.0 = Release|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Debug|x64.ActiveCfg = Debug|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Debug|x64.Build.0 = Debug|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Debug|x86.ActiveCfg = Debug|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Debug|x86.Build.0 = Debug|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Release|Any CPU.Build.0 = Release|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Release|x64.ActiveCfg = Release|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Release|x64.Build.0 = Release|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Release|x86.ActiveCfg = Release|Any CPU
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58}.Release|x86.Build.0 = Release|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Debug|x64.ActiveCfg = Debug|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Debug|x64.Build.0 = Debug|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Debug|x86.ActiveCfg = Debug|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Debug|x86.Build.0 = Debug|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Release|Any CPU.Build.0 = Release|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Release|x64.ActiveCfg = Release|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Release|x64.Build.0 = Release|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Release|x86.ActiveCfg = Release|Any CPU
{37024E79-A857-4EB2-9B50-F724ED34E5EB}.Release|x86.Build.0 = Release|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Debug|x64.ActiveCfg = Debug|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Debug|x64.Build.0 = Debug|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Debug|x86.ActiveCfg = Debug|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Debug|x86.Build.0 = Debug|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Release|Any CPU.Build.0 = Release|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Release|x64.ActiveCfg = Release|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Release|x64.Build.0 = Release|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Release|x86.ActiveCfg = Release|Any CPU
{DD8EC1B0-F50C-44E4-8399-2D560F95E572}.Release|x86.Build.0 = Release|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Debug|Any CPU.Build.0 = Debug|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Debug|x64.ActiveCfg = Debug|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Debug|x64.Build.0 = Debug|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Debug|x86.ActiveCfg = Debug|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Debug|x86.Build.0 = Debug|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Release|Any CPU.ActiveCfg = Release|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Release|Any CPU.Build.0 = Release|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Release|x64.ActiveCfg = Release|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Release|x64.Build.0 = Release|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Release|x86.ActiveCfg = Release|Any CPU
{036D547D-1C9B-4E6F-B7E6-2E375E4CAF01}.Release|x86.Build.0 = Release|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Debug|x64.ActiveCfg = Debug|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Debug|x64.Build.0 = Debug|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Debug|x86.ActiveCfg = Debug|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Debug|x86.Build.0 = Debug|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Release|Any CPU.Build.0 = Release|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Release|x64.ActiveCfg = Release|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Release|x64.Build.0 = Release|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Release|x86.ActiveCfg = Release|Any CPU
{C64ADBA3-AED2-4938-8E26-8D6679C395CB}.Release|x86.Build.0 = Release|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Debug|x64.ActiveCfg = Debug|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Debug|x64.Build.0 = Debug|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Debug|x86.ActiveCfg = Debug|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Debug|x86.Build.0 = Debug|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Release|Any CPU.Build.0 = Release|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Release|x64.ActiveCfg = Release|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Release|x64.Build.0 = Release|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Release|x86.ActiveCfg = Release|Any CPU
{B3393919-26F1-4200-88CD-B71EEAF0EA51}.Release|x86.Build.0 = Release|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Debug|x64.ActiveCfg = Debug|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Debug|x64.Build.0 = Debug|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Debug|x86.ActiveCfg = Debug|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Debug|x86.Build.0 = Debug|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Release|Any CPU.Build.0 = Release|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Release|x64.ActiveCfg = Release|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Release|x64.Build.0 = Release|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Release|x86.ActiveCfg = Release|Any CPU
{0CF6EE4B-4015-4DE0-9D48-1EADCDE296E6}.Release|x86.Build.0 = Release|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Debug|x64.ActiveCfg = Debug|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Debug|x64.Build.0 = Debug|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Debug|x86.ActiveCfg = Debug|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Debug|x86.Build.0 = Debug|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Release|Any CPU.Build.0 = Release|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Release|x64.ActiveCfg = Release|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Release|x64.Build.0 = Release|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Release|x86.ActiveCfg = Release|Any CPU
{18562660-BF70-4EF3-A765-22713BDE2EB1}.Release|x86.Build.0 = Release|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Debug|x64.ActiveCfg = Debug|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Debug|x64.Build.0 = Debug|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Debug|x86.ActiveCfg = Debug|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Debug|x86.Build.0 = Debug|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Release|Any CPU.Build.0 = Release|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Release|x64.ActiveCfg = Release|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Release|x64.Build.0 = Release|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Release|x86.ActiveCfg = Release|Any CPU
{264EBC5A-B897-4DA8-9C9E-9A445B1E368C}.Release|x86.Build.0 = Release|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Debug|Any CPU.Build.0 = Debug|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Debug|x64.ActiveCfg = Debug|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Debug|x64.Build.0 = Debug|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Debug|x86.ActiveCfg = Debug|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Debug|x86.Build.0 = Debug|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Release|Any CPU.Build.0 = Release|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Release|x64.ActiveCfg = Release|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Release|x64.Build.0 = Release|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Release|x86.ActiveCfg = Release|Any CPU
{95BE948B-6102-4453-982D-C7B21E51B582}.Release|x86.Build.0 = Release|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Debug|x64.ActiveCfg = Debug|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Debug|x64.Build.0 = Debug|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Debug|x86.ActiveCfg = Debug|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Debug|x86.Build.0 = Debug|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Release|Any CPU.Build.0 = Release|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Release|x64.ActiveCfg = Release|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Release|x64.Build.0 = Release|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Release|x86.ActiveCfg = Release|Any CPU
{6272C7ED-432E-4286-914C-898304A1880E}.Release|x86.Build.0 = Release|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Debug|x64.ActiveCfg = Debug|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Debug|x64.Build.0 = Debug|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Debug|x86.ActiveCfg = Debug|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Debug|x86.Build.0 = Debug|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Release|Any CPU.Build.0 = Release|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Release|x64.ActiveCfg = Release|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Release|x64.Build.0 = Release|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Release|x86.ActiveCfg = Release|Any CPU
{20766F18-AEC7-4382-BDE2-0C846F2857AA}.Release|x86.Build.0 = Release|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Debug|x64.ActiveCfg = Debug|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Debug|x64.Build.0 = Debug|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Debug|x86.ActiveCfg = Debug|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Debug|x86.Build.0 = Debug|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Release|Any CPU.Build.0 = Release|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Release|x64.ActiveCfg = Release|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Release|x64.Build.0 = Release|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Release|x86.ActiveCfg = Release|Any CPU
{1C374C51-6C82-4E71-9701-5F378BC0356C}.Release|x86.Build.0 = Release|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Debug|x64.ActiveCfg = Debug|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Debug|x64.Build.0 = Debug|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Debug|x86.ActiveCfg = Debug|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Debug|x86.Build.0 = Debug|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Release|Any CPU.Build.0 = Release|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Release|x64.ActiveCfg = Release|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Release|x64.Build.0 = Release|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Release|x86.ActiveCfg = Release|Any CPU
{6F7AB11D-D2AE-4D1C-AFEE-7FBA922D6C26}.Release|x86.Build.0 = Release|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Debug|x64.ActiveCfg = Debug|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Debug|x64.Build.0 = Debug|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Debug|x86.ActiveCfg = Debug|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Debug|x86.Build.0 = Debug|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Release|Any CPU.Build.0 = Release|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Release|x64.ActiveCfg = Release|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Release|x64.Build.0 = Release|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Release|x86.ActiveCfg = Release|Any CPU
{FBCCBA12-9DBF-403C-9FA4-222CBB080955}.Release|x86.Build.0 = Release|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Debug|x64.ActiveCfg = Debug|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Debug|x64.Build.0 = Debug|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Debug|x86.ActiveCfg = Debug|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Debug|x86.Build.0 = Debug|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Release|Any CPU.Build.0 = Release|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Release|x64.ActiveCfg = Release|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Release|x64.Build.0 = Release|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Release|x86.ActiveCfg = Release|Any CPU
{B9414195-69A2-40E6-B071-751DCCE95AF0}.Release|x86.Build.0 = Release|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Debug|x64.ActiveCfg = Debug|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Debug|x64.Build.0 = Debug|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Debug|x86.ActiveCfg = Debug|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Debug|x86.Build.0 = Debug|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Release|Any CPU.Build.0 = Release|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Release|x64.ActiveCfg = Release|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Release|x64.Build.0 = Release|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Release|x86.ActiveCfg = Release|Any CPU
{4AE3AC67-A927-42CC-B286-E0A0735DC7A2}.Release|x86.Build.0 = Release|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Debug|x64.ActiveCfg = Debug|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Debug|x64.Build.0 = Debug|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Debug|x86.ActiveCfg = Debug|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Debug|x86.Build.0 = Debug|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Release|Any CPU.Build.0 = Release|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Release|x64.ActiveCfg = Release|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Release|x64.Build.0 = Release|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Release|x86.ActiveCfg = Release|Any CPU
{12E7F2CE-E91B-446F-A269-F88FB546B6A8}.Release|x86.Build.0 = Release|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Debug|x64.ActiveCfg = Debug|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Debug|x64.Build.0 = Debug|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Debug|x86.ActiveCfg = Debug|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Debug|x86.Build.0 = Debug|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Release|Any CPU.Build.0 = Release|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Release|x64.ActiveCfg = Release|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Release|x64.Build.0 = Release|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Release|x86.ActiveCfg = Release|Any CPU
{4554BDF3-0723-4076-B054-616D830942D4}.Release|x86.Build.0 = Release|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Debug|x64.ActiveCfg = Debug|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Debug|x64.Build.0 = Debug|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Debug|x86.ActiveCfg = Debug|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Debug|x86.Build.0 = Debug|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Release|Any CPU.Build.0 = Release|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Release|x64.ActiveCfg = Release|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Release|x64.Build.0 = Release|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Release|x86.ActiveCfg = Release|Any CPU
{85A37D38-54D9-4FA2-B311-CA48BD7AF916}.Release|x86.Build.0 = Release|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Debug|Any CPU.Build.0 = Debug|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Debug|x64.ActiveCfg = Debug|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Debug|x64.Build.0 = Debug|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Debug|x86.ActiveCfg = Debug|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Debug|x86.Build.0 = Debug|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Release|Any CPU.ActiveCfg = Release|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Release|Any CPU.Build.0 = Release|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Release|x64.ActiveCfg = Release|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Release|x64.Build.0 = Release|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Release|x86.ActiveCfg = Release|Any CPU
{305E2CE7-9D64-43D7-A26C-11036ACE2A89}.Release|x86.Build.0 = Release|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Debug|x64.ActiveCfg = Debug|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Debug|x64.Build.0 = Debug|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Debug|x86.ActiveCfg = Debug|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Debug|x86.Build.0 = Debug|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Release|Any CPU.Build.0 = Release|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Release|x64.ActiveCfg = Release|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Release|x64.Build.0 = Release|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Release|x86.ActiveCfg = Release|Any CPU
{5BEE8076-59A0-47BB-9CC6-222EC978AE16}.Release|x86.Build.0 = Release|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Debug|x64.ActiveCfg = Debug|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Debug|x64.Build.0 = Debug|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Debug|x86.ActiveCfg = Debug|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Debug|x86.Build.0 = Debug|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Release|Any CPU.Build.0 = Release|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Release|x64.ActiveCfg = Release|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Release|x64.Build.0 = Release|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Release|x86.ActiveCfg = Release|Any CPU
{FCE2405B-A215-434B-A47C-32053E27A907}.Release|x86.Build.0 = Release|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Debug|x64.ActiveCfg = Debug|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Debug|x64.Build.0 = Debug|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Debug|x86.ActiveCfg = Debug|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Debug|x86.Build.0 = Debug|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Release|Any CPU.Build.0 = Release|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Release|x64.ActiveCfg = Release|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Release|x64.Build.0 = Release|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Release|x86.ActiveCfg = Release|Any CPU
{3D16490A-9EBA-488C-9B3E-6A11FC1E0300}.Release|x86.Build.0 = Release|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Debug|x64.ActiveCfg = Debug|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Debug|x64.Build.0 = Debug|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Debug|x86.ActiveCfg = Debug|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Debug|x86.Build.0 = Debug|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Release|Any CPU.Build.0 = Release|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Release|x64.ActiveCfg = Release|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Release|x64.Build.0 = Release|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Release|x86.ActiveCfg = Release|Any CPU
{2BD88288-E05D-4978-B045-17937078E63C}.Release|x86.Build.0 = Release|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|x64.ActiveCfg = Debug|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|x64.Build.0 = Debug|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|x86.ActiveCfg = Debug|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|x86.Build.0 = Debug|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|Any CPU.Build.0 = Release|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|x64.ActiveCfg = Release|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|x64.Build.0 = Release|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|x86.ActiveCfg = Release|Any CPU
{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|x86.Build.0 = Release|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Debug|x64.ActiveCfg = Debug|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Debug|x64.Build.0 = Debug|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Debug|x86.ActiveCfg = Debug|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Debug|x86.Build.0 = Debug|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Release|Any CPU.Build.0 = Release|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Release|x64.ActiveCfg = Release|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Release|x64.Build.0 = Release|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Release|x86.ActiveCfg = Release|Any CPU
{1780A30A-397A-4CC3-B2A0-A385D9081FA2}.Release|x86.Build.0 = Release|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Debug|x64.ActiveCfg = Debug|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Debug|x64.Build.0 = Debug|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Debug|x86.ActiveCfg = Debug|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Debug|x86.Build.0 = Debug|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Release|Any CPU.Build.0 = Release|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Release|x64.ActiveCfg = Release|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Release|x64.Build.0 = Release|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Release|x86.ActiveCfg = Release|Any CPU
{8A3B636E-5828-438B-A8F4-83811D2704CD}.Release|x86.Build.0 = Release|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Debug|x64.ActiveCfg = Debug|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Debug|x64.Build.0 = Debug|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Debug|x86.ActiveCfg = Debug|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Debug|x86.Build.0 = Debug|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Release|Any CPU.Build.0 = Release|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Release|x64.ActiveCfg = Release|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Release|x64.Build.0 = Release|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Release|x86.ActiveCfg = Release|Any CPU
{65CB00B0-A3AE-4E8F-A990-4C8C1A232FE2}.Release|x86.Build.0 = Release|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Debug|x64.ActiveCfg = Debug|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Debug|x64.Build.0 = Debug|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Debug|x86.ActiveCfg = Debug|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Debug|x86.Build.0 = Debug|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Release|Any CPU.Build.0 = Release|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Release|x64.ActiveCfg = Release|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Release|x64.Build.0 = Release|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Release|x86.ActiveCfg = Release|Any CPU
{A9FDE73A-8452-4CA3-B366-3F900597E132}.Release|x86.Build.0 = Release|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Debug|x64.ActiveCfg = Debug|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Debug|x64.Build.0 = Debug|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Debug|x86.ActiveCfg = Debug|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Debug|x86.Build.0 = Debug|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Release|Any CPU.Build.0 = Release|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Release|x64.ActiveCfg = Release|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Release|x64.Build.0 = Release|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Release|x86.ActiveCfg = Release|Any CPU
{ABE3E734-0756-4D5A-B28A-E6E526D9927D}.Release|x86.Build.0 = Release|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Debug|x64.ActiveCfg = Debug|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Debug|x64.Build.0 = Debug|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Debug|x86.ActiveCfg = Debug|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Debug|x86.Build.0 = Debug|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Release|Any CPU.Build.0 = Release|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Release|x64.ActiveCfg = Release|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Release|x64.Build.0 = Release|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Release|x86.ActiveCfg = Release|Any CPU
{BAB490D6-FF8D-462B-B2B0-933384D629DB}.Release|x86.Build.0 = Release|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Debug|x64.ActiveCfg = Debug|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Debug|x64.Build.0 = Debug|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Debug|x86.ActiveCfg = Debug|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Debug|x86.Build.0 = Debug|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Release|Any CPU.Build.0 = Release|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Release|x64.ActiveCfg = Release|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Release|x64.Build.0 = Release|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Release|x86.ActiveCfg = Release|Any CPU
{FC5852F1-E01F-4DF7-9B49-CA19A9EE670F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{E2C9023A-D24F-4F5D-8411-5E2FEA642FEF} = {4682E9B7-B54C-419D-B92F-470DA4E5674C}
{7FC2594D-55D6-4688-AB7D-C9C903414448} = {4682E9B7-B54C-419D-B92F-470DA4E5674C}
{6EA8F935-A230-4171-8618-FDFABA553292} = {4682E9B7-B54C-419D-B92F-470DA4E5674C}
{DEB88B47-658E-4FCB-BD1D-05C99E7EFA58} = {4682E9B7-B54C-419D-B92F-470DA4E5674C}
{37024E79-A857-4EB2-9B50-F724ED34E5EB} = {4682E9B7-B54C-419D-B92F-470DA4E5674C}
{DD8EC1B0-F50C-44E4-8399-2D560F95E572} = {2571F1BD-6556-4F96-B27B-B6190E1BF13A}
{BAB490D6-FF8D-462B-B2B0-933384D629DB} = {4682E9B7-B54C-419D-B92F-470DA4E5674C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3EE724C5-CAB4-410D-AC63-8D4260EF83ED}
EndGlobalSection
EndGlobal

123
examples/Shared/ColorBox.cs Normal file
View File

@@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using Spectre.Console.Rendering;
namespace Spectre.Console.Examples;
public sealed class ColorBox : Renderable
{
private readonly int _height;
private int? _width;
public ColorBox(int height)
{
_height = height;
}
public ColorBox(int width, int height)
: this(height)
{
_width = width;
}
protected override Measurement Measure(RenderOptions options, int maxWidth)
{
return new Measurement(1, GetWidth(maxWidth));
}
protected override IEnumerable<Segment> Render(RenderOptions options, int maxWidth)
{
maxWidth = GetWidth(maxWidth);
for (var y = 0; y < _height; y++)
{
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);
}
else
{
return temp1;
}
}
}

View File

@@ -0,0 +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;
}
private static float GetLuminance(this Color color)
{
return (float)((0.2126 * color.R) + (0.7152 * color.G) + (0.0722 * color.B));
}
}

Some files were not shown because too many files have changed in this diff Show More