diff --git a/src/Spectre.Console.Cli/Internal/CommandExecutor.cs b/src/Spectre.Console.Cli/Internal/CommandExecutor.cs index 0268a3c..db64733 100644 --- a/src/Spectre.Console.Cli/Internal/CommandExecutor.cs +++ b/src/Spectre.Console.Cli/Internal/CommandExecutor.cs @@ -1,20 +1,20 @@ -namespace Spectre.Console.Cli; - -internal sealed class CommandExecutor -{ - private readonly ITypeRegistrar _registrar; - - public CommandExecutor(ITypeRegistrar registrar) - { - _registrar = registrar ?? throw new ArgumentNullException(nameof(registrar)); - _registrar.Register(typeof(DefaultPairDeconstructor), typeof(DefaultPairDeconstructor)); +namespace Spectre.Console.Cli; + +internal sealed class CommandExecutor +{ + private readonly ITypeRegistrar _registrar; + + public CommandExecutor(ITypeRegistrar registrar) + { + _registrar = registrar ?? throw new ArgumentNullException(nameof(registrar)); + _registrar.Register(typeof(DefaultPairDeconstructor), typeof(DefaultPairDeconstructor)); } - public async Task Execute(IConfiguration configuration, IEnumerable args) - { - if (configuration == null) - { - throw new ArgumentNullException(nameof(configuration)); + public async Task Execute(IConfiguration configuration, IEnumerable args) + { + if (configuration == null) + { + throw new ArgumentNullException(nameof(configuration)); } args ??= new List(); @@ -22,13 +22,9 @@ internal sealed class CommandExecutor _registrar.RegisterInstance(typeof(IConfiguration), configuration); _registrar.RegisterLazy(typeof(IAnsiConsole), () => configuration.Settings.Console.GetConsole()); - // Register the help provider - var defaultHelpProvider = new HelpProvider(configuration.Settings); - _registrar.RegisterInstance(typeof(IHelpProvider), defaultHelpProvider); - - // Create the command model. - var model = CommandModelBuilder.Build(configuration); - _registrar.RegisterInstance(typeof(CommandModel), model); + // Create the command model. + var model = CommandModelBuilder.Build(configuration); + _registrar.RegisterInstance(typeof(CommandModel), model); _registrar.RegisterDependencies(model); // Asking for version? Kind of a hack, but it's alright. @@ -39,20 +35,21 @@ internal sealed class CommandExecutor console.WriteLine(ResolveApplicationVersion(configuration)); return 0; } - - // Parse and map the model against the arguments. + + // Parse and map the model against the arguments. var parsedResult = ParseCommandLineArguments(model, configuration.Settings, args); // Register the arguments with the container. - _registrar.RegisterInstance(typeof(CommandTreeParserResult), parsedResult); - _registrar.RegisterInstance(typeof(IRemainingArguments), parsedResult.Remaining); - - // Create the resolver. - using (var resolver = new TypeResolverAdapter(_registrar.Build())) + _registrar.RegisterInstance(typeof(CommandTreeParserResult), parsedResult); + _registrar.RegisterInstance(typeof(IRemainingArguments), parsedResult.Remaining); + + // Create the resolver. + using (var resolver = new TypeResolverAdapter(_registrar.Build())) { // Get the registered help provider, falling back to the default provider - // registered above if no custom implementations have been registered. - var helpProvider = resolver.Resolve(typeof(IHelpProvider)) as IHelpProvider ?? defaultHelpProvider; + // if no custom implementations have been registered. + var helpProviders = resolver.Resolve(typeof(IEnumerable)) as IEnumerable; + var helpProvider = helpProviders?.LastOrDefault() ?? new HelpProvider(configuration.Settings); // Currently the root? if (parsedResult?.Tree == null) @@ -77,14 +74,14 @@ internal sealed class CommandExecutor // Display help for default command. configuration.Settings.Console.SafeRender(helpProvider.Write(model, leaf.Command)); return 1; - } - - // Create the content. - var context = new CommandContext(parsedResult.Remaining, leaf.Command.Name, leaf.Command.Data); - - // Execute the command tree. - return await Execute(leaf, parsedResult.Tree, context, resolver, configuration).ConfigureAwait(false); - } + } + + // Create the content. + var context = new CommandContext(parsedResult.Remaining, leaf.Command.Name, leaf.Command.Data); + + // Execute the command tree. + return await Execute(leaf, parsedResult.Tree, context, resolver, configuration).ConfigureAwait(false); + } } #pragma warning disable CS8603 // Possible null reference return. @@ -100,7 +97,7 @@ internal sealed class CommandExecutor var lastParsedCommand = lastParsedLeaf?.Command; if (lastParsedLeaf != null && lastParsedCommand != null && lastParsedCommand.IsBranch && !lastParsedLeaf.ShowHelp && - lastParsedCommand.DefaultCommand != null) + lastParsedCommand.DefaultCommand != null) { // Insert this branch's default command into the command line // arguments and try again to see if it will parse. @@ -117,33 +114,33 @@ internal sealed class CommandExecutor } #pragma warning restore CS8603 // Possible null reference return. - private static string ResolveApplicationVersion(IConfiguration configuration) - { - return - configuration.Settings.ApplicationVersion ?? // potential override - VersionHelper.GetVersion(Assembly.GetEntryAssembly()); - } - - private static Task Execute( - CommandTree leaf, - CommandTree tree, - CommandContext context, - ITypeResolver resolver, - IConfiguration configuration) - { - // Bind the command tree against the settings. - var settings = CommandBinder.Bind(tree, leaf.Command.SettingsType, resolver); - configuration.Settings.Interceptor?.Intercept(context, settings); - - // Create and validate the command. - var command = leaf.CreateCommand(resolver); - var validationResult = command.Validate(context, settings); - if (!validationResult.Successful) - { - throw CommandRuntimeException.ValidationFailed(validationResult); - } - - // Execute the command. - return command.Execute(context, settings); - } + private static string ResolveApplicationVersion(IConfiguration configuration) + { + return + configuration.Settings.ApplicationVersion ?? // potential override + VersionHelper.GetVersion(Assembly.GetEntryAssembly()); + } + + private static Task Execute( + CommandTree leaf, + CommandTree tree, + CommandContext context, + ITypeResolver resolver, + IConfiguration configuration) + { + // Bind the command tree against the settings. + var settings = CommandBinder.Bind(tree, leaf.Command.SettingsType, resolver); + configuration.Settings.Interceptor?.Intercept(context, settings); + + // Create and validate the command. + var command = leaf.CreateCommand(resolver); + var validationResult = command.Validate(context, settings); + if (!validationResult.Successful) + { + throw CommandRuntimeException.ValidationFailed(validationResult); + } + + // Execute the command. + return command.Execute(context, settings); + } } \ No newline at end of file