C++11 port of docopt

Overview

docopt.cpp: A C++11 Port

Contents

docopt creates beautiful command-line interfaces

Isn't it awesome how getopt (and boost::program_options for you fancy folk!) generate help messages based on your code?! These timeless functions have been around for decades and have proven we don't need anything better, right?

Hell no! You know what's awesome? It's when the option parser is generated based on the beautiful help message that you write yourself! This way you don't need to write this stupid repeatable parser-code, and instead can write only the help message--the way you want it.

docopt helps you create most beautiful command-line interfaces easily:

#include "docopt.h"

#include <iostream>

static const char USAGE[] =
R"(Naval Fate.

    Usage:
      naval_fate ship new <name>...
      naval_fate ship <name> move <x> <y> [--speed=<kn>]
      naval_fate ship shoot <x> <y>
      naval_fate mine (set|remove) <x> <y> [--moored | --drifting]
      naval_fate (-h | --help)
      naval_fate --version

    Options:
      -h --help     Show this screen.
      --version     Show version.
      --speed=<kn>  Speed in knots [default: 10].
      --moored      Moored (anchored) mine.
      --drifting    Drifting mine.
)";

int main(int argc, const char** argv)
{
    std::map<std::string, docopt::value> args
        = docopt::docopt(USAGE,
                         { argv + 1, argv + argc },
                         true,               // show help if requested
                         "Naval Fate 2.0");  // version string

    for(auto const& arg : args) {
        std::cout << arg.first <<  arg.second << std::endl;
    }

    return 0;
}

Beat that! The option parser is generated based on the docstring above that is passed to docopt::docopt function. docopt parses the usage pattern ("Usage: ...") and option descriptions (lines starting with a dash "-") and ensures that the program invocation matches the usage pattern; it parses options, arguments and commands based on that. The basic idea is that a good help message has all necessary information in it to make a parser.

Getting and using

To get docopt.cpp, the simplest is to use Conda:

conda install -c conda-forge docopt.cpp

Alternatively manual installation is done using (unix):

git clone
cmake .
make install

To link docopt.cpp, the simplest is to use CMake. The general structure of your CMakeLists.txt would be as follows:

cmake_minimum_required(VERSION 3.1)

project(example)

find_package(docopt COMPONENTS CXX REQUIRED)
include_directories(${DOCOPT_INCLUDE_DIRS})

add_executable(${PROJECT_NAME} ...)

target_link_libraries(${PROJECT_NAME} docopt)

C++11 port details

This is a port of the docopt.py module (https://github.com/docopt/docopt), and we have tried to maintain full feature parity (and code structure) as the original.

This port is written in C++11 and also requires a good C++11 standard library (in particular, one with regex support). The following compilers are known to work with docopt:

  • Clang 3.3 and later
  • GCC 4.9
  • Visual C++ 2015 RC

GCC-4.8 can work, but the std::regex module needs to be replaced with Boost.Regex. In that case, you will need to define DOCTOPT_USE_BOOST_REGEX when compiling docopt, and link your code with the appropriated Boost libraries. A relatively recent version of Boost is needed: 1.55 works, but 1.46 does not for example.

This port is licensed under the MIT license, just like the original module. However, we are also dual-licensing this code under the Boost License, version 1.0, as this is a popular C++ license. The licenses are similar and you are free to use this code under the terms of either license.

The differences from the Python port are:

  • the addition of a docopt_parse function, which does not terminate the program on error
  • a docopt::value type to hold the various value types that can be parsed. We considered using boost::variant, but it seems better to have no external dependencies (beyond a good STL).
  • because C++ is statically-typed and Python is not, we had to make some changes to the interfaces of the internal parse tree types.
  • because std::regex does not have an equivalent to Python's regex.split, some of the regex's had to be restructured and additional loops used.

API

docopt::docopt(doc, argv, help /* =true */, version /* ="" */, options_first /* =false */)

docopt takes 2 required and 3 optional arguments:

  • doc is a string that contains a help message that will be parsed to create the option parser. The simple rules of how to write such a help message are given in next sections. Here is a quick example of such a string (note that this example uses the "raw string literal" feature that was added to C++11):
R"(Usage: my_program [-hso FILE] [--quiet | --verbose] [INPUT ...]

-h --help    show this
-s --sorted  sorted output
-o FILE      specify output file [default: ./test.txt]
--quiet      print less text
--verbose    print more text
)"
  • argv is a vector of strings representing the args passed. Although main usually takes a (int argc, const char** argv) pair, you can pass the value {argv+1, argv+argc} to generate the vector automatically. (Note we skip the argv[0] argument!) Alternatively you can supply a list of strings like { "--verbose", "-o", "hai.txt" }.

  • help, by default true, specifies whether the parser should automatically print the help message (supplied as doc) and terminate, in case -h or --help option is encountered (options should exist in usage pattern, more on that below). If you want to handle -h or --help options manually (as other options), set help=false.

  • version, by default empty, is an optional argument that specifies the version of your program. If supplied, then, (assuming --version option is mentioned in usage pattern) when parser encounters the --version option, it will print the supplied version and terminate. version could be any printable object, but most likely a string, e.g. "2.1.0rc1".

    Note, when docopt is set to automatically handle -h, --help and --version options, you still need to mention them in usage pattern for this to work (also so your users to know about them!)

  • options_first, by default false. If set to true will disallow mixing options and positional argument. I.e. after first positional argument, all arguments will be interpreted as positional even if the look like options. This can be used for strict compatibility with POSIX, or if you want to dispatch your arguments to other programs.

