Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes parsing of [default: x] in some cases on Win. #23

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 10 additions & 18 deletions docopt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -908,32 +908,24 @@ PatternList parse_argv(Tokens tokens, std::vector<Option>& options, bool options
}

std::vector<Option> 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<Option> 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;
}

Expand Down
12 changes: 12 additions & 0 deletions docopt_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef docopt_docopt_util_h
#define docopt_docopt_util_h

#include <regex>

#pragma mark -
#pragma mark General utility
Expand Down Expand Up @@ -85,6 +86,17 @@ namespace {
}
return ret;
}

std::vector<std::string> regex_split(std::string const& text, std::regex const& re)
{
std::vector<std::string> 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 {
Expand Down
18 changes: 18 additions & 0 deletions testcases.docopt
Original file line number Diff line number Diff line change
Expand Up @@ -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 <foo_>] [--baz <baz_>]

Options:
--foo <foo_>
Foo [default: 42]
--baz <baz_>
Baz [default: 1]
"""
$ prog
{"--baz": "1", "--foo": "42"}

$ prog --foo 82
{"--baz": "1", "--foo": "82"}