11// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
22
3+ using CommandLine . Core ;
4+ using CommandLine . Infrastructure ;
5+
6+ using CSharpx ;
7+
38using System ;
49using System . Collections ;
510using System . Collections . Generic ;
611using System . IO ;
7- using System . Text ;
812using System . Linq ;
913using System . Reflection ;
10- using CommandLine . Infrastructure ;
11- using CommandLine . Core ;
12- using CSharpx ;
14+ using System . Text ;
1315
1416namespace CommandLine . Text
1517{
1618 /// <summary>
1719 /// Provides means to format an help screen.
1820 /// You can assign it in place of a <see cref="System.String"/> instance.
1921 /// </summary>
20-
21-
22-
22+
23+
24+
2325 public struct ComparableOption
2426 {
2527 public bool Required ;
@@ -29,7 +31,7 @@ public struct ComparableOption
2931 public string ShortName ;
3032 public int Index ;
3133 }
32-
34+
3335 public class HelpText
3436 {
3537
@@ -55,40 +57,40 @@ ComparableOption ToComparableOption(Specification spec, int index)
5557
5658 public Comparison < ComparableOption > OptionComparison { get ; set ; } = null ;
5759
58- public static Comparison < ComparableOption > RequiredThenAlphaComparison = ( ComparableOption attr1 , ComparableOption attr2 ) =>
59- {
60- if ( attr1 . IsOption && attr2 . IsOption )
61- {
62- if ( attr1 . Required && ! attr2 . Required )
63- {
64- return - 1 ;
65- }
66- else if ( ! attr1 . Required && attr2 . Required )
67- {
68- return 1 ;
69- }
70-
71- return String . Compare ( attr1 . LongName , attr2 . LongName , StringComparison . Ordinal ) ;
72-
73- }
74- else if ( attr1 . IsOption && attr2 . IsValue )
75- {
76- return - 1 ;
77- }
78- else
79- {
80- return 1 ;
81- }
82- } ;
83-
60+ public static Comparison < ComparableOption > RequiredThenAlphaComparison = ( ComparableOption attr1 , ComparableOption attr2 ) =>
61+ {
62+ if ( attr1 . IsOption && attr2 . IsOption )
63+ {
64+ if ( attr1 . Required && ! attr2 . Required )
65+ {
66+ return - 1 ;
67+ }
68+ else if ( ! attr1 . Required && attr2 . Required )
69+ {
70+ return 1 ;
71+ }
72+
73+ return String . Compare ( attr1 . LongName , attr2 . LongName , StringComparison . Ordinal ) ;
74+
75+ }
76+ else if ( attr1 . IsOption && attr2 . IsValue )
77+ {
78+ return - 1 ;
79+ }
80+ else
81+ {
82+ return 1 ;
83+ }
84+ } ;
85+
8486 #endregion
85-
87+
8688 private const int BuilderCapacity = 128 ;
8789 private const int DefaultMaximumLength = 80 ; // default console width
8890 /// <summary>
8991 /// The number of spaces between an option and its associated help text
9092 /// </summary>
91- private const int OptionToHelpTextSeparatorWidth = 4 ;
93+ private const int OptionToHelpTextSeparatorWidth = 4 ;
9294 /// <summary>
9395 /// The width of the option prefix (either "--" or " "
9496 /// </summary>
@@ -334,7 +336,7 @@ public static HelpText AutoBuild<T>(
334336
335337 var errors = Enumerable . Empty < Error > ( ) ;
336338
337-
339+
338340 if ( onError != null && parserResult . Tag == ParserResultType . NotParsed )
339341 {
340342 errors = ( ( NotParsed < T > ) parserResult ) . Errors ;
@@ -392,7 +394,7 @@ public static HelpText AutoBuild<T>(ParserResult<T> parserResult, int maxDisplay
392394 var errors = ( ( NotParsed < T > ) parserResult ) . Errors ;
393395
394396 if ( errors . Any ( e => e . Tag == ErrorType . VersionRequestedError ) )
395- return new HelpText ( $ "{ HeadingInfo . Default } { Environment . NewLine } ") { MaximumDisplayWidth = maxDisplayWidth } . AddPreOptionsLine ( Environment . NewLine ) ;
397+ return new HelpText ( $ "{ HeadingInfo . Default } { Environment . NewLine } ") { MaximumDisplayWidth = maxDisplayWidth } . AddPreOptionsLine ( Environment . NewLine ) ;
396398
397399 if ( ! errors . Any ( e => e . Tag == ErrorType . HelpVerbRequestedError ) )
398400 return AutoBuild ( parserResult , current => DefaultParsingErrorsHandler ( parserResult , current ) , e => e , maxDisplayWidth : maxDisplayWidth ) ;
@@ -520,6 +522,7 @@ public HelpText AddOptions<T>(ParserResult<T> result)
520522 return AddOptionsImpl (
521523 GetSpecificationsFromType ( result . TypeInfo . Current ) ,
522524 SentenceBuilder . RequiredWord ( ) ,
525+ SentenceBuilder . OptionGroupWord ( ) ,
523526 MaximumDisplayWidth ) ;
524527 }
525528
@@ -537,6 +540,7 @@ public HelpText AddVerbs(params Type[] types)
537540 return AddOptionsImpl (
538541 AdaptVerbsToSpecifications ( types ) ,
539542 SentenceBuilder . RequiredWord ( ) ,
543+ SentenceBuilder . OptionGroupWord ( ) ,
540544 MaximumDisplayWidth ) ;
541545 }
542546
@@ -553,6 +557,7 @@ public HelpText AddOptions<T>(int maximumLength, ParserResult<T> result)
553557 return AddOptionsImpl (
554558 GetSpecificationsFromType ( result . TypeInfo . Current ) ,
555559 SentenceBuilder . RequiredWord ( ) ,
560+ SentenceBuilder . OptionGroupWord ( ) ,
556561 maximumLength ) ;
557562 }
558563
@@ -571,6 +576,7 @@ public HelpText AddVerbs(int maximumLength, params Type[] types)
571576 return AddOptionsImpl (
572577 AdaptVerbsToSpecifications ( types ) ,
573578 SentenceBuilder . RequiredWord ( ) ,
579+ SentenceBuilder . OptionGroupWord ( ) ,
574580 maximumLength ) ;
575581 }
576582
@@ -614,7 +620,7 @@ public static IEnumerable<string> RenderParsingErrorsTextAsLines<T>(
614620 if ( meaningfulErrors . Empty ( ) )
615621 yield break ;
616622
617- foreach ( var error in meaningfulErrors
623+ foreach ( var error in meaningfulErrors
618624 . Where ( e => e . Tag != ErrorType . MutuallyExclusiveSetError ) )
619625 {
620626 var line = new StringBuilder ( indent . Spaces ( ) )
@@ -751,9 +757,9 @@ private IEnumerable<Specification> GetSpecificationsFromType(Type type)
751757 var optionSpecs = specs
752758 . OfType < OptionSpecification > ( ) ;
753759 if ( autoHelp )
754- optionSpecs = optionSpecs . Concat ( new [ ] { MakeHelpEntry ( ) } ) ;
760+ optionSpecs = optionSpecs . Concat ( new [ ] { MakeHelpEntry ( ) } ) ;
755761 if ( autoVersion )
756- optionSpecs = optionSpecs . Concat ( new [ ] { MakeVersionEntry ( ) } ) ;
762+ optionSpecs = optionSpecs . Concat ( new [ ] { MakeVersionEntry ( ) } ) ;
757763 var valueSpecs = specs
758764 . OfType < ValueSpecification > ( )
759765 . OrderBy ( v => v . Index ) ;
@@ -780,29 +786,30 @@ private static Maybe<Tuple<UsageAttribute, IEnumerable<Example>>> GetUsageFromTy
780786 private IEnumerable < Specification > AdaptVerbsToSpecifications ( IEnumerable < Type > types )
781787 {
782788 var optionSpecs = from verbTuple in Verb . SelectFromTypes ( types )
783- select
784- OptionSpecification . NewSwitch (
785- string . Empty ,
786- verbTuple . Item1 . Name ,
787- false ,
788- verbTuple . Item1 . HelpText ,
789- string . Empty ,
790- verbTuple . Item1 . Hidden ) ;
789+ select
790+ OptionSpecification . NewSwitch (
791+ string . Empty ,
792+ verbTuple . Item1 . Name ,
793+ false ,
794+ verbTuple . Item1 . HelpText ,
795+ string . Empty ,
796+ verbTuple . Item1 . Hidden ) ;
791797 if ( autoHelp )
792- optionSpecs = optionSpecs . Concat ( new [ ] { MakeHelpEntry ( ) } ) ;
798+ optionSpecs = optionSpecs . Concat ( new [ ] { MakeHelpEntry ( ) } ) ;
793799 if ( autoVersion )
794- optionSpecs = optionSpecs . Concat ( new [ ] { MakeVersionEntry ( ) } ) ;
800+ optionSpecs = optionSpecs . Concat ( new [ ] { MakeVersionEntry ( ) } ) ;
795801 return optionSpecs ;
796802 }
797803
798804 private HelpText AddOptionsImpl (
799805 IEnumerable < Specification > specifications ,
800806 string requiredWord ,
807+ string optionGroupWord ,
801808 int maximumLength )
802809 {
803810 var maxLength = GetMaxLength ( specifications ) ;
804-
805-
811+
812+
806813
807814 optionsHelp = new StringBuilder ( BuilderCapacity ) ;
808815
@@ -822,14 +829,14 @@ private HelpText AddOptionsImpl(
822829 foreach ( var comparable in comparables )
823830 {
824831 Specification spec = specifications . ElementAt ( comparable . Index ) ;
825- AddOption ( requiredWord , maxLength , spec , remainingSpace ) ;
832+ AddOption ( requiredWord , optionGroupWord , maxLength , spec , remainingSpace ) ;
826833 }
827834 }
828835 else
829836 {
830837 specifications . ForEach (
831838 option =>
832- AddOption ( requiredWord , maxLength , option , remainingSpace ) ) ;
839+ AddOption ( requiredWord , optionGroupWord , maxLength , option , remainingSpace ) ) ;
833840
834841 }
835842
@@ -865,7 +872,7 @@ private HelpText AddPreOptionsLine(string value, int maximumLength)
865872 return this ;
866873 }
867874
868- private HelpText AddOption ( string requiredWord , int maxLength , Specification specification , int widthOfHelpText )
875+ private HelpText AddOption ( string requiredWord , string optionGroupWord , int maxLength , Specification specification , int widthOfHelpText )
869876 {
870877 if ( specification . Hidden )
871878 return this ;
@@ -891,11 +898,16 @@ private HelpText AddOption(string requiredWord, int maxLength, Specification spe
891898
892899 if ( specification . Required )
893900 optionHelpText = "{0} " . FormatInvariant ( requiredWord ) + optionHelpText ;
894-
901+
902+ if ( specification . Tag == SpecificationType . Option && specification is OptionSpecification optionSpecification && optionSpecification . Group . IsJust ( ) )
903+ {
904+ optionHelpText = "({0}: {1})" . FormatInvariant ( optionGroupWord , optionSpecification . Group . GetValueOrDefault ( null ) ) + optionHelpText ;
905+ }
906+
895907 //note that we need to indent trim the start of the string because it's going to be
896908 //appended to an existing line that is as long as the indent-level
897- var indented = TextWrapper . WrapAndIndentText ( optionHelpText , maxLength + TotalOptionPadding , widthOfHelpText ) . TrimStart ( ) ;
898-
909+ var indented = TextWrapper . WrapAndIndentText ( optionHelpText , maxLength + TotalOptionPadding , widthOfHelpText ) . TrimStart ( ) ;
910+
899911 optionsHelp
900912 . Append ( indented )
901913 . Append ( Environment . NewLine )
@@ -989,7 +1001,7 @@ private int GetMaxOptionLength(OptionSpecification spec)
9891001 }
9901002
9911003 if ( hasShort && hasLong )
992- specLength += OptionPrefixWidth ;
1004+ specLength += OptionPrefixWidth ;
9931005
9941006 return specLength ;
9951007 }
@@ -1037,7 +1049,7 @@ private static string FormatDefaultValue<T>(T value)
10371049 : string . Empty ;
10381050 }
10391051
1040-
1052+
10411053
10421054 }
10431055}
0 commit comments