Skip to content

Commit

Permalink
Properly assign arguments after a double dash to values, rather than …
Browse files Browse the repository at this point in the history
…options.
  • Loading branch information
Rob Nasby authored and rmunn committed Apr 27, 2020
1 parent ee77b84 commit b6d3d47
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/CommandLine/Core/Scalar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static IEnumerable<Token> Partition(
{
return from tseq in tokens.Pairwise(
(f, s) =>
f.IsName() && s.IsValue()
f.IsName() && s.IsValueUnforced()
? typeLookup(f.Text).MapValueOrDefault(info =>
info.TargetType == TargetType.Scalar ? new[] { f, s } : new Token[] { }, new Token[] { })
: new Token[] { })
Expand Down
2 changes: 1 addition & 1 deletion src/CommandLine/Core/Sequence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static IEnumerable<Token> Partition(
break;

case SequenceState.TokenFound:
if (token.IsValue())
if (token.IsValueUnforced())
{
if (sequences.TryGetValue(nameToken, out var sequence))
{
Expand Down
35 changes: 25 additions & 10 deletions src/CommandLine/Core/Token.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ public static Token Value(string text)
return new Value(text);
}

public static Token Value(string text, bool explicitlyAssigned)
public static Token Value(string text, bool forced)
{
return new Value(text, explicitlyAssigned);
return new Value(text, forced);
}

public static Token ValueForced(string text)
{
return new Value(text, true);
}

public TokenType Tag
Expand Down Expand Up @@ -79,22 +84,22 @@ public bool Equals(Name other)

class Value : Token, IEquatable<Value>
{
private readonly bool explicitlyAssigned;
private readonly bool forced;

public Value(string text)
: this(text, false)
{
}

public Value(string text, bool explicitlyAssigned)
public Value(string text, bool forced)
: base(TokenType.Value, text)
{
this.explicitlyAssigned = explicitlyAssigned;
this.forced = forced;
}

public bool ExplicitlyAssigned
public bool Forced
{
get { return explicitlyAssigned; }
get { return forced; }
}

public override bool Equals(object obj)
Expand All @@ -110,7 +115,7 @@ public override bool Equals(object obj)

public override int GetHashCode()
{
return new { Tag, Text }.GetHashCode();
return new { Tag, Text, Forced }.GetHashCode();
}

public bool Equals(Value other)
Expand All @@ -120,7 +125,7 @@ public bool Equals(Value other)
return false;
}

return Tag.Equals(other.Tag) && Text.Equals(other.Text);
return Tag.Equals(other.Tag) && Text.Equals(other.Text) && this.Forced == other.Forced;
}
}

Expand All @@ -135,5 +140,15 @@ public static bool IsValue(this Token token)
{
return token.Tag == TokenType.Value;
}

public static bool IsValueForced(this Token token)
{
return token.IsValue() && ((Value)token).Forced;
}

public static bool IsValueUnforced(this Token token)
{
return token.IsValue() && ! ((Value)token).Forced;
}
}
}
}
11 changes: 7 additions & 4 deletions src/CommandLine/Core/Tokenizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public static Result<IEnumerable<Token>, Error> Tokenize(
int consumeNext = 0;
Action<int> onConsumeNext = (n => consumeNext = consumeNext + n);

bool isForced = false;

var tokens = new List<Token>();

var enumerator = arguments.GetEnumerator();
Expand All @@ -44,21 +46,22 @@ public static Result<IEnumerable<Token>, Error> Tokenize(
break;

case string arg when consumeNext > 0:
tokens.Add(new Value(arg));
tokens.Add(new Value(arg, isForced));
consumeNext = consumeNext - 1;
break;

case "--" when allowDashDash:
consumeNext = System.Int32.MaxValue;
isForced = true;
break;

case "--":
tokens.Add(new Value("--"));
tokens.Add(new Value("--", isForced));
break;

case "-":
// A single hyphen is always a value (it usually means "read from stdin" or "write to stdout")
tokens.Add(new Value("-"));
tokens.Add(new Value("-", isForced));
break;

case string arg when arg.StartsWith("--"):
Expand All @@ -71,7 +74,7 @@ public static Result<IEnumerable<Token>, Error> Tokenize(

case string arg:
// If we get this far, it's a plain value
tokens.Add(new Value(arg));
tokens.Add(new Value(arg, isForced));
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;

namespace CommandLine.Tests.Fakes
{
public class Options_With_Option_Sequence_And_Value_Sequence
{
[Option('o', "option-seq")]
public IEnumerable<string> OptionSequence { get; set; }

[Value(0)]
public IEnumerable<string> ValueSequence { get; set; }
}
}
20 changes: 20 additions & 0 deletions tests/CommandLine.Tests/Unit/ParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,26 @@ public void Parse_options_with_double_dash()
// Teardown
}

[Fact]
public void Parse_options_with_double_dash_and_option_sequence()
{
var expectedOptions = new Options_With_Option_Sequence_And_Value_Sequence
{
OptionSequence = new[] { "option1", "option2", "option3" },
ValueSequence = new[] { "value1", "value2", "value3" }
};

var sut = new Parser(with => with.EnableDashDash = true);

// Exercize system
var result =
sut.ParseArguments<Options_With_Option_Sequence_And_Value_Sequence>(
new[] { "--option-seq", "option1", "option2", "option3", "--", "value1", "value2", "value3" });

// Verify outcome
((Parsed<Options_With_Option_Sequence_And_Value_Sequence>)result).Value.Should().BeEquivalentTo(expectedOptions);
}

[Fact]
public void Parse_options_with_double_dash_in_verbs_scenario()
{
Expand Down

0 comments on commit b6d3d47

Please sign in to comment.