-
Notifications
You must be signed in to change notification settings - Fork 381
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
New Config proposal #2101
Comments
With the regards to public class CliConfiguration
{
/// <summary>
/// The standard output.
/// </summary>
public TextWriter Out { get; set; } = Console.Out;
/// <summary>
/// The standard error.
/// </summary>
public TextWriter Error { get; set; } = Console.Error;
} this would allow us to still test the apps without introducing new abstraction to BCL and remove the last property from |
Feedback from @KalleOlaviNiemitalo #2103 (comment) |
I guess this would need some additional check so that HelpOption with parse errors shows help and ignores the parse errors. Didn't review the implementation yet. |
Especially if the subcommand needs |
Yeah I don't like Command.Parse having side effects on Command.Options. It seems cleaner if a multithreaded server can set up the Command tree once and then use that for parsing command lines from different clients on different threads; but I didn't check whether Symbol or Command already has some mutable caches that would make that unsafe. |
Will the library provide something that combines var commandLine = CreateAppCommandLine();
return await commandLine.InvokeAsync(args); |
Agreed. While the symbol types are mutable because it makes the API easier to use, System.CommandLine itself should not mutate them indirectly. This is why the implicit parser used by |
I think |
Yes, the name is appropriate for something that holds configuration settings. Not for something that is invoked on. |
After trying the result of #2102, I don't like how the configuration builder injects HelpOption and VersionOption to Command.Options. Instead I would like one of:
In one of my applications, there is a subcommand for which I want --help to output an additional section. After #2102, I implement that by first calling Parse, then checking for HelpAction, and checking whether the ParseResult.CommandResult.Command is that specific command; if so, then I call CustomizeLayout on the HelpBuilder that I get from the HelpAction. But this mutates the HelpBuilder that is referenced by HelpAction that is referenced by HelpOption that is referenced by the Command, so the Command is not deeply immutable after initialisation. It would be a bit nicer if the mutation were in CommandLineConfiguration or HelpContext only. There is a similar consideration with the width of the help output, I suppose. |
Overriding global options' aliases on specific subcommands has always been supported, so this should work fine.
We've tried to make sure that end users get a good CLI experience by default, so I would worry this would lead to a proliferation of command line tools without help support. |
An alternative solution that we have just discussed offline with @jonsequitur is extending |
I took one more look at it, here are my thoughts: Feels natural for public List<Directive> Directives { get; } Is related to parsing, in theory could be customized per public bool EnablePosixBundling { get; set; } = true;
public bool EnableParseErrorReporting { get; set; } = true;
public bool EnableTypoCorrections { get; set; } = false;
public TryReplaceToken? ResponseFileTokenReplacer { get; set; } = StringExtensions.TryReadResponseFile; Is related to execution and is required to be configurable for scenarios where public bool EnableDefaultExceptionHandler { get; set; } = true;
public TimeSpan? ProcessTerminationTimeout { get; set; } = TimeSpan.FromSeconds(2);
public TextWriter Output { get; set; } = Console.Out;
public TextWriter Error { get; set; } = Console.Error; @jonsequitur I lean towards keeping public class CliConfiguration
{
// parsing
public bool EnablePosixBundling { get; set; } = true;
public bool EnableParseErrorReporting { get; set; } = true;
public bool EnableTypoCorrections { get; set; } = false;
public TryReplaceToken? ResponseFileTokenReplacer { get; set; } = StringExtensions.TryReadResponseFile;
// symbols
public List<Directive> Directives { get; }
public HelpOption? HelpOption { get; set; } = new ();
public VersionOption? VersionOption { get; set; } = new ();
// execution
public bool EnableDefaultExceptionHandler { get; set; } = true;
public TimeSpan? ProcessTerminationTimeout { get; set; } = TimeSpan.FromSeconds(2);
public TextWriter Output { get; set; } = Console.Out;
public TextWriter Error { get; set; } = Console.Error;
} |
One of our goals is simplyfing the configuration, making it easier to discover and use.
This can be achieved by making the configuration mutable (no need for a dedicated builder) and making it an optional argument for
Command.Parse
(this has already happened).My current idea is following:
How to disable signaling and handling of process termination via a
CancellationToken
? SetProcessTerminationTimeout
tonull
.How to disable default response file token replacer? Set
ResponseFileTokenReplacer
tonull
.How to customize exception handler? Set
EnableDefaultExceptionHandler
tofalse
and catch the exceptions on your own:The alternative for customizing the
ParseErrorExitCode
is following:The most tricky part is how
HelpOption
andVersionOption
should be enabled and disabled. Currently, the config builder just adds them to the providedCommand
options list:command-line-api/src/System.CommandLine/Builder/CommandLineBuilderExtensions.cs
Lines 336 to 351 in 3b5c4be
I don't like it, as it's a side effect. But on the other hand, I don't have an ideal alternative.
Possible solutions:
Expect the users to add them in explicit way.
Advantage(s): no magic, everything is crystal clear, perf.
Disadvantage(s): help would be not enabled by default.
Create every command with Help and Version options added by default
Advantage(s): help enabled by default.
Disadvantage(s): Hard to customize help (find, cast & customize or replace) I expect that
Version
makes sense only for the root command, it would pollute subcommands.Perhaps it would make more sense for
RootCommand
?Maybe the argument should not be optional, so everyone who creates a Command would need to think about it?
Expose the options as part of Config type, add them the root Command when parsing
Advantage(s): quite easy to discover and configure, enabled by default.
Disadvantage(s): side effect of adding them to the root command (but so far nobody complained about it beside me?)
Do we really need
VersionOption
enabled by default?Add a list of default Options to Config, similarly to Directives
Advantage(s): quite easy to discover, consistent with Directives
Disadvantage(s): hard to configure a specific option (find HelpOption, cast it and then set the builder), side effect of adding them to the root command
@jonsequitur @KathleenDollard @Keboo @KalleOlaviNiemitalo please provide feedback
The text was updated successfully, but these errors were encountered: