Git Product home page Git Product logo

cli11's People

Contributors

allcontributors[bot] avatar andrew-hardin avatar bindreams avatar captainurist avatar cbachhuber avatar dcbaker avatar deining avatar delpinux avatar dependabot[bot] avatar dherrera-meta avatar dvj avatar fpeng1985 avatar henryiii avatar j-rivero avatar jbriales avatar krzmbrzl avatar lambdafu avatar lczech avatar mensinda avatar phlptp avatar polistern avatar pre-commit-ci[bot] avatar rafiw avatar rcurtin avatar samhocevar avatar seanfisk avatar sherlockinspace avatar skytoground avatar thewtex avatar volkerchristian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cli11's Issues

Inheritance of values

Currently, CLI11 allows some settings on commands to be inherited by subcommands. This proposal would standardize that inheritance and add option inheritance.

The following app settings would be "inheritable":

  • prefix command
  • allow extras
  • group name
  • ignore case

The following option settings would be "inheritable":

  • group name (NOT the same as app; called option_group() on app)
  • required (called option_required() on app)
  • ignore case (same as app)
  • take last (replaces current mixed true/false setting)

Option-only settings would be settable on an app, causing it to be inherited by options and subcommands, but having no direct effect.

The inheritance would be handled in one place, by a templated pair of functions, something like this:

inherit_from(T* pointer) {
    item_one = pointer->item_one;
    ...
}

This allows easy setting of defaults, either directly or by a subclass. Thoughts?

conversion error on multiple bool flagse

When using a bool flag, giving the option multiple times on the command line causes a conversion error (because it can not count the number of times the option appears in a bool variable, I presume).

But that error message is ugly and user-unfriendly, so why would anybody ever use that? Which means everybody will just use an int and check for == 0.

Why not just keep the value at true and ignore the extraneous appearances of the bool flag on the command line?

Test case is in AppTest.cpp:156:

    args = {"-b", "-b"};
    EXPECT_THROW(run(), CLI::ConversionError);

Windows warning

Look into adding #if statements and the windows version of getenv to avoid the one warning given with \W4. Env access is not threaded, so it should be safe without this change, however.

Interleaving options and flags

I want to be able to interleave options with flags like so;

myCommand -flag0 file1 file2 file3 -flag1 file4

and when parsing know which flags apply to which files. Since positional arguments are stored as a vector it gets a bit tricky; I can do it using a check() call that actually stores the file names, and then use a dummy vector as the target;

	opts.add_option("files", dummyVector, "Filename")->check([&](const std::string &n) -> std::string {
		realVector.push_back(make_pair(currentFlags, n));
		return "";
	});

but it would be easier if there was a version of add_option that accepted a function that took a std::string, and called it for each occurrence of the option.

Release 1.5

If all goes well, release 1.5 should happen on Monday. #88 should be fixed (? no test yet), and #87 will be too tricky to implement properly by 1.5.

optional support (and boost configuration) issue

This issue has 2 parts:

  • It appears as though the single-file, combined, CLI11.hpp file is built by first assembling the CLI/Optional.hpp file above the CLI/Version.hpp file. This has the side effect that some defines like CLI11_CPP17 won't be set yet when Optional.hpp starts looking over them.

  • There's no way to disable boost support. The library goes out of its way to detect boost but in my case I kind of don't want it to do that :) How do I ensure CLI11 doesn't drag in boost headers when I don't want it to? Maybe use an ALLOW_BOOST define that the user can set before including CLI11.hpp so the lib knows not to check at all.

Support overriding arguments

Hi, thanks for the great library!

Is it possible to specify arguments multiple times and have the last one take precedence?

E.g. my-app --name foo --name bar would be identical to my-app --name bar.

I know there is good support for array arguments, but using them to get the above functionality doesn't seem ideal.

Thoughts?

Smart Validators

Validators could have other properties added, such as help information. This would require that they be rewritten from simple functions into something else (and simple functions could be accepted as well, auto wrapped into a structure). The biggest problem is finding a way not to add () to all validators (maybe okay? Range has to have parenthesis already) (solved)

Unicode

This is a general issue for discussion on unicode/wchar support.

My thought is to start by making typedefs (using aliases now) for the main types of strings being used and main functions on strings, then it would be easy to change in one place. I could even do a check for C++17 and use string_view if available.

Any help from people who use extended chars appreciated.

Hybrid flag/option

