Skip to content

Enhance HelpText customization using a new overload AutoBuild method. #557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 31, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/CommandLine/Text/CopyrightInfo.cs
Original file line number Diff line number Diff line change
@@ -27,11 +27,11 @@ public class CopyrightInfo
/// <summary>
/// An empty object used for initialization.
/// </summary>
public static CopyrightInfo Empty
public static CopyrightInfo Empty
{
get
{
return new CopyrightInfo("author", 1);
return new CopyrightInfo("author", DateTime.Now.Year);
}
}

@@ -115,12 +115,13 @@ public static CopyrightInfo Default
case MaybeType.Just:
return new CopyrightInfo(copyrightAttr.FromJustOrFail());
default:
// if no copyright attribute exist but a company attribute does, use it as copyright holder
return new CopyrightInfo(
ReflectionHelper.GetAttribute<AssemblyCompanyAttribute>().FromJustOrFail(
new InvalidOperationException("CopyrightInfo::Default requires that you define AssemblyCopyrightAttribute or AssemblyCompanyAttribute.")
).Company,
DateTime.Now.Year);
var companyAttr = ReflectionHelper.GetAttribute<AssemblyCompanyAttribute>();
return companyAttr.IsNothing()
//if both copyrightAttr and companyAttr aren't available in Assembly,don't fire Exception
? Empty
// if no copyright attribute exist but a company attribute does, use it as copyright holder
: new CopyrightInfo(companyAttr.FromJust().Company, DateTime.Now.Year);

}
}
}
@@ -192,4 +193,4 @@ protected virtual string FormatYears(int[] years)
return yearsPart.ToString();
}
}
}
}
54 changes: 41 additions & 13 deletions src/CommandLine/Text/HelpText.cs
Original file line number Diff line number Diff line change
@@ -266,7 +266,7 @@ public bool AdditionalNewLineAfterOption
/// </summary>
public bool AddNewLineBetweenHelpSections
{
get { return addNewLineBetweenHelpSections; }
get { return addNewLineBetweenHelpSections; }
set { addNewLineBetweenHelpSections = value; }
}

@@ -389,7 +389,7 @@ public static HelpText AutoBuild<T>(
}

