Commit d9e99842 authored by Dominik Charousset's avatar Dominik Charousset

Merge branch 'develop'

parents 1c6f23eb 18c6afa0
......@@ -3,14 +3,6 @@ project(caf_core C CXX)
set (CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_CXX_FLAGS "-std=c++11 -Wextra -Wall -pedantic ${EXTRA_FLAGS}")
include_directories(.)
# get header files; only needed by CMake generators,
......@@ -95,10 +87,9 @@ add_custom_target(libcaf_core)
if (NOT CAF_BUILD_STATIC_ONLY)
add_library(libcaf_core_shared SHARED ${LIBCAF_CORE_SRCS} ${LIBCAF_CORE_HDRS})
target_link_libraries(libcaf_core_shared ${LD_FLAGS})
set(LIBRARY_SOVERSION ${CAF_VERSION_MAJOR})
set_target_properties(libcaf_core_shared
PROPERTIES
SOVERSION ${LIBRARY_SOVERSION}
SOVERSION ${CAF_VERSION}
VERSION ${CAF_VERSION}
OUTPUT_NAME caf_core)
if(NOT WIN32)
......
......@@ -34,7 +34,7 @@
* whereas each number is a two-digit decimal number without
* leading zeros (e.g. 900 is version 0.9.0).
*/
#define CAF_VERSION 1301
#define CAF_VERSION 1302
/**
* Defined to the major version number of CAF.
......
......@@ -216,6 +216,11 @@ class message {
*/
std::string text;
/**
* Auto-generated helptext for this item.
*/
std::string helptext;
/**
* Returns `true` on a match, `false` otherwise.
*/
......@@ -253,6 +258,8 @@ class message {
struct cli_res;
using help_factory = std::function<std::string (const std::vector<cli_arg>&)>;
/**
* A simplistic interface for using `extract` to parse command line options.
* Usage example:
......@@ -280,8 +287,15 @@ class message {
* // ...
* }
* ~~~
*/
cli_res extract_opts(std::vector<cli_arg> xs) const;
* @param xs List of argument descriptors.
* @param f Optional factory function to generate help text
* (overrides the default generator).
* @returns A struct containing remainder
* (i.e. unmatched elements), a set containing the names of all
* used arguments, and the generated help text.
* @throws std::invalid_argument if no name or more than one long name is set
*/
cli_res extract_opts(std::vector<cli_arg> xs, help_factory f = nullptr) const;
/**
* Queries whether the element at position `p` is of type `T`.
......
......@@ -102,8 +102,10 @@ class message_builder {
/**
* @copydoc message::extract_opts
*/
inline message::cli_res extract_opts(std::vector<message::cli_arg> xs) const {
return to_message().extract_opts(std::move(xs));
inline message::cli_res extract_opts(std::vector<message::cli_arg> xs,
message::help_factory f
= nullptr) const {
return to_message().extract_opts(std::move(xs), std::move(f));
}
/**
......
......@@ -143,26 +143,53 @@ message message::extract(message_handler handler) const {
return extract_impl(0, handler);
}
message::cli_res message::extract_opts(std::vector<cli_arg> xs) const {
std::set<std::string> opts;
cli_arg dummy{"help,h", ""};
message::cli_res message::extract_opts(std::vector<cli_arg> xs,
help_factory f) const {
// add default help item if not specified by user
auto pred = [](const cli_arg& arg) {
return arg.name == "help" || arg.name.compare(0, 5, "help,") == 0;
};
if (std::none_of(xs.begin(), xs.end(), pred)) {
xs.push_back(cli_arg{"help,h,?", "print this text"});
}
std::map<std::string, cli_arg*> shorts;
std::map<std::string, cli_arg*> longs;
shorts["-h"] = &dummy;
shorts["-?"] = &dummy;
longs["--help"] = &dummy;
for (auto& cliarg : xs) {
std::vector<std::string> s;
split(s, cliarg.name, is_any_of(","), token_compress_on);
if (s.size() == 2 && s.back().size() == 1) {
if (s.empty()) {
throw std::invalid_argument("invalid option name: " + cliarg.name);
}
longs["--" + s.front()] = &cliarg;
shorts["-" + s.back()] = &cliarg;
} else if (s.size() == 1) {
longs[s.front()] = &cliarg;
for (size_t i = 1; i < s.size(); ++i) {
if (s[i].size() != 1) {
throw std::invalid_argument("invalid short option name: " + s[i]);
}
shorts["-" + s[i]] = &cliarg;
}
// generate helptext for this item
auto& ht = cliarg.helptext;
if (s.size() == 1) {
ht += "--";
ht += s.front();
} else {
throw std::invalid_argument("invalid option name: " + cliarg.name);
ht += "-";
ht += s[1];
ht += " [";
for (size_t i = 2; i < s.size(); ++i) {
ht += "-";
ht += s[i];
ht += ",";
}
ht += "--";
ht += s.front();
ht += "]";
}
if (cliarg.fun) {
ht += " arg";
}
}
std::set<std::string> opts;
auto insert_opt_name = [&](const cli_arg* ptr) {
auto separator = ptr->name.find(',');
if (separator == std::string::npos) {
......@@ -232,43 +259,24 @@ message::cli_res message::extract_opts(std::vector<cli_arg> xs) const {
return none;
}
});
size_t name_width = 0;
for (auto& x : xs) {
// name field contains either only "--<long_name>" or
// "-<short name> [--<long name>]" depending on whether or not
// a ',' appears in the name
auto nw = x.name.find(',') == std::string::npos
? x.name.size() + 2 // "--<name>"
: x.name.size() + 5; // "-X [--<name>]" (minus trailing ",X")
if (x.fun) {
nw += 4; // trailing " arg"
}
name_width = std::max(name_width, nw);
}
std::string helptext;
if (f) {
helptext = f(xs);
} else {
auto op = [](size_t tmp, const cli_arg& arg) {
return std::max(tmp, arg.helptext.size());
};
auto name_width = std::accumulate(xs.begin(), xs.end(), size_t{0}, op);
std::ostringstream oss;
oss << std::left;
oss << "Allowed options:" << std::endl;
for (auto& ca : xs) {
std::string lhs;
auto separator = ca.name.find(',');
if (separator == std::string::npos) {
lhs += "--";
lhs += ca.name;
} else {
lhs += "-";
lhs += ca.name.back();
lhs += " [--";
lhs += ca.name.substr(0, separator);
lhs += "]";
}
if (ca.fun) {
lhs += " arg";
}
oss << " ";
oss.width(static_cast<std::streamsize>(name_width));
oss << lhs << " : " << ca.text << std::endl;
oss << ca.helptext << " : " << ca.text << std::endl;
}
helptext = oss.str();
}
auto helptext = oss.str();
if (opts.count("help") == 1) {
std::cout << helptext << std::endl;
}
......
......@@ -30,10 +30,9 @@ add_custom_target(libcaf_io)
if (NOT CAF_BUILD_STATIC_ONLY)
add_library(libcaf_io_shared SHARED ${LIBCAF_IO_SRCS} ${LIBCAF_IO_HDRS})
target_link_libraries(libcaf_io_shared ${LD_FLAGS} ${LIBCAF_CORE_LIBRARY})
set(LIBRARY_SOVERSION ${CAF_VERSION_MAJOR})
set_target_properties(libcaf_io_shared
PROPERTIES
SOVERSION ${LIBRARY_SOVERSION}
SOVERSION ${CAF_VERSION}
VERSION ${CAF_VERSION}
OUTPUT_NAME caf_io)
if(NOT WIN32)
......
Subproject commit bf5196b0a505ec682705c5715f2f976d34fdf4be
Subproject commit 91ebbda2986f3f32a873d02ca5eb550f26c6b70d
Subproject commit 711263e8e02a71a95478b7a5097fdef0ec739fe6
Subproject commit 855e725739b7688290f66f592f858149c92375c5
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment