Allow using -? as a shorthand for -h

Given that it's quite a common switch and extremely unlikely to be already in use for something else, we can just consider it to be the same as having entered `-h` as an arg.

This adds the `?` as a valid option character name.

Fixes #1547
This commit is contained in:
Daniel Cazzulino 2024-05-17 18:08:29 -03:00 committed by Patrik Svensson
parent 0e2ed511a5
commit 5c87d7fa04
6 changed files with 72 additions and 3 deletions

View File

@ -86,7 +86,7 @@ internal static class TemplateParser
foreach (var character in token.Value) foreach (var character in token.Value)
{ {
if (!char.IsLetterOrDigit(character) && character != '-' && character != '_') if (!char.IsLetterOrDigit(character) && character != '-' && character != '_' && character != '?')
{ {
throw CommandTemplateException.InvalidCharacterInOptionName(template, token, character); throw CommandTemplateException.InvalidCharacterInOptionName(template, token, character);
} }

View File

@ -21,7 +21,7 @@ internal class CommandTreeParser
{ {
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
_parsingMode = parsingMode ?? _configuration.ParsingMode; _parsingMode = parsingMode ?? _configuration.ParsingMode;
_help = new CommandOptionAttribute("-h|--help"); _help = new CommandOptionAttribute("-?|-h|--help");
_convertFlagsToRemainingArguments = convertFlagsToRemainingArguments ?? false; _convertFlagsToRemainingArguments = convertFlagsToRemainingArguments ?? false;
CaseSensitivity = caseSensitivity; CaseSensitivity = caseSensitivity;

View File

@ -176,7 +176,7 @@ internal static class CommandTreeTokenizer
break; break;
} }
if (char.IsLetter(current)) if (char.IsLetter(current) || current is '?')
{ {
context.AddRemaining(current); context.AddRemaining(current);
reader.Read(); // Consume reader.Read(); // Consume

View File

@ -0,0 +1,10 @@
USAGE:
myapp [OPTIONS] <COMMAND>
OPTIONS:
-h, --help Prints help information
COMMANDS:
dog <AGE> The dog command
horse The horse command
giraffe <LENGTH> The giraffe command

View File

@ -0,0 +1,17 @@
DESCRIPTION:
The horse command.
USAGE:
myapp horse [LEGS] [OPTIONS]
ARGUMENTS:
[LEGS] The number of legs
OPTIONS:
DEFAULT
-h, --help Prints help information
-a, --alive Indicates whether or not the animal is alive
-n, --name <VALUE>
-d, --day <MON|TUE>
--file food.txt
--directory

View File

@ -28,6 +28,27 @@ public sealed partial class CommandAppTests
return Verifier.Verify(result.Output); return Verifier.Verify(result.Output);
} }
[Fact]
[Expectation("Root", "QuestionMark")]
public Task Should_Output_Root_Correctly_QuestionMark()
{
// Given
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
configurator.AddCommand<DogCommand>("dog");
configurator.AddCommand<HorseCommand>("horse");
configurator.AddCommand<GiraffeCommand>("giraffe");
});
// When
var result = fixture.Run("-?");
// Then
return Verifier.Verify(result.Output);
}
[Fact] [Fact]
[Expectation("Root_Command")] [Expectation("Root_Command")]
public Task Should_Output_Root_Command_Correctly() public Task Should_Output_Root_Command_Correctly()
@ -49,6 +70,27 @@ public sealed partial class CommandAppTests
return Verifier.Verify(result.Output); return Verifier.Verify(result.Output);
} }
[Fact]
[Expectation("Root_Command", "QuestionMark")]
public Task Should_Output_Root_Command_Correctly_QuestionMark()
{
// Given
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
configurator.AddCommand<DogCommand>("dog");
configurator.AddCommand<HorseCommand>("horse");
configurator.AddCommand<GiraffeCommand>("giraffe");
});
// When
var result = fixture.Run("horse", "-?");
// Then
return Verifier.Verify(result.Output);
}
[Fact] [Fact]
[Expectation("Hidden_Commands")] [Expectation("Hidden_Commands")]
public Task Should_Skip_Hidden_Commands() public Task Should_Skip_Hidden_Commands()