Skip to content

Commit 6274e0a

Browse files
authored
Merge pull request #771 from jonsequitur/add-global-options-and-make-help-a-proper-option
add global options, make -h a proper option
2 parents ad1ef32 + 8ec50ae commit 6274e0a

File tree

16 files changed

+250
-185
lines changed

16 files changed

+250
-185
lines changed

src/System.CommandLine.DragonFruit.Tests/CommandLineTests.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System.CommandLine.Rendering;
5-
using System.Reflection;
65
using System.Threading.Tasks;
76
using FluentAssertions;
87
using Xunit;
@@ -64,7 +63,7 @@ public async Task It_shows_help_text_based_on_XML_documentation_comments()
6463
.Contain("<args> These are arguments")
6564
.And.Contain("Arguments:");
6665
stdOut.Should()
67-
.Contain("--name <name> Specifies the name option")
66+
.ContainAll("--name <name>", "Specifies the name option")
6867
.And.Contain("Options:");
6968
stdOut.Should()
7069
.Contain("Help for the test program");
@@ -88,7 +87,7 @@ public void It_synchronously_shows_help_text_based_on_XML_documentation_comments
8887
.Contain("<args> These are arguments")
8988
.And.Contain("Arguments:");
9089
stdOut.Should()
91-
.Contain("--name <name> Specifies the name option")
90+
.ContainAll("--name <name>","Specifies the name option")
9291
.And.Contain("Options:");
9392
stdOut.Should()
9493
.Contain("Help for the test program");

src/System.CommandLine.Suggest.Tests/DotnetSuggestEndToEndTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ await Process.ExecuteAsync(
155155

156156
stdOut.ToString()
157157
.Should()
158-
.Be($"--apple{NewLine}--banana{NewLine}--cherry{NewLine}--durian{NewLine}--version{NewLine}");
158+
.Be($"--apple{NewLine}--banana{NewLine}--cherry{NewLine}--durian{NewLine}--help{NewLine}--version{NewLine}-?{NewLine}-h{NewLine}/?{NewLine}/h{NewLine}");
159159
}
160160
}
161161
}

src/System.CommandLine.Tests/CommandTests.cs

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -323,16 +323,44 @@ public void When_multiple_options_are_configured_then_they_must_differ_by_name()
323323
var command = new Command("the-command")
324324
{
325325
new Option("--same")
326-
{
327-
Argument = new Argument<string>()
328-
}
329326
};
330327

331328
command
332-
.Invoking(c => c.Add(new Option("--same")
333-
{
334-
Argument = new Argument<string>()
335-
}))
329+
.Invoking(c => c.Add(new Option("--same")))
330+
.Should()
331+
.Throw<ArgumentException>()
332+
.And
333+
.Message
334+
.Should()
335+
.Be("Alias '--same' is already in use.");
336+
}
337+
338+
[Fact]
339+
public void When_global_options_are_added_then_they_must_differ_from_local_options_by_name()
340+
{
341+
var command = new Command("the-command")
342+
{
343+
new Option("--same")
344+
};
345+
346+
command
347+
.Invoking(c => c.AddGlobalOption(new Option("--same")))
348+
.Should()
349+
.Throw<ArgumentException>()
350+
.And
351+
.Message
352+
.Should()
353+
.Be("Alias '--same' is already in use.");
354+
}
355+
356+
[Fact]
357+
public void When_local_options_are_added_then_they_must_differ_from_global_options_by_name()
358+
{
359+
var command = new Command("the-command");
360+
command.AddGlobalOption(new Option("--same"));
361+
362+
command
363+
.Invoking(c => c.Add(new Option("--same")))
336364
.Should()
337365
.Throw<ArgumentException>()
338366
.And

src/System.CommandLine.Tests/Help/HelpBuilderTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,51 @@ public void Required_options_are_indicated_when_argument_is_named()
11061106
.Contain("-r, --required <ARG> (REQUIRED)");
11071107
}
11081108