I would like to have support for options that can act as flags if no argument is given.
These options would require the forms -Xsomething or --longer=something when used as options.

opts.add_hybrid_option("--sign", stringValue, "Sign archive with specified key or default if none given", "defaultKey");

if(stringValue != "") {
  // Perfom signing
}

Should print help text such as;
--sign[=TEXT]

Setting default values do not take effect

int test = 0;  
app->add_option("--test", test, "Test the default value.")->set_default_val(std::to_string(200));  
app->parse(argc, argv);
std::cout << test << endl; // output:0, want: 200

Vector options conflict with positional arguments when there is no space.

If you have -a as a vector option, and b as a positional argument, there will be a conflict when there is no space after the vector option.

Usage: ./out [OPTIONS] [b]

The following will work fine:

./out -a 5 positional_value

-a is parsed as ["5"] and b is parsed as "positional_value".

However, if you do the exact same thing without a space:

./a out -a5 positional_value

-a is parsed as ["5", "positional_value"], and b is not parsed at all.

Flag and/or option fallback function

I want to parse special flags that begins with a dash and contains a single digit to mean compression levels for my zip like compression tool.

Right now I need to handle this with a special check inside a callback for positional arguments.

I would like to have something like:

opts.add_flag_fallback("-<digit>", [&](const char d) {
    compressionLevel = d - '0';
}, "Set compression level (0-9)");

Prefix command

Add support for a prefix command, where a different app can be called after parsing. This is almost already supported; the problem is that you can't do the following:

./my_app --my_app_flag another_command --another_command_flag --my_app_flag

The final --my_app_flag will be parsed and used with CLI11 before returning the unparsed arguments.

You could use subcommands to solve this problem already, but then you would have to know the another_command beforehand.

See https://stackoverflow.com/questions/37996617/create-a-prefix-command-with-boost-program-options

Unlimited positional and unlimitied option

Hi, have a question. I have a situation where there's one unlimited positional and one unlimited option. Like this:

std::vector<std::string> t1, t2;
app->add_option("test1", t1);
app->add_option("--test2", t2);

If you give these arguments: ./test a b c --test2 d e f, then a b c and e f will go to t1, and only d will go to t2.

I've seen in the source code:

// If there are any unlimited positionals, those also take priority

Could you please explain why you design like this? I think in this situation, d e f should go to t2.

Inter-argument order

The poster here describes a specific issue that should be easy to solve with a small modification to CLI11.

Planned solution: store a vector of pointers to Options as it parses. Then this could be solved like this:

for(Option* opt : app.parse_order()) {
    if(opt == arg1)
        \\ use value of arg1
}

Validator ExistingFileOrDirectory

For a program that I am currently writing, it would be nice to have a validator that checks whether a path is existing. Kind of an or between ExistingFile and ExistingDirectory:

/// Check for an existing file or directory
inline std::string ExistingFileOrDirectory(const std::string &filename) {
    struct stat buffer;
    bool exist = stat(filename.c_str(), &buffer) == 0;
    if(!exist) {
        return "Path does not exist: " + filename;
    }
    return std::string();
}

Could also be called ExistingPath, assuming that all kinds of files are allowed, e.g., block devices etc, see https://linux.die.net/man/2/stat

"is required" displayed twice in case of required option is not found

In method App::_parse :
RequiredError(opt->single_name() + " is required");

In class RequiredError :
RequiredError(std::string name) : RequiredError(name + " is required", ExitCodes::RequiredError)

It would make sense to remove the "is required" string from App::_parse method and let it in the RequiredError() class.

Tutorial set

Add a tutorial set to help new users. Not sure if that should be a .md file, a gitbook, part of the API docs, etc.

Readme error

From the readme:

CLI::App app{"App description"};

std::string filename = "default";
app.add_option("-f,--file", file, "A help string");

try {
    app.parse(argc, argv);
} catch (const CLI::ParseError &e) {
    return app.exit(e);
}

should be

CLI::App app{"App description"};

std::string filename = "default";
app.add_option("-f,--file", filename, "A help string");

try {
    app.parse(argc, argv);
} catch (const CLI::ParseError &e) {
    return app.exit(e);
}

right?

No take_last specifier for add_flag

In the CLI11 tutorials it says that:

This will bind the flag -f to the boolean my_flag. After the parsing step, my_flag will be false if the flag was not found on the command line, or true if it was. By default, it will be allowed any number of times, but if you explicitly1 request ->take_last(false), it will only be allowed once; passing something like ./my_app -f -f or ./my_app -ff will throw a ParseError with a nice help description.

