From cccae2db749c2ebf25125bfd18e05427be0adbcf Mon Sep 17 00:00:00 2001 From: moh-hassan Date: Sat, 4 Jul 2020 03:34:06 +0300 Subject: [PATCH] Add ParseArg method to split commandline --- src/CommandLine/UnParserExtensions.cs | 57 ++++++++++++++++++- .../Unit/UnParserExtensionsTests.cs | 24 ++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/CommandLine/UnParserExtensions.cs b/src/CommandLine/UnParserExtensions.cs index 8e726ca5..51811ef9 100644 --- a/src/CommandLine/UnParserExtensions.cs +++ b/src/CommandLine/UnParserExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Linq; using System.Text; using CommandLine.Core; @@ -102,6 +103,18 @@ public static string FormatCommandLine(this Parser parser, T options) return parser.FormatCommandLine(options, config => { }); } + /// + /// Format a command line argument string from a parsed instance in the form of string[]. + /// + /// Type of . + /// Parser instance. + /// A parsed (or manually correctly constructed instance). + /// A string[] with command line arguments. + public static string[] FormatCommandLineArgs(this Parser parser, T options) + { + return parser.FormatCommandLine(options, config => { }).SplitArgs(); + } + /// /// Format a command line argument string from a parsed instance. /// @@ -180,7 +193,19 @@ orderby v.Index return builder .ToString().TrimEnd(' '); } - + /// + /// Format a command line argument string[] from a parsed instance. + /// + /// Type of . + /// Parser instance. + /// A parsed (or manually correctly constructed instance). + /// The lambda used to configure + /// aspects and behaviors of the unparsersing process. + /// A string[] with command line arguments. + public static string[] FormatCommandLineArgs(this Parser parser, T options, Action configuration) + { + return FormatCommandLine(parser, options, configuration).SplitArgs(); + } private static string FormatValue(Specification spec, object value) { var builder = new StringBuilder(); @@ -273,5 +298,35 @@ private static bool IsEmpty(this object value, Specification specification, bool if (value is IEnumerable && !((IEnumerable)value).GetEnumerator().MoveNext()) return true; return false; } + + + #region splitter + /// + /// Returns a string array that contains the substrings in this instance that are delimited by space considering string between double quote. + /// + /// the commandline string + /// don't remove the quote + /// a string array that contains the substrings in this instance + public static string[] SplitArgs(this string command, bool keepQuote = false) + { + if (string.IsNullOrEmpty(command)) + return new string[0]; + + var inQuote = false; + var chars = command.ToCharArray().Select(v => + { + if (v == '"') + inQuote = !inQuote; + return !inQuote && v == ' ' ? '\n' : v; + }).ToArray(); + + return new string(chars).Split('\n') + .Select(x => keepQuote ? x : x.Trim('"')) + .Where(x => !string.IsNullOrWhiteSpace(x)) + .ToArray(); + } + + #endregion + } } diff --git a/tests/CommandLine.Tests/Unit/UnParserExtensionsTests.cs b/tests/CommandLine.Tests/Unit/UnParserExtensionsTests.cs index d25c99e1..45850cb1 100644 --- a/tests/CommandLine.Tests/Unit/UnParserExtensionsTests.cs +++ b/tests/CommandLine.Tests/Unit/UnParserExtensionsTests.cs @@ -250,6 +250,30 @@ public static void UnParsing_instance_with_nullable_bool(bool? flag, string expe .FormatCommandLine(options) .Should().BeEquivalentTo(expected); } + #region SplitArgs + [Theory] + [InlineData("--shape Circle", new[] { "--shape","Circle" })] + [InlineData(" --shape Circle ", new[] { "--shape", "Circle" })] + [InlineData("-a --shape Circle", new[] {"-a", "--shape", "Circle" })] + [InlineData("-a --shape Circle -- -x1 -x2", new[] { "-a", "--shape", "Circle","--","-x1","-x2" })] + [InlineData("--name \"name with space and quote\" -x1", new[] { "--name", "name with space and quote","-x1" })] + public static void Split_arguments(string command, string[] expectedArgs) + { + var args = command.SplitArgs(); + args.Should().BeEquivalentTo(expectedArgs); + } + [Theory] + [InlineData("--shape Circle", new[] { "--shape", "Circle" })] + [InlineData(" --shape Circle ", new[] { "--shape", "Circle" })] + [InlineData("-a --shape Circle", new[] { "-a", "--shape", "Circle" })] + [InlineData("-a --shape Circle -- -x1 -x2", new[] { "-a", "--shape", "Circle", "--", "-x1", "-x2" })] + [InlineData("--name \"name with space and quote\" -x1", new[] { "--name", "\"name with space and quote\"", "-x1" })] + public static void Split_arguments_with_keep_quote(string command, string[] expectedArgs) + { + var args = command.SplitArgs(true); + args.Should().BeEquivalentTo(expectedArgs); + } + #endregion class Option_Int_Nullable { [Option('v', Default = 1)]