dotnet / command-line-api

Command line parsing, invocation, and rendering of terminal output.
https://github.com/dotnet/command-line-api/wiki
MIT License
3.38k stars 380 forks source link

Will HelpBuilder.Default.GetLayout() return the same delegates as OptionsSection() etc.? #1888

Open KalleOlaviNiemitalo opened 1 year ago

KalleOlaviNiemitalo commented 1 year ago

I want to add a custom help section after OptionsSection. As of System.CommandLine 2.0.0-beta4.22272.1, HelpBuilder.Default.GetLayout() returns the sections in this order:

https://github.com/dotnet/command-line-api/blob/209b724a3c843253d3071e8348c353b297b0b8b5/src/System.CommandLine/Help/HelpBuilder.Default.cs#L141-L152

The documentation "Add or replace help sections" suggests using Enumerable.Skip, i.e. trusting that the positions of the sections never change, but that seems risky to me. If a future version of System.CommandLine adds a new section between SynopsisSection and CommandUsageSection, and I keep adding my section between the fourth and fifth default section, then my section will go above OptionsSection even though I want it to go below.

So, I'm considering this kind of code instead:

        private static IEnumerable<HelpSectionDelegate> GetLayout(HelpContext helpContext)
        {
            var layout = new List<HelpSectionDelegate>(HelpBuilder.Default.GetLayout());

            int index = layout.IndexOf(HelpBuilder.Default.OptionsSection());
            layout.Insert(index + 1, ShowOptionDetails);

            return layout;
        }

i.e. locate the OptionsSection in the list and then insert after that. However, does the System.CommandLine API promise that this kind of search will find the delegate in the list? I mean, the list might contain a different delegate instance that does not compare equal to the delegate that HelpBuilder.Default.OptionsSection() returns, even though both delegates do the same thing. The OptionsSection() method returns a delegate constructed from an anonymous function:

https://github.com/dotnet/command-line-api/blob/209b724a3c843253d3071e8348c353b297b0b8b5/src/System.CommandLine/Help/HelpBuilder.Default.cs#L199-L201

and ECMA-334:2022 §11.11.9 (Delegate equality operators) seems to say that invocation list entries constructed that way are not necessarily equal. So the questions are:

jonsequitur commented 1 year ago

The order of these sections is very standard as a broad CLI convention so I wouldn't expect a change, but I agree the API should provide clearer support for a deterministic way of modifying the defaults.