11using System ;
22using System . Collections . Generic ;
3- using System . Globalization ;
3+ using System . ComponentModel ;
44using System . Linq ;
55using System . Reflection ;
6+ using System . Text ;
67using Codeaddicts . libArgument . Attributes ;
7- using System . ComponentModel ;
8+ using Codeaddicts . libArgument . Documentation ;
89
910namespace Codeaddicts . libArgument
1011{
@@ -13,60 +14,97 @@ namespace Codeaddicts.libArgument
1314 /// </summary>
1415 public static class ArgumentParser
1516 {
17+ static List < DocNode > documentation ;
18+
1619 /// <summary>
1720 /// Parses the specified arguments.
1821 /// </summary>
1922 /// <param name="args">Arguments.</param>
2023 /// <typeparam name="T">The class that contains the options.</typeparam>
2124 public static T Parse < T > ( string [ ] args ) where T : class , new ( )
2225 {
26+ // Create the documentation cache for this class
27+ if ( documentation == null )
28+ documentation = new List < DocNode > ( ) ;
29+ else
30+ documentation . Clear ( ) ;
31+
2332 // Instantiate the class that contains the options
2433 T options = new T ( ) ;
2534
26- // Create a new List<string> and fill it with the arguments
35+ // Create a new List<string> from the supplied arguments
2736 var list = new List < string > ( args ) ;
2837
2938 // Get all public fields from the class instance
3039 var fields = typeof ( T ) . GetFields ( BindingFlags . Instance | BindingFlags . Public ) ;
3140
3241 // Iterate over all fields
33- foreach ( var item in fields )
42+ foreach ( var item in fields ) {
3443
3544 // Parse the current field
45+ ParseDoc < T > ( options , item . Name ) ;
3646 ParseField < T > ( options , list , item . Name ) ;
3747
48+ }
49+
3850 // Return the generated class instance
3951 return options ;
4052 }
4153
4254 /// <summary>
4355 /// Generates and prints the argument doc.
4456 /// </summary>
45- /// <typeparam name="T">The 1st type parameter .</typeparam>
46- static void PrintHelp < T > ( ) where T : class , new ( )
57+ /// <typeparam name="T">The class that contains the options .</typeparam>
58+ public static void Help ( )
4759 {
48- // Not ready yet.
60+ documentation . Sort ( ( n1 , n2 ) => {
61+ if ( ! string . IsNullOrEmpty ( n1 . ShortName ) && ! string . IsNullOrEmpty ( n2 . ShortName ) )
62+ return n1 . ShortName . CompareTo ( n2 . ShortName ) ;
63+ if ( string . IsNullOrEmpty ( n1 . FullName ) && string . IsNullOrEmpty ( n2 . ShortName ) )
64+ return n1 . ShortName . CompareTo ( n2 . FullName ) ;
65+ if ( ! string . IsNullOrEmpty ( n1 . FullName ) && ! string . IsNullOrEmpty ( n2 . FullName ) )
66+ return n1 . FullName . CompareTo ( n2 . FullName ) ;
67+ if ( string . IsNullOrEmpty ( n1 . ShortName ) && string . IsNullOrEmpty ( n2 . FullName ) )
68+ return n1 . FullName . CompareTo ( n2 . ShortName ) ;
69+ return n1 . FieldName . CompareTo ( n2 . FieldName ) ;
70+ } ) ;
71+ var accum = new StringBuilder ( ) ;
72+ foreach ( var node in documentation ) {
73+ if ( ! string . IsNullOrEmpty ( node . ShortName ) )
74+ accum . AppendFormat ( "{0}" , node . ShortName . PadRight ( Console . WindowWidth / 10 ) + "| " ) ;
75+ if ( ! string . IsNullOrEmpty ( node . ShortName ) && ! string . IsNullOrEmpty ( node . FullName ) )
76+ accum . AppendFormat ( "\n {0}" , node . FullName . PadRight ( Console . WindowWidth / 10 ) + "| " ) ;
77+ else if ( string . IsNullOrEmpty ( node . ShortName ) && ! string . IsNullOrEmpty ( node . FullName ) )
78+ accum . Append ( node . FullName . PadRight ( Console . WindowWidth / 10 ) + "| " ) ;
79+ else if ( string . IsNullOrEmpty ( node . ShortName ) && string . IsNullOrEmpty ( node . FullName ) )
80+ accum . Append ( node . FieldName . PadRight ( Console . WindowWidth / 10 ) + "| " ) ;
81+ if ( ! string . IsNullOrEmpty ( node . Description ) )
82+ accum . AppendLine ( node . Description ) ;
83+ else
84+ accum . AppendLine ( "<No Description>" ) ;
85+ }
86+ Console . WriteLine ( accum ) ;
4987 }
5088
5189 /// <summary>
5290 /// Parses the field.
5391 /// </summary>
5492 /// <param name="options">Options.</param>
5593 /// <param name="args">Arguments.</param>
56- /// <param name="name ">Name.</param>
94+ /// <param name="fieldname ">Name.</param>
5795 /// <typeparam name="T">The 1st type parameter.</typeparam>
58- static void ParseField < T > ( T options , List < string > args , string name ) where T : class , new ( )
96+ static void ParseField < T > ( T options , List < string > args , string fieldname ) where T : class , new ( )
5997 {
6098 // Get field
61- var field = typeof ( T ) . GetField ( name ) ;
99+ var field = typeof ( T ) . GetField ( fieldname ) ;
62100
63101 // Get attributes
64102 var attributes = field . GetCustomAttributes ( true ) ;
65103
66104 // Iterate over the attributes
67105 foreach ( var attrib in attributes ) {
68106
69- // Check if the current attribute is a Switch attribute
107+ // Check if the current attribute is of type Switch
70108 var @switch = attrib as Switch ;
71109 if ( @switch != null ) {
72110
@@ -135,6 +173,53 @@ public static class ArgumentParser
135173 return ;
136174 }
137175 }
176+
177+ static void ParseDoc < T > ( T options , string fieldname ) where T : class , new ( )
178+ {
179+ // Get field
180+ var field = typeof ( T ) . GetField ( fieldname ) ;
181+
182+ // Get or create a documentation node for this field
183+ var node = documentation . Exists ( _node => _node . FieldName == fieldname )
184+ ? documentation . First ( _node => _node . FieldName == fieldname )
185+ : new DocNode ( fieldname ) ;
186+
187+ // Get attributes
188+ var attributes = field . GetCustomAttributes ( true ) ;
189+
190+ // Iterate over all attributes
191+ foreach ( var attrib in attributes ) {
192+
193+ // Check if the current attribute is of type Argument or Switch
194+ var xarg = attrib as Argument ;
195+ var xswitch = attrib as Switch ;
196+ if ( xswitch != null ) {
197+ if ( xswitch . infername )
198+ xswitch = xswitch . InferName ( field . Name ) ;
199+ node . ShortName = xswitch . FriendlyShort ;
200+ node . FullName = xswitch . FriendlyFull ;
201+ } else if ( xarg != null ) {
202+ if ( xarg . infername )
203+ xarg = xarg . InferName ( field . Name ) ;
204+ node . ShortName = xarg . FriendlyShort ;
205+ node . FullName = xarg . FriendlyFull ;
206+ }
207+
208+ // Check if the current attribute is of type Docs
209+ var doc = attrib as Docs ;
210+
211+ // If not, skip this attribute
212+ if ( doc == null )
213+ continue ;
214+
215+ // Return the documentation for this field
216+ node . Description = doc . description ;
217+ }
218+
219+ if ( documentation . Exists ( _node => _node . FieldName == fieldname ) ) {
220+ documentation . Remove ( documentation . First ( _node => _node . FieldName == fieldname ) ) ;
221+ }
222+ documentation . Add ( node ) ;
223+ }
138224 }
139225}
140-
0 commit comments