However, after including the CLI11.hpp file and using this kind of expression I get the error:

no member named 'take_last' in 'CLI::Option'

The expression I used is the following:

bool runSingleThread;
subcommand->add_flag("-s,--singleThread", runSingleThread, "Split execution into multiple threads")
      ->take_last(false);

Is there something I did wrong? Is this option implemented in a later version than the one I'm using?

Cheers

allow_extras/prefix_command and subcommands

allow_extras/prefix_command and subcommands don't mix well. The main problem is that allow_extras/prefix_command has to be set on the parent, rather than the subcommand, for it to have any effect. This implies:

  • If no subcommand is given, extra arguments are ignored and parsing stops at the first unknown positional. There is no way to get allow_extra/prefix_command only for subcommands but not for the parent.
  • You can't have some subcommands that are the prefix of an operation, and some subcommands that are not.

To regain composability, allow_extras/prefix_command should take affect only at the level they are given.

Add/remove new possible choices after a call to add_set

Hi CLI11 team,

Great job with this library, I really enjoy the simplicity !

I'm trying to use CLI11 in AFF3CT, here is a code example:

CLI::App app{"App description"};

std::string type;
auto opt = app.add_set("--type", type, {"TYPE1","TYPE2","TYPE3","TYPE4","TYPE5"}, "A type");

// I would like to do something like this to add a choice
opt->add_choices({"TYPE6", "TYPE7"});

// and something like this to remove a choice
opt->remove_choices({"TYPE1", "TYPE2"});

Is it possible to do something like this with CLI11?
If not, should it be possible to add this type of feature ?

Many thanks,
Adrien

clarify how to return runtime errors

I noticed that main() returns an int, but parse and callback_ return void. On the other hand, there is an exit_code stored in CLI::Error, but CLI11_PARSE catches on the more specific CLI::ParseError. This raises the question how subcommands called through run_callback should return an exit code to main that is not related to parsing, and if this should even be supported by CLI11.
A straightforward approach is to use exceptions. Of course, this can be done without any support by CLI11 already. But given that most of the required code is already in there, it seems reasonable to define CLI::RuntimeError that is handled like CLI::ParseError by CLI11_PARSE, probably by catching on CLI::RuntimeError and making CLI::ParseError derive from that. Then subcommands can simply throw CLI::RuntimeError or derivatives. If this sounds like a good idea to you, I could come up with a pull request for that.

Consider integration of std::optional (C++17)

Consider adding direct support for std::optional from C++17 (or boost::optional, etc).

Note that this is just for ease of use for people familiar with optionals, the functionality is already there:

int option;
CLI::Option* option_ptr = app.add_option("-o", option);
// Parse

if(*option):
   // use option

// OR
if(option->count() > 0)
    // use option

Support repeating multi-argument options

First of all, thank you for creating CLI11! It's much better than anything else out there. I've used Boost.Program_Options, which was ok, and QCommandLineParser, which was awful. CLI11 is a breath of fresh air and has saved me a lot of time, so, thank you!

I am looking to implement a command-line interface that allows a repeating option that takes 2 arguments. Here is an example Python program using argparse that implements it:

#!/usr/bin/env python3.6
# repeating_multi_arg_option.py

import argparse

parser = argparse.ArgumentParser(
    description='Repeating options that take multiple arguments')
parser.add_argument('--entry', nargs=2, metavar=('KEY', 'VALUE'),
                    action='append', help='key & value')
print(parser.parse_args())

Example runs:

$ ./repeating_multi_arg_option.py --entry key1 val1 --entry key2 val2
Namespace(entry=[['key1', 'val1'], ['key2', 'val2']])

$ ./repeating_multi_arg_option.py --entry
usage: repeating_multi_arg_option.py [-h] [--entry KEY VALUE]
repeating_multi_arg_option.py: error: argument --entry: expected 2 arguments

$ ./repeating_multi_arg_option.py --entry key1 --entry key2 val2
usage: repeating_multi_arg_option.py [-h] [--entry KEY VALUE]
repeating_multi_arg_option.py: error: argument --entry: expected 2 arguments

$ ./repeating_multi_arg_option.py --help
usage: repeating_multi_arg_option.py [-h] [--entry KEY VALUE]

Repeating options that take multiple arguments

optional arguments:
  -h, --help         show this help message and exit
  --entry KEY VALUE  key & value

