Skip to content

Commit 3acc90e

Browse files
Make -v|--version opt-in
We added an automatic version option in 0.49. We did this with good intentions, but forgot that people might already use --version as an option for a root command. This commit makes -v|--version completely opt-in.
1 parent 88515b7 commit 3acc90e

File tree

36 files changed

+276
-211
lines changed

36 files changed

+276
-211
lines changed

src/Spectre.Console.Cli/Help/HelpProvider.cs

Lines changed: 78 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ private sealed class HelpArgument
4141
public bool Required { get; }
4242
public string? Description { get; }
4343

44-
public HelpArgument(string name, int position, bool required, string? description)
44+
private HelpArgument(string name, int position, bool required, string? description)
4545
{
4646
Name = name;
4747
Position = position;
@@ -68,7 +68,7 @@ private sealed class HelpOption
6868
public string? Description { get; }
6969
public object? DefaultValue { get; }
7070

71-
public HelpOption(string? @short, string? @long, string? @value, bool? valueIsOptional, string? description, object? defaultValue)
71+
private HelpOption(string? @short, string? @long, string? @value, bool? valueIsOptional, string? description, object? defaultValue)
7272
{
7373
Short = @short;
7474
Long = @long;
@@ -78,17 +78,27 @@ public HelpOption(string? @short, string? @long, string? @value, bool? valueIsOp
7878
DefaultValue = defaultValue;
7979
}
8080

81-
public static IReadOnlyList<HelpOption> Get(ICommandInfo? command, HelpProviderResources resources)
81+
public static IReadOnlyList<HelpOption> Get(
82+
ICommandModel model,
83+
ICommandInfo? command,
84+
HelpProviderResources resources)
8285
{
83-
var parameters = new List<HelpOption>();
84-
parameters.Add(new HelpOption("h", "help", null, null, resources.PrintHelpDescription, null));
86+
var parameters = new List<HelpOption>
87+
{
88+
new HelpOption("h", "help", null, null, resources.PrintHelpDescription, null),
89+
};
8590

8691
// Version information applies to the entire application
8792
// Include the "-v" option in the help when at the root of the command line application
8893
// Don't allow the "-v" option if users have specified one or more sub-commands
89-
if ((command == null || command?.Parent == null) && !(command?.IsBranch ?? false))
94+
if ((command?.Parent == null) && !(command?.IsBranch ?? false))
9095
{
91-
parameters.Add(new HelpOption("v", "version", null, null, resources.PrintVersionDescription, null));
96+
// Only show the version command if there is an
97+
// application version set.
98+
if (model.ApplicationVersion != null)
99+
{
100+
parameters.Add(new HelpOption("v", "version", null, null, resources.PrintVersionDescription, null));
101+
}
92102
}
93103

94104
parameters.AddRange(command?.Parameters.OfType<ICommandOption>().Where(o => !o.IsHidden).Select(o =>
@@ -101,11 +111,6 @@ public static IReadOnlyList<HelpOption> Get(ICommandInfo? command, HelpProviderR
101111
}
102112
}
103113

104-
internal Composer NewComposer()
105-
{
106-
return new Composer(RenderMarkupInline);
107-
}
108-
109114
/// <summary>
110115
/// Initializes a new instance of the <see cref="HelpProvider"/> class.
111116
/// </summary>
@@ -383,7 +388,7 @@ public virtual IEnumerable<IRenderable> GetArguments(ICommandModel model, IComma
383388
public virtual IEnumerable<IRenderable> GetOptions(ICommandModel model, ICommandInfo? command)
384389
{
385390
// Collect all options into a single structure.
386-
var parameters = HelpOption.Get(command, resources);
391+
var parameters = HelpOption.Get(model, command, resources);
387392
if (parameters.Count == 0)
388393
{
389394
return Array.Empty<IRenderable>();
@@ -420,7 +425,7 @@ public virtual IEnumerable<IRenderable> GetOptions(ICommandModel model, ICommand
420425

421426
if (defaultValueColumn)
422427
{
423-
columns.Add(GetOptionDefaultValue(option.DefaultValue));
428+
columns.Add(GetDefaultValueForOption(option.DefaultValue));
424429
}
425430

426431
columns.Add(NewComposer().Text(option.Description?.TrimEnd('.') ?? " "));
@@ -433,60 +438,6 @@ public virtual IEnumerable<IRenderable> GetOptions(ICommandModel model, ICommand
433438
return result;
434439
}
435440

436-
private IRenderable GetOptionParts(HelpOption option)
437-
{
438-
var composer = NewComposer();
439-
440-
if (option.Short != null)
441-
{
442-
composer.Text("-").Text(option.Short);
443-
if (option.Long != null)
444-
{
445-
composer.Text(", ");
446-
}
447-
}
448-
else
449-
{
450-
composer.Text(" ");
451-
if (option.Long != null)
452-
{
453-
composer.Text(" ");
454-
}
455-
}
456-
457-
if (option.Long != null)
458-
{
459-
composer.Text("--").Text(option.Long);
460-
}
461-
462-
if (option.Value != null)
463-
{
464-
composer.Text(" ");
465-
if (option.ValueIsOptional ?? false)
466-
{
467-
composer.Style(helpStyles?.Options?.OptionalOption ?? Style.Plain, $"[{option.Value}]");
468-
}
469-
else
470-
{
471-
composer.Style(helpStyles?.Options?.RequiredOption ?? Style.Plain, $"<{option.Value}>");
472-
}
473-
}
474-
475-
return composer;
476-
}
477-
478-
private IRenderable GetOptionDefaultValue(object? defaultValue)
479-
{
480-
return defaultValue switch
481-
{
482-
null => NewComposer().Text(" "),
483-
"" => NewComposer().Text(" "),
484-
Array { Length: 0 } => NewComposer().Text(" "),
485-
Array array => NewComposer().Join(", ", array.Cast<object>().Select(o => NewComposer().Style(helpStyles?.Options?.DefaultValue ?? Style.Plain, o.ToString() ?? string.Empty))),
486-
_ => NewComposer().Style(helpStyles?.Options?.DefaultValue ?? Style.Plain, defaultValue?.ToString() ?? string.Empty),
487-
};
488-
}
489-
490441
/// <summary>
491442
/// Gets the commands section of the help information.
492443
/// </summary>
@@ -556,4 +507,63 @@ public virtual IEnumerable<IRenderable> GetFooter(ICommandModel model, ICommandI
556507
{
557508
yield break;
558509
}
510+
511+
private Composer NewComposer()
512+
{
513+
return new Composer(RenderMarkupInline);
514+
}
515+
516+
private IRenderable GetOptionParts(HelpOption option)
517+
{
518+
var composer = NewComposer();
519+
520+
if (option.Short != null)
521+
{
522+
composer.Text("-").Text(option.Short);
523+
if (option.Long != null)
524+
{
525+
composer.Text(", ");
526+
}
527+
}
528+
else
529+
{
530+
composer.Text(" ");
531+
if (option.Long != null)
532+
{
533+
composer.Text(" ");
534+
}
535+
}
536+
537+
if (option.Long != null)
538+
{
539+
composer.Text("--").Text(option.Long);
540+
}
541+
542+
if (option.Value != null)
543+
{
544+
composer.Text(" ");
545+
if (option.ValueIsOptional ?? false)
546+
{
547+
composer.Style(helpStyles?.Options?.OptionalOption ?? Style.Plain, $"[{option.Value}]");
548+
}
549+
else
550+
{
551+
composer.Style(helpStyles?.Options?.RequiredOption ?? Style.Plain, $"<{option.Value}>");
552+
}
553+
}
554+
555+
return composer;
556+
}
557+
558+
private Composer GetDefaultValueForOption(object? defaultValue)
559+
{
560+
return defaultValue switch
561+
{
562+
null => NewComposer().Text(" "),
563+
"" => NewComposer().Text(" "),
564+
Array { Length: 0 } => NewComposer().Text(" "),
565+
Array array => NewComposer().Join(", ", array.Cast<object>().Select(o => NewComposer().Style(helpStyles?.Options?.DefaultValue ?? Style.Plain, o.ToString() ?? string.Empty))),
566+
_ => NewComposer().Style(helpStyles?.Options?.DefaultValue ?? Style.Plain, defaultValue?.ToString() ?? string.Empty),
567+
};
568+
}
559569
}

src/Spectre.Console.Cli/Help/ICommandModel.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,9 @@ public interface ICommandModel : ICommandContainer
99
/// Gets the name of the application.
1010
/// </summary>
1111
string ApplicationName { get; }
12+
13+
/// <summary>
14+
/// Gets the version of the application.
15+
/// </summary>
16+
string? ApplicationVersion { get; }
1217
}

src/Spectre.Console.Cli/Internal/CommandExecutor.cs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,12 @@ public async Task<int> Execute(IConfiguration configuration, IEnumerable<string>
3939
if (firstArgument.Equals("--version", StringComparison.OrdinalIgnoreCase) ||
4040
firstArgument.Equals("-v", StringComparison.OrdinalIgnoreCase))
4141
{
42-
var console = configuration.Settings.Console.GetConsole();
43-
console.WriteLine(ResolveApplicationVersion(configuration));
44-
return 0;
42+
if (configuration.Settings.ApplicationVersion != null)
43+
{
44+
var console = configuration.Settings.Console.GetConsole();
45+
console.MarkupLine(configuration.Settings.ApplicationVersion);
46+
return 0;
47+
}
4548
}
4649
}
4750
}
@@ -126,13 +129,6 @@ private CommandTreeParserResult ParseCommandLineArguments(CommandModel model, Co
126129
return parsedResult;
127130
}
128131

129-
private static string ResolveApplicationVersion(IConfiguration configuration)
130-
{
131-
return
132-
configuration.Settings.ApplicationVersion ?? // potential override
133-
VersionHelper.GetVersion(Assembly.GetEntryAssembly());
134-
}
135-
136132
private static async Task<int> Execute(
137133
CommandTree leaf,
138134
CommandTree tree,

src/Spectre.Console.Cli/Internal/Modelling/CommandModel.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ namespace Spectre.Console.Cli;
33
internal sealed class CommandModel : ICommandContainer, ICommandModel
44
{
55
public string? ApplicationName { get; }
6+
public string? ApplicationVersion { get; }
67
public ParsingMode ParsingMode { get; }
78
public IList<CommandInfo> Commands { get; }
89
public IList<string[]> Examples { get; }
@@ -20,9 +21,10 @@ public CommandModel(
2021
IEnumerable<string[]> examples)
2122
{
2223
ApplicationName = settings.ApplicationName;
24+
ApplicationVersion = settings.ApplicationVersion;
2325
ParsingMode = settings.ParsingMode;
24-
Commands = new List<CommandInfo>(commands ?? Array.Empty<CommandInfo>());
25-
Examples = new List<string[]>(examples ?? Array.Empty<string[]>());
26+
Commands = new List<CommandInfo>(commands);
27+
Examples = new List<string[]>(examples);
2628
}
2729

2830
/// <summary>
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
USAGE:
1+
USAGE:
22
myapp <FOO> <BAR> <BAZ> <CORGI> [QUX] [OPTIONS]
33

44
ARGUMENTS:
@@ -9,5 +9,4 @@ ARGUMENTS:
99
[QUX]
1010

1111
OPTIONS:
12-
-h, --help Prints help information
13-
-v, --version Prints version information
12+
-h, --help Prints help information
Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
--------------------------------------
2-
--- CUSTOM HELP PROVIDER ---
3-
--------------------------------------
4-
5-
USAGE:
6-
myapp [OPTIONS] <COMMAND>
7-
8-
OPTIONS:
9-
-h, --help Prints help information
10-
-v, --version Prints version information
11-
12-
COMMANDS:
13-
dog <AGE> The dog command
14-
1+
--------------------------------------
2+
--- CUSTOM HELP PROVIDER ---
3+
--------------------------------------
4+
5+
USAGE:
6+
myapp [OPTIONS] <COMMAND>
7+
8+
OPTIONS:
9+
-h, --help Prints help information
10+
11+
COMMANDS:
12+
dog <AGE> The dog command
13+
1514
Version 1.0

test/Spectre.Console.Cli.Tests/Expectations/Help/Custom_Help_Registered_By_Instance.Output.verified.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
--------------------------------------
1+
--------------------------------------
22
--- CUSTOM HELP PROVIDER ---
33
--------------------------------------
44

55
USAGE:
66
myapp [OPTIONS] <COMMAND>
77

88
OPTIONS:
9-
-h, --help Prints help information
10-
-v, --version Prints version information
9+
-h, --help Prints help information
1110

1211
COMMANDS:
1312
dog <AGE> The dog command

test/Spectre.Console.Cli.Tests/Expectations/Help/Default.Output.verified.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
DESCRIPTION:
1+
DESCRIPTION:
22
The lion command.
33

44
USAGE:
@@ -10,8 +10,7 @@ ARGUMENTS:
1010

1111
OPTIONS:
1212
DEFAULT
13-
-h, --help Prints help information
14-
-v, --version Prints version information
13+
-h, --help Prints help information
1514
-a, --alive Indicates whether or not the animal is alive
1615
-n, --name <VALUE>
1716
--agility <VALUE> 10 The agility between 0 and 100

test/Spectre.Console.Cli.Tests/Expectations/Help/Default_Examples.Output.verified.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
DESCRIPTION:
1+
DESCRIPTION:
22
The dog command.
33

44
USAGE:
@@ -18,7 +18,6 @@ ARGUMENTS:
1818

1919
OPTIONS:
2020
-h, --help Prints help information
21-
-v, --version Prints version information
2221
-a, --alive Indicates whether or not the animal is alive
2322
-n, --name <VALUE>
2423
-g, --good-boy

test/Spectre.Console.Cli.Tests/Expectations/Help/Default_Without_Args.Output.verified.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
DESCRIPTION:
1+
DESCRIPTION:
22
The lion command.
33

44
USAGE:
@@ -10,8 +10,7 @@ ARGUMENTS:
1010

1111
OPTIONS:
1212
DEFAULT
13-
-h, --help Prints help information
14-
-v, --version Prints version information
13+
-h, --help Prints help information
1514
-a, --alive Indicates whether or not the animal is alive
1615
-n, --name <VALUE>
1716
--agility <VALUE> 10 The agility between 0 and 100

0 commit comments

Comments
 (0)