diff --git a/src/Spectre.Console.Cli/Internal/Configuration/TemplateParser.cs b/src/Spectre.Console.Cli/Internal/Configuration/TemplateParser.cs index d7eef9b..1259472 100644 --- a/src/Spectre.Console.Cli/Internal/Configuration/TemplateParser.cs +++ b/src/Spectre.Console.Cli/Internal/Configuration/TemplateParser.cs @@ -86,7 +86,7 @@ internal static class TemplateParser 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); } diff --git a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParser.cs b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParser.cs index e4fad73..d985dcb 100644 --- a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParser.cs +++ b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeParser.cs @@ -21,7 +21,7 @@ internal class CommandTreeParser { _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _parsingMode = parsingMode ?? _configuration.ParsingMode; - _help = new CommandOptionAttribute("-h|--help"); + _help = new CommandOptionAttribute("-?|-h|--help"); _convertFlagsToRemainingArguments = convertFlagsToRemainingArguments ?? false; CaseSensitivity = caseSensitivity; diff --git a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizer.cs b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizer.cs index 27e6edb..840b072 100644 --- a/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizer.cs +++ b/src/Spectre.Console.Cli/Internal/Parsing/CommandTreeTokenizer.cs @@ -176,7 +176,7 @@ internal static class CommandTreeTokenizer break; } - if (char.IsLetter(current)) + if (char.IsLetter(current) || current is '?') { context.AddRemaining(current); reader.Read(); // Consume diff --git a/test/Spectre.Console.Cli.Tests/Expectations/Help/Root.QuestionMark.verified.txt b/test/Spectre.Console.Cli.Tests/Expectations/Help/Root.QuestionMark.verified.txt new file mode 100644 index 0000000..0432fe4 --- /dev/null +++ b/test/Spectre.Console.Cli.Tests/Expectations/Help/Root.QuestionMark.verified.txt @@ -0,0 +1,10 @@ +USAGE: + myapp [OPTIONS] + +OPTIONS: + -h, --help Prints help information + +COMMANDS: + dog The dog command + horse The horse command + giraffe The giraffe command \ No newline at end of file diff --git a/test/Spectre.Console.Cli.Tests/Expectations/Help/Root_Command.QuestionMark.verified.txt b/test/Spectre.Console.Cli.Tests/Expectations/Help/Root_Command.QuestionMark.verified.txt new file mode 100644 index 0000000..03c6875 --- /dev/null +++ b/test/Spectre.Console.Cli.Tests/Expectations/Help/Root_Command.QuestionMark.verified.txt @@ -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 + -d, --day + --file food.txt + --directory \ No newline at end of file diff --git a/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Help.cs b/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Help.cs index 9ce30cc..8d3af80 100644 --- a/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Help.cs +++ b/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Help.cs @@ -28,6 +28,27 @@ public sealed partial class CommandAppTests 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("dog"); + configurator.AddCommand("horse"); + configurator.AddCommand("giraffe"); + }); + + // When + var result = fixture.Run("-?"); + + // Then + return Verifier.Verify(result.Output); + } + [Fact] [Expectation("Root_Command")] public Task Should_Output_Root_Command_Correctly() @@ -49,6 +70,27 @@ public sealed partial class CommandAppTests 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("dog"); + configurator.AddCommand("horse"); + configurator.AddCommand("giraffe"); + }); + + // When + var result = fixture.Run("horse", "-?"); + + // Then + return Verifier.Verify(result.Output); + } + [Fact] [Expectation("Hidden_Commands")] public Task Should_Skip_Hidden_Commands()