1-  using  System . Diagnostics ; 
1+ using  System . Diagnostics ; 
22using  System . Reflection ; 
33using  RT . Internal ; 
44using  RT . PostBuild ; 
@@ -116,23 +116,19 @@ namespace RT.CommandLine;
116116///                 the values in the enum type must also have documentation or <see cref="UndocumentedAttribute"/>, except 
117117///                 for the enum value that corresponds to the field’s default value if the field is not mandatory.</para> 
118118///             <para> 
119- ///                 Documentation is  provided in one of the following ways:</para> 
119+ ///                 Documentation can be  provided in one of the following ways:</para> 
120120///             <list type="bullet"> 
121121///                 <item><description> 
122- ///                     Monolingual, translation-agnostic (unlocalisable) applications use the <see 
123- ///                     cref="DocumentationAttribute"/> to specify documentation directly.</description></item> 
122+ ///                     Use <see cref="DocumentationAttribute"/> to specify unformatted text directly.</description></item> 
124123///                 <item><description> 
125- ///                     <para> 
126- ///                         Translatable applications must declare methods with the following signature:</para> 
127- ///                     <code> 
128- ///                         static string FieldNameDoc(Translation)</code> 
129- ///                     <para> 
130- ///                         The first parameter must be of the same type as the object passed in for the <c>applicationTr</c> 
131- ///                         parameter of <see cref="Parse"/>. The name of the method is the name of the field or enum value 
132- ///                         followed by <c>Doc</c>. The return value is the translated string.</para></description></item></list></description></item> 
124+ ///                     Use <see cref="DocumentationEggsMLAttribute"/> or <see cref="DocumentationRhoMLAttribute"/> to format 
125+ ///                     your text with coloration using one of the two markup systems.</description></item></list></description></item> 
133126///         <item><description> 
134127///             <see cref="IsPositionalAttribute"/> and <see cref="IsMandatoryAttribute"/> can be used together. However, a 
135- ///             positional field can only be made mandatory if all the positional fields preceding it are also mandatory.</description></item></list></remarks> 
128+ ///             positional field can only be made mandatory if all the positional fields preceding it are also mandatory.</description></item></list> 
129+ ///     <para> 
130+ ///         <see cref="SectionAttribute"/> can be used to split the help screen into sections with headers for better 
131+ ///         readability.</para></remarks> 
136132public  static class  CommandLineParser 
137133{ 
138134    /// <summary> 
@@ -589,21 +585,6 @@ private static Func<int, ConsoleColoredString> getHelpGenerator(Type type, Func<
589585            } 
590586            helpString . Add ( ConsoleColoredString . NewLine ) ; 
591587
592-             // 
593-             //  ##  CONSTRUCT THE TABLES 
594-             // 
595- 
596-             var  anyCommandsWithSuboptions  =  false ; 
597-             var  requiredParamsTable  =  new  TextTable  {  MaxWidth  =  wrapWidth  -  leftMargin ,  ColumnSpacing  =  3 ,  RowSpacing  =  1 ,  LeftMargin  =  leftMargin  } ; 
598-             int  requiredRow  =  0 ; 
599-             foreach  ( var  f  in  mandatoryPositional . Select ( fld =>  new  {  Positional  =  true ,  Field  =  fld  } ) . Concat ( mandatoryOptions . Select ( fld =>  new  {  Positional  =  false ,  Field  =  fld  } ) ) ) 
600-                 anyCommandsWithSuboptions  |=  createParameterHelpRow ( ref  requiredRow ,  requiredParamsTable ,  f . Field ,  f . Positional ,  helpProcessor ) ; 
601- 
602-             var  optionalParamsTable  =  new  TextTable  {  MaxWidth  =  wrapWidth  -  leftMargin ,  ColumnSpacing  =  3 ,  RowSpacing  =  1 ,  LeftMargin  =  leftMargin  } ; 
603-             int  optionalRow  =  0 ; 
604-             foreach  ( var  f  in  optionalPositional . Select ( fld =>  new  {  Positional  =  true ,  Field  =  fld  } ) . Concat ( optionalOptions . Select ( fld =>  new  {  Positional  =  false ,  Field  =  fld  } ) ) ) 
605-                 anyCommandsWithSuboptions  |=  createParameterHelpRow ( ref  optionalRow ,  optionalParamsTable ,  f . Field ,  f . Positional ,  helpProcessor ) ; 
606- 
607588            // Word-wrap the documentation for the command (if any) 
608589            var  doc  =  getDocumentation ( type ,  helpProcessor ) ; 
609590            foreach  ( var  line  in  doc . WordWrap ( wrapWidth ) ) 
@@ -612,26 +593,40 @@ private static Func<int, ConsoleColoredString> getHelpGenerator(Type type, Func<
612593                helpString . Add ( ConsoleColoredString . NewLine ) ; 
613594            } 
614595
615-             // Table of required parameters 
616-             if  ( mandatoryOptions . Count  >  0  ||  mandatoryPositional . Count  >  0 ) 
596+ 
597+             // 
598+             //  ##  CONSTRUCT THE TABLES 
599+             // 
600+ 
601+             var  anyCommandsWithSuboptions  =  false ; 
602+             var  paramsTables  =  new  List < ( string  heading ,  TextTable  table ) > ( ) ; 
603+             TextTable  curTable  =  null ; 
604+             var  curRow  =  0 ; 
605+             var  lastMandatory  =  false ; 
606+             foreach  ( var  ( mandatory ,  positional ,  field )  in  mandatoryPositional . Select ( fld =>  ( mandatory :  true ,  positional :  true ,  field :  fld ) ) 
607+                 . Concat ( mandatoryOptions . Select ( fld =>  ( mandatory :  true ,  positional :  false ,  field :  fld ) ) ) 
608+                 . Concat ( optionalPositional . Select ( fld =>  ( mandatory :  false ,  positional :  true ,  field :  fld ) ) ) 
609+                 . Concat ( optionalOptions . Select ( fld =>  ( mandatory :  false ,  positional :  false ,  field :  fld ) ) ) ) 
617610            { 
618-                 helpString . Add ( ConsoleColoredString . NewLine ) ; 
619-                 helpString . Add ( new  ConsoleColoredString ( "Required parameters:" ,  CmdLineColor . HelpHeading ) ) ; 
620-                 helpString . Add ( ConsoleColoredString . NewLine ) ; 
621-                 helpString . Add ( ConsoleColoredString . NewLine ) ; 
622-                 requiredParamsTable . RemoveEmptyColumns ( ) ; 
623-                 helpString . Add ( requiredParamsTable . ToColoredString ( ) ) ; 
611+                 var  section  =  field . GetCustomAttribute < SectionAttribute > ( ) ; 
612+                 if  ( curTable  ==  null  ||  lastMandatory  !=  mandatory  ||  section  !=  null ) 
613+                 { 
614+                     curTable  =  new  TextTable  {  MaxWidth  =  wrapWidth  -  leftMargin ,  ColumnSpacing  =  3 ,  RowSpacing  =  1 ,  LeftMargin  =  leftMargin  } ; 
615+                     paramsTables . Add ( ( section ? . Heading  ??  $ "{ ( mandatory  ?  "Required"  :  "Optional" ) }  parameters:",  curTable ) ) ; 
616+                     curRow  =  0 ; 
617+                 } 
618+                 anyCommandsWithSuboptions  |=  createParameterHelpRow ( ref  curRow ,  curTable ,  field ,  positional ,  helpProcessor ) ; 
619+                 lastMandatory  =  mandatory ; 
624620            } 
625621
626-             // Table of optional parameters 
627-             if  ( optionalOptions . Count  >  0  ||  optionalPositional . Count  >  0 ) 
622+             foreach  ( var  ( heading ,  table )  in  paramsTables ) 
628623            { 
629624                helpString . Add ( ConsoleColoredString . NewLine ) ; 
630-                 helpString . Add ( new  ConsoleColoredString ( "Optional parameters:" ,  CmdLineColor . HelpHeading ) ) ; 
625+                 helpString . Add ( new  ConsoleColoredString ( heading ,  CmdLineColor . HelpHeading ) ) ; 
631626                helpString . Add ( ConsoleColoredString . NewLine ) ; 
632627                helpString . Add ( ConsoleColoredString . NewLine ) ; 
633-                 optionalParamsTable . RemoveEmptyColumns ( ) ; 
634-                 helpString . Add ( optionalParamsTable . ToColoredString ( ) ) ; 
628+                 table . RemoveEmptyColumns ( ) ; 
629+                 helpString . Add ( table . ToColoredString ( ) ) ; 
635630            } 
636631
637632            // “This command accepts further arguments on the command line.” 
0 commit comments