From 2912a6f399ebe3ad3da77ece24902d0e1f3890ee Mon Sep 17 00:00:00 2001 From: Bill Boga Date: Wed, 20 Jul 2016 12:03:49 -0400 Subject: [PATCH] Allow spaces when tokenizing option-value Previous behavior split the incoming token long-name value using the equal sign as the separator. This would cause an option's value containing spaces to get truncated. New behavior does regex. match to make sure format is correct and gets the full value. --- src/CommandLine/Core/Tokenizer.cs | 17 +++++++-- .../Unit/Core/TokenizerTests.cs | 35 +++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/CommandLine/Core/Tokenizer.cs b/src/CommandLine/Core/Tokenizer.cs index 902b65e4..e0e09fd3 100644 --- a/src/CommandLine/Core/Tokenizer.cs +++ b/src/CommandLine/Core/Tokenizer.cs @@ -6,6 +6,7 @@ using CommandLine.Infrastructure; using CSharpx; using RailwaySharp.ErrorHandling; +using System.Text.RegularExpressions; namespace CommandLine.Core { @@ -188,9 +189,19 @@ private static IEnumerable TokenizeLongName( onError(new BadFormatTokenError(value)); yield break; } - var parts = text.Split('='); - yield return Token.Name(parts[0]); - yield return Token.Value(parts[1], true); + + var tokenMatch = Regex.Match(text, "^([^=]+)=([^ ].*)$"); + + if (tokenMatch.Success) + { + yield return Token.Name(tokenMatch.Groups[1].Value); + yield return Token.Value(tokenMatch.Groups[2].Value, true); + } + else + { + onError(new BadFormatTokenError(value)); + yield break; + } } } } diff --git a/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs b/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs index 37dbe51f..bceb1ea0 100644 --- a/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs +++ b/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs @@ -92,6 +92,41 @@ public void Normalize_should_remove_all_value_with_explicit_assignment_of_existi // Teardown } + + [Fact] + public void Should_properly_parse_option_with_equals_in_value() + { + /** + * This is how the arg. would look in `static void Main(string[] args)` + * if passed from the command-line and the option-value wrapped in quotes. + * Ex.) ./app --connectionString="Server=localhost;Data Source..." + */ + var args = new[] { "--connectionString=Server=localhost;Data Source=(LocalDB)\v12.0;Initial Catalog=temp;" }; + + var result = Tokenizer.Tokenize(args, name => NameLookupResult.OtherOptionFound, token => token); + + var tokens = result.SucceededWith(); + + Assert.NotNull(tokens); + Assert.Equal(2, tokens.Count()); + Assert.Equal("connectionString", tokens.First().Text); + Assert.Equal("Server=localhost;Data Source=(LocalDB)\v12.0;Initial Catalog=temp;", tokens.Last().Text); + } + + [Fact] + public void Should_return_error_if_option_format_with_equals_is_not_correct() + { + var args = new[] { "--option1 = fail", "--option2= fail" }; + + var result = Tokenizer.Tokenize(args, name => NameLookupResult.OtherOptionFound, token => token); + + var tokens = result.SuccessfulMessages(); + + Assert.NotNull(tokens); + Assert.Equal(2, tokens.Count()); + Assert.Equal(ErrorType.BadFormatTokenError, tokens.First().Tag); + Assert.Equal(ErrorType.BadFormatTokenError, tokens.Last().Tag); + } } }