/// <summary>
/// Creates a new instance of the <see cref="CommandLine.Text.HelpText"/> class,
/// Creates a default instance of the <see cref="CommandLine.Text.HelpText"/> class,
/// automatically handling verbs or options scenario.
/// </summary>
/// <param name='parserResult'>The <see cref="CommandLine.ParserResult{T}"/> containing the instance that collected command line arguments parsed with <see cref="CommandLine.Parser"/> class.</param>
@@ -400,6 +400,23 @@ public static HelpText AutoBuild<T>(
/// <remarks>This feature is meant to be invoked automatically by the parser, setting the HelpWriter property
/// of <see cref="CommandLine.ParserSettings"/>.</remarks>
public static HelpText AutoBuild<T>(ParserResult<T> parserResult, int maxDisplayWidth = DefaultMaximumLength)
{
return AutoBuild<T>(parserResult, h => h, maxDisplayWidth);
}

/// <summary>
/// Creates a custom instance of the <see cref="CommandLine.Text.HelpText"/> class,
/// automatically handling verbs or options scenario.
/// </summary>
/// <param name='parserResult'>The <see cref="CommandLine.ParserResult{T}"/> containing the instance that collected command line arguments parsed with <see cref="CommandLine.Parser"/> class.</param>
/// <param name='onError'>A delegate used to customize the text block of reporting parsing errors text block.</param>
/// <param name="maxDisplayWidth">The maximum width of the display.</param>
/// <returns>
/// An instance of <see cref="CommandLine.Text.HelpText"/> class.
/// </returns>
/// <remarks>This feature is meant to be invoked automatically by the parser, setting the HelpWriter property
/// of <see cref="CommandLine.ParserSettings"/>.</remarks>
public static HelpText AutoBuild<T>(ParserResult<T> parserResult, Func<HelpText, HelpText> onError, int maxDisplayWidth = DefaultMaximumLength)
{
if (parserResult.Tag != ParserResultType.NotParsed)
throw new ArgumentException("Excepting NotParsed<T> type.", "parserResult");
@@ -410,13 +427,25 @@ public static HelpText AutoBuild<T>(ParserResult<T> parserResult, int maxDisplay
return new HelpText($"{HeadingInfo.Default}{Environment.NewLine}") { MaximumDisplayWidth = maxDisplayWidth }.AddPreOptionsLine(Environment.NewLine);

if (!errors.Any(e => e.Tag == ErrorType.HelpVerbRequestedError))
return AutoBuild(parserResult, current => DefaultParsingErrorsHandler(parserResult, current), e => e, maxDisplayWidth: maxDisplayWidth);
return AutoBuild(parserResult, current =>
{
onError?.Invoke(current);
return DefaultParsingErrorsHandler(parserResult, current);
}, e => e, maxDisplayWidth: maxDisplayWidth);

var err = errors.OfType<HelpVerbRequestedError>().Single();
var pr = new NotParsed<object>(TypeInfo.Create(err.Type), Enumerable.Empty<Error>());
var pr = new NotParsed<object>(TypeInfo.Create(err.Type), new Error[] { err });
return err.Matched
? AutoBuild(pr, current => DefaultParsingErrorsHandler(pr, current), e => e, maxDisplayWidth: maxDisplayWidth)
: AutoBuild(parserResult, current => DefaultParsingErrorsHandler(parserResult, current), e => e, true, maxDisplayWidth);
? AutoBuild(pr, current =>
{
onError?.Invoke(current);
return DefaultParsingErrorsHandler(pr, current);
}, e => e, maxDisplayWidth: maxDisplayWidth)
: AutoBuild(parserResult, current =>
{
onError?.Invoke(current);
return DefaultParsingErrorsHandler(parserResult, current);
}, e => e, true, maxDisplayWidth);
}

/// <summary>
@@ -431,7 +460,6 @@ public static HelpText DefaultParsingErrorsHandler<T>(ParserResult<T> parserResu

if (((NotParsed<T>)parserResult).Errors.OnlyMeaningfulOnes().Empty())
return current;

var errors = RenderParsingErrorsTextAsLines(parserResult,
current.SentenceBuilder.FormatError,
current.SentenceBuilder.FormatMutuallyExclusiveSetErrors,
@@ -732,8 +760,8 @@ public override string ToString()
var result = new StringBuilder(sbLength);

result.Append(heading)
.AppendWhen(!string.IsNullOrEmpty(copyright),
Environment.NewLine,
.AppendWhen(!string.IsNullOrEmpty(copyright),
Environment.NewLine,
copyright)
.AppendWhen(preOptionsHelp.SafeLength() > 0,
NewLineIfNeededBefore(preOptionsHelp),
@@ -743,15 +771,15 @@ public override string ToString()
Environment.NewLine,
Environment.NewLine,
optionsHelp.SafeToString())
.AppendWhen(postOptionsHelp.SafeLength() > 0,
.AppendWhen(postOptionsHelp.SafeLength() > 0,
NewLineIfNeededBefore(postOptionsHelp),
Environment.NewLine,
postOptionsHelp.ToString());

string NewLineIfNeededBefore(StringBuilder sb)
{
if (AddNewLineBetweenHelpSections
&& result.Length > 0
if (AddNewLineBetweenHelpSections
&& result.Length > 0
&& !result.SafeEndsWith(Environment.NewLine)
&& !sb.SafeStartsWith(Environment.NewLine))
return Environment.NewLine;
@@ -952,7 +980,7 @@ specification is OptionSpecification optionSpecification &&

if (optionGroupSpecification != null)
{
optionHelpText = "({0}: {1}) ".FormatInvariant(optionGroupWord, optionGroupSpecification.Group) + optionHelpText;
optionHelpText = "({0}: {1}) ".FormatInvariant(optionGroupWord, optionGroupSpecification.Group) + optionHelpText;
}

//note that we need to indent trim the start of the string because it's going to be
Loading