8000 Merge pull request #43 from Luthaf/master · indianakernick/docopt.cpp@52e3064 · GitHub
[go: up one dir, main page]

Skip to content

Commit 52e3064

Browse files
authored
Merge pull request docopt#43 from Luthaf/master
Support GCC 4.8, using Boost.Regex
2 parents c15f292 + 8f926b6 commit 52e3064

File tree

7 files changed

+163
-107
lines changed

7 files changed

+163
-107
lines changed

.travis.yml

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,24 @@ matrix:
1010
apt:
1111
sources: ['ubuntu-toolchain-r-test', 'george-edison55-precise-backports']
1212
packages: ["g++-5", "cmake-data", "cmake"]
13+
- os: linux
14+
env:
15+
- COMPILER=g++-4.8 USE_BOOST_REGEX=ON
16+
addons:
17+
apt:
18+
sources: ['ubuntu-toolchain-r-test', 'george-edison55-precise-backports', 'boost-latest']
19+
packages: ["g++-4.8", "cmake-data", "cmake", "libboost-regex1.55-dev"]
1320

1421
- os: linux
15-
env:
22+
env:
1623
- COMPILER=clang++-3.6 STDLIB=libc++
1724
addons:
1825
apt:
1926
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6', 'george-edison55-precise-backports']
2027
packages: ["clang-3.6", "cmake-data", "cmake"]
2128

2229
- os: linux
23-
env:
30+
env:
2431
- COMPILER=clang++-3.7 STDLIB=libc++
2532
addons:
2633
apt:
@@ -29,35 +36,41 @@ matrix:
2936

3037
- os: osx
3138
osx_image: xcode6.4
32-
env:
39+
env:
3340
- COMPILER=clang++ V='Apple LLVM 6.4'
3441
- COMPILER=clang++ V='Apple LLVM 6.4' WITH_CPP14=true
3542

3643
- os: osx
3744
osx_image: xcode7
38-
env:
45+
env:
3946
- COMPILER=clang++ V='Apple LLVM 7.0'
4047
- COMPILER=clang++ V='Apple LLVM 7.0' WITH_CPP14=true
4148

4249
before_install:
4350
- |
4451
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
45-
brew install cmake
52+
brew rm --force cmake && brew install cmake
4653
fi
4754
4855
- CMAKE_CXX_FLAGS+=" -Wall"
4956

5057
- if [[ "${WITH_CPP14}" == "true" ]]; then CMAKE_OPTIONS+=" -DCMAKE_CXX_STANDARD=14"; fi
58+
- |
59+
if [[ "${USE_BOOST_REGEX}" == "ON" ]]; then
60+
CMAKE_OPTIONS+=" -DUSE_BOOST_REGEX=ON"
61+
CMAKE_OPTIONS+=" -DBoost_REGEX_LIBRARY_DEBUG=/usr/lib/x86_64-linux-gnu/libboost_regex.so.1.55.0"
62+
CMAKE_OPTIONS+=" -DBoost_REGEX_LIBRARY_RELEASE=/usr/lib/x86_64-linux-gnu/libboost_regex.so.1.55.0"
63+
fi
5164
- if [[ "${STDLIB}" == "libc++" ]]; then CMAKE_CXX_FLAGS+=" -stdlib=libc++"; fi
5265

53-
- sh ${COMPILER} --version || true
66+
- ${COMPILER} --version
5467

5568
before_script:
5669
- rm -rf build/
5770
- mkdir build
5871
- cd build
5972
- cmake -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} -DWITH_TESTS=1 -DWITH_EXAMPLE=1 ${CMAKE_OPTIONS} ..
6073

61-
script:
74+
script:
6275
- cmake --build .
6376
- python run_tests

CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ include(GNUInstallDirs)
88
#============================================================================
99
option(WITH_TESTS "Build tests." OFF)
1010
option(WITH_EXAMPLE "Build example." OFF)
11+
option(USE_BOOST_REGEX "Replace std::regex with Boost.Regex" OFF)
1112

1213
#============================================================================
1314
# Internal compiler options
@@ -52,6 +53,19 @@ if(NOT MSVC)
5253
set_target_properties(docopt_s PROPERTIES OUTPUT_NAME docopt)
5354
endif()
5455

56+
if(USE_BOOST_REGEX)
57+
add_definitions("-DDOCTOPT_USE_BOOST_REGEX")
58+
# This is needed on Linux, where linking a static library into docopt.so
59+
# fails because boost static libs are not compiled with -fPIC
60+
set(Boost_USE_STATIC_LIBS OFF)
61+
find_package(Boost 1.53 REQUIRED COMPONENTS regex)
62+
include_directories(${Boost_INCLUDE_DIRS})
63+
target_link_libraries(docopt ${Boost_LIBRARIES})
64+
if(WITH_STATIC)
65+
target_link_libraries(docopt_s ${Boost_LIBRARIES})
66+
endif()
67+
endif()
68+
5569
#============================================================================
5670
# Examples
5771
#============================================================================

README.rst

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ and instead can write only the help message--*the way you want it*.
4242