The return value is a map<string, docopt::value> with options, arguments and commands as keys, spelled exactly like in your help message. Long versions of options are given priority. For example, if you invoke the top example as:

naval_fate ship Guardian move 100 150 --speed=15

the return dictionary will be:

{"--drifting": false,    "mine": false,
 "--help": false,        "move": true,
 "--moored": false,      "new": false,
 "--speed": "15",        "remove": false,
 "--version": false,     "set": false,
 "<name>": ["Guardian"], "ship": true,
 "<x>": "100",           "shoot": false,
 "<y>": "150"}

If any parsing error (in either the usage, or due to incorrect user inputs) is encountered, the program will exit with exit code -1.

Note that there is another function that does not exit on error, and instead will propagate an exception that you can catch and process as you like. See the docopt.h file for information on the exceptions and usage:

docopt::docopt_parse(doc, argv, help /* =true */, version /* =true */, options_first /* =false)

Help message format

Help message consists of 2 parts:

  • Usage pattern, e.g.:

    Usage: my_program [-hso FILE] [--quiet | --verbose] [INPUT ...]
    
  • Option descriptions, e.g.:

    -h --help    show this
    -s --sorted  sorted output
    -o FILE      specify output file [default: ./test.txt]
    --quiet      print less text
    --verbose    print more text
    

Their format is described below; other text is ignored.

Usage pattern format

Usage pattern is a substring of doc that starts with usage: (case insensitive) and ends with a visibly empty line. Minimum example:

"""Usage: my_program

"""

The first word after usage: is interpreted as your program's name. You can specify your program's name several times to signify several exclusive patterns:

"""Usage: my_program FILE
          my_program COUNT FILE

"""

Each pattern can consist of the following elements:

  • <arguments>, ARGUMENTS. Arguments are specified as either upper-case words, e.g. my_program CONTENT-PATH or words surrounded by angular brackets: my_program <content-path>.
  • --options. Options are words started with dash (-), e.g. --output, -o. You can "stack" several of one-letter options, e.g. -oiv which will be the same as -o -i -v. The options can have arguments, e.g. --input=FILE or -i FILE or even -iFILE. However it is important that you specify option descriptions if you want your option to have an argument, a default value, or specify synonymous short/long versions of the option (see next section on option descriptions).
  • commands are words that do not follow the described above conventions of --options or <arguments> or ARGUMENTS, plus two special commands: dash "-" and double dash "--" (see below).

Use the following constructs to specify patterns:

  • [ ] (brackets) optional elements. e.g.: my_program [-hvqo FILE]
  • ( ) (parens) required elements. All elements that are not put in [ ] are also required, e.g.: my_program --path=<path> <file>... is the same as my_program (--path=<path> <file>...). (Note, "required options" might be not a good idea for your users).
  • | (pipe) mutually exclusive elements. Group them using ( ) if one of the mutually exclusive elements is required: my_program (--clockwise | --counter-clockwise) TIME. Group them using [ ] if none of the mutually exclusive elements are required: my_program [--left | --right].
  • ... (ellipsis) one or more elements. To specify that arbitrary number of repeating elements could be accepted, use ellipsis (...), e.g. my_program FILE ... means one or more FILE-s are accepted. If you want to accept zero or more elements, use brackets, e.g.: my_program [FILE ...]. Ellipsis works as a unary operator on the expression to the left.
  • [options] (case sensitive) shortcut for any options. You can use it if you want to specify that the usage pattern could be provided with any options defined below in the option-descriptions and do not want to enumerate them all in usage-pattern.
  • "[--]". Double dash "--" is used by convention to separate positional arguments that can be mistaken for options. In order to support this convention add "[--]" to your usage patterns.
  • "[-]". Single dash "-" is used by convention to signify that stdin is used instead of a file. To support this add "[-]" to your usage patterns. "-" acts as a normal command.

If your pattern allows to match argument-less option (a flag) several times:

Usage: my_program [-v | -vv | -vvv]

then number of occurrences of the option will be counted. I.e. args['-v'] will be 2 if program was invoked as my_program -vv. Same works for commands.

If your usage pattern allows to match same-named option with argument or positional argument several times, the matched arguments will be collected into a list:

Usage: my_program <file> <file> --path=<path>...

I.e. invoked with my_program file1 file2 --path=./here --path=./there the returned dict will contain args['<file>'] == ['file1', 'file2'] and args['--path'] == ['./here', './there'].

Option descriptions format

Option descriptions consist of a list of options that you put below your usage patterns.

It is necessary to list option descriptions in order to specify:

  • synonymous short and long options,
  • if an option has an argument,
  • if option's argument has a default value.

The rules are as follows:

  • Every line in doc that starts with - or -- (not counting spaces) is treated as an option description, e.g.:

    Options:
      --verbose   # GOOD
      -o FILE     # GOOD
    Other: --bad  # BAD, line does not start with dash "-"
    
  • To specify that option has an argument, put a word describing that argument after space (or equals "=" sign) as shown below. Follow either <angular-brackets> or UPPER-CASE convention for options' arguments. You can use comma if you want to separate options. In the example below, both lines are valid. However you are recommended to stick to a single style.:

    -o FILE --output=FILE       # without comma, with "=" sign
    -i <file>, --input <file>   # with comma, without "=" sing
    
  • Use two spaces to separate options with their informal description:

    --verbose More text.   # BAD, will be treated as if verbose option had
                           # an argument "More", so use 2 spaces instead
    -q        Quit.        # GOOD
    -o FILE   Output file. # GOOD
    --stdout  Use stdout.  # GOOD, 2 spaces
    
  • If you want to set a default value for an option with an argument, put it into the option-description, in form [default: <my-default-value>]:

    --coefficient=K  The K coefficient [default: 2.95]
    --output=FILE    Output file [default: test.txt]
    --directory=DIR  Some directory [default: ./]
    
  • If the option is not repeatable, the value inside [default: ...] will be interpreted as string. If it is repeatable, it will be split into a list on whitespace:

    Usage: my_program [--repeatable=<arg> --repeatable=<arg>]
                         [--another-repeatable=<arg>]...
                         [--not-repeatable=<arg>]
    
    # will be ['./here', './there']
    --repeatable=<arg>          [default: ./here ./there]
    
    # will be ['./here']
    --another-repeatable=<arg>  [default: ./here]
    
    # will be './here ./there', because it is not repeatable
    --not-repeatable=<arg>      [default: ./here ./there]
    

Examples

We have an extensive list of examples which cover every aspect of functionality of docopt. Try them out, read the source if in doubt.

There are also very interesting applications and ideas at that page. Check out the sister project for more information!

Subparsers, multi-level help and huge applications (like git)

If you want to split your usage-pattern into several, implement multi-level help (with separate help-screen for each subcommand), want to interface with existing scripts that don't use docopt, or you're building the next "git", you will need the new options_first parameter (described in API section above). To get you started quickly we implemented a subset of git command-line interface as an example: examples/git

Compiling the example / Running the tests

The original Python module includes some language-agnostic unit tests, and these can be run with this port as well.

The tests are a Python driver that uses the testcases.docopt file to then invoke a C++ test case runner (run_testcase.cpp):

$ clang++ --std=c++11 --stdlib=libc++ docopt.cpp run_testcase.cpp -o run_testcase
$ python run_tests.py
PASS (175)

You can also compile the example shown at the start (included as example.cpp):

$ clang++ --std=c++11 --stdlib=libc++ -I . docopt.cpp examples/naval_fate.cpp -o naval_fate
$ ./naval_fate --help
 [ ... ]
$ ./naval_fate ship Guardian move 100 150 --speed=15
--drifting: false
--help: false
--moored: false
--speed: "15"
--version: false
<name>: ["Guardian"]
<x>: "100"
<y>: "150"
mine: false
move: true
new: false
remove: false
set: false
ship: true
shoot: false

Development

Comments and suggestions are very welcome! If you find issues, please file them and help improve our code!

Please note, however, that we have tried to stay true to the original Python code. If you have any major patches, structural changes, or new features, we might want to first negotiate these changes into the Python code first. However, bring it up! Let's hear it!

Changelog

docopt follows semantic versioning. The first release with stable API will be 1.0.0 (soon).

  • 0.6.2 Bugfix release (still based on docopt 0.6.1)
  • 0.6.1 The initial C++ port of docopt.py (based on docopt 0.6.1)
Comments
  • Regex expressions cause stack overflows in MSVC 2015

    Regex expressions cause stack overflows in MSVC 2015

    First of all, let me thank you for this awesome library!

    The standard <regex> implementation for Visual C++ seems to have a rather severe design issue that seems to cause stack overflows for complicated expressions (I suspect the lookaheads you use, but I'm not really sure about that). A couple of google searches revealed that this seems to be a known issue. Some people seem to have been able to avoid the problem by increasing their stack size, but that didn't help in my case (I've added an example program below that reproduces the problem; the nested method calls in std::_Matcher are really quite insane).

    I've already written a patch for parse_section that resolves my original problem, but I still get a similar error in parse_defaults with the demo program below. Also, I unfortunately don't have any git-tools at my disposal right now, so I can't start a pull request for this. For now, I'll post my version of parse_section in the comments and see if I can come up with a similar "fix" for the other expressions.

    Here's my test program to reproduce the problem:

    #include <docopt.h>
    #include <iostream>
    #include <string>
    
    void printArguments(const std::map<std::string, docopt::value> &args)
    {
        std::cout << "Arguments:\n\n";
        for (auto &entry : args)
        {
            const std::string &name = entry.first;
            const docopt::value &value = entry.second;
    
            std::cout << name << ": \n";
    
            if (value.isString())
                std::cout << "       (string)   " << value.asString() << "\n\n";
            else if (value.isLong())
                std::cout << "       (long)     " << value.asLong() << "\n\n";
            else if (value.isBool())
                std::cout << "       (bool)     " << value.asBool() << "\n\n";
            else if (value.isStringList())
            {
                const auto &list = value.asStringList();
                std::cout << "       (str_list) [\n";
    
                for (auto &str : list)
                    std::cout << "                        " << str << ",\n";
                std::cout << "                  ]\n\n";
            }
            else if (!value) std::cout << "       (empty)\n\n";
            else std::cout << "       (unknown)\n\n";
    
        }
        std::cout << std::endl;
    }
    
    const auto USAGE =
    R"(
    Usage:
        foo [options] <ARG1> <ARG2> [--option1=<OPTION1>] [--option2=<OPTION2>]
        foo --command1 <ARG3> <ARG4> <ARG5> <ARG6>  [--option3=<OPTION3> [--option4=<OPTION4>]] [--option5=<OPTION5>]
        foo --command2 <ARG4>
        foo (-v | --version)
        foo (-h | --help)
    
    Options:
        -o <OPTION6>, --option6=<OPTION6>      Some rather long description of option #6 which makes this line longer than it really should be...
    )";
    
    void main(int argc, const char** argv)
    {
        try
        {
            auto arguments = docopt::docopt(USAGE, { argv + 1,argv + argc }, true, "1.0.0.0", true);
            printArguments(arguments);
        }
        catch (std::exception &e)
        {
            std::cerr << "Encountered exception of type "
                << typeid(e).name() << ": "
                << e.what();
        }
        std::cin.ignore();
    }
    
    opened by mfrischknecht 26
  • tags for official releases

    tags for official releases

    I can see that docopt has been staying at version 0.6.1 for quite a while now without an official release being made. Is the development currently focusing on the next version, or is it because 0.6.1 is not complete yet? Please consider tagging official releases in the future.

    Cheers, Ghis

    opened by ghisvail 15
  • Support GCC 4.8, using Boost.Regex

    Support GCC 4.8, using Boost.Regex

    I got one failure on my machine:

    $ ./run_tests
    ========================================
    UsAgE: prog [options]
    
    OpTiOnS: --path=<files>  Path to files
                    [dEfAuLt: /root]
    
    
    ::::::::::::::::::::
    prog
    --------------------
    { "--path": null }
    
     ** JSON does not match expected: {u'--path': u'/root'}
    1 failures
    

    Also, I checked that the code still compiles normally using clang. I can try to add GCC 4.8 to travis, but this will make it fail.

    Fixes #42.

    opened by Luthaf 13
  • New release?

    New release?

    I would like to add docopt.cpp to conda-forge. However, it relies on releases. Therefore it would be great of a new release can be made!

    Once this is done, I can create the conda-forge package. It would be great if I can add one or more of the authors/maintainers to that package, for them to have push-rights also for the conda-forge package.

    opened by tdegeus 12
  • Value.asLong not working as expected

    Value.asLong not working as expected

    I don't know if I am missing something, but I can not figure out how to get an integer-type value out from an argument.

    From the example, you have an option like this:

    --speed=<kn>  Speed in knots [default: 10].
    

    Now, if I look at that value after docopt.cpp parsing, I get

    "--speed": "10"
    

    You can see that "15" is a string and not an integer.

    Calling

    args["--speed"].asLong()
    

    results in a runtime exception due to the type being std::string.

    Currently, to get around this I'm doing

    auto speed = std::stoi(args["--speed"].asString());  // Type of speed will be integer
    

    Is there something that needs to be specified in the USAGE string, or is this a bug?

    opened by isbecker 12
  • Implement #115

    Implement #115

    Implements issue #115. I moved the Kind enum out into the docopt namespaces because I thought that docopt::value::Kind::StringList was an unnecessarily long name. I found out that this library uses tabs instead of spaces. The raging war between tabs and spaces continues!


    I've been thinking about ways to refactor docopt::value for a while now and a few of them break backwards compatibility. Something that doesn't change the interface but cleans up the internals a little bit is the use of a visitor (much like std::visit). It could look something like the following.

    struct value {
    private:
      template <typename ValueA, typename ValueB, typename Func>
      static void visit(ValueA &a, ValueB &b, Func func) {
        assert(a.mKind == b.mKind);
        switch (a.mKind) {
          case Kind::Bool:
            return func(a.mVariant.boolValue, b.mVariant.boolValue);
          case Kind::Long:
            return func(a.mVariant.longValue, b.mVariant.longValue);
          case Kind::String:
            return func(a.mVariant.strValue, b.mVariant.strValue);
          case Kind::StringList:
            return func(a.mVariant.strList, b.mVariant.strList);
          case Kind::Empty: ;
        }
      }
    };
    

    That simplifies a lot of the other functions. Like operator== for example.

    bool docopt::value::operator==(const value &other) const {
      if (mKind != other.mKind) return false;
      bool equal = true;
      visit(*this, other, [&equal](auto &self, auto &other) {
        equal = (self == other);
      });
      return equal;
    }
    

    Some other changes would be to rename docopt::value to docopt::Value, mark as many functions as possible with noexcept, use .hpp (C++ header file) instead of .h (C header file), also that convertToLong thing I've been rattling on about (which can be implemented in C++11 but better with C++17). Would some of these changes be accepted in a PR? What about the breaking changes? Should I stick to C++11 (it's almost 10 years old at this point)?

    opened by indianakernick 9
  • Fix several parsing issues + association of short and long options

    Fix several parsing issues + association of short and long options

    Hi,

    That patch fixes the following:

    • when an option name between <> contains space, it's not handled correctly
    • long option is detected as a short option
    • default value is not detected
    • when a long and short options are possible, they are not put together

    In the last case, the value set for the passed version is also assigned to its companion: for instance, if "-h, --help" are defined, if we pass only "-h", both "-h" and "--help" are set to true. The inverse is also true. I didn't find if it was or not the behavior expected, but I considered as a bug.

    I've also updated the test cases to take into account that long and short options are associated.

    what do you think of it?

    opened by toch 9
  • Abort trap 6 failure if linking with MPI

    Abort trap 6 failure if linking with MPI

    Linking certain versions of OpenMPI or mpich cause abort trap while running. I attach example and CMake setup. On my macos system I get the issue with mpich 3.2.1; with openmpi 3.1.3, but not with openmpi 1.6.3. It happens regardless if MPI_Init() is called or not. Without docopt, I can compile and run parallel programs with all mentioned MPI versions.

    cmake .
    make hello
    ./hello --help
    Abort trap: 6
    

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.11.4 FATAL_ERROR)
    set(CMAKE_CXX_STANDARD 14)
    set(CMAKE_CXX_STANDARD_REQUIRED YES)
    set(CMAKE_CXX_EXTENSIONS NO)
    find_package(MPI REQUIRED)
    set(docopt_SOURCES docopt.cpp)
    set(docopt_HEADERS docopt.h docopt_private.h docopt_util.h docopt_value.h)
    add_executable(hello hello.cpp ${docopt_SOURCES} ${docopt_HEADERS})
    target_link_libraries(hello PRIVATE MPI::MPI_CXX) # runs fine if this is commented out
    

    hello.cpp

    #include "docopt.h"
    #include <iostream>
    
    static const char USAGE[] =
    R"(Naval Fate.
    
        Usage:
          naval_fate ship new <name>...
          naval_fate ship <name> move <x> <y> [--speed=<kn>]
          naval_fate ship shoot <x> <y>
          naval_fate mine (set|remove) <x> <y> [--moored | --drifting]
          naval_fate (-h | --help)
          naval_fate --version
    
        Options:
          -h --help     Show this screen.
          --version     Show version.
          --speed=<kn>  Speed in knots [default: 10].
          --moored      Moored (anchored) mine.
          --drifting    Drifting mine.
    )";
    
    int main(int argc, char** argv)
    {
        std::map<std::string, docopt::value> args
            = docopt::docopt(USAGE,
                    { argv + 1, argv + argc },
                    true,               // show help if requested
                    "Naval Fate 2.0", true);  // version string
        for(auto const& arg : args)
            std::cout << arg.first <<  arg.second << std::endl;
        return 0;
    }
    
    question 
    opened by mlund 8
  • Crash inside regex

    Crash inside regex

    This is my usage string:

    static const char usage[] =
    R"( Usage:
      my_app [-s] [-t <num_threads>] [--config <cfg_file>] [--ult | --test] [<client>]
      my_app (-h | --help)
    
     Options:
      -s                   Display users' stats.
      -t <num_threads>     Limit number of worker threads.
      --config <cfg_file>  Path to configuration file. [default: data/cfg_fimi.yaml]
      --ult                Run tests: unit level.
      --test               Run tests: full test suite.
      -h --help            Show this screen.
    )";
    

    It causes infinite recursion and a crash inside regex matcher. I run it on windows 10, visual studio 15 version as snipped below: image

    Remove either of these lines from the options section:

      -t <num_threads>     Limit number of worker threads.
      --config <cfg_file>  Path to configuration file. [default: data/cfg_fimi.yaml]
    

    and then it works fine. It looks like adding too many option lines causes some issue in the regex runtime. I have no idea if this is VS std library problem, something wrong with docopt or I'm doing something wrong with my usage string. Debugging the regex runtime is rather time consuming and after a quick try I didn't come to any conclusion.

    duplicate 
    opened by jdukat 8
  • Fix/export operator symbol

    Fix/export operator symbol

    Hi Jared,

    I know some PRs are already opened to fix both issues fixed by this one (i.e. DLL interface for operator<< and building only one target at a time), but they are stalling since a few months right now, so I hope this will make it go forward 😄

    opened by theodelrieu 7
  • Consider removing noexcept on `docopt::docopt()`.

    Consider removing noexcept on `docopt::docopt()`.

    Right now, docopt::docopt() is marked as noexcept. However, it can throw exceptions. In particular, it threw a std::regex_error(). Because of the noexcept, this caused the program to terminate. It would have been nice for me to have the chance to give a more meaningful error message when docopt gives that exception. What is the reason for the noexcept?

    opened by chrisdembia 7
  • Check how docopt is used to decide whether generate install target or not.

    Check how docopt is used to decide whether generate install target or not.

    When I try to use docopt through FecthContent of cmake, docopt.cpp generate the install target as well, which is annoying.

    Although there is [a way][stackoverflow-link] to exclude the installation of docopt.cpp, it's not so elegant.

    I write this patch by checking how spdlog handling this not-root-project situation. It seems work.

    opened by black-desk 0
  • Add CMake imported target for docopt library

    Add CMake imported target for docopt library

    This PR writes the CMake config-file package using CMakePackageConfigHelpers and exports the target as a Docopt::docopt imported target.

    This allows developers to install and use the library without necessarily requiring root permission by:

    1. Installing docopt with -DCMAKE_INSTALL_PREFIX="${HOME}/wherever"
    2. then using with -DCMAKE_PREFIX_PATH="${HOME}/wherever" and linking to imported target Docopt::docopt.

    Keeping in mind the newly released FetchContent and find_package() integration, also add an alias target so that Docopt::docopt can be linked to regardless of whether the build uses a prebuilt package or fetches the sources.

    opened by eaaltonen 2
  • Unused variable in `Option::parse`

    Unused variable in `Option::parse`

    The following variable appears to be unused: https://github.com/docopt/docopt.cpp/blob/400e6dd8e59196c914dcc2c56caf7dae7efa5eb3/docopt_private.h#L549

    For context, I work on libc++ and we are considering enabling the unused variable warnings for some standard library types, including std::string. This produces a warning on your project and could potentially break some of the users (if they compile with warnings as errors), so we wanted to give you an early heads-up. The fix appears to be straightforward.

    opened by var-const 0
  • Move return so that switch has default case

    Move return so that switch has default case

    Commit

    • Move return so that switch has default case

    When a project using docopt.cpp is built with -Werror=switch-default option, there's an error

    error: switch missing default case [-Werror=switch-default]
    

    which this fixes.

    Signed-off-by: Eero Aaltonen [email protected]

    opened by eaaltonen 1
  • Unclear/undocumented value interface.

    Unclear/undocumented value interface.

    So I've found myself quite struggling to figure out how to use the returned code. Perhaps documentation or example with the use cases of the functions should be added:

    Use case that didn't work:

    constexpr char USAGE[] = R"(i3 geometric window switcher
    
    Usage:
      i3switch (next | prev) [wrap]
      i3switch number <num>
      i3switch (left | up | right | down) [wrap]
      i3switch (-h | --help)
    )"
    
    int main(int argc, char *argv) {
      auto args = docopt::docopt(std::string(USAGE), std::vector<std::string>(argv + 1, argv + argc), true, "0.1.0");
      
      int order;
      if (args["number"]) {
        order = args["<num>"].asLong();
      }
      
      direction2d = Direction2d::INVALID;
      for (std::pair<std::string, Direction2d> pair : direction_2d_map) {
        if (args[pair.first]) {
          direction2d = pair.second;
          break;
        }
      }
    }
    

    Command: i3 switch right

    By instinct I was looking for a common pattern like args["left"] or args["left"].empty() to check if argument was present. I expected that direction2d would be set to first encountered direction, and order to contain the value if number keyword was present.

    Turns out it's unclear what empty does, because You have to use asBool. And You can't figure it out unless You dig into the parsing, which shouldn't happend for API... So perhaps in example or in README these should get covered?

    opened by mibli 4
Releases(v0.6.3)
Owner
null
Lean4 port of Arduino balance car controller

lean4-balance-car This is a small proof-of-concept exercise to show a Lean 4 program controlling a real robotics platform which requires low latency c

Galois, Inc. 31 Jul 11, 2022
QEMU port for t8030

QEMU README QEMU is a generic and open source machine & userspace emulator and virtualizer. QEMU is capable of emulating a complete machine in softwar

null 1.7k Jan 4, 2023
Trial port of the rtf_433 Library for use with OpenMQTTGateway on a ESP32 and a CC1101 Transceiver

This is an attempt at creating an Arduino library for use on ESP32 boards with a CC1101 transceiver with the device decoders from the rtl_433 package.

Northern Man 92 Jan 3, 2023
Port of my M5Stack Core 2 audio monitor project to generic ESP32s with TFT screens

ESP32 Audio Monitor This is a port of this project to work with any ESP32 device with a TFT display. You can watch a video explainer here (YouTube) wh

atomic14 47 Nov 9, 2022
Doom port for InfOS - the University of Edinburgh Informatics research operating system used in the UG3 OS course

Doom on InfOS InfOS is the Informatics research operating system, designed specifically for the UG3 Operating Systems course. This project aims to por

Cheng Kai 14 Aug 20, 2022
Port of Golang channels to C++

Copper is a C++ library of a powerful queue object for communication between threads. It is based on Go's channels and follows the quote: Don't commun

null 155 Dec 20, 2022
NDS port of the uxn virtual machine

uxnds Quick and simple port of the uxn virtual machine to the NDS console. By default, uxnds will run /uxn/boot.rom. It also supports reading files fr

Adrian Siekierka 106 Dec 12, 2022
High Quality DeNoise 3D is an AviSynth port of the MPlayer filter of the same name

High Quality DeNoise 3D is an AviSynth port of the MPlayer filter of the same name. It performs a 3-way low-pass filter, which can completely remove high-frequency noise while minimizing blending artifacts.

null 13 Oct 3, 2022
A fast and small port of Zstandard to WASM.

Zstandard WASM A fast and small port of Zstandard to WASM. (Decompress-only for now). Features Fast: Zstandard has been compiled with the -03 flag, so

Fabio Spampinato 13 Nov 9, 2022
This is the Arduino® compatible port of the AIfES machine learning framework, developed and maintained by Fraunhofer Institute for Microelectronic Circuits and Systems.

AIfES for Arduino® AIfES (Artificial Intelligence for Embedded Systems) is a platform-independent and standalone AI software framework optimized for e

null 166 Jan 4, 2023
Doom port to the Ikea Tradfri RGB1923R5 and any device using Silicon labs EFR32MG21 based modules

MG21DOOM Doom port to the Ikea Tradfri RGB1923R5 lamp and any device using Silicon labs EFR32MG21 based modules. Coded by Nicola Wrachien. WARNING Do

null 20 Aug 2, 2022
A port of the Uxn virtual machine to the ESP32

Uxn An assembler and emulator for the Uxn stack-machine, written in ANSI C. Build Linux To build the Uxn emulator, you must have SDL2. If you wish to

Maxime ANDRÉ 27 Mar 24, 2022
Moonlight port for Nintendo Switch

Moonlight-Switch Moonlight-Switch is a port of Moonlight Game Streaming Project for Nintendo Switch. Thanks a lot to Rock88 and his Moonlight-NX, lots

Vinogradov Daniil 313 Jan 5, 2023
Hobbyist Operating System targeting x86_64 systems. Includes userspace, Virtual File System, An InitFS (tarfs), Lua port, easy porting, a decent LibC and LibM, and a shell that supports: piping, file redirection, and more.

SynnixOS Epic Hobby OS targeting x86_64 CPUs, it includes some hacked together functionality for most essential OSs although, with interactivity via Q

RaidTheWeb 42 Oct 28, 2022
Fix for various issues in the PC port of Ace Attorney Chronicles.

Hackfix for a few issues in the PC port - Animation framerate can now be set to arbitrary rate. (defaults to 60 but can be freely adjusted in the ini

Admiral H. Curtiss 82 Nov 28, 2022
This is a C port of Stefan Hirschmann's NoteBook FanControl.

It provides the same utilities with the same interfaces as the original NBFC, although the implementation differs.

null 161 Jan 2, 2023
This is a plan9 port of the vim editor.

This is a plan9 port of the vim editor.

phil9 5 Nov 30, 2022
Port of MIT's xv6 OS to the Nezha RISC-V board with Allwinner D1 SoC

xv6 is a re-implementation of Dennis Ritchie's and Ken Thompson's Unix Version 6 (v6). xv6 loosely follows the structure and style of v6, but is impl

Michael Engel 62 Dec 12, 2022
Apple cctools and ld64 port for Linux, *BSD and macOS

Apple cctools and ld64 port for Linux, *BSD and macOS

Thomas Pöchtrager 642 Dec 30, 2022