Skip to content

Commit 7d27ed9

Browse files
Kahbazianalogrelay
authored andcommitted
Set argument if no option has found (dotnet/extensions#2822)
\n\nCommit migrated from dotnet/extensions@1513ad0
1 parent 639de3f commit 7d27ed9

File tree

2 files changed

+98
-2
lines changed

2 files changed

+98
-2
lines changed

src/Shared/CommandLineUtils/CommandLine/CommandLineApplication.cs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@ internal class CommandLineApplication
2626
// options.
2727
private readonly bool _continueAfterUnexpectedArg;
2828

29-
public CommandLineApplication(bool throwOnUnexpectedArg = true, bool continueAfterUnexpectedArg = false)
29+
private readonly bool _treatUnmatchedOptionsAsArguments;
30+
31+
public CommandLineApplication(bool throwOnUnexpectedArg = true, bool continueAfterUnexpectedArg = false, bool treatUnmatchedOptionsAsArguments = false)
3032
{
3133
_throwOnUnexpectedArg = throwOnUnexpectedArg;
3234
_continueAfterUnexpectedArg = continueAfterUnexpectedArg;
35+
_treatUnmatchedOptionsAsArguments = treatUnmatchedOptionsAsArguments;
3336
Options = new List<CommandOption>();
3437
Arguments = new List<CommandArgument>();
3538
Commands = new List<CommandLineApplication>();
@@ -136,6 +139,7 @@ public int Execute(params string[] args)
136139
CommandLineApplication command = this;
137140
CommandOption option = null;
138141
IEnumerator<CommandArgument> arguments = null;
142+
var argumentsAssigned = false;
139143

140144
for (var index = 0; index < args.Length; index++)
141145
{
@@ -161,6 +165,25 @@ public int Execute(params string[] args)
161165
var longOptionName = longOption[0];
162166
option = command.GetOptions().SingleOrDefault(opt => string.Equals(opt.LongName, longOptionName, StringComparison.Ordinal));
163167

168+
if (option == null && _treatUnmatchedOptionsAsArguments)
169+
{
170+
if (arguments == null)
171+
{
172+
arguments = new CommandArgumentEnumerator(command.Arguments.GetEnumerator());
173+
}
174+
if (arguments.MoveNext())
175+
{
176+
processed = true;
177+
arguments.Current.Values.Add(arg);
178+
argumentsAssigned = true;
179+
continue;
180+
}
181+
//else
182+
//{
183+
// argumentsAssigned = false;
184+
//}
185+
}
186+
164187
if (option == null)
165188
{
166189
var ignoreContinueAfterUnexpectedArg = false;
@@ -221,6 +244,25 @@ public int Execute(params string[] args)
221244
processed = true;
222245
option = command.GetOptions().SingleOrDefault(opt => string.Equals(opt.ShortName, shortOption[0], StringComparison.Ordinal));
223246

247+
if (option == null && _treatUnmatchedOptionsAsArguments)
248+
{
249+
if (arguments == null)
250+
{
251+
arguments = new CommandArgumentEnumerator(command.Arguments.GetEnumerator());
252+
}
253+
if (arguments.MoveNext())
254+
{
255+
processed = true;
256+
arguments.Current.Values.Add(arg);
257+
argumentsAssigned = true;
258+
continue;
259+
}
260+
//else
261+
//{
262+
// argumentsAssigned = false;
263+
//}
264+
}
265+
224266
// If not a short option, try symbol option
225267
if (option == null)
226268
{
@@ -278,7 +320,7 @@ public int Execute(params string[] args)
278320
option = null;
279321
}
280322

281-
if (!processed && arguments == null)
323+
if (!processed && !argumentsAssigned)
282324
{
283325
var currentCommand = command;
284326
foreach (var subcommand in command.Commands)

src/Shared/test/Shared.Tests/CommandLineApplicationTests.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,5 +1166,59 @@ public void ThrowsExceptionOnInvalidOption()
11661166

11671167
Assert.Equal($"Unrecognized option '{inputOption}'", exception.Message);
11681168
}
1169+
1170+
[Fact]
1171+
public void TreatUnmatchedOptionsAsArguments()
1172+
{
1173+
CommandArgument first = null;
1174+
CommandArgument second = null;
1175+
1176+
CommandOption firstOption = null;
1177+
CommandOption secondOption = null;
1178+
1179+
var firstUnmatchedOption = "-firstUnmatchedOption";
1180+
var firstActualOption = "-firstActualOption";
1181+
var seconUnmatchedOption = "--secondUnmatchedOption";
1182+
var secondActualOption = "--secondActualOption";
1183+
1184+
var app = new CommandLineApplication(treatUnmatchedOptionsAsArguments: true);
1185+
1186+
app.Command("test", c =>
1187+
{
1188+
firstOption = c.Option("-firstActualOption", "first option", CommandOptionType.NoValue);
1189+
secondOption = c.Option("--secondActualOption", "second option", CommandOptionType.NoValue);
1190+
1191+
first = c.Argument("first", "First argument");
1192+
second = c.Argument("second", "Second argument");
1193+
c.OnExecute(() => 0);
1194+
});
1195+
1196+
app.Execute("test", firstUnmatchedOption, firstActualOption, seconUnmatchedOption, secondActualOption);
1197+
1198+
Assert.Equal(firstUnmatchedOption, first.Value);
1199+
Assert.Equal(seconUnmatchedOption, second.Value);
1200+
1201+
Assert.Equal(firstActualOption, firstOption.Template);
1202+
Assert.Equal(secondActualOption, secondOption.Template);
1203+
}
1204+
1205+
[Fact]
1206+
public void ThrowExceptionWhenUnmatchedOptionAndTreatUnmatchedOptionsAsArgumentsIsFalse()
1207+
{
1208+
CommandArgument first = null;
1209+
1210+
var firstOption = "-firstUnmatchedOption";
1211+
1212+
var app = new CommandLineApplication(treatUnmatchedOptionsAsArguments: false);
1213+
app.Command("test", c =>
1214+
{
1215+
first = c.Argument("first", "First argument");
1216+
c.OnExecute(() => 0);
1217+
});
1218+
1219+
var exception = Assert.Throws<CommandParsingException>(() => app.Execute("test", firstOption));
1220+
1221+
Assert.Equal($"Unrecognized option '{firstOption}'", exception.Message);
1222+
}
11691223
}
11701224
}

0 commit comments

Comments
 (0)