Improve Help customization
Current version: 2.0.0-beta4.23307.1 of S.CL
Description
I wanted to customize my help
- I wanted options/aliases sorted by length, so it always shows
-s, --sl, --something-long - I want my options to be sorted (I can do this with
CustomizeSymbol - Add additional help text based on validators (I haven't found a good solution for this).
- I have validators that check for mutually exclusive options and wanted to call out the options in the help
- I have options that can mutate their required state, e.g., if you have option A and B, then C becomes required.
For sorting the options, all I really needed was a way to change the OptionSeciton https://github.com/dotnet/command-line-api/blob/f6ff2f1a94a58617e744f8fe0d469a2a420a6259/src/System.CommandLine/Help/HelpBuilder.Default.cs#L240
to
ctx.HelpBuilder.WriteColumns(optionRows.OrderBy(o=>o.FirstColumnText).ToList(), ctx);
To do this I had to
- copy the
OptionSectioncode, - Workaround the accessibility of
ParentNode(it's internal) and I'm not sure how safe my workaround is.
CliCommand parentCommand = null;
var parent = current.Parents.FirstOrDefault();
- Implement my own version of
WriteHeading(it's marked as private)
Are there any plans on improving S.CL help customization or expose more extension points?
We do plan to overhaul the help customization API but it's an open issue as to what that will look like. Broadly speaking, we currently support:
- Replacing the entire help implementation.
- Replacing / reordering / adding whole horizontal sections.
- Customizing certain text within a given section (e.g.
CliArgument.HelpName)
Making the last one more granular or exposing more of the APIs that it uses internally would likely have made your goal easier while also adding even more API surface to an API that's already quite complicated. We're not sure what the right balance is there. I've been of the opinion that a templating language (e.g. https://spectreconsole.net/markup) is ultimately simpler and more flexible, but it's not currently in scope for System.CommandLine.