Skip to content

Commit ac09c57

Browse files
committed
refactor parsing grouper class
1 parent 44639f2 commit ac09c57

File tree

5 files changed

+117
-151
lines changed

5 files changed

+117
-151
lines changed

FluentCommandLineParser.Tests/Internals/CommandLineOptionGrouperTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ abstract class GroupByOptionTestContext : CommandLineOptionGrouperTestContext
4444

4545
Because of = () =>
4646
error = Catch.Exception(() =>
47-
actualResult = sut.GroupByOption(args));
47+
actualResult = sut.GroupArgumentsByOption(args));
4848
}
4949

5050
class when_double_dashes_are_used_to_terminate_option_parsing : GroupByOptionTestContext

FluentCommandLineParser/FluentCommandLineParser.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,8 @@
9595
<Compile Include="Internals\Parsers\Int32CommandLineOptionParser.cs" />
9696
<Compile Include="Internals\Parsers\ListCommandLineOptionParser.cs" />
9797
<Compile Include="Internals\Parsers\StringCommandLineOptionParser.cs" />
98-
<Compile Include="Internals\Parsing\CommandLineOptionGrouper.cs" />
9998
<Compile Include="Internals\Parsing\OptionArgumentParser.cs" />
100-
<Compile Include="Internals\Parsing\Something.cs" />
99+
<Compile Include="Internals\Parsing\CommandLineOptionGrouper.cs" />
101100
<Compile Include="Internals\SpecialCharacters.cs" />
102101
<Compile Include="Internals\Validators\CommandLineOptionValidator.cs" />
103102
<Compile Include="Internals\Validators\ICommandLineOptionValidator.cs" />

FluentCommandLineParser/Internals/CommandLineParserEngineMark2.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public ParserEngineResult Parse(string[] args)
4747

4848
var grouper = new CommandLineOptionGrouper();
4949

50-
foreach (var optionGroup in grouper.GroupByOption(args))
50+
foreach (var optionGroup in grouper.GroupArgumentsByOption(args))
5151
{
5252
string rawKey = optionGroup.First();
5353
ParseGroupIntoOption(rawKey, optionGroup.Skip(1));
Lines changed: 114 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,143 @@
1-
using System.Collections.Generic;
1+
#region License
2+
// CommandLineOptionGrouper.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;
26+
using System.Collections.Generic;
27+
using System.Linq;
228
using Fclp.Internals.Extensions;
329

430
namespace Fclp.Internals.Parsing
531
{
632
/// <summary>
7-
///
33+
/// Organises arguments into group defined by their associated Option.
834
/// </summary>
935
public class CommandLineOptionGrouper
1036
{
37+
private string[] _args;
38+
private int _currentOptionLookupIndex;
39+
private int[] _foundOptionLookup;
40+
private int _currentOptionIndex;
41+
1142
/// <summary>
12-
/// Groups the by option.
43+
/// Groups the specified arguments by the associated Option.
1344
/// </summary>
14-
/// <param name="args">The args.</param>
15-
/// <returns></returns>
16-
public string[][] GroupByOption(string[] args)
45+
public string[][] GroupArgumentsByOption(string[] args)
1746
{
1847
if (args.IsNullOrEmpty()) return new string[0][];
1948

20-
var optionParser = new Something(args);
49+
_args = args;
50+
51+
_currentOptionIndex = -1;
52+
_currentOptionLookupIndex = -1;
53+
FindOptionIndexes();
2154

2255
var options = new List<string[]>();
2356

24-
if (optionParser.ArgsContainsOptions() == false)
57+
if (this.ArgsContainsOptions() == false)
2558
{
26-
options.Add(optionParser.CreateGroupForCurrent());
59+
options.Add(this.CreateGroupForCurrent());
2760
}
2861
else
2962
{
30-
while (optionParser.MoveToNextOption())
63+
while (MoveToNextOption())
3164
{
32-
options.Add(optionParser.CreateGroupForCurrent());
65+
options.Add(CreateGroupForCurrent());
3366
}
3467
}
3568

3669
return options.ToArray();
3770
}
3871

72+
private string[] CreateGroupForCurrent()
73+
{
74+
var optionEndIndex = LookupTheNextOptionIndex();
75+
76+
optionEndIndex = optionEndIndex != -1
77+
? optionEndIndex - 1
78+
: _args.Length - 1;
79+
80+
var length = optionEndIndex - (_currentOptionIndex - 1);
81+
82+
return _args.Skip(_currentOptionIndex)
83+
.Take(length)
84+
.ToArray();
85+
}
86+
87+
private void FindOptionIndexes()
88+
{
89+
var indexes = new List<int>();
90+
91+
for (int index = 0; index < _args.Length; index++)
92+
{
93+
string currentArg = _args[index];
94+
95+
if (IsEndOfOptionsKey(currentArg)) break;
96+
if (IsAKey(currentArg) == false) continue;
97+
98+
indexes.Add(index);
99+
}
100+
101+
_foundOptionLookup = indexes.ToArray();
102+
}
103+
104+
private bool ArgsContainsOptions()
105+
{
106+
return _foundOptionLookup.Any();
107+
}
108+
109+
private bool MoveToNextOption()
110+
{
111+
var nextIndex = LookupTheNextOptionIndex();
112+
if (nextIndex == -1) return false;
113+
114+
_currentOptionLookupIndex += 1;
115+
_currentOptionIndex = nextIndex;
116+
117+
return true;
118+
}
119+
120+
private int LookupTheNextOptionIndex()
121+
{
122+
return _foundOptionLookup.ElementAtOrDefault(_currentOptionLookupIndex + 1, -1);
123+
}
124+
125+
/// <summary>
126+
/// Gets whether the specified <see cref="System.String"/> is a Option key.
127+
/// </summary>
128+
/// <param name="arg">The <see cref="System.String"/> to examine.</param>
129+
/// <returns><c>true</c> if <paramref name="arg"/> is a Option key; otherwise <c>false</c>.</returns>
130+
static bool IsAKey(string arg)
131+
{
132+
return arg != null && SpecialCharacters.OptionPrefix.Any(arg.StartsWith);
133+
}
134+
135+
/// <summary>
136+
/// Determines whether the specified string indicates the end of parsed options.
137+
/// </summary>
138+
static bool IsEndOfOptionsKey(string arg)
139+
{
140+
return string.Equals(arg, SpecialCharacters.EndOfOptionsKey, StringComparison.InvariantCultureIgnoreCase);
141+
}
39142
}
40143
}

FluentCommandLineParser/Internals/Parsing/Something.cs

Lines changed: 0 additions & 136 deletions
This file was deleted.

0 commit comments

Comments
 (0)