mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-06-20 05:48:14 +08:00
Add Spectre.Cli to Spectre.Console
* Renames Spectre.Cli to Spectre.Console.Cli. * Now uses Verify with Spectre.Console.Cli tests. * Removes some duplicate definitions. Closes #168
This commit is contained in:

committed by
Patrik Svensson

parent
0bbf9b81a9
commit
0ae419326d
155
src/Spectre.Console/Cli/CommandApp.cs
Normal file
155
src/Spectre.Console/Cli/CommandApp.cs
Normal file
@ -0,0 +1,155 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Cli.Internal;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console.Cli
|
||||
{
|
||||
/// <summary>
|
||||
/// The entry point for a command line application.
|
||||
/// </summary>
|
||||
public sealed class CommandApp : ICommandApp
|
||||
{
|
||||
private readonly Configurator _configurator;
|
||||
private readonly CommandExecutor _executor;
|
||||
private bool _executed;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CommandApp"/> class.
|
||||
/// </summary>
|
||||
/// <param name="registrar">The registrar.</param>
|
||||
public CommandApp(ITypeRegistrar? registrar = null)
|
||||
{
|
||||
registrar ??= new DefaultTypeRegistrar();
|
||||
|
||||
_configurator = new Configurator(registrar);
|
||||
_executor = new CommandExecutor(registrar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures the command line application.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration.</param>
|
||||
public void Configure(Action<IConfigurator> configuration)
|
||||
{
|
||||
if (configuration == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configuration));
|
||||
}
|
||||
|
||||
configuration(_configurator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the default command.
|
||||
/// </summary>
|
||||
/// <typeparam name="TCommand">The command type.</typeparam>
|
||||
public void SetDefaultCommand<TCommand>()
|
||||
where TCommand : class, ICommand
|
||||
{
|
||||
GetConfigurator().SetDefaultCommand<TCommand>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs the command line application with specified arguments.
|
||||
/// </summary>
|
||||
/// <param name="args">The arguments.</param>
|
||||
/// <returns>The exit code from the executed command.</returns>
|
||||
public int Run(IEnumerable<string> args)
|
||||
{
|
||||
return RunAsync(args).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs the command line application with specified arguments.
|
||||
/// </summary>
|
||||
/// <param name="args">The arguments.</param>
|
||||
/// <returns>The exit code from the executed command.</returns>
|
||||
public async Task<int> RunAsync(IEnumerable<string> args)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_executed)
|
||||
{
|
||||
// Add built-in (hidden) commands.
|
||||
_configurator.AddBranch(Constants.Commands.Branch, cli =>
|
||||
{
|
||||
cli.HideBranch();
|
||||
cli.AddCommand<VersionCommand>(Constants.Commands.Version);
|
||||
cli.AddCommand<XmlDocCommand>(Constants.Commands.XmlDoc);
|
||||
});
|
||||
|
||||
_executed = true;
|
||||
}
|
||||
|
||||
return await _executor
|
||||
.Execute(_configurator, args)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Render the exception.
|
||||
var pretty = GetRenderableErrorMessage(ex);
|
||||
if (pretty != null)
|
||||
{
|
||||
_configurator.Settings.Console.SafeRender(pretty);
|
||||
}
|
||||
|
||||
// Should we always propagate when debugging?
|
||||
if (Debugger.IsAttached
|
||||
&& ex is CommandAppException appException
|
||||
&& appException.AlwaysPropagateWhenDebugging)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
if (_configurator.Settings.PropagateExceptions)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
internal Configurator GetConfigurator()
|
||||
{
|
||||
return _configurator;
|
||||
}
|
||||
|
||||
private static List<IRenderable?>? GetRenderableErrorMessage(Exception ex, bool convert = true)
|
||||
{
|
||||
if (ex is CommandAppException renderable && renderable.Pretty != null)
|
||||
{
|
||||
return new List<IRenderable?> { renderable.Pretty };
|
||||
}
|
||||
|
||||
if (convert)
|
||||
{
|
||||
var converted = new List<IRenderable?>
|
||||
{
|
||||
new Composer()
|
||||
.LineBreak()
|
||||
.Text("[red]Error:[/]")
|
||||
.Space().Text(ex.Message.EscapeMarkup()),
|
||||
};
|
||||
|
||||
// Got a renderable inner exception?
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
var innerRenderable = GetRenderableErrorMessage(ex.InnerException, convert: false);
|
||||
if (innerRenderable != null)
|
||||
{
|
||||
converted.AddRange(innerRenderable);
|
||||
}
|
||||
}
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user