dotnet / command-line-api

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

Mutually exclusive options #381

Open sandcastle opened 5 years ago

sandcastle commented 5 years ago

It would be great to be able to handle mutually exclusive options.

Example

For example, if I had a command that either took an --all option or a --tenant <tenant-id> option, but never both.

public static Command Rebuild(IContainer container)
{
    var rebuild = new Command("rebuild", "Rebuilds a search index for one (--tenant <tenant-id>) or all (--all) tenants.")
    {
        Handler = CommandHandler.Create<bool, Guid>((all, tenant) =>
            container.Resolve<SearchRebuildTask>().ExecuteAsync(all, tenant))
    };

    rebuild.AddOption(new Option(new[] {"--all", "-a"},
        "Indicates if all tenants should be rebuilt.",
        new Argument<bool>(false) {Arity = ArgumentArity.ZeroOrOne}));

    rebuild.AddOption(new Option(new[] {"--tenant", "-t"},
        "Specifies the specific tenant that should be rebuilt.",
        new Argument<Guid> {Arity = ArgumentArity.ZeroOrOne}));

    return rebuild;
}
jonsequitur commented 5 years ago

This can currently be done using a custom validator, although it's a bit awkward.

https://github.com/dotnet/command-line-api/blob/master/src/System.CommandLine.Tests/ParsingValidationTests.cs#L104

Suggestions on a nicer API for this feature?

srsaggam commented 5 years ago

@jonsequitur As per our discussion earlier. It would also be great to have these changes cascade to dotnet-suggest. i.e The auto completion should not suggest the mutually excusive options when one of them is set.

Should we track this in separate issue or should we include it in this issue itself?

jonsequitur commented 5 years ago

I think it's fine to track it here.

srsaggam commented 5 years ago

cc : @CESARDELATORRE @vinodshanbhag @rjoshi

CESARDELATORRE commented 5 years ago

@jonsequitur Jon, what's the priority for this feature? It'd be very good for the ML.NET CLI due to parameters like the following which are exclusive:

--label-column-name | --label-column-index

jonsequitur commented 5 years ago

@CESARDELATORRE, this capability is supported right now but the API is awkward. Improving the API will likely be done along with improvements to enable #310, and it's fairly high priority but I don't have a timeline for it. I don't believe this should block you.

@srsaggam, my understanding is that you have the validation working but tab suggestions don't reflect the exclusivity. Is that correct?

srsaggam commented 5 years ago

@jonsequitur That is correct. My comment is regarding tab suggestions. I think @CESARDELATORRE is referring to the same. We are not blocked by the functionality but we were thinking the intelligent suggestions for this case will be a good feature to demo and will help our users to not make mistakes.

CESARDELATORRE commented 5 years ago

Sorry, I was not clear with my comment. It is regarding tab suggestions. For example, if I use the arg --label-column-name then since --label-column-index is mutually exclusive, the tab suggestion shouldn't show --label-column-index but the next argument.

I think we're good if that feature related to tab suggestions is moving forward. You are right that this is not a blocking issue but improving the user's experience. 👍

srsaggam commented 5 years ago

Also for this. Lets say we have options like : --abc --abze --dab --dbc

when we type --ab[->TAB] the suggestions should be abc on first tab and abze on the second tab and this should repeat it shouldn't suggest anything else. kind of prefix tree based suggestions then sorting ascending order

but looks like the current dotnet suggest doesn't do this kind of behavior it doesn't seem to respect the prefix that is already typed. it just suggests in the alphabetical order on whole set rather than filtered prefix.

@jonsequitur @CESARDELATORRE

jonsequitur commented 5 years ago

@srsaggam This deserves a separate issue. If you type ab and hit tab do you see the expected behavior?

AndrewSav commented 3 years ago

The link to a custom validator above is no longer valid. Here is a valid one

ransagy commented 1 year ago

Just to circle back on this; Is the current way to do this only via custom validation? is there a different API planned or..?

jonsequitur commented 1 year ago

Currently, a custom parse delegate is the recommended approach, although we'll likely add first-class API for this in the future.

dorssel commented 1 year ago

In case anyone is interested; this is how I do it:

Generic validator: https://github.com/dorssel/usbipd-win/blob/2f7cbb732889ed00617e85f2f0b22239e8533960/Usbipd/Program.cs#L86-L94

Used as: https://github.com/dorssel/usbipd-win/blob/2f7cbb732889ed00617e85f2f0b22239e8533960/Usbipd/Program.cs#L188-L191

This can be used for any number of n mutually exclusive options, with the correct error message if none or too many are given. Of course, this can easily be tweaked to allow zero options as well.