Skip to content

Commit 9126267

Browse files
committed
Update release notes and fixup a few polish items
1 parent 7d3d726 commit 9126267

File tree

9 files changed

+41
-105
lines changed

9 files changed

+41
-105
lines changed

CommandLineUtils.sln

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -41,85 +41,33 @@ EndProject
4141
Global
4242
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4343
Debug|Any CPU = Debug|Any CPU
44-
Debug|x64 = Debug|x64
45-
Debug|x86 = Debug|x86
4644
Release|Any CPU = Release|Any CPU
47-
Release|x64 = Release|x64
48-
Release|x86 = Release|x86
4945
EndGlobalSection
5046
GlobalSection(ProjectConfigurationPlatforms) = postSolution
5147
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5248
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
53-
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Debug|x64.ActiveCfg = Debug|Any CPU
54-
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Debug|x64.Build.0 = Debug|Any CPU
55-
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Debug|x86.ActiveCfg = Debug|Any CPU
56-
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Debug|x86.Build.0 = Debug|Any CPU
5749
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
5850
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Release|Any CPU.Build.0 = Release|Any CPU
59-
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Release|x64.ActiveCfg = Release|Any CPU
60-
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Release|x64.Build.0 = Release|Any CPU
61-
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Release|x86.ActiveCfg = Release|Any CPU
62-
{CBCFAFF3-A3B1-4C41-B2D1-092BF7307A4E}.Release|x86.Build.0 = Release|Any CPU
6351
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
6452
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Debug|Any CPU.Build.0 = Debug|Any CPU
65-
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Debug|x64.ActiveCfg = Debug|Any CPU
66-
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Debug|x64.Build.0 = Debug|Any CPU
67-
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Debug|x86.ActiveCfg = Debug|Any CPU
68-
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Debug|x86.Build.0 = Debug|Any CPU
6953
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Release|Any CPU.ActiveCfg = Release|Any CPU
7054
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Release|Any CPU.Build.0 = Release|Any CPU
71-
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Release|x64.ActiveCfg = Release|Any CPU
72-
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Release|x64.Build.0 = Release|Any CPU
73-
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Release|x86.ActiveCfg = Release|Any CPU
74-
{1258544C-1FDE-4810-9A1B-189A925E9B45}.Release|x86.Build.0 = Release|Any CPU
7555
{71521E54-158D-45D7-8746-4905E6B3EB21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
7656
{71521E54-158D-45D7-8746-4905E6B3EB21}.Debug|Any CPU.Build.0 = Debug|Any CPU
77-
{71521E54-158D-45D7-8746-4905E6B3EB21}.Debug|x64.ActiveCfg = Debug|Any CPU
78-
{71521E54-158D-45D7-8746-4905E6B3EB21}.Debug|x64.Build.0 = Debug|Any CPU
79-
{71521E54-158D-45D7-8746-4905E6B3EB21}.Debug|x86.ActiveCfg = Debug|Any CPU
80-
{71521E54-158D-45D7-8746-4905E6B3EB21}.Debug|x86.Build.0 = Debug|Any CPU
8157
{71521E54-158D-45D7-8746-4905E6B3EB21}.Release|Any CPU.ActiveCfg = Release|Any CPU
8258
{71521E54-158D-45D7-8746-4905E6B3EB21}.Release|Any CPU.Build.0 = Release|Any CPU
83-
{71521E54-158D-45D7-8746-4905E6B3EB21}.Release|x64.ActiveCfg = Release|Any CPU
84-
{71521E54-158D-45D7-8746-4905E6B3EB21}.Release|x64.Build.0 = Release|Any CPU
85-
{71521E54-158D-45D7-8746-4905E6B3EB21}.Release|x86.ActiveCfg = Release|Any CPU
86-
{71521E54-158D-45D7-8746-4905E6B3EB21}.Release|x86.Build.0 = Release|Any CPU
8759
{71521E54-158D-45D7-8746-4905E6B3EB22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
8860
{71521E54-158D-45D7-8746-4905E6B3EB22}.Debug|Any CPU.Build.0 = Debug|Any CPU
89-
{71521E54-158D-45D7-8746-4905E6B3EB22}.Debug|x64.ActiveCfg = Debug|Any CPU
90-
{71521E54-158D-45D7-8746-4905E6B3EB22}.Debug|x64.Build.0 = Debug|Any CPU
91-
{71521E54-158D-45D7-8746-4905E6B3EB22}.Debug|x86.ActiveCfg = Debug|Any CPU
92-
{71521E54-158D-45D7-8746-4905E6B3EB22}.Debug|x86.Build.0 = Debug|Any CPU
9361
{71521E54-158D-45D7-8746-4905E6B3EB22}.Release|Any CPU.ActiveCfg = Release|Any CPU
9462
{71521E54-158D-45D7-8746-4905E6B3EB22}.Release|Any CPU.Build.0 = Release|Any CPU
95-
{71521E54-158D-45D7-8746-4905E6B3EB22}.Release|x64.ActiveCfg = Release|Any CPU
96-
{71521E54-158D-45D7-8746-4905E6B3EB22}.Release|x64.Build.0 = Release|Any CPU
97-
{71521E54-158D-45D7-8746-4905E6B3EB22}.Release|x86.ActiveCfg = Release|Any CPU
98-
{71521E54-158D-45D7-8746-4905E6B3EB22}.Release|x86.Build.0 = Release|Any CPU
9963
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
10064
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Debug|Any CPU.Build.0 = Debug|Any CPU
101-
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Debug|x64.ActiveCfg = Debug|Any CPU
102-
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Debug|x64.Build.0 = Debug|Any CPU
103-
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Debug|x86.ActiveCfg = Debug|Any CPU
104-
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Debug|x86.Build.0 = Debug|Any CPU
10565
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Release|Any CPU.ActiveCfg = Release|Any CPU
10666
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Release|Any CPU.Build.0 = Release|Any CPU
107-
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Release|x64.ActiveCfg = Release|Any CPU
108-
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Release|x64.Build.0 = Release|Any CPU
109-
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Release|x86.ActiveCfg = Release|Any CPU
110-
{F8BC68FE-2F44-4AB5-AD31-7B39376A616B}.Release|x86.Build.0 = Release|Any CPU
11167
{074F1099-BEC5-496D-AA37-75A427A437E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
11268
{074F1099-BEC5-496D-AA37-75A427A437E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
113-
{074F1099-BEC5-496D-AA37-75A427A437E7}.Debug|x64.ActiveCfg = Debug|Any CPU
114-
{074F1099-BEC5-496D-AA37-75A427A437E7}.Debug|x64.Build.0 = Debug|Any CPU
115-
{074F1099-BEC5-496D-AA37-75A427A437E7}.Debug|x86.ActiveCfg = Debug|Any CPU
116-
{074F1099-BEC5-496D-AA37-75A427A437E7}.Debug|x86.Build.0 = Debug|Any CPU
11769
{074F1099-BEC5-496D-AA37-75A427A437E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
11870
{074F1099-BEC5-496D-AA37-75A427A437E7}.Release|Any CPU.Build.0 = Release|Any CPU
119-
{074F1099-BEC5-496D-AA37-75A427A437E7}.Release|x64.ActiveCfg = Release|Any CPU
120-
{074F1099-BEC5-496D-AA37-75A427A437E7}.Release|x64.Build.0 = Release|Any CPU
121-
{074F1099-BEC5-496D-AA37-75A427A437E7}.Release|x86.ActiveCfg = Release|Any CPU
122-
{074F1099-BEC5-496D-AA37-75A427A437E7}.Release|x86.Build.0 = Release|Any CPU
12371
EndGlobalSection
12472
GlobalSection(SolutionProperties) = preSolution
12573
HideSolutionNode = FALSE

releasenotes.props

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,22 @@
33
<PackageReleaseNotes Condition="'$(VersionPrefix)' == '2.1.0'">
44
2.1.0:
55
New features:
6-
- CommandLineApplication.HandleResponseFiles - the parser can expand response files. Response files contain arguments
7-
that will be treated as if they were passed on command line
8-
6+
- Attributes. Simplify command line argument definitions by adding attributes to a class that represents options and arguments.
7+
- Options defined as [Option] or [Argument], [Subcommand].
8+
- Command parsing options can be defined with [Command] and [Subcmomand].
9+
- Special options include [HelpOption] and [VersionOption].
10+
- Async from end to end. Using C# 7.1 and attribute binding, your console app can be async from top to bottom.
11+
12+
New API
13+
- Added OptionAttribute, ArgumentAttribute, CommandAttribute, SubcommandAttribute, HelpOptionAttribute, and VersionOptionAttribute.
14+
- CommandLineApplication.Execute&lt;TApp&gt;() - executes an app where TApp uses attributes to define its options
15+
- CommandLineApplication.ExecuteAsync&lt;TApp&gt;() - sample thing, but async.
16+
- CommandLineApplication.StopParsingHelpOption and StopParsingVerboseOption. When the help and verbose options are matched
17+
against a command-line flag, the parsing will stop by default. You can turn this off by setting these options if you
18+
want OnExecute to be invoked no matter what.
19+
- CommandLineApplication.HandleResponseFiles - the parser can treat arguments that begin with '@' as response files.
20+
Response files contain arguments that will be treated as if they were passed on command line.
21+
922
Minor bug fixes:
1023
- Add return types to .VerboseOption() and ensure .HasValue() is true when HelpOption or VerboseOption are matched
1124
- Fix a NullReferenceException in some edge cases when parsing args

samples/Subcommands/Program.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@ class Program : CommandBase
2020

2121
protected override int OnExecute(CommandLineApplication app)
2222
{
23-
// this shows help even if the --help option isn't displayed
23+
// this shows help even if the --help option isn't specified
2424
app.ShowHelp();
2525
return 1;
2626
}
2727

2828
public override List<string> CreateArgs()
2929
{
3030
var args = new List<string>();
31-
3231
if (GitDir != null)
3332
{
3433
args.Add("--git-dir=" + GitDir);
@@ -43,7 +42,7 @@ class AddCommand : CommandBase
4342
[Argument(0)]
4443
public string[] Files { get; set; }
4544

46-
// this will automatically be set OnExecute
45+
// this will automatically be set before OnExecute is invoked
4746
private Program Parent { get; set; }
4847

4948
public override List<string> CreateArgs()
@@ -66,7 +65,7 @@ class CommitCommand : CommandBase
6665
[Option("-m")]
6766
public string Message { get; set; }
6867

69-
// this will automatically be set OnExecute
68+
// this will automatically be set before OnExecute is invoked
7069
private Program Parent { get; set; }
7170

7271
public override List<string> CreateArgs()

src/CommandLineUtils/CommandLineApplication.Execute.cs

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@
33
// This file has been modified from the original form. See Notice.txt in the project root for more information.
44

55
using System;
6-
using System.Collections;
7-
using System.Collections.Generic;
8-
using System.IO;
9-
using System.Linq;
106
using System.Reflection;
11-
using System.Text;
127
using System.Threading.Tasks;
138

149
namespace McMaster.Extensions.CommandLineUtils
@@ -20,41 +15,41 @@ namespace McMaster.Extensions.CommandLineUtils
2015
partial class CommandLineApplication
2116
{
2217
/// <summary>
23-
/// Creates an instance of <typeparamref name="T"/>, matching <paramref name="args"/>
18+
/// Creates an instance of <typeparamref name="TApp"/>, matching <paramref name="args"/>
2419
/// to all attributes on the type, and then invoking a method named "Execute" if it exists.
2520
/// See <seealso cref="OptionAttribute" />, <seealso cref="ArgumentAttribute" />,
2621
/// <seealso cref="HelpOptionAttribute"/>, and <seealso cref="VersionOptionAttribute"/>.
2722
/// </summary>
2823
/// <param name="args">The arguments</param>
29-
/// <typeparam name="T">A type that should be bound to the arguments.</typeparam>
24+
/// <typeparam name="TApp">A type that should be bound to the arguments.</typeparam>
3025
/// <exception cref="CommandParsingException">Thrown when arguments cannot be parsed correctly.</exception>
3126
/// <exception cref="InvalidOperationException">Thrown when attributes are incorrectly configured.</exception>
3227
/// <returns>The process exit code</returns>
33-
public static int Execute<T>(params string[] args)
34-
where T : class, new()
35-
=> Execute<T>(PhysicalConsole.Singleton, args);
28+
public static int Execute<TApp>(params string[] args)
29+
where TApp : class, new()
30+
=> Execute<TApp>(PhysicalConsole.Singleton, args);
3631

3732
/// <summary>
38-
/// Creates an instance of <typeparamref name="T"/>, matching <paramref name="args"/>
33+
/// Creates an instance of <typeparamref name="TApp"/>, matching <paramref name="args"/>
3934
/// to all attributes on the type, and then invoking a method named "Execute" if it exists.
4035
/// See <seealso cref="OptionAttribute" />, <seealso cref="ArgumentAttribute" />,
4136
/// <seealso cref="HelpOptionAttribute"/>, and <seealso cref="VersionOptionAttribute"/>.
4237
/// </summary>
4338
/// <param name="console">The console to use</param>
4439
/// <param name="args">The arguments</param>
45-
/// <typeparam name="T">A type that should be bound to the arguments.</typeparam>
40+
/// <typeparam name="TApp">A type that should be bound to the arguments.</typeparam>
4641
/// <exception cref="CommandParsingException">Thrown when arguments cannot be parsed correctly.</exception>
4742
/// <exception cref="InvalidOperationException">Thrown when attributes are incorrectly configured.</exception>
4843
/// <returns>The process exit code</returns>
49-
public static int Execute<T>(IConsole console, params string[] args)
50-
where T : class, new()
44+
public static int Execute<TApp>(IConsole console, params string[] args)
45+
where TApp : class, new()
5146
{
5247
if (console == null)
5348
{
5449
throw new ArgumentNullException(nameof(console));
5550
}
5651

57-
var applicationBuilder = new ReflectionAppBuilder<T>();
52+
var applicationBuilder = new ReflectionAppBuilder<TApp>();
5853
var bindResult = applicationBuilder.Bind(console, args).GetBottomContext();
5954
if (IsShowingInfo(bindResult))
6055
{
@@ -74,41 +69,41 @@ public static int Execute<T>(IConsole console, params string[] args)
7469
}
7570

7671
/// <summary>
77-
/// Creates an instance of <typeparamref name="T"/>, matching <paramref name="args"/>
72+
/// Creates an instance of <typeparamref name="TApp"/>, matching <paramref name="args"/>
7873
/// to all attributes on the type, and then invoking a method named "Execute" if it exists.
7974
/// See <seealso cref="OptionAttribute" />, <seealso cref="ArgumentAttribute" />,
8075
/// <seealso cref="HelpOptionAttribute"/>, and <seealso cref="VersionOptionAttribute"/>.
8176
/// </summary>
8277
/// <param name="args">The arguments</param>
83-
/// <typeparam name="T">A type that should be bound to the arguments.</typeparam>
78+
/// <typeparam name="TApp">A type that should be bound to the arguments.</typeparam>
8479
/// <exception cref="CommandParsingException">Thrown when arguments cannot be parsed correctly.</exception>
8580
/// <exception cref="InvalidOperationException">Thrown when attributes are incorrectly configured.</exception>
8681
/// <returns>The process exit code</returns>
87-
public static Task<int> ExecuteAsync<T>(params string[] args)
88-
where T : class, new()
89-
=> ExecuteAsync<T>(PhysicalConsole.Singleton, args);
82+
public static Task<int> ExecuteAsync<TApp>(params string[] args)
83+
where TApp : class, new()
84+
=> ExecuteAsync<TApp>(PhysicalConsole.Singleton, args);
9085

9186
/// <summary>
92-
/// Creates an instance of <typeparamref name="T"/>, matching <paramref name="args"/>
87+
/// Creates an instance of <typeparamref name="TApp"/>, matching <paramref name="args"/>
9388
/// to all attributes on the type, and then invoking a method named "Execute" if it exists.
9489
/// See <seealso cref="OptionAttribute" />, <seealso cref="ArgumentAttribute" />,
9590
/// <seealso cref="HelpOptionAttribute"/>, and <seealso cref="VersionOptionAttribute"/>.
9691
/// </summary>
9792
/// <param name="console">The console to use</param>
9893
/// <param name="args">The arguments</param>
99-
/// <typeparam name="T">A type that should be bound to the arguments.</typeparam>
94+
/// <typeparam name="TApp">A type that should be bound to the arguments.</typeparam>
10095
/// <exception cref="CommandParsingException">Thrown when arguments cannot be parsed correctly.</exception>
10196
/// <exception cref="InvalidOperationException">Thrown when attributes are incorrectly configured.</exception>
10297
/// <returns>The process exit code</returns>
103-
public static async Task<int> ExecuteAsync<T>(IConsole console, params string[] args)
104-
where T : class, new()
98+
public static async Task<int> ExecuteAsync<TApp>(IConsole console, params string[] args)
99+
where TApp : class, new()
105100
{
106101
if (console == null)
107102
{
108103
throw new ArgumentNullException(nameof(console));
109104
}
110105

111-
var applicationBuilder = new ReflectionAppBuilder<T>(console);
106+
var applicationBuilder = new ReflectionAppBuilder<TApp>(console);
112107
var bindResult = applicationBuilder.Bind(console, args).GetBottomContext();
113108
if (IsShowingInfo(bindResult))
114109
{

src/CommandLineUtils/CommandLineApplication.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using System.Collections.Generic;
88
using System.IO;
99
using System.Linq;
10-
using System.Reflection;
1110
using System.Text;
1211
using System.Threading.Tasks;
1312

src/CommandLineUtils/CommandLineApplicationExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public static CommandOption HelpOption(this CommandLineApplication app)
2121
=> app.HelpOption(Strings.DefaultHelpTemplate);
2222

2323
/// <summary>
24-
/// Adds the verbose option with the template <c></c>.
24+
/// Adds the verbose option with the template <c>-v|--verbose</c>.
2525
/// </summary>
2626
/// <param name="app"></param>
2727
/// <returns></returns>

src/CommandLineUtils/Internal/BindContext.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright (c) Nate McMaster.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System;
5-
64
namespace McMaster.Extensions.CommandLineUtils
75
{
86
internal class BindContext
@@ -14,12 +12,10 @@ internal class BindContext
1412
public BindContext GetBottomContext()
1513
{
1614
var retVal = this;
17-
1815
while (retVal?.Child != null)
1916
{
2017
retVal = retVal.Child;
2118
}
22-
2319
return retVal;
2420
}
2521
}

src/CommandLineUtils/Internal/ReflectionAppBuilder.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,6 @@ private void AddProperties(IEnumerable<PropertyInfo> props,
174174
}
175175
}
176176

177-
// in the event AddType gets called multiple times
178-
App.Arguments.Clear();
179-
180177
foreach (var arg in _argOrder)
181178
{
182179
if (App.Arguments.Count > 0)

src/CommandLineUtils/Internal/ReflectionHelper.cs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,10 @@ public static MethodInfo GetExecuteMethod(Type type, bool async)
3737

3838
if (async)
3939
{
40-
var returnType = method.ReturnType.GetTypeInfo();
41-
42-
if (!typeof(Task).GetTypeInfo().IsAssignableFrom(returnType))
40+
if (method.ReturnType != typeof(Task) && method.ReturnType != typeof(Task<int>))
4341
{
4442
throw new InvalidOperationException(Strings.InvalidAsyncOnExecuteReturnType);
4543
}
46-
47-
if (returnType.IsGenericType)
48-
{
49-
var genericTypes = returnType.GetGenericArguments();
50-
if (genericTypes[0] != typeof(int))
51-
{
52-
throw new InvalidOperationException(Strings.InvalidAsyncOnExecuteReturnType);
53-
}
54-
}
5544
}
5645
else if (method.ReturnType != typeof(void) && method.ReturnType != typeof(int))
5746
{

0 commit comments

Comments
 (0)