diff --git a/docopt.cpp b/docopt.cpp index 2aed8a4..03d8719 100644 --- a/docopt.cpp +++ b/docopt.cpp @@ -908,32 +908,24 @@ PatternList parse_argv(Tokens tokens, std::vector& options, bool options } std::vector parse_defaults(std::string const& doc) { - // This pattern is a bit more complex than the python docopt one due to lack of - // re.split. Effectively, it grabs any line with leading whitespace and then a - // hyphen; it stops grabbing when it hits another line that also looks like that. - static std::regex const pattern { + // This pattern is a delimiter by which we split the options. + // The delimiter is a new line followed by a whitespace(s) followed by one or two hyphens. + static std::regex const re_delimiter{ "(?:^|\\n)[ \\t]*" // a new line with leading whitespace - "(-(.|\\n)*?)" // a hyphen, and then grab everything it can... - "(?=\\n[ \\t]*-|$)" // .. until it hits another new line with space and a hyphen + "(?=-{1,2})" // [split happens here] (positive lookahead) ... and followed by one or two hyphes }; - + std::vector defaults; - - for(auto s : parse_section("options:", doc)) { - s.erase(s.begin(), s.begin()+s.find(':')+1); // get rid of "options:" + + for (auto s : parse_section("options:", doc)) { + s.erase(s.begin(), s.begin() + s.find(':') + 1); // get rid of "options:" - std::for_each(std::sregex_iterator{ s.begin(), s.end(), pattern }, - std::sregex_iterator{}, - [&](std::smatch const& m) - { - std::string opt = m[1].str(); - + for (const auto& opt : regex_split(s, re_delimiter)) { if (starts_with(opt, "-")) { defaults.emplace_back(Option::parse(opt)); } - }); + } } - return defaults; } diff --git a/docopt_util.h b/docopt_util.h index 966158a..79f679b 100644 --- a/docopt_util.h +++ b/docopt_util.h @@ -9,6 +9,7 @@ #ifndef docopt_docopt_util_h #define docopt_docopt_util_h +#include #pragma mark - #pragma mark General utility @@ -85,6 +86,17 @@ namespace { } return ret; } + + std::vector regex_split(std::string const& text, std::regex const& re) + { + std::vector ret; + for (auto it = std::sregex_token_iterator(text.begin(), text.end(), re, -1); + it != std::sregex_token_iterator(); + ++it) { + ret.emplace_back(*it); + } + return ret; + } } namespace docopt { diff --git a/testcases.docopt b/testcases.docopt index efe9a07..2969be7 100644 --- a/testcases.docopt +++ b/testcases.docopt @@ -955,3 +955,21 @@ other options: """ $ prog --baz --egg {"--foo": false, "--baz": true, "--bar": false, "--egg": true, "--spam": false} + +# +# Tests new lines in options +# +r"""Usage: + prog [--foo ] [--baz ] + +Options: + --foo + Foo [default: 42] + --baz + Baz [default: 1] +""" +$ prog +{"--baz": "1", "--foo": "42"} + +$ prog --foo 82 +{"--baz": "1", "--foo": "82"}