Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit bd9602c

Browse filesBrowse files
authored
some ergonomic improvements (#2559)
* a little project upkeep * make some validation methods fluent-friendly * fix some warnings * update API baseline
1 parent aba0e9a commit bd9602c
Copy full SHA for bd9602c

11 files changed

+140
-94
lines changed

‎.gitignore

Copy file name to clipboardExpand all lines: .gitignore
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ _NCrunch_*/
147147
_ReSharper.*/
148148
buildlog.txt
149149
nCrunchTemp*
150+
.NCrunch_System.CommandLine/
150151
TestResults/
151152

152153
.fake

‎Directory.Build.props

Copy file name to clipboardExpand all lines: Directory.Build.props
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<PropertyGroup>
88
<NoWarn>$(NoWarn);NU5125;CS0618</NoWarn>
99
<PackageLicenseExpression>MIT</PackageLicenseExpression>
10-
<LangVersion>10.0</LangVersion>
10+
<LangVersion>13.0</LangVersion>
1111
<PackageProjectUrl>https://github.com/dotnet/command-line-api</PackageProjectUrl>
1212
</PropertyGroup>
1313

‎System.CommandLine.v3.ncrunchsolution

Copy file name to clipboardExpand all lines: System.CommandLine.v3.ncrunchsolution
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
<Settings>
33
<AllowParallelTestExecution>True</AllowParallelTestExecution>
44
<CustomBuildProperties>
5-
<Value>TargetFrameworks = net7.0</Value>
6-
<Value>TargetFramework = net7.0</Value>
5+
<Value>TargetFrameworks = net8.0</Value>
6+
<Value>TargetFramework = net8.0</Value>
77
</CustomBuildProperties>
8+
<EnableRDI>False</EnableRDI>
9+
<RdiConfigured>True</RdiConfigured>
810
<SolutionConfigured>True</SolutionConfigured>
911
</Settings>
1012
</SolutionConfiguration>

‎core.slnf

Copy file name to clipboard
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"solution": {
3+
"path": "System.CommandLine.sln",
4+
"projects": [
5+
"src\\System.CommandLine.ApiCompatibility.Tests\\System.CommandLine.ApiCompatibility.Tests.csproj",
6+
"src\\System.CommandLine.DragonFruit\\System.CommandLine.DragonFruit.csproj",
7+
"src\\System.CommandLine.NamingConventionBinder.Tests\\System.CommandLine.NamingConventionBinder.Tests.csproj",
8+
"src\\System.CommandLine.NamingConventionBinder\\System.CommandLine.NamingConventionBinder.csproj",
9+
"src\\System.CommandLine.Tests\\System.CommandLine.Tests.csproj",
10+
"src\\System.CommandLine\\System.CommandLine.csproj"
11+
]
12+
}
13+
}

‎src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt

Copy file name to clipboardExpand all lines: src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt
+6-6Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
public Func<System.CommandLine.Parsing.ArgumentResult,T> DefaultValueFactory { get; set; }
1616
public System.Boolean HasDefaultValue { get; }
1717
public System.Type ValueType { get; }
18-
public System.Void AcceptLegalFileNamesOnly()
19-
public System.Void AcceptLegalFilePathsOnly()
20-
public System.Void AcceptOnlyFromAmong(System.String[] values)
2118
public struct ArgumentArity : System.ValueType, System.IEquatable<ArgumentArity>
2219
public static ArgumentArity ExactlyOne { get; }
2320
public static ArgumentArity OneOrMore { get; }
@@ -35,6 +32,9 @@
3532
public static Argument<System.IO.DirectoryInfo> AcceptExistingOnly(this Argument<System.IO.DirectoryInfo> argument)
3633
public static Argument<System.IO.FileSystemInfo> AcceptExistingOnly(this Argument<System.IO.FileSystemInfo> argument)
3734
public static Argument<T> AcceptExistingOnly<T>(this Argument<T> argument)
35+
public static Argument<T> AcceptLegalFileNamesOnly<T>(this Argument<T> argument)
36+
public static Argument<T> AcceptLegalFilePathsOnly<T>(this Argument<T> argument)
37+
public static Argument<T> AcceptOnlyFromAmong<T>(this Argument<T> argument, System.String[] values)
3838
public class Command : Symbol, System.Collections.IEnumerable
3939
.ctor(System.String name, System.String description = null)
4040
public System.CommandLine.Invocation.CommandLineAction Action { get; set; }
@@ -105,9 +105,9 @@
105105
public Func<System.CommandLine.Parsing.ArgumentResult,T> CustomParser { get; set; }
106106
public Func<System.CommandLine.Parsing.ArgumentResult,T> DefaultValueFactory { get; set; }
107107
public System.Type ValueType { get; }
108-
public System.Void AcceptLegalFileNamesOnly()
109-
public System.Void AcceptLegalFilePathsOnly()
110-
public System.Void AcceptOnlyFromAmong(System.String[] values)
108+
public Option<T> AcceptLegalFileNamesOnly()
109+
public Option<T> AcceptLegalFilePathsOnly()
110+
public Option<T> AcceptOnlyFromAmong(System.String[] values)
111111
public static class OptionValidation
112112
public static Option<System.IO.FileInfo> AcceptExistingOnly(this Option<System.IO.FileInfo> option)
113113
public static Option<System.IO.DirectoryInfo> AcceptExistingOnly(this Option<System.IO.DirectoryInfo> option)

