Giter Club home page Giter Club logo

clara's Introduction

Clara v1.1.5

Build Status Build status codecov

!! This repository is unmaintained. Go here for a fork that is somewhat maintained. !!


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

Clara is a single-header library.

To use, just #include "clara.hpp"

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

int width = 0;
// ...
using namespace clara;
auto cli
    = Opt( width, "width" )
        ["-w"]["--width"]
        ("How wide should it be?");

You can use this parser directly like this:

auto result = cli.parse( Args( 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
    = Opt( width, "width" )
        ["-w"]["--width"]
        ("How wide should it be?")
    | Opt( name, "name" )
        ["-n"]["--name"]
        ("By what name should I be known")
    | Opt( doIt )
        ["-d"]["--doit"]
        ("Do the thing" )
    | Arg( command, "command" )
        ("which command to run");

Opts specify options that start with a short dash (-) or long dash (--). On Windows forward slashes are also accepted (and automatically interpretted as a short 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.

Args specify arguments that are not tied to options, and so have no square bracket names. They otherwise work just like Opts.

A, console optimised, usage string can be obtained by inserting the parser into a stream. The usage string is built from the information supplied and is formatted for the console width.

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.

For more usage please see the unit tests or look at how it is used in the Catch code-base (catch-lib.net). Fuller documentation will be coming soon.

Some of the key features:

  • A single header file with no external dependencies (except the std library).
  • Define your interface once to get parsing, type conversions and usage strings with no redundancy.
  • Composable. 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 behaviour.

Roadmap

To see which direction Clara is going in, please see the roadmap

Old version

If you used the earlier, v0.x, version of Clara please note that this is a complete rewrite which assumes C++11 and has a different interface (composability was a big step forward). Conversion between v0.x and v1.x is a fairly simple and mechanical task, but is a bit of manual work - so don't take this version until you're ready (and, of course, able to use C++11).

I hope you'll find the new interface an improvement - and this will be built on to offer new features moving forwards. I don't expect to maintain v0.x any further, but it remains on a branch.

clara's People

Contributors

bmburstein avatar claremacrae avatar girtsf avatar horenmar avatar mikecrowe avatar mklimenko avatar philsquared avatar rioderelfte avatar ronen avatar vadz 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

clara's Issues

Provide CMake INTERFACE and INSTALL

It would be nice to use the newer CMake INTERFACE option in conjunction with add_library and the appropriate install entries in the CMakeLists.txt.

It would also be nice to add the tests explicitly using add_test so that ctest can be run easily.

Parsing arguments with trailing garbage should fail

Integer arguments with trailing garbage are successfully decoded instead of giving an error:
42garbage is decoded as 42 instead of parse error

This will be also a problem for other types. I looked at the implementation and the fix should be quite simple -- just checking if the stringstream is empty after the conversion.

Extend handling of arguments

I'd like to propose to extend the handling of arguments, which I have implemented in a fork of mine (which is again based on BMBurstein's).

Specifically:

  • allow for hidden arguments and options (which is used for another upcoming PR for subcommands)
  • list arguments in the help output if they have a description
  • make Args handle the case when argv doesn't contain the executable as its first element, which is useful for Win32 programs

Provide a built-in way of dealing with --help option

Almost(?) all command line programs will have the --help option so IMO it would make sense to either support it out of the box or at least make it simpler to implement it than currently as it involves many steps:

  1. Call bindProcessName() (it's not going to be used for anything else than the usage message).
  2. Add bool help to the options struct.
  3. Bind -h and --help to it.
  4. Call usage() if help is true.

I'd rather have a way to tell parse() to do all of this automatically, but this would require changing its return type, as we need to know whether help was requested or not, so maybe a better idea would be to add another method, e.g. parse_or_give_help() returning bool.

OTOH I think it's quite wrong for parse() to throw on command line syntax errors, this is not something exceptional and can (and does) happen all the time. So personally I'd rather change parse() to return an enum indicating whether the command line was successfully parsed, an error occurred or help was requested.

BoundLambda take a std::vector

Just as a BoundValueRef is specialised for a std::vector; it would be useful to have the same functionality for a BoundLambda

Support for "-"

Many programs use a single - (minus sign) on the command line to mean "read from stdin" or similar. Clara currently doesn't support this, a lonely - is always reported as error and doesn't end up in the positional arguments.

Compilation warning: ‘flag’ may be used uninitialized

Compilation produces following warning:

./third_party/clara/clara.hpp: In member function ‘virtual clara::detail::ParserResult clara::detail::BoundFlagRefBase::setValue(const string&)’:
./third_party/clara/clara.hpp:686:24: warning: ‘flag’ may be used uninitialized in this function [-Wmaybe-uninitialized]
                 setFlag( flag );
                 ~~~~~~~^~~~~~~~

I fixed it locally by initializing flag to false but there might be better ways to solve this.

.required() on Parsers doesn't make them fail the parse

I'm guessing this is just not written yet, since the spot where it'd go at the end of parse() has a // !TBD about it. It doesn't look like there's a super clean place to expose required/not to users of the API, since there's no magic operator()/operator[] left open for it, in contrast with descriptions/flags (unless you want to get cute with overloading), but even just correct behavior with the somewhat-less-pretty .required() would work for me.

If you've got an approach in mind, I'd be happy to take a whack at it since it looks like it won't take too much to do.

cc @TheOnlyRew

Bug - whitespace in a boost::path option

Hi, thanks for the cool library, I'm enjoying using it and look forward to its ongoing development!

I seem to have encountered a bug, though: if the argument to a boost::path option has white space in it, the resulting path only includes the first word. Here's a small example:

#include <boost/filesystem/path.hpp> // using boost 1.66
#include <clara.hpp>                 // using v1.1.1
#include <iostream>
#include <string>

using path = boost::filesystem::path;
using namespace clara;

int main(int argc, char *argv[]) {

  path path_opt;
  std::string string_opt;

  const auto cli = Opt(path_opt, "path")["--path"]("boost path argument") |
                   Opt(string_opt, "string")["--str"]("string argument");
  const auto result = cli.parse(Args(argc, argv));
  if (!result) {
    std::cerr << "Error: " << result.errorMessage() << std::endl;
    exit(1);
  }

  std::cout << "path_opt=" << path_opt << std::endl;
  std::cout << "path(string_opt)=" << path(string_opt) << std::endl;
}

Here's what happens when I compile and run... notice below that the path "with a space" comes out to just "with".

$ c++ --std=c++11 -I. -o bug bug.cpp -lboost_system   # Apple LLVM version 9.0.0 (clang-900.0.39.2)
$ ./bug --path "with a space" --str "with a space"
path_opt="with"
path(string_opt)="with a space"
$

Of course the workaround of using a string opt then creating a path from that is viable, just not nearly as pretty.

It's possible that this isn't a Clara bug per se, but just that boost::path don't have the right construction semantics to work as a Clara Opt. If so that's a bummer -- and a little insidious, since it seems to work fine as long as there's no whitespace. And when/if you do use a path with whitespace there's no warning, just elsewhere in the app you get unexpected behavior because the path isn't what you think it is :)

Opts can't accept variadic arguments

I know that the Arg class is meant to take variadic arguments, but why can't the Opt class take variadic arguments as well? I would like to take multiple arguments for 2 different options, but the Opt class doesn't accept vectors. Is there any reason this couldn't be changed, or is there some implementation obstacle that prevents Opts from taking vectors?

Handle carriage returns in the description text of the command line options

Hi,

in the help screen, when the description contains a carriage return (\n), the library prints it in the middle of the column. This causes the overall content to be misaligned. See the example below:

# ./my_hello_program -h
usage:
  my_hello_program [<arguments> ... ] options

where options are:
  -?, -h, --help                   display usage information
  -e, --experiment <experiment>    The experiment to perform. The possible
                                   choices are:
- option1: Insert <N>
                                   unique elements in the data structure,
                                   then perform <M> look ups of existing
                                   elements. Measure the total insertion &
                                   look up time
- option2:
                                   Create an AB tree with the defined bounds
                                   for the leaves and the inner nodes. Measure
                                   the loading time, the insertion time and
                                   look up time
-
                                   option3: Insert the elements
                                   gradually, by doubling the size of the
                                   data structure, and measure at each step
                                   both the insert & search time
[...]

Note that my intention is that the options, listed below the experiment, should still appear on the rightmost column, the one that contains the description of the parameter `experiment'.

Perhaps does it exist a manner to achieve the intended behaviour without altering the source code of the library?

All the best,
Dean

Please provide LICENSE file

I've been trying to work out what license Clara is under. The "single-include" contains license text from clara_textflow.hpp:

// This work is licensed under the BSD 2-Clause license.
// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause

But I can't see a LICENSE file in the repository.

The separate clara.hpp contains no license information at all.

I suspect that Clara is also under the 2-clause BSD license, but I think this needs to be made completely clear.

Thanks.

Mike.

for Windows style parsing, allow multi-character option names

On windows it is common to have multi-character option names, without needing a different way to start the option. For example: "/test". The current parser accepts the leading '/' on the option, but then it sees that it is multiple characters without a second '-', so it breaks it up into: -t -e -s -t.

I'd like a way to say "do this 'windows style', and don't require "--" to start multiple-character option names.

(I have "fixed" this in my program by looking for this case and putting in the second '-', but it's a hack. I have to put both "/test" and "/-test" as equivalent names for the option, else it won't match.)

(I have no need for composing options in one option string, unlike: ls -lrt)

ParseResultType is rarely handled properly

Out of 4 values of ParseResultType, one is not used at all ShortCircuitSame and ShortCircuitAll is only possible for Options.

I tried to add and Arg with ShortCircuitAll to be able to implement subcommands, but it simply didn't work (as Arg::parse only returns Matched or failed values, no matter what valueRef->setValue returns).

Why does CommandLine need to be a template?

This is not really an issue, more of a question, but as there doesn't seem to be any better place to discuss it, let me start it here: why do we need to use ConfigT as template parameter everywhere? It is indeed good practice to collect all the command line options values in one struct, but looking at my existing projects (which I am thinking of migrating to Clara), I see that quite a few of them don't actually do it like this and just use local variables. And there doesn't seem to be any reason not support it in Clara too, i.e. it seems to me that the following should be possible:

int main(int argc, char const* argv[])
{
    struct Options {
        bool foo = false;
    };

    Clara::CommandLine cl; // not a template!

    // It looks like this could still be made to work:
    Options opts;
    cl["-f"].bind(&Options::foo, opts);

    // But we could also have this:
    bool bar = false;
    cl["-b"].bind(&bar);
    cl.parse(argc, argv);
}

Granted, implementing #1 would make this less critical as I could then do

  cl["-b"].bind([&](bool value) { bar = value; });

but it would still be nice to have direct support for this IMHO.

The placeholder in a bound option is....odd

I'm a bit confused by the placeholder...what I think I want is to be able to set a default value for that field; I know that I can set it in the options struct constructor but I was expecting to be able to use the placeholder. However, that didn't work if the option never got specified...

So I left the placeholder empty (since it didn't get used) but then when I run it it throws an invalid conversion:

c:\Projects\ClaraExample\Debug>ClaraExample.exe --host
Exception: Invalid conversion
- while parsing: (--host)

c:\Projects\ClaraExample\Debug>ClaraExample.exe --host=fred
Exception: Invalid conversion
- while parsing: (--host)

This is the code:

#define CLARA_CONFIG_MAIN
#include <clara.h>
#include <iostream>

struct Opt
{
    Opt()
        : showHelp(false)
        , hostname("api.github.com")
    {}
    std::string processName;
    bool showHelp;
    std::string hostname;
};

int main(int argc, char* argv[])
{
    using namespace Clara;
    try
    {
        CommandLine<Opt> cli;

        cli.bindProcessName(&Opt::processName);
        cli["-?"]["-h"]["--help"]
            .describe("describes how to use the program")
            .bind(&Opt::showHelp);
        cli["--host"]
            .describe("host to connect to")
            .bind(&Opt::hostname, "");
            //.bind(&Opt::hostname, "must not be empty...but never gets used");

        Opt opt;
        cli.parseInto(argc, const_cast<const char**>(argv), opt);
        if (opt.showHelp)
        {
            cli.usage(std::cout, opt.processName);
        }
        else
        {
            std::cout << "Host: " << opt.hostname << std::endl;
        }
    }
    catch (const std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
    catch (...)
    {
        std::cerr << "Unknown exception..." << std::endl;
    }

    return 0;
}

I know that I can make this work by specifiying the placeholder, but it never seems to get used (using the 'bind' that is commented out above):

# This is fine...option specified on the command line...
c:\Projects\ClaraExample\Debug>ClaraExample.exe --host=fred
Host: fred

# This fails (and doesn't seem to use the placeholder)...
c:\Projects\ClaraExample\Debug>ClaraExample.exe --host
Exception: Expected argument to option: host

How do I make the placeholder useful? Can the value be 'optional'?

Is it possible/desirable to set the bound member variable (perhaps to the value of the placeholder) even if I don't specify the option on the command line (I;m not sure what side effects this might have on existing code...)?

remainingTokens is not accessible after parsing

I was trying to extract remainingTokens from InternalParseResult from failed parse, but I was not able to. It seems that remainingTokens are a pair of iterators that are no longer valid after Parser::parse() method was finished.

I think it means that return value of Parser::parser() has wrong return type, as it gives access to variables that cannot be accessed. It could be fixed by either changing the return type, make variables valid at that point, or add a new TokenStream/std::vectorstd::string member to Parser class that will contain remainingTokens after parse() is finished.

I've ended up with implementing my own class from Parser that does the last thing.

Please let me know what do you think about it (nb.: in some previous version of clara those values were easily accessible by unusedTokens() method).

Is it possible to find out if an option was specified on the command line?

I would like to know if the user specified a particular command line option. I can do that by setting a bool in a bound function, but I can't help thinking that the framework already 'knows' if the option got used...I couldn't see any way to find out if it had been set though - can it be done?

My rather cludgy example code;

#define CLARA_CONFIG_MAIN
#include <clara.h>
#include <iostream>

struct Opt
{
    Opt()
        : hostnameWasSet(false)
    {}
    std::string processName;
    bool hostnameWasSet;
    std::string hostname;

    void setHostname(const std::string& h)
    {
        hostnameWasSet = true;
        hostname = h;
    }
};

int main(int argc, char* argv[])
{
    using namespace Clara;
    try
    {
        CommandLine<Opt> cli;

        cli.bindProcessName(&Opt::processName);
        cli["--host"]
            .describe("set the host name")
            .bind(&Opt::setHostname, "api.github.com");

        Opt opt;
        cli.parseInto(argc, const_cast<const char**>(argv), opt);
        if (opt.hostnameWasSet)
        {
            std::cout << "Hostname was set..." << opt.hostname << std::endl;
        }
        else
        {
            std::cout << "Hostname was NOT set...do stuff that doesn't need the hostname" << std::endl;
        }
    }
    catch (const std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
    catch (...)
    {
        std::cerr << "Unknown exception..." << std::endl;
    }

    return 0;
}

This is the result that I want:

c:\Projects\ClaraExample\Debug>ClaraExample.exe --host=fred
Hostname was set...fred

c:\Projects\ClaraExample\Debug>ClaraExample.exe
Hostname was NOT set...do stuff that doesn't need the hostname

Missing include for std::optional

Clara/include/clara.hpp

Lines 21 to 27 in adb5ec3

#ifndef CLARA_CONFIG_OPTIONAL_TYPE
# ifdef __has_include
# if __has_include(<optional>) && __cplusplus >= 201703L
# define CLARA_CONFIG_OPTIONAL_TYPE std::optional
# endif
# endif
#endif

<optional> should probably be included here.

Subcommands

Tools, which aren't a command in their own respect but rather offer several independent sub commands, are quite hard to achieve with the current state of the library. Examples are git or the windows service utility sc.

Subcommands are a good way to reduce the complexity of the commandline by separating different concerns.

Support for shebang

Hi,

I'm writing a little script interpreter using your option parser.

It would be cool if we could specify an arbitrary plain string as argument, like a filename, without specifying '--filename' before.

This would allow to support shebangs because this :

script.custom_extension

#! /bin/custom_interpreter

is read by the kernel and run as :

/bin/custom_interpreter script.custom_extension

Thank you for your option parser, it's very useful for me.

Respect COLUMNS environment variable

Determining the real terminal width is hard to do portably, but it's pretty simple to see if the COLUMNS env var is defined and use it instead of the hard coded 80 if it is.

I could make a PR if this is considered to be a good idea.

A simple working demo?

Hello, is there a simple working demo here? With just include "clara.hpp", and a main function.

Parsing `-j 8` but also `-j8`

Dear Clara authors,

First thanks for this lightweight cmdline parsing library. It's much appreciated after years of program_options. 😉

I'm using Clara and I noticed that most of the time I mistype the command line argument without space between the value and the option.

Is there an easy way or could you give some hints to make a patch, so that -j 8 but also -j8 could be parsed as 8 for a case like this :

  std::optional<size_t> cpus_j;
  auto cmd_args =
      Opt ( cpus_j, "cpus" )
          ["-j"]
          ("How many CPU cores have to be dedicated to the build.\n");

Or is it something you don't want at all in Clara ?

Warm regards,

Option value can't start with a dash

This test case fails:

TEST_CASE( "Opt value can start with a dash" ) {
    std::string name;
    bool showHelp = false;
    auto parser
            = Help( showHelp )
            | Opt( name, "name" )
                ["-n"]["--name"]
                ( "the name to use" );

    auto result = parser.parse( Args{ "TestApp", "-n", "-lfoobar" } );
    CHECK( result );
    REQUIRE( name == "-lfoobar" );
}

I have a program that receives compiler flags in arguments so a leading dash is common.

Use of `cassert` infects all users

The use of the cassert header, and thus inclusion of the lowercase assert macro, prevents users importing this library from having "assert" as any identifier or namespace, which doesn't tend to play well with larger projects not making use of this header, and certainly doesn't play well with C++11 unit test libraries!

A simple fix, as cassert is essentially guaranteed to contain nothing but assert, would be to #undef assert at the end of the header. However the special stitch script complains because there is no visible counterpart #define assert, making this a lot less trivial.

Parser::operator<< fails for long help strings

I get a std::bad_alloc for help strings that are too wide for my console when trying to do std::cerr << cli << std::endl;

The problem comes from this line of code:

                auto row =
                        TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
                        TextFlow::Spacer(4) +
                        TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );

where optWidth is not bounded to be less than consoleWidth - 7

README needs updating.

Composing args with + symbols causes errors on compilation. Those should probably be | symbols instead.

Optional arguments to Opt using std::optional

There is code to handle std::optional via CLARA_CONFIG_OPTIONAL_TYPE; however Opt still is expecting an argument if none is given.

For example for logging: ./program, run with no logging (default), ./program -l enable logging, ./program -l file.log enable logging to named file.

This would make sense to use std::optional here.

For example, the default will not do anything; giving the "flag" -l will act like a pass the log through to std::clog; giving the optional with a filename -l /path/to/file.log will pass through to the /path/to/file.log.

std::ostream m_log{nullptr};
std::ofstream m_log_{};

clara::Opt{[&](std::optional<fs::path> filename) {
	           if (!filename) {
		           m_log.rdbuf(std::clog.rdbuf());
		           return clara::ParserResult::ok(clara::ParseResultType::Matched);
	           }
	           m_log_.open(*filename);
	           m_log.rdbuf(m_log_.rdbuf());
	           return clara::ParserResult::ok(clara::ParseResultType::Matched);
           },
           "filename"s}["-l"s]["--log"s]("enable logging [set log file {stderr}]"s);

Help for Args, like with Opt

Currently clara::Arg(filenames, "filename"s)("input filenames"s) does not produce an entry in the help; it's is common for a brief description to appear

usage:
    NAME [<filename> ... ] options

    where <filename> ...     input filenames
    where options are:
    ETC

or something similar.

Frankly, I also find it strange that the options appear after the arguments, rather than before, as is fairly standard.

Opt and Arg classes can be inherited from, but are sliced by default

I had some special needs from one of my Arg parameter that I wanted to implement by inheriting from it and reimplementing parse method. It turned out to not work, as Arg and Opt instances are sliced in Parser class (see m_options and m_args members).

I think that either Arg and Opt could be make final, or m_options and m_args could use some kind of pointers instead of using values to allow for own implementations of those concepts.

Set up Travis CI

I can't do it myself (you'd need to make me part of Clara organization, I think), but it would be nice to have Travis CI for this.

At the very least I could write a (trivial) makefile to run the tests.

Joint Options

It would be used to be able to write options that are joint together

as an example of what I mean, my use case:

User needs to either give an input and output filename; this does one file.
Alternatively user gives input and output directories; this does the operation over a predefined subset within those directories.

If one is used, the other shouldn't be

Treat lambdas as containers

It would be useful if options that use lambdas would allow the same option being specified multiple times.

out of bounds

cppcheck reports:
When i==arg.size(), arg[i] is out of bounds. on line 554 in clara.h

handle positional args after `--`

It looks that Clara just stops parsing when encountering --.

        void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
            const std::string doubleDash = "--";
            for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
                parseIntoTokens( args[i], tokens);
        }

I guess the intended behavior (example: grep -- -b file) is not implemented yet?

Provide mechanism for general description text, that is not specific to any option or argument

For background, see twitter discussion here:
https://twitter.com/ClareMacraeUK/status/949415455399268353

Summary: It would be great to be able provide some descriptive prose to the parser, and have that nicely formatted and included when writing out help text.

My case is that I'm writing out Clara's usage text twice - once on error, and once on --help, and I'd like to insert some text between Clara's "usage:" and "where the options are:" lines.

Single positional argument appears not to be parsed correctly

I'm having trouble getting Clara to recognise a single positional argument.

Adding this to ClaraTests.cpp:

TEST_CASE("Mike") {
    bool flag;
    std::string filename;

    auto command_line_parser
	= Opt(flag)["-f"]("Test flag")
	+ Arg(filename, "filename")("Test data filename");

    SECTION("preceding flag")
    {
	auto result = command_line_parser.parse({ "-f", "the-filename" });
	REQUIRE(result);
	REQUIRE(filename == "the-filename");
    }

    SECTION("following flag")
    {
	auto result = command_line_parser.parse({ "the-filename", "-f" });
	REQUIRE(result);
	REQUIRE(filename == "the-filename");
    }

    SECTION("no flag")
    {
	auto result = command_line_parser.parse({ "the-filename" });
	REQUIRE(result);
	REQUIRE(filename == "the-filename");
    }
}

Fails with:

-------------------------------------------------------------------------------
Mike
  following flag
-------------------------------------------------------------------------------
/home/mac/git/Clara/src/ClaraTests.cpp:331
...............................................................................

/home/mac/git/Clara/src/ClaraTests.cpp:335: FAILED:
  REQUIRE( filename == "the-filename" )
with expansion:
  "" == "the-filename"

-------------------------------------------------------------------------------
Mike
  no flag
-------------------------------------------------------------------------------
/home/mac/git/Clara/src/ClaraTests.cpp:338
...............................................................................

/home/mac/git/Clara/src/ClaraTests.cpp:342: FAILED:
  REQUIRE( filename == "the-filename" )
with expansion:
  "" == "the-filename"

Compared the the other tests, I can't see what I'm doing wrong. :(

Cannot construct Opt from lambda when passed via variable

The following code fails to compile for me on Apple Clang (Apple LLVM version 8.0.0 (clang-800.0.42.1; Target: x86_64-apple-darwin15.6.0):

#include <clara.hpp>
#include <string>

int main(int argc, char** argv) {
  bool showHelp = false;

  auto parsePlayerPos = [](const std::string& playerPosString) { /* Do something here */ };

  using namespace clara;
  auto commandLineParser =
    Help(showHelp)
    | Opt(parsePlayerPos, "player-pos")
      ["--player-pos"]
      ("Some text here");

  return 0;
}

if I specify the lambda expression inline, it works, i.e.:

Opt([](const std::string& playerPosString) { /* Do something here */ }, "player-pos")

The error message I get is:

In file included from /Users/lethal-guitar/RigelEngine/src/main.cpp:20:
/Users/lethal-guitar/RigelEngine/3rd_party/clara/clara.hpp:640:12: error: invalid operands to binary expression ('std::stringstream'
      (aka 'basic_stringstream<char>') and '(lambda at /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25)')
        ss >> target;
        ~~ ^  ~~~~~~
/Users/lethal-guitar/RigelEngine/3rd_party/clara/clara.hpp:690:20: note: in instantiation of function template specialization
      'clara::detail::convertInto<(lambda at /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25)>' requested here
            return convertInto( arg, m_ref );
                   ^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:2125:7: note: in instantiation of member function
      'clara::detail::BoundValueRef<(lambda at /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25)>::setValue' requested here
class __libcpp_compressed_pair_imp<_T1, _T2, 1>
      ^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:4411:26: note: in instantiation of function template specialization
      'std::__1::__shared_ptr_emplace<clara::detail::BoundValueRef<(lambda at /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25)>,
      std::__1::allocator<clara::detail::BoundValueRef<(lambda at /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25)> >
      >::__shared_ptr_emplace<(lambda at /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25) &>' requested here
    ::new(__hold2.get()) _CntrlBlk(__a2, _VSTD::forward<_Args>(__args)...);
                         ^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:4775:29: note: in instantiation of function template specialization
      'std::__1::shared_ptr<clara::detail::BoundValueRef<(lambda at /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25)>
      >::make_shared<(lambda at /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25) &>' requested here
    return shared_ptr<_Tp>::make_shared(_VSTD::forward<_Args>(__args)...);
                            ^
/Users/lethal-guitar/RigelEngine/3rd_party/clara/clara.hpp:817:25: note: in instantiation of function template specialization
      'std::__1::make_shared<clara::detail::BoundValueRef<(lambda at /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25)>, (lambda at
      /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25) &>' requested here
        :   m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
                        ^
/Users/lethal-guitar/RigelEngine/3rd_party/clara/clara.hpp:946:50: note: in instantiation of function template specialization
      'clara::detail::ParserRefImpl<clara::detail::Opt>::ParserRefImpl<(lambda at /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25)>'
      requested here
        Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
                                                 ^
/Users/lethal-guitar/RigelEngine/src/main.cpp:35:7: note: in instantiation of function template specialization
      'clara::detail::Opt::Opt<(lambda at /Users/lethal-guitar/RigelEngine/src/main.cpp:29:25)>' requested here
    | Opt(parsePlayerPos, "player-pos")

I'm using Clara v. 1.1.2.

Contribution for docs/examples

Hi @philsquared
There is some issues about documentation and it's also add in the roadmap.
Did you need help on this point ?
Did you already have a table of content or a structure that we can complete ?
Did you prefer complete explanation of each functionnality or just a bunch of examples ?

related : #49

Need comparison with Boost program_options

Boost has a command-line (another other) configuration processor, boost::program_options. It would be useful if the README.md here could compare and contrast clara with that.

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.