It's almost possible with a combination of …->expected(2)->join(), but what I'm really looking for is a result that shows accurate error messages and preserves the nested structure (a list of lists).

If there is a path forward, I may also be able to help implement. Thank you!

Version flag/option

So far to get a simple flag that triggers it's callback first time it's detected I had to do this workaround.

auto ver = app.add_option("-v,--version", (CLI::callback_t)show_version, "Show version");
ver->set_custom_option("", 0); 

It would be much more user friendly to have it similar to add_flag syntax but just with a callback.
No sure if it qualifies to be a separate function as add_config.

Option *add_version(std::string name, callback_t callback, std::string description = "") {
    Option *opt = add_option(name, callback, description, false);
    opt->set_custom_option("", 0);
    return opt;
}

Manually set value of an option

The command line options are parsed CLI11_PARSE(options, argc, argv). Is it possible to manually set the value of a single option to some value and still get validated?

"App:allow_extras(true)" calls are ignored when parsing ini files

When calling App:allow_extras(true) to allow for extra (undefined) arguments passed to CLI11, this call is ignored when the extra argument is located in an ini-file.

I am busy with more important things the coming few weeks but I am willing to look into solving this problem when I have the time. Probably early next month.

`excludes` is not symmetric in help text

When using

opt_a->excludes( opt_b );

the help text shows the message 'Excludes: ..." just for opt_a, but not for opt_b, although the behavior is of course symmetrical.

As a workaround, adding opt_b->excludes( opt_a ); does the trick. But maybe this should not be necessary.

User defined config file

When using add_config option and passing a custom filename for the config file it is not loaded.
app.add_config("-c,--config", "config.ini", "Read config from an ini file", false);
>> app --config custom_config.ini

Ini parsing code in App.hpp should be something like this to make it work.

        // Process an INI file
        if(config_ptr_ != nullptr && config_name_ != "") {
            auto user_config = config_ptr_->results();
            
            // take user passed filename into account
            if( config_ptr_->count() ) {
                config_name_ = config_ptr_->results()[0];
            }
            
            try {
                std::vector<detail::ini_ret_t> values = detail::parse_ini(config_name_);
                while(!values.empty()) {
                    if(!_parse_ini(values)) {
                        throw ExtrasINIError(values.back().fullname);
                    }
                }
            } catch(const FileError &) {
                if(config_required_)
                    throw;
            }
        }

"is required is required" is printed if a subcommand parameter is not provided

Hi guys, I have this undesired behaviour when I try to parse a subcommand option. If a subcommand parameter is needed and it is not provided then CLI11 throw two times the string message "is required" after the parameter_flag that is required.

Example:
The executable should be running in this way:
./executable subcommand --paramter_flag <some_input_directory>
So, if some run mistakenly:
./executable subcommand

the following error appears:
#--paramter_flag is required is require

Thanks in advance,

Taihú

[Bug] Parser assumes positional arguments which happen to match subcommand names are subcommands

Consider this demo program:

#include <string>
#include <iostream>

#include "CLI11.hpp"

using std::string;
using std::cout;
using std::endl;

int main(int argc, char** argv) {
    CLI::App app{"Buggy demo app"};
    app.require_subcommand();

    auto foo = app.add_subcommand("foo", "Foo Description", false);
    auto bar = app.add_subcommand("bar", "Bar Description", false);
    string baz;
    bar->add_option("baz", baz, "Baz Description", true)->required();

    foo->set_callback([] {
        cout << "Bad" << endl;
    });
    bar->set_callback([&baz] {
        cout << "Good; baz was " << baz << endl;
    });

    try {
        app.parse(argc, argv);
    } catch (CLI::ParseError& e) {
        return app.exit(e);
    }
}

The app has two subcommands, foo and bar, where bar takes a required positional argument named baz. Suppose I want to run bar with baz set to "qux":

$ ./demo bar qux
Good; baz was qux

This works great! But suppose instead I want baz set to "foo":

$ ./demo bar foo
ERROR: RequiredError: baz
Foo Description
Usage: ./a.out foo

The parser has seen "foo" and given up parsing arguments for bar, but it instead context switched to the foo subcommand.

There might be a use case for running multiple subcommands in the same invocation of the program, but the behavior we're seeing here is clearly incorrect, especially since there is no apparent way to fix it: adding app.fallthrough(false) and/or bar->fallthrough(false) do not solve the issue.

The only workaround I see so far is to convert baz to a named argument:

    bar->add_option("--baz", baz, "Baz Description", true)->required();

