8000 Merge pull request #3 from docopt/fix-1 · AmesianX/docopt.cpp@2df7edc · GitHub
[go: up one dir, main page]

Skip to content

Commit 2df7edc

Browse files
committed
Merge pull request docopt#3 from docopt/fix-1
Fix docopt#1: Hangs until killed
2 parents ea59a92 + c343367 commit 2df7edc

File tree

3 files changed

+47
-26
lines changed

3 files changed

+47
-26
lines changed

README.rst

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,15 @@ and we have tried to maintain full feature parity (and code structure) as the
7171
original.
7272

7373
This port is written in C++11 and also requires a good C++11 standard library
74-
(in particular, one with ``regex`` support). The following compilers should
75-
be able to handle this:
74+
(in particular, one with ``regex`` support). The following compilers are known
75+
to work with docopt:
7676

77-
- clang 3.3
78-
- gcc 4.9 (If someone can verify this, or provide patches, that would be great!)
79-
- Visual C++ 2013: will *not* compile this code. Hopefully next year.
77+
- clang 3.3 and later
78+
- gcc 4.9
79+
80+
Note that gcc-4.8 will not work due to its missing the ``regex`` module.
81+
Note that Visual C++ 2013 will not compile this code, as its C++11 is not
82+
quite good enough. If a later VC++ works, please let me know!
8083

8184
This port is licensed under the MIT license, just like the original module.
8285
However, we are also dual-licensing this code under the Boost License, version 1.0,
@@ -436,4 +439,5 @@ Changelog
436439
**docopt** follows `semantic versioning <http://semver.org>`_. The
437440
first release with stable API will be 1.0.0 (soon).
438441

439-
- 0.6.4.1 The initial C++ port of docopt.py
442+
- 0.6.1 The initial C++ port of docopt.py
443+

docopt.cpp

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -174,23 +174,33 @@ Option Option::parse(std::string const& option_description)
174174
}
175175

176176
static const std::regex pattern {"(--|-)?(.*?)([,= ]|$)"};
177-
std::for_each(std::sregex_iterator{option_description.begin(), options_end, pattern},
178-
std::sregex_iterator{},
179-
[&](std::smatch const& match)
180-
{
181-
if (match[1].matched) {
182-
if (match[1].length()==1) {
183-
shortOption = "-" + match[2].str();
184-
} else {
185-
longOption = "--" + match[2].str();
186-
}
187-
} else if (match[2].matched && match[2].length()) {
188-
argcount = 1;
189-
} else {
190-
// delimeter
191-
}
192-
});
193-
177+
for(std::sregex_iterator i {option_description.begin(), options_end, pattern, std::regex_constants::match_not_null},
178+
e{};
179+
i != e;
180+
++i)
181+
{
182+
std::smatch const& match = *i;
183+
if (match[1].matched) { // [1] is optional.
184+
if (match[1].length()==1) {
185+
shortOption = "-" + match[2].str();
186+
} else {
187+
longOption = "--" + match[2].str();
188+
}
189+
} else if (match[2].length() > 0) { // [2] always matches.
190+
std::string m = match[2];
191+
argcount = 1;
192+
} else {
193+
// delimeter
194+
}
195+
196+
if (match[3].length() == 0) { // [3] always matches.
197+
// Hit end of string. For some reason 'match_not_null' will let us match empty
198+
// at the end, and then we'll spin in an infinite loop. So, if we hit an empty
199+
// match, we know we must be at the end.
200+
break;
201+
}
202+
}
203+
194204
if (argcount) {
195205
std::smatch match;
196206
if (std::regex_search(options_end, option_description.end(),
@@ -537,8 +547,16 @@ std::vector<T*> flat_filter(Pattern& pattern) {
537547
}
538548

539549
std::vector<std::string> parse_section(std::string const& name, std::string const& source) {
550+
// ECMAScript regex only has "?=" for a non-matching lookahead. In order to make sure we always have
551+
// a newline to anchor our matching, we have to avoid matching the final newline of each grouping.
552+
// Therefore, our regex is adjusted from the docopt Python one to use ?= to match the newlines before
553+
// the following lines, rather than after.
540554
std::regex const re_section_pattern {
541-
"(?:^|\\n)([^\\n]*" + name + "[^\\n]*\\n?(?:[ \\t].*?(?:\\n|$))*)",
555+
"(?:^|\\n)" // anchored at a linebreak (or start of string)
556+
"("
557+
"[^\\n]*" + name + "[^\\n]*(?=\\n?)" // a line that contains the name
558+
"(?:\\n[ \\t].*?(?=\\n|$))*" // followed by any number of lines that are indented
559+
")",
542560
std::regex::icase
543561
};
544562

@@ -571,7 +589,7 @@ std::vector<std::string> longOptions(I iter, I end) {
571589
std::vector<std::string> ret;
572590
std::transform(iter, end,
573591
std::back_inserter(ret),
574-
[](decltype(*iter) const& opt) { return opt->longOption(); });
592+
[](typename I::reference opt) { return opt->longOption(); });
575593
return ret;
576594
}
577595

docopt_value.h

Lines changed: 0 additions & 1 deletion
< 6667 div data-testid="neutral diffstat" class="DiffSquares-module__diffSquare--h5kjy DiffSquares-module__neutral--VlyoP">
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,6 @@ namespace docopt {
218218
}
219219

220220
template <class T>
221-
inline
222221
void hash_combine(std::size_t& seed, const T& v);
223222

224223
inline

0 commit comments

Comments
 (0)
0