|
using Microsoft.Extensions.DependencyInjection; |
|
using Microsoft.Extensions.Hosting; |
|
using Microsoft.Extensions.Hosting.Internal; |
|
using Spectre.Console; |
|
using Spectre.Console.Cli; |
|
|
|
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); |
|
|
|
builder.Services.AddSingleton<IAnsiConsole>((_) => |
|
AnsiConsole.Create( |
|
new AnsiConsoleSettings |
|
{ |
|
Ansi = AnsiSupport.Detect, |
|
ColorSystem = ColorSystemSupport.Detect, |
|
Out = new AnsiConsoleOutput(Console.Out) |
|
} |
|
) |
|
); |
|
builder.Services.AddSingleton<ILiveConsoleService, LiveConsoleService>(); |
|
builder.Services.AddSingleton<IHostLifetime, ConsoleLifetime>(); |
|
builder.Services.AddScoped<IMessageService, MessageService>(); |
|
|
|
ServiceCollectionRegistrar registrar = new (builder.Services); |
|
|
|
CommandApp app = new(registrar); |
|
|
|
app.SetDefaultCommand<GreetCommand>(); |
|
|
|
app.Configure(config => |
|
{ |
|
config.AddCommand<ScareCommand>("scare"); |
|
config.AddCommand<SurpriseCommand>("surprise"); |
|
}); |
|
|
|
return await app.RunAsync(args); |
|
|
|
internal interface IMessageService |
|
{ |
|
string GetGreeting(string salutation, string name); |
|
|
|
string GetScare(string name); |
|
|
|
string GetSurprise(); |
|
} |
|
|
|
internal sealed class MessageService : IMessageService |
|
{ |
|
public string GetGreeting(string salutation, string name) => $"{salutation}, {name}!"; |
|
|
|
public string GetScare(string name) => $"BOO, {name}!"; |
|
|
|
public string GetSurprise() => "SURPRISE!"; |
|
} |
|
|
|
internal interface ILiveConsoleService |
|
{ |
|
Task StartLiveConsoleAsync(Func<IAnsiConsole, StatusContext, Task> asyncLogic, string startMessage = "Starting..."); |
|
} |
|
|
|
internal sealed class LiveConsoleService( |
|
IAnsiConsole console |
|
) : ILiveConsoleService |
|
{ |
|
public async Task StartLiveConsoleAsync(Func<IAnsiConsole, StatusContext, Task> asyncLogic, string startMessage = "Starting...") |
|
{ |
|
await console.Status().StartAsync( |
|
startMessage, |
|
async (StatusContext context) => |
|
{ |
|
await asyncLogic(console, context); |
|
} |
|
); |
|
} |
|
} |
|
|
|
internal sealed class GreetSettings : CommandSettings |
|
{ |
|
[CommandOption("-n|--name <NAME>")] |
|
public required string Name { get; init; } = "World"; |
|
|
|
[CommandOption("-s|--salutation <SALUTATION>")] |
|
public string Salutation { get; init; } = "Hello"; |
|
} |
|
|
|
internal sealed class GreetCommand( |
|
IMessageService messageService, |
|
ILiveConsoleService liveConsoleService |
|
) : AsyncCommand<GreetSettings> |
|
{ |
|
public override async Task<int> ExecuteAsync(CommandContext context, GreetSettings settings) |
|
{ |
|
await liveConsoleService.StartLiveConsoleAsync( |
|
async (console, live) => |
|
{ |
|
live.Spinner(Spinner.Known.Star); |
|
live.SpinnerStyle(Style.Parse("yellow")); |
|
await DoWorkAsync(settings, console, live); |
|
}, |
|
startMessage: "Greeting..." |
|
); |
|
return 0; |
|
} |
|
|
|
private async Task DoWorkAsync(GreetSettings settings, IAnsiConsole console, StatusContext live) |
|
{ |
|
live.Status("[italic green]Starting...[/]"); |
|
await Task.Delay(TimeSpan.FromSeconds(1.5)); |
|
|
|
string message = messageService.GetGreeting(settings.Salutation, settings.Name); |
|
console.MarkupLine($"[blue][bold]MESSAGE:[/]\t{message}[/]"); |
|
|
|
await Task.Delay(TimeSpan.FromSeconds(1.5)); |
|
live.Status("[italic green]Finishing...[/]"); |
|
|
|
await Task.Delay(TimeSpan.FromSeconds(1.5)); |
|
} |
|
} |
|
|
|
internal sealed class ScareSettings : CommandSettings |
|
{ |
|
[CommandOption("-n|--name <NAME>")] |
|
public required string Name { get; init; } = "World"; |
|
} |
|
|
|
internal sealed class ScareCommand( |
|
IMessageService messageService, |
|
ILiveConsoleService liveConsoleService |
|
) : AsyncCommand<ScareSettings> |
|
{ |
|
public override async Task<int> ExecuteAsync(CommandContext context, ScareSettings settings) |
|
{ |
|
await liveConsoleService.StartLiveConsoleAsync( |
|
async (console, live) => |
|
{ |
|
live.Spinner(Spinner.Known.Aesthetic); |
|
live.SpinnerStyle(Style.Parse("yellow")); |
|
await DoWorkAsync(settings, console, live); |
|
}, |
|
startMessage: "Scaring..." |
|
); |
|
return 0; |
|
} |
|
|
|
private async Task DoWorkAsync(ScareSettings settings, IAnsiConsole console, StatusContext live) |
|
{ |
|
live.Status("[italic red]Starting...[/]"); |
|
await Task.Delay(TimeSpan.FromSeconds(1.5)); |
|
|
|
string message = messageService.GetScare(settings.Name); |
|
console.MarkupLine($"[blue][bold]MESSAGE:[/]\t{message}[/]"); |
|
await Task.Delay(TimeSpan.FromSeconds(1.5)); |
|
|
|
live.Status("[italic red]Finishing...[/]"); |
|
await Task.Delay(TimeSpan.FromSeconds(1.5)); |
|
} |
|
} |
|
|
|
internal sealed class SurpriseCommand( |
|
IMessageService messageService, |
|
ILiveConsoleService liveConsoleService |
|
) : AsyncCommand |
|
{ |
|
public override async Task<int> ExecuteAsync(CommandContext context) |
|
{ |
|
await liveConsoleService.StartLiveConsoleAsync( |
|
async (console, live) => |
|
{ |
|
live.Spinner(Spinner.Known.Dots8Bit); |
|
live.SpinnerStyle(Style.Parse("yellow")); |
|
await DoWorkAsync(console, live); |
|
}, |
|
startMessage: "Surprising..." |
|
); |
|
return 0; |
|
} |
|
|
|
private async Task DoWorkAsync(IAnsiConsole console, StatusContext live) |
|
{ |
|
live.Status("[italic purple]Starting...[/]"); |
|
await Task.Delay(TimeSpan.FromSeconds(1.5)); |
|
|
|
string message = messageService.GetSurprise(); |
|
console.MarkupLine($"[blue][bold]MESSAGE:[/]\t{message}[/]"); |
|
await Task.Delay(TimeSpan.FromSeconds(1.5)); |
|
|
|
live.Status("[italic purple]Finishing...[/]"); |
|
await Task.Delay(TimeSpan.FromSeconds(1.5)); |
|
} |
|
} |