This allows me to slip it by the parser correctly:

$ ./demo bar --baz foo
Good; baz was foo

Finalize 1.3

Here are a few things that should be finished before the 1.3 release is ready:

  • Extras help message should be improved (simple print)
  • Check other help messages (simple print)
  • Check that -e number fails if number is missing (critical)
  • Try to move most string output in errors to error definitions (easier localization)
  • Revisit locking required(), remove checks from (most) individual lambdas, new error if wrong number given
  • Consider changing default for take_last; since git uses take_last it is probably a more common default: Added policies instead

Add an extra class `Help` or `HelpProvider`.

This would allow customization of all components of the help messages; things like localization would be possible.

I like the idea of adding a new class that takes responsibility for the help formatting; even with no changes, this would keep App and Option a bit shorter and cleaner, which is a good thing.

INI creation

Move config_to_str to a new class for Cleaner App code and similarity to Formatters.

Support for enumerations

I tried the following code to see whether CLI11 supports the use of enumerations in add_set and got a series of errors. Is the code wrong is support for enumerations planned/not going to be added?

#include <iostream>
#include <string>

#include <CLI/CLI.hpp>

enum Level : std::int32_t
{
  High,
  Medium,
  Low
};

int main(int argc, char* argv[])
{
  CLI::App app{"App description"};
  try
  {
    Level level;
    app.add_set("-l,--level", level, {Level::High, Level::Medium, Level::Low}, "Level settings");
    app.parse(argc, argv);
  }
  catch (CLI::Error const& e)
  {
    app.exit(e);
  }
  return EXIT_SUCCESS;
}

Errors:

1>f:\github\cli11\include\cli\typetools.hpp(108): error C2440: '=': cannot convert from 'std::string' to 'Level'
1>f:\github\cli11\include\cli\typetools.hpp(108): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>f:\github\cli11\include\cli\app.hpp(326): note: see reference to function template instantiation 'bool CLI::detail::lexical_cast<T,0>(std::string,T &)' being compiled
1>        with
1>        [
1>            T=Level
1>        ]
1>f:\code\visual studio 2017\projects\cmdapp\cmdapp\main.cpp(20): note: see reference to function template instantiation 'CLI::Option *CLI::App::add_set<Level>(std::string,T &,std::set<Level,std::less<_Kty>,std::allocator<_Kty>>,std::string,bool)' being compiled
1>        with
1>        [
1>            T=Level,
1>            _Kty=Level
1>        ]
1>Done building project "cmdapp.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

lexical_cast for integers doesn't check if the string is fully consumed

CLI11 doesn't check for invalid strings like 100500blabla and happily consumes it.

I guess lexical_cast for integers should look like this:

/// Integers / enums
template <typename T,
          enable_if_t<std::is_integral<T>::value || std::is_enum<T>::value, detail::enabler> = detail::dummy>
bool lexical_cast(std::string input, T &output) {
    try {
        size_t n = 0;
        output = static_cast<T>(std::stoll(input, &n, 0)); // note: this way conversion works for HEX too
        return (n == input.size());
    } catch(const std::invalid_argument &) {
        return false;
    } catch(const std::out_of_range &) {
        return false;
    }
}

/// Floats
template <typename T, enable_if_t<std::is_floating_point<T>::value, detail::enabler> = detail::dummy>
bool lexical_cast(std::string input, T &output) {
    try {
        size_t n = 0;
        output = static_cast<T>(std::stold(input, &n));
        return n == input.size();
    } catch(const std::invalid_argument &) {
        return false;
    } catch(const std::out_of_range &) {
        return false;
    }
}

conversion error on multiple occurences of a non-vector option

