Skip to content

Commit a7f919d

Browse files
committed
Added OptionStyle to Option to indicate whether an option is a switch, a single-valued option or a multi-valued option.
1 parent cf253c1 commit a7f919d

15 files changed

+133
-107
lines changed

J4JCommandLine.Tests/SwitchPropertyTest.cs

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@ namespace J4JCommandLine.Tests
88
public class SwitchPropertyTest
99
{
1010
[Theory]
11-
[InlineData("-x 32", true, MappingResults.Success, true, new int[] { 32 })]
12-
[InlineData("-x", true, MappingResults.Success, true, new int[] { })]
13-
[InlineData("-x", false, MappingResults.MissingParameter, false, new int[] { })]
11+
[InlineData("-x 32", MappingResults.Success, true, new int[] { 32 })]
12+
[InlineData("-x", MappingResults.Success, true, new int[] { })]
1413
public void root_properties(
1514
string cmdLine,
16-
bool isSwitch,
1715
MappingResults result,
1816
bool optValue,
1917
int[] unkeyedValues)
@@ -22,17 +20,15 @@ public void root_properties(
2220
var option = target!.Bind(x => x.Switch, "x");
2321
var unkeyed = target!.BindUnkeyed(x => x.Unkeyed);
2422

25-
ProcessTest(cmdLine, isSwitch, target, option, unkeyed, result, () => target.Value, optValue,
23+
ProcessTest(cmdLine, target, option, unkeyed, result, () => target.Value, optValue,
2624
unkeyedValues);
2725
}
2826

2927
[Theory]
30-
[InlineData("-x 32", true, MappingResults.Success, true, new int[] { 32 })]
31-
[InlineData("-x", true, MappingResults.Success, true, new int[] { })]
32-
[InlineData("-x", false, MappingResults.MissingParameter, false, new int[] { })]
28+
[InlineData("-x 32", MappingResults.Success, true, new int[] { 32 })]
29+
[InlineData("-x", MappingResults.Success, true, new int[] { })]
3330
public void parameterless_properties(
3431
string cmdLine,
35-
bool isSwitch,
3632
MappingResults result,
3733
bool optValue,
3834
int[] unkeyedValues)
@@ -41,17 +37,15 @@ public void parameterless_properties(
4137
var option = target!.Bind(x => x.TestProperties.Switch, "x");
4238
var unkeyed = target!.BindUnkeyed(x => x.TestProperties.Unkeyed);
4339

44-
ProcessTest(cmdLine, isSwitch, target, option, unkeyed, result, () => target.Value.TestProperties, optValue,
40+
ProcessTest(cmdLine, target, option, unkeyed, result, () => target.Value.TestProperties, optValue,
4541
unkeyedValues);
4642
}
4743

4844
[Theory]
49-
[InlineData("-x 32", true, MappingResults.Success, true, new int[] { 32 })]
50-
[InlineData("-x", true, MappingResults.Success, true, new int[] { })]
51-
[InlineData("-x", false, MappingResults.MissingParameter, false, new int[] { })]
45+
[InlineData("-x 32", MappingResults.Success, true, new int[] { 32 })]
46+
[InlineData("-x", MappingResults.Success, true, new int[] { })]
5247
public void parametered_properties(
5348
string cmdLine,
54-
bool isSwitch,
5549
MappingResults result,
5650
bool optValue,
5751
int[] unkeyedValues)
@@ -64,13 +58,12 @@ public void parametered_properties(
6458
var option = target!.Bind(x => x.TestProperties.Switch, "x");
6559
var unkeyed = target!.BindUnkeyed(x => x.TestProperties.Unkeyed);
6660

67-
ProcessTest(cmdLine, isSwitch, target, option, unkeyed, result, () => target.Value.TestProperties, optValue,
61+
ProcessTest(cmdLine, target, option, unkeyed, result, () => target.Value.TestProperties, optValue,
6862
unkeyedValues);
6963
}
7064

7165
private void ProcessTest<T>(
7266
string cmdLine,
73-
bool isSwitch,
7467
BindingTarget<T> target,
7568
Option option,
7669
Option unkeyed,
@@ -83,8 +76,6 @@ private void ProcessTest<T>(
8376
target.Should().NotBeNull();
8477

8578
option.Should().BeAssignableTo<MappableOption>();
86-
option.Switch(isSwitch);
87-
8879
unkeyed.Should().BeAssignableTo<MappableOption>();
8980

9081
var parseResults = target.Parse(new string[] { cmdLine });

J4JCommandLine/option/MappableOption.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,19 @@ public override MappingResults Convert(
3232

3333
switch( targetType.Multiplicity )
3434
{
35-
case Multiplicity.Array:
35+
case PropertyMultiplicity.Array:
3636
retVal = ConvertToArray( bindingTarget, parseResult, out var arrayResult );
3737
result = arrayResult;
3838

3939
break;
4040

41-
case Multiplicity.List:
41+
case PropertyMultiplicity.List:
4242
retVal = ConvertToList( bindingTarget, parseResult, out var listResult);
4343
result = listResult;
4444

4545
break;
4646

47-
case Multiplicity.SimpleValue:
47+
case PropertyMultiplicity.SimpleValue:
4848
retVal = ConvertToSimpleValue( bindingTarget, parseResult, out var singleResult);
4949
result = singleResult;
5050

@@ -81,13 +81,13 @@ private MappingResults ConvertToSimpleValue(
8181
out object? result )
8282
{
8383
result = null;
84-
var retVal = ValidParameterCount( bindingTarget, parseResult, false );
84+
var retVal = ValidParameterCount( bindingTarget, parseResult );
8585

8686
if( retVal != MappingResults.Success )
8787
return retVal;
8888

8989
// handle boolean flag parameters which don't have a parameter
90-
var text = IsSwitch && parseResult.NumParameters == 0
90+
var text = OptionStyle == OptionStyle.Switch && parseResult.NumParameters == 0
9191
? "true"
9292
: parseResult.Parameters[ 0 ];
9393

@@ -109,7 +109,7 @@ private MappingResults ConvertToArray(
109109
out Array? result )
110110
{
111111
result = null;
112-
var retVal = ValidParameterCount(bindingTarget, parseResult, true);
112+
var retVal = ValidParameterCount(bindingTarget, parseResult );
113113

114114
if (retVal != MappingResults.Success)
115115
return retVal;
@@ -147,7 +147,7 @@ private MappingResults ConvertToList(
147147
out IList? result )
148148
{
149149
result = null;
150-
var retVal = ValidParameterCount(bindingTarget, parseResult, true);
150+
var retVal = ValidParameterCount(bindingTarget, parseResult);
151151

152152
if (retVal != MappingResults.Success)
153153
return retVal;

J4JCommandLine/option/Option.cs

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34

45
namespace J4JSoftware.CommandLine
56
{
7+
public enum OptionStyle
8+
{
9+
Switch,
10+
SingleValued,
11+
Collection
12+
}
13+
614
// the abstract base class of Option and NullOption.
715
public abstract class Option
816
{
@@ -43,8 +51,10 @@ OptionCollection options
4351
// flag indicating whether or not the option must be specified on the command line
4452
public bool IsRequired { get; internal set; }
4553

46-
// flag indicating whether or not an option requires a parameter. Switches do not.
47-
public bool IsSwitch { get; internal set; }
54+
// flag indicating whether or not an option requires a parameter and whether or not
55+
// multiple parameters are allowed. Switches do not have parameters. Collections
56+
// require multiple parameters to be allowed.
57+
public OptionStyle OptionStyle { get; internal set; }
4858

4959
// the validator for the Option
5060
public IOptionValidator Validator { get; internal set; }
@@ -93,37 +103,44 @@ public abstract MappingResults Convert(
93103

94104
// validates whether or not a valid number of parameters are included in the specified
95105
// IParseResult
96-
protected MappingResults ValidParameterCount( IBindingTarget bindingTarget, IParseResult parseResult, bool isCollection )
106+
protected MappingResults ValidParameterCount( IBindingTarget bindingTarget, IParseResult parseResult )
97107
{
98108
// The UnkeyedOption allows for any number of parameters
99109
if( OptionType == OptionType.Unkeyed )
100110
return MappingResults.Success;
101111

102-
if( IsSwitch )
112+
switch( OptionStyle )
103113
{
104-
if( parseResult.NumParameters > 0 )
105-
parseResult.MoveExcessParameters(0);
106-
}
107-
else
108-
{
109-
switch( parseResult.NumParameters )
110-
{
111-
case 0:
112-
bindingTarget.AddError(parseResult.Key, $"Expected one parameter, got none");
113-
return MappingResults.MissingParameter;
114-
115-
case 1:
116-
// no op
117-
break;
118-
119-
default:
120-
// keep only one parameter unless we're a collection
121-
// in which case keep them all
122-
if( !isCollection )
114+
case OptionStyle.Switch:
115+
if (parseResult.NumParameters > 0)
116+
parseResult.MoveExcessParameters(0);
117+
118+
break;
119+
120+
case OptionStyle.SingleValued:
121+
switch( parseResult.NumParameters )
122+
{
123+
case 0:
124+
bindingTarget.AddError(parseResult.Key, $"Expected one parameter, got none");
125+
return MappingResults.MissingParameter;
126+
127+
case 1:
128+
// no op; desired situation
129+
break;
130+
131+
default:
123132
parseResult.MoveExcessParameters(1);
133+
break;
134+
}
135+
136+
break;
137+
138+
case OptionStyle.Collection:
139+
// any number of a parameters is okay
140+
break;
124141

125-
break;
126-
}
142+
default:
143+
throw new NotSupportedException( $"Unsupported {nameof(OptionStyle)} '{OptionStyle}'" );
127144
}
128145

129146
return MappingResults.Success;

J4JCommandLine/option/OptionExtensions.cs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,6 @@ public static T Optional<T>( this T option )
7979
return option;
8080
}
8181

82-
// sets the minimum and maximum, if specified, allowed number of parameters that can appear
83-
// after a key on the command line for an Option. Ignored if the specified Option object is
84-
// a NullOption.
85-
public static T Switch<T>( this T option, bool isSwitch = true )
86-
where T : Option
87-
{
88-
if( option.OptionType != OptionType.Keyed )
89-
return option;
90-
91-
option.IsSwitch = isSwitch;
92-
93-
return option;
94-
}
95-
9682
// sets the optional description for an Option. Ignored if the specified Option object is
9783
// a NullOption.
9884
public static T SetDescription<T>( this T option, string description )

0 commit comments

Comments
 (0)