In a cake build script there is a very neat way of documenting the tasks using the .Description()
extension on the Task. These descriptions are displayed when calling the build script with the -showdescription
argument.
I have several custom arguments in my build script that I'd like to document somehow. Currently I added a task that outputs a description text similar to the manual page style for the available arguments that looks something like this:
var nextLineDescription = "\n\t\t\t\t\t"; // for formatting
Console.WriteLine("ARGUMENTS");
Console.WriteLine("");
Console.WriteLine("\t--someparameter=<number>\t\t" +
"Description of the parameter" + nextLineDescription +
"that can span multiple lines" + nextLineDescription +
"and defaults to 5.\n");
This works fine but is a lot of work, especially if the text should be properly formatted so it's readable in the command line.
So when I call ./build.ps1 -Target MyDocTask
I get a nice result:
ARGUMENTS --someparameter=number Description of the parameter that can span multiple lines and defaults to 5 --nextParameter Next description ...
Is there another way or a best practice to add documentation for arguments so it can be displayed in the command line similar to the tasks descriptions?
Edit: Alternatively, can I find all available parameters in my build script to loop over them and generate such a description instead of writing it manually for each parameter?
There's currently no built-in feature for "registering" arguments for help, would be an great addition though so please raise an issue about that.
That said it can be achieved, as Cake is just .NET you could utilize one of the command line parsers available on NuGet to achieve this. One such parser is CommandLineParser.
Assemblies can be references from NuGet using the #addin
directive, for CommandLineParser it looks below
#addin "nuget:?package=CommandLineParser&version=2.1.1-beta&prerelease=true"
As it's not an "native" Cake addin you'll need to use fully qualified type names or just like regular C# add a using statement like this
using CommandLine;
CommandLineParser uses a class and attributes on the properties to provide rules and help. Porting your example below would look something like below
class Options
{
[Option("someparameter",
HelpText = "Description of the parameter, that can span multiple lines",
Default = 5)]
public int SomeParameter { get; set; }
[Option("nextParameter", HelpText = "Next description")]
public string NextParameter { get; set; }
[Option("target", HelpText = "Target", Default = "Default")]
public string Target { get; set; }
}
Normally CommandLineParser will output help to the console, but if you want to display it in a task, you can capture the output with a TextWriter
var helpWriter = new StringWriter();
var parser = new Parser(config => config.HelpWriter = helpWriter);
Then parsing arguments and if "MyDocTask" is specified render help to the helpWriter
Options options = parser
.ParseArguments<Options>(
StringComparer.OrdinalIgnoreCase.Equals(Argument("target", "Default"), "MyDocTask")
? new []{ "--help" }
: System.Environment.GetCommandLineArgs()
)
.MapResult(
o => o,
errors=> new Options { Target = "MyDocTask"} // TODO capture errors here
);
and tasks
Task("MyDocTask")
.Does(() => {
Information(helpWriter.ToString());
}
);
Task("Default")
.Does(() => {
Information("SomeParameter: {0}", options.SomeParameter);
Information("NextParameter: {0}", options.NextParameter);
Information("Target: {0}", options.Target);
}
);
then executed
RunTarget(options.Target);
The MyDocTask
will output the help
>> cake .\commandline.cake --Target="MyDocTask"
========================================
MyDocTask
========================================
Cake 0.20.0+Branch.main.Sha.417d1eb9097a6c71ab25736687162c0f58bbb74a
Copyright (c) .NET Foundation and Contributors
--someparameter (Default: 5) Description of the parameter, that can span multiple lines
--nextParameter Next description
--target (Default: Default) Target
--help Display this help screen.
--version Display version information.
and Default
task will just output values of the parsed arguments
>> cake .\commandline.cake
========================================
Default
========================================
SomeParameter: 5
NextParameter: [NULL]
Target: Default
Task Duration
--------------------------------------------------
Default 00:00:00.0133265
--------------------------------------------------
Total: 00:00:00.0133265
This will give you strongly typed and documented arguments in a fairly easy way.
The complete Cake script below:
#addin "nuget:?package=CommandLineParser&version=2.1.1-beta&prerelease=true"
using CommandLine;
class Options
{
[Option("someparameter",
HelpText = "Description of the parameter, that can span multiple lines",
Default = 5)]
public int SomeParameter { get; set; }
[Option("nextParameter", HelpText = "Next description")]
public string NextParameter { get; set; }
[Option("target", HelpText = "Target", Default = "Default")]
public string Target { get; set; }
}
var helpWriter = new StringWriter();
var parser = new Parser(config => config.HelpWriter = helpWriter);
Options options = parser
.ParseArguments<Options>(
StringComparer.OrdinalIgnoreCase.Equals(Argument("target", "Default"), "MyDocTask")
? new []{ "--help" }
: System.Environment.GetCommandLineArgs()
)
.MapResult(
o => o,
errors=> new Options { Target = "MyDocTask"} // could capture errors here
);
Task("MyDocTask")
.Does(() => {
Information(helpWriter.ToString());
}
);
Task("Default")
.Does(() => {
Information("SomeParameter: {0}", options.SomeParameter);
Information("NextParameter: {0}", options.NextParameter);
Information("Target: {0}", options.Target);
}
);
RunTarget(options.Target);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With