Skip to content

Commit 70a60b9

Browse files
committed
Add ability to skip options with default values for UnParserSettings (#541) and Quote DatTime Option (#502)
1 parent ce3011c commit 70a60b9

File tree

4 files changed

+88
-21
lines changed

4 files changed

+88
-21
lines changed

src/CommandLine/UnParserExtensions.cs

+36-20
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public class UnParserSettings
1919
private bool groupSwitches;
2020
private bool useEqualToken;
2121
private bool showHidden;
22+
private bool skipDefault;
2223

2324
/// <summary>
2425
/// Gets or sets a value indicating whether unparsing process shall prefer short or long names.
@@ -56,6 +57,14 @@ public bool ShowHidden
5657
set { PopsicleSetter.Set(Consumed, ref showHidden, value); }
5758
}
5859
/// <summary>
60+
/// Gets or sets a value indicating whether unparsing process shall skip options with DefaultValue.
61+
/// </summary>
62+
public bool SkipDefault
63+
{
64+
get { return skipDefault; }
65+
set { PopsicleSetter.Set(Consumed, ref skipDefault, value); }
66+
}
67+
/// <summary>
5968
/// Factory method that creates an instance of <see cref="CommandLine.UnParserSettings"/> with GroupSwitches set to true.
6069
/// </summary>
6170
/// <returns>A properly initalized <see cref="CommandLine.UnParserSettings"/> instance.</returns>
@@ -90,7 +99,7 @@ public static class UnParserExtensions
9099
/// <returns>A string with command line arguments.</returns>
91100
public static string FormatCommandLine<T>(this Parser parser, T options)
92101
{
93-
return parser.FormatCommandLine(options, config => {});
102+
return parser.FormatCommandLine(options, config => { });
94103
}
95104

96105
/// <summary>
@@ -119,34 +128,38 @@ public static string FormatCommandLine<T>(this Parser parser, T options, Action<
119128
var specs =
120129
(from info in
121130
type.GetSpecifications(
122-
pi => new { Specification = Specification.FromProperty(pi),
123-
Value = pi.GetValue(options, null).NormalizeValue(), PropertyValue = pi.GetValue(options, null) })
124-
where !info.PropertyValue.IsEmpty()
125-
select info)
131+
pi => new
132+
{
133+
Specification = Specification.FromProperty(pi),
134+
Value = pi.GetValue(options, null).NormalizeValue(),
135+
PropertyValue = pi.GetValue(options, null)
136+
})
137+
where !info.PropertyValue.IsEmpty(info.Specification,settings.SkipDefault)
138+
select info)
126139
.Memorize();
127140

128141
var allOptSpecs = from info in specs.Where(i => i.Specification.Tag == SpecificationType.Option)
129-
let o = (OptionSpecification)info.Specification
130-
where o.TargetType != TargetType.Switch || (o.TargetType == TargetType.Switch && ((bool)info.Value))
131-
where !o.Hidden || settings.ShowHidden
132-
orderby o.UniqueName()
133-
select info;
142+
let o = (OptionSpecification)info.Specification
143+
where o.TargetType != TargetType.Switch || (o.TargetType == TargetType.Switch && ((bool)info.Value))
144+
where !o.Hidden || settings.ShowHidden
145+
orderby o.UniqueName()
146+
select info;
134147

135148
var shortSwitches = from info in allOptSpecs
136-
let o = (OptionSpecification)info.Specification
137-
where o.TargetType == TargetType.Switch
138-
where o.ShortName.Length > 0
139-
orderby o.UniqueName()
140-
select info;
149+
let o = (OptionSpecification)info.Specification
150+
where o.TargetType == TargetType.Switch
151+
where o.ShortName.Length > 0
152+
orderby o.UniqueName()
153+
select info;
141154

142155
var optSpecs = settings.GroupSwitches
143156
? allOptSpecs.Where(info => !shortSwitches.Contains(info))
144157
: allOptSpecs;
145158

146159
var valSpecs = from info in specs.Where(i => i.Specification.Tag == SpecificationType.Value)
147-
let v = (ValueSpecification)info.Specification
148-
orderby v.Index
149-
select info;
160+
let v = (ValueSpecification)info.Specification
161+
orderby v.Index
162+
select info;
150163

