Skip to content

Commit f97804c

Browse files
committed
Update CHANGELOG, release notes, and polish a few API for the 2.3.0-alpha release
* Get rid of ClusterOptions on CommandAttribute: still need to noodle on this one and ParserSettings * Get rid of APIs named "alias". Just use "names" instead for consistency with options.
1 parent 8367e32 commit f97804c

File tree

8 files changed

+82
-56
lines changed

8 files changed

+82
-56
lines changed

CHANGELOG.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Changelog
22

3-
## [Unreleased]
3+
## [2.3.0-alpha]
44

55
Enhancements:
66

@@ -10,8 +10,8 @@ Enhancements:
1010
* New type: `Pager`. Provides a simple interaction model for displaying console output in a pager.
1111
* Display help text using the `less` pager on macOS/Linux.
1212
* Make suggestions when invalid options or commands are used, but there is a valid one that is similar.
13-
(Thanks to [@MadbHatter][@MadbHatter] for doing the inital work on this.)
14-
* Add support for subcommand aliases.
13+
(Thanks to [@MadbHatter][@MadbHatter] for doing the initial work on this.)
14+
* Add support for subcommand aliases. Commands can be given multiple names.
1515

1616
```c#
1717
[Command("organization", "org", "o")]
@@ -25,6 +25,7 @@ Enhancements:
2525

2626
public class AddCommand { } // subcommand name = "add"
2727
```
28+
* [@lvermeulen]: Sort subcommands by name in help text. This can be disabled with `DefaultHelpTextGenerator.SortCommandsByName`.
2829

2930
Bugs fixed:
3031

@@ -39,8 +40,8 @@ Details:
3940

4041
* **Clustering options:** I've added this behavior as the new default, but only if I think it won't interfere with existing apps.
4142
If it causes issues or you don't like clustering, you can disable this by setting
42-
`CommandLineApplication.ParserSettings.ClusterOptions = false`, or adding `[Command(ClusterOptions = false)]`.
43-
To preserve compatibilty with existing apps, this behavior is off if you have configured options with short names with
43+
`CommandLineApplication.ParserSettings.ClusterOptions = false`.
44+
To preserve compatibility with existing apps, this behavior is off if you have configured options with short names with
4445
multiple characters. In a future version, this will cause an error unless you set `ClusterOptions = false`.
4546

