-
-
Notifications
You must be signed in to change notification settings - Fork 60
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
Add support for positional arguments #26
Comments
The command name and options are currently parsed in the This obviously needs to change to support positional arguments. The biggest question to answer is: when does the command name stop and the positional argument(s) start? -- especially when considering commands with both subcommands and positional arguments. My suggestion would be to split the parsing in two parts:
The most specific command schema would be the one with most of the arguments matching the command name. For instance, having two commands
@Tyrrrz what are your thoughts on this approach? |
We also need to figure out how to mark a property as positional argument. I was thinking a separate attribute
The
This approach might be tricky when considering whether or not to support multiple positional arguments, and/or collections as positional arguments, which could make sense, for instance:
To map the correct argument to Alternatively, we could allow only a single property to be marked as a positional argument, and let the user utilize collections to support such scenarios. This would however require the library users to parse the input themselves if the arguments contain different data types, e.g.:
In summary
Depending on how we answer these questions, it may also be possible to just extend the |
This is the approach I had in mind, except I saw this happening during resolving part. The parser is currently context-unaware that makes it simpler to test and work with for users, and if possible I'd like to keep it this way. So the way I envisioned it is that Everything else you said, I agree with your way of thinking. :)
Yes, I don't see it possible to re-use
Unfortunately, yes. Hopefully
I think that would be a step in the wrong direction because we want the users to effectively forget they're dealing with command line.
Yes.
We will use the
Yes. Only one collection type argument is allowed and it must be last in order to remove ambiguity. We should ideally validate this so the user doesn't make a mistake. |
Good, I agree with your observations. I will probably take a stab at this when I get the time. |
Awesome :) |
@Tyrrrz I had some time to look into this, and I think that the choice to have a context-free parser makes implementing this feature hard/impossible, or at least makes us unable to sensibly disambiguate in certain scenarios. Let me explain. First of all, I think having the positional arguments before the options was a bad suggestion. Doing so will mean that we cannot disambiguate positional arguments from command names and option keys at the same time, at least not in a sensible manner. Having the commands
Supporting invokation of What GNU CLIs typically do, is to have the positional arguments after the options, possibly with a
The first calls the command Secondly, to disambiguate from option keys:
The first calls Since this library uses a context-free parser, we lose some usability goodies. If
However, without the context that
The examples are of course contrived, but I think they demonstrate that the choice of having a context-free parser will definitely make it harder to disambiguate arguments in certain scenarios. What do you think about these considerations? Any insightful suggestions? |
Thank you for such a thorough analysis @thorhj Can you give me an example CLI that uses this Anyway, I've given it a lot of thought after reading your message. I really hate ambiguity in command line arguments as I believe they should deterministically convey the user's intent. Ideally, you should be able to look at command line arguments and be able to tell what is set to what, without having to know the structure of the program. This is also why I think it's nice that the arguments go first. I realize the existence of command arguments and subcommands violates this perfect world where everything is deterministic. This is why I sort of lead on to a compromise where the parser separates the input into arguments and options and later, during command initialization stage, arguments are matched one by one against potential subcommands to see if they are normal arguments or subcommands. In essence, it would like this:
The above approach, if extended to match required arguments first, should even work with scenarios such as:
In case one of the arguments matches the name of a subcommand, the subcommand should win. After all, the designer of the CLI committed to this when they made it this way. To avoid ambiguity, they can declare the argument as an option instead. Also, this problem will also happen with context-aware parsers. This separates the parser logic from the routing logic which, in my opinion, makes it easier to reason about and test. As for taking Inputs such as |
I prefer a cleaner syntax:
I think we could limit the ability to register ambiguous commands when bootstrapping to protect developers first and users second. These are valid commands:
But these are not:
|
One such CLI is git, e.g.
although in this example it additionally ambiguate the required
Yes, this crossed my mind as well, but .NET parses the arguments into a By invoking
with each line denoting a Notice that the strings |
There is the Generally, if we can discourage using ambiguous configurations we will be fine so long as they have a viable alternative. The only one without a workaround is setting I think if there are multiple ways of doing the same thing, we should try to enforce only one that is the least ambiguous. In case with |
Also, to be a bit pedantic, introducing |
Here are some POSIX/GNU guidelines I found:
(https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html)
(https://www.gnu.org/prep/standards/html_node/Command_002dLine-Interfaces.html) |
If both If so, should the parser produce this output?
Then we can check the individual arguments for whitespace, and only expand to commands if there are no whitespace characters in the arguments (in the example use Do you agree with this approach? |
@thorhj |
For future reference: I've decided to rename the concept of arguments into "parameters" to avoid ambiguity with command line arguments (which includes everything). |
Commands may have an argument that is always required and makes sense semantically without an option flag. E.g.:
Positional arguments are not supported, so the above would need to be invoked like this:
The text was updated successfully, but these errors were encountered: