A simple to use, composable, command line parser for C++ 11 and beyond

Lyra

A simple to use, composing, header only, command line arguments parser for C++ 11 and beyond.

Obtain

GitHub All Releases

License

Boost Software License 1.0

Standards

Pitchfork Layout C\\ 11 C\\ 14 C\\ 17 C\\ 2a

Stats

GitHub code size in bytes GitHub issues GitHub stars

Tests

Azure DevOps Azure DevOps AppVeyor AppVeyor

License

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Features

  • Header only with no external dependencies (except the std library).

  • Define your interface once to get parsing, type conversions and usage strings with no redundancy.

  • Composing. Each opt or arg is an independent parser. Combine these to produce a composite parser — this can be done in stages across multiple function calls — or even projects.

  • Bind parsers directly to variables that will receive the results of the parse — no intermediate dictionaries to worry about.

  • Or can also bind parsers to lambdas for more custom handling.

  • Deduces types from bound variables or lambdas and performs type conversions (via ostream <<), with error handling, behind the scenes.

  • Bind parsers to vectors for args that can have multiple values.

  • Uses result types for error propagation, rather than exceptions (doesn’t yet build with exceptions disabled, but that will be coming later)

  • Models POSIX standards for short and long opt behavior.

  • Customizable option syntax.

  • Specify cardinality of arg-s from one to many.

  • Limit option values to a specified set of values.

  • Recursive argument groups with callback for detection. This allows for easy and generic sub-command specifications.

Using

To use, just #include <lyra/lyra.hpp>

A parser for a single option can be created like this:

int width = 0;
auto cli = lyra::cli()
    | lyra::opt( width, "width" )
        ["-w"]["--width"]
        ("How wide should it be?");

You can use this parser directly like this:

auto result = cli.parse( { argc, argv } );
if ( !result )
{
	std::cerr << "Error in command line: " << result.errorMessage() << std::endl;
	exit(1);
}

// Everything was ok, width will have a value if supplied on command line.

Note that exceptions are not used for error handling.

You can combine parsers by composing with |, like this:

int width = 0;
std::string name;
bool doIt = false;
std::string command;
auto cli
    = lyra::opt( width, "width" )
        ["-w"]["--width"]
        ("How wide should it be?")
    | lyra::opt( name, "name" )
        ["-n"]["--name"]
        ("By what name should I be known")
    | lyra::opt( doIt )
        ["-d"]["--doit"]
        ("Do the thing" )
    | lyra::arg( command, "command" )
        ("which command to run");

opt specifies options that start with a short dash (-) or long dash (--). Options can be argument taking (such as -w 42), in which case the opt takes a second argument — a hint, or they are pure flags (such as -d), in which case the opt has only one argument — which must be a boolean. The option names are provided in one or more sets of square brackets, and a description string can be provided in parentheses. The first argument to an opt is any variable, local, global member, of any type that can be converted from a string using std::ostream.

arg specifies arguments that are not tied to options, and so have no square bracket names. They otherwise work just like opt.

A usage string can be obtained by inserting the parser into a stream. The usage string is built from the information supplied.

As a convenience, the standard help options (-h, --help and -?) can be specified using the help parser, which just takes a boolean to bind to.

More

There is a single-header version that is generated from the source files. You can find it at data/single_include/lyra/lyra.hpp. Some caveats for it:

  • It’s not the preferred method of using the library.

  • It’s not thoroughly tested.

  • It’s intended for use cases like Compiler Explorer. Where it allows for immediate experimentation.

  • Support for it will not be a priority.

  • Hence prefer to use the regular multi-file sources in your projects.

For more information and documentation see the web site.