4647
* **Pager:** this is the new default for showing help text. The pager should have graceful fallback to regular stdout
@@ -94,7 +95,7 @@ Bug fixes:
9495
- Don't assign option and argument options if no value was provided, preserving the default CLR value unless there is user-input.
9596
- Fix ShowHint() to use ShortName or SymbolName if OptionHelp.LongName is not set
9697
- Fix [#85](https://github.com/natemcmaster/CommandLineUtils/issues/85) - lower priority of resolving AdditionalServices after most built-in services
97-
- Fix [#79](https://github.com/natemcmaster/CommandLineUtils/issues/79) - OnValidate callbacks invoked before property valueswere assigned
98+
- Fix [#79](https://github.com/natemcmaster/CommandLineUtils/issues/79) - OnValidate callbacks invoked before property values were assigned
9899

99100
Minor improvements:
100101

@@ -105,7 +106,7 @@ Minor improvements:
105106
**March 30, 2018**
106107

107108
- Added support for command validators using `CommandLineApplication.Validators` and added a new OnValidate convention
108-
- Fix minor bug in ArgumentEscaper where some strings were not properly escaped
109+
- Fix minor bug in `ArgumentEscaper` where some strings were not properly escaped
109110
- Update to System.ComponentModel.Annotations 4.4.1 (netstandard2.0 only)
110111
- [@atruskie]: Ensure ValueParsers are inherited in subcommands
111112

@@ -227,12 +228,14 @@ Other:
227228
[@jerriep]: https://github.com/jerriep
228229
[@kant2002]: https://github.com/kant2002
229230
[@liamdawson]: https://github.com/liamdawson
231+
[@lvermeulen]: https://github.com/lvermeulen
230232
[@MadbHatter]: https://github.com/MadbHatter
231233
[@rmcc13]: https://github.com/rmcc13
232234
[@SeanFeldman]: https://github.com/SeanFeldman
233235
[@sebastienros]: https://github.com/sebastienros
234236

235237
[Unreleased]: https://github.com/natemcmaster/CommandLineUtils/compare/v2.2.5...HEAD
238+
[v2.3.0-alpha]: https://github.com/natemcmaster/CommandLineUtils/compare/v2.2.5...v2.3.0-alpha
236239
[v2.2.5]: https://github.com/natemcmaster/CommandLineUtils/compare/v2.2.4...v2.2.5
237240
[v2.2.4]: https://github.com/natemcmaster/CommandLineUtils/compare/v2.2.3...v2.2.4
238241
[v2.2.3]: https://github.com/natemcmaster/CommandLineUtils/compare/v2.2.3...v2.2.3

releasenotes.props

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,53 @@
11
<Project>
22
<PropertyGroup>
3+
<PackageReleaseNotes Condition="'$(VersionPrefix)' == '2.3.0'">
4+
<![CDATA[
5+
6+
Enhancements:
7+
8+
* Support the POSIX convention for cluster multiple options. For example, `-ixd` is treated the same as `-i -x -d`.
9+
10+
* @bjorg: support SingleOrNoValue notation. `--option[:value]`
11+
12+
* New type: `Pager`. Provides a simple interaction model for displaying console output in a pager.
13+
14+
* Display help text using the `less` pager on macOS/Linux.
15+
16+
* Make suggestions when invalid options or commands are used, but there is a valid one that is similar.
17+
(Thanks to @MadbHatter for doing the initial work on this.)
18+
19+
* Add support for subcommand aliases. Commands can be given multiple names.
20+
```c#
21+
[Command("organization", "org", "o")]
22+
public class OrgCommand { }
23+
```
24+
25+
* Obsolete the constructor of `[Subcommand]` which takes a string.
26+
27+
* Infer subcommand names from the type name
28+
```c#
29+
[Subcommand(typeof(AddCommand))]
30+
public class Git { }
31+
32+
public class AddCommand { } // subcommand name = "add"
33+
```
34+
35+
* @lvermeulen: Sort subcommands by name in help text. This can be disabled with `DefaultHelpTextGenerator.SortCommandsByName`.
36+
37+
Bugs fixed:
38+
39+
* Duplicate subcommand names used to cause undefined behavior. Now, attempting to add a duplicate subcommand name or aliases will
40+
cause the library to throw before the app can execute.
41+
42+
* Fix bug in subcommand name inference. When not specified, the subcommand always matched the entry assembly name.
43+
In this update, this convention only applies to the parent command.
44+
45+
* Add generic overloads of `.IsRequired()` for `CommandOption<T>` and `CommandArgument<T>`.
46+
47+
48+
See more details here: https://github.com/natemcmaster/CommandLineUtils/blob/master/CHANGELOG.md#v$(VersionPrefix.Replace('.',''))
49+
]]>
50+
</PackageReleaseNotes>
351
<PackageReleaseNotes Condition="'$(VersionPrefix)' == '2.2.5'">
452
<![CDATA[
553
Bug fixes:

src/CommandLineUtils/Attributes/CommandAttribute.cs

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ namespace McMaster.Extensions.CommandLineUtils
1414
[AttributeUsage(AttributeTargets.Class)]
1515
public sealed class CommandAttribute : Attribute
1616
{
17-
private bool? _clusterOptions;
1817
private string[] _names = Util.EmptyArray<string>();
1918

2019
/// <summary>
@@ -35,11 +34,10 @@ public CommandAttribute(string name)
3534
/// <summary>
3635
/// Initializes a new <see cref="CommandAttribute"/>.
3736
/// </summary>
38-
/// <param name="name">The primary name of the command.</param>
39-
/// <param name="aliases">The names of the command.</param>
40-
public CommandAttribute(string name, params string[] aliases)
37+
/// <param name="names">The names of the command. The first name given is the primary name</param>
38+
public CommandAttribute(params string[] names)
4139
{
42-
_names = new[] { name }.Concat(aliases).ToArray();
40+
_names = names;
4341
}
4442

4543
/// <summary>
@@ -102,31 +100,14 @@ public string Name
102100
/// </summary>
103101
public CultureInfo ParseCulture { get; set; } = CultureInfo.CurrentCulture;
104102

105-
/// <summary>
106-
/// <para>
107-
/// One or more options of <see cref="CommandOptionType.NoValue"/>, followed by at most one option that takes values, should be accepted when grouped behind one '-' delimiter.
108-
/// </para>
109-
/// <para>
110-
/// This defaults to true unless an option with a short name of two or more characters is added.
111-
/// </para>
112-
/// <para>
113-
/// See <see cref="ParserSettings.ClusterOptions"/> for more details.
114-
/// </para>
115-
/// </summary>
116-
public bool ClusterOptions
117-
{
118-
get => _clusterOptions ?? true;
119-
set => _clusterOptions = value;
120-
}
121-
122103
internal void Configure(CommandLineApplication app)
123104
{
124105
// this might have been set from SubcommandAttribute
125106
app.Name = Name ?? app.Name;
126107

127-
foreach (var alias in Names.Skip(1))
108+
foreach (var name in Names.Skip(1))
128109
{
129-
app.AddAlias(alias);
110+
app.AddName(name);
130111
}
131112

132113
app.AllowArgumentSeparator = AllowArgumentSeparator;
@@ -138,12 +119,6 @@ internal void Configure(CommandLineApplication app)
138119
app.ThrowOnUnexpectedArgument = ThrowOnUnexpectedArgument;
139120
app.OptionsComparison = OptionsComparison;
140121
app.ValueParsers.ParseCulture = ParseCulture;
141-
142-
// detect if this is explicitly set. Otherwise, we try to infer if clustering options is okay.
143-
if (_clusterOptions.HasValue)
144-
{
145-
app.ParserSettings.ClusterOptions = ClusterOptions;
146-
}
147122
}
148123
}
149124
}

src/CommandLineUtils/CommandLineApplication.cs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public partial class CommandLineApplication : IServiceProvider
2626
private List<Action<ParseResult>> _onParsingComplete;
2727
internal readonly Dictionary<string, PropertyInfo> _shortOptions = new Dictionary<string, PropertyInfo>();
2828
internal readonly Dictionary<string, PropertyInfo> _longOptions = new Dictionary<string, PropertyInfo>();
29-
private readonly HashSet<string> _aliases = new HashSet<string>(StringComparer.Ordinal);
29+
private readonly HashSet<string> _names = new HashSet<string>(StringComparer.Ordinal);
3030

3131

3232
private const int HelpExitCode = 0;
@@ -171,7 +171,7 @@ public string Name
171171
public List<CommandOption> Options { get; private set; }
172172

173173
/// <summary>
174-
/// All names by which the command can be referenced. This includes <see cref="Name"/> and an aliases added in <see cref="AddAlias"/>.
174+
/// All names by which the command can be referenced. This includes <see cref="Name"/> and an aliases added in <see cref="AddName"/>.
175175
/// </summary>
176176
public IEnumerable<string> Names
177177
{
@@ -182,9 +182,9 @@ public IEnumerable<string> Names
182182
yield return Name;
183183
}
184184

185-
foreach (var alias in _aliases)
185+
foreach (var names in _names)
186186
{
187-
yield return alias;
187+
yield return names;
188188
}
189189
}
190190
}
@@ -332,22 +332,22 @@ public IEnumerable<CommandOption> GetOptions()
332332
}
333333

334334
/// <summary>
335-
/// Add an alias for the command.
335+
/// Add another name for the command.
336336
/// <para>
337-
/// An alias is a shorter name by which a command may be referenced.
337+
/// Additional names can be shorter, longer, or alternative names by which a command may be invoked on the command line.
338338
/// </para>
339339
/// </summary>
340-
/// <param name="alias">The alias. Must not be null or empty.</param>
341-
public void AddAlias(string alias)
340+
/// <param name="name">The name. Must not be null or empty.</param>
341+
public void AddName(string name)
342342
{
343-
if (string.IsNullOrEmpty(alias))
343+
if (string.IsNullOrEmpty(name))
344344
{
345-
throw new ArgumentException("Value cannot be null or empty.", nameof(alias));
345+
throw new ArgumentException("Value cannot be null or empty.", nameof(name));
346346
}
347347

348-
Parent?.AssertCommandNameIsUnique(alias, this);
348+
Parent?.AssertCommandNameIsUnique(name, this);
349349

350-
_aliases.Add(alias);
350+
_names.Add(name);
351351
}
352352

353353
/// <summary>
@@ -965,7 +965,7 @@ internal bool MatchesName(string name)
965965
return true;
966966
}
967967

