Commit e37062c4 authored by Millian Poquet's avatar Millian Poquet
Browse files

Batsim CLI update (docopt + clean).

All options no longer require a short name.
-> rare options are only long now.

Some options have been renamed to sound clearer.
--mmax, --mmax-workload, --enable-sg-process-tracing,
--allow-time-sharing, --workflow-jobs-limit, ...

Some default values have been changed for consistency.
--mmax and --workflow-jobs-limit both have 0 as
default unlimited value.

Running batsim --help should now be more readable, and
display what can be done via the CLI.
parent bbbb2551
......@@ -85,7 +85,9 @@ file(GLOB batsim_SRC
"src/*.hpp"
"src/*.cpp"
"src/pugixml-1.7/*.hpp"
"src/pugixml-1.7/*.cpp")
"src/pugixml-1.7/*.cpp"
"src/docopt/*.cpp"
"src/docopt/*.h")
# Executables
add_executable(batsim ${batsim_SRC})
......@@ -205,10 +207,10 @@ add_test(long_simulation_time
-bod /tmp/batsim_tests/long_simulation_time
-bwd ${CMAKE_SOURCE_DIR})
add_test(space_sharing
add_test(time_sharing
${CMAKE_SOURCE_DIR}/tools/experiments/execute_instances.py
${CMAKE_SOURCE_DIR}/test/test_space_sharing.yaml
-bod /tmp/batsim_tests/space_sharing
${CMAKE_SOURCE_DIR}/test/test_time_sharing.yaml
-bod /tmp/batsim_tests/time_sharing
-bwd ${CMAKE_SOURCE_DIR})
add_test(smpi
......
......@@ -8,8 +8,9 @@ More information about git hooks can be found
## pre-commit
The [pre-commit](pre-commit) hook is called when you want to commit something.
This script checks whather the commit will fail on Travis or not. Notably, it
checks whether:
This script checks whether the commit will probably fail on the CI.
Notably, it checks whether:
- Doxygen produces warnings
- Input examples of execution scripts work
- Batsim can be built without warnings
- The execution scripts work
- Tests pass
......@@ -17,6 +17,13 @@ fi
failed=0
# Let's check whether Batsim compiles
echo "Checking whether Batsim compiles..."
mkdir -p ${base_dir}/build
cd ${base_dir}/build
cmake .. -Dtreat_warnings_as_errors=ON
make -j 4
# Let's run a redis server if needed
server_launched_by_me=0
r=$(ps faux | grep redis-server | grep -v grep | wc -l)
......@@ -33,14 +40,9 @@ fi
# Let's check that tests run correctly
echo -n "Checking whether tests pass..."
cd ${base_dir}
bash -e ./test/run_tests.sh >/dev/null
if [ $? -ne 0 ]
then
failed=1
echo " NOPE! :("
fi
cd ${base_dir}/build
ctest -E smpi
failed=$?
# Let's stop the redis server if it has been launched by this script
if [ $server_launched_by_me -eq 1 ]
......
This diff is collapsed.
......@@ -57,53 +57,50 @@ struct MainArguments
double start_time; //!< The moment in time at which the workflow should be started
};
// Input
std::string platform_filename; //!< The SimGrid platform filename
std::list<WorkloadDescription> workload_descriptions; //!< The workloads' descriptions
std::list<WorkflowDescription> workflow_descriptions; //!< The workflows' descriptions
bool terminate_with_last_workflow = false; //!< If true, allows to ignore the jobs submitted after the last workflow termination
std::string socket_filename = "/tmp/bat_socket"; //!< The Unix Domain Socket filename
// Common
std::string master_host_name; //!< The name of the SimGrid host which runs scheduler processes and not user tasks
bool energy_used; //!< True if and only if the SimGrid energy plugin should be used.
std::string master_host_name = "master_host"; //!< The name of the SimGrid host which runs scheduler processes and not user tasks
std::string export_prefix; //!< The filename prefix used to export simulation information
// Execution context
std::string socket_filename; //!< The Unix Domain Socket filename
std::string redis_hostname; //!< The Redis (data storage) server host name
int redis_port; //!< The Redis (data storage) server port
std::string redis_prefix; //!< The Redis (data storage) instance prefix
std::string pfs_host_name = "pfs_host"; //!< The name of the SimGrid host which serves as parallel file system
// Output
std::string export_prefix; //!< The filename prefix used to export simulation information
bool enable_simgrid_process_tracing; //!< If set to true, this option enables the tracing of SimGrid processes
bool enable_schedule_tracing; //!< If set to true, the schedule is exported to a Pajé trace file
bool enable_machine_state_tracing; //!< If set to true, this option enables the tracing of the machine states into a CSV time series.
std::string redis_hostname = "127.0.0.1"; //!< The Redis (data storage) server host name
int redis_port = 6379; //!< The Redis (data storage) server port
std::string redis_prefix; //!< The Redis (data storage) instance prefix
// Platform size limit
int limit_machines_count; //!< The number of machines to use to compute jobs. 0 : no limit. > 0 : the number of computation machines
bool limit_machines_count_by_workload; //!< If set to true, the number of computing machiens to use should be limited by the workload description
int limit_machines_count = -1; //!< The number of machines to use to compute jobs. -1 : no limit. >= 1 : the number of computation machines
bool limit_machines_count_by_workload = false; //!< If set to true, the number of computing machiens to use should be limited by the workload description
// Verbosity
VerbosityLevel verbosity; //!< Sets the Batsim verbosity
bool energy_used = false; //!< True if and only if the SimGrid energy plugin should be used.
VerbosityLevel verbosity = VerbosityLevel::INFORMATION; //!< Sets the Batsim verbosity
bool allow_space_sharing = false; //!< Allows/forbids space sharing. Two jobs can run on the same machine if and only if space sharing is allowed.
bool enable_simgrid_process_tracing = false; //!< If set to true, this option enables the tracing of SimGrid processes
bool enable_schedule_tracing = true; //!< If set to true, the schedule is exported to a Pajé trace file
bool enable_machine_state_tracing = true; //!< If set to true, this option enables the tracing of the machine states into a CSV time series.
// Workflow
int workflow_nb_concurrent_jobs_limit = 0; //!< Limits the number of concurrent jobs for workflows
bool terminate_with_last_workflow; //!< If true, allows to ignore the jobs submitted after the last workflow termination
bool abort = false; //!< A boolean value. If set to yet, the launching should be aborted for reason abortReason
std::string abortReason; //!< Human readable reasons which explains why the launch should be aborted
int workflow_limit = 0; //!< limit on workflow needs
ProgramType program_type = ProgramType::BATSIM; //!< The program type
// Other
bool allow_time_sharing; //!< Allows/forbids time sharing. Two jobs can run on the same machine if and only if time sharing is allowed.
ProgramType program_type; //!< The program type (Batsim or Batexec at the moment)
std::string pfs_host_name; //!< The name of the SimGrid host which serves as parallel file system
};
/**
* @brief Used to parse the main function parameters
* @param[in] key The current key
* @param[in] arg The current argument
* @param[in, out] state The current argp_state
* @return 0
*/
int parse_opt (int key, char *arg, struct argp_state *state);
/**
* @brief Parses Batsim's command-line arguments
* @param[in] argc The number of arguments given to the main function
* @param[in] argv The values of arguments given to the main function
* @param[out] main_args Batsim's usable arguments
* @return
* @return true on success, false otherwise
*/
bool parse_main_args(int argc, char * argv[], MainArguments & main_args);
......
......@@ -40,7 +40,7 @@ struct BatsimContext
CurrentSwitches current_switches; //!< The current switches
RedisStorage storage; //!< The RedisStorage
bool terminate_with_last_workflow = false; //!< If true, allows to ignore the jobs submitted after the last workflow termination
bool terminate_with_last_workflow; //!< If true, allows to ignore the jobs submitted after the last workflow termination
Rational energy_first_job_submission = -1; //!< The amount of consumed energy (J) when the first job is submitted
Rational energy_last_job_completion = -1; //!< The amount of consumed energy (J) when the last job is completed
......@@ -51,10 +51,10 @@ struct BatsimContext
bool energy_used; //!< Stores whether the energy part of Batsim should be used
bool smpi_used; //!< Stores whether SMPI should be used
bool allow_space_sharing; //!< Stores whether space sharing (using the same machines to compute different jobs) should be allowed
bool allow_time_sharing; //!< Stores whether time sharing (using the same machines to compute different jobs) should be allowed
bool trace_schedule; //!< Stores whether the resulting schedule should be outputted
bool trace_machine_states; //!< Stores whether the machines states should be outputted
std::string platform_filename; //!< The name of the platform file
std::string export_prefix; //!< The output export prefix
int workflow_limit = 0; //!< limit on workflow needs
int workflow_nb_concurrent_jobs_limit; //!< Limits the number of concurrent jobs for workflows
};
# Compiled Object files
*.slo
*.lo
*.o
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Compiled Static libraries
*.lai
*.la
*.a
# Compiled examples, as per docs
example
naval_fate
run_testcase
run_testcase.exe
# CMake temporary files
CMakeCache.txt
CMakeFiles
CPackConfig.cmake
CPackSourceConfig.cmake
Makefile
cmake_install.cmake
docopt-config-version.cmake
# Files configured by CMake
run_tests
language: cpp
sudo: false # Use the new container infrastructure
matrix:
include:
- os: linux
env:
- COMPILER=g++-5 STDLIB=libc++
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'george-edison55-precise-backports']
packages: ["g++-5", "cmake-data", "cmake"]
- os: linux
env:
- COMPILER=g++-4.8 USE_BOOST_REGEX=ON
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'george-edison55-precise-backports', 'boost-latest']
packages: ["g++-4.8", "cmake-data", "cmake", "libboost-regex1.55-dev"]
- os: linux
env:
- COMPILER=clang++-3.6 STDLIB=libc++
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6', 'george-edison55-precise-backports']
packages: ["clang-3.6", "cmake-data", "cmake"]
- os: linux
env:
- COMPILER=clang++-3.7 STDLIB=libc++
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7', 'george-edison55-precise-backports']
packages: ["clang-3.7", "cmake-data", "cmake"]
- os: osx
osx_image: xcode6.4
env:
- COMPILER=clang++ V='Apple LLVM 6.4'
- COMPILER=clang++ V='Apple LLVM 6.4' WITH_CPP14=true
- os: osx
osx_image: xcode7
env:
- COMPILER=clang++ V='Apple LLVM 7.0'
- COMPILER=clang++ V='Apple LLVM 7.0' WITH_CPP14=true
before_install:
- |
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
brew rm --force cmake && brew install cmake
fi
- CMAKE_CXX_FLAGS+=" -Wall"
- if [[ "${WITH_CPP14}" == "true" ]]; then CMAKE_OPTIONS+=" -DCMAKE_CXX_STANDARD=14"; fi
- |
if [[ "${USE_BOOST_REGEX}" == "ON" ]]; then
CMAKE_OPTIONS+=" -DUSE_BOOST_REGEX=ON"
CMAKE_OPTIONS+=" -DBoost_REGEX_LIBRARY_DEBUG=/usr/lib/x86_64-linux-gnu/libboost_regex.so.1.55.0"
CMAKE_OPTIONS+=" -DBoost_REGEX_LIBRARY_RELEASE=/usr/lib/x86_64-linux-gnu/libboost_regex.so.1.55.0"
fi
- if [[ "${STDLIB}" == "libc++" ]]; then CMAKE_CXX_FLAGS+=" -stdlib=libc++"; fi
- ${COMPILER} --version
before_script:
- rm -rf build/
- mkdir build
- cd build
- cmake -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} -DWITH_TESTS=1 -DWITH_EXAMPLE=1 ${CMAKE_OPTIONS} ..
script:
- cmake --build .
- python run_tests
cmake_minimum_required(VERSION 3.1)
project(docopt.cpp VERSION 0.6.1)
include(GNUInstallDirs)
#============================================================================
# Settable options
#============================================================================
option(WITH_TESTS "Build tests." OFF)
option(WITH_EXAMPLE "Build example." OFF)
option(USE_BOOST_REGEX "Replace std::regex with Boost.Regex" OFF)
#============================================================================
# Internal compiler options
#============================================================================
# C++ standard
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if(NOT CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD LESS 11)
set(CMAKE_CXX_STANDARD 11)
endif()
# Suppression of "unknown pragma" warning on GCC
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas") # Code uses #pragma mark
endif()
#============================================================================
# Sources & headers
#============================================================================
set(docopt_SOURCES docopt.cpp)
set(docopt_HEADERS
docopt.h
docopt_private.h
docopt_util.h
docopt_value.h
)
#============================================================================
# Compile targets
#============================================================================
if(MSVC OR XCODE)
# MSVC requires __declspec() attributes, which are achieved via the
# DOCOPT_DLL and DOCOPT_EXPORTS macros below. Since those macros are only
# defined when building a shared library, we must build the shared and
# static libraries completely separately.
# Xcode does not support libraries with only object files as sources.
# See https://cmake.org/cmake/help/v3.0/command/add_library.html?highlight=add_library
add_library(docopt SHARED ${docopt_SOURCES} ${docopt_HEADERS})
add_library(docopt_s STATIC ${docopt_SOURCES} ${docopt_HEADERS})
else()
# If not using MSVC or Xcode, we will create an intermediate object target
# to avoid compiling the source code twice.
add_library(docopt_o OBJECT ${docopt_SOURCES} ${docopt_HEADERS})
set_target_properties(docopt_o PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
add_library(docopt SHARED $<TARGET_OBJECTS:docopt_o>)
add_library(docopt_s STATIC $<TARGET_OBJECTS:docopt_o>)
endif()
target_include_directories(docopt PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}> $<INSTALL_INTERFACE:include/docopt>)
target_include_directories(docopt_s PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}> $<INSTALL_INTERFACE:include/docopt>)
if(MSVC)
# DOCOPT_DLL: Must be specified when building *and* when using the DLL.
# That's what the "PUBLIC" means.
# DOCOPT_EXPORTS: Must use __declspec(dllexport) when building the DLL.
# "PRIVATE" means it's only defined when building the DLL.
target_compile_definitions(docopt PUBLIC DOCOPT_DLL
PRIVATE DOCOPT_EXPORTS)
endif()
if(NOT MSVC)
set_target_properties(docopt PROPERTIES OUTPUT_NAME docopt)
set_target_properties(docopt_s PROPERTIES OUTPUT_NAME docopt)
endif()
if(USE_BOOST_REGEX)
add_definitions("-DDOCTOPT_USE_BOOST_REGEX")
# This is needed on Linux, where linking a static library into docopt.so
# fails because boost static libs are not compiled with -fPIC
set(Boost_USE_STATIC_LIBS OFF)
find_package(Boost 1.53 REQUIRED COMPONENTS regex)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(docopt ${Boost_LIBRARIES})
if(WITH_STATIC)
target_link_libraries(docopt_s ${Boost_LIBRARIES})
endif()
endif()
#============================================================================
# Examples
#============================================================================
if(WITH_EXAMPLE)
add_executable(docopt_example examples/naval_fate.cpp)
target_link_libraries(docopt_example docopt)
endif()
#============================================================================
# Tests
#============================================================================
if(WITH_TESTS)
set(TESTPROG "${CMAKE_CURRENT_BINARY_DIR}/run_testcase")
set(TESTCASES "${PROJECT_SOURCE_DIR}/testcases.docopt")
add_executable(run_testcase run_testcase.cpp)
target_link_libraries(run_testcase docopt)
configure_file(
"${PROJECT_SOURCE_DIR}/run_tests.py"
"${CMAKE_CURRENT_BINARY_DIR}/run_tests"
ESCAPE_QUOTES
)
add_test("Testcases docopt" ${TESTPROG})
endif()
#============================================================================
# Install
#============================================================================
set(export_name "docopt-targets")
# Runtime package
install(TARGETS docopt EXPORT ${export_name} DESTINATION ${CMAKE_INSTALL_LIBDIR})
# Development package
install(TARGETS docopt_s EXPORT ${export_name} DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES ${docopt_HEADERS} DESTINATION include/docopt)
# CMake Package
include(CMakePackageConfigHelpers)
write_basic_package_version_file("${PROJECT_BINARY_DIR}/docopt-config-version.cmake" COMPATIBILITY SameMajorVersion)
install(FILES docopt-config.cmake ${PROJECT_BINARY_DIR}/docopt-config-version.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/docopt")
install(EXPORT ${export_name} DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/docopt")
#============================================================================
# CPack
#============================================================================
set(CPACK_PACKAGE_NAME "docopt")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "")
set(CPACK_RPM_PACKAGE_REQUIRES "")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Beautiful command line interfaces")
set(CPACK_PACKAGE_VENDOR "Jared Grubb")
set(CPACK_PACKAGE_CONTACT ${CPACK_PACKAGE_VENDOR})
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.rst")
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE-MIT")
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
set(CPACK_DEBIAN_PACKAGE_SECTION "Development")
set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
set(CPACK_STRIP_FILES TRUE)
include(CPack)
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Copyright (c) 2012 Vladimir Keleshev, <vladimir@keleshev.com>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to
whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall
be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
``docopt.cpp``: A C++11 Port
============================
docopt creates *beautiful* command-line interfaces
--------------------------------------------------
Isn't it awesome how ``getopt`` (and ``boost::program_options`` for you fancy
folk!) generate help messages based on your code?! These timeless functions
have been around for decades and have proven we don't need anything better, right?
*Hell no!* You know what's awesome? It's when the option parser *is*
generated based on the beautiful help message that you write yourself!
This way you don't need to write this stupid repeatable parser-code,
and instead can write only the help message--*the way you want it*.
**docopt** helps you create most beautiful command-line interfaces
*easily*:
.. code:: c++
#include "docopt.h"
#include <iostream>
static const char USAGE[] =
R"(Naval Fate.
Usage:
naval_fate ship new <name>...
naval_fate ship <name> move <x> <y> [--speed=<kn>]
naval_fate ship shoot <x> <y>
naval_fate mine (set|remove) <x> <y> [--moored | --drifting]
naval_fate (-h | --help)
naval_fate --version
Options:
-h --help Show this screen.
--version Show version.
--speed=<kn> Speed in knots [default: 10].
--moored Moored (anchored) mine.
--drifting Drifting mine.
)";
int main(int argc, const char** argv)
{
std::map<std::string, docopt::value> args
= docopt::docopt(USAGE,
{ argv + 1, argv + argc },
true, // show help if requested
"Naval Fate 2.0"); // version string
for(auto const& arg : args) {
std::cout << arg.first << arg.second << std::endl;
}
return 0;
}
Beat that! The option parser is generated based on the docstring above
that is passed to ``docopt::docopt`` function. ``docopt`` parses the usage
pattern (``"Usage: ..."``) and option descriptions (lines starting
with dash "``-``") and ensures that the program invocation matches the
usage pattern; it parses options, arguments and commands based on
that. The basic idea is that *a good help message has all necessary
information in it to make a parser*.
C++11 port details
---------------------------------------------------
This is a port of the ``docopt.py`` module (https://github.com/docopt/docopt),
and we have tried to maintain full feature parity (and code structure) as the
original.
This port is written in C++11 and also requires a good C++11 standard library
(in particular, one with ``regex`` support). The following compilers are known
to work with docopt:
- Clang 3.3 and later
- GCC 4.9
- Visual C++ 2015 RC
GCC-4.8 can work, but the std::regex module needs to be replaced with ``Boost.Regex``.
In that case, you will need to define ``DOCTOPT_USE_BOOST_REGEX`` when compiling
docopt, and link your code with the appropriated Boost libraries. A relativley
recent version of Boost is needed: 1.55 works, but 1.46 does not for example.
This port is licensed under the MIT license, just like the original module.
However, we are also dual-licensing this code under the Boost License, version 1.0,
as this is a popular C++ license. The licenses are similar and you are free to
use this code under the terms of either license.
The differences from the Python port are:
* the addition of a ``docopt_parse`` function, which does not terminate
the program on error
* a ``docopt::value`` type to hold the various value types that can be parsed.
We considered using boost::variant, but it seems better to have no external
dependencies (beyond a good STL).
* because C++ is statically-typed and Python is not, we had to make some
changes to the interfaces of the internal parse tree types.
* because ``std::regex`` does not have an equivalent to Python's regex.split,
some of the regex's had to be restructured and additional loops used.
API
---------------------------------------------------
.. code:: c++
docopt::docopt(doc, argv, help /* =true */, version /* ="" */, options_first /* =false */)
``docopt`` takes 2 required and 3 optional arguments:
- ``doc`` is a string that contains a **help message** that will be parsed to
create the option parser. The simple rules of how to write such a
help message are given in next sections. Here is a quick example of
such a string (note that this example uses the "raw string literal" feature
that was added to C++11):
.. code:: c++
R"(Usage: my_program [-hso FILE] [--quiet | --verbose] [INPUT ...]
-h --help show this
-s --sorted sorted output
-o FILE specify output file [default: ./test.txt]
--quiet print less text
--verbose print more text
)"
- ``argv`` is a vector of strings representing the args passed. Although
main usually takes a ``(int argc, const char** argv)`` pair, you can
pass the value ``{argv+1, argv+argc}`` to generate the vector automatically.
(Note we skip the argv[0] argument!) Alternatively you can supply a list of
strings like ``{ "--verbose", "-o", "hai.txt" }``.
- ``help``, by default ``true``, specifies whether the parser should
automatically print the help message (supplied as ``doc``) and
terminate, in case ``-h`` or ``--help`` option is encountered
(options should exist in usage pattern, more on that below). If you
want to handle ``-h`` or ``--help`` options manually (as other
options), set ``help=false``.
- ``version``, by default empty, is an optional argument that
specifies the version of your program. If supplied, then, (assuming