Skip to content

Commit 817c42e

Browse files
committed
add CaseInsensitiveValues param to ParserSettings
for parsing enum values in caseInsensetive way
1 parent 6373ddb commit 817c42e

File tree

7 files changed

+33
-14
lines changed

7 files changed

+33
-14
lines changed

src/CommandLine/Core/InstanceBuilder.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public static ParserResult<T> Build<T>(
1717
Func<IEnumerable<string>, IEnumerable<OptionSpecification>, Result<IEnumerable<Token>, Error>> tokenizer,
1818
IEnumerable<string> arguments,
1919
StringComparer nameComparer,
20+
bool ignoreValueCase,
2021
CultureInfo parsingCulture,
2122
IEnumerable<ErrorType> nonFatalErrors)
2223
{
@@ -57,14 +58,14 @@ public static ParserResult<T> Build<T>(
5758
OptionMapper.MapValues(
5859
(from pt in specProps where pt.Specification.IsOption() select pt),
5960
optionsPartition,
60-
(vals, type, isScalar) => TypeConverter.ChangeType(vals, type, isScalar, parsingCulture),
61+
(vals, type, isScalar) => TypeConverter.ChangeType(vals, type, isScalar, parsingCulture, ignoreValueCase),
6162
nameComparer);
6263

6364
var valueSpecPropsResult =
6465
ValueMapper.MapValues(
6566
(from pt in specProps where pt.Specification.IsValue() select pt),
6667
valuesPartition,
67-
(vals, type, isScalar) => TypeConverter.ChangeType(vals, type, isScalar, parsingCulture));
68+
(vals, type, isScalar) => TypeConverter.ChangeType(vals, type, isScalar, parsingCulture, ignoreValueCase));
6869

6970
var missingValueErrors = from token in errorsPartition
7071
select

src/CommandLine/Core/InstanceChooser.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ private static ParserResult<object> MatchVerb(
6060
tokenizer,
6161
arguments.Skip(1),
6262
nameComparer,
63+
false,
6364
parsingCulture,
6465
nonFatalErrors)
6566
: MakeNotParsed(verbs.Select(v => v.Item2), new BadVerbSelectedError(arguments.First()));

src/CommandLine/Core/TypeConverter.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ namespace CommandLine.Core
1212
{
1313
static class TypeConverter
1414
{
15-
public static Maybe<object> ChangeType(IEnumerable<string> values, Type conversionType, bool scalar, CultureInfo conversionCulture)
15+
public static Maybe<object> ChangeType(IEnumerable<string> values, Type conversionType, bool scalar, CultureInfo conversionCulture, bool ignoreValueCase)
1616
{
1717
return scalar
18-
? ChangeTypeScalar(values.Single(), conversionType, conversionCulture)
19-
: ChangeTypeSequence(values, conversionType, conversionCulture);
18+
? ChangeTypeScalar(values.Single(), conversionType, conversionCulture, ignoreValueCase)
19+
: ChangeTypeSequence(values, conversionType, conversionCulture, ignoreValueCase);
2020
}
2121

22-
private static Maybe<object> ChangeTypeSequence(IEnumerable<string> values, Type conversionType, CultureInfo conversionCulture)
22+
private static Maybe<object> ChangeTypeSequence(IEnumerable<string> values, Type conversionType, CultureInfo conversionCulture, bool ignoreValueCase)
2323
{
2424
var type =
2525
conversionType.GetGenericArguments()
@@ -28,22 +28,22 @@ private static Maybe<object> ChangeTypeSequence(IEnumerable<string> values, Type
2828
.FromJustOrFail(
2929
new ApplicationException("Non scalar properties should be sequence of type IEnumerable<T>."));
3030

31-
var converted = values.Select(value => ChangeTypeScalar(value, type, conversionCulture));
31+
var converted = values.Select(value => ChangeTypeScalar(value, type, conversionCulture, ignoreValueCase));
3232

3333
return converted.Any(a => a.MatchNothing())
3434
? Maybe.Nothing<object>()
3535
: Maybe.Just(converted.Select(c => ((Just<object>)c).Value).ToUntypedArray(type));
3636
}
3737

38-
private static Maybe<object> ChangeTypeScalar(string value, Type conversionType, CultureInfo conversionCulture)
38+
private static Maybe<object> ChangeTypeScalar(string value, Type conversionType, CultureInfo conversionCulture, bool ignoreValueCase)
3939
{
40-
var result = ChangeTypeScalarImpl(value, conversionType, conversionCulture);
40+
var result = ChangeTypeScalarImpl(value, conversionType, conversionCulture, ignoreValueCase);
4141
result.Match((_,__) => { }, e => e.First().RethrowWhenAbsentIn(
4242
new[] { typeof(InvalidCastException), typeof(FormatException), typeof(OverflowException) }));
4343
return result.ToMaybe();
4444
}
4545

46-
private static Result<object, Exception> ChangeTypeScalarImpl(string value, Type conversionType, CultureInfo conversionCulture)
46+
private static Result<object, Exception> ChangeTypeScalarImpl(string value, Type conversionType, CultureInfo conversionCulture, bool ignoreValueCase)
4747
{
4848
Func<object> changeType = () =>
4949
{
@@ -72,7 +72,7 @@ private static Result<object, Exception> ChangeTypeScalarImpl(string value, Type
7272

7373
return value.IsBooleanString()
7474
? value.ToBoolean() : conversionType.IsEnum
75-
? value.ToEnum(conversionType) : safeChangeType();
75+
? value.ToEnum(conversionType, ignoreValueCase) : safeChangeType();
7676
};
7777

7878
Func<object> makeType = () =>
@@ -94,12 +94,12 @@ private static Result<object, Exception> ChangeTypeScalarImpl(string value, Type
9494
: makeType);
9595
}
9696

97-
private static object ToEnum(this string value, Type conversionType)
97+
private static object ToEnum(this string value, Type conversionType, bool ignoreValueCase)
9898
{
9999
object parsedValue;
100100
try
101101
{
102-
parsedValue = Enum.Parse(conversionType, value);
102+
parsedValue = Enum.Parse(conversionType, value, ignoreValueCase);
103103
}
104104
catch (ArgumentException)
105105
{

src/CommandLine/Parser.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public ParserResult<T> ParseArguments<T>(IEnumerable<string> args)
9797
(arguments, optionSpecs) => Tokenize(arguments, optionSpecs, settings),
9898
args,
9999
settings.NameComparer,
100+
settings.CaseInsensitiveValues,
100101
settings.ParsingCulture,
101102
HandleUnknownArguments(settings.IgnoreUnknownArguments)),
102103
settings);
@@ -125,6 +126,7 @@ public ParserResult<T> ParseArguments<T>(Func<T> factory, IEnumerable<string> ar
125126
(arguments, optionSpecs) => Tokenize(arguments, optionSpecs, settings),
126127
args,
127128
settings.NameComparer,
129+
settings.CaseInsensitiveValues,
128130
settings.ParsingCulture,
129131
HandleUnknownArguments(settings.IgnoreUnknownArguments)),
130132
settings);

src/CommandLine/ParserSettings.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public class ParserSettings : IDisposable
1515
{
1616
private bool disposed;
1717
private bool caseSensitive;
18+
private bool caseInsensitiveValues;
1819
private TextWriter helpWriter;
1920
private bool ignoreUnknownArguments;
2021
private CultureInfo parsingCulture;
@@ -26,6 +27,7 @@ public class ParserSettings : IDisposable
2627
public ParserSettings()
2728
{
2829
caseSensitive = true;
30+
caseInsensitiveValues = false;
2931
parsingCulture = CultureInfo.InvariantCulture;
3032
}
3133

@@ -48,6 +50,16 @@ public bool CaseSensitive
4850
set { PopsicleSetter.Set(Consumed, ref caseSensitive, value); }
4951
}
5052

53+
/// <summary>
54+
/// Gets or sets a value indicating whether perform case sensitive comparisons of <i>values</i>.
55+
/// Note that case insensitivity only applies to <i>values</i>, not the parameters.
56+
/// </summary>
57+
public bool CaseInsensitiveValues
58+
{
59+
get { return caseInsensitiveValues; }
60+
set { PopsicleSetter.Set(Consumed, ref caseInsensitiveValues, value); }
61+
}
62+
5163
/// <summary>
5264
/// Gets or sets the culture used when parsing arguments to typed properties.
5365
/// </summary>

tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ private static ParserResult<T> InvokeBuild<T>(string[] arguments)
2525
(args, optionSpecs) => Tokenizer.ConfigureTokenizer(StringComparer.Ordinal, false, false)(args, optionSpecs),
2626
arguments,
2727
StringComparer.Ordinal,
28+
false,
2829
CultureInfo.InvariantCulture,
2930
Enumerable.Empty<ErrorType>());
3031
}
@@ -36,6 +37,7 @@ private static ParserResult<T> InvokeBuildImmutable<T>(string[] arguments)
3637
(args, optionSpecs) => Tokenizer.ConfigureTokenizer(StringComparer.Ordinal, false, false)(args, optionSpecs),
3738
arguments,
3839
StringComparer.Ordinal,
40+
false,
3941
CultureInfo.InvariantCulture,
4042
Enumerable.Empty<ErrorType>());
4143
}
@@ -411,6 +413,7 @@ public void Double_dash_force_subsequent_arguments_as_values()
411413
args => Tokenizer.Tokenize(args, name => NameLookup.Contains(name, optionSpecs, StringComparer.Ordinal))),
412414
arguments,
413415
StringComparer.Ordinal,
416+
false,
414417
CultureInfo.InvariantCulture,
415418
Enumerable.Empty<ErrorType>());
416419

tests/CommandLine.Tests/Unit/Core/OptionMapperTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public void Map_boolean_switch_creates_boolean_value()
3434
var result = OptionMapper.MapValues(
3535
specProps.Where(pt => pt.Specification.IsOption()),
3636
tokenPartitions,
37-
(vals, type, isScalar) => TypeConverter.ChangeType(vals, type, isScalar, CultureInfo.InvariantCulture),
37+
(vals, type, isScalar) => TypeConverter.ChangeType(vals, type, isScalar, CultureInfo.InvariantCulture, false),
3838
StringComparer.InvariantCulture);
3939

4040
// Verify outcome

0 commit comments

Comments
 (0)