968-
return _aliases.Contains(name);
968+
return _names.Contains(name);
969969
}
970970

971971
private sealed class Builder : IConventionBuilder

src/CommandLineUtils/Properties/Strings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public static string OptionNameIsAmbiguous(string optionName, PropertyInfo first
4242
=> $"Ambiguous option name. Both {first.DeclaringType.FullName}.{first.Name} and {second.DeclaringType.FullName}.{second.Name} produce a CommandOption with the name '{optionName}'";
4343

4444
public static string DuplicateSubcommandName(string commandName)
45-
=> $"The subcommand name '{commandName}' has already been been specified. Subcommand names and aliases must be unique.";
45+
=> $"The subcommand name '{commandName}' has already been been specified. Subcommand names must be unique.";
4646

4747
public static string BothOptionAndArgumentAttributesCannotBeSpecified(PropertyInfo prop)
4848
=> $"Cannot specify both {nameof(OptionAttribute)} and {nameof(ArgumentAttribute)} on property {prop.DeclaringType.Name}.{prop.Name}.";

test/CommandLineUtils.Tests/CommandLineApplicationTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public void ItThrowsIfAnotherSubcommandHasNameName()
8888

8989
app.Command("sub1", c =>
9090
{
91-
c.AddAlias("s");
91+
c.AddName("s");
9292
});
9393

9494
var ex = Assert.Throws<InvalidOperationException>(() => app.Command("sub1", null));
@@ -105,10 +105,10 @@ public void ItThrowsIfAnotherSubCommandHasTheSameAlias()
105105

106106
app.Command("sub1", c =>
107107
{
108-
c.AddAlias("s");
108+
c.AddName("s");
109109
});
110110

111-
var ex = Assert.Throws<InvalidOperationException>(() => app.Command("sub2", c => c.AddAlias("s")));
111+
var ex = Assert.Throws<InvalidOperationException>(() => app.Command("sub2", c => c.AddName("s")));
112112
Assert.Equal(Strings.DuplicateSubcommandName("s"), ex.Message);
113113
}
114114

test/CommandLineUtils.Tests/CommandLineProcessorTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ public void ItFindsSubcommandsByAliases()
262262
var app = new CommandLineApplication();
263263
var cmd = app.Command("sub1", c =>
264264
{
265-
c.AddAlias("s");
265+
c.AddName("s");
266266
});
267267

268268
var result = app.Parse("s");

version.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project>
22
<PropertyGroup>
33
<VersionPrefix>2.3.0</VersionPrefix>
4-
<VersionSuffix>alpha1</VersionSuffix>
4+
<VersionSuffix>alpha</VersionSuffix>
55
<PackageVersion Condition="'$(APPVEYOR_REPO_TAG)' == 'true' AND '$(VersionSuffix)' != ''">$(VersionPrefix)-$(VersionSuffix)</PackageVersion>
66
<PackageVersion Condition="'$(APPVEYOR_REPO_TAG)' == 'true' AND '$(VersionSuffix)' == 'rtm'">$(VersionPrefix)</PackageVersion>
77

0 commit comments

Comments
 (0)