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 ;
228using Fclp . Internals . Extensions ;
329
430namespace 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}
0 commit comments