151164
builder = settings.GroupSwitches && shortSwitches.Any()
152165
? builder.Append('-').Append(string.Join(string.Empty, shortSwitches.Select(
@@ -191,6 +204,7 @@ private static string FormatValue(Specification spec, object value)
191204

192205
private static object FormatWithQuotesIfString(object value)
193206
{
207+
if (value is DateTime) value = $"\"{value}\"";
194208
Func<string, string> doubQt = v
195209
=> v.Contains("\"") ? v.Replace("\"", "\\\"") : v;
196210

@@ -218,7 +232,7 @@ private static string FormatName(this OptionSpecification optionSpec, UnParserSe
218232
{
219233
// Have a long name and short name not preferred? Go with long!
220234
// No short name? Has to be long!
221-
var longName = (optionSpec.LongName.Length > 0 && !settings.PreferShortName)
235+
var longName = (optionSpec.LongName.Length > 0 && !settings.PreferShortName)
222236
|| optionSpec.ShortName.Length == 0;
223237

224238
return
@@ -242,9 +256,11 @@ private static object NormalizeValue(this object value)
242256
return value;
243257
}
244258

245-
private static bool IsEmpty(this object value)
259+
private static bool IsEmpty(this object value, Specification specification,bool skipDefault)
246260
{
247261
if (value == null) return true;
262+
263+
if (skipDefault && value.Equals(specification.DefaultValue.FromJust())) return true;
248264
#if !SKIP_FSHARP
249265
if (ReflectionHelper.IsFSharpOptionType(value.GetType()) && !FSharpOptionHelper.IsSome(value)) return true;
250266
#endif

tests/CommandLine.Tests/Fakes/Hidden_Option.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace CommandLine.Tests.Fakes
88
{
99
public class Hidden_Option
1010
{
11-
[Option('h', "hiddenOption", Default="hidden", Hidden = true)]
11+
[Option('h', "hiddenOption", Hidden = true)]
1212
public string HiddenOption { get; set; }
1313
}
1414
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace CommandLine.Tests.Fakes
2+
{
3+
class Options_With_Defaults
4+
{
5+
[Option(Default = 99)]
6+
public int P1 { get; set; }
7+
[Option()]
8+
public string P2 { get; set; }
9+
[Option(Default = 88)]
10+
public int P3 { get; set; }
11+
[Option(Default = Shapes.Square)]
12+
public Shapes P4 { get; set; }
13+
}
14+
}
15+

tests/CommandLine.Tests/Unit/UnParserExtensionsTests.cs

+36
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
22

3+
using System;
34
using System.Collections.Generic;
45
using System.Linq;
6+
using System.Text.RegularExpressions;
57
using CommandLine.Tests.Fakes;
68
using Xunit;
79
using FluentAssertions;
@@ -103,6 +105,40 @@ public static void UnParsing_instance_with_dash_in_value_and_dashdash_disabled_r
103105
.Should().BeEquivalentTo("-something with dash");
104106
}
105107

108+
[Fact]
109+
public static void UnParsing_instance_with_default_values_when_skip_default_is_false()
110+
{
111+
var options = new Options_With_Defaults { P2 = "xyz", P1 = 99, P3 = 88, P4 = Shapes.Square };
112+
new Parser()
113+
.FormatCommandLine(options)
114+
.Should().BeEquivalentTo("--p1 99 --p2 xyz --p3 88 --p4 Square");
115+
}
116+
117+
[Fact]
118+
public static void UnParsing_instance_with_default_values_when_skip_default_is_true()
119+
{
120+
var options = new Options_With_Defaults {P2 = "xyz", P1 = 99, P3 = 88,P4= Shapes.Square } ;
121+
new Parser()
122+
.FormatCommandLine(options,x=>x.SkipDefault=true)
123+
.Should().BeEquivalentTo("--p2 xyz");
124+
}
125+
126+
[Fact]
127+
public static void UnParsing_instance_with_datetime()
128+
{
129+
var date = new DateTime(2019, 5, 1);
130+
var options = new Options_Date { Start=date };
131+
var result = new Parser()
132+
.FormatCommandLine(options); //--start "1/5/2019 12:00:00 AM", date is based on Culture
133+
var expected = Regex.Match(result, @"--start\s"".+""").Success; //result contain quote
134+
Assert.True(expected);
135+
}
136+
137+
internal class Options_Date
138+
{
139+
[Option]
140+
public DateTime? Start { get; set; }
141+
}
106142
public static IEnumerable<object[]> UnParseData
107143
{
108144
get

0 commit comments

Comments
 (0)