-
Notifications
You must be signed in to change notification settings - Fork 17
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 command-line parser #123
Conversation
b07f750
to
f193f83
Compare
4f6d9ad
to
350829c
Compare
Port of godotengine/godot#44594 to Godot 3.x. Co-authored-by: Shatur95 <[email protected]> Co-authored-by: lupoDharkael <[email protected]>
Not properly supported in Godot 3.x.
Note: this could be ported to simple `PackedStringArray` equality comparison in Godot 4.0. [tests skip]
[tests skip]
Consistent with other parsers in Godot, such as json/xml. [tests skip]
Consistent with `Expression.get_error_text()`, and `CommandLineParser`'s own `get_help_text()`. [tests skip]
`get_values/prefixes()` to `get_value/prefix_list()`, make consistent with other `_list()` methods on Godot. `get_forwarded_args()` to `get_forwarding_args()`, make consistent with `allow_forwarding_args` property.
These are not so trivial to implement in Godot 3.x since there's no Callable, which is Godot 4.x feature, and it might be better to see whether checher functionality is really needed in the first place, since validation is also possible to do via code after parsing, which is user-specific.
[ci skip]
There's not much benefit in separating the two, and in most cases makes API more confusing. Current parsing code validates arguments as well anyways.
Allows to conveniently add new options without instantiating `CommandLineOption` classes manually.
4ecbbf6
to
093b4d2
Compare
When declarative approach is not enough.
return OK; | ||
} | ||
|
||
Error CommandLineParser::validate() { | ||
for (int i = 0; i < _options.size(); ++i) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You will not able to define a help method and required arguments without validate
. This is how it done in other parsers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't removed validation code, but merged it at the end of parse()
, also renamed validated
signal to parsed
for options, so more consolidation. As a user, I still don't quite get the usefulness of this to be honest. Could you elaborate?
The validation doesn't look any much different from validation done in parse()
to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I understand. But without this separation, if you declare a help
command and mark some other command as required, the help command will not work because it will fail on required check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this separation you can check for the help / version commands first and then call validate
to check if other arguments are valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I understand. But without this separation, if you declare a
help
command and mark some other command as required, the help command will not work because it will fail on required check.
Alright, yeah I understand this now. But is it only useful for help
/version
options, or are there other use cases where this separation may be required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like this:
Then the text will be hardcoded :)
As I said, we have both add_help_option() and add_version_option() in public API. Those could be treated as special options and be recognized accordingly by the parser.
Then options will have a switch (maybe internal) to skip validation as I mentioned before.
As to me this behavior (with automatic validation skip) will be less obvious then a direct call to detect required variables (e.g. validate
). But it just me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've personally never used Boost.program_options
, but I did use Python's argparse
. There, if you define an option which is required=True
, then somehow it still allows to parse --help
and it prints a message, so I assume Python does have an internal mechanism to handle such cases. Godot users are more familiar with Python, so I think we should go with this approach.
Also, according to argparse.required
documentation:
Required options are generally considered bad form because users expect options to be optional, and thus they should be avoided when possible.
So having API which allows to explicitly validate frowned upon approach for defining options might not be a good idea.
As I said, parse()
already does a lot of validation checks for options/arguments prior to validate()
(see various internal _validate_*
methods), so it's also not 100% clear which checks are purely user-facing to make a better distinction, those that simply set _error_text
or just ERR_FAIL_*
(incorrect usage of command-line parser itself).
I'd personally like to keep API simpler if there's a possibility to make it simpler without losing functionality. If users say that validate()
is needed, it could be added in future versions without breaking compatibility, I guess.
Then options will have a switch (maybe internal) to skip validation as I mentioned before.
I think this is the way to go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... This makes.
On second thought a command option to skip validation if the command is specified not that bad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added ability to mark options as "meta", see recent commits. Options that are meta are designed to get information about application itself, so if any such option is detected on the command-line, there's no need to check for required options, because meta options are not designed to interact with user options.
I haven't exposed it as a property, should probably stay internal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome!
I would allow user to set it, cost nothing, but it's up to you.
I feel like current implementation and API is fine. So lets merge this and make it go through https://github.com/goostengine/goost-fuzzer to reveal potential crashes in Thanks for providing implementation and going through review process, hopefully we have consensus here. 🙂 |
You are welcome :) |
Port of godotengine/godot#44594 to Godot 3.x to be available in Goost, with another bulk of changes and enhancements.
Co-authored-by: https://github.com/Shatur and https://github.com/lupoDharkael, thanks for the work on this as well, it would be too bad for such a feature to remain in the Limbo.
To-do
Callable
, which is not present in Godot 3.xdecided not to implement for now, see
d074e05
(#123).