Skip to content

Commit 14c2d2a

Browse files
Rob NasbyRob Nasby
Rob Nasby
authored and
Rob Nasby
committed
Properly assign arguments after a double dash to values, rather than options.
1 parent 1373286 commit 14c2d2a

File tree

5 files changed

+61
-6
lines changed

5 files changed

+61
-6
lines changed

src/CommandLine/Core/Sequence.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ private static IEnumerable<Token> OfSequence(this IEnumerable<Token> tokens, Tok
3434
return info.NextValue.MapValueOrDefault(
3535
_ => info.MaxItems.MapValueOrDefault(
3636
n => tokens.Skip(nameIndex + 1).Take(n),
37-
tokens.Skip(nameIndex + 1).TakeWhile(v => v.IsValue())),
38-
tokens.Skip(nameIndex + 1).TakeWhile(v => v.IsValue()));
37+
tokens.Skip(nameIndex + 1).TakeWhile(v => v.IsValue() && !v.IsValueForced())),
38+
tokens.Skip(nameIndex + 1).TakeWhile(v => v.IsValue() && !v.IsValueForced()));
3939
}
4040
return new Token[] { };
4141
}

src/CommandLine/Core/Token.cs

+25-3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ public static Token Value(string text, bool explicitlyAssigned)
3232
return new Value(text, explicitlyAssigned);
3333
}
3434

35+
public static Token ValueForced(string text)
36+
{
37+
return new Value(text, false, true);
38+
}
39+
3540
public TokenType Tag
3641
{
3742
get { return tag; }
@@ -80,23 +85,35 @@ public bool Equals(Name other)
8085
class Value : Token, IEquatable<Value>
8186
{
8287
private readonly bool explicitlyAssigned;
88+
private readonly bool forced;
8389

8490
public Value(string text)
85-
: this(text, false)
91+
: this(text, false, false)
8692
{
8793
}
8894

8995
public Value(string text, bool explicitlyAssigned)
96+
: this(text, explicitlyAssigned, false)
97+
{
98+
}
99+
100+
public Value(string text, bool explicitlyAssigned, bool forced)
90101
: base(TokenType.Value, text)
91102
{
92103
this.explicitlyAssigned = explicitlyAssigned;
104+
this.forced = forced;
93105
}
94106

95107
public bool ExplicitlyAssigned
96108
{
97109
get { return explicitlyAssigned; }
98110
}
99111

112+
public bool Forced
113+
{
114+
get { return forced; }
115+
}
116+
100117
public override bool Equals(object obj)
101118
{
102119
var other = obj as Value;
@@ -120,7 +137,7 @@ public bool Equals(Value other)
120137
return false;
121138
}
122139

123-
return Tag.Equals(other.Tag) && Text.Equals(other.Text);
140+
return Tag.Equals(other.Tag) && Text.Equals(other.Text) && this.Forced == other.Forced;
124141
}
125142
}
126143

@@ -135,5 +152,10 @@ public static bool IsValue(this Token token)
135152
{
136153
return token.Tag == TokenType.Value;
137154
}
155+
156+
public static bool IsValueForced(this Token token)
157+
{
158+
return token.IsValue() && ((Value)token).Forced;
159+
}
138160
}
139-
}
161+
}

src/CommandLine/Core/Tokenizer.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public static Result<IEnumerable<Token>, Error> PreprocessDashDash(
5050
if (arguments.Any(arg => arg.EqualsOrdinal("--")))
5151
{
5252
var tokenizerResult = tokenizer(arguments.TakeWhile(arg => !arg.EqualsOrdinal("--")));
53-
var values = arguments.SkipWhile(arg => !arg.EqualsOrdinal("--")).Skip(1).Select(Token.Value);
53+
var values = arguments.SkipWhile(arg => !arg.EqualsOrdinal("--")).Skip(1).Select(Token.ValueForced);
5454
return tokenizerResult.Map(tokens => tokens.Concat(values));
5555
}
5656
return tokenizer(arguments);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Collections.Generic;
2+
3+
namespace CommandLine.Tests.Fakes
4+
{
5+
public class Options_With_Option_Sequence_And_Value_Sequence
6+
{
7+
[Option('o', "option-seq")]
8+
public IEnumerable<string> OptionSequence { get; set; }
9+
10+
[Value(0)]
11+
public IEnumerable<string> ValueSequence { get; set; }
12+
}
13+
}

tests/CommandLine.Tests/Unit/ParserTests.cs

+20
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,26 @@ public void Parse_options_with_double_dash()
132132
// Teardown
133133
}
134134

135+
[Fact]
136+
public void Parse_options_with_double_dash_and_option_sequence()
137+
{
138+
var expectedOptions = new Options_With_Option_Sequence_And_Value_Sequence
139+
{
140+
OptionSequence = new[] { "option1", "option2", "option3" },
141+
ValueSequence = new[] { "value1", "value2", "value3" }
142+
};
143+
144+
var sut = new Parser(with => with.EnableDashDash = true);
145+
146+
// Exercize system
147+
var result =
148+
sut.ParseArguments<Options_With_Option_Sequence_And_Value_Sequence>(
149+
new[] { "--option-seq", "option1", "option2", "option3", "--", "value1", "value2", "value3" });
150+
151+
// Verify outcome
152+
((Parsed<Options_With_Option_Sequence_And_Value_Sequence>)result).Value.Should().BeEquivalentTo(expectedOptions);
153+
}
154+
135155
[Fact]
136156
public void Parse_options_with_double_dash_in_verbs_scenario()
137157
{

0 commit comments

Comments
 (0)