From 3b5bc33ea0467421c6bb9c440e42702dc9ae49cd Mon Sep 17 00:00:00 2001 From: Nikolay Kostov Date: Mon, 8 Jan 2018 08:23:51 +0200 Subject: [PATCH 01/10] Fixed usage of Default in README.md examples --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 593d98f4..8c4857d2 100644 --- a/README.md +++ b/README.md @@ -66,12 +66,12 @@ internal class Options { // Omitting long name, defaults to name of property, ie "--verbose" [Option( - DefaultValue = false, + Default = false, HelpText = "Prints all messages to standard output.")] public bool Verbose { get; set; } [Option("stdin", - DefaultValue = false + Default = false HelpText = "Read from stdin")] public bool stdin { get; set; } @@ -91,7 +91,7 @@ F# Examples: type options = { [] files : seq; [] verbose : bool; - [] language : string; + [] language : string; [] offset : int64 option; } @@ -115,7 +115,7 @@ Class Options HelpText:="Prints all messages to standard output.")> Public Property Verbose As Boolean - Public Property Language As String From 734519ccd83c6e50a9f722f5286908489dd9395a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ce=CC=81dric=20Luthi?= Date: Fri, 5 Jan 2018 23:32:19 +0100 Subject: [PATCH 02/10] Extract Convert.ChangeType into a new ConvertString method The purpose of this commit is to trigger CI on AppVeyor to verify that all tests are passing since 30 of them do not pass on my machine (macOS 10.12.6 with JetBrains Rider 2017.3 and mono 5.4.1.7) --- src/CommandLine/Core/TypeConverter.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/CommandLine/Core/TypeConverter.cs b/src/CommandLine/Core/TypeConverter.cs index ad2b7d81..1e5a95e3 100644 --- a/src/CommandLine/Core/TypeConverter.cs +++ b/src/CommandLine/Core/TypeConverter.cs @@ -49,6 +49,11 @@ private static Maybe ChangeTypeScalar(string value, Type conversionType, return result.ToMaybe(); } + private static object ConvertString(string value, Type type, CultureInfo conversionCulture) + { + return Convert.ChangeType(value, type, conversionCulture); + } + private static Result ChangeTypeScalarImpl(string value, Type conversionType, CultureInfo conversionCulture, bool ignoreValueCase) { Func changeType = () => @@ -71,10 +76,9 @@ private static Result ChangeTypeScalarImpl(string value, Type () => #if !SKIP_FSHARP isFsOption - ? FSharpOptionHelper.Some(type, Convert.ChangeType(value, type, conversionCulture)) : + ? FSharpOptionHelper.Some(type, ConvertString(value, type, conversionCulture)) : #endif - Convert.ChangeType(value, type, conversionCulture); - + ConvertString(value, type, conversionCulture); #if !SKIP_FSHARP Func empty = () => isFsOption ? FSharpOptionHelper.None(type) : null; #else From d46d332d665955fd455934108d90d6ae2b276f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ce=CC=81dric=20Luthi?= Date: Fri, 5 Jan 2018 23:46:12 +0100 Subject: [PATCH 03/10] Add support for TimeSpan options Fixes #173 --- src/CommandLine/Core/TypeConverter.cs | 12 ++++++++++-- tests/CommandLine.Tests/CommandLine.Tests.csproj | 1 + .../Fakes/Options_With_TimeSpan.cs | 12 ++++++++++++ .../Unit/Core/InstanceBuilderTests.cs | 16 ++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 tests/CommandLine.Tests/Fakes/Options_With_TimeSpan.cs diff --git a/src/CommandLine/Core/TypeConverter.cs b/src/CommandLine/Core/TypeConverter.cs index 1e5a95e3..2feb54ca 100644 --- a/src/CommandLine/Core/TypeConverter.cs +++ b/src/CommandLine/Core/TypeConverter.cs @@ -51,9 +51,17 @@ private static Maybe ChangeTypeScalar(string value, Type conversionType, private static object ConvertString(string value, Type type, CultureInfo conversionCulture) { - return Convert.ChangeType(value, type, conversionCulture); + try + { + return Convert.ChangeType(value, type, conversionCulture); + } + catch (InvalidCastException) + { + // Required for converting from string to TimeSpan because Convert.ChangeType can't + return System.ComponentModel.TypeDescriptor.GetConverter(type).ConvertFrom(null, conversionCulture, value); + } } - + private static Result ChangeTypeScalarImpl(string value, Type conversionType, CultureInfo conversionCulture, bool ignoreValueCase) { Func changeType = () => diff --git a/tests/CommandLine.Tests/CommandLine.Tests.csproj b/tests/CommandLine.Tests/CommandLine.Tests.csproj index eb6e691e..cabb761d 100644 --- a/tests/CommandLine.Tests/CommandLine.Tests.csproj +++ b/tests/CommandLine.Tests/CommandLine.Tests.csproj @@ -95,6 +95,7 @@ + diff --git a/tests/CommandLine.Tests/Fakes/Options_With_TimeSpan.cs b/tests/CommandLine.Tests/Fakes/Options_With_TimeSpan.cs new file mode 100644 index 00000000..0e88896d --- /dev/null +++ b/tests/CommandLine.Tests/Fakes/Options_With_TimeSpan.cs @@ -0,0 +1,12 @@ +// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information. + +using System; + +namespace CommandLine.Tests.Fakes +{ + public class Options_With_TimeSpan + { + [Option('d', "duration")] + public TimeSpan Duration { get; set; } + } +} diff --git a/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs b/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs index 7d7544e6..7a49b39b 100644 --- a/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs +++ b/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs @@ -1023,6 +1023,22 @@ public void Parse_Guid(string[] arguments, Options_With_Guid expected) // Teardown } + [Fact] + public void Parse_TimeSpan() + { + // Fixture setup + var expectedResult = new Options_With_TimeSpan { Duration = TimeSpan.FromMinutes(42) }; + + // Exercize system + var result = InvokeBuild( + new[] { "--duration=00:42:00" }); + + // Verify outcome + expectedResult.ShouldBeEquivalentTo(((Parsed)result).Value); + + // Teardown + } + public static IEnumerable RequiredValueStringData { get From 3fcfa9a260dc87df3ea78bfa92bd154071fe58ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ce=CC=81dric=20Luthi?= Date: Mon, 8 Jan 2018 10:50:52 +0100 Subject: [PATCH 04/10] Update copyright in unit tests --- tests/CommandLine.Tests/Unit/ParserTests.cs | 16 ++++++++-------- .../CommandLine.Tests/Unit/Text/HelpTextTests.cs | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/CommandLine.Tests/Unit/ParserTests.cs b/tests/CommandLine.Tests/Unit/ParserTests.cs index 5ecd085c..43b44e27 100644 --- a/tests/CommandLine.Tests/Unit/ParserTests.cs +++ b/tests/CommandLine.Tests/Unit/ParserTests.cs @@ -366,7 +366,7 @@ public void Implicit_help_screen_in_verb_scenario() var lines = result.ToNotEmptyLines().TrimStringArray(); #if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); - lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2018 Giacomo Stelluti Scala & Contributors"); #else // Takes the name of the xUnit test program lines[0].Should().StartWithEquivalent("xUnit"); @@ -397,7 +397,7 @@ public void Double_dash_help_dispalys_verbs_index_in_verbs_scenario() var lines = result.ToNotEmptyLines().TrimStringArray(); #if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); - lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2018 Giacomo Stelluti Scala & Contributors"); #else // Takes the name of the xUnit test program lines[0].Should().StartWithEquivalent("xUnit"); @@ -452,7 +452,7 @@ public void Errors_of_type_MutuallyExclusiveSetError_are_properly_formatted() var lines = result.ToNotEmptyLines().TrimStringArray(); #if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); - lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2018 Giacomo Stelluti Scala & Contributors"); #else // Takes the name of the xUnit test program lines[0].Should().StartWithEquivalent("xUnit"); @@ -501,7 +501,7 @@ public void Properly_formatted_help_screen_is_displayed_when_usage_is_defined_in var lines = result.ToNotEmptyLines().TrimStringArray(); #if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); - lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2018 Giacomo Stelluti Scala & Contributors"); #else // Takes the name of the xUnit test program lines[0].Should().StartWithEquivalent("xUnit"); @@ -541,7 +541,7 @@ public void Properly_formatted_help_screen_is_displayed_when_there_is_a_hidden_v var lines = result.ToNotEmptyLines().TrimStringArray(); #if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); - lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2018 Giacomo Stelluti Scala & Contributors"); #else // Takes the name of the xUnit test program lines[0].Should().StartWithEquivalent("xUnit"); @@ -571,7 +571,7 @@ public void Properly_formatted_help_screen_is_displayed_when_there_is_a_hidden_v var lines = result.ToNotEmptyLines().TrimStringArray(); #if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); - lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2018 Giacomo Stelluti Scala & Contributors"); #else // Takes the name of the xUnit test program lines[0].Should().StartWithEquivalent("xUnit"); @@ -639,7 +639,7 @@ public void Specific_verb_help_screen_should_be_displayed_regardless_other_argum var lines = result.ToNotEmptyLines().TrimStringArray(); #if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); - lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2018 Giacomo Stelluti Scala & Contributors"); #else // Takes the name of the xUnit test program lines[0].Should().StartWithEquivalent("xUnit"); @@ -709,7 +709,7 @@ public void Properly_formatted_help_screen_excludes_help_as_unknown_option() var lines = result.ToNotEmptyLines().TrimStringArray(); #if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); - lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2018 Giacomo Stelluti Scala & Contributors"); #else // Takes the name of the xUnit test program lines[0].Should().StartWithEquivalent("xUnit"); diff --git a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs index e041026a..90ca41b5 100644 --- a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs +++ b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs @@ -390,7 +390,7 @@ public void Invoke_AutoBuild_for_Verbs_with_specific_verb_returns_appropriate_fo #if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); - lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2018 Giacomo Stelluti Scala & Contributors"); #else // Takes the name of the xUnit test program lines[0].Should().StartWithEquivalent("xUnit"); From 23bdea45161d94fa96165178d545a4bf47ee045f Mon Sep 17 00:00:00 2001 From: gbritton1 Date: Tue, 27 Mar 2018 19:31:19 -0400 Subject: [PATCH 05/10] Update UnParserExtensions.cs Short name not preferred? Go with long! No short name? Has to be long! --- src/CommandLine/UnParserExtensions.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/CommandLine/UnParserExtensions.cs b/src/CommandLine/UnParserExtensions.cs index 20122a7b..c543819e 100644 --- a/src/CommandLine/UnParserExtensions.cs +++ b/src/CommandLine/UnParserExtensions.cs @@ -206,9 +206,8 @@ private static string FormatOption(OptionSpecification spec, object value, UnPar private static string FormatName(this OptionSpecification optionSpec, UnParserSettings settings) { - var longName = - optionSpec.LongName.Length > 0 - && !settings.PreferShortName; + // Short name not preferred? Go with long! No short name? Has to be long! + var longName = !settings.PreferShortName || optionSpec.ShortName.Length == 0; return new StringBuilder(longName From fd14076cd187e532326a73682092762aafc4bc73 Mon Sep 17 00:00:00 2001 From: gbritton1 Date: Tue, 27 Mar 2018 20:51:00 -0400 Subject: [PATCH 06/10] Update UnParserExtensions.cs If there is no long name, take the short name regardless of the preference setting --- src/CommandLine/UnParserExtensions.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/CommandLine/UnParserExtensions.cs b/src/CommandLine/UnParserExtensions.cs index c543819e..924e8ec6 100644 --- a/src/CommandLine/UnParserExtensions.cs +++ b/src/CommandLine/UnParserExtensions.cs @@ -206,8 +206,10 @@ private static string FormatOption(OptionSpecification spec, object value, UnPar private static string FormatName(this OptionSpecification optionSpec, UnParserSettings settings) { - // Short name not preferred? Go with long! No short name? Has to be long! - var longName = !settings.PreferShortName || optionSpec.ShortName.Length == 0; + // Have a long name and short name not preferred? Go with long! + // No short name? Has to be long! + var longName = (optionSpec.LongName.Length > 0 && !settings.PreferShortName) + || optionSpec.ShortName.Length == 0; return new StringBuilder(longName From 5a68768eb387cc5ca7cb5a26321551adadef2008 Mon Sep 17 00:00:00 2001 From: Gerald Britton Date: Sun, 1 Apr 2018 18:20:33 -0400 Subject: [PATCH 07/10] Ad showHidden option to UnParser. Only return hidden options if showHidden is true --- src/CommandLine/UnParserExtensions.cs | 10 ++++++++++ .../CommandLine.Tests/CommandLine.Tests.csproj | 1 + tests/CommandLine.Tests/Fakes/Hidden_Option.cs | 14 ++++++++++++++ .../Unit/UnParserExtensionsTests.cs | 17 +++++++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 tests/CommandLine.Tests/Fakes/Hidden_Option.cs diff --git a/src/CommandLine/UnParserExtensions.cs b/src/CommandLine/UnParserExtensions.cs index 924e8ec6..7db948e7 100644 --- a/src/CommandLine/UnParserExtensions.cs +++ b/src/CommandLine/UnParserExtensions.cs @@ -18,6 +18,7 @@ public class UnParserSettings private bool preferShortName; private bool groupSwitches; private bool useEqualToken; + private bool showHidden; /// /// Gets or sets a value indicating whether unparsing process shall prefer short or long names. @@ -46,6 +47,14 @@ public bool UseEqualToken set { PopsicleSetter.Set(Consumed, ref useEqualToken, value); } } + /// + /// Gets or sets a value indicating whether unparsing process shall expose hidden options. + /// + public bool ShowHidden + { + get { return showHidden; } + set { PopsicleSetter.Set(Consumed, ref showHidden, value); } + } /// /// Factory method that creates an instance of with GroupSwitches set to true. /// @@ -119,6 +128,7 @@ public static string FormatCommandLine(this Parser parser, T options, Action< var allOptSpecs = from info in specs.Where(i => i.Specification.Tag == SpecificationType.Option) let o = (OptionSpecification)info.Specification where o.TargetType != TargetType.Switch || (o.TargetType == TargetType.Switch && ((bool)info.Value)) + where !o.Hidden || settings.ShowHidden orderby o.UniqueName() select info; diff --git a/tests/CommandLine.Tests/CommandLine.Tests.csproj b/tests/CommandLine.Tests/CommandLine.Tests.csproj index 5914a3a9..08d84442 100644 --- a/tests/CommandLine.Tests/CommandLine.Tests.csproj +++ b/tests/CommandLine.Tests/CommandLine.Tests.csproj @@ -58,6 +58,7 @@ Properties\SharedAssemblyInfo.cs + diff --git a/tests/CommandLine.Tests/Fakes/Hidden_Option.cs b/tests/CommandLine.Tests/Fakes/Hidden_Option.cs new file mode 100644 index 00000000..1f18f216 --- /dev/null +++ b/tests/CommandLine.Tests/Fakes/Hidden_Option.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CommandLine.Tests.Fakes +{ + public class Hidden_Option + { + [Option('h', "hiddenOption", Default="hidden", Hidden = true)] + public string HiddenOption { get; set; } + } +} diff --git a/tests/CommandLine.Tests/Unit/UnParserExtensionsTests.cs b/tests/CommandLine.Tests/Unit/UnParserExtensionsTests.cs index 3d15e2d0..74851163 100644 --- a/tests/CommandLine.Tests/Unit/UnParserExtensionsTests.cs +++ b/tests/CommandLine.Tests/Unit/UnParserExtensionsTests.cs @@ -40,6 +40,15 @@ public static void UnParsing_immutable_instance_returns_command_line(Immutable_S .ShouldBeEquivalentTo(result); } + [Theory] + [MemberData("UnParseDataHidden")] + public static void Unparsing_hidden_option_returns_command_line(Hidden_Option options, bool showHidden, string result) + { + new Parser() + .FormatCommandLine(options, config => config.ShowHidden = showHidden) + .ShouldBeEquivalentTo(result); + } + #if !SKIP_FSHARP [Theory] [MemberData("UnParseDataFSharpOption")] @@ -141,6 +150,14 @@ public static IEnumerable UnParseDataImmutable } } + public static IEnumerable UnParseDataHidden + { + get + { + yield return new object[] { new Hidden_Option { HiddenOption = "hidden" }, true, "--hiddenOption hidden" }; + yield return new object[] { new Hidden_Option { HiddenOption = "hidden" }, false, ""}; + } + } #if !SKIP_FSHARP public static IEnumerable UnParseDataFSharpOption { From 032e4c7e2d66a01aaf7889cb379142252195936c Mon Sep 17 00:00:00 2001 From: Stephen Price Date: Sun, 8 Apr 2018 15:49:58 +0800 Subject: [PATCH 08/10] Added simple quick start example for C# to the README.md --- README.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/README.md b/README.md index e20d9b90..acb67113 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,43 @@ You can utilize the parser library in several ways: 1. Create a class to define valid options, and to receive the parsed options. 2. Call ParseArguments with the args string array. +C# Quick Start: + +```csharp +using System; +using CommandLine; + +namespace QuickStart +{ + class Program + { + public class Options + { + [Option('v', "verbose", Required = false, HelpText = "Set output to verbose messages.")] + public bool Verbose { get; set; } + } + + static void Main(string[] args) + { + Parser.Default.ParseArguments(args) + .WithParsed(o => + { + if (o.Verbose) + { + Console.WriteLine($"Verbose output has been enabled. Current Arguments: -v {o.Verbose}"); + Console.WriteLine("Quick Start Example! App is in Verbose mode so verbose messages will be shown!"); + } + else + { + Console.WriteLine($"Current Arguments: -v {o.Verbose}"); + Console.WriteLine("Quick Start Example!"); + } + }); + } + } +} +``` + C# Examples: ```csharp From da54cf217b6f440c036c2dbc71441869304dcd41 Mon Sep 17 00:00:00 2001 From: Stephen Price Date: Sun, 8 Apr 2018 15:56:19 +0800 Subject: [PATCH 09/10] Shortened message to remove scrollbar on Github --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 92615d38..6fe2a4e5 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ namespace QuickStart if (o.Verbose) { Console.WriteLine($"Verbose output has been enabled. Current Arguments: -v {o.Verbose}"); - Console.WriteLine("Quick Start Example! App is in Verbose mode so verbose messages will be shown!"); + Console.WriteLine("Quick Start Example! App is in Verbose mode!"); } else { From 6ce423d63015e827517d3603af495c105314f2ed Mon Sep 17 00:00:00 2001 From: Stephen Price Date: Sun, 8 Apr 2018 15:58:31 +0800 Subject: [PATCH 10/10] Shortened message to remove scrollbar --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6fe2a4e5..1f031da2 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ namespace QuickStart { if (o.Verbose) { - Console.WriteLine($"Verbose output has been enabled. Current Arguments: -v {o.Verbose}"); + Console.WriteLine($"Verbose output enabled. Current Arguments: -v {o.Verbose}"); Console.WriteLine("Quick Start Example! App is in Verbose mode!"); } else