-
Notifications
You must be signed in to change notification settings - Fork 402
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
iox #1067 create command line parser abstraction #1102
iox #1067 create command line parser abstraction #1102
Conversation
dec4497
to
10d0ea7
Compare
Codecov Report
@@ Coverage Diff @@
## master #1102 +/- ##
==========================================
- Coverage 77.39% 75.68% -1.71%
==========================================
Files 367 375 +8
Lines 14248 14566 +318
Branches 1992 2072 +80
==========================================
- Hits 11027 11025 -2
- Misses 2590 2909 +319
- Partials 631 632 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
|
0d4c789
to
570da07
Compare
I can't promise to look at this anytime soon |
@elBoberido this is alright ... but I hoped that I maybe can bribe you with coffee, cookies, cake and chocolate. |
iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/command_line_parser.hpp
Outdated
Show resolved
Hide resolved
83ca102
to
13232d8
Compare
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.
Only reviewed command_line.hpp
and corresponding .inl and tests so far.
iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/command_line.inl
Outdated
Show resolved
Hide resolved
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.
CommandLineParser, but not the tests.
iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/command_line_parser.hpp
Outdated
Show resolved
Hide resolved
iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/command_line_parser.hpp
Outdated
Show resolved
Hide resolved
iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/command_line_parser.hpp
Outdated
Show resolved
Hide resolved
iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/command_line_parser.hpp
Outdated
Show resolved
Hide resolved
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.
Please don't introduce new direct calls to errorHandler()
in iceoryx_hoofs
.
iceoryx_hoofs/include/iceoryx_hoofs/error_handling/error_handling.hpp
Outdated
Show resolved
Hide resolved
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 checked if the CommandLineParser
tests make sense; will check for missing tests in the next review round.
iceoryx_hoofs/test/moduletests/test_cxx_command_line_parser.cpp
Outdated
Show resolved
Hide resolved
iceoryx_hoofs/test/moduletests/test_cxx_command_line_parser.cpp
Outdated
Show resolved
Hide resolved
iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/storable_function.hpp
Outdated
Show resolved
Hide resolved
2e440d5
to
ed271a8
Compare
ed271a8
to
d113363
Compare
iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/command_line_parser.hpp
Outdated
Show resolved
Hide resolved
e1929cf
to
be68cad
Compare
Signed-off-by: Christian Eltzschig <[email protected]>
Signed-off-by: Christian Eltzschig <[email protected]>
Signed-off-by: Christian Eltzschig <[email protected]>
Signed-off-by: Christian Eltzschig <[email protected]>
…on appears Signed-off-by: Christian Eltzschig <[email protected]>
… copyright header Signed-off-by: Christian Eltzschig <[email protected]>
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.
We are getting closer but still not there yet.
The tests are still no reviewed. Some fun for later.
/// @brief returns true when it contains a long option which is set | ||
bool hasLongOption() const noexcept; | ||
|
||
char shortOption = NO_SHORT_OPTION; |
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.
This somehow smells like a cxx::optional<char> shortOption
or cxx::string<1> shortOption
. It's not a request for change just a food for thought.
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 would stick to this. The reason is that char
is also somehow nullable and this I cannot avoid. What if the user explicitly state that the short option should be \0
? With this approach I covered it.
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.
Shouldn't this be a the same with a cxx::string<1>
which would be empty for \0
? I'm just thinking about this since it would lead to a nice symmetry in the checks with longOption
. Maybe something for a future refactoring.
iceoryx_hoofs/source/cli/option.cpp
Outdated
return shortOption == '-'; | ||
} | ||
|
||
bool Option::hasLongOptionName(const OptionName_t& value) const noexcept |
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.
Also just food for thought. matchingLongOptionName
/hasMatchingLongOptionName
instead of hasLongOptionName
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.
Alright but then it would be inconsistent with the other methods. But I could rename all methods to something like matchesLongOptionName
, matchesShortOptionName
, matchesOptionName
but I prefer the current names.
void CommandLineArgumentParser::setDefaultValuesToUnsetOptions() noexcept | ||
{ | ||
for (const auto& r : m_optionSet->m_availableOptions) | ||
{ | ||
if (r.details.type != OptionType::OPTIONAL) | ||
{ | ||
continue; | ||
} | ||
|
||
bool isOptionAlreadySet = false; | ||
for (auto& option : m_optionValue.m_arguments) | ||
{ | ||
if (option.isSameOption(r)) | ||
{ | ||
isOptionAlreadySet = true; | ||
break; | ||
} | ||
} | ||
|
||
if (!isOptionAlreadySet) | ||
{ | ||
m_optionValue.m_arguments.emplace_back(r); | ||
} | ||
} | ||
} |
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.
This also took me a while. Actually this does not set default values to unset options since all specified options are already in m_optionValue.m_arguments
. What is does is adding unspecified options to the specified options if actionWhenOptionUnknown
is not UnknownOption::TERMINATE
. Please keep a consistent terminology. Currently it is a mixture of unknown
and unset
.
I would even argue to not add the unknown options to m_optionValue.m_arguments
. If the developer forgot to specify the option at least it will be revealed in tests and the incorrect behavior can be fixed.
} | ||
case UnknownOption::IGNORE: | ||
{ | ||
if (isNextArgumentAValue(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.
Pleas print a message that an unknown option was found and that it will be ignored.
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 explicitly do not want that. Let's assume you do something like ros with the commands and subcommands and parse some arguments internally and the remaining arguments are forwarded to another command line parser which knows what to do with it.
Then it would be absolutely annoying to see messages on the console that some arguments weren't parsed by the first parser.
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.
But what ros does with the subcommands is different that what this does, doesn't it?
Let's assume I have ./foo bar baz caramba
. Then I would assume that the parser would stop parsing when the subcommand bar
is found and delegate the remaining arguments to the next stage. If there is no output, how do I know that I mistyped the command like ./foo baz baz caramba
?
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.
... when thinking about it, there shouldn't be an option to ignore params but just the option to stop parsing when a subcommand is found or maybe call the nesting parser on the remaining arguments
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 removed the feature again. Whenever you type an unknown option you get an error message and the help is shown.
You challenged me with the struct size ... now I throw my code in the ring :) https://gist.github.com/elBoberido/86ec2d69912a47a5ba7cf09acba9de4e The resulting struct has only 8 bytes of additional data ... on the plus side, the parser front-end is even simpler ... the secret is once again to prefer factories over constructors :) |
…rite methods for better readability, options are only sorted before they are printed in the help, add parameter to doxygen docu Signed-off-by: Christian Eltzschig <[email protected]>
…truct by creating an explicit factory which holds all the temporary members Signed-off-by: Christian Eltzschig <[email protected]>
…e can use argv[0] system wide starting from main Signed-off-by: Christian Eltzschig <[email protected]>
Alright you mastered the challenge! And you inspired me, I used your idea and reduced the base size of the user defined command line struct to 16 - not to 8 like you. The reason is that this command line struct stores by default the binary name which require additional 8 byte since I store the const char *. This shouldn't pose any problem since |
…er reflected in their name Signed-off-by: Christian Eltzschig <[email protected]>
Signed-off-by: Christian Eltzschig <[email protected]>
Signed-off-by: Christian Eltzschig <[email protected]>
…gumentValue Signed-off-by: Christian Eltzschig <[email protected]>
@elfenpiff @elBoberido @dkroenke any chance we could get this merged in? Would be super useful elsewhere 😄 |
@flynneva with the introduction of |
Signed-off-by: Christian Eltzschig <[email protected]>
Signed-off-by: Christian Eltzschig <[email protected]>
Signed-off-by: Christian Eltzschig <[email protected]>
Signed-off-by: Christian Eltzschig <[email protected]>
…inted where the test ids are missing Signed-off-by: Christian Eltzschig <[email protected]>
Signed-off-by: Christian Eltzschig <[email protected]>
Signed-off-by: Christian Eltzschig <[email protected]>
… case Signed-off-by: Christian Eltzschig <[email protected]>
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.
Okay to be merged into dust
Pre-Review Checklist for the PR Author
iox-#123-this-is-a-branch
)iox-#123 commit text
)git commit -s
)task-list-completed
)Notes for Reviewer
Required for the Windows command line feature in the upcoming iceoryx 2.0. This provides the building blocks to replace and unify all the command line parsing algorithms in all applications with a simple struct based interface. With this the requirement for the library
getopt.h
is removed and we have the same simplistic command line parsing approach on all platforms.Furthermore, this class provides a lot of error handling, boundary checking etc. which is not present at the moment. Invalid arguments are most of the time only poorly checked and this may lead to crashes. With those classes this should be a problem of the past.
Most likely the command line parser will not become a safety certified class therefore the tests most not perform a MC/DC coverage. Nevertheless I tried to be as diligent as possible.
Checklist for the PR Reviewer
Post-review Checklist for the PR Author
References