mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-16 00:42:51 +08:00

Allow custom help providers * Version option will show in help even with a default command * Reserve `-v` and `--version` as special Spectre.Console command line arguments (nb. breaking change for Spectre.Console users who have a default command with a settings class that uses either of these switches). * Help writer correctly determines if trailing commands exist and whether to display them as optional or mandatory in the usage statement. * Ability to control the number of indirect commands to display in the help text when the command itself doesn't have any examples of its own. Defaults to 5 (for backward compatibility) but can be set to any integer or zero to disable completely. * Significant increase in unit test coverage for the help writer. * Minor grammatical improvements to website documentation.
114 lines
4.1 KiB
C#
114 lines
4.1 KiB
C#
namespace Spectre.Console.Cli;
|
|
|
|
internal sealed class Configurator : IUnsafeConfigurator, IConfigurator, IConfiguration
|
|
{
|
|
private readonly ITypeRegistrar _registrar;
|
|
|
|
public IList<ConfiguredCommand> Commands { get; }
|
|
public CommandAppSettings Settings { get; }
|
|
public ConfiguredCommand? DefaultCommand { get; private set; }
|
|
public IList<string[]> Examples { get; }
|
|
|
|
ICommandAppSettings IConfigurator.Settings => Settings;
|
|
|
|
public Configurator(ITypeRegistrar registrar)
|
|
{
|
|
_registrar = registrar;
|
|
|
|
Commands = new List<ConfiguredCommand>();
|
|
Settings = new CommandAppSettings(registrar);
|
|
Examples = new List<string[]>();
|
|
}
|
|
|
|
public void SetHelpProvider(IHelpProvider helpProvider)
|
|
{
|
|
// Register the help provider
|
|
_registrar.RegisterInstance(typeof(IHelpProvider), helpProvider);
|
|
}
|
|
|
|
public void SetHelpProvider<T>()
|
|
where T : IHelpProvider
|
|
{
|
|
// Register the help provider
|
|
_registrar.Register(typeof(IHelpProvider), typeof(T));
|
|
}
|
|
|
|
public void AddExample(params string[] args)
|
|
{
|
|
Examples.Add(args);
|
|
}
|
|
|
|
public ConfiguredCommand SetDefaultCommand<TDefaultCommand>()
|
|
where TDefaultCommand : class, ICommand
|
|
{
|
|
DefaultCommand = ConfiguredCommand.FromType<TDefaultCommand>(
|
|
CliConstants.DefaultCommandName, isDefaultCommand: true);
|
|
return DefaultCommand;
|
|
}
|
|
|
|
public ICommandConfigurator AddCommand<TCommand>(string name)
|
|
where TCommand : class, ICommand
|
|
{
|
|
var command = Commands.AddAndReturn(ConfiguredCommand.FromType<TCommand>(name, isDefaultCommand: false));
|
|
return new CommandConfigurator(command);
|
|
}
|
|
|
|
public ICommandConfigurator AddDelegate<TSettings>(string name, Func<CommandContext, TSettings, int> func)
|
|
where TSettings : CommandSettings
|
|
{
|
|
var command = Commands.AddAndReturn(ConfiguredCommand.FromDelegate<TSettings>(
|
|
name, (context, settings) => Task.FromResult(func(context, (TSettings)settings))));
|
|
return new CommandConfigurator(command);
|
|
}
|
|
|
|
public ICommandConfigurator AddAsyncDelegate<TSettings>(string name, Func<CommandContext, TSettings, Task<int>> func)
|
|
where TSettings : CommandSettings
|
|
{
|
|
var command = Commands.AddAndReturn(ConfiguredCommand.FromDelegate<TSettings>(
|
|
name, (context, settings) => func(context, (TSettings)settings)));
|
|
return new CommandConfigurator(command);
|
|
}
|
|
|
|
public IBranchConfigurator AddBranch<TSettings>(string name, Action<IConfigurator<TSettings>> action)
|
|
where TSettings : CommandSettings
|
|
{
|
|
var command = ConfiguredCommand.FromBranch<TSettings>(name);
|
|
action(new Configurator<TSettings>(command, _registrar));
|
|
var added = Commands.AddAndReturn(command);
|
|
return new BranchConfigurator(added);
|
|
}
|
|
|
|
ICommandConfigurator IUnsafeConfigurator.AddCommand(string name, Type command)
|
|
{
|
|
var method = GetType().GetMethod("AddCommand");
|
|
if (method == null)
|
|
{
|
|
throw new CommandConfigurationException("Could not find AddCommand by reflection.");
|
|
}
|
|
|
|
method = method.MakeGenericMethod(command);
|
|
|
|
if (!(method.Invoke(this, new object[] { name }) is ICommandConfigurator result))
|
|
{
|
|
throw new CommandConfigurationException("Invoking AddCommand returned null.");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
IBranchConfigurator IUnsafeConfigurator.AddBranch(string name, Type settings, Action<IUnsafeBranchConfigurator> action)
|
|
{
|
|
var command = ConfiguredCommand.FromBranch(settings, name);
|
|
|
|
// Create the configurator.
|
|
var configuratorType = typeof(Configurator<>).MakeGenericType(settings);
|
|
if (!(Activator.CreateInstance(configuratorType, new object?[] { command, _registrar }) is IUnsafeBranchConfigurator configurator))
|
|
{
|
|
throw new CommandConfigurationException("Could not create configurator by reflection.");
|
|
}
|
|
|
|
action(configurator);
|
|
var added = Commands.AddAndReturn(command);
|
|
return new BranchConfigurator(added);
|
|
}
|
|
} |