‎src/System.CommandLine.NamingConventionBinder/BindingContextExtensions.cs

Copy file name to clipboardExpand all lines: src/System.CommandLine.NamingConventionBinder/BindingContextExtensions.cs
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ private sealed class DummyStateHoldingHandler : BindingHandler
1717
public override Task<int> InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken = default) => Task.FromResult(0);
1818
}
1919

20+
/// <summary>
21+
/// Gets the binding context for the specified parse result.
22+
/// </summary>
23+
/// <param name="parseResult">The parse result from the command line parsing.</param>
24+
/// <returns>The binding context associated with the parse result.</returns>
2025
public static BindingContext GetBindingContext(this ParseResult parseResult)
2126
{
2227
// parsing resulted with no handler or it was not created yet, we fake it to just store the BindingContext between the calls

‎src/System.CommandLine.NamingConventionBinder/BindingHandler.cs

Copy file name to clipboardExpand all lines: src/System.CommandLine.NamingConventionBinder/BindingHandler.cs
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
namespace System.CommandLine.NamingConventionBinder
88
{
9+
/// <summary>
10+
/// Represents a handler that provides binding functionality for command-line actions.
11+
/// </summary>
12+
/// <remarks>This abstract class serves as a base for implementing custom binding logic in command-line
13+
/// applications. It provides a mechanism to retrieve or initialize a <see cref="BindingContext"/> for the current
14+
/// invocation.</remarks>
915
public abstract class BindingHandler : AsynchronousCommandLineAction
1016
{
1117
private BindingContext? _bindingContext;

‎src/System.CommandLine/ArgumentValidation.cs

Copy file name to clipboardExpand all lines: src/System.CommandLine/ArgumentValidation.cs
+89Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,95 @@ public static Argument<T> AcceptExistingOnly<T>(this Argument<T> argument)
6969
return argument;
7070
}
7171

72+
/// <summary>
73+
/// Configures the argument to accept only values representing legal file names.
74+
/// </summary>
75+
/// <remarks>A parse error will result, for example, if file path separators are found in the parsed value.</remarks>
76+
public static Argument<T> AcceptLegalFileNamesOnly<T>(this Argument<T> argument)
77+
{
78+
argument.Validators.Add(static result =>
79+
{
80+
var invalidFileNameChars = Path.GetInvalidFileNameChars();
81+
82+
for (var i = 0; i < result.Tokens.Count; i++)
83+
{
84+
var token = result.Tokens[i];
85+
var invalidCharactersIndex = token.Value.IndexOfAny(invalidFileNameChars);
86+
87+
if (invalidCharactersIndex >= 0)
88+
{
89+
result.AddError(LocalizationResources.InvalidCharactersInFileName(token.Value[invalidCharactersIndex]));
90+
}
91+
}
92+
});
93+
94+
return argument;
95+
}
96+
97+
98+
/// <summary>
99+
/// Configures the argument to accept only values representing legal file paths.
100+
/// </summary>
101+
public static Argument<T> AcceptLegalFilePathsOnly<T>(this Argument<T> argument)
102+
{
103+
argument.Validators.Add(static result =>
104+
{
105+
var invalidPathChars = Path.GetInvalidPathChars();
106+
107+
for (var i = 0; i < result.Tokens.Count; i++)
108+
{
109+
var token = result.Tokens[i];
110+
111+
// File class no longer check invalid character
112+
// https://blogs.msdn.microsoft.com/jeremykuhne/2018/03/09/custom-directory-enumeration-in-net-core-2-1/
113+
var invalidCharactersIndex = token.Value.IndexOfAny(invalidPathChars);
114+
115+
if (invalidCharactersIndex >= 0)
116+
{
117+
result.AddError(LocalizationResources.InvalidCharactersInPath(token.Value[invalidCharactersIndex]));
118+
}
119+
}
120+
});
121+
122+
return argument;
123+
}
124+
125+
/// <summary>
126+
/// Configures the argument to accept only the specified values, and to suggest them as command line completions.
127+
/// </summary>
128+
/// <param name="argument">The argument to configure.</param>
129+
/// <param name="values">The values that are allowed for the argument.</param>
130+
public static Argument<T> AcceptOnlyFromAmong<T>(
131+
this Argument<T> argument,
132+
params string[] values)
133+
{
134+
if (values is not null && values.Length > 0)
135+
{
136+
argument.Validators.Clear();
137+
argument.Validators.Add(UnrecognizedArgumentError);
138+
argument.CompletionSources.Clear();
139+
argument.CompletionSources.Add(values);
140+
}
141+
142+
return argument;
143+
144+
void UnrecognizedArgumentError(ArgumentResult argumentResult)
145+
{
146+
for (var i = 0; i < argumentResult.Tokens.Count; i++)
147+
{
148+
var token = argumentResult.Tokens[i];
149+
150+
if (token.Symbol is null || token.Symbol == argument)
151+
{
152+
if (Array.IndexOf(values, token.Value) < 0)
153+
{
154+
argumentResult.AddError(LocalizationResources.UnrecognizedArgument(token.Value, values));
155+
}
156+
}
157+
}
158+
}
159+
}
160+
72161
private static void FileOrDirectoryExists<T>(ArgumentResult result)
73162
where T : FileSystemInfo
74163
{

‎src/System.CommandLine/Argument{T}.cs

Copy file name to clipboardExpand all lines: src/System.CommandLine/Argument{T}.cs
-81Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
using System.Collections.Generic;
55
using System.CommandLine.Parsing;
66
using System.Diagnostics.CodeAnalysis;
7-
using System.IO;
8-
97
namespace System.CommandLine
108
{
119
/// <inheritdoc cref="Argument" />
@@ -84,85 +82,6 @@ public Argument(string name) : base(name)
8482
return DefaultValueFactory.Invoke(argumentResult);
8583
}
8684

87-
/// <summary>
88-
/// Configures the argument to accept only the specified values, and to suggest them as command line completions.
89-
/// </summary>
90-
/// <param name="values">The values that are allowed for the argument.</param>
91-
public void AcceptOnlyFromAmong(params string[] values)
92-
{
93-
if (values is not null && values.Length > 0)
94-
{
95-
Validators.Clear();
96-
Validators.Add(UnrecognizedArgumentError);
97-
CompletionSources.Clear();
98-
CompletionSources.Add(values);
99-
}
100-
101-
void UnrecognizedArgumentError(ArgumentResult argumentResult)
102-
{
103-
for (var i = 0; i < argumentResult.Tokens.Count; i++)
104-
{
105-
var token = argumentResult.Tokens[i];
106-
107-
if (token.Symbol is null || token.Symbol == this)
108-
{
109-
if (Array.IndexOf(values, token.Value) < 0)
110-
{
111-
argumentResult.AddError(LocalizationResources.UnrecognizedArgument(token.Value, values));
112-
}
113-
}
114-
}
115-
}
116-
}
117-
118-
/// <summary>
119-
/// Configures the argument to accept only values representing legal file paths.
120-
/// </summary>
121-
public void AcceptLegalFilePathsOnly()
122-
{
123-
Validators.Add(static result =>
124-
{
125-
var invalidPathChars = Path.GetInvalidPathChars();
126-
127-
for (var i = 0; i < result.Tokens.Count; i++)
128-
{
129-
var token = result.Tokens[i];
130-
131-
// File class no longer check invalid character
132-
// https://blogs.msdn.microsoft.com/jeremykuhne/2018/03/09/custom-directory-enumeration-in-net-core-2-1/
133-
var invalidCharactersIndex = token.Value.IndexOfAny(invalidPathChars);
134-
135-
if (invalidCharactersIndex >= 0)
136-
{
137-
result.AddError(LocalizationResources.InvalidCharactersInPath(token.Value[invalidCharactersIndex]));
138-
}
139-
}
140-
});
141-
}
142-
143-
/// <summary>
144-
/// Configures the argument to accept only values representing legal file names.
145-
/// </summary>
146-
/// <remarks>A parse error will result, for example, if file path separators are found in the parsed value.</remarks>
147-
public void AcceptLegalFileNamesOnly()
148-
{
149-
Validators.Add(static result =>
150-
{
151-
var invalidFileNameChars = Path.GetInvalidFileNameChars();
152-
153-
for (var i = 0; i < result.Tokens.Count; i++)
154-
{
155-
var token = result.Tokens[i];
156-
var invalidCharactersIndex = token.Value.IndexOfAny(invalidFileNameChars);
157-
158-
if (invalidCharactersIndex >= 0)
159-
{
160-
result.AddError(LocalizationResources.InvalidCharactersInFileName(token.Value[invalidCharactersIndex]));
161-
}
162-
}
163-
});
164-
}
165-
16685
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050", Justification = "https://github.com/dotnet/command-line-api/issues/1638")]
16786
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2091", Justification = "https://github.com/dotnet/command-line-api/issues/1638")]
16887
internal static T? CreateDefaultValue()

‎src/System.CommandLine/OptionValidation.cs

Copy file name to clipboardExpand all lines: src/System.CommandLine/OptionValidation.cs
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ public static Option<T> AcceptExistingOnly<T>(this Option<T> option)
5454
where T : IEnumerable<FileSystemInfo>
5555
{
5656
option._argument.AcceptExistingOnly();
57-
5857
return option;
5958
}
6059
}

‎src/System.CommandLine/Option{T}.cs

Copy file name to clipboardExpand all lines: src/System.CommandLine/Option{T}.cs
+15-3Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,29 @@ public Func<ArgumentResult, T>? DefaultValueFactory
5151
/// Configures the option to accept only the specified values, and to suggest them as command line completions.
5252
/// </summary>
5353
/// <param name="values">The values that are allowed for the option.</param>
54-
public void AcceptOnlyFromAmong(params string[] values) => _argument.AcceptOnlyFromAmong(values);
54+
public Option<T> AcceptOnlyFromAmong(params string[] values)
55+
{
56+
_argument.AcceptOnlyFromAmong(values);
57+
return this;
58+
}
5559

5660
/// <summary>
5761
/// Configures the option to accept only values representing legal file paths.
5862
/// </summary>
59-
public void AcceptLegalFilePathsOnly() => _argument.AcceptLegalFilePathsOnly();
63+
public Option<T> AcceptLegalFilePathsOnly()
64+
{
65+
_argument.AcceptLegalFilePathsOnly();
66+
return this;
67+
}
6068

6169
/// <summary>
6270
/// Configures the option to accept only values representing legal file names.
6371
/// </summary>
6472
/// <remarks>A parse error will result, for example, if file path separators are found in the parsed value.</remarks>
65-
public void AcceptLegalFileNamesOnly() => _argument.AcceptLegalFileNamesOnly();
73+
public Option<T> AcceptLegalFileNamesOnly()
74+
{
75+
_argument.AcceptLegalFileNamesOnly();
76+
return this;
77+
}
6678
}
6779
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.