Skip to content

Commit cc553c0

Browse files
committed
added ability to enable/disable case sensitive comparisons
1 parent 6cc36dc commit cc553c0

File tree

2 files changed

+191
-52
lines changed

2 files changed

+191
-52
lines changed

FluentCommandLineParser.Tests/Internals/Validators/NoDuplicateOptionValidatorTests.cs

Lines changed: 173 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
// POSSIBILITY OF SUCH DAMAGE.
2323
#endregion
2424

25+
using System;
2526
using Fclp.Internals;
2627
using Fclp.Internals.Validators;
2728
using Machine.Specifications;
@@ -44,6 +45,34 @@ abstract class NoDuplicateOptionValidatorTestContext : TestContextBase<NoDuplica
4445
};
4546
}
4647

48+
sealed class IsCaseSensitive
49+
{
50+
abstract class IsCaseSensitiveTestContext : NoDuplicateOptionValidatorTestContext
51+
{ }
52+
53+
class when_enabled : IsCaseSensitiveTestContext
54+
{
55+
Because of = () => sut.IsCaseSensitive = true;
56+
57+
It should_return_enabled = () =>
58+
sut.IsCaseSensitive.ShouldBeTrue();
59+
60+
It should_set_the_comparison_type_to_case_sensitive = () =>
61+
sut.ComparisonType.ShouldEqual(StringComparison.CurrentCulture);
62+
}
63+
64+
class when_disabled : IsCaseSensitiveTestContext
65+
{
66+
Because of = () => sut.IsCaseSensitive = false;
67+
68+
It should_return_enabled = () =>
69+
sut.IsCaseSensitive.ShouldBeFalse();
70+
71+
It should_set_the_comparison_type_to_ignore_case = () =>
72+
sut.ComparisonType.ShouldEqual(StringComparison.CurrentCultureIgnoreCase);
73+
}
74+
}
75+
4776
sealed class Validate
4877
{
4978
[Subject("Validate")]
@@ -92,82 +121,176 @@ class when_there_have_been_no_options_setup_thus_far : ValidateTestContext
92121
It should_not_throw_an_error = () => error.ShouldBeNull();
93122
}
94123

95-
class when_an_existing_option_contains_the_same_short_name_but_it_differs_by_case : ValidateTestContext
124+
sealed class when_case_sensitive
96125
{
97-
Establish context = () =>
126+
abstract class CaseSensitiveTestContext : ValidateTestContext
98127
{
99-
var existingOption =
100-
CreateOptionWith(shortName: option.Object.ShortName.ToUpperInvariant());
128+
Establish context = () => sut.IsCaseSensitive = true;
129+
}
101130

102-
SetupExistingParserOptions(existingOption);
103-
};
131+
class when_an_existing_option_contains_the_same_short_name_but_it_differs_by_case : CaseSensitiveTestContext
132+
{
133+
Establish context = () =>
134+
{
135+
var existingOption =
136+
CreateOptionWith(shortName: option.Object.ShortName.ToUpperInvariant());
104137

105-
It should_not_throw_an_error = () => error.ShouldBeNull();
106-
}
138+
SetupExistingParserOptions(existingOption);
139+
};
107140

108-
class when_an_existing_option_contains_the_same_short_name : ValidateTestContext
109-
{
110-
Establish context = () =>
141+
It should_not_throw_an_error = () => error.ShouldBeNull();
142+
}
143+
144+
class when_an_existing_option_contains_the_same_short_name : CaseSensitiveTestContext
111145
{
112-
var existingOption =
113-
CreateOptionWith(shortName: option.Object.ShortName);
146+
Establish context = () =>
147+
{
148+
var existingOption =
149+
CreateOptionWith(shortName: option.Object.ShortName);
114150

115-
SetupExistingParserOptions(existingOption);
116-
};
151+
SetupExistingParserOptions(existingOption);
152+
};
117153

118-
It should_throw_an_error = () => error.ShouldNotBeNull();
119-
}
154+
It should_throw_an_error = () => error.ShouldNotBeNull();
155+
}
120156