1109+
[Fact]
1110+
public void Help_option_is_shown_in_help()
1111+
{
1112+
var parser = new CommandLineBuilder()
1113+
.UseHelp()
1114+
.Build();
1115+
1116+
_helpBuilder.Write(parser.Configuration.RootCommand);
1117+
1118+
var help = _console.Out.ToString();
1119+
1120+
help.Should()
1121+
.Contain($"-?, -h, --help{_columnPadding}Show help and usage information");
1122+
}
1123+
1124+
[Fact]
1125+
public void Options_aliases_differing_only_by_prefix_are_deduplicated_favoring_dashed_prefixes()
1126+
{
1127+
var command = new RootCommand
1128+
{
1129+
new Option(new[] { "-x", "/x" })
1130+
};
1131+
1132+
_helpBuilder.Write(command);
1133+
1134+
var help = _console.Out.ToString();
1135+
1136+
help.Should().NotContain("/x");
1137+
}
1138+
1139+
[Fact]
1140+
public void Options_aliases_differing_only_by_prefix_are_deduplicated_favoring_double_dashed_prefixes()
1141+
{
1142+
var command = new RootCommand
1143+
{
1144+
new Option(new[] { "--long", "/long" })
1145+
};
1146+
1147+
_helpBuilder.Write(command);
1148+
1149+
var help = _console.Out.ToString();
1150+
1151+
help.Should().NotContain("/long");
1152+
}
1153+
11091154
#endregion Options
11101155

11111156
#region Subcommands

src/System.CommandLine.Tests/ParserTests.cs

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,26 +1625,6 @@ public void Arguments_can_match_the_aliases_of_sibling_options(string input)
16251625
valueForOption.Should().Be("-y");
16261626
}
16271627

1628-
[Theory]
1629-
[InlineData("/o")]
1630-
[InlineData("-o")]
1631-
[InlineData("--o")]
1632-
[InlineData("/output")]
1633-
[InlineData("-output")]
1634-
[InlineData("--output")]
1635-
public void Option_aliases_can_be_specified_and_are_prefixed_with_defaults(string input)
1636-
{
1637-
var option = new Option(new[] { "output", "o" });
1638-
var configuration = new CommandLineConfiguration(
1639-
new[] { option },
1640-
prefixes: new[] { "-", "--", "/" });
1641-
var parser = new Parser(configuration);
1642-
1643-
ParseResult parseResult = parser.Parse(input);
1644-
parseResult["output"].Should().NotBeNull();
1645-
parseResult["o"].Should().NotBeNull();
1646-
}
1647-
16481628
[Fact]
16491629
public void Option_aliases_do_not_need_to_be_prefixed()
16501630
{
@@ -1655,27 +1635,6 @@ public void Option_aliases_do_not_need_to_be_prefixed()
16551635
result.HasOption(option).Should().BeTrue();
16561636
}
16571637

1658-
[Theory]
1659-
[InlineData("/o")]
1660-
[InlineData("-o")]
1661-
[InlineData("--output")]
1662-
[InlineData("--out")]
1663-
[InlineData("-out")]
1664-
[InlineData("/out")]
1665-
public void Option_aliases_can_be_specified_for_particular_prefixes(string input)
1666-
{
1667-
var option = new Option(new[] { "--output", "-o", "/o", "out" });
1668-
var configuration = new CommandLineConfiguration(
1669-
new[] { option },
1670-
prefixes: new[] { "-", "--", "/" });
1671-
var parser = new Parser(configuration);
1672-
1673-
ParseResult parseResult = parser.Parse(input);
1674-
parseResult["o"].Should().NotBeNull();
1675-
parseResult["out"].Should().NotBeNull();
1676-
parseResult["output"].Should().NotBeNull();
1677-
}
1678-
16791638
[Fact]
16801639
public void Boolean_options_with_no_argument_specified_do_not_match_subsequent_arguments()
16811640
{

src/System.CommandLine.Tests/UseHelpTests.cs

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,6 @@ public async Task UseHelp_interrupts_execution_of_the_specified_command()
5555
wasCalled.Should().BeFalse();
5656
}
5757