4343
int main(int argc, const char** argv)
4444
{
45-
std::map<std::string, docopt::value> args
46-
= docopt::docopt(USAGE,
45+
std::map<std::string, docopt::value> args
46+
= docopt::docopt(USAGE,
4747
{ argv + 1, argv + argc },
4848
true, // show help if requested
4949
"Naval Fate 2.0"); // version string
@@ -78,7 +78,10 @@ to work with docopt:
7878
- GCC 4.9
7979
- Visual C++ 2015 RC
8080

81-
Note that GCC-4.8 will not work due to its missing the ``regex`` module.
81+
GCC-4.8 can work, but the std::regex module needs to be replaced with ``Boost.Regex``.
82+
In that case, you will need to define ``DOCTOPT_USE_BOOST_REGEX`` when compiling
83+
docopt, and link your code with the appropriated Boost libraries. A relativley
84+
recent version of Boost is needed: 1.55 works, but 1.46 does not for example.
8285

8386
This port is licensed under the MIT license, just like the original module.
8487
However, we are also dual-licensing this code under the Boost License, version 1.0,
@@ -92,8 +95,8 @@ The differences from the Python port are:
9295
* a ``docopt::value`` type to hold the various value types that can be parsed.
9396
We considered using boost::variant, but it seems better to have no external
9497
dependencies (beyond a good STL).
95-
* because C++ is statically-typed and Python is not, we had to make some
96-
changes to the interfaces of the internal parse tree types.
98+
* because C++ is statically-typed and Python is not, we had to make some
99+
changes to the interfaces of the internal parse tree types.
97100
* because ``std::regex`` does not have an equivalent to Python's regex.split,
98101
some of the regex's had to be restructured and additional loops used.
99102

@@ -126,7 +129,7 @@ API
126129
- ``argv`` is a vector of strings representing the args passed. Although
127130
main usually takes a ``(int argc, const char** argv)`` pair, you can
128131
pass the value ``{argv+1, argv+argc}`` to generate the vector automatically.
129-
(Note we skip the argv[0] argument!) Alternatively you can supply a list of
132+
(Note we skip the argv[0] argument!) Alternatively you can supply a list of
130133
strings like ``{ "--verbose", "-o", "hai.txt" }``.
131134

132135
- ``help``, by default ``true``, specifies whether the parser should
@@ -155,8 +158,8 @@ API
155158
compatibility with POSIX, or if you want to dispatch your arguments
156159
to other programs.
157160

158-
The **return** value is a ``map<string, docopt::value>`` with options,
159-
arguments and commands as keys, spelled exactly like in your help message.
161+
The **return** value is a ``map<string, docopt::value>`` with options,
162+
arguments and commands as keys, spelled exactly like in your help message.
160163
Long versions of options are given priority. For example, if you invoke the
161164
top example as::
162165

@@ -372,7 +375,7 @@ We have an extensive list of `examples
372375
every aspect of functionality of **docopt**. Try them out, read the
373376
source if in doubt.
374377

375-
There are also very intersting applications and ideas at that page.
378+
There are also very intersting applications and ideas at that page.
376379
Check out the sister project for more information!
377380

378381
Subparsers, multi-level help and *huge* applications (like git)
@@ -397,7 +400,7 @@ a C++ test case runner (run_testcase.cpp)::
397400

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

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

@@ -424,10 +427,10 @@ You can also compile the example shown at the start (included as example.cpp)::
424427
Development
425428
---------------------------------------------------
426429

427-
Comments and suggestions are *very* welcome! If you find issues, please
430+
Comments and suggestions are *very* welcome! If you find issues, please
428431
file them and help improve our code!
429432

430-
Please note, however, that we have tried to stay true to the original
433+
Please note, however, that we have tried to stay true to the original
431434
Python code. If you have any major patches, structural changes, or new features,
432435
we might want to first negotiate these changes into the Python code first.
433436
However, bring it up! Let's hear it!
@@ -439,4 +442,3 @@ Changelog
439442
first release with stable API will be 1.0.0 (soon).
440443

441444
- 0.6.1 The initial C++ port of docopt.py
442-

docopt.cpp

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include <unordered_map>
1818
#include <map>
1919
#include <string>
20-
#include <regex>
2120
#include <iostream>
2221
#include <cassert>
2322
#include <cstddef>
@@ -522,31 +521,23 @@ static PatternList parse_argv(Tokens tokens, std::vector<Option>& options, bool
522521
return ret;
523522
}
524523

525-
static std::vector<Option> parse_defaults(std::string const& doc) {
526-
// This pattern is a bit more complex than the python docopt one due to lack of
527-
// re.split. Effectively, it grabs any line with leading whitespace and then a
528-
// hyphen; it stops grabbing when it hits another line that also looks like that.
529-
static std::regex const pattern {
524+
std::vector<Option> parse_defaults(std::string const& doc) {
525+
// This pattern is a delimiter by which we split the options.
526+
// The delimiter is a new line followed by a whitespace(s) followed by one or two hyphens.
527+
static std::regex const re_delimiter{
530528
"(?:^|\\n)[ \\t]*" // a new line with leading whitespace
531-
"(-(.|\\n)*?)" // a hyphen, and then grab everything it can...
532-
"(?=\\n[ \\t]*-|$)" // .. until it hits another new line with space and a hyphen
529+
"(?=-{1,2})" // [split happens here] (positive lookahead) ... and followed by one or two hyphes
533530
};
534531

535532
std::vector<Option> defaults;
533+
for (auto s : parse_section("options:", doc)) {
534+
s.erase(s.begin(), s.begin() + s.find(':') + 1); // get rid of "options:"
536535

537-
for(auto s : parse_section("options:", doc)) {
538-
s.erase(s.begin(), s.begin()+static_cast<std::ptrdiff_t>(s.find(':'))+1); // get rid of "options:"
539-
540-
std::for_each(std::sregex_iterator{ s.begin(), s.end(), pattern },
541-
std::sregex_iterator{},
542-
[&](std::smatch const& m)
543-
{
544-
std::string opt = m[1].str();
545-
536+
for (const auto& opt : regex_split(s, re_delimiter)) {
546537
if (starts_with(opt, "-")) {
547538
defaults.emplace_back(Option::parse(opt));
548539
}
549-
});
540+
}
550541
}
551542

552543
return defaults;

0 commit comments

Comments
 (0)
0