Owner
Build Frameworks Group
We create high quality frameworks and tools for build systems.
Build Frameworks Group
Comments
  • Surprising behavior of lyra::group, is it a bug?

    Surprising behavior of lyra::group, is it a bug?

    Hi, I'm in the process of migrating my project to Lyra, and I've encountered some surprising behavior of the "group" feature where I'm not sure if it is intentional.

    Specifically, it seems that as soon as I specify an option belonging to a group, the very next subsequently given option will always be treated as a positional argument even if it should instead be matched by another option. This is easiest to explain by example. Consider the following program (ready for copy & paste and build):

    #include <lyra/lyra.hpp>
    
    #include <iostream>
    #include <string>
    
    int main(int argc, char** argv) {
      bool someFlag = false;
      std::string requiredArgInGroup;
      std::string optionalArgInGroup;
      std::string positionalArg;
    
      auto optionsParser =
        lyra::opt(someFlag).name("-f")
        | lyra::group([](const lyra::group&){})
          .add_argument(
            lyra::opt(requiredArgInGroup, "req")
            .name("--req-in-group")
            .required())
          .add_argument(
            lyra::opt(optionalArgInGroup, "opt")
            .name("--opt-in-group"))
        | lyra::arg(positionalArg, "positional");
    
      if (auto result = optionsParser.parse({argc, argv})) {
        std::cout << std::boolalpha << someFlag << ", " << positionalArg << '\n';
      } else {
        std::cout << result.errorMessage() << '\n';
      }
    }
    

    Expected behavior

    If I invoke the program and specify the -f option after --req-in-group, I would expect it to result in setting someFlag, and a subsequent positional argument to be assigned to positionalArg.

    Expected output:

    $ ./a.out --req-in-group test1 -f test2
    true, test2
    

    Expected output without positional arg:

    $ ./a.out --req-in-group test1 -f
    true, 
    

    Actual behavior

    What actually happens is that -f is assigned to positionalArg:

    $ ./a.out --req-in-group test1 -f
    false, -f
    

    And adding a subsequent positional argument (i.e. --req-in-group test1 -f test2) results in a parse error (unrecognized token: test2).

    Interestingly, specifying the positional argument first after the group argument results in the behavior I would expect:

    $ ./a.out --req-in-group test1 test2 -f
    true, test2
    

    This seems like a bug to me, but maybe I'm misunderstanding something about how groups work? Any clarification would be appreciated 🙂 I really like the groups feature and would love to use it!

  • Output formatting differs from clara

    Output formatting differs from clara

    I just started a new project using Lyra (after heeding the warning on the Clara repo, thanks for that!)

    Under clara my help cam out like this:

    usage:
      pt_three_ways <output> options
    
    where options are:
      -w, --width <width>           output image width
      -h, --height <height>         output image height
      --max-cpus <#cpus>            maximum number of CPUs to use (0 for all)
      --spp <samples>               number of samples per pixel
    

    etc

    In a new project using Lyra 1.1, the formatting of the help is very different:

    Usage:
      ticks2hdf5 [-?|-h|--help] <output> <input...>
    
    Options, arguments:
      -?, -h, --help
    
      Display usage information.
    
      <output>
    
      HDF5 output filename
    
      <input...>
    
      Input files, in gzip compressed CSV format
    

    Am I missing a changed configuration option somewhere? How might I get the nice formatting back?

  • cmake install option

    cmake install option

    I've added a simple cmake trick to detect if Lyra is "built" and installed directly or if it is used via the add_subdirectory directive.

    This allow the users of the latter not being polluted by Lyra install targets. It is also compatible with existing procedure as it automatically turns the install targets ON when used directly.

    Finally even when using it as a subdir, you can override that behaviour and still install Lyra by doing the following:

    set(LYRA_INSTALL ON CACHE BOOL "please install lyra anyway" FORCE)
    add_subdirectory(path/to/Lyra)
    

    Hope it is useful for others :)

  • Add CMake Support

    Add CMake Support

    This PR is intended to fix issue #29. It adds a installable target for CMake and makes it possible to use lyra by the standard CMake procedure of target_link_libraries(yourlib PUBLIC BFG::Lyra).

  • cli_parser::parse overwrites exe_name

    cli_parser::parse overwrites exe_name

    when you call cli_parser::parse(), whatever value you set via lyra::exe_name is lost and replaced with the default executable name. If you constructed lyra::exe_name with a string in the stack, that string is also overwritten.

    An exemple:

    // my executable is called "myapp"
    bool show_help; std::string command;
    auto cli = lyra::cli_parser()
        | lyra::help(show_help)
        | lyra::arg(command, "command")("Command to perform.").required();
    
    std::string program_name = "different";
    cli.add_argument(lyra::exe_name(program_name)); // changes the name to "different"
    
    auto result = cli.parse({argc, argv});
    // exeName is is back to "myapp" at this point
    // the value of 'program_name' silently changes to "myapp"  😱 
    
    if (show_help) {
        // won't have the expected name
        std::cout << cli;
        exit(EXIT_SUCCESS);
    }
    
  • Help not working in sub-command example

    Help not working in sub-command example

    I was trying to get lyra::help to work with the add_argument interface and the sub-command example has just that. However, it looks like --help is not working in this case. I got it to work by moving the cli.parse invocation before the check for show_help - I believe that it's the right fix (parsing the command line for --help before checking the corresponding flag makes sense to me) but it's my first time trying Lyra so I can't really be sure.

    I believe that it was introduced when implementing the fix for #16.

  • optional option with container

    optional option with container

    It might be handy to be able to call a program with an [0;n] option. So you might be able to do the following: myprog -a foo -a bar stuff.txt or myprog stuff.txt

    In the current version of Lyra (using opt(std::vector, "foo")) I have two cases:

    • Default (seems to be required): [1; n] option when calling the program (using required(0) doesn't change that behavior)
    • .optional(): [0;1] option when calling the program.
  • Unknown options are silently ignored and mixed with positional arguments

    Unknown options are silently ignored and mixed with positional arguments

    When there are options as well as positional arguments, some of which may be optional, there is a problem with unknown options. Consider this repro case:

    int foo = 0;
    std::string positional;
    std::string optional = "default";
    
    auto cli = lyra::cli();
    cli |= lyra::opt(foo, "foo")["--foo"];
    cli |= lyra::arg(positional, "positional");
    cli |= lyra::arg(optional, "optional").optional();
    
    auto result = cli.parse(lyra::args({ argv[0], "--foo", "1", "--bar", "a" }));
    if (!result) {
        std::cerr << "Error in command line: " << result.errorMessage() << std::endl;
        std::cerr << cli << std::endl;
        return EXIT_FAILURE;
    }
    
    std::cout << "foo = " << foo << std::endl;
    std::cout << "positional = " << positional << std::endl;
    std::cout << "optional = " << optional << std::endl;
    

    which leads to this output:

    foo = 1
    positional = --bar
    optional = a
    

    This is a problem, because --bar as is not reported as unknown/invalid option, but passed to the next positional argument. It is pretty unlikely that the user intended to use --bar as a positional argument -- most likely they made a typo or another mistake and need to read the help page.

  • Named args with parameters' args don't appear in usage

    Named args with parameters' args don't appear in usage

    In the config:

    #include <lyra/lyra.hpp>
    #include <string>
    
    int main(int argc, const char *argv[]) {
      std::string named_required;
      std::string optional;
      auto cli = lyra::opt(named_required,
                      "required-arg")["--required"]("You must supply this arg")
                .required() |
            lyra::arg(optional, "optional")("This is an optional arg");
    
        std::cout << cli << "\n";
    }
    

    The output is:

    USAGE:
      <executable> --required [<optional>]
    
    OPTIONS, ARGUMENTS:
      --required <required-arg>
                              You must supply this arg
      <optional>              This is an optional arg
    

    The --required in the USAGE: line does not refer to the required parameter name. I'd expect to see:

    USAGE:
      <executable> --required <required-arg> [<optional>]
    
    OPTIONS, ARGUMENTS:
      --required <required-arg>
                              You must supply this arg
      <optional>              This is an optional arg
    
  • Single header?

    Single header?

    Clara was a single header parser. That options seems to have been removed. Any chance it could be re-added? It is really handy to be able to drop in a single file to an app.

  • Harmless but annoying -Woverloaded-virtual warnings from gcc

    Harmless but annoying -Woverloaded-virtual warnings from gcc

    Compiling the header with g++ -Wall results in several warnings:

    In file included from lyra/include/lyra/arg.hpp:10,
                     from lyra/include/lyra/lyra.hpp:12,
                     from main.cpp:31:
    lyra/include/lyra/parser.hpp:165:23: warning: ‘virtual lyra::parse_result lyra::parser::parse(const string&, const lyra::detail::token_iterator&, const lyra::parser_customization&) const’ was hidden [-Woverloaded-virtual]
      virtual parse_result parse(std::string const & exe_name,
                           ^~~~~
    In file included from lyra/include/lyra/arguments.hpp:10,
                     from lyra/include/lyra/lyra.hpp:13,
                     from main.cpp:31:
    lyra/include/lyra/exe_name.hpp:45:23: warning:   by ‘virtual lyra::parse_result lyra::exe_name::parse(const lyra::detail::token_iterator&, const lyra::parser_customization&) const’ [-Woverloaded-virtual]
      virtual parse_result parse(
                           ^~~~~
    In file included from lyra/include/lyra/arg.hpp:10,
                     from lyra/include/lyra/lyra.hpp:12,
                     from main.cpp:31:
    lyra/include/lyra/parser.hpp:165:23: warning: ‘virtual lyra::parse_result lyra::parser::parse(const string&, const lyra::detail::token_iterator&, const lyra::parser_customization&) const’ was hidden [-Woverloaded-virtual]
      virtual parse_result parse(std::string const & exe_name,
                           ^~~~~
    In file included from lyra/include/lyra/lyra.hpp:13,
                     from main.cpp:31:
    lyra/include/lyra/arguments.hpp:146:15: warning:   by ‘virtual lyra::parse_result lyra::arguments::parse(const lyra::detail::token_iterator&, const lyra::parser_customization&) const’ [-Woverloaded-virtual]
      parse_result parse(detail::token_iterator const & tokens,
                   ^~~~~
    

    Getting rid of them seems to be relatively simple using the usual trick of making parse() itself non-virtual and adding pure virtual do_parse(), but maybe it would be even better to avoid having two overloaded parse() versions just to use it in cli? It looks like this could be solved by just setting m_exeName in the "normal" parse() overload, but maybe I'm missing something here, as I've just started using Lyra and don't know it at all.

    I could propose a PR doing this if you'd be interested.

  • Crash in lyra::args::args with zero arguments

    Crash in lyra::args::args with zero arguments

    While unusual, this can happen e.g. when execve invokes main without arguments and the calling program doesn't perform a check before calling lyra::args::args.

  • When building with -Wshadow on GCC there are many shadowing warnings.

    When building with -Wshadow on GCC there are many shadowing warnings.

    As Lyra is a header-only library it is affected by project build flags so there is no reasonable way for a project to work around this short of disabling the flag.

    Here is a sanitised log from my project:

    In file included from [PATH]/main.cpp:39:
    [PATH]/lyra.hpp: In constructor ‘lyra::detail::print::print(const char*)’:
    [PATH]/lyra.hpp:55:3: warning: declaration of ‘scope’ shadows a member of ‘lyra::detail::print’ [-Wshadow]
       55 |   : scope(scope)
          |   ^
    [PATH]/lyra.hpp:84:15: note: shadowed declaration is here
       84 |  const char * scope;
          |               ^~~~~
    [PATH]/lyra.hpp: In constructor ‘lyra::detail::print::print(const char*)’:
    [PATH]/lyra.hpp:59:2: warning: declaration of ‘scope’ shadows a member of ‘lyra::detail::print’ [-Wshadow]
       59 |  }
          |  ^
    [PATH]/lyra.hpp:84:15: note: shadowed declaration is here
       84 |  const char * scope;
          |               ^~~~~
    [PATH]/lyra.hpp: In constructor ‘lyra::detail::print::print(const char*)’:
    [PATH]/lyra.hpp:59:2: warning: declaration of ‘scope’ shadows a member of ‘lyra::detail::print’ [-Wshadow]
       59 |  }
          |  ^
    [PATH]/lyra.hpp:84:15: note: shadowed declaration is here
       84 |  const char * scope;
          |               ^~~~~
    In file included from [PATH]/main.cpp:39:
    [PATH]/lyra.hpp: In constructor ‘lyra::args::args(std::initializer_list<std::__cxx11::basic_string<char> >)’:
    [PATH]/lyra.hpp:136:3: warning: declaration of ‘args’ shadows a member of ‘lyra::args’ [-Wshadow]
      136 |   : m_exeName(*args.begin())
          |   ^
    [PATH]/lyra.hpp:128:1: note: shadowed declaration is here
      128 | {
          | ^
    [PATH]/lyra.hpp: In constructor ‘lyra::args::args(std::initializer_list<std::__cxx11::basic_string<char> >)’:
    [PATH]/lyra.hpp:138:3: warning: declaration of ‘args’ shadows a member of ‘lyra::args’ [-Wshadow]
      138 |  {}
          |   ^
    [PATH]/lyra.hpp:128:1: note: shadowed declaration is here
      128 | {
          | ^
    [PATH]/lyra.hpp: In constructor ‘lyra::args::args(std::initializer_list<std::__cxx11::basic_string<char> >)’:
    [PATH]/lyra.hpp:138:3: warning: declaration of ‘args’ shadows a member of ‘lyra::args’ [-Wshadow]
      138 |  {}
          |   ^
    [PATH]/lyra.hpp:128:1: note: shadowed declaration is here
      128 | {
          | ^
    	BUILD:		logger.cpp
    In file included from [PATH]/main.cpp:39:
    [PATH]/lyra.hpp: In constructor ‘lyra::detail::choices_check<Lambda>::choices_check(const Lambda&)’:
    [PATH]/lyra.hpp:984:3: warning: declaration of ‘checker’ shadows a member of ‘lyra::detail::choices_check<Lambda>’ [-Wshadow]
      984 |   : checker(checker)
          |   ^
    [PATH]/lyra.hpp:980:9: note: shadowed declaration is here
      980 |  Lambda checker;
          |         ^~~~~~~
    [PATH]/lyra.hpp: In constructor ‘lyra::option_style::option_style(std::string&&, std::string&&, std::size_t, std::string&&, std::size_t)’:
    [PATH]/lyra.hpp:1063:3: warning: declaration of ‘short_option_size’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1063 |   : value_delimiters(std::move(value_delimiters))
          |   ^
    [PATH]/lyra.hpp:1055:14: note: shadowed declaration is here
     1055 |  std::size_t short_option_size = 0;
          |              ^~~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1063:3: warning: declaration of ‘short_option_prefix’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1063 |   : value_delimiters(std::move(value_delimiters))
          |   ^
    [PATH]/lyra.hpp:1054:14: note: shadowed declaration is here
     1054 |  std::string short_option_prefix;
          |              ^~~~~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1063:3: warning: declaration of ‘long_option_size’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1063 |   : value_delimiters(std::move(value_delimiters))
          |   ^
    [PATH]/lyra.hpp:1053:14: note: shadowed declaration is here
     1053 |  std::size_t long_option_size = 0;
          |              ^~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1063:3: warning: declaration of ‘long_option_prefix’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1063 |   : value_delimiters(std::move(value_delimiters))
          |   ^
    [PATH]/lyra.hpp:1052:14: note: shadowed declaration is here
     1052 |  std::string long_option_prefix;
          |              ^~~~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1063:3: warning: declaration of ‘value_delimiters’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1063 |   : value_delimiters(std::move(value_delimiters))
          |   ^
    [PATH]/lyra.hpp:1051:14: note: shadowed declaration is here
     1051 |  std::string value_delimiters;
          |              ^~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp: In constructor ‘lyra::option_style::option_style(std::string&&, std::string&&, std::size_t, std::string&&, std::size_t)’:
    [PATH]/lyra.hpp:1068:3: warning: declaration of ‘short_option_size’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1068 |  {}
          |   ^
    [PATH]/lyra.hpp:1055:14: note: shadowed declaration is here
     1055 |  std::size_t short_option_size = 0;
          |              ^~~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1068:3: warning: declaration of ‘short_option_prefix’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1068 |  {}
          |   ^
    [PATH]/lyra.hpp:1054:14: note: shadowed declaration is here
     1054 |  std::string short_option_prefix;
          |              ^~~~~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1068:3: warning: declaration of ‘long_option_size’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1068 |  {}
          |   ^
    [PATH]/lyra.hpp:1053:14: note: shadowed declaration is here
     1053 |  std::size_t long_option_size = 0;
          |              ^~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1068:3: warning: declaration of ‘long_option_prefix’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1068 |  {}
          |   ^
    [PATH]/lyra.hpp:1052:14: note: shadowed declaration is here
     1052 |  std::string long_option_prefix;
          |              ^~~~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1068:3: warning: declaration of ‘value_delimiters’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1068 |  {}
          |   ^
    [PATH]/lyra.hpp:1051:14: note: shadowed declaration is here
     1051 |  std::string value_delimiters;
          |              ^~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp: In constructor ‘lyra::option_style::option_style(std::string&&, std::string&&, std::size_t, std::string&&, std::size_t)’:
    [PATH]/lyra.hpp:1068:3: warning: declaration of ‘short_option_size’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1068 |  {}
          |   ^
    [PATH]/lyra.hpp:1055:14: note: shadowed declaration is here
     1055 |  std::size_t short_option_size = 0;
          |              ^~~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1068:3: warning: declaration of ‘short_option_prefix’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1068 |  {}
          |   ^
    [PATH]/lyra.hpp:1054:14: note: shadowed declaration is here
     1054 |  std::string short_option_prefix;
          |              ^~~~~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1068:3: warning: declaration of ‘long_option_size’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1068 |  {}
          |   ^
    [PATH]/lyra.hpp:1053:14: note: shadowed declaration is here
     1053 |  std::size_t long_option_size = 0;
          |              ^~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1068:3: warning: declaration of ‘long_option_prefix’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1068 |  {}
          |   ^
    [PATH]/lyra.hpp:1052:14: note: shadowed declaration is here
     1052 |  std::string long_option_prefix;
          |              ^~~~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp:1068:3: warning: declaration of ‘value_delimiters’ shadows a member of ‘lyra::option_style’ [-Wshadow]
     1068 |  {}
          |   ^
    [PATH]/lyra.hpp:1051:14: note: shadowed declaration is here
     1051 |  std::string value_delimiters;
          |              ^~~~~~~~~~~~~~~~
    [PATH]/lyra.hpp: In member function ‘virtual lyra::parse_result lyra::arg::parse(const lyra::detail::token_iterator&, const lyra::option_style&) const’:
    [PATH]/lyra.hpp:2182:8: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     2182 |   auto result = valueRef->setValue(token.name);
          |        ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp: In member function ‘virtual lyra::result lyra::arguments::validate() const’:
    [PATH]/lyra.hpp:2471:9: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     2471 |    auto result = p->validate();
          |         ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp: In member function ‘lyra::parse_result lyra::arguments::parse_any(const lyra::detail::token_iterator&, const lyra::option_style&) const’:
    [PATH]/lyra.hpp:2508:8: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     2508 |   auto result = parse_result::ok(
          |        ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp: In member function ‘lyra::parse_result lyra::arguments::parse_sequence(const lyra::detail::token_iterator&, const lyra::option_style&) const’:
    [PATH]/lyra.hpp:2589:8: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     2589 |   auto result = parse_result::ok(
          |        ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp: In member function ‘virtual const lyra::parser* lyra::arguments::get_named(const string&) const’:
    [PATH]/lyra.hpp:2654:19: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     2654 |    const parser * result = p->get_named(n);
          |                   ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp: In member function ‘virtual lyra::parse_result lyra::group::parse(const lyra::detail::token_iterator&, const lyra::option_style&) const’:
    [PATH]/lyra.hpp:2926:16: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     2926 |   parse_result result = arguments::parse(tokens, style);
          |                ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp: In member function ‘lyra::cli::value_result::operator T() const’:
    [PATH]/lyra.hpp:3157:43: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     3157 |    typename detail::remove_cvref<T>::type result {};
          |                                           ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp: In member function ‘lyra::cli::value_result::operator std::vector<T>() const’:
    [PATH]/lyra.hpp:3168:19: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     3168 |    std::vector<T> result;
          |                   ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp: In member function ‘lyra::parse_result lyra::cli::parse(const lyra::args&, const lyra::option_style&) const’:
    [PATH]/lyra.hpp:3399:15: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     3399 |  parse_result result = parse(args_tokens, style);
          |               ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp: In member function ‘lyra::literal& lyra::literal::operator()(const string&)’:
    [PATH]/lyra.hpp:3589:69: warning: declaration of ‘description’ shadows a member of ‘lyra::literal’ [-Wshadow]
     3589 | inline literal & literal::operator()(std::string const & description)
          |                                                                     ^
    [PATH]/lyra.hpp:3535:14: note: shadowed declaration is here
     3535 |  std::string description;
          |              ^~~~~~~~~~~
    [PATH]/lyra.hpp: In member function ‘virtual std::string lyra::opt::get_usage_text(const lyra::option_style&) const’:
    [PATH]/lyra.hpp:3825:15: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     3825 |   std::string result;
          |               ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp: In member function ‘virtual lyra::parser::help_text lyra::opt::get_help_text(const lyra::option_style&) const’:
    [PATH]/lyra.hpp:3839:21: warning: declaration of ‘opt’ shadows a member of ‘lyra::opt’ [-Wshadow]
     3839 |   for (auto const & opt : opt_names)
          |                     ^~~
    [PATH]/lyra.hpp:3773:1: note: shadowed declaration is here
     3773 | {
          | ^
    [PATH]/lyra.hpp: In member function ‘virtual lyra::parse_result lyra::opt::parse(const lyra::detail::token_iterator&, const lyra::option_style&) const’:
    [PATH]/lyra.hpp:3886:11: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     3886 |      auto result = flagRef->setFlag(true);
          |           ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp:3910:11: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     3910 |      auto result = valueRef->setValue(argToken.name);
          |           ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    [PATH]/lyra.hpp: In member function ‘lyra::main& lyra::main::operator()(const T&)’:
    [PATH]/lyra.hpp:4273:41: warning: declaration of ‘parser’ shadows a member of ‘lyra::main’ [-Wshadow]
     4273 | main & main::operator()(const T & parser)
          |                                         ^
    [PATH]/lyra.hpp:1582:1: note: shadowed declaration is here
     1582 | {
          | ^
    [PATH]/lyra.hpp: In member function ‘lyra::main& lyra::main::add_argument(const T&)’:
    [PATH]/lyra.hpp:4279:43: warning: declaration of ‘parser’ shadows a member of ‘lyra::main’ [-Wshadow]
     4279 | main & main::add_argument(const T & parser)
          |                                           ^
    [PATH]/lyra.hpp:1582:1: note: shadowed declaration is here
     1582 | {
          | ^
    [PATH]/lyra.hpp: In member function ‘lyra::main& lyra::main::operator|=(const T&)’:
    [PATH]/lyra.hpp:4285:41: warning: declaration of ‘parser’ shadows a member of ‘lyra::main’ [-Wshadow]
     4285 | main & main::operator|=(const T & parser)
          |                                         ^
    [PATH]/lyra.hpp:1582:1: note: shadowed declaration is here
     1582 | {
          | ^
    [PATH]/lyra.hpp: In member function ‘int lyra::main::operator()(const lyra::args&, L)’:
    [PATH]/lyra.hpp:4391:7: warning: declaration of ‘result’ shadows a global declaration [-Wshadow]
     4391 |  auto result = cli::parse(argv);
          |       ^~~~~~
    [PATH]/lyra.hpp:603:7: note: shadowed declaration is here
      603 | using result = detail::basic_result<void>;
          |       ^~~~~~
    

    I'm using the single header version of 1.6.0 but this should still occur with the multi-header version.

  • lyra::group in

    lyra::group in "|" operator chain

    For lyra::group, I'd like to use the "|" operator chain way, but no example in the docs, and it seems that the callback passed into lyra::group isn't called.

    #include "lyra/lyra.hpp"
    
    #include "spdlog/fmt/fmt.h"
    #include "spdlog/fmt/ostr.h"
    
    int main(int argc, const char *argv[]) {
    
        bool show_help = false;
        auto name = std::string {};
        bool use_grade_id = false;
        int grade = 0;
        int id = 0;
    
        auto cli = lyra::help(show_help) | lyra::opt(name, "name")["-n"]["--name"].required()
                   | (lyra::group([&](const lyra::group &) {
                          use_grade_id = true;
                          fmt::print("{}\n", use_grade_id);
                      })
                      | lyra::opt(id, "id")["--id"].required()
                      | lyra::opt(grade, "grade")["--grade"].required());
    
        auto cli_result = cli.parse({argc, argv});
        if (!cli_result) {
            fmt::print(stderr, "Error in command line: {}\n{}", cli_result.message(), cli);
            return EXIT_FAILURE;
        }
    
        if (show_help) {
            fmt::print("{}\n", cli);
            return EXIT_SUCCESS;
        }
    
        fmt::print("name: {}\n", name);
        fmt::print("use_grade_id: {}\n", use_grade_id);
        fmt::print("grade: {}\n", grade);
        fmt::print("id: {}\n", id);
    
        return EXIT_SUCCESS;
    }
    

    Am I using it wrong? or is it a bug?

    Thanks!

  • ignore help of subcommands

    ignore help of subcommands

    I have sub-commands with own arguments and I see them if I do app foo --help

    but I don't want to see those when I type foo --help I only want to see that sub-command itself exists, is it currently possible to do?

  • Long text wrapping in the help output

    Long text wrapping in the help output

    The length of the "help" strings for options is not limited, but the implementation assumes that they are somewhat short, else the help output looks pretty ugly when it is wrapped in a terminal. For example (hard-wrapped manually to show the issue in HTML):

    ...
    
    OPTIONS, ARGUMENTS:
      -?, -h, --help
      --detect-features       Before mesh generation, detect sharp features and boundaries of the
    internal bounding polyhedron (and the potential internal polyhedron) and inserts them as features
    of the domain. Default value: 0.
      --features-angle-bound <SCALAR>
                              The maximum angle (in degrees) between the two normal vectors of adjacent
    triangles. For an edge of the polyhedron, if the angle between the two normal vectors of its
    incident facets is bigger than the given bound, then the edge is considered as a feature edge.
    Default value: 60.
      --edge-size <SCALAR>    A constant providing a uniform upper bound for the lengths of curve edges.
    This parameter has to be set to a positive value when 1-dimensional features protection is used.
    Default value: 1.
      --facet-angle <SCALAR>  A lower bound for the angles (in degrees) of the surface mesh facets.
    Default value: 25.
      --facet-size <SCALAR>   A constant describing a uniform upper-bound or for the radii of the
    surface Delaunay balls. Default value: 1.
      --facet-distance <SCALAR>
                              A constant describing a uniform upper bound for the distance between the
    facet circumcenter and the center of its surface Delaunay ball. Default value: 0.125.
    

    Instead, Lyra should do the wrapping and print something like this:

    OPTIONS, ARGUMENTS:
      -?, -h, --help
      --detect-features       Before mesh generation, detect sharp features and boundaries of the
                              internal bounding polyhedron (and the potential internal polyhedron) and
                              inserts them as features of the domain. Default value: 0.
      --features-angle-bound <SCALAR>
                              The maximum angle (in degrees) between the two normal vectors of adjacent
                              triangles. For an edge of the polyhedron, if the angle between the two
                              normal vectors of its incident facets is bigger than the given bound,
                              then the edge is considered as a feature edge.  Default value: 60.
      --edge-size <SCALAR>    A constant providing a uniform upper bound for the lengths of curve edges.
                              This parameter has to be set to a positive value when 1-dimensional
                              features protection is used.  Default value: 1.
      --facet-angle <SCALAR>  A lower bound for the angles (in degrees) of the surface mesh facets.
                              Default value: 25.
      --facet-size <SCALAR>   A constant describing a uniform upper-bound or for the radii of the
                              surface Delaunay balls. Default value: 1.
      --facet-distance <SCALAR>
                              A constant describing a uniform upper bound for the distance between the
                              facet circumcenter and the center of its surface Delaunay ball. Default
                              value: 0.125.
    
CLI11 is a command line parser for C++11 and beyond that provides a rich feature set with a simple and intuitive interface.
CLI11 is a command line parser for C++11 and beyond that provides a rich feature set with a simple and intuitive interface.

CLI11: Command line parser for C++11 What's new • Documentation • API Reference CLI11 is a command line parser for C++11 and beyond that provides a ri

Sep 16, 2022
Lightweight C++ command line option parser

Release versions Note that master is generally a work in progress, and you probably want to use a tagged release version. Version 3 breaking changes I

Sep 22, 2022
Tiny command-line parser for C / C++

tinyargs Another commandline argument parser for C / C++. This one is tiny, source only, and builds cleanly with -Wall -pedantic under C99 and C++11 o

Aug 22, 2022
led is a line-oriented text editor in command line
led is a line-oriented text editor in command line

led is a line-oriented text editor in command line. This editor is similar to the standard program on unix systems - GNU ed. But i'm not going to make an exact clone of that program, it's just a pet project.

Aug 28, 2022
easy to use, powerful & expressive command line argument parsing for modern C++ / single header / usage & doc generation

clipp - command line interfaces for modern C++ Easy to use, powerful and expressive command line argument handling for C++11/14/17 contained in a sing

Sep 23, 2022
Simple command line utilities for extracting data from Fallout 4 and 76 files

fo76utils Simple command line utilities for extracting data from Fallout 4 and 76 files. baunpack - list the contents of, or extract from .BA2 archive

Sep 13, 2022
Simple command line tool that processes image files using the FidelityFX Super Resolution (FSR) or Contrast Adaptive Sharpening (CAS) shader systems.

Simple command line tool that processes image files using the FidelityFX Super Resolution (FSR) or Contrast Adaptive Sharpening (CAS) shader systems.

Sep 4, 2022
Simple, command line based player toolkit for the Ironsworn tabletop RPG
Simple, command line based player toolkit for the Ironsworn tabletop RPG

isscrolls - Command line based player toolkit for the Ironsworn tabletop RPG isscrolls is a simple toolkit for players of the Ironsworn tabletop RPG.

Sep 9, 2022
A simple command line application in order to create new Code workspaces.

mkcws Summary A simple command line application in order to create new Code workspaces. License This project's license is GPL 2. The whole license tex

Apr 1, 2022
Simple command line tools to create/extract X4 .cat+.dat files

x4cat Simple command line tools to to create/extract X4 .cat+.dat files x4encat Usage: x4encat <archive name> Looks for a directory named <archive nam

Oct 31, 2021
Simple Driver loading command-line utility.

lddrv Simple Driver loading command-line utility. Command Line Load a driver: "lddrv.exe -operation create -binpath C:\Dev\TestDriver.sys -svcname Tes

Sep 8, 2022
udmp-parser: A Windows user minidump C++ parser library.
udmp-parser: A Windows user minidump C++ parser library.

udmp-parser: A Windows user minidump C++ parser library. This is a cross-platform (Windows / Linux / OSX / x86 / x64) C++ library that parses Windows

Aug 23, 2022
A single header C++ library for parsing command line arguments and options with minimal amount of code

Quick Arg Parser Tired of unwieldy tools like getopt or argp? Quick Arg Parser is a single header C++ library for parsing command line arguments

Aug 10, 2022
Aug 15, 2022
Rizin - UNIX-like reverse engineering framework and command-line toolset.
Rizin - UNIX-like reverse engineering framework and command-line toolset.

Rizin - UNIX-like reverse engineering framework and command-line toolset.

Sep 17, 2022
A command line tool for numerically computing Out-of-time-ordered correlations for N=4 supersymmetric Yang-Mills theory and Beta deformed N=4 SYM.

A command line tool to compute OTOC for N=4 supersymmetric Yang–Mills theory This is a command line tool to numerically compute Out-of-time-ordered co

Oct 16, 2021
C++ Library for pulling system and hardware information, without hitting the command line.

infoware C++ Library for pulling system and hardware information, without hitting the command line. Requirements No non-built-in ones by default. Some

Sep 17, 2022
EAMain provides a multi-platform entry point used for platforms that don't support console output, return codes and command-line arguments.

EAMain provides a multi-platform entry point used for platforms that don't support console output, return codes and command-line arguments.

Aug 23, 2022
JSONes - c++ json parser & writer. Simple api. Easy to use.

JSONes Just another small json parser and writer. It has no reflection or fancy specs. It is tested with examples at json.org Only standart library. N

Dec 28, 2021