58-
[Fact]
59-
public async Task UseHelp_allows_help_for_all_configured_prefixes()
60-
{
61-
var parser =
62-
new CommandLineBuilder()
63-
.AddCommand(new Command("command"))
64-
.UseHelp()
65-
.UsePrefixes(new[] { "~" })
66-
.Build();
67-
68-
await parser.InvokeAsync("command ~help", _console);
69-
70-
_console.Out.ToString().Should().StartWith("Usage:");
71-
}
72-
7358
[Theory]
7459
[InlineData("-h")]
7560
[InlineData("--help")]
@@ -89,12 +74,12 @@ public async Task UseHelp_accepts_default_values(string value)
8974
}
9075

9176
[Fact]
92-
public async Task UseHelp_accepts_collection_of_help_options()
77+
public async Task UseHelp_accepts_custom_aliases()
9378
{
9479
var parser =
9580
new CommandLineBuilder()
9681
.AddCommand(new Command("command"))
97-
.UseHelp(new[] { "~cthulhu" })
82+
.UseHelp(new Option(new[] { "~cthulhu" }))
9883
.Build();
9984

10085
await parser.InvokeAsync("command ~cthulhu", _console);
@@ -120,5 +105,38 @@ public async Task UseHelp_does_not_display_when_option_defined_with_same_alias()
120105

121106
_console.Out.ToString().Should().BeEmpty();
122107
}
108+
109+
[Fact]
110+
public void There_are_no_parse_errors_when_help_is_invoked_on_root_command()
111+
{
112+
var parser = new CommandLineBuilder()
113+
.UseHelp()
114+
.Build();
115+
116+
var result = parser.Parse("-h");
117+
118+
result.Errors
119+
.Should()
120+
.BeEmpty();
121+
}
122+
123+
[Fact]
124+
public void There_are_no_parse_errors_when_help_is_invoked_on_subcommand()
125+
{
126+
var command = new RootCommand
127+
{
128+
new Command("subcommand")
129+
};
130+
131+
var parser = new CommandLineBuilder(command)
132+
.UseHelp()
133+
.Build();
134+
135+
var result = parser.Parse("subcommand -h");
136+
137+
result.Errors
138+
.Should()
139+
.BeEmpty();
140+
}
123141
}
124142
}

src/System.CommandLine.Tests/VersionOptionTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public async Task Version_option_appears_in_help()
6666
console.Out
6767
.ToString()
6868
.Should()
69-
.Match("*Options:*--version*Display version information*");
69+
.Match("*Options:*--version*Show version information*");
7070
}
7171

7272
[Fact]

src/System.CommandLine/Argument.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ public override IEnumerable<string> GetSuggestions(string textToMatch = null)
192192
.Concat(dynamicSuggestions)
193193
.Concat(typeSuggestions)
194194
.Distinct()
195-
.OrderBy(c => c)
195+
.OrderBy(c => c, StringComparer.OrdinalIgnoreCase)
196196
.Containing(textToMatch);
197197
}
198198

src/System.CommandLine/Builder/CommandLineBuilder.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,19 @@ public CommandLineBuilder(Command rootCommand = null)
2323

2424
public bool EnablePosixBundling { get; set; } = true;
2525

26-
public IReadOnlyCollection<string> Prefixes { get; set; }
27-
2826
public ResponseFileHandling ResponseFileHandling { get; set; }
2927

3028
internal Func<BindingContext, IHelpBuilder> HelpBuilderFactory { get; set; }
3129

30+
internal Option HelpOption { get; set; }
31+
3232
public Parser Build()
3333
{
3434
var rootCommand = Command;
3535

3636
return new Parser(
3737
new CommandLineConfiguration(
3838
new[] { rootCommand },
39-
prefixes: Prefixes,
4039
enablePosixBundling: EnablePosixBundling,
4140
enableDirectives: EnableDirectives,
4241
validationMessages: ValidationMessages.Instance,

0 commit comments

Comments
 (0)