Skip to content

Commit 48d6bff

Browse files
authored
fix #2589 (#2654)
1 parent bbfa637 commit 48d6bff

File tree

2 files changed

+79
-4
lines changed

2 files changed

+79
-4
lines changed

src/System.CommandLine.Tests/HelpOptionTests.cs

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.CommandLine.Invocation;
77
using System.CommandLine.Tests.Utility;
88
using System.IO;
9+
using System.Linq;
910
using System.Threading;
1011
using System.Threading.Tasks;
1112
using Xunit;
@@ -239,9 +240,9 @@ public void The_users_can_set_max_width()
239240

240241
RootCommand rootCommand = new(description);
241242
rootCommand.Options.Clear();
242-
rootCommand.Options.Add(new HelpOption()
243+
rootCommand.Options.Add(new HelpOption
243244
{
244-
Action = new HelpAction()
245+
Action = new HelpAction
245246
{
246247
MaxWidth = 2 /* each line starts with two spaces */ + description.Length / 2
247248
}
@@ -286,6 +287,79 @@ public void DefaultValueFactory_does_not_throw_when_help_is_invoked()
286287
invocationConfiguration.Error.ToString().Should().Be("");
287288
}
288289

290+
[Fact] // https://github.com/dotnet/command-line-api/issues/2589
291+
public void Help_and_version_options_are_displayed_after_other_options_on_root_command()
292+
{
293+
var command = new RootCommand
294+
{
295+
Subcommands =
296+
{
297+
new Command("subcommand")
298+
{
299+
Description = "The subcommand"
300+
}
301+
},
302+
Options =
303+
{
304+
new Option<int>("-i")
305+
{
306+
Description = "The option"
307+
}
308+
}
309+
};
310+
311+
var output = new StringWriter();
312+
313+
314+
command.Parse("-h").Invoke(new() { Output = output });
315+
316+
output.ToString()
317+
.Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries)
318+
.Select(line => line.Trim())
319+
.Should()
320+
.ContainInOrder([
321+
"Options:",
322+
"-i The option",
323+
"-?, -h, --help Show help and usage information",
324+
"--version Show version information",
325+
"Commands:"
326+
]);
327+
}
328+
329+
[Fact] // https://github.com/dotnet/command-line-api/issues/2589
330+
public void Help_and_version_options_are_displayed_after_other_options_on_subcommand()
331+
{
332+
var command = new RootCommand
333+
{
334+
Subcommands =
335+
{
336+
new Command("subcommand")
337+
{
338+
Description = "The subcommand", Options =
339+
{
340+
new Option<int>("-i")
341+
{
342+
Description = "The option"
343+
}
344+
}
345+
}
346+
}
347+
};
348+
349+
var output = new StringWriter();
350+
351+
command.Parse("subcommand -h").Invoke(new() { Output = output });
352+
353+
output.ToString()
354+
.Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries)
355+
.Select(line => line.Trim())
356+
.Should()
357+
.ContainInOrder([
358+
"Options:",
359+
"-i The option",
360+
"-?, -h, --help Show help and usage information",
361+
]);
362+
}
289363

290364
private sealed class CustomizedHelpAction : SynchronousCommandLineAction
291365
{

src/System.CommandLine/Help/HelpBuilder.Default.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,16 @@ public static Func<HelpContext, bool> OptionsSection() =>
215215
{
216216
List<TwoColumnHelpRow> optionRows = new();
217217
bool addedHelpOption = false;
218-
foreach (Option option in ctx.Command.Options)
218+
foreach (Option option in ctx.Command.Options.OrderBy(o => o is HelpOption or VersionOption))
219219
{
220220
if (!option.Hidden)
221221
{
222-
optionRows.Add(ctx.HelpBuilder.GetTwoColumnRow(option, ctx));
223222
if (option is HelpOption)
224223
{
225224
addedHelpOption = true;
226225
}
226+
227+
optionRows.Add(ctx.HelpBuilder.GetTwoColumnRow(option, ctx));
227228
}
228229
}
229230

0 commit comments

Comments
 (0)