Skip to content

make CommandLineConfiguration mutable, remove CommandLineBuilder #2107

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 15 commits into from
Mar 28, 2023

Conversation

adamsitnik
Copy link
Member

@adamsitnik adamsitnik commented Mar 20, 2023

fixes #2101

fixes #1907
fixes #1920
fixes #1922
fixes #1924
fixes #1925
fixes #1926
fixes #2034
closes #2046 (the last element from the TODO list)
fixes #2057
fixes #2111
fixes #2117

it allows us for creating the host and everything else after parsing has finished
UseCommandHandler must specify the handler for instance of a Command, not per type as there can be multiple commands of the same type
# Conflicts:
#	src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt
#	src/System.CommandLine.Tests/Invocation/InvocationPipelineTests.cs
#	src/System.CommandLine/Builder/CommandLineBuilder.cs
#	src/System.CommandLine/Builder/CommandLineBuilderExtensions.cs
#	src/System.CommandLine/CommandLineConfiguration.cs
# Conflicts:
#	src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_Hosting_api_is_not_changed.approved.txt
#	src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt
#	src/System.CommandLine.Benchmarks/CommandLine/Perf_Parser_Directives_Suggest.cs
#	src/System.CommandLine.Benchmarks/CommandLine/Perf_Parser_TypoCorrection.cs
#	src/System.CommandLine.DragonFruit.Tests/ConfigureFromMethodTests.cs
#	src/System.CommandLine.DragonFruit/CommandLine.cs
#	src/System.CommandLine.Hosting.Tests/HostingHandlerTest.cs
#	src/System.CommandLine.Hosting/HostingAction.cs
#	src/System.CommandLine.Hosting/HostingExtensions.cs
#	src/System.CommandLine.Rendering.Tests/ViewRenderingTests.cs
#	src/System.CommandLine.Tests/Help/HelpBuilderTests.Customization.cs
#	src/System.CommandLine.Tests/Invocation/InvocationPipelineTests.cs
#	src/System.CommandLine.Tests/Invocation/TypoCorrectionTests.cs
#	src/System.CommandLine.Tests/ParseDirectiveTests.cs
#	src/System.CommandLine.Tests/SuggestDirectiveTests.cs
#	src/System.CommandLine.Tests/UseExceptionHandlerTests.cs
#	src/System.CommandLine.Tests/UseHelpTests.cs
#	src/System.CommandLine.Tests/VersionOptionTests.cs
#	src/System.CommandLine/Builder/CommandLineBuilder.cs
#	src/System.CommandLine/Builder/CommandLineBuilderExtensions.cs
#	src/System.CommandLine/CommandLineConfiguration.cs
#	src/System.CommandLine/Help/HelpOption.cs
#	src/System.CommandLine/Help/VersionOption.cs
#	src/System.CommandLine/Invocation/InvocationPipeline.cs
#	src/System.CommandLine/Invocation/TypoCorrection.cs
…sing the config instance for config.RootCommand.Parse(args, $config)
@@ -37,7 +38,35 @@ public ChildList(Command parent)
public void Add(T item)
{
item.AddParent(_parent);

if (_children.Count > 0 && _parent is RootCommand)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RootCommand ctor adds HelpOption and VersionOption by default now. Users might want to customize it like that:

RootCommand rootCommand = new()
{
    new VersionOption("-v", "-version"),
};

In order to avoid duplicates, this method checks if a help option or version option already exists. If it does, it overrides it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be less surprising to just ask people to remove the other instance, especially given that the HelpAction is also customizable and is probably the more common path to customizing help.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonsequitur you are right, I've removed this logic and updated the tests

tokens.Add(
directive.Name,
new Token(directive.Name, TokenType.Directive, directive, Token.ImplicitPosition));
tokens[directive.Name] = new Token(directive.Name, TokenType.Directive, directive, Token.ImplicitPosition);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some directives are enabled by default. To avoid issues when users are not aware of that and they also add them to the config, I've replaced Add (it throws on duplicates) with just an indexer (overrides if given key was already present)

RootCommand = rootCommand ?? throw new ArgumentNullException(nameof(rootCommand));
Directives = new()
{
new SuggestDirective()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not sure which directives should be enabled by default, it's an open question.

I have not enabled all of them, as it would cause a perf hit for the users.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though I understand not wanting to cause a perf hit. I have a slight preference towards have the user opt-out rather than needing to opt-in to enable them.

@adamsitnik adamsitnik marked this pull request as ready for review March 27, 2023 20:15
@adamsitnik adamsitnik requested review from jonsequitur and Keboo March 27, 2023 20:15
RootCommand commandWithDuplicates = new()
{
new VersionOption(),
new VersionOption(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be an error because of the symbol identifier collision?

I think the expectation with the builder is that it's idempotent, but I don't think I have the same expectation with Command.Add since we're enforcing name and alias uniqueness.

new VersionOption("-v", "-version"),
};
if (rootCommand.Options[i] is VersionOption)
rootCommand.Options[i] = new VersionOption("-v", "-version");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a general comment and doesn't need to block merging.

The API through beta4 treated the arguments to Option<T> such that new VersionOption("-v", "-version") would indicate -version is the description.

The beta5 API understands this as setting Name to -v and using -version as an alias. In general usage though, -version would be the name (being longer) and -v would be the alias.

Two observations:

  • I've found this to be a gotcha in upgrading my code.
  • This usage in tests, while perfectly valid, might mislead about the way in which the API is typically used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment