Skip to content

Commit 13a8d0a

Browse files
committed
- added the ability to treat empty args as help args.
- also added EmptyArgs property to the result to other action could be taken.
1 parent d03bd5f commit 13a8d0a

8 files changed

+147
-9
lines changed

FluentCommandLineParser.Tests/FluentCommandLineParser.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
<Compile Include="Internals\CommandLineParserEngine\when_args_contains_a_boolean_option_that_ends_with_negative_sign.cs" />
102102
<Compile Include="Internals\CommandLineParserEngine\when_args_contains_a_boolean_option_that_ends_with_no_sign.cs" />
103103
<Compile Include="Internals\CommandLineParserEngine\when_args_contains_a_boolean_option_that_ends_with_positive_sign.cs" />
104+
<Compile Include="Internals\HelpCommandLineOptionTests.cs" />
104105
<Compile Include="Internals\TestContextBase.cs" />
105106
<Compile Include="TestContext\TestContext.cs" />
106107
<Compile Include="FluentCommandLineParser\TestContext\TestType.cs" />

FluentCommandLineParser.Tests/FluentCommandLineParserTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ public void Ensure_Can_Specify_Empty_Args()
509509
var result = parser.Parse(new string[0]);
510510

511511
Assert.IsFalse(result.HasErrors);
512+
Assert.IsTrue(result.EmptyArgs);
512513
Assert.IsFalse(result.Errors.Any());
513514
}
514515

@@ -520,9 +521,40 @@ public void Ensure_Can_Specify_Null_Args()
520521
var result = parser.Parse(null);
521522

522523
Assert.IsFalse(result.HasErrors);
524+
Assert.IsTrue(result.EmptyArgs);
523525
Assert.IsFalse(result.Errors.Any());
524526
}
525527

528+
[Test]
529+
public void Ensure_Defaults_Are_Called_When_Empty_Args_Specified()
530+
{
531+
var parser = CreateFluentParser();
532+
533+
const int expectedInt = 123;
534+
const double expectedDouble = 123.456;
535+
const string expectedString = "my string";
536+
const bool expectedBool = true;
537+
538+
int actualInt = 0;
539+
double actualDouble = 0;
540+
string actualString = null;
541+
bool actualBool = false;
542+
543+
parser.Setup<int>("i").Callback(i => actualInt = i).SetDefault(expectedInt);
544+
parser.Setup<string>("s").Callback(s=> actualString = s).SetDefault(expectedString);
545+
parser.Setup<bool>("b").Callback(b => actualBool = b).SetDefault(expectedBool);
546+
parser.Setup<double>("d").Callback(d => actualDouble = d).SetDefault(expectedDouble);
547+
548+
var result = parser.Parse(null);
549+
550+
Assert.IsFalse(result.HasErrors);
551+
Assert.IsTrue(result.EmptyArgs);
552+
Assert.AreEqual(expectedInt, actualInt);
553+
Assert.AreEqual(expectedDouble, actualDouble);
554+
Assert.AreEqual(expectedString, actualString);
555+
Assert.AreEqual(expectedBool, actualBool);
556+
}
557+
526558
#endregion No Args
527559

528560
#region Example
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#region License
2+
// HelpCommandLineOptionTests.cs
3+
// Copyright (c) 2013, Simon Williams
4+
// All rights reserved.
5+
//
6+
// Redistribution and use in source and binary forms, with or without modification, are permitted provide
7+
// d that the following conditions are met:
8+
//
9+
// Redistributions of source code must retain the above copyright notice, this list of conditions and the
10+
// following disclaimer.
11+
//
12+
// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
13+
// the following disclaimer in the documentation and/or other materials provided with the distribution.
14+
//
15+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
16+
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17+
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18+
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
19+
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20+
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21+
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22+
// POSSIBILITY OF SUCH DAMAGE.
23+
#endregion
24+
25+
using System.Collections.Generic;
26+
using Fclp.Internals;
27+
using Machine.Specifications;
28+
29+
namespace Fclp.Tests.Internals
30+
{
31+
sealed class HelpCommandLineOptionTests
32+
{
33+
abstract class HelpCommandLineOptionTestContext : TestContextBase<HelpCommandLineOption>
34+
{
35+
Establish context = () => CreatSut();
36+
}
37+
38+
39+
sealed class ShouldShowHelp
40+
{
41+
abstract class ShouldShowHelpTestContext : HelpCommandLineOptionTestContext
42+
{
43+
protected static bool actualResult;
44+
protected static IEnumerable<ParsedOption> parsedOptions;
45+
46+
Because of = () => actualResult = sut.ShouldShowHelp(parsedOptions);
47+
}
48+
49+
class when_the_args_are_empty_and_the_option_is_setup_to_handle_empty_args_like_help_args : ShouldShowHelpTestContext
50+
{
51+
Establish context = () =>
52+
{
53+
parsedOptions = null;
54+
sut.UseForEmptyArgs();
55+
};
56+
57+
It should_return_true = () => actualResult.ShouldBeTrue();
58+
}
59+
class when_the_args_are_empty_and_the_option_is_not_setup_to_handle_empty_args_like_help_args : ShouldShowHelpTestContext
60+
{
61+
Establish context = () => parsedOptions = null;
62+
63+
It should_return_false = () => actualResult.ShouldBeFalse();
64+
}
65+
}
66+
}
67+
}

