├── .gitignore
├── CMakeLists.txt
├── Example_Images
├── example_automated_script_that_watches_a_folder.sh
├── example_command_invocation_for_test_input_jpg.sh
├── test_input.jpg
├── test_output_left_page.jpg
└── test_output_right_page.jpg
├── LICENSE.md
├── README.md
├── docopt-0.6.2
├── .gitignore
├── .travis.yml
├── CMakeLists.txt
├── LICENSE-Boost-1.0
├── LICENSE-MIT
├── README.rst
├── docopt-config.cmake
├── docopt.cpp
├── docopt.h
├── docopt_private.h
├── docopt_util.h
├── docopt_value.h
├── examples
│ └── naval_fate.cpp
├── main.cpp
├── run_testcase.cpp
├── run_tests.py
└── testcases.docopt
├── main.cpp
├── marker.cpp
├── marker.h
├── markers
├── markers.ai
├── markers.pdf
├── markers_for_book_scanner.ai
└── markers_for_book_scanner.pdf
├── page.cpp
├── page.h
└── voussoir.spec
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 |
6 | # Compiled Dynamic libraries
7 | *.so
8 |
9 | # Compiled Static libraries
10 | *.lai
11 | *.la
12 | *.a
13 |
14 | # Ignore SCons-related files
15 | .sconsign.dblite
16 |
17 | # Ignore CMake-related files
18 | CMakeFiles
19 | CMakeCache.txt
20 | cmake_install.cmake
21 | Makefile
22 |
23 | # Ignore OS X related files
24 | .DS_Store
25 |
26 | # Ignore executables
27 | bin
28 |
29 | # Ignore Miscellaneous
30 | scratchpad
31 |
32 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8)
2 |
3 | PROJECT(voussoir CXX)
4 |
5 | set(ROOT ./)
6 |
7 | include_directories(${ROOT})
8 |
9 | ADD_EXECUTABLE(voussoir main.cpp marker.cpp page.cpp)
10 |
11 | FIND_PACKAGE(OpenCV REQUIRED)
12 |
13 | TARGET_LINK_LIBRARIES(voussoir ${OpenCV_LIBS})
14 |
15 | ##############
16 | # For getting docopt to work
17 | ##############
18 |
19 | target_compile_definitions(voussoir PRIVATE DOCOPT_HEADER_ONLY=1) # This is added because of an if statement at the bottom of docopt.h -- this enables actually including docopt.cpp from docopt.h.
20 | set(CMAKE_CXX_FLAGS "-std=c++11") # docopt needs this, per https://github.com/Qihoo360/logkafka/issues/1
21 |
22 | ##############
23 |
24 | FILE(COPY ${PROJECT_SOURCE_DIR}/Example_Images/test_input.jpg DESTINATION ${PROJECT_BINARY_DIR}/bin/docs)
25 | FILE(COPY ${PROJECT_SOURCE_DIR}/markers/markers_for_book_scanner.ai DESTINATION ${PROJECT_BINARY_DIR}/bin/docs)
26 | FILE(COPY ${PROJECT_SOURCE_DIR}/markers/markers_for_book_scanner.pdf DESTINATION ${PROJECT_BINARY_DIR}/bin/docs)
27 |
28 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
29 |
--------------------------------------------------------------------------------
/Example_Images/example_automated_script_that_watches_a_folder.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ################################
4 | # Notes
5 | ################################
6 |
7 | # This script requires that inotifywait be installed. Sometimes inotifywait comes in a larger package called inotify-tools.
8 |
9 | # You can stop the script with Ctrl+C
10 |
11 | ################################
12 | # End Notes
13 | ################################
14 |
15 | ################################
16 | # Settings
17 | ################################
18 |
19 | # Neither of these path names should have a trailing slash (i.e., a '/' at the end):
20 | directory_to_watch="/home/jacoblevernier/Downloads/test"
21 | output_directory="/home/jacoblevernier/Downloads/test/output"
22 |
23 | program_location="/home/jacoblevernier/Downloads/bookscan/bin/voussoir"
24 |
25 | program_arguments="--verbose"
26 |
27 | ################################
28 | # End Settings
29 | ################################
30 |
31 | # Create the output directory if necessary:
32 | mkdir --parents "$output_directory"
33 | cd "$directory_to_watch"
34 |
35 | # Watch for files to be placed into $directory_to_watch. When they are, run the program on them.
36 | inotifywait --monitor "$directory_to_watch" --format '%f' -e close_write | \
37 | while read file; do
38 | "$program_location" \
39 | $program_arguments \
40 | --input-image "$file" \
41 | "$output_directory/$file-left_page" \
42 | "$output_directory/$file-right_page"
43 | done
44 |
--------------------------------------------------------------------------------
/Example_Images/example_command_invocation_for_test_input_jpg.sh:
--------------------------------------------------------------------------------
1 | ./bin/voussoir \
2 | --verbose \
3 | --offset-left-page-left-side 0.3 \
4 | --offset-left-page-right-side 0.3 \
5 | --offset-left-page-top-side 0.2 \
6 | --offset-left-page-bottom-side -0.2 \
7 | --offset-right-page-left-side -0.4 \
8 | --offset-right-page-right-side -0.3 \
9 | --offset-right-page-top-side 0.25 \
10 | --offset-right-page-bottom-side -0.2 \
11 | -i bin/docs/test_input.jpg \
12 | ~/Downloads/voussoir_output/test1.jpg \
13 | ~/Downloads/voussoir_output/test2.jpg
14 |
--------------------------------------------------------------------------------
/Example_Images/test_input.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jglev/voussoir/efff2fe86a986e2fc2052270749b8c3b99f71dc9/Example_Images/test_input.jpg
--------------------------------------------------------------------------------
/Example_Images/test_output_left_page.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jglev/voussoir/efff2fe86a986e2fc2052270749b8c3b99f71dc9/Example_Images/test_output_left_page.jpg
--------------------------------------------------------------------------------
/Example_Images/test_output_right_page.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jglev/voussoir/efff2fe86a986e2fc2052270749b8c3b99f71dc9/Example_Images/test_output_right_page.jpg
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012, 2016, Yutaka Tsutano
2 | Portions copyright 2016, Jacob Levernier
3 |
4 | Permission to use, copy, modify, and/or distribute this software for any
5 | purpose with or without fee is hereby granted, provided that the above
6 | copyright notice and this permission notice appear in all copies.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
10 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 | PERFORMANCE OF THIS SOFTWARE.
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # voussoir *("voo-swar")*
2 |
3 | A single-camera solution for book scanning.
4 |
5 | This program takes images of books (each picture including either one page or a two-page spread), detects special glyphs pasted in the corners of the book's pages, and **[de-keystones](https://en.wikipedia.org/wiki/Keystone_effect "Wikipedia: 'Keystone Effect'") and thereby digitally flattens the pages.** It then **automatically separates the pages into separate, cropped image files.**
6 |
7 | ## Why is this program called "voussoir"?
8 |
9 | A [voussoir](https://en.wikipedia.org/wiki/Voussoir "Wikipedia: 'Voussoir'") is a stone in an archway; a [keystone](https://en.wikipedia.org/wiki/Keystone_(architecture) "Wikipedia: 'Keystone'") is a type of voussoir. Voussoir (the software) is meant to be one piece among several in a book scanning workflow (like one of several stones that compose an arch), and deals centrally with the ["keystone effect,"](https://en.wikipedia.org/wiki/Keystone_effect "Wikipedia: 'Keystone Effect'"), which is named after the type of arch stone : )
10 |
11 | Other useful open-source programs to use when book scanning include [darktable](http://www.darktable.org/ "darktable") and [ScanTailor](http://scantailor.org/ "ScanTailor"). An example workflow could include voussoir to de-keystone and crop images, darktable to adjust contrast and sharpen images, and ScanTailor to do final processing.
12 |
13 | # Example
14 |
15 | The program takes images like this:
16 |
17 |
18 |
19 |
20 |
21 | And turns them into images like these:
22 |
23 |
28 |
29 |
30 |
31 |
35 |
36 |
37 |
38 | # Background
39 |
40 | This program is an annotated and expanded fork of a one-day build written in 2012 by [Yutaka Tsutano](http://yutaka.tsutano.com/projects/others/ "Yutaka Tsutano's website"). Videos of Mr. Tsutano's prototype book scanner build and software tests are available here:
41 |
42 | * [Book Scanner: First Prototype](http://www.youtube.com/watch?v=rjzxlA9RWio)
43 | * [Book Scanner: Marker Test](http://www.youtube.com/watch?v=YXANjnry6CU)
44 | * [Book Scanner: Image Processing Test #1](http://www.youtube.com/watch?v=lHHPFBH2EkA)
45 |
46 | Mr. Tsutano posted the code after receiving requests from viewers of the above videos, and kindly released the code under the permissive [ISC license](https://en.wikipedia.org/wiki/ISC_license "ISC License") (which is [functionally equivalent to](http://choosealicense.com/licenses/#isc "ChooseALicense.com: ISC License") the [BSD 2-Clause](http://choosealicense.com/licenses/bsd-2-clause/ "BSD Two-Clause License") and [MIT](http://choosealicense.com/licenses/mit/ "MIT License") licenses) in 2016.
47 |
48 | Mr. Tsutano noted in the code's original readme that "this program was written in ad-hoc manner without thinking about publishing the source code. It was just a test of concept. So I published it. But it was a project that was done in a day years ago, and I have no time to verify it still works today." Jacob Levernier, a member of the [DIY Book Scanning](http://DIYBookscanner.org "DIYBookScanner.org") community, forked the codebase in 2016 in order to better document and clean it for a wider audience. The program now has a documented command-line interface that supports any size of book and fine-tuned adjustment of output image borders.
49 |
50 | ## Compilation
51 |
52 | ### Install OpenCV and `cmake`:
53 |
54 | * **MacPorts:** `sudo port install opencv cmake`
55 | * **Linux:**
56 | * **openSUSE**: `sudo zypper install opencv cmake libopencv2_4 opencv-devel`
57 | * **Ubuntu**: `sudo apt-get install opencv cmake opencv-dev` (This will also install opencv dependencies).
58 |
59 | ### Confirm that you have installed (and are using) `gcc` 4.9+
60 |
61 | This program uses [docopt](https://github.com/docopt/docopt.cpp "Docopt.cpp GitHub page"). Docopt does not need to be installed separately (i.e., it's bundled within this repository), but it *does* depend on `gcc` 4.9 or greater.
62 |
63 | If you are getting an error when compiling that includes "undefined reference to `std::regex_token_iterator`", run `gcc --version` and confirm that your `gcc` version is greater than or equal to 4.9. If not, you need to upgrade `gcc.` Note that `g++ --version`, `c++ --version`, and `cpp --version` should similarly show 4.9 or greater.
64 |
65 | If you've upgraded and are still seeing the error, it's likely that your system is still trying to use the lower version. In this case, one way to explicitly tell cmake which version to use (for example, version 5) is to replace the command `cmake ./` below with `cmake -DCMAKE_CXX_COMPILER=g++-5 .`.
66 |
67 | *\[If you successfully build the program on another type of system, please let me know, and I'll add the required packages here.]*
68 |
69 | ### Compile using `cmake` (See above for information regarding telling `cmake` explicitly which version of c++ to use):
70 |
71 | ```
72 | cd [directory of the source code]
73 | cmake ./
74 | make
75 | ```
76 |
77 | The binary executable will be saved under `./bin/voussoir`, along with .pdf and .ai copies of the glyphs/markers discussed below.
78 |
79 | # Usage
80 |
81 | ## Getting Ready to Use the Program / Taking Pictures
82 |
83 | Within the `markers` directory, you'll find PDF and Adobe Illustrator / Inkscape versions of a series of 15 "glyphs," small images that each comprises a unique pattern of pixels in a 6x6 grid. You'll need to print and cut out the glyphs; currently, only glyphs 0-3 (left page) and 4-7 (right page) are needed.
84 |
85 | Tape or otherwise affix the glyphs in **clockwise order** around the perimeter of each book page (for example, if you're using a glass or acrylic [platen](http://diybookscanner.org/ "DIYBookScanner.org -- Scroll down for a description of each part of a book scanner") to flatten the pages of a book, affix the glyphs in each corner of the platen: **starting at the top left and moving clockwise to the center/spine of the book,** glyphs 0, 1, 2, and 3 on the left page, and (again from top left and moving clockwise) glyphs 4, 5, 6, and 7 on the right page.
86 |
87 | Alternatively, instead of moving the markers for each book you scan, you can more permanently affix the markers to the outside of your platen or book cradle, and then use the program's "offset" command-line options to adjust the output images for each book.
88 |
89 | **Electrical tape** works well to affix the markers to glass or acrylic, because it is unlikely to leave residue.
90 |
91 | When you take photos, it should be under **bright, even lighting,** in order to make both the book pages and the glyphs visible and crisp. One of the advantages of using this program is that you can take photos from off center -- as long as the glyphs can all be clearly seen and are not blurry in the image, each page will be de-keystoned as if it had been photographed perpendicularly (i.e., straight on) from the camera.
92 |
93 | One useful workflow with this program is to set up your camera, take several test photos, and confirm that the program will be able to recognize the glyphs in them. Once you have confirmed this, you can scan the full book.
94 |
95 | Do note that the program only transforms the pages as two-dimensional objects; that is, it **assumes that the pages are each (individually) flat** (e.g., under a glass or acrylic platen). If the pages are **warped/curled** in addition to being keystoned, this program will not correct the curl (correcting curl is difficult to do; [ScanTailor](http://scantailor.org/ "ScanTailor"), also linked below, makes a good effort by looking for curves in lines of text on each page, as do commercial options like [Booksorber](http://booksorber.com/ "Booksorber"), which tries to find the outline of the book's pages; in general, though, dewarping a page consistently likely requires a more complicated setup using [lasers](https://github.com/duerig/laser-dewarp "Laser Dewarper DIY book scanning software") or [infrared light](https://www.youtube.com/watch?v=03ccxwNssmo "YouTube: 'BFS-Auto: High Speed Book Scanner at over 250 pages/min'").
96 |
97 | ## Using the Program
98 |
99 | The program takes six basic arguments:
100 |
101 | `./voussoir --page-height 10 --page-width 6 --input-image test_input.jpg output_left.jpg output_right.jpg`
102 |
103 | In this example, `test_input.jpg` is the input file name, and the final two arguments are the
104 | output file names. The page is 10 units high and 6 units wide (these can be inches or any other unit -- what matters is their relation to each other). If you do not specify a height and width, they will default to 9.5 and 6, respectively.
105 |
106 | Run `./bin/voussoir --help` to see additional options for making cropping ("offset") adjustments to each edge of each page, and/or for specifying that you only want to process a left page or right page (vs. both pages).
107 |
108 | ### Debugging using a Webcam
109 |
110 | To debug using a webcam, execute the program without an input file argument:
111 |
112 | ```
113 | ./voussoir
114 | ```
115 |
116 | If a webcam is found, this will cause a window to open, showing output from the webcam. When the four "left page" glyphs (i.e., glyphs 0, 1, 2, and 3) are detected by the webcam, a new window will open showing the de-keystoned image that the four glyphs surround. Similarly, when the four "right page" glyphs (i.e., glyphs 4, 5, 6, and 7) are detected by the webcam, an additional new window will open, showing the de-keystoned image for those four glyphs. Throughout this process, debugging text will be given in the terminal window, including which glyphs are detected.
117 |
118 | ### Example Scripts
119 |
120 | The Example_Images directory in this repository contains two example scripts.
121 |
122 | * `example_automated_script_that_watches_a_folder.sh` provides an approach for watching a directory and automatically processing any images that are placed into it.
123 | * `example_command_invocation_for_test_input_jpg.sh` provides an example invocation for the program for the image located in this repository under `Example_Images/test_input.jpg`.
124 |
125 | ### More on Book Scanning
126 |
127 | * If you're interested in building some **hardware** to flatten the pages of the book, I recommend exploring the [DIYBookScanner.org gallery and forums](http://diybookscanner.org/intro.html "DIYBookScanner.org: Gallery"). An especially popular and easy-to-build model was created by a gentleman named David Landin in 2013 out of **PVC plumbing pipe,** and can be viewed [here](http://diybookscanner.org/forum/viewtopic.php?f=14&t=2914 "DIYBookScanner.org: David Landin model").
128 | * Additionally, the founder of the DIYBookScanning community, [Daniel Reetz](http://www.danreetz.com/ "Daniel Reetz"), wrote an extensive [monograph](http://diybookscanner.org/archivist "DIYBookScanner.org: The Archivist") on DIY scanning hardware in 2015, when he retired from the project (see also [Mr. Reetz' blog post](http://www.danreetz.com/blog/2015/12/31/internet-dan-seems-to-be-dead/ "Daniel Reetz: 'Internet Dan Seems to be Dead'") about the site). Mr. Reetz' expertise on the topic is unmatched; his monograph is, in my opinion, the single best place to begin learning about DIY scanners (after the [DIYBookScanner.org home page](http://diybookscanner.org "DIYBookScanner.org: Home Page") and [gallery](http://diybookscanner.org/intro.html "DIYBookScanner.org: Gallery") linked above).
129 | * As noted above, if you are interested in post-processing for your book photos (e.g., white-balance correcting, further automatic cropping, etc., the output from this program can be used as input for **[darktable](http://www.darktable.org/ "darktable")** and **[ScanTailor](http://scantailor.org/ "ScanTailor"),** which are also free and open-source.
130 |
131 | # Todo
132 |
133 | * Add a command line option (perhaps '-a --list-of-images-with-alert-glyph ') for scanning workflows that involve occasional non-standard page sizes (for example, for books with inserts). The option would cause the program to behave differently if it recognizes an additional glyph (e.g., glyph #8 in the markers .pdf and .ai files); when the glyph is recognized, the input image name would be appended to a text file.
134 | * This would allow a scanner operator to take a picture of the book with image inserts extended, etc., but to temporarily affix the "alert" glyph anywhere near the book, and then remove the glyph and move on to the next pages of the book. This would simplify the process for going back and separately processing those non-standard pages later.
135 | * This could be defined in a separate function ("is_alert_glyph_present") called from main.cpp near where the page processing function is called for the left and right pages.
136 | * Establish a build process to allow distributing ready-to-use binaries for different platforms (including the major Linux distros 32- and 64-bit, OSX 64-bit, and Windows)
137 | * **Get more people on board!** I (Jacob) am not a C++ developer, so I see my role as primarily custodial right now (i.e., working on documentation and community-building).
138 | * **Hannes Künsebeck has written [a port of Voussoir to Python called `pyvoussoir`](https://github.com/hnesk/pyvoussoir). That project is likely to be more maintained than this one.**
139 |
140 | # Contributors (in reverse-chronological order)
141 |
142 | * [Jacob Levernier](http://adunumdatum.org "Jacob Levernier's website")
143 | * [Yutaka Tsutano](http://yutaka.tsutano.com "Yutaka Tsutano's website")
144 |
--------------------------------------------------------------------------------
/docopt-0.6.2/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 |
6 | # Compiled Dynamic libraries
7 | *.so
8 | *.dylib
9 | *.dll
10 |
11 | # Compiled Static libraries
12 | *.lai
13 | *.la
14 | *.a
15 |
16 | # Compiled examples, as per docs
17 | example
18 | naval_fate
19 | run_testcase
20 | run_testcase.exe
21 |
22 | # CMake temporary files
23 | CMakeCache.txt
24 | CMakeFiles
25 | CPackConfig.cmake
26 | CPackSourceConfig.cmake
27 | Makefile
28 | cmake_install.cmake
29 | docopt-config-version.cmake
30 |
31 | # Files configured by CMake
32 | run_tests
33 |
--------------------------------------------------------------------------------
/docopt-0.6.2/.travis.yml:
--------------------------------------------------------------------------------
1 | language: cpp
2 | sudo: false # Use the new container infrastructure
3 |
4 | matrix:
5 | include:
6 | - os: linux
7 | env:
8 | - COMPILER=g++-5 STDLIB=libc++
9 | addons:
10 | apt:
11 | sources: ['ubuntu-toolchain-r-test', 'george-edison55-precise-backports']
12 | 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"]
20 |
21 | - os: linux
22 | env:
23 | - COMPILER=clang++-3.6 STDLIB=libc++
24 | addons:
25 | apt:
26 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6', 'george-edison55-precise-backports']
27 | packages: ["clang-3.6", "cmake-data", "cmake"]
28 |
29 | - os: linux
30 | env:
31 | - COMPILER=clang++-3.7 STDLIB=libc++
32 | addons:
33 | apt:
34 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7', 'george-edison55-precise-backports']
35 | packages: ["clang-3.7", "cmake-data", "cmake"]
36 |
37 | - os: osx
38 | osx_image: xcode6.4
39 | env:
40 | - COMPILER=clang++ V='Apple LLVM 6.4'
41 | - COMPILER=clang++ V='Apple LLVM 6.4' WITH_CPP14=true
42 |
43 | - os: osx
44 | osx_image: xcode7
45 | env:
46 | - COMPILER=clang++ V='Apple LLVM 7.0'
47 | - COMPILER=clang++ V='Apple LLVM 7.0' WITH_CPP14=true
48 |
49 | before_install:
50 | - |
51 | if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
52 | brew rm --force cmake && brew install cmake
53 | fi
54 |
55 | - CMAKE_CXX_FLAGS+=" -Wall"
56 |
57 | - 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
64 | - if [[ "${STDLIB}" == "libc++" ]]; then CMAKE_CXX_FLAGS+=" -stdlib=libc++"; fi
65 |
66 | - ${COMPILER} --version
67 |
68 | before_script:
69 | - rm -rf build/
70 | - mkdir build
71 | - cd build
72 | - cmake -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} -DWITH_TESTS=1 -DWITH_EXAMPLE=1 ${CMAKE_OPTIONS} ..
73 |
74 | script:
75 | - cmake --build .
76 | - python run_tests
77 |
--------------------------------------------------------------------------------
/docopt-0.6.2/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.1)
2 | project(docopt.cpp VERSION 0.6.1)
3 |
4 | include(GNUInstallDirs)
5 |
6 | #============================================================================
7 | # Settable options
8 | #============================================================================
9 | option(WITH_TESTS "Build tests." OFF)
10 | option(WITH_EXAMPLE "Build example." OFF)
11 | option(USE_BOOST_REGEX "Replace std::regex with Boost.Regex" OFF)
12 |
13 | #============================================================================
14 | # Internal compiler options
15 | #============================================================================
16 | # C++ standard
17 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
18 | set(CMAKE_CXX_EXTENSIONS OFF)
19 | if(NOT CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD LESS 11)
20 | set(CMAKE_CXX_STANDARD 11)
21 | endif()
22 |
23 | # Suppression of "unknown pragma" warning on GCC
24 | if(CMAKE_COMPILER_IS_GNUCXX)
25 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas") # Code uses #pragma mark
26 | endif()
27 |
28 | #============================================================================
29 | # Sources & headers
30 | #============================================================================
31 | set(docopt_SOURCES docopt.cpp)
32 | set(docopt_HEADERS
33 | docopt.h
34 | docopt_private.h
35 | docopt_util.h
36 | docopt_value.h
37 | )
38 |
39 | #============================================================================
40 | # Compile targets
41 | #============================================================================
42 | if(MSVC OR XCODE)
43 | # MSVC requires __declspec() attributes, which are achieved via the
44 | # DOCOPT_DLL and DOCOPT_EXPORTS macros below. Since those macros are only
45 | # defined when building a shared library, we must build the shared and
46 | # static libraries completely separately.
47 | # Xcode does not support libraries with only object files as sources.
48 | # See https://cmake.org/cmake/help/v3.0/command/add_library.html?highlight=add_library
49 | add_library(docopt SHARED ${docopt_SOURCES} ${docopt_HEADERS})
50 | add_library(docopt_s STATIC ${docopt_SOURCES} ${docopt_HEADERS})
51 | else()
52 | # If not using MSVC or Xcode, we will create an intermediate object target
53 | # to avoid compiling the source code twice.
54 | add_library(docopt_o OBJECT ${docopt_SOURCES} ${docopt_HEADERS})
55 | set_target_properties(docopt_o PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
56 |
57 | add_library(docopt SHARED $)
58 | add_library(docopt_s STATIC $)
59 | endif()
60 |
61 | target_include_directories(docopt PUBLIC $ $)
62 | target_include_directories(docopt_s PUBLIC $ $)
63 |
64 | if(MSVC)
65 | # DOCOPT_DLL: Must be specified when building *and* when using the DLL.
66 | # That's what the "PUBLIC" means.
67 | # DOCOPT_EXPORTS: Must use __declspec(dllexport) when building the DLL.
68 | # "PRIVATE" means it's only defined when building the DLL.
69 | target_compile_definitions(docopt PUBLIC DOCOPT_DLL
70 | PRIVATE DOCOPT_EXPORTS)
71 | endif()
72 |
73 | if(NOT MSVC)
74 | set_target_properties(docopt PROPERTIES OUTPUT_NAME docopt)
75 | set_target_properties(docopt_s PROPERTIES OUTPUT_NAME docopt)
76 | endif()
77 |
78 | if(USE_BOOST_REGEX)
79 | add_definitions("-DDOCTOPT_USE_BOOST_REGEX")
80 | # This is needed on Linux, where linking a static library into docopt.so
81 | # fails because boost static libs are not compiled with -fPIC
82 | set(Boost_USE_STATIC_LIBS OFF)
83 | find_package(Boost 1.53 REQUIRED COMPONENTS regex)
84 | include_directories(${Boost_INCLUDE_DIRS})
85 | target_link_libraries(docopt ${Boost_LIBRARIES})
86 | if(WITH_STATIC)
87 | target_link_libraries(docopt_s ${Boost_LIBRARIES})
88 | endif()
89 | endif()
90 |
91 | #============================================================================
92 | # Examples
93 | #============================================================================
94 | if(WITH_EXAMPLE)
95 | add_executable(docopt_example examples/naval_fate.cpp)
96 | target_link_libraries(docopt_example docopt)
97 | endif()
98 |
99 | #============================================================================
100 | # Tests
101 | #============================================================================
102 | if(WITH_TESTS)
103 | set(TESTPROG "${CMAKE_CURRENT_BINARY_DIR}/run_testcase")
104 | set(TESTCASES "${PROJECT_SOURCE_DIR}/testcases.docopt")
105 | add_executable(run_testcase run_testcase.cpp)
106 | target_link_libraries(run_testcase docopt)
107 | configure_file(
108 | "${PROJECT_SOURCE_DIR}/run_tests.py"
109 | "${CMAKE_CURRENT_BINARY_DIR}/run_tests"
110 | ESCAPE_QUOTES
111 | )
112 | add_test("Testcases docopt" ${TESTPROG})
113 | endif()
114 |
115 | #============================================================================
116 | # Install
117 | #============================================================================
118 | set(export_name "docopt-targets")
119 |
120 | # Runtime package
121 | install(TARGETS docopt EXPORT ${export_name} DESTINATION ${CMAKE_INSTALL_LIBDIR})
122 |
123 | # Development package
124 | install(TARGETS docopt_s EXPORT ${export_name} DESTINATION ${CMAKE_INSTALL_LIBDIR})
125 | install(FILES ${docopt_HEADERS} DESTINATION include/docopt)
126 |
127 | # CMake Package
128 | include(CMakePackageConfigHelpers)
129 | write_basic_package_version_file("${PROJECT_BINARY_DIR}/docopt-config-version.cmake" COMPATIBILITY SameMajorVersion)
130 | install(FILES docopt-config.cmake ${PROJECT_BINARY_DIR}/docopt-config-version.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/docopt")
131 | install(EXPORT ${export_name} DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/docopt")
132 |
133 | #============================================================================
134 | # CPack
135 | #============================================================================
136 | set(CPACK_PACKAGE_NAME "docopt")
137 | set(CPACK_DEBIAN_PACKAGE_DEPENDS "")
138 | set(CPACK_RPM_PACKAGE_REQUIRES "")
139 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Beautiful command line interfaces")
140 | set(CPACK_PACKAGE_VENDOR "Jared Grubb")
141 | set(CPACK_PACKAGE_CONTACT ${CPACK_PACKAGE_VENDOR})
142 | set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.rst")
143 | set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE-MIT")
144 | set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
145 | set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
146 | set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
147 | set(CPACK_DEBIAN_PACKAGE_SECTION "Development")
148 | set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
149 | set(CPACK_RPM_PACKAGE_LICENSE "MIT")
150 | set(CPACK_STRIP_FILES TRUE)
151 | include(CPack)
152 |
--------------------------------------------------------------------------------
/docopt-0.6.2/LICENSE-Boost-1.0:
--------------------------------------------------------------------------------
1 | Boost Software License - Version 1.0 - August 17th, 2003
2 |
3 | Permission is hereby granted, free of charge, to any person or organization
4 | obtaining a copy of the software and accompanying documentation covered by
5 | this license (the "Software") to use, reproduce, display, distribute,
6 | execute, and transmit the Software, and to prepare derivative works of the
7 | Software, and to permit third-parties to whom the Software is furnished to
8 | do so, all subject to the following:
9 |
10 | The copyright notices in the Software and this entire statement, including
11 | the above license grant, this restriction and the following disclaimer,
12 | must be included in all copies of the Software, in whole or in part, and
13 | all derivative works of the Software, unless such copies or derivative
14 | works are solely in the form of machine-executable object code generated by
15 | a source language processor.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/docopt-0.6.2/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012 Vladimir Keleshev,
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the Software
6 | without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense,
8 | and/or sell copies of the Software, and to permit persons to
9 | whom the Software is furnished to do so, subject to the
10 | following conditions:
11 |
12 | The above copyright notice and this permission notice shall
13 | be included in all copies or substantial portions of the
14 | Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 | KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
19 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/docopt-0.6.2/README.rst:
--------------------------------------------------------------------------------
1 | ``docopt.cpp``: A C++11 Port
2 | ============================
3 | docopt creates *beautiful* command-line interfaces
4 | --------------------------------------------------
5 |
6 | Isn't it awesome how ``getopt`` (and ``boost::program_options`` for you fancy
7 | folk!) generate help messages based on your code?! These timeless functions
8 | have been around for decades and have proven we don't need anything better, right?
9 |
10 | *Hell no!* You know what's awesome? It's when the option parser *is*
11 | generated based on the beautiful help message that you write yourself!
12 | This way you don't need to write this stupid repeatable parser-code,
13 | and instead can write only the help message--*the way you want it*.
14 |
15 | **docopt** helps you create most beautiful command-line interfaces
16 | *easily*:
17 |
18 | .. code:: c++
19 |
20 | #include "docopt.h"
21 |
22 | #include
23 |
24 | static const char USAGE[] =
25 | R"(Naval Fate.
26 |
27 | Usage:
28 | naval_fate ship new ...
29 | naval_fate ship move [--speed=]
30 | naval_fate ship shoot
31 | naval_fate mine (set|remove) [--moored | --drifting]
32 | naval_fate (-h | --help)
33 | naval_fate --version
34 |
35 | Options:
36 | -h --help Show this screen.
37 | --version Show version.
38 | --speed= Speed in knots [default: 10].
39 | --moored Moored (anchored) mine.
40 | --drifting Drifting mine.
41 | )";
42 |
43 | int main(int argc, const char** argv)
44 | {
45 | std::map args
46 | = docopt::docopt(USAGE,
47 | { argv + 1, argv + argc },
48 | true, // show help if requested
49 | "Naval Fate 2.0"); // version string
50 |
51 | for(auto const& arg : args) {
52 | std::cout << arg.first << arg.second << std::endl;
53 | }
54 |
55 | return 0;
56 | }
57 |
58 | Beat that! The option parser is generated based on the docstring above
59 | that is passed to ``docopt::docopt`` function. ``docopt`` parses the usage
60 | pattern (``"Usage: ..."``) and option descriptions (lines starting
61 | with dash "``-``") and ensures that the program invocation matches the
62 | usage pattern; it parses options, arguments and commands based on
63 | that. The basic idea is that *a good help message has all necessary
64 | information in it to make a parser*.
65 |
66 | C++11 port details
67 | ---------------------------------------------------
68 |
69 | This is a port of the ``docopt.py`` module (https://github.com/docopt/docopt),
70 | and we have tried to maintain full feature parity (and code structure) as the
71 | original.
72 |
73 | 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 are known
75 | to work with docopt:
76 |
77 | - Clang 3.3 and later
78 | - GCC 4.9
79 | - Visual C++ 2015 RC
80 |
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.
85 |
86 | This port is licensed under the MIT license, just like the original module.
87 | However, we are also dual-licensing this code under the Boost License, version 1.0,
88 | as this is a popular C++ license. The licenses are similar and you are free to
89 | use this code under the terms of either license.
90 |
91 | The differences from the Python port are:
92 |
93 | * the addition of a ``docopt_parse`` function, which does not terminate
94 | the program on error
95 | * a ``docopt::value`` type to hold the various value types that can be parsed.
96 | We considered using boost::variant, but it seems better to have no external
97 | dependencies (beyond a good STL).
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.
100 | * because ``std::regex`` does not have an equivalent to Python's regex.split,
101 | some of the regex's had to be restructured and additional loops used.
102 |
103 | API
104 | ---------------------------------------------------
105 |
106 | .. code:: c++
107 |
108 | docopt::docopt(doc, argv, help /* =true */, version /* ="" */, options_first /* =false */)
109 |
110 | ``docopt`` takes 2 required and 3 optional arguments:
111 |
112 | - ``doc`` is a string that contains a **help message** that will be parsed to
113 | create the option parser. The simple rules of how to write such a
114 | help message are given in next sections. Here is a quick example of
115 | such a string (note that this example uses the "raw string literal" feature
116 | that was added to C++11):
117 |
118 | .. code:: c++
119 |
120 | R"(Usage: my_program [-hso FILE] [--quiet | --verbose] [INPUT ...]
121 |
122 | -h --help show this
123 | -s --sorted sorted output
124 | -o FILE specify output file [default: ./test.txt]
125 | --quiet print less text
126 | --verbose print more text
127 | )"
128 |
129 | - ``argv`` is a vector of strings representing the args passed. Although
130 | main usually takes a ``(int argc, const char** argv)`` pair, you can
131 | pass the value ``{argv+1, argv+argc}`` to generate the vector automatically.
132 | (Note we skip the argv[0] argument!) Alternatively you can supply a list of
133 | strings like ``{ "--verbose", "-o", "hai.txt" }``.
134 |
135 | - ``help``, by default ``true``, specifies whether the parser should
136 | automatically print the help message (supplied as ``doc``) and
137 | terminate, in case ``-h`` or ``--help`` option is encountered
138 | (options should exist in usage pattern, more on that below). If you
139 | want to handle ``-h`` or ``--help`` options manually (as other
140 | options), set ``help=false``.
141 |
142 | - ``version``, by default empty, is an optional argument that
143 | specifies the version of your program. If supplied, then, (assuming
144 | ``--version`` option is mentioned in usage pattern) when parser
145 | encounters the ``--version`` option, it will print the supplied
146 | version and terminate. ``version`` could be any printable object,
147 | but most likely a string, e.g. ``"2.1.0rc1"``.
148 |
149 | Note, when ``docopt`` is set to automatically handle ``-h``,
150 | ``--help`` and ``--version`` options, you still need to mention
151 | them in usage pattern for this to work (also so your users to
152 | know about them!)
153 |
154 | - ``options_first``, by default ``false``. If set to ``true`` will
155 | disallow mixing options and positional argument. I.e. after first
156 | positional argument, all arguments will be interpreted as positional
157 | even if the look like options. This can be used for strict
158 | compatibility with POSIX, or if you want to dispatch your arguments
159 | to other programs.
160 |
161 | The **return** value is a ``map`` with options,
162 | arguments and commands as keys, spelled exactly like in your help message.
163 | Long versions of options are given priority. For example, if you invoke the
164 | top example as::
165 |
166 | naval_fate ship Guardian move 100 150 --speed=15
167 |
168 | the return dictionary will be:
169 |
170 | .. code:: python
171 |
172 | {"--drifting": false, "mine": false,
173 | "--help": false, "move": true,
174 | "--moored": false, "new": false,
175 | "--speed": "15", "remove": false,
176 | "--version": false, "set": false,
177 | "": ["Guardian"], "ship": true,
178 | "": "100", "shoot": false,
179 | "": "150"}
180 |
181 | If any parsing error (in either the usage, or due to incorrect user inputs) is
182 | encountered, the program will exit with exit code -1.
183 |
184 | Note that there is another function that does not exit on error, and instead will
185 | propogate an exception that you can catch and process as you like. See the docopt.h file
186 | for information on the exceptions and usage:
187 |
188 | .. code:: c++
189 |
190 | docopt::docopt_parse(doc, argv, help /* =true */, version /* =true */, options_first /* =false)
191 |
192 |
193 | Help message format
194 | ---------------------------------------------------
195 |
196 | Help message consists of 2 parts:
197 |
198 | - Usage pattern, e.g.::
199 |
200 | Usage: my_program [-hso FILE] [--quiet | --verbose] [INPUT ...]
201 |
202 | - Option descriptions, e.g.::
203 |
204 | -h --help show this
205 | -s --sorted sorted output
206 | -o FILE specify output file [default: ./test.txt]
207 | --quiet print less text
208 | --verbose print more text
209 |
210 | Their format is described below; other text is ignored.
211 |
212 | Usage pattern format
213 | ----------------------------------------------------------------------
214 |
215 | **Usage pattern** is a substring of ``doc`` that starts with
216 | ``usage:`` (case *insensitive*) and ends with a *visibly* empty line.
217 | Minimum example:
218 |
219 | .. code:: python
220 |
221 | """Usage: my_program
222 |
223 | """
224 |
225 | The first word after ``usage:`` is interpreted as your program's name.
226 | You can specify your program's name several times to signify several
227 | exclusive patterns:
228 |
229 | .. code:: python
230 |
231 | """Usage: my_program FILE
232 | my_program COUNT FILE
233 |
234 | """
235 |
236 | Each pattern can consist of the following elements:
237 |
238 | - ****, **ARGUMENTS**. Arguments are specified as either
239 | upper-case words, e.g. ``my_program CONTENT-PATH`` or words
240 | surrounded by angular brackets: ``my_program ``.
241 | - **--options**. Options are words started with dash (``-``), e.g.
242 | ``--output``, ``-o``. You can "stack" several of one-letter
243 | options, e.g. ``-oiv`` which will be the same as ``-o -i -v``. The
244 | options can have arguments, e.g. ``--input=FILE`` or ``-i FILE`` or
245 | even ``-iFILE``. However it is important that you specify option
246 | descriptions if you want your option to have an argument, a default
247 | value, or specify synonymous short/long versions of the option (see
248 | next section on option descriptions).
249 | - **commands** are words that do *not* follow the described above
250 | conventions of ``--options`` or ```` or ``ARGUMENTS``,
251 | plus two special commands: dash "``-``" and double dash "``--``"
252 | (see below).
253 |
254 | Use the following constructs to specify patterns:
255 |
256 | - **[ ]** (brackets) **optional** elements. e.g.: ``my_program
257 | [-hvqo FILE]``
258 | - **( )** (parens) **required** elements. All elements that are *not*
259 | put in **[ ]** are also required, e.g.: ``my_program
260 | --path=...`` is the same as ``my_program
261 | (--path=...)``. (Note, "required options" might be not
262 | a good idea for your users).
263 | - **|** (pipe) **mutually exclusive** elements. Group them using **(
264 | )** if one of the mutually exclusive elements is required:
265 | ``my_program (--clockwise | --counter-clockwise) TIME``. Group
266 | them using **[ ]** if none of the mutually-exclusive elements are
267 | required: ``my_program [--left | --right]``.
268 | - **...** (ellipsis) **one or more** elements. To specify that
269 | arbitrary number of repeating elements could be accepted, use
270 | ellipsis (``...``), e.g. ``my_program FILE ...`` means one or
271 | more ``FILE``-s are accepted. If you want to accept zero or more
272 | elements, use brackets, e.g.: ``my_program [FILE ...]``. Ellipsis
273 | works as a unary operator on the expression to the left.
274 | - **[options]** (case sensitive) shortcut for any options. You can
275 | use it if you want to specify that the usage pattern could be
276 | provided with any options defined below in the option-descriptions
277 | and do not want to enumerate them all in usage-pattern.
278 | - "``[--]``". Double dash "``--``" is used by convention to separate
279 | positional arguments that can be mistaken for options. In order to
280 | support this convention add "``[--]``" to your usage patterns.
281 | - "``[-]``". Single dash "``-``" is used by convention to signify that
282 | ``stdin`` is used instead of a file. To support this add "``[-]``"
283 | to your usage patterns. "``-``" acts as a normal command.
284 |
285 | If your pattern allows to match argument-less option (a flag) several
286 | times::
287 |
288 | Usage: my_program [-v | -vv | -vvv]
289 |
290 | then number of occurrences of the option will be counted. I.e.
291 | ``args['-v']`` will be ``2`` if program was invoked as ``my_program
292 | -vv``. Same works for commands.
293 |
294 | If your usage patterns allows to match same-named option with argument
295 | or positional argument several times, the matched arguments will be
296 | collected into a list::
297 |
298 | Usage: my_program --path=...
299 |
300 | I.e. invoked with ``my_program file1 file2 --path=./here
301 | --path=./there`` the returned dict will contain ``args[''] ==
302 | ['file1', 'file2']`` and ``args['--path'] == ['./here', './there']``.
303 |
304 |
305 | Option descriptions format
306 | ----------------------------------------------------------------------
307 |
308 | **Option descriptions** consist of a list of options that you put
309 | below your usage patterns.
310 |
311 | It is necessary to list option descriptions in order to specify:
312 |
313 | - synonymous short and long options,
314 | - if an option has an argument,
315 | - if option's argument has a default value.
316 |
317 | The rules are as follows:
318 |
319 | - Every line in ``doc`` that starts with ``-`` or ``--`` (not counting
320 | spaces) is treated as an option description, e.g.::
321 |
322 | Options:
323 | --verbose # GOOD
324 | -o FILE # GOOD
325 | Other: --bad # BAD, line does not start with dash "-"
326 |
327 | - To specify that option has an argument, put a word describing that
328 | argument after space (or equals "``=``" sign) as shown below. Follow
329 | either or UPPER-CASE convention for options'
330 | arguments. You can use comma if you want to separate options. In
331 | the example below, both lines are valid, however you are recommended
332 | to stick to a single style.::
333 |
334 | -o FILE --output=FILE # without comma, with "=" sign
335 | -i , --input # with comma, without "=" sing
336 |
337 | - Use two spaces to separate options with their informal description::
338 |
339 | --verbose More text. # BAD, will be treated as if verbose option had
340 | # an argument "More", so use 2 spaces instead
341 | -q Quit. # GOOD
342 | -o FILE Output file. # GOOD
343 | --stdout Use stdout. # GOOD, 2 spaces
344 |
345 | - If you want to set a default value for an option with an argument,
346 | put it into the option-description, in form ``[default:
347 | ]``::
348 |
349 | --coefficient=K The K coefficient [default: 2.95]
350 | --output=FILE Output file [default: test.txt]
351 | --directory=DIR Some directory [default: ./]
352 |
353 | - If the option is not repeatable, the value inside ``[default: ...]``
354 | will be interpreted as string. If it *is* repeatable, it will be
355 | splited into a list on whitespace::
356 |
357 | Usage: my_program [--repeatable= --repeatable=]
358 | [--another-repeatable=]...
359 | [--not-repeatable=]
360 |
361 | # will be ['./here', './there']
362 | --repeatable= [default: ./here ./there]
363 |
364 | # will be ['./here']
365 | --another-repeatable= [default: ./here]
366 |
367 | # will be './here ./there', because it is not repeatable
368 | --not-repeatable= [default: ./here ./there]
369 |
370 | Examples
371 | ----------------------------------------------------------------------
372 |
373 | We have an extensive list of `examples
374 | `_ which cover
375 | every aspect of functionality of **docopt**. Try them out, read the
376 | source if in doubt.
377 |
378 | There are also very intersting applications and ideas at that page.
379 | Check out the sister project for more information!
380 |
381 | Subparsers, multi-level help and *huge* applications (like git)
382 | ----------------------------------------------------------------------
383 |
384 | If you want to split your usage-pattern into several, implement
385 | multi-level help (with separate help-screen for each subcommand),
386 | want to interface with existing scripts that don't use **docopt**, or
387 | you're building the next "git", you will need the new ``options_first``
388 | parameter (described in API section above). To get you started quickly
389 | we implemented a subset of git command-line interface as an example:
390 | `examples/git
391 | `_
392 |
393 | Compiling the example / Running the tests
394 | ----------------------------------------------------------------------
395 | The original Python module includes some language-agnostic unit tests,
396 | and these can be run with this port as well.
397 |
398 | The tests are a Python driver that uses the testcases.docopt file to then invoke
399 | a C++ test case runner (run_testcase.cpp)::
400 |
401 | $ clang++ --std=c++11 --stdlib=libc++ docopt.cpp run_testcase.cpp -o run_testcase
402 | $ python run_tests.py
403 | PASS (175)
404 |
405 | You can also compile the example shown at the start (included as example.cpp)::
406 |
407 | $ clang++ --std=c++11 --stdlib=libc++ -I . docopt.cpp examples/naval_fate.cpp -o naval_fate
408 | $ ./naval_fate --help
409 | [ ... ]
410 | $ ./naval_fate ship Guardian move 100 150 --speed=15
411 | --drifting: false
412 | --help: false
413 | --moored: false
414 | --speed: "15"
415 | --version: false
416 | : ["Guardian"]
417 | : "100"
418 | : "150"
419 | mine: false
420 | move: true
421 | new: false
422 | remove: false
423 | set: false
424 | ship: true
425 | shoot: false
426 |
427 | Development
428 | ---------------------------------------------------
429 |
430 | Comments and suggestions are *very* welcome! If you find issues, please
431 | file them and help improve our code!
432 |
433 | Please note, however, that we have tried to stay true to the original
434 | Python code. If you have any major patches, structural changes, or new features,
435 | we might want to first negotiate these changes into the Python code first.
436 | However, bring it up! Let's hear it!
437 |
438 | Changelog
439 | ---------------------------------------------------
440 |
441 | **docopt** follows `semantic versioning `_. The
442 | first release with stable API will be 1.0.0 (soon).
443 |
444 | - 0.6.2 Bugfix release (still based on docopt 0.6.1)
445 | - 0.6.1 The initial C++ port of docopt.py (based on docopt 0.6.1)
446 |
--------------------------------------------------------------------------------
/docopt-0.6.2/docopt-config.cmake:
--------------------------------------------------------------------------------
1 | include("${CMAKE_CURRENT_LIST_DIR}/docopt-targets.cmake")
2 |
--------------------------------------------------------------------------------
/docopt-0.6.2/docopt.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // docopt.cpp
3 | // docopt
4 | //
5 | // Created by Jared Grubb on 2013-11-03.
6 | // Copyright (c) 2013 Jared Grubb. All rights reserved.
7 | //
8 |
9 | #include "docopt.h"
10 | #include "docopt_util.h"
11 | #include "docopt_private.h"
12 |
13 | #include "docopt_value.h"
14 |
15 | #include
16 | #include
17 | #include
18 | #include