Show help for default command (#953)

Shows help if the default command was called without any arguments but has required arguments.
This way it does not hinder execution of a default command without any required arguments.

When called without args:
- Default command with required params -> Show help
- Default command with required params and additional commands -> Show help including additional commands
- Default command without required params -> Execute command
This commit is contained in:
krisrok 2022-12-14 18:19:12 +01:00 committed by GitHub
parent b793482ebb
commit 4a8a4ab048
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 449 additions and 319 deletions

View File

@ -66,6 +66,14 @@ internal sealed class CommandExecutor
return leaf.ShowHelp ? 0 : 1;
}
// Is this the default and is it called without arguments when there are required arguments?
if (leaf.Command.IsDefaultCommand && args.Count() == 0 && leaf.Command.Parameters.Any(p => p.Required))
{
// Display help for default command.
configuration.Settings.Console.SafeRender(HelpWriter.WriteCommand(model, leaf.Command));
return 1;
}
// Register the arguments with the container.
_registrar.RegisterInstance(typeof(IRemainingArguments), parsedResult.Remaining);

View File

@ -0,0 +1,17 @@
using Spectre.Console;
public class GreeterCommand : Command<OptionalArgumentWithDefaultValueSettings>
{
private readonly IAnsiConsole _console;
public GreeterCommand(IAnsiConsole console)
{
_console = console;
}
public override int Execute([NotNull] CommandContext context, [NotNull] OptionalArgumentWithDefaultValueSettings settings)
{
_console.WriteLine(settings.Greeting);
return 0;
}
}

View File

@ -0,0 +1,16 @@
DESCRIPTION:
The lion command.
USAGE:
myapp <TEETH> [LEGS] [OPTIONS]
ARGUMENTS:
<TEETH> The number of teeth the lion has
[LEGS] The number of legs
OPTIONS:
-h, --help Prints help information
-a, --alive Indicates whether or not the animal is alive
-n, --name <VALUE>
--agility <VALUE> The agility between 0 and 100
-c <CHILDREN> The number of children the lion has

View File

@ -0,0 +1,19 @@
DESCRIPTION:
The lion command.
USAGE:
myapp <TEETH> [LEGS] [OPTIONS]
ARGUMENTS:
<TEETH> The number of teeth the lion has
[LEGS] The number of legs
OPTIONS:
-h, --help Prints help information
-a, --alive Indicates whether or not the animal is alive
-n, --name <VALUE>
--agility <VALUE> The agility between 0 and 100
-c <CHILDREN> The number of children the lion has
COMMANDS:
giraffe <LENGTH> The giraffe command

View File

@ -29,4 +29,15 @@
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Expectations\Help\Default_Without_Args_Additional.Output.verified.txt">
<ParentFile>$([System.String]::Copy('%(FileName)').Split('.')[0])</ParentFile>
<DependentUpon>%(ParentFile).cs</DependentUpon>
</None>
<None Update="Expectations\Help\Greeter_Default.Output.verified.txt">
<ParentFile>$([System.String]::Copy('%(FileName)').Split('.')[0])</ParentFile>
<DependentUpon>%(ParentFile).cs</DependentUpon>
</None>
</ItemGroup>
</Project>

View File

@ -141,6 +141,64 @@ public sealed partial class CommandAppTests
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Default_Without_Args")]
public Task Should_Output_Default_Command_When_Command_Has_Required_Parameters_And_Is_Called_Without_Args()
{
// Given
var fixture = new CommandAppTester();
fixture.SetDefaultCommand<LionCommand>();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
});
// When
var result = fixture.Run();
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Default_Without_Args_Additional")]
public Task Should_Output_Default_Command_And_Additional_Commands_When_Default_Command_Has_Required_Parameters_And_Is_Called_Without_Args()
{
// Given
var fixture = new CommandAppTester();
fixture.SetDefaultCommand<LionCommand>();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
configurator.AddCommand<GiraffeCommand>("giraffe");
});
// When
var result = fixture.Run();
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Greeter_Default")]
public Task Should_Not_Output_Default_Command_When_Command_Has_No_Required_Parameters_And_Is_Called_Without_Args()
{
// Given
var fixture = new CommandAppTester();
fixture.SetDefaultCommand<GreeterCommand>();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
});
// When
var result = fixture.Run();
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("RootExamples")]
public Task Should_Output_Root_Examples_Defined_On_Root()