Skip to content
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 options to handle windows style command line options #187

Merged
merged 3 commits into from
Jan 10, 2019

Conversation

phlptp
Copy link
Collaborator

@phlptp phlptp commented Jan 7, 2019

If merged this pull request will add an option for CLI11 to handle windows style options
such as /d /D /file:some_file.ext

This is enabled through a new app function allow_windows_style_options()

The modifications include some refactoring of the parse_arg function to take a Classifier enum instead of a boolean and the addition of a parse_windows helper function.

The Classifer enum was renamed to Classifier (not entirely sure if that was a misspelling or on purpose?) If it was on purpose I can change it back.

add test cases for windows options and refactor for additional string functions
@codecov
Copy link

codecov bot commented Jan 7, 2019

Codecov Report

Merging #187 into master will decrease coverage by 0.15%.
The diff coverage is 96.9%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #187      +/-   ##
==========================================
- Coverage     100%   99.84%   -0.16%     
==========================================
  Files          12       12              
  Lines        1849     1894      +45     
==========================================
+ Hits         1849     1891      +42     
- Misses          0        3       +3
Impacted Files Coverage Δ
include/CLI/Option.hpp 100% <ø> (ø) ⬆️
include/CLI/Formatter.hpp 100% <ø> (ø) ⬆️
include/CLI/StringTools.hpp 100% <100%> (ø) ⬆️
include/CLI/Split.hpp 100% <100%> (ø) ⬆️
include/CLI/Validators.hpp 100% <100%> (ø) ⬆️
include/CLI/App.hpp 99.65% <95.52%> (-0.35%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2c02440...11b6cd1. Read the comment docs.

@codecov
Copy link

codecov bot commented Jan 7, 2019

Codecov Report

Merging #187 into master will decrease coverage by 0.05%.
The diff coverage is 98.92%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #187      +/-   ##
==========================================
- Coverage     100%   99.94%   -0.06%     
==========================================
  Files          12       12              
  Lines        1849     1890      +41     
==========================================
+ Hits         1849     1889      +40     
- Misses          0        1       +1
Impacted Files Coverage Δ
include/CLI/Formatter.hpp 100% <ø> (ø) ⬆️
include/CLI/Option.hpp 100% <ø> (ø) ⬆️
include/CLI/Validators.hpp 100% <100%> (ø) ⬆️
include/CLI/StringTools.hpp 100% <100%> (ø) ⬆️
include/CLI/Split.hpp 100% <100%> (ø) ⬆️
include/CLI/App.hpp 99.88% <98.41%> (-0.12%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2c02440...775e413. Read the comment docs.

@henryiii
Copy link
Collaborator

henryiii commented Jan 8, 2019

I'll try to review on Thursday. Thanks for catching Classifier!

@phlptp
Copy link
Collaborator Author

phlptp commented Jan 8, 2019

I am not totally clear what to do about the coverage, it seems to be no recording the the closing brace on a lambda function, which seems strange to me.

@phlptp
Copy link
Collaborator Author

phlptp commented Jan 8, 2019

A little background: I tried a couple different variations the first had a number of different functions to control the parsing. allow_slash_for_short(), allow_slash_for_long(), But that ended up with a lot of conditions and controls in both App and Option. I also looked at allowing the option definition to allow "/option" in addition to the existing one and have the control be through the options. But the parsing is done in the App and that got complex in a hurry.

So I went with a single control in App to simplify matters then nothing would need to be changed in the Options. It is possible to allow the use /option=XXX but that is not typical for windows style options, it would require a couple lines in the parse_windows function. So it was left off.
Also typical windows options do not allow chaining of the short form options, That restriction fell out naturally from the parsing. It could be allowed with a little bit of additional logic, but because it is not typical in windows applications seems natural to leave the restriction in place. I tried to convey those limitations in the readme.

My main reason for needing this is even though I prefer the unix style option parsing we have a couple cases where our application is layered with windows specific applications that need to forward command line options, and would require mixing the options style and some odd positional parsing if Windows Style options were not allowed. So allowing that style of options allows everything to be consistent.

Copy link
Collaborator

@henryiii henryiii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks fantastic. I had a couple of questions. The non-100% coverage issue probably is not the final line of a lambda, but rather a nearby line. For some reason on this and the last PR the coverage line reporting has been off. After it is merged I think we'll see the real line that is causing problems.

@@ -26,30 +26,6 @@ TEST_F(TApp, ExistingExeCheck) {
EXPECT_EQ(str3, "\"quoted string\"");
}

TEST_F(TApp, ExistingExeCheckWithSpace) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this being removed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was mainly testing the file name separation, which is then redundant with the new Validators test since the function that handles that was moved out of the parse function.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having an integration-style test in addition to the unit-style test is not a bad idea, at least as long as it already exists. I might add it back in.

/// the string is assumed to contain a file name followed by other arguments
/// the return value contains is a pair with the first argument containing the program name and the second everything
/// else
inline std::pair<std::string, std::string> split_program_name(std::string commandline) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this is Validators.hpp? Shouldn't it be in one of the other headers, like string tools?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main reason was it uses the validators to check for an existing file, and if it was included in one of the other tools that header would then have to include the validators header, which I wasn't sure how you felt about.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, we'll leave it there for now. Maybe should be moved to a new header at some point.

@henryiii henryiii merged commit ce6dc07 into CLIUtils:master Jan 10, 2019
@henryiii
Copy link
Collaborator

Merged, we can look at the coverage after the CI completes on master, and hopefully track down the problem line.

@henryiii
Copy link
Collaborator

henryiii commented Jan 10, 2019

Question: what happens if there's an option named -a and --a? Who wins?

And, note to self, add to changelog.

@phlptp
Copy link
Collaborator Author

phlptp commented Jan 10, 2019

The long options are checked first so the long option would take precedence in that case
App.hpp line 1949 return opt->check_lname(name) || opt->check_sname(name);

@phlptp phlptp deleted the windows_like_options branch January 10, 2019 23:13
@henryiii henryiii mentioned this pull request Jan 11, 2019
@henryiii
Copy link
Collaborator

The long options are checked first

No, the options are checked one by one in definition order. The first match counts, even if it is opt->check_sname. So the first defined option with that name is used. That's fine, it just should be mentioned and tested (doing that now).

@henryiii
Copy link
Collaborator

@phlptp, would it make sense to set the default for allow_windows_style_options to be true on windows, and false otherwise? It would be easier for user code to write ->allow_windows_style_options(false) if they really did not want windows users to use windows style options. Would there be any drawbacks?

@phlptp
Copy link
Collaborator Author

phlptp commented Jan 11, 2019

The potential drawbacks would be a slight performance degradation to have an additional check for /options and if someone had a relative path using / to start as part of a positional argument that would probably break it if they didn't turn the check off. I wouldn't have any problem with that being the default for my applications but it could cause some unexpected behavior in specific situations, but those would likely be rare.

@henryiii henryiii mentioned this pull request Jan 24, 2019
@henryiii henryiii added this to the v1.7 milestone Feb 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants