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

Optionals that are somewhat positional #712

Closed
biowpn opened this issue Mar 2, 2022 · 4 comments
Closed

Optionals that are somewhat positional #712

biowpn opened this issue Mar 2, 2022 · 4 comments

Comments

@biowpn
Copy link

biowpn commented Mar 2, 2022

Behavior 1

In gcc there is an option -x <language> that works as described:

Specify explicitly the language for the following input files

This means that while -x looks like an optional, it is positional and affect the following positionals:

gcc -xc file1 file2

is different from

gcc file1 -xc file2

Behavior 2

Furthermore, there are flags in the gcc/linker that affect the following options. Take --whole-archive:

gcc --whole-archive -lmylib1 --no-whole-archive -lmylib2

The above basically turns on whole-archive for mylib1, but not mylib2.

Question

Is there a way to emulate the above behaviors with CLI11?

Notes

I've searched to docs through and through and haven't found a good answer.

With behavior 1, I can somewhat get around with

vector<string> args;
CLI::App app;
app.add_option("file,-x", args);

Only 2 issues: no separate help messages for file and -x; one can't really tell whether an element in args is contributed by -x or file.

With behavior 2, there isn't much I can do about it.

Just my opinion: it would solve both cases if add_option and add_flag accept a callback that is invoked for each individual argument during the parsing stage. Something like:

vector<string> c_files;
vector<string> cxx_files;
vector<string>* curr = &c_files;

CLI::App app;
app.add_option("file", [&](const string& file) { 
  curr->push_back(file);
  return true;
});
app.add_option("-x", [&](const string& language) { 
  if (language == "c") { curr = &c_files; }
  else if (language == "c++) { curr = &cxx_files; }
  else { return false; }
  return true;
});
@phlptp
Copy link
Collaborator

phlptp commented Mar 2, 2022

You likely want to look at trigger_on_parse() this will execute the callback given for the option or flag when the option is parsed vs after all parsing is finished.

@biowpn
Copy link
Author

biowpn commented Mar 2, 2022

You likely want to look at trigger_on_parse() this will execute the callback given for the option or flag when the option is parsed vs after all parsing is finished.

Thanks for the swift reply!

I can now get case 2 working. However, case 1 still doesn't work: callback for positional is invoked after parsing still.

Full test program attached below:

#include "CLI11.hpp"

int main(int argc, char** argv) {
    using namespace std;

    CLI::App app;
    app.add_option("file", "input file")
        ->take_all()
        ->allow_extra_args(true)
        ->each([&](string arg) { cout << "file callback invoked: " << arg << "\n"; })
        ->trigger_on_parse();
    app.add_option("-x", "specify the language for the following files")
        ->take_all()
        ->each([&](string arg) { cout << "-x callback invoked: " << arg << "\n"; })
        ->trigger_on_parse();
    CLI11_PARSE(app, argc, argv);

    return 0;
}

Compile and run:

$ g++ main.cpp
$ ./a.out  file1 -xc file2
-x callback invoked: c
file callback invoked: file1
file callback invoked: file2

I would expect

file callback invoked: file1
-x callback invoked: c
file callback invoked: file2

@biowpn
Copy link
Author

biowpn commented Mar 2, 2022

By the way, the conan center still only has version 1.9.1: https://conan.io/center/CLI11

Edit: never mind, found https://conan.io/center/cli11

@phlptp
Copy link
Collaborator

phlptp commented Apr 12, 2022

I think this is issue is resolved in the latest release now that trigger_on_parse works for positional arguments as well

@phlptp phlptp closed this as completed Apr 12, 2022
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

No branches or pull requests

2 participants