121-
class when_an_existing_option_contains_the_same_long_name_but_it_differs_by_case : ValidateTestContext
122-
{
123-
Establish context = () =>
157+
class when_an_existing_option_contains_the_same_long_name_but_it_differs_by_case : CaseSensitiveTestContext
124158
{
125-
var existingOption =
126-
CreateOptionWith(longName: option.Object.LongName.ToUpperInvariant());
159+
Establish context = () =>
160+
{
161+
var existingOption =
162+
CreateOptionWith(longName: option.Object.LongName.ToUpperInvariant());
127163

128-
SetupExistingParserOptions(existingOption);
129-
};
164+
SetupExistingParserOptions(existingOption);
165+
};
130166

131-
It should_not_throw_an_error = () => error.ShouldBeNull();
132-
}
167+
It should_not_throw_an_error = () => error.ShouldBeNull();
168+
}
133169

134-
class when_an_existing_option_contains_the_same_long_name : ValidateTestContext
135-
{
136-
Establish context = () =>
170+
class when_an_existing_option_contains_the_same_long_name : CaseSensitiveTestContext
137171
{
138-
var existingOption =
139-
CreateOptionWith(longName: option.Object.LongName);
172+
Establish context = () =>
173+
{
174+
var existingOption =
175+
CreateOptionWith(longName: option.Object.LongName);
140176

141-
SetupExistingParserOptions(existingOption);
142-
};
177+
SetupExistingParserOptions(existingOption);
178+
};
143179

144-
It should_throw_an_error = () => error.ShouldNotBeNull();
145-
}
180+
It should_throw_an_error = () => error.ShouldNotBeNull();
181+
}
146182

147-
class when_an_existing_option_contains_the_same_short_AND_long_name_but_they_differs_by_case : ValidateTestContext
148-
{
149-
Establish context = () =>
183+
class when_an_existing_option_contains_the_same_short_AND_long_name_but_they_differs_by_case : CaseSensitiveTestContext
150184
{
151-
var existingOption =
152-
CreateOptionWith(shortName: option.Object.ShortName.ToUpperInvariant(), longName: option.Object.LongName.ToUpperInvariant());
185+
Establish context = () =>
186+
{
187+
var existingOption =
188+
CreateOptionWith(shortName: option.Object.ShortName.ToUpperInvariant(), longName: option.Object.LongName.ToUpperInvariant());
153189

154-
SetupExistingParserOptions(existingOption);
155-
};
190+
SetupExistingParserOptions(existingOption);
191+
};
156192

157-
It should_not_throw_an_error = () => error.ShouldBeNull();
193+
It should_not_throw_an_error = () => error.ShouldBeNull();
194+
}
195+
196+
class when_an_existing_option_contains_the_same_short_AND_long_name : CaseSensitiveTestContext
197+
{
198+
Establish context = () =>
199+
{
200+
var existingOption =
201+
CreateOptionWith(shortName: option.Object.ShortName, longName: option.Object.LongName);
202+
203+
SetupExistingParserOptions(existingOption);
204+
};
205+
206+
It should_throw_an_error = () => error.ShouldNotBeNull();
207+
}
158208
}
159209

160-
class when_an_existing_option_contains_the_same_short_AND_long_name : ValidateTestContext
210+
sealed class when_ignore_case
161211
{
162-
Establish context = () =>
212+
abstract class IgnoreCaseTestContext : ValidateTestContext
163213
{
164-
var existingOption =
165-
CreateOptionWith(shortName: option.Object.ShortName, longName: option.Object.LongName);
214+
Establish context = () => sut.IsCaseSensitive = false;
215+
}
166216

167-
SetupExistingParserOptions(existingOption);
168-
};
217+
class when_an_existing_option_contains_the_same_short_name_but_it_differs_by_case : IgnoreCaseTestContext
218+
{
219+
Establish context = () =>
220+
{
221+
var existingOption =
222+
CreateOptionWith(shortName: option.Object.ShortName.ToUpperInvariant());
223+
224+
SetupExistingParserOptions(existingOption);
225+
};
226+
227+
It should_throw_an_error_because_case_is_ignored = () => error.ShouldNotBeNull();
228+
}
229+
230+
class when_an_existing_option_contains_the_same_short_name : IgnoreCaseTestContext
231+
{
232+
Establish context = () =>
233+
{
234+
var existingOption =
235+
CreateOptionWith(shortName: option.Object.ShortName);
236+
237+
SetupExistingParserOptions(existingOption);
238+
};
239+
240+
It should_throw_an_error = () => error.ShouldNotBeNull();
241+
}
242+
243+
class when_an_existing_option_contains_the_same_long_name_but_it_differs_by_case : IgnoreCaseTestContext
244+
{
245+
Establish context = () =>
246+
{
247+
var existingOption =
248+
CreateOptionWith(longName: option.Object.LongName.ToUpperInvariant());
249+
250+
SetupExistingParserOptions(existingOption);
251+
};
252+
253+
It should_throw_an_error_because_case_is_ignored = () => error.ShouldNotBeNull();
254+
}
255+
256+
class when_an_existing_option_contains_the_same_long_name : IgnoreCaseTestContext
257+
{
258+
Establish context = () =>
259+
{
260+
var existingOption =
261+
CreateOptionWith(longName: option.Object.LongName);
262+
263+
SetupExistingParserOptions(existingOption);
264+
};
265+
266+
It should_throw_an_error = () => error.ShouldNotBeNull();
267+
}
268+
269+
class when_an_existing_option_contains_the_same_short_AND_long_name_but_they_differs_by_case : IgnoreCaseTestContext
270+
{
271+
Establish context = () =>
272+
{
273+
var existingOption =
274+
CreateOptionWith(shortName: option.Object.ShortName.ToUpperInvariant(), longName: option.Object.LongName.ToUpperInvariant());
275+
276+
SetupExistingParserOptions(existingOption);
277+
};
278+
279+
It should_throw_an_error_because_case_is_ignored = () => error.ShouldNotBeNull();
280+
}
281+
282+
class when_an_existing_option_contains_the_same_short_AND_long_name : IgnoreCaseTestContext
283+
{
284+
Establish context = () =>
285+
{
286+
var existingOption =
287+
CreateOptionWith(shortName: option.Object.ShortName, longName: option.Object.LongName);
288+
289+
SetupExistingParserOptions(existingOption);
290+
};
169291

170-
It should_throw_an_error = () => error.ShouldNotBeNull();
292+
It should_throw_an_error = () => error.ShouldNotBeNull();
293+
}
171294
}
172295
}
173296
}

FluentCommandLineParser/Internals/Validators/NoDuplicateOptionValidator.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public class NoDuplicateOptionValidator : ICommandLineOptionValidator
3333
{
3434
private readonly IFluentCommandLineParser _parser;
3535

36+
37+
3638
/// <summary>
3739
/// Initialises a new instance of the <see cref="NoDuplicateOptionValidator"/> class.
3840
/// </summary>
@@ -43,6 +45,20 @@ public NoDuplicateOptionValidator(IFluentCommandLineParser parser)
4345
_parser = parser;
4446
}
4547

48+
/// <summary>
49+
/// Gets the <see cref="StringComparison"/> type used for duplicates.
50+
/// </summary>
51+
public StringComparison ComparisonType { get; private set; }
52+
53+
/// <summary>
54+
/// Gets or sets whether values that differ by case are considered different.
55+
/// </summary>
56+
public bool IsCaseSensitive
57+
{
58+
get { return ComparisonType == StringComparison.CurrentCulture; }
59+
set { ComparisonType = value ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase; }
60+
}
61+
4662
/// <summary>
4763
/// Verifies that the specified <see cref="ICommandLineOption"/> will not cause any duplication.
4864
/// </summary>
@@ -63,9 +79,9 @@ public void Validate(ICommandLineOption commandLineOption)
6379
}
6480
}
6581

66-
private static void ValuesAreEqual(string value, string otherValue)
82+
private void ValuesAreEqual(string value, string otherValue)
6783
{
68-
if (string.Equals(value, otherValue, StringComparison.CurrentCulture))
84+
if (string.Equals(value, otherValue, ComparisonType))
6985
{
7086
throw new OptionAlreadyExistsException(value);
7187
}

0 commit comments

Comments
 (0)