FluentCommandLineParser/FluentCommandLineParser.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,11 @@ public ICommandLineOptionFluent<T> Setup<T>(string shortOption)
173173
/// <returns>An <see cref="ICommandLineParserResult"/> representing the results of the parse operation.</returns>
174174
public ICommandLineParserResult Parse(string[] args)
175175
{
176-
var result = new CommandLineParserResult();
177-
178176
var parsedOptions = this.ParserEngine.Parse(args).ToList();
179177

180-
if (this.HelpOption.ShouldShowHelp(parsedOptions))
178+
var result = new CommandLineParserResult { EmptyArgs = parsedOptions.IsNullOrEmpty() };
179+
180+
if (this.HelpOption.ShouldShowHelp(parsedOptions))
181181
{
182182
result.HelpCalled = true;
183183
this.HelpOption.ShowHelp(this.Options);

FluentCommandLineParser/ICommandLineParserResult.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public interface ICommandLineParserResult
4242
/// </summary>
4343
bool HelpCalled { get; }
4444

45+
/// <summary>
46+
/// Gets whether the parser was called with empty arguments.
47+
/// </summary>
48+
bool EmptyArgs { get; }
49+
4550
/// <summary>
4651
/// Gets the errors which occurred during the parse operation.
4752
/// </summary>

FluentCommandLineParser/IHelpCommandLineOptionFluent.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,28 @@ public interface IHelpCommandLineOptionFluent
5353
/// <param name="callback">
5454
/// The callback to execute. If you have also setup the other help callback this will be called last.
5555
/// </param>
56-
/// <returns>A <see cref="ICommandLineOptionFluent{T}"/>.</returns>
56+
/// <returns>A <see cref="IHelpCommandLineOptionFluent"/>.</returns>
5757
IHelpCommandLineOptionFluent Callback(Action callback);
5858

5959
/// <summary>
6060
/// Registers a custom <see cref="ICommandLineOptionFormatter"/> to use to generate the help text.
6161
/// </summary>
6262
/// <param name="formatter">The custom formatter to use. This must not be <c>null</c>.</param>
63+
/// <returns>A <see cref="IHelpCommandLineOptionFluent"/>.</returns>
6364
IHelpCommandLineOptionFluent WithCustomFormatter(ICommandLineOptionFormatter formatter);
6465

6566
/// <summary>
6667
/// Provides a custom header to be printed before the registered options.
6768
/// </summary>
6869
/// <param name="header">The header to use.</param>
70+
/// <returns>A <see cref="IHelpCommandLineOptionFluent"/>.</returns>
6971
IHelpCommandLineOptionFluent WithHeader(string header);
72+
73+
/// <summary>
74+
/// Specifies that if empty arguments are found then the behaviour should be the same as when any help arguments
75+
/// are found.
76+
/// </summary>
77+
/// <returns>A <see cref="IHelpCommandLineOptionFluent"/>.</returns>
78+
IHelpCommandLineOptionFluent UseForEmptyArgs();
7079
}
7180
}

FluentCommandLineParser/Internals/CommandLineParserResult.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public bool HasErrors
5050
get { return this.Errors.Any(); }
5151
}
5252

53-
/// <summary>
53+
/// <summary>
5454
///
5555
/// </summary>
5656
internal IList<ICommandLineParserError> Errors { get; set; }
@@ -93,5 +93,10 @@ IEnumerable<ICommandLineOption> ICommandLineParserResult.UnMatchedOptions
9393
/// Gets whether the help text was called.
9494
/// </summary>
9595
public bool HelpCalled { get; set; }
96+
97+
/// <summary>
98+
/// Gets whether the parser was called with empty arguments.
99+
/// </summary>
100+
public bool EmptyArgs { get; set; }
96101
}
97102
}

FluentCommandLineParser/Internals/HelpCommandLineOption.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public HelpCommandLineOption(IEnumerable<string> helpArgs)
5656

5757
private Action ReturnCallbackWithoutParser { get; set; }
5858

59+
private bool ShouldUseForEmptyArgs { get; set; }
60+
5961
/// <summary>
6062
/// Gets or sets any header to display at the top of the printed options.
6163
/// </summary>
@@ -119,15 +121,32 @@ public IHelpCommandLineOptionFluent WithHeader(string header)
119121
return this;
120122
}
121123

122-
/// <summary>
124+
/// <summary>
125+
/// Specifies that if empty arguments are found then the behaviour should be the same as when any help arguments
126+
/// are found.
127+
/// </summary>
128+
/// <returns>A <see cref="IHelpCommandLineOptionFluent"/>.</returns>
129+
public IHelpCommandLineOptionFluent UseForEmptyArgs()
130+
{
131+
this.ShouldUseForEmptyArgs = true;
132+
return this;
133+
}
134+
135+
/// <summary>
123136
/// Determines whether the help text should be shown.
124137
/// </summary>
125138
/// <param name="parsedOptions">The parsed command line arguments</param>
126139
/// <returns>true if the parser operation should cease and <see cref="ShowHelp"/> should be called; otherwise false if the parse operation to continue.</returns>
127140
public bool ShouldShowHelp(IEnumerable<ParsedOption> parsedOptions)
128-
{
129-
parsedOptions = parsedOptions ?? new List<ParsedOption>();
130-
return this.HelpArgs.Any(helpArg => parsedOptions.Any(cmdArg => helpArg.Equals(cmdArg.Key, StringComparison.CurrentCultureIgnoreCase)));
141+
{
142+
var parsed = parsedOptions != null ? parsedOptions.ToList() : new List<ParsedOption>();
143+
144+
if (parsed.Any() == false && ShouldUseForEmptyArgs)
145+
{
146+
return true;
147+
}
148+
149+
return this.HelpArgs.Any(helpArg => parsed.Any(cmdArg => helpArg.Equals(cmdArg.Key, StringComparison.CurrentCultureIgnoreCase)));
131150
}
132151

133152
/// <summary>

0 commit comments

Comments
 (0)