If I use a std::string as an option (say, "-o") and the option appears multiple times ("-o foo -o bar"), there is a conversion error thrown, because the lambda returns false (it checks if size of result is 1).
Some observations:

  • The exception messages are not very user friendly. They are too generic, not localized, etc.
  • The exception type is the same for all options, so it's not easy to customize the message.
  • Due to the simplicity of many getopt-based implementations, usually tools take the last-writer-wins strategy when options are repeated (for example, "cp -S .bak -S .orig" will choose ".orig" for backup copies).
  • It is possible to implement such a strategy with a custom lambda function (that's nice!), but it's extra work and not immediately obvious.
  • Another strategy is to always use vectors, and do the error handling / value folding post-parsing (barf!).

Simple things should be simple, and if only one "-x foo" should be allowed, then giving a diagnostics like "only one -x option allowed" should be made simple by the library. It doesn't need to be automatic, it's sufficient if I can catch the error and output an appropriate message.
In case that's not easy to do, maybe the last-writer-wins strategy for non-vectors is the better default strategy, because it can not fail by definition.
CLI11 shows some excellent design taste, and I don't want to blemish it with a specific proposal how to fix this. The main point of this ticket is to share one of the few frustrations I have with the library as a new user. Thanks!

Hard to read custom options

Hi,

I current experiment a little with CLI11 and tried to read a std::pair<int, float> as a custom option.
All works fine. I used set_custom_option("INT FLOAT", 2), to enforce that there are exactly two arguments and to reflect the types I expect. But the help text that is generated looks weird.

-p INT FLOAT x 2      Some text

It gets even worst if I also print default values (depends a little on how you stringify a pair).

-p INT FLOAT=(1, 0.00000) x 2      Some text

I looked a while into the documentation and what methods are provided, but I couldn't find a solution to this.

So I took a quick look into the code and I added a quick fix for this. See the commit 1561a1a in my fork. If you are interested I can send a Pull Request.

But please let me know if I just didn't saw the right options.

Best,
Alex

Cleanup CMake

A few thoughts on the CMakeLists:

  • Use find Python to get the python command or disable the generation if Python not found
  • Hide BUILD_G* from cmake -LH ..
  • Work on default Python on most systems

C++20 concepts compatibility issue

Concepts are coming to C++20 and one of the changes included is making requires a keyword. Assuming no major revisions to that, CLI11 will have to be updated to rename conflicting methods.

There's no rush on fixing this; I'm using CLI11 in a local project that has -fconcepts turned on and have worked around it by #define-ing the method to a new name. This issue is mostly a heads up so you can start thinking about it.

Option variables are not populated when the -h flag is provided

Consider the following code:

#include "CLI11.hpp"
int main(int argc, char **argv) {
  CLI::App test;
  std::string some_option;
  test.add_option("-a", some_option, "Some description");
  try {
    test.parse(argc, argv);
  } catch (const CLI::Error &e) {
    std::cout << "Option string:" << some_option << std::endl;
    return test.exit(e);
  }
  std::cout << "Option string:" << some_option << std::endl;
  return 0;
}

When passing -h to the application, the some_option variable is empty regardless of if -a has been used. This makes it hard to deal with some use cases where you want to handle partially incorrect command line arguments or context based help.

Options without separating space consume positional arguments

Consider this application:

    std::vector<std::string> options;
    std::string foo, bar;
    CLI::App app{"Test"};
    app.add_option("-O", options);
    app.add_option("foo", foo)->required();
    app.add_option("bar", bar)->required();
    CLI11_PARSE(app, argc, argv);

Following fails: ./test -OTest param1 param2
Error: bar is required

Following works: ./test -O Test param1 param2

It should either warn that -OTest is not a proper option instead of consuming param1 or accept -OTest with value Test.

Help for fallthrough options in subcommands

I am using app.fallthrough() to define common options at the topmost level. While this works perfectly, it seems that the help message does not include those "inherited" options.

For example, see below the output for my tool is currently. What I'd expect is that the general options are repeated for the subcommand as well.

> slate --help
SLATE command line interface
Usage: ./slate [OPTIONS] SUBCOMMAND

Options:
  -h,--help                   Print this help message and exit

General:
  --output TEXT               Output format. Must be default or json.
  --debug                     Prints extra info to debug the commandline.

Subcommands:
  app                         Manage SLATE applications
  version                     Outputs the version of the command-line
  vo                          Manage SLATE vos
  cluster                     Manage SLATE clusters


> slate app --help
Manage SLATE applications
Usage: ./slate app [OPTIONS] SUBCOMMAND

Options:
  -h,--help                   Print this help message and exit
  --vo TEXT (REQUIRED)        The VO for which to install the application
  --cluster TEXT (REQUIRED)   The cluster in which to install the application

Subcommands:
  install                     Install an application
  list                        Lists installed applications
  delete                      Delete an application

Am I missing something?

Requiring one Option or another, not both

Hi, is there some way to require that one of { "--option1", "--option2" } is present, but not necessarily both? I looked at the documentation and examples, and couldn't figure out if this is possible. Do I need a custom callback?

By the way, excellent work on this library! Something like this was sorely needed in C++.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.