Skip to content

Commit 8b057fb

Browse files
committed
Shifted to using string[] instead of the full string from Environment.CommandLine as that's not consistent between runtime versions. Also eliminated single quoted strings as they aren't supported by the runtime.
1 parent b926268 commit 8b057fb

10 files changed

Lines changed: 116 additions & 67 deletions

File tree

CommandlineParsing.sln

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
4-
VisualStudioVersion = 15.0.27130.2010
4+
VisualStudioVersion = 15.0.27130.2020
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ubiquity.CommandlineParsing", "Ubiquity.CommandlineParsing\Ubiquity.CommandlineParsing.csproj", "{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}"
77
EndProject
@@ -28,34 +28,78 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repo Items", "Repo Items",
2828
EndProject
2929
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{D50F6965-5684-404D-A886-CD6E1A7A093E}"
3030
EndProject
31-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleArgs", "SampleArgs\SampleArgs.csproj", "{694CC71C-BD60-4B94-BC64-391949BA269E}"
31+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleArgs", "SampleArgs\SampleArgs.csproj", "{694CC71C-BD60-4B94-BC64-391949BA269E}"
3232
EndProject
3333
Global
3434
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3535
Debug|Any CPU = Debug|Any CPU
36+
Debug|x64 = Debug|x64
37+
Debug|x86 = Debug|x86
3638
Release|Any CPU = Release|Any CPU
39+
Release|x64 = Release|x64
40+
Release|x86 = Release|x86
3741
EndGlobalSection
3842
GlobalSection(ProjectConfigurationPlatforms) = postSolution
3943
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
4044
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Debug|Any CPU.Build.0 = Debug|Any CPU
45+
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Debug|x64.ActiveCfg = Debug|Any CPU
46+
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Debug|x64.Build.0 = Debug|Any CPU
47+
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Debug|x86.ActiveCfg = Debug|Any CPU
48+
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Debug|x86.Build.0 = Debug|Any CPU
4149
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Release|Any CPU.ActiveCfg = Release|Any CPU
4250
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Release|Any CPU.Build.0 = Release|Any CPU
51+
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Release|x64.ActiveCfg = Release|Any CPU
52+
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Release|x64.Build.0 = Release|Any CPU
53+
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Release|x86.ActiveCfg = Release|Any CPU
54+
{068EAD73-EE70-4D5F-BFC8-5F13AB1BFE21}.Release|x86.Build.0 = Release|Any CPU
4355
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
4456
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Debug|Any CPU.Build.0 = Debug|Any CPU
57+
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Debug|x64.ActiveCfg = Debug|Any CPU
58+
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Debug|x64.Build.0 = Debug|Any CPU
59+
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Debug|x86.ActiveCfg = Debug|Any CPU
60+
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Debug|x86.Build.0 = Debug|Any CPU
4561
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Release|Any CPU.ActiveCfg = Release|Any CPU
4662
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Release|Any CPU.Build.0 = Release|Any CPU
63+
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Release|x64.ActiveCfg = Release|Any CPU
64+
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Release|x64.Build.0 = Release|Any CPU
65+
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Release|x86.ActiveCfg = Release|Any CPU
66+
{A910DA7C-3F3E-4EA1-8418-1327DAF69B70}.Release|x86.Build.0 = Release|Any CPU
4767
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
4868
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
69+
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Debug|x64.ActiveCfg = Debug|Any CPU
70+
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Debug|x64.Build.0 = Debug|Any CPU
71+
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Debug|x86.ActiveCfg = Debug|Any CPU
72+
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Debug|x86.Build.0 = Debug|Any CPU
4973
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
5074
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Release|Any CPU.Build.0 = Release|Any CPU
75+
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Release|x64.ActiveCfg = Release|Any CPU
76+
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Release|x64.Build.0 = Release|Any CPU
77+
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Release|x86.ActiveCfg = Release|Any CPU
78+
{9088CB07-E75F-499F-A7E6-6EB8928595EE}.Release|x86.Build.0 = Release|Any CPU
5179
{54A04023-808D-4F10-9EB2-6741703A6D43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5280
{54A04023-808D-4F10-9EB2-6741703A6D43}.Debug|Any CPU.Build.0 = Debug|Any CPU
81+
{54A04023-808D-4F10-9EB2-6741703A6D43}.Debug|x64.ActiveCfg = Debug|Any CPU
82+
{54A04023-808D-4F10-9EB2-6741703A6D43}.Debug|x64.Build.0 = Debug|Any CPU
83+
{54A04023-808D-4F10-9EB2-6741703A6D43}.Debug|x86.ActiveCfg = Debug|Any CPU
84+
{54A04023-808D-4F10-9EB2-6741703A6D43}.Debug|x86.Build.0 = Debug|Any CPU
5385
{54A04023-808D-4F10-9EB2-6741703A6D43}.Release|Any CPU.ActiveCfg = Release|Any CPU
5486
{54A04023-808D-4F10-9EB2-6741703A6D43}.Release|Any CPU.Build.0 = Release|Any CPU
87+
{54A04023-808D-4F10-9EB2-6741703A6D43}.Release|x64.ActiveCfg = Release|Any CPU
88+
{54A04023-808D-4F10-9EB2-6741703A6D43}.Release|x64.Build.0 = Release|Any CPU
89+
{54A04023-808D-4F10-9EB2-6741703A6D43}.Release|x86.ActiveCfg = Release|Any CPU
90+
{54A04023-808D-4F10-9EB2-6741703A6D43}.Release|x86.Build.0 = Release|Any CPU
5591
{694CC71C-BD60-4B94-BC64-391949BA269E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5692
{694CC71C-BD60-4B94-BC64-391949BA269E}.Debug|Any CPU.Build.0 = Debug|Any CPU
93+
{694CC71C-BD60-4B94-BC64-391949BA269E}.Debug|x64.ActiveCfg = Debug|Any CPU
94+
{694CC71C-BD60-4B94-BC64-391949BA269E}.Debug|x64.Build.0 = Debug|Any CPU
95+
{694CC71C-BD60-4B94-BC64-391949BA269E}.Debug|x86.ActiveCfg = Debug|Any CPU
96+
{694CC71C-BD60-4B94-BC64-391949BA269E}.Debug|x86.Build.0 = Debug|Any CPU
5797
{694CC71C-BD60-4B94-BC64-391949BA269E}.Release|Any CPU.ActiveCfg = Release|Any CPU
5898
{694CC71C-BD60-4B94-BC64-391949BA269E}.Release|Any CPU.Build.0 = Release|Any CPU
99+
{694CC71C-BD60-4B94-BC64-391949BA269E}.Release|x64.ActiveCfg = Release|Any CPU
100+
{694CC71C-BD60-4B94-BC64-391949BA269E}.Release|x64.Build.0 = Release|Any CPU
101+
{694CC71C-BD60-4B94-BC64-391949BA269E}.Release|x86.ActiveCfg = Release|Any CPU
102+
{694CC71C-BD60-4B94-BC64-391949BA269E}.Release|x86.Build.0 = Release|Any CPU
59103
EndGlobalSection
60104
GlobalSection(SolutionProperties) = preSolution
61105
HideSolutionNode = FALSE

SampleArgs/Program.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,26 @@ namespace SampleArgs
1010
{
1111
public static class Program
1212
{
13-
public static void Main( )
13+
public static void Main( string[] args )
1414
{
15+
Console.WriteLine( "ARGS:" );
16+
for( int i = 0; i< args.Length; ++i )
17+
{
18+
Console.WriteLine( "{0}: [{1}]", i, args[ i ] );
19+
}
20+
1521
// Run with arguments like:
16-
// >SampleArgs.exe positionalarg0 -Option1 "positional arg 1" -Option2="this is a test" positional2 "positional\foo 3\\"
22+
// >SampleArgs.exe positionalarg0 -Option1 "option1 value" -Option2="this is a test" positional2 "positional\foo 3\\"
1723
try
1824
{
19-
var options = Options.ParseFrom( EnvironmentEx.CommandLine );
25+
var options = Options.ParseFrom( args );
26+
Console.WriteLine( "Option1: {0}", options.Option1 );
27+
Console.WriteLine( "Option2: {0}", options.Option2 );
28+
Console.WriteLine( "PositionalArgs:" );
29+
foreach( var positional in options.PositionalArgs )
30+
{
31+
Console.WriteLine( positional );
32+
}
2033
}
2134
catch(CommandlineParseException ex)
2235
{
@@ -35,9 +48,10 @@ internal class Options
3548

3649
public string Option2 { get; set; }
3750

38-
public static Options ParseFrom( string commandLine )
51+
public static Options ParseFrom( string[] args )
3952
{
40-
return CommandlineBinder.ParseAndBind<Options>( new Ubiquity.CommandlineParsing.Monad.Parser( ), commandLine );
53+
var parser = new Ubiquity.CommandlineParsing.Monad.Parser( );
54+
return new Options( ).BindArguments( parser.Parse( args ) );
4155
}
4256

4357
public static void ShowHelp()

Ubiquity.CommandlineParsing.Monad.UT/BinderTests.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,27 @@ public class BinderTests
4343
// This includes all forms of option switches quoting and the special problematic case of a trailing \ in a quoted string
4444
// The trailing \ in a quoted string is a notorious hidden gotcha for .NET apps as the default .NET arg parsing generates
4545
// a quote character as it implements character escaping, unlike any other runtime.
46-
private const string FullCommandLine
47-
= @"positionalarg0 -m:'Multi 1' --o1 'space delimited value1' -MultiOption=""Multi 2"" positional1 -Option2='this is a test' /option3:baz -m:multi3 -o4 positional2 ""positional 3\""";
46+
private readonly string[] FullCommandLine =
47+
{
48+
@"positionalarg0",
49+
@"-m:""Multi 1""",
50+
@"--o1",
51+
@"""space delimited value1""",
52+
@"-MultiOption=""Multi 2""",
53+
@"positional1",
54+
@"-Option2=""this is a test""",
55+
@"/option3:baz",
56+
@"-m:multi3",
57+
@"-o4",
58+
@"positional2",
59+
@"""positional 3\"""
60+
};
4861

4962
[TestMethod]
5063
public void CommandLineBinderTest()
5164
{
5265
var parser = new Parser( );
53-
TestOptions options = CommandlineBinder.ParseAndBind<TestOptions>( parser, FullCommandLine );
66+
TestOptions options = new TestOptions( ).BindArguments( parser.Parse( FullCommandLine ) );
5467
Assert.IsNotNull( options );
5568
Assert.AreEqual( 4, options.PositionalArgs.Count );
5669
Assert.AreEqual( 3, options.MultiOption.Count );

Ubiquity.CommandlineParsing.Monad.UT/GrammarLexemeTests.cs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -199,21 +199,6 @@ public void NonWhitespaceExceptionTest( )
199199
char result = NonWhiteSpaceChar.Parse( "\t" );
200200
}
201201

202-
[TestMethod]
203-
public void SingleQuotedStringTest( )
204-
{
205-
const string singleQuotedString = " 'asdf \"ghijk\" \u0394' ";
206-
Assert.AreEqual( singleQuotedString.Trim( ).Trim('\''), QuotedString.Text( ).Parse( singleQuotedString ) );
207-
}
208-
209-
[TestMethod]
210-
[ExpectedException( typeof( ParseException ) )]
211-
public void SingleQuotedStringExceptionTest( )
212-
{
213-
const string singleQuotedString = "'asdf ghijk \u0394";
214-
Assert.AreEqual( singleQuotedString, QuotedString.Parse( singleQuotedString ) );
215-
}
216-
217202
[TestMethod]
218203
public void DoubleQuotedStringTest( )
219204
{

Ubiquity.CommandlineParsing.Monad.UT/ParserTests.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,17 @@ public void OptionWithEqualValueTests( )
5353
[TestMethod]
5454
public void CommandLineParserTest( )
5555
{
56-
var args = CommandLine.Parse( @"positionalarg0 --Option1 'positional arg 1' -Option2='this is a test' /option3:foo positional2 ""positional 3\""" )
57-
.ToList( );
56+
string[ ] unparsedArgs =
57+
{
58+
@"positionalarg0",
59+
@"--Option1",
60+
@"positional arg 1",
61+
@"-Option2=this is a test",
62+
@"/option3:foo",
63+
@"positional2",
64+
@"positional 3\"
65+
};
66+
var args = unparsedArgs.Select( CommandlineArg.Parse ).ToList( );
5867

5968
Assert.IsInstanceOfType( args[ 0 ], typeof( CommandlineValue ) );
6069
var arg0 = ( CommandlineValue )args[ 0 ];
@@ -93,5 +102,5 @@ public void CommandLineParserTest( )
93102
var arg6 = ( CommandlineValue )args[ 6 ];
94103
Assert.AreEqual( @"positional 3\", arg6.Text );
95104
}
96-
}
105+
}
97106
}

Ubiquity.CommandlineParsing.Monad/Grammar.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,12 @@ public static readonly Parser<char> NonWhiteSpaceChar
8383

8484
/// <summary> Parser monad for a Quoted string (either single or double quotes)</summary>
8585
public static readonly Parser<IEnumerable<char>> QuotedString
86-
= BlockString( SingleQuote.Once() )
87-
.XOr( BlockString( DoubleQuote.Once() ) );
86+
= BlockString( DoubleQuote.Once() );
8887

89-
/// <summary>Parser monad for an unquoted positional value</summary>
88+
/// <summary>Parser monad for an unquoted positional value or the value of an option</summary>
9089
public static readonly Parser<IEnumerable<char>> UnquotedValue
91-
= ( from firstChar in Parse.CharExcept( "-'\"" )
92-
from rest in Parse.CharExcept( "'\"" ).Except(Parse.WhiteSpace).Many()
90+
= ( from firstChar in Parse.CharExcept( "-\"" )
91+
from rest in Parse.CharExcept( "\"" ).Many()
9392
select rest.Prepend( firstChar )
9493
).Token();
9594

@@ -140,9 +139,13 @@ public static Parser<CommandlineOption> OptionParser( Parser<IEnumerable<char>>
140139
from value in ValueContent.Named( "Positional Argument" ).Text( )
141140
select new CommandlineValue( value );
142141

142+
/// <summary>Gets a parser for a single command line argument</summary>
143+
public static Parser<ICommandlineArgument> CommandlineArg
144+
=> Option.Or( PositionalArg );
145+
143146
/// <summary>Gets the Top level parser to parse a command line into a sequence of <see cref="ICommandlineArgument"/></summary>
144147
public static Parser<IEnumerable<ICommandlineArgument>> CommandLine
145-
=> ( Option.Or( PositionalArg ) ).DelimitedBy( Parse.WhiteSpace.Many() ).End();
148+
=> ( CommandlineArg ).DelimitedBy( Parse.WhiteSpace.Many() ).End();
146149

147150
/// <summary>Parser combinator to provide semantic action support for matched parsers</summary>
148151
/// <typeparam name="T">Type of elements the parser produces</typeparam>

Ubiquity.CommandlineParsing.Monad/Parser.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Copyright (c) Ubiquity.NET Contributors. All rights reserved.
22
// Licensed under the MIT license. See the LICENSE.md file in the project root for full license information.
33

4+
using System.Collections.Generic;
45
using System.Collections.Immutable;
6+
using System.Linq;
57
using Sprache;
68

79
namespace Ubiquity.CommandlineParsing.Monad
@@ -10,12 +12,12 @@ namespace Ubiquity.CommandlineParsing.Monad
1012
public class Parser
1113
: ICommandlineParser
1214
{
13-
/// <summary>Parse a command line into base components</summary>
14-
/// <param name="commandLine">Command line to parse</param>
15-
/// <returns>Results of the parse</returns>
16-
public IImmutableList<ICommandlineArgument> Parse( string commandLine )
15+
/// <inheritdoc/>
16+
public IImmutableList<ICommandlineArgument> Parse( IEnumerable<string> args )
1717
{
18-
return ParseCommandLine( commandLine );
18+
return ( from arg in args
19+
select Grammar.Option.Or( Grammar.PositionalArg ).Parse( arg )
20+
).ToImmutableList( );
1921
}
2022

2123
/// <summary>Static method to parse a command line</summary>

Ubiquity.CommandlineParsing/CommandLineBinder.cs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,6 @@ public void BindParseResults( object instance, IImmutableList<ICommandlineArgume
6868
}
6969
}
7070

71-
/// <summary>Parser a command line and binds the results to an options instance object</summary>
72-
/// <typeparam name="TResult">Type of object to bind</typeparam>
73-
/// <param name="parser">parser to use to parse the command line </param>
74-
/// <param name="commandLine">Command line to parse</param>
75-
/// <returns> New instance of <typeparamref name="TResult"/> with the parsed command line values set on the instance properties</returns>
76-
public static TResult ParseAndBind<TResult>( ICommandlineParser parser, string commandLine )
77-
where TResult : new()
78-
{
79-
var results = parser.Parse( commandLine );
80-
return CommandLineBinderExtensions.BindArguments( new TResult( ), results );
81-
}
82-
8371
private void BindOptionValue( object instance, IImmutableList<ICommandlineArgument> parsedResults, CommandlineOption option, ref int i )
8472
{
8573
var prop = PropertyProvider.GetPropertyForOption( instance, option );

Ubiquity.CommandlineParsing/EnvironmentEx.cs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public static class EnvironmentEx
1919
/// path the user intended to provide. This has always been an annoyance for .NET developers but was easily worked around
2020
/// by not using the args to Main() and instead getting at the full args via Environment.CommandLine and parsing that using
2121
/// whatever rules the app wants to support for args.</para>
22-
/// <para>Unfortunately with .NET Core things behave very differently. <see cref="Environment.CommandLine"/> is no longer
22+
/// <para>Unfortunately, with .NET Core things behave very differently. <see cref="Environment.CommandLine"/> is no longer
2323
/// the unprocessed command line and instead it is effectively a space delimited join of Environment.GetCommandLineArgs().
2424
/// Meaning that is has all the .NET Specific escaping applied and there is no platform independent means of getting at
2525
/// the unprocessed args.</para>
@@ -33,19 +33,9 @@ public static string CommandLine
3333
// On .NET Core - no option exists to get the original command line, it isn't really possible to fully reverse
3434
// the escaping as the process is lossy. e.g. `"foo\"` -> `foo"`, and `foo\"`-> `foo"` with no way to know if
3535
// the opening quote was present. For a value with whitespace it can be inferred but otherwise it can't be known
36-
// which presents a problem as reversing the escaping could creates quotes that are unmatched.
37-
return string.Join( " ", Environment.GetCommandLineArgs( ).Skip( 1 ).Select( Requote ) );
36+
// which presents a problem as reversing the escaping could create quotes that are unmatched.
37+
return string.Join( " ", Environment.GetCommandLineArgs( ).Skip( 1 ) );
3838
}
3939
}
40-
41-
private static string Requote( string arg )
42-
{
43-
if( arg.Any( Char.IsWhiteSpace ) )
44-
{
45-
return $"\"{arg}\"";
46-
}
47-
48-
return arg;
49-
}
5040
}
5141
}

Ubiquity.CommandlineParsing/ICommandlineParser.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Ubiquity.NET Contributors. All rights reserved.
22
// Licensed under the MIT license. See the LICENSE.md file in the project root for full license information.
33

4+
using System.Collections.Generic;
45
using System.Collections.Immutable;
56

67
namespace Ubiquity.CommandlineParsing
@@ -38,8 +39,8 @@ namespace Ubiquity.CommandlineParsing
3839
/// </remarks>
3940
public interface ICommandlineParser
4041
{
41-
/// <summary>Parses the input command line into an immutable list of arguments</summary>
42-
/// <param name="commandLine">Command line to parse</param>
42+
/// <summary>Parse arguments list from platform provided list of args</summary>
43+
/// <param name="args">Args list provided to Main() or via <see cref="System.Environment.GetCommandLineArgs"/></param>
4344
/// <returns>The list of parsed arguments in the order they appeared on the command line</returns>
4445
/// <remarks>
4546
/// <para>This will parse the command line into the various components in the order they appeared
@@ -57,6 +58,6 @@ public interface ICommandlineParser
5758
/// really is the value to associate with the preceding option `-optionWithValue`</para>
5859
/// </remarks>
5960
/// <seealso cref="CommandlineArgAttribute.AllowSpaceDelimitedValue"/>
60-
IImmutableList<ICommandlineArgument> Parse( string commandLine );
61+
IImmutableList<ICommandlineArgument> Parse( IEnumerable<string> args );
6162
}
6263
}

0 commit comments

Comments
 (0)