From facf4c32f3ef35f4657fff561bda52c9ac05b5a7 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Tue, 5 May 2020 07:41:09 -0400 Subject: [PATCH] rework of conf, ini, vswhere things are broken --- src/conf.cpp | 971 +++-- src/conf.h | 144 +- src/context.cpp | 2 + src/context.h | 13 +- src/env.cpp | 39 +- src/main.cpp | 80 +- src/pch.h | 2 + src/process.cpp | 169 +- src/process.h | 19 + src/tasks/openssl.cpp | 2 +- src/tools/cmake.cpp | 2 +- src/tools/git.cpp | 4 +- src/tools/msbuild.cpp | 2 +- src/tools/tools.cpp | 2 +- src/utility.cpp | 20 + src/utility.h | 4 +- third-party/bin/vswhere.exe | Bin 0 -> 458872 bytes third-party/include/clipp.h | 7024 +++++++++++++++++++++++++++++++++++ 18 files changed, 8057 insertions(+), 442 deletions(-) create mode 100644 third-party/bin/vswhere.exe create mode 100644 third-party/include/clipp.h diff --git a/src/conf.cpp b/src/conf.cpp index cdbd14a..ed67108 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -2,46 +2,236 @@ #include "conf.h" #include "utility.h" #include "context.h" +#include "process.h" namespace mob { +using string_map = std::map; +using path_map = std::map; +using bool_map = std::map; + +static fs::path g_ini; +const std::string ini_filename = "mob.ini"; + +// special case for options that are used often to avoid string manipulations +static bool g_dry = false; +static int g_log = 3; +static bool g_redownload = false; +static bool g_reextract = false; +static bool g_rebuild = false; + +static string_map g_options = +{ + {"mo_org", "ModOrganizer2"}, + {"mo_branch", "master"} +}; + +static path_map g_third_party = +{ + {"sevenz", ""}, + {"jom", ""}, + {"patch", ""}, + {"nuget", ""}, + {"vswhere", ""}, +}; + +static bool_map g_prebuilt = +{ + {"boost", false} +}; + +static string_map g_versions = +{ + {"vs", ""}, + {"vs_year", ""}, + {"vs_toolset", ""}, + {"sdk", ""}, + {"sevenzip", ""}, + {"zlib", ""}, + {"boost", ""}, + {"boost_vs", ""}, + {"python", ""}, + {"fmt", ""}, + {"gtest", ""}, + {"libbsarch", ""}, + {"libloot", ""}, + {"libloot_hash", ""}, + {"openssl", ""}, + {"bzip2", ""}, + {"lz4", ""}, + {"nmm", ""}, + {"spdlog", ""}, + {"usvfs", ""}, + {"qt", ""}, + {"qt_vs", ""}, + {"pyqt", ""}, + {"pyqt_builder", ""}, + {"sip", ""}, + {"pyqt_sip", ""}, +}; + +static path_map g_paths = +{ + {"third_party" , ""}, + {"prefix", ""}, + {"cache", ""}, + {"build", ""}, + {"install", ""}, + {"install_bin", ""}, + {"install_libs", ""}, + {"install_pdbs", ""}, + {"install_dlls", ""}, + {"install_loot", ""}, + {"install_plugins", ""}, + {"patches", ""}, + {"vs", ""}, + {"vcvars", ""}, + {"qt_install", ""}, + {"qt_bin", ""}, + {"pf_x86", ""}, + {"pf_x64", ""}, + {"temp_dir", ""}, +}; + + +template +const typename Map::mapped_type& get( + const std::string& map_name, const Map& map, + const std::string& name) +{ + auto itor = map.find(name); + + if (itor == map.end()) + { + gcx().bail_out(context::conf, + map_name + " '" + name + "' doesn't exist"); + } + + return itor->second; +} + + +const std::string& conf::by_name(const std::string& name) +{ + return get("option", g_options, name); +} + +const fs::path& third_party::by_name(const std::string& s) +{ + return get("third party", g_third_party, s); +} + +bool prebuilt::by_name(const std::string& s) +{ + return get("prebuilt", g_prebuilt, s); +} + +const std::string& versions::by_name(const std::string& s) +{ + return get("version", g_versions, s); +} + +const fs::path& paths::by_name(const std::string& s) +{ + return get("path", g_paths, s); +} + + +bool conf::log_dump() { return g_log > 5; } +bool conf::log_trace() { return g_log > 4; } +bool conf::log_debug() { return g_log > 3; } +bool conf::log_info() { return g_log > 2; } +bool conf::log_warning() { return g_log > 1; } +bool conf::log_error() { return g_log > 0; } +bool conf::dry() { return g_dry; } +bool conf::redownload() { return g_redownload; } +bool conf::reextract() { return g_reextract; } +bool conf::rebuild() { return g_rebuild; } + + +fs::path tool_paths::perl() { return "perl.exe"; } +fs::path tool_paths::msbuild() { return "msbuild.exe"; } +fs::path tool_paths::devenv() { return "devenv.exe"; } +fs::path tool_paths::cmake() { return "cmake.exe"; } +fs::path tool_paths::git() { return "git.exe"; } + + +void conf_command_line_options(clipp::group& g) +{ + g.push_back( + (clipp::option("-i", "--ini") + >> [&](auto&& v){ g_ini = v; }) + % ("path to the ini file (defaults to ./" + ini_filename + ")"), + + (clipp::option("--dry") + >> [&]{ g_dry = true; }) + % "simulates filesystem operations", + + (clipp::option("-l", "--log-level") + & clipp::value("level", g_log)) + % "0 is silent, 6 is max", + + //(clipp::option("-o", "--option") + // & clipp::value("key=value") + // >> [&](auto&& v){ set_opt(v); }) + // % "sets an option", + + (clipp::option("-g", "--redownload") + >> [&]{ g_redownload = true; }) + % "redownloads archives, see --reextract", + + (clipp::option("-e", "--reextract") + >> [&]{ g_reextract = true; }) + % "deletes source directories and re-extracts archives", + + (clipp::option("-b", "--rebuild") + >> [&]{ g_rebuild = true; }) + % "cleans and rebuilds projects", + + (clipp::option("-c", "--clean") + >> [&]{ g_redownload=true; g_reextract=true; g_rebuild=true; }) + % "combines --redownload, --reextract and --rebuild" + ); +} + + +bool try_parts(fs::path& check, const std::vector& parts) +{ + for (std::size_t i=0; i g_conf = -{ - {"qt_install", ""}, - {"vs", "16"}, - {"vs_year", "2019"}, - {"vs_toolset", "14.2"}, - {"sdk", "10.0.18362.0"}, - {"sevenzip", "19.00"}, - {"zlib", "1.2.11"}, - {"boost", "1.72.0-b1-rc1"}, - {"boost_vs", "14.2"}, - {"python", "v3.8.1"}, - {"fmt", "6.1.2"}, - {"gtest", "master"}, - {"libbsarch", "0.0.8"}, - {"libloot", "0.15.1"}, - {"libloot_hash", "gf725dd7"}, - {"openssl", "1.1.1d"}, - {"bzip2", "1.0.6"}, - {"lz4", "v1.9.2"}, - {"nmm", "0.71.2"}, - {"spdlog", "v1.4.2"}, - {"usvfs", "master"}, - {"qt", "5.14.2"}, - {"qt_vs", "2017"}, - {"pyqt", "5.14.2"}, - {"pyqt_builder", "1.3.0"}, - {"sip", "5.1.2"}, - {"pyqt_sip", "12.7.2"}, - - {"prefix", R"(C:\dev\projects\mobuild-out)"}, -}; - -const std::string& get_conf(const std::string& name) -{ - auto itor = g_conf.find(name); - if (itor == g_conf.end()) - gcx().bail_out(context::generic, "conf '" + name + "' doesn't exist"); - - return itor->second; -} - -bool g_dry = false; -int g_log = 5; -bool g_redownload = false; -bool g_reextract = false; -bool g_rebuild = false; - -bool conf::log_dump() { return g_log > 5; } -bool conf::log_trace() { return g_log > 4; } -bool conf::log_debug() { return g_log > 3; } -bool conf::log_info() { return g_log > 2; } -bool conf::log_warning() { return g_log > 1; } -bool conf::log_error() { return g_log > 0; } - -bool conf::dry() { return g_dry; } -bool conf::redownload() { return g_redownload; } -bool conf::reextract() { return g_reextract; } -bool conf::rebuild() { return g_rebuild; } - -std::string conf::mo_org() { return "ModOrganizer2"; } -std::string conf::mo_branch() { return "master"; } - -void conf::set(int argc, char** argv) -{ - for (int i=1; i& parts) -{ - for (std::size_t i=0; i locations = - { - program_files_x64(), - "C:", - "D:" - }; - // look for qmake, which is in %qt%/version/msvc.../bin - fs::path qmake = find_in_path("qmake.exe"); - if (!qmake.empty()) - locations.insert(locations.begin(), qmake.parent_path() / "../../"); + std::vector locations = + { + paths::pf_x64(), + "C:", + "D:" + }; - // look for qtcreator.exe, which is in %qt%/Tools/QtCreator/bin - fs::path qtcreator = find_in_path("qtcreator.exe"); - if (!qtcreator.empty()) - locations.insert(locations.begin(), qtcreator.parent_path() / "../../../"); + // look for qmake, which is in %qt%/version/msvc.../bin + fs::path qmake = find_in_path("qmake.exe"); + if (!qmake.empty()) + locations.insert(locations.begin(), qmake.parent_path() / "../../"); - for (fs::path loc : locations) - { - loc = fs::absolute(loc); - if (find_qt(loc)) - return loc; - } + // look for qtcreator.exe, which is in %qt%/Tools/QtCreator/bin + fs::path qtcreator = find_in_path("qtcreator.exe"); + if (!qtcreator.empty()) + locations.insert(locations.begin(), qtcreator.parent_path() / "../../../"); - gcx().bail_out(context::generic, "can't find qt install"); - }(); + for (fs::path loc : locations) + { + loc = fs::absolute(loc); + if (try_qt_location(loc)) + return loc; + } - return path; + gcx().bail_out(context::conf, "can't find qt install"); } -fs::path paths::qt_bin() +void validate_qt() { - static fs::path path = qt() / "bin"; - return path; + fs::path p = paths::qt_install(); + + if (!try_qt_location(p)) + { + gcx().bail_out(context::conf, + "qt path " + p.string() + " doesn't exist\n"); + } + + g_paths["qt_install"] = p; } fs::path get_known_folder(const GUID& id) @@ -348,93 +375,441 @@ fs::path get_known_folder(const GUID& id) return p; } -fs::path paths::program_files_x86() +fs::path find_program_files_x86() { - static fs::path path = [] + fs::path p = get_known_folder(FOLDERID_ProgramFilesX86); + + if (p.empty()) { - fs::path p = get_known_folder(FOLDERID_ProgramFilesX86); + const auto e = GetLastError(); - if (p.empty()) - { - const auto e = GetLastError(); + p = fs::path(R"(C:\Program Files (x86))"); - p = fs::path(R"(C:\Program Files (x86))"); + gcx().warning(context::conf, + "failed to get x86 program files folder, defaulting to " + + p.string(), e); + } + else + { + gcx().trace(context::conf, + "x86 program files is " + p.string()); + } - gcx().warning(context::generic, - "failed to get x86 program files folder, defaulting to " + - p.string(), e); - } - else - { - gcx().trace(context::generic, - "x86 program files is " + p.string()); - } + return p; +} - return p; - }(); +fs::path find_program_files_x64() +{ + fs::path p = get_known_folder(FOLDERID_ProgramFilesX64); + + if (p.empty()) + { + const auto e = GetLastError(); + + p = fs::path(R"(C:\Program Files)"); + + gcx().warning(context::conf, + "failed to get x64 program files folder, defaulting to " + + p.string(), e); + } + else + { + gcx().trace(context::conf, + "x64 program files is " + p.string()); + } + + return p; +} + +fs::path find_temp_dir() +{ + const std::size_t buffer_size = MAX_PATH + 2; + wchar_t buffer[buffer_size] = {}; + + if (GetTempPathW(static_cast(buffer_size), buffer) == 0) + { + const auto e = GetLastError(); + gcx().bail_out(context::conf, "can't get temp path", e); + } + + fs::path p(buffer); + gcx().trace(context::conf, "temp dir is " + p.string()); + + return p; +} + +fs::path find_vs() +{ + auto p = process() + .binary(third_party::vswhere()) + .arg("-prerelease") + .arg("-version", versions::vs()) + .arg("-property", "installationPath") + .stdout_flags(process::keep_in_string) + .stderr_flags(process::inherit); + + p.run(); + p.join(); + + if (p.exit_code() != 0) + gcx().bail_out(context::conf, "vswhere failed"); + + fs::path path = trim_copy(p.steal_stdout()); + + if (!fs::exists(path)) + { + gcx().bail_out(context::conf, + "the path given by vswhere doesn't exist: " + path.string()); + } return path; } -fs::path paths::program_files_x64() +fs::path find_vcvars() { - static fs::path path = [] + const auto vcvars = + paths::vs() / "VC" / "Auxiliary" / "Build" / "vcvarsall.bat"; + + if (!fs::exists(vcvars)) { - fs::path p = get_known_folder(FOLDERID_ProgramFilesX64); + gcx().bail_out(context::conf, + "can't find vcvars batch file at " + vcvars.string()); + } - if (p.empty()) + return vcvars; +} + + + +template +bool parse_value(const std::string& s, T& out) = delete; + +template <> +bool parse_value(const std::string& s, bool& out) +{ + std::istringstream iss(s); + iss >> out; + return !iss.bad(); +} + +template <> +bool parse_value(const std::string& s, std::string& out) +{ + out = s; + return true; +} + +template <> +bool parse_value(const std::string& s, fs::path& out) +{ + out = s; + return true; +} + + +void ini_error(std::size_t line, const std::string& what) +{ + gcx().bail_out(context::conf, + g_ini.filename().string() + ":" + + std::to_string(line + 1) + ": " + + what); +} + +fs::path find_ini() +{ + fs::path p = g_ini; + + if (!p.empty()) + { + if (fs::exists(p)) + return fs::canonical(p); + } + + p = fs::current_path(); + + if (try_parts(p, {"..", "..", "..", ini_filename})) + return p; + + gcx().bail_out(context::conf, "can't find " + ini_filename); +} + +std::vector read_ini(const fs::path& ini) +{ + std::ifstream in(ini); + + std::vector lines; + + for (;;) + { + std::string line; + std::getline(in, line); + trim(line); + + if (!in) + break; + + if (line.empty() || line[0] == '#' || line[0] == ';') + continue; + + lines.push_back(std::move(line)); + } + + if (in.bad()) + gcx().bail_out(context::conf, "failed to read ini " + ini.string()); + + return lines; +} + +template +void parse_section( + std::size_t& i, const std::vector& lines, Map& map) +{ + ++i; + + for (;;) + { + if (i >= lines.size() || lines[i][0] == '[') + break; + + const auto& line = lines[i]; + + const auto sep = line.find("="); + if (sep == std::string::npos) + ini_error(i, "bad line '" + line + "'"); + + const std::string k = trim_copy(line.substr(0, sep)); + const std::string v = trim_copy(line.substr(sep + 1)); + + if (k.empty()) + ini_error(i, "bad line '" + line + "'"); + + auto itor = map.find(k); + if (itor == map.end()) + ini_error(i, "unknown key '" + k + "'"); + + if (!parse_value(v, itor->second)) + ini_error(i, "bad line '" + line + "'"); + + ++i; + } +} + +void parse_ini() +{ + g_ini = find_ini(); + gcx().debug(context::conf, "using ini at " + g_ini.string()); + + const auto lines = read_ini(g_ini); + std::size_t i = 0; + + for (;;) + { + if (i >= lines.size()) + break; + + if (lines[i] == "[options]") + parse_section(i, lines, g_options); + else if (lines[i] == "[third-party]") + parse_section(i, lines, g_third_party); + else if (lines[i] == "[prebuilt]") + parse_section(i, lines, g_prebuilt); + else if (lines[i] == "[versions]") + parse_section(i, lines, g_versions); + else if (lines[i] == "[paths]") + parse_section(i, lines, g_paths); + else + ini_error(i, "bad section " + lines[i]); + } +} + +void check_missing_options() +{ + if (conf::mo_org().empty()) + gcx().bail_out(context::conf, "missing mo_org in [options]"); + + if (conf::mo_branch().empty()) + gcx().bail_out(context::conf, "missing mo_branch in [options]"); + + if (paths::prefix().empty()) + gcx().bail_out(context::conf, "missing prefix in [paths]"); + + for (auto&& [k, v] : g_versions) + { + if (v.empty()) + gcx().bail_out(context::conf, "missing version for " + k); + } +} + + +void find_in_third_party(const std::string& k, const std::string& exe) +{ + auto itor = g_third_party.find(k); + + if (itor == g_third_party.end()) + gcx().bail_out(context::conf, "unknown third party key " + k); + + if (!itor->second.empty()) + { + if (fs::exists(itor->second)) { - const auto e = GetLastError(); - - p = fs::path(R"(C:\Program Files)"); - - gcx().warning(context::generic, - "failed to get x64 program files folder, defaulting to " + - p.string(), e); + itor->second = fs::canonical(itor->second); + return; } else { - gcx().trace(context::generic, - "x64 program files is " + p.string()); + gcx().bail_out(context::conf, + "third party " + itor->second.string() + " not found"); } + } - return p; - }(); + auto p = paths::third_party() / "bin" / exe; - return path; -} - -fs::path paths::temp_dir() -{ - static fs::path temp_dir = [] + if (fs::exists(p)) { - const std::size_t buffer_size = MAX_PATH + 2; - wchar_t buffer[buffer_size] = {}; + itor->second = fs::canonical(p); + return; + } - if (GetTempPathW(static_cast(buffer_size), buffer) == 0) - { - const auto e = GetLastError(); - gcx().bail_out(context::generic, "can't get temp path", e); - } + p = find_in_path(exe); + if (fs::exists(p)) + { + itor->second = fs::canonical(p); + return; + } - fs::path p(buffer); - gcx().trace(context::generic, "temp dir is " + p.string()); - return p; - }(); - - return temp_dir; + gcx().bail_out(context::conf, "can't find " + exe); } -fs::path paths::temp_file() +template +void set_path_if_empty(const std::string& k, F&& f) { - static fs::path dir = temp_dir(); + auto itor = g_paths.find(k); + if (itor == g_paths.end()) + gcx().bail_out(context::conf, "unknown path party key " + k); + + if (!itor->second.empty()) + { + if (fs::exists(itor->second)) + { + itor->second = fs::canonical(itor->second); + return; + } + else + { + gcx().bail_out(context::conf, + "path " + itor->second.string() + " not found"); + } + } + + fs::path cp; + + if constexpr (std::is_same_v>) + cp = fs::absolute(f); + else + cp = fs::absolute(f()); + + if (!fs::exists(cp)) + { + gcx().bail_out(context::conf, + "path " + cp.string() + " not found"); + } + + itor->second = fs::canonical(cp); +} + + +void init_options() +{ + parse_ini(); + + check_missing_options(); + + set_path_if_empty("third_party", find_third_party_directory); + + find_in_third_party("sevenz", "7z.exe"); + find_in_third_party("jom", "jom.exe"); + find_in_third_party("patch", "patch.exe"); + find_in_third_party("vswhere", "vswhere.exe"); + find_in_third_party("nuget", "nuget.exe"); + + set_path_if_empty("vs", find_vs); + set_path_if_empty("vcvars", find_vcvars); + set_path_if_empty("qt_install", find_qt); + set_path_if_empty("pf_x86", find_program_files_x86); + set_path_if_empty("pf_x64", find_program_files_x64); + set_path_if_empty("temp_dir", find_temp_dir); + set_path_if_empty("patches", []{ return find_in_root("patches"); }); + + set_path_if_empty("cache", paths::prefix() / "downloads"); + set_path_if_empty("build", paths::prefix() / "build"); + set_path_if_empty("install", paths::prefix() / "install"); + set_path_if_empty("install_bin", paths::install() / "bin"); + set_path_if_empty("install_libs", paths::install() / "libs"); + set_path_if_empty("install_pdbs", paths::install() / "pdbs"); + set_path_if_empty("install_dlls", paths::install_bin() / "dlls"); + set_path_if_empty("install_loot", paths::install_bin() / "loot"); + set_path_if_empty("install_plugins", paths::install_bin() / "plugins"); + set_path_if_empty("qt_bin", paths::qt_install() / "bin"); + + validate_qt(); +} + +template +void table(const std::string& caption, const Map& values) +{ + std::size_t longest = 0; + for (auto&& [k, v] : values) + longest = std::max(longest, k.size()); + + gcx().trace(context::conf, caption + ":"); + for (auto&& [k, v] : values) + gcx().trace(context::conf, " . " + pad_right(k, longest) + " = " + v); +} + +void dump_options() +{ + const string_map manual_opts = + { + {"dry", g_dry ? "true" : "false"}, + {"log", std::to_string(g_log)}, + {"redownload", g_redownload ? "true" : "false"}, + {"reextract", g_reextract ? "true" : "false"}, + {"rebuild", g_rebuild ? "true" : "false"}, + }; + + string_map opts = g_options; + opts.insert(manual_opts.begin(), manual_opts.end()); + table("options", g_options); + + string_map third_party; + for (auto&& [k, v] : g_third_party) + third_party[k] = v.string(); + table("third-party", third_party); + + string_map prebuilt; + for (auto&& [k, v] : g_prebuilt) + prebuilt[k] = (v ? "true" : "false"); + table("prebuilt", prebuilt); + + table("versions", g_versions); + + string_map paths; + for (auto&& [k, v] : g_paths) + paths[k] = v.string(); + table("paths", paths); +} + + +fs::path make_temp_file() +{ + static fs::path dir = paths::temp_dir(); wchar_t name[MAX_PATH + 1] = {}; if (GetTempFileNameW(dir.native().c_str(), L"mob", 0, name) == 0) { const auto e = GetLastError(); - gcx().bail_out(context::generic, + gcx().bail_out(context::conf, "can't create temp file in " + dir.string(), e); } diff --git a/src/conf.h b/src/conf.h index d0b5c04..4bf05aa 100644 --- a/src/conf.h +++ b/src/conf.h @@ -3,10 +3,24 @@ namespace mob { +class bad_command_line {}; +class bad_conf {}; + +#define VALUE(NAME) \ + static decltype(auto) NAME() { return by_name(#NAME); } + + +struct tool_paths +{ + static fs::path perl(); + static fs::path msbuild(); + static fs::path devenv(); + static fs::path cmake(); + static fs::path git(); +}; + struct conf { - static void set(int argc, char** argv); - static bool log_dump(); static bool log_trace(); static bool log_debug(); @@ -19,83 +33,97 @@ struct conf static bool reextract(); static bool rebuild(); - static std::string mo_org(); - static std::string mo_branch(); + static const std::string& by_name(const std::string& s); + + VALUE(mo_org); + VALUE(mo_branch); }; struct third_party { - static fs::path sevenz(); - static fs::path jom(); - static fs::path patch(); - static fs::path git(); - static fs::path cmake(); - static fs::path perl(); - static fs::path devenv(); - static fs::path msbuild(); - static fs::path nuget(); + static const fs::path& by_name(const std::string& s); + + VALUE(sevenz); + VALUE(jom); + VALUE(patch); + VALUE(nuget); + VALUE(vswhere); }; struct prebuilt { - static bool boost(); + static bool by_name(const std::string& s); + + VALUE(boost); }; struct versions { - static const std::string& vs(); - static const std::string& vs_year(); - static const std::string& vs_toolset(); - static const std::string& sdk(); - static const std::string& sevenzip(); - static const std::string& zlib(); - static const std::string& boost(); - static const std::string& boost_vs(); - static const std::string& python(); - static const std::string& fmt(); - static const std::string& gtest(); - static const std::string& libbsarch(); - static const std::string& libloot(); - static const std::string& libloot_hash(); - static const std::string& openssl(); - static const std::string& bzip2(); - static const std::string& lz4(); - static const std::string& nmm(); - static const std::string& spdlog(); - static const std::string& usvfs(); - static const std::string& qt(); - static const std::string& qt_vs(); - static const std::string& pyqt(); - static const std::string& pyqt_builder(); - static const std::string& sip(); - static const std::string& pyqt_sip(); + static const std::string& by_name(const std::string& s); + + VALUE(vs); + VALUE(vs_year); + VALUE(vs_toolset); + VALUE(sdk); + VALUE(sevenzip); + VALUE(zlib); + VALUE(boost); + VALUE(boost_vs); + VALUE(python); + VALUE(fmt); + VALUE(gtest); + VALUE(libbsarch); + VALUE(libloot); + VALUE(libloot_hash); + VALUE(openssl); + VALUE(bzip2); + VALUE(lz4); + VALUE(nmm); + VALUE(spdlog); + VALUE(usvfs); + VALUE(qt); + VALUE(qt_vs); + VALUE(pyqt); + VALUE(pyqt_builder); + VALUE(sip); + VALUE(pyqt_sip); }; struct paths { - static fs::path prefix(); - static fs::path cache(); - static fs::path patches(); - static fs::path build(); + static const fs::path& by_name(const std::string& s); - static fs::path install(); - static fs::path install_bin(); - static fs::path install_libs(); - static fs::path install_pdbs(); + VALUE(third_party); + VALUE(prefix); + VALUE(cache); + VALUE(patches); + VALUE(build); - static fs::path install_dlls(); - static fs::path install_loot(); - static fs::path install_plugins(); + VALUE(install); + VALUE(install_bin); + VALUE(install_libs); + VALUE(install_pdbs); - static fs::path qt(); - static fs::path qt_bin(); - static fs::path program_files_x86(); - static fs::path program_files_x64(); + VALUE(install_dlls); + VALUE(install_loot); + VALUE(install_plugins); - static fs::path temp_dir(); - static fs::path temp_file(); + VALUE(vs); + VALUE(vcvars); + VALUE(qt_install); + VALUE(qt_bin); + VALUE(pf_x86); + VALUE(pf_x64); + VALUE(temp_dir); }; -fs::path find_third_party_directory(); +#undef VALUE + + +void init_options(); +void dump_options(); +void conf_command_line_options(clipp::group& g); + +fs::path make_temp_file(); } // namespace diff --git a/src/context.cpp b/src/context.cpp index 7d13516..cdf6df9 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -50,6 +50,7 @@ std::string reason_string(context::reason r) case context::fs: return "fs"; case context::net: return "net"; case context::generic: return ""; + case context::conf: return "conf"; default: return "?"; } } @@ -252,6 +253,7 @@ std::string context::make_log_string(reason r, level, std::string_view s) const case context::fs: case context::net: case context::generic: + case context::conf: default: oss << s; break; diff --git a/src/context.h b/src/context.h index 843098b..ac36645 100644 --- a/src/context.h +++ b/src/context.h @@ -14,19 +14,22 @@ public: // generic generic, - // an action was bypassed because it was already done + // a configuration action + conf, + + // something was bypassed because it was already done bypass, - // an action was done because the --redownload option was set + // something was done because the --redownload option was set redownload, - // an action was done because the --rebuild option was set + // something was done because the --rebuild option was set rebuild, - // an action was done because the --reextract option was set + // something was done because the --reextract option was set reextract, - // an action was done in case of interruption or because something + // something was done in case of interruption or because something // was interrupted interruption, diff --git a/src/env.cpp b/src/env.cpp index 7393a0d..fd6fffb 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -8,41 +8,6 @@ namespace mob { -fs::path find_vcvars() -{ - const std::vector editions = - { - "Community", "Preview", "Enterprise", "Professional" - }; - - const fs::path bat = "vcvarsall.bat"; - - gcx().trace(context::generic, "looking for " + bat.string()); - - for (auto&& edition : editions) - { - const auto dir = - paths::program_files_x86() / - "Microsoft Visual Studio" / - versions::vs_year() / - edition / "VC" / "Auxiliary" / "Build"; - - const auto f = dir / bat; - - if (fs::exists(f)) - { - gcx().trace(context::generic, "found " + f.string()); - return f; - } - else - { - gcx().trace(context::generic, "not found in " + dir.string()); - } - } - - gcx().bail_out(context::generic, "couldn't find visual studio"); -} - env get_vcvars_env(arch a) { std::string arch_s; @@ -64,11 +29,11 @@ env get_vcvars_env(arch a) gcx().trace(context::generic, "looking for vcvars for " + arch_s); - const fs::path tmp = paths::temp_file(); + const fs::path tmp = make_temp_file(); // "vcvarsall.bat" amd64 && set > temp_file std::string cmd = - "\"" + find_vcvars().string() + "\" " + arch_s + + "\"" + paths::vcvars().string() + "\" " + arch_s + " && set > \"" + tmp.string() + "\""; process::raw(gcx(), cmd) diff --git a/src/main.cpp b/src/main.cpp index 04dd2fa..4a23e58 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,7 @@ namespace mob { + BOOL WINAPI signal_handler(DWORD) noexcept { gcx().debug(context::generic, "caught sigint"); @@ -31,18 +32,74 @@ struct curl_init }; +std::string version() +{ + return "mob 1.0"; +} + +void show_help(const clipp::group& g) +{ + std::cout + << clipp::make_man_page( + g, "mob", clipp::doc_formatting() + .first_column(4) + .doc_column(30)); +} + + int run(int argc, char** argv) { + struct + { + bool version = false; + bool help = false; + } cmd; + + clipp::group g; + + g.push_back( + (clipp::option("--version") + >> [&]{ cmd.version = true; }) + % "shows the version", + + (clipp::option("-h", "--help") + >> [&]{ cmd.help = true; }) + % "shows this message" + ); + + + conf_command_line_options(g); + try { + const auto pr = clipp::parse(argc, argv, g); + + if (!pr) + throw bad_command_line(); + + + if (cmd.version) + { + std::cout << version() << "\n"; + return 0; + } + + if (cmd.help) + { + show_help(g); + return 0; + } + + + init_options(); + dump_options(); + return 0; + ::SetConsoleCtrlHandler(signal_handler, TRUE); curl_init curl; - this_env::set( - "PATH", - (find_third_party_directory() / "bin").string() + ";", - env::prepend); + //this_env::set("PATH", paths::third_party().string() + ";", env::prepend); add_task(); add_task(); @@ -63,7 +120,7 @@ int run(int argc, char** argv) add_task(); add_task(); - if (argc > 1) + /*if (argc > 1) { std::vector tasks; @@ -84,13 +141,22 @@ int run(int argc, char** argv) } return 0; - } + }*/ run_all_tasks(); return 0; } - catch(bailed) + catch(bad_command_line&) + { + show_help(g); + return 1; + } + catch(bad_conf&) + { + return 1; + } + catch(bailed&) { error("bailing out"); return 1; diff --git a/src/pch.h b/src/pch.h index 6b3fd1f..1a058ee 100644 --- a/src/pch.h +++ b/src/pch.h @@ -64,7 +64,9 @@ #include #include + #include +#include #pragma warning(pop) diff --git a/src/process.cpp b/src/process.cpp index 99c5ccf..454a46b 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -8,7 +8,7 @@ namespace mob { -HANDLE bit_bucket() +HANDLE get_bit_bucket() { SECURITY_ATTRIBUTES sa { .nLength = sizeof(sa), .bInheritHandle = TRUE }; return ::CreateFileA("NUL", GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0); @@ -212,7 +212,9 @@ process::impl& process::impl::operator=(const impl& i) process::process() : cx_(&gcx()), flags_(process::noflags), + stdout_flags_(process::forward_to_log), stdout_level_(context::level::trace), + stderr_flags_(process::forward_to_log), stderr_level_(context::level::error), code_(0) { @@ -279,6 +281,12 @@ const fs::path& process::cwd() const return cwd_; } +process& process::stdout_flags(stream_flags s) +{ + stdout_flags_ = s; + return *this; +} + process& process::stdout_level(context::level lv) { stdout_level_ = lv; @@ -291,6 +299,12 @@ process& process::stdout_filter(filter_fun f) return *this; } +process& process::stderr_flags(stream_flags s) +{ + stderr_flags_ = s; + return *this; +} + process& process::stderr_level(context::level lv) { stderr_level_ = lv; @@ -363,6 +377,9 @@ void process::run() void process::do_run(const std::string& what) { + if (raw_.empty() && bin_.empty()) + cx_->bail_out(context::cmd, "process: nothing to run"); + if (fs::exists(error_log_file_)) { cx_->trace(context::cmd, @@ -375,12 +392,55 @@ void process::do_run(const std::string& what) STARTUPINFOA si = { .cb=sizeof(si) }; PROCESS_INFORMATION pi = {}; - auto process_stderr = impl_.stderr_pipe.create(); - auto process_stdout = impl_.stdout_pipe.create(); + handle_ptr stdout_pipe, stderr_pipe; - si.hStdOutput = process_stdout.get(); - si.hStdError = process_stderr.get(); - si.hStdInput = bit_bucket(); + switch (stdout_flags_) + { + case forward_to_log: + case keep_in_string: + { + stdout_pipe = impl_.stdout_pipe.create(); + si.hStdOutput = stdout_pipe.get(); + break; + } + + case bit_bucket: + { + si.hStdOutput = get_bit_bucket(); + break; + } + + case inherit: + { + si.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); + break; + } + } + + switch (stderr_flags_) + { + case forward_to_log: + case keep_in_string: + { + stderr_pipe = impl_.stderr_pipe.create(); + si.hStdError = stderr_pipe.get(); + break; + } + + case bit_bucket: + { + si.hStdError = get_bit_bucket(); + break; + } + + case inherit: + { + si.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); + break; + } + } + + si.hStdInput = get_bit_bucket(); si.dwFlags = STARTF_USESTDHANDLES; const std::string cmd = this_env::get("COMSPEC"); @@ -458,37 +518,76 @@ void process::join() void process::read_pipes() { // stdout - std::string_view s = impl_.stdout_pipe.read(); - for_each_line(s, [&](auto&& line) + switch (stdout_flags_) { - filter f = {line, context::std_out, stdout_level_, false}; - - if (stdout_filter_) + case forward_to_log: { - stdout_filter_(f); - if (f.ignore) - return; + std::string_view s = impl_.stdout_pipe.read(); + + for_each_line(s, [&](auto&& line) + { + filter f = {line, context::std_out, stdout_level_, false}; + + if (stdout_filter_) + { + stdout_filter_(f); + if (f.ignore) + return; + } + + cx_->log(f.r, f.lv, f.line); + }); + + break; } - cx_->log(f.r, f.lv, f.line); - }); - - - // stderr - s = impl_.stderr_pipe.read(); - for_each_line(s, [&](auto&& line) - { - filter f = {line, context::std_err, stderr_level_, false}; - - if (stderr_filter_) + case keep_in_string: { - stderr_filter_(f); - if (f.ignore) - return; + std::string_view s = impl_.stdout_pipe.read(); + stdout_string_ += s; + break; } - cx_->log(f.r, f.lv, f.line); - }); + case bit_bucket: + case inherit: + break; + } + + + switch (stderr_flags_) + { + case forward_to_log: + { + std::string_view s = impl_.stderr_pipe.read(); + + for_each_line(s, [&](auto&& line) + { + filter f = {line, context::std_err, stderr_level_, false}; + + if (stderr_filter_) + { + stderr_filter_(f); + if (f.ignore) + return; + } + + cx_->log(f.r, f.lv, f.line); + }); + + break; + } + + case keep_in_string: + { + std::string_view s = impl_.stderr_pipe.read(); + stderr_string_ += s; + break; + } + + case bit_bucket: + case inherit: + break; + } } void process::on_completed() @@ -603,6 +702,16 @@ int process::exit_code() const return static_cast(code_); } +std::string process::steal_stdout() +{ + return std::move(stdout_string_); +} + +std::string process::steal_stderr() +{ + return std::move(stderr_string_); +} + void process::add_arg(const std::string& k, const std::string& v, arg_flags f) { if ((f & log_debug) && !conf::log_debug()) diff --git a/src/process.h b/src/process.h index 89b5460..5224635 100644 --- a/src/process.h +++ b/src/process.h @@ -55,6 +55,14 @@ public: quote = 0x20 }; + enum stream_flags + { + forward_to_log = 1, + bit_bucket, + keep_in_string, + inherit + }; + struct filter { const std::string_view line; @@ -96,9 +104,11 @@ public: process& cwd(const fs::path& p); const fs::path& cwd() const; + process& stdout_flags(stream_flags s); process& stdout_level(context::level lv); process& stdout_filter(filter_fun f); + process& stderr_flags(stream_flags s); process& stderr_level(context::level lv); process& stderr_filter(filter_fun f); @@ -146,6 +156,8 @@ public: void join(); int exit_code() const; + std::string steal_stdout(); + std::string steal_stderr(); private: struct impl @@ -164,10 +176,17 @@ private: fs::path bin_; fs::path cwd_; flags_t flags_; + + stream_flags stdout_flags_; context::level stdout_level_; filter_fun stdout_filter_; + std::string stdout_string_; + + stream_flags stderr_flags_; context::level stderr_level_; filter_fun stderr_filter_; + std::string stderr_string_; + mob::env env_; std::string raw_; std::string cmd_; diff --git a/src/tasks/openssl.cpp b/src/tasks/openssl.cpp index 86496e3..4b30b6d 100644 --- a/src/tasks/openssl.cpp +++ b/src/tasks/openssl.cpp @@ -51,7 +51,7 @@ void openssl::do_build_and_install() void openssl::configure() { run_tool(process_runner(process() - .binary(third_party::perl()) + .binary(tool_paths::perl()) .arg("Configure") .arg("--openssldir=", build_path()) .arg("--prefix=", build_path()) diff --git a/src/tools/cmake.cpp b/src/tools/cmake.cpp index 10cce25..272d00c 100644 --- a/src/tools/cmake.cpp +++ b/src/tools/cmake.cpp @@ -8,7 +8,7 @@ cmake::cmake() : basic_process_runner("cmake"), gen_(jom), arch_(arch::def) { process_ - .binary(third_party::cmake()); + .binary(tool_paths::cmake()); } cmake& cmake::generator(generators g) diff --git a/src/tools/git.cpp b/src/tools/git.cpp index 1ecf82c..faf3014 100644 --- a/src/tools/git.cpp +++ b/src/tools/git.cpp @@ -56,7 +56,7 @@ void git_clone::do_run() void git_clone::clone() { process_ = process() - .binary(third_party::git()) + .binary(tool_paths::git()) .stderr_level(context::level::trace) .arg("clone") .arg("--recurse-submodules") @@ -73,7 +73,7 @@ void git_clone::clone() void git_clone::pull() { process_ = process() - .binary(third_party::git()) + .binary(tool_paths::git()) .stderr_level(context::level::trace) .arg("pull") .arg("--recurse-submodules") diff --git a/src/tools/msbuild.cpp b/src/tools/msbuild.cpp index 3d0a9af..2f722b6 100644 --- a/src/tools/msbuild.cpp +++ b/src/tools/msbuild.cpp @@ -9,7 +9,7 @@ msbuild::msbuild() : basic_process_runner("msbuild"), config_("Release"), arch_(arch::def) { process_ - .binary(third_party::msbuild()); + .binary(tool_paths::msbuild()); } msbuild& msbuild::solution(const fs::path& sln) diff --git a/src/tools/tools.cpp b/src/tools/tools.cpp index 0f81e45..6ad84a4 100644 --- a/src/tools/tools.cpp +++ b/src/tools/tools.cpp @@ -64,7 +64,7 @@ devenv_upgrade::devenv_upgrade(fs::path sln) : basic_process_runner("upgrade project"), sln_(std::move(sln)) { process_ - .binary(third_party::devenv()) + .binary(tool_paths::devenv()) .env(env::vs(arch::x64)); } diff --git a/src/utility.cpp b/src/utility.cpp index 424edb8..bf7188c 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -39,6 +39,26 @@ std::string join(const std::vector& v, const std::string& sep) return s; } +void trim(std::string& s, const std::string& what) +{ + while (!s.empty()) + { + if (what.find(s[0]) != std::string::npos) + s.erase(0, 1); + else if (what.find(s[s.size() - 1]) != std::string::npos) + s.erase(s.size() - 1, 1); + else + break; + } +} + +std::string trim_copy(const std::string& s, const std::string& what) +{ + std::string c = s; + trim(c, what); + return c; +} + std::string pad_right(std::string s, std::size_t n, char c) { if (s.size() < n) diff --git a/src/utility.h b/src/utility.h index 3fb7e42..91eb859 100644 --- a/src/utility.h +++ b/src/utility.h @@ -166,10 +166,12 @@ std::string replace_all( std::string s, const std::string& from, const std::string& to); std::string join(const std::vector& v, const std::string& sep); - std::string pad_right(std::string s, std::size_t n, char c=' '); std::string pad_left(std::string s, std::size_t n, char c=' '); +void trim(std::string& s, const std::string& what=" \t\r\n"); +std::string trim_copy(const std::string& s, const std::string& what=" \t\r\n"); + template void for_each_line(std::string_view s, F&& f) diff --git a/third-party/bin/vswhere.exe b/third-party/bin/vswhere.exe new file mode 100644 index 0000000000000000000000000000000000000000..582e82868dddc97bec4a8c8353f729348be55f56 GIT binary patch literal 458872 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

X?Pan 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 literal 0 HcmV?d00001 diff --git a/third-party/include/clipp.h b/third-party/include/clipp.h new file mode 100644 index 0000000..69dd13a --- /dev/null +++ b/third-party/include/clipp.h @@ -0,0 +1,7024 @@ +/***************************************************************************** + * ___ _ _ ___ ___ + * | _|| | | | | _ \ _ \ CLIPP - command line interfaces for modern C++ + * | |_ | |_ | | | _/ _/ version 1.2.3 + * |___||___||_| |_| |_| https://github.com/muellan/clipp + * + * Licensed under the MIT License . + * Copyright (c) 2017-2018 André Müller + * + * --------------------------------------------------------------------------- + * 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. + * + *****************************************************************************/ + +#ifndef AM_CLIPP_H__ +#define AM_CLIPP_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/*************************************************************************//** + * + * @brief primary namespace + * + *****************************************************************************/ +namespace clipp { + + + +/***************************************************************************** + * + * basic constants and datatype definitions + * + *****************************************************************************/ +using arg_index = int; + +using arg_string = std::string; +using doc_string = std::string; + +using arg_list = std::vector; + + + +/*************************************************************************//** + * + * @brief tristate + * + *****************************************************************************/ +enum class tri : char { no, yes, either }; + +inline constexpr bool operator == (tri t, bool b) noexcept { + return b ? t != tri::no : t != tri::yes; +} +inline constexpr bool operator == (bool b, tri t) noexcept { return (t == b); } +inline constexpr bool operator != (tri t, bool b) noexcept { return !(t == b); } +inline constexpr bool operator != (bool b, tri t) noexcept { return !(t == b); } + + + +/*************************************************************************//** + * + * @brief (start,size) index range + * + *****************************************************************************/ +class subrange { +public: + using size_type = arg_string::size_type; + + /** @brief default: no match */ + explicit constexpr + subrange() noexcept : + at_{arg_string::npos}, length_{0} + {} + + /** @brief match length & position within subject string */ + explicit constexpr + subrange(size_type pos, size_type len) noexcept : + at_{pos}, length_{len} + {} + + /** @brief position of the match within the subject string */ + constexpr size_type at() const noexcept { return at_; } + /** @brief length of the matching subsequence */ + constexpr size_type length() const noexcept { return length_; } + + /** @brief returns true, if query string is a prefix of the subject string */ + constexpr bool prefix() const noexcept { + return at_ == 0; + } + + /** @brief returns true, if query is a substring of the query string */ + constexpr explicit operator bool () const noexcept { + return at_ != arg_string::npos; + } + +private: + size_type at_; + size_type length_; +}; + + + +/*************************************************************************//** + * + * @brief match predicates + * + *****************************************************************************/ +using match_predicate = std::function; +using match_function = std::function; + + + + + + +/*************************************************************************//** + * + * @brief type traits (NOT FOR DIRECT USE IN CLIENT CODE!) + * no interface guarantees; might be changed or removed in the future + * + *****************************************************************************/ +namespace traits { + +/*************************************************************************//** + * + * @brief function (class) signature type trait + * + *****************************************************************************/ +template +constexpr auto +check_is_callable(int) -> decltype( + std::declval()(std::declval()...), + std::integral_constant::value>{} ); + +template +constexpr auto +check_is_callable(long) -> std::false_type; + +template +constexpr auto +check_is_callable_without_arg(int) -> decltype( + std::declval()(), + std::integral_constant::value>{} ); + +template +constexpr auto +check_is_callable_without_arg(long) -> std::false_type; + + + +template +constexpr auto +check_is_void_callable(int) -> decltype( + std::declval()(std::declval()...), std::true_type{}); + +template +constexpr auto +check_is_void_callable(long) -> std::false_type; + +template +constexpr auto +check_is_void_callable_without_arg(int) -> decltype( + std::declval()(), std::true_type{}); + +template +constexpr auto +check_is_void_callable_without_arg(long) -> std::false_type; + + + +template +struct is_callable; + + +template +struct is_callable : + decltype(check_is_callable(0)) +{}; + +template +struct is_callable : + decltype(check_is_callable_without_arg(0)) +{}; + + +template +struct is_callable : + decltype(check_is_void_callable(0)) +{}; + +template +struct is_callable : + decltype(check_is_void_callable_without_arg(0)) +{}; + + + +/*************************************************************************//** + * + * @brief input range type trait + * + *****************************************************************************/ +template +constexpr auto +check_is_input_range(int) -> decltype( + begin(std::declval()), end(std::declval()), + std::true_type{}); + +template +constexpr auto +check_is_input_range(char) -> decltype( + std::begin(std::declval()), std::end(std::declval()), + std::true_type{}); + +template +constexpr auto +check_is_input_range(long) -> std::false_type; + +template +struct is_input_range : + decltype(check_is_input_range(0)) +{}; + + + +/*************************************************************************//** + * + * @brief size() member type trait + * + *****************************************************************************/ +template +constexpr auto +check_has_size_getter(int) -> + decltype(std::declval().size(), std::true_type{}); + +template +constexpr auto +check_has_size_getter(long) -> std::false_type; + +template +struct has_size_getter : + decltype(check_has_size_getter(0)) +{}; + +} // namespace traits + + + + + + +/*************************************************************************//** + * + * @brief helpers (NOT FOR DIRECT USE IN CLIENT CODE!) + * no interface guarantees; might be changed or removed in the future + * + *****************************************************************************/ +namespace detail { + + +/*************************************************************************//** + * @brief forwards string to first non-whitespace char; + * std string -> unsigned conv yields max value, but we want 0; + * also checks for nullptr + *****************************************************************************/ +inline bool +fwd_to_unsigned_int(const char*& s) +{ + if(!s) return false; + for(; std::isspace(*s); ++s); + if(!s[0] || s[0] == '-') return false; + if(s[0] == '-') return false; + return true; +} + + +/*************************************************************************//** + * + * @brief value limits clamping + * + *****************************************************************************/ +template sizeof(T))> +struct limits_clamped { + static T from(const V& v) { + if(v >= V(std::numeric_limits::max())) { + return std::numeric_limits::max(); + } + if(v <= V(std::numeric_limits::lowest())) { + return std::numeric_limits::lowest(); + } + return T(v); + } +}; + +template +struct limits_clamped { + static T from(const V& v) { return T(v); } +}; + + +/*************************************************************************//** + * + * @brief returns value of v as a T, clamped at T's maximum + * + *****************************************************************************/ +template +inline T clamped_on_limits(const V& v) { + return limits_clamped::from(v); +} + + + + +/*************************************************************************//** + * + * @brief type conversion helpers + * + *****************************************************************************/ +template +struct make { + static inline T from(const char* s) { + if(!s) return false; + //a conversion from const char* to / must exist + return static_cast(s); + } +}; + +template<> +struct make { + static inline bool from(const char* s) { + if(!s) return false; + return static_cast(s); + } +}; + +template<> +struct make { + static inline unsigned char from(const char* s) { + if(!fwd_to_unsigned_int(s)) return (0); + return clamped_on_limits(std::strtoull(s,nullptr,10)); + } +}; + +template<> +struct make { + static inline unsigned short int from(const char* s) { + if(!fwd_to_unsigned_int(s)) return (0); + return clamped_on_limits(std::strtoull(s,nullptr,10)); + } +}; + +template<> +struct make { + static inline unsigned int from(const char* s) { + if(!fwd_to_unsigned_int(s)) return (0); + return clamped_on_limits(std::strtoull(s,nullptr,10)); + } +}; + +template<> +struct make { + static inline unsigned long int from(const char* s) { + if(!fwd_to_unsigned_int(s)) return (0); + return clamped_on_limits(std::strtoull(s,nullptr,10)); + } +}; + +template<> +struct make { + static inline unsigned long long int from(const char* s) { + if(!fwd_to_unsigned_int(s)) return (0); + return clamped_on_limits(std::strtoull(s,nullptr,10)); + } +}; + +template<> +struct make { + static inline char from(const char* s) { + //parse as single character? + const auto n = std::strlen(s); + if(n == 1) return s[0]; + //parse as integer + return clamped_on_limits(std::strtoll(s,nullptr,10)); + } +}; + +template<> +struct make { + static inline short int from(const char* s) { + return clamped_on_limits(std::strtoll(s,nullptr,10)); + } +}; + +template<> +struct make { + static inline int from(const char* s) { + return clamped_on_limits(std::strtoll(s,nullptr,10)); + } +}; + +template<> +struct make { + static inline long int from(const char* s) { + return clamped_on_limits(std::strtoll(s,nullptr,10)); + } +}; + +template<> +struct make { + static inline long long int from(const char* s) { + return (std::strtoll(s,nullptr,10)); + } +}; + +template<> +struct make { + static inline float from(const char* s) { + return (std::strtof(s,nullptr)); + } +}; + +template<> +struct make { + static inline double from(const char* s) { + return (std::strtod(s,nullptr)); + } +}; + +template<> +struct make { + static inline long double from(const char* s) { + return (std::strtold(s,nullptr)); + } +}; + +template<> +struct make { + static inline std::string from(const char* s) { + return std::string(s); + } +}; + + + +/*************************************************************************//** + * + * @brief assigns boolean constant to one or multiple target objects + * + *****************************************************************************/ +template +class assign_value +{ +public: + template + explicit constexpr + assign_value(T& target, X&& value) noexcept : + t_{std::addressof(target)}, v_{std::forward(value)} + {} + + void operator () () const { + if(t_) *t_ = v_; + } + +private: + T* t_; + V v_; +}; + + + +/*************************************************************************//** + * + * @brief flips bools + * + *****************************************************************************/ +class flip_bool +{ +public: + explicit constexpr + flip_bool(bool& target) noexcept : + b_{&target} + {} + + void operator () () const { + if(b_) *b_ = !*b_; + } + +private: + bool* b_; +}; + + + +/*************************************************************************//** + * + * @brief increments using operator ++ + * + *****************************************************************************/ +template +class increment +{ +public: + explicit constexpr + increment(T& target) noexcept : t_{std::addressof(target)} {} + + void operator () () const { + if(t_) ++(*t_); + } + +private: + T* t_; +}; + + + +/*************************************************************************//** + * + * @brief decrements using operator -- + * + *****************************************************************************/ +template +class decrement +{ +public: + explicit constexpr + decrement(T& target) noexcept : t_{std::addressof(target)} {} + + void operator () () const { + if(t_) --(*t_); + } + +private: + T* t_; +}; + + + +/*************************************************************************//** + * + * @brief increments by a fixed amount using operator += + * + *****************************************************************************/ +template +class increment_by +{ +public: + explicit constexpr + increment_by(T& target, T by) noexcept : + t_{std::addressof(target)}, by_{std::move(by)} + {} + + void operator () () const { + if(t_) (*t_) += by_; + } + +private: + T* t_; + T by_; +}; + + + + +/*************************************************************************//** + * + * @brief makes a value from a string and assigns it to an object + * + *****************************************************************************/ +template +class map_arg_to +{ +public: + explicit constexpr + map_arg_to(T& target) noexcept : t_{std::addressof(target)} {} + + void operator () (const char* s) const { + if(t_ && s) *t_ = detail::make::from(s); + } + +private: + T* t_; +}; + + +//------------------------------------------------------------------- +/** + * @brief specialization for vectors: append element + */ +template +class map_arg_to> +{ +public: + map_arg_to(std::vector& target): t_{std::addressof(target)} {} + + void operator () (const char* s) const { + if(t_ && s) t_->push_back(detail::make::from(s)); + } + +private: + std::vector* t_; +}; + + +//------------------------------------------------------------------- +/** + * @brief specialization for bools: + * set to true regardless of string content + */ +template<> +class map_arg_to +{ +public: + map_arg_to(bool& target): t_{&target} {} + + void operator () (const char* s) const { + if(t_ && s) *t_ = true; + } + +private: + bool* t_; +}; + + +} // namespace detail + + + + + + +/*************************************************************************//** + * + * @brief string matching and processing tools + * + *****************************************************************************/ + +namespace str { + + +/*************************************************************************//** + * + * @brief converts string to value of target type 'T' + * + *****************************************************************************/ +template +T make(const arg_string& s) +{ + return detail::make::from(s); +} + + + +/*************************************************************************//** + * + * @brief removes trailing whitespace from string + * + *****************************************************************************/ +template +inline void +trimr(std::basic_string& s) +{ + if(s.empty()) return; + + s.erase( + std::find_if_not(s.rbegin(), s.rend(), + [](char c) { return std::isspace(c);} ).base(), + s.end() ); +} + + +/*************************************************************************//** + * + * @brief removes leading whitespace from string + * + *****************************************************************************/ +template +inline void +triml(std::basic_string& s) +{ + if(s.empty()) return; + + s.erase( + s.begin(), + std::find_if_not(s.begin(), s.end(), + [](char c) { return std::isspace(c);}) + ); +} + + +/*************************************************************************//** + * + * @brief removes leading and trailing whitespace from string + * + *****************************************************************************/ +template +inline void +trim(std::basic_string& s) +{ + triml(s); + trimr(s); +} + + +/*************************************************************************//** + * + * @brief removes all whitespaces from string + * + *****************************************************************************/ +template +inline void +remove_ws(std::basic_string& s) +{ + if(s.empty()) return; + + s.erase(std::remove_if(s.begin(), s.end(), + [](char c) { return std::isspace(c); }), + s.end() ); +} + + +/*************************************************************************//** + * + * @brief returns true, if the 'prefix' argument + * is a prefix of the 'subject' argument + * + *****************************************************************************/ +template +inline bool +has_prefix(const std::basic_string& subject, + const std::basic_string& prefix) +{ + if(prefix.size() > subject.size()) return false; + return subject.find(prefix) == 0; +} + + +/*************************************************************************//** + * + * @brief returns true, if the 'postfix' argument + * is a postfix of the 'subject' argument + * + *****************************************************************************/ +template +inline bool +has_postfix(const std::basic_string& subject, + const std::basic_string& postfix) +{ + if(postfix.size() > subject.size()) return false; + return (subject.size() - postfix.size()) == subject.find(postfix); +} + + + +/*************************************************************************//** +* +* @brief returns longest common prefix of several +* sequential random access containers +* +* @details InputRange require begin and end (member functions or overloads) +* the elements of InputRange require a size() member +* +*****************************************************************************/ +template +auto +longest_common_prefix(const InputRange& strs) + -> typename std::decay::type +{ + static_assert(traits::is_input_range(), + "parameter must satisfy the InputRange concept"); + + static_assert(traits::has_size_getter< + typename std::decay::type>(), + "elements of input range must have a ::size() member function"); + + using std::begin; + using std::end; + + using item_t = typename std::decay::type; + using str_size_t = typename std::decaysize())>::type; + + const auto n = size_t(distance(begin(strs), end(strs))); + if(n < 1) return item_t(""); + if(n == 1) return *begin(strs); + + //length of shortest string + auto m = std::min_element(begin(strs), end(strs), + [](const item_t& a, const item_t& b) { + return a.size() < b.size(); })->size(); + + //check each character until we find a mismatch + for(str_size_t i = 0; i < m; ++i) { + for(str_size_t j = 1; j < n; ++j) { + if(strs[j][i] != strs[j-1][i]) + return strs[0].substr(0, i); + } + } + return strs[0].substr(0, m); +} + + + +/*************************************************************************//** + * + * @brief returns longest substring range that could be found in 'arg' + * + * @param arg string to be searched in + * @param substrings range of candidate substrings + * + *****************************************************************************/ +template +subrange +longest_substring_match(const std::basic_string& arg, + const InputRange& substrings) +{ + using string_t = std::basic_string; + + static_assert(traits::is_input_range(), + "parameter must satisfy the InputRange concept"); + + static_assert(std::is_same::type>(), + "substrings must have same type as 'arg'"); + + auto i = string_t::npos; + auto n = string_t::size_type(0); + for(const auto& s : substrings) { + auto j = arg.find(s); + if(j != string_t::npos && s.size() > n) { + i = j; + n = s.size(); + } + } + return subrange{i,n}; +} + + + +/*************************************************************************//** + * + * @brief returns longest prefix range that could be found in 'arg' + * + * @param arg string to be searched in + * @param prefixes range of candidate prefix strings + * + *****************************************************************************/ +template +subrange +longest_prefix_match(const std::basic_string& arg, + const InputRange& prefixes) +{ + using string_t = std::basic_string; + using s_size_t = typename string_t::size_type; + + static_assert(traits::is_input_range(), + "parameter must satisfy the InputRange concept"); + + static_assert(std::is_same::type>(), + "prefixes must have same type as 'arg'"); + + auto i = string_t::npos; + auto n = s_size_t(0); + for(const auto& s : prefixes) { + auto j = arg.find(s); + if(j == 0 && s.size() > n) { + i = 0; + n = s.size(); + } + } + return subrange{i,n}; +} + + + +/*************************************************************************//** + * + * @brief returns the first occurrence of 'query' within 'subject' + * + *****************************************************************************/ +template +inline subrange +substring_match(const std::basic_string& subject, + const std::basic_string& query) +{ + if(subject.empty() && query.empty()) return subrange(0,0); + if(subject.empty() || query.empty()) return subrange{}; + auto i = subject.find(query); + if(i == std::basic_string::npos) return subrange{}; + return subrange{i,query.size()}; +} + + + +/*************************************************************************//** + * + * @brief returns first substring match (pos,len) within the input string + * that represents a number + * (with at maximum one decimal point and digit separators) + * + *****************************************************************************/ +template +subrange +first_number_match(std::basic_string s, + C digitSeparator = C(','), + C decimalPoint = C('.'), + C exponential = C('e')) +{ + using string_t = std::basic_string; + + str::trim(s); + if(s.empty()) return subrange{}; + + auto i = s.find_first_of("0123456789+-"); + if(i == string_t::npos) { + i = s.find(decimalPoint); + if(i == string_t::npos) return subrange{}; + } + + bool point = false; + bool sep = false; + auto exp = string_t::npos; + auto j = i + 1; + for(; j < s.size(); ++j) { + if(s[j] == digitSeparator) { + if(!sep) sep = true; else break; + } + else { + sep = false; + if(s[j] == decimalPoint) { + //only one decimal point before exponent allowed + if(!point && exp == string_t::npos) point = true; else break; + } + else if(std::tolower(s[j]) == std::tolower(exponential)) { + //only one exponent separator allowed + if(exp == string_t::npos) exp = j; else break; + } + else if(exp != string_t::npos && (exp+1) == j) { + //only sign or digit after exponent separator + if(s[j] != '+' && s[j] != '-' && !std::isdigit(s[j])) break; + } + else if(!std::isdigit(s[j])) { + break; + } + } + } + + //if length == 1 then must be a digit + if(j-i == 1 && !std::isdigit(s[i])) return subrange{}; + + return subrange{i,j-i}; +} + + + +/*************************************************************************//** + * + * @brief returns first substring match (pos,len) + * that represents an integer (with optional digit separators) + * + *****************************************************************************/ +template +subrange +first_integer_match(std::basic_string s, + C digitSeparator = C(',')) +{ + using string_t = std::basic_string; + + str::trim(s); + if(s.empty()) return subrange{}; + + auto i = s.find_first_of("0123456789+-"); + if(i == string_t::npos) return subrange{}; + + bool sep = false; + auto j = i + 1; + for(; j < s.size(); ++j) { + if(s[j] == digitSeparator) { + if(!sep) sep = true; else break; + } + else { + sep = false; + if(!std::isdigit(s[j])) break; + } + } + + //if length == 1 then must be a digit + if(j-i == 1 && !std::isdigit(s[i])) return subrange{}; + + return subrange{i,j-i}; +} + + + +/*************************************************************************//** + * + * @brief returns true if candidate string represents a number + * + *****************************************************************************/ +template +bool represents_number(const std::basic_string& candidate, + C digitSeparator = C(','), + C decimalPoint = C('.'), + C exponential = C('e')) +{ + const auto match = str::first_number_match(candidate, digitSeparator, + decimalPoint, exponential); + + return (match && match.length() == candidate.size()); +} + + + +/*************************************************************************//** + * + * @brief returns true if candidate string represents an integer + * + *****************************************************************************/ +template +bool represents_integer(const std::basic_string& candidate, + C digitSeparator = C(',')) +{ + const auto match = str::first_integer_match(candidate, digitSeparator); + return (match && match.length() == candidate.size()); +} + +} // namespace str + + + + + + +/*************************************************************************//** + * + * @brief makes function object with a const char* parameter + * that assigns a value to a ref-captured object + * + *****************************************************************************/ +template +inline detail::assign_value +set(T& target, V value) { + return detail::assign_value{target, std::move(value)}; +} + + + +/*************************************************************************//** + * + * @brief makes parameter-less function object + * that assigns value(s) to a ref-captured object; + * value(s) are obtained by converting the const char* argument to + * the captured object types; + * bools are always set to true if the argument is not nullptr + * + *****************************************************************************/ +template +inline detail::map_arg_to +set(T& target) { + return detail::map_arg_to{target}; +} + + + +/*************************************************************************//** + * + * @brief makes function object that sets a bool to true + * + *****************************************************************************/ +inline detail::assign_value +set(bool& target) { + return detail::assign_value{target,true}; +} + +/*************************************************************************//** + * + * @brief makes function object that sets a bool to false + * + *****************************************************************************/ +inline detail::assign_value +unset(bool& target) { + return detail::assign_value{target,false}; +} + +/*************************************************************************//** + * + * @brief makes function object that flips the value of a ref-captured bool + * + *****************************************************************************/ +inline detail::flip_bool +flip(bool& b) { + return detail::flip_bool(b); +} + + + + + +/*************************************************************************//** + * + * @brief makes function object that increments using operator ++ + * + *****************************************************************************/ +template +inline detail::increment +increment(T& target) { + return detail::increment{target}; +} + +/*************************************************************************//** + * + * @brief makes function object that decrements using operator -- + * + *****************************************************************************/ +template +inline detail::increment_by +increment(T& target, T by) { + return detail::increment_by{target, std::move(by)}; +} + +/*************************************************************************//** + * + * @brief makes function object that increments by a fixed amount using operator += + * + *****************************************************************************/ +template +inline detail::decrement +decrement(T& target) { + return detail::decrement{target}; +} + + + + + + +/*************************************************************************//** + * + * @brief helpers (NOT FOR DIRECT USE IN CLIENT CODE!) + * + *****************************************************************************/ +namespace detail { + + +/*************************************************************************//** + * + * @brief mixin that provides action definition and execution + * + *****************************************************************************/ +template +class action_provider +{ +private: + //--------------------------------------------------------------- + using simple_action = std::function; + using arg_action = std::function; + using index_action = std::function; + + //----------------------------------------------------- + class simple_action_adapter { + public: + simple_action_adapter() = default; + simple_action_adapter(const simple_action& a): action_(a) {} + simple_action_adapter(simple_action&& a): action_(std::move(a)) {} + void operator() (const char*) const { action_(); } + void operator() (int) const { action_(); } + private: + simple_action action_; + }; + + +public: + //--------------------------------------------------------------- + /** @brief adds an action that has an operator() that is callable + * with a 'const char*' argument */ + Derived& + call(arg_action a) { + argActions_.push_back(std::move(a)); + return *static_cast(this); + } + + /** @brief adds an action that has an operator()() */ + Derived& + call(simple_action a) { + argActions_.push_back(simple_action_adapter(std::move(a))); + return *static_cast(this); + } + + /** @brief adds an action that has an operator() that is callable + * with a 'const char*' argument */ + Derived& operator () (arg_action a) { return call(std::move(a)); } + + /** @brief adds an action that has an operator()() */ + Derived& operator () (simple_action a) { return call(std::move(a)); } + + + //--------------------------------------------------------------- + /** @brief adds an action that will set the value of 't' from + * a 'const char*' arg */ + template + Derived& + set(Target& t) { + static_assert(!std::is_pointer::value, + "parameter target type must not be a pointer"); + + return call(clipp::set(t)); + } + + /** @brief adds an action that will set the value of 't' to 'v' */ + template + Derived& + set(Target& t, Value&& v) { + return call(clipp::set(t, std::forward(v))); + } + + + //--------------------------------------------------------------- + /** @brief adds an action that will be called if a parameter + * matches an argument for the 2nd, 3rd, 4th, ... time + */ + Derived& + if_repeated(simple_action a) { + repeatActions_.push_back(simple_action_adapter{std::move(a)}); + return *static_cast(this); + } + /** @brief adds an action that will be called with the argument's + * index if a parameter matches an argument for + * the 2nd, 3rd, 4th, ... time + */ + Derived& + if_repeated(index_action a) { + repeatActions_.push_back(std::move(a)); + return *static_cast(this); + } + + + //--------------------------------------------------------------- + /** @brief adds an action that will be called if a required parameter + * is missing + */ + Derived& + if_missing(simple_action a) { + missingActions_.push_back(simple_action_adapter{std::move(a)}); + return *static_cast(this); + } + /** @brief adds an action that will be called if a required parameter + * is missing; the action will get called with the index of + * the command line argument where the missing event occurred first + */ + Derived& + if_missing(index_action a) { + missingActions_.push_back(std::move(a)); + return *static_cast(this); + } + + + //--------------------------------------------------------------- + /** @brief adds an action that will be called if a parameter + * was matched, but was unreachable in the current scope + */ + Derived& + if_blocked(simple_action a) { + blockedActions_.push_back(simple_action_adapter{std::move(a)}); + return *static_cast(this); + } + /** @brief adds an action that will be called if a parameter + * was matched, but was unreachable in the current scope; + * the action will be called with the index of + * the command line argument where the problem occurred + */ + Derived& + if_blocked(index_action a) { + blockedActions_.push_back(std::move(a)); + return *static_cast(this); + } + + + //--------------------------------------------------------------- + /** @brief adds an action that will be called if a parameter match + * was in conflict with a different alternative parameter + */ + Derived& + if_conflicted(simple_action a) { + conflictActions_.push_back(simple_action_adapter{std::move(a)}); + return *static_cast(this); + } + /** @brief adds an action that will be called if a parameter match + * was in conflict with a different alternative parameter; + * the action will be called with the index of + * the command line argument where the problem occurred + */ + Derived& + if_conflicted(index_action a) { + conflictActions_.push_back(std::move(a)); + return *static_cast(this); + } + + + //--------------------------------------------------------------- + /** @brief adds targets = either objects whose values should be + * set by command line arguments or actions that should + * be called in case of a match */ + template + Derived& + target(T&& t, Ts&&... ts) { + target(std::forward(t)); + target(std::forward(ts)...); + return *static_cast(this); + } + + /** @brief adds action that should be called in case of a match */ + template::type>() && + (traits::is_callable() || + traits::is_callable() ) + >::type> + Derived& + target(T&& t) { + call(std::forward(t)); + return *static_cast(this); + } + + /** @brief adds object whose value should be set by command line arguments + */ + template::type>() || + (!traits::is_callable() && + !traits::is_callable() ) + >::type> + Derived& + target(T& t) { + set(t); + return *static_cast(this); + } + + //TODO remove ugly empty param list overload + Derived& + target() { + return *static_cast(this); + } + + + //--------------------------------------------------------------- + /** @brief adds target, see member function 'target' */ + template + inline friend Derived& + operator << (Target&& t, Derived& p) { + p.target(std::forward(t)); + return p; + } + /** @brief adds target, see member function 'target' */ + template + inline friend Derived&& + operator << (Target&& t, Derived&& p) { + p.target(std::forward(t)); + return std::move(p); + } + + //----------------------------------------------------- + /** @brief adds target, see member function 'target' */ + template + inline friend Derived& + operator >> (Derived& p, Target&& t) { + p.target(std::forward(t)); + return p; + } + /** @brief adds target, see member function 'target' */ + template + inline friend Derived&& + operator >> (Derived&& p, Target&& t) { + p.target(std::forward(t)); + return std::move(p); + } + + + //--------------------------------------------------------------- + /** @brief executes all argument actions */ + void execute_actions(const arg_string& arg) const { + int i = 0; + for(const auto& a : argActions_) { + ++i; + a(arg.c_str()); + } + } + + /** @brief executes repeat actions */ + void notify_repeated(arg_index idx) const { + for(const auto& a : repeatActions_) a(idx); + } + /** @brief executes missing error actions */ + void notify_missing(arg_index idx) const { + for(const auto& a : missingActions_) a(idx); + } + /** @brief executes blocked error actions */ + void notify_blocked(arg_index idx) const { + for(const auto& a : blockedActions_) a(idx); + } + /** @brief executes conflict error actions */ + void notify_conflict(arg_index idx) const { + for(const auto& a : conflictActions_) a(idx); + } + +private: + //--------------------------------------------------------------- + std::vector argActions_; + std::vector repeatActions_; + std::vector missingActions_; + std::vector blockedActions_; + std::vector conflictActions_; +}; + + + + + + +/*************************************************************************//** + * + * @brief mixin that provides basic common settings of parameters and groups + * + *****************************************************************************/ +template +class token +{ +public: + //--------------------------------------------------------------- + using doc_string = clipp::doc_string; + + + //--------------------------------------------------------------- + /** @brief returns documentation string */ + const doc_string& doc() const noexcept { + return doc_; + } + + /** @brief sets documentations string */ + Derived& doc(const doc_string& txt) { + doc_ = txt; + return *static_cast(this); + } + + /** @brief sets documentations string */ + Derived& doc(doc_string&& txt) { + doc_ = std::move(txt); + return *static_cast(this); + } + + + //--------------------------------------------------------------- + /** @brief returns if a group/parameter is repeatable */ + bool repeatable() const noexcept { + return repeatable_; + } + + /** @brief sets repeatability of group/parameter */ + Derived& repeatable(bool yes) noexcept { + repeatable_ = yes; + return *static_cast(this); + } + + + //--------------------------------------------------------------- + /** @brief returns if a group/parameter is blocking/positional */ + bool blocking() const noexcept { + return blocking_; + } + + /** @brief determines, if a group/parameter is blocking/positional */ + Derived& blocking(bool yes) noexcept { + blocking_ = yes; + return *static_cast(this); + } + + +private: + //--------------------------------------------------------------- + doc_string doc_; + bool repeatable_ = false; + bool blocking_ = false; +}; + + + + +/*************************************************************************//** + * + * @brief sets documentation strings on a token + * + *****************************************************************************/ +template +inline T& +operator % (doc_string docstr, token& p) +{ + return p.doc(std::move(docstr)); +} +//--------------------------------------------------------- +template +inline T&& +operator % (doc_string docstr, token&& p) +{ + return std::move(p.doc(std::move(docstr))); +} + +//--------------------------------------------------------- +template +inline T& +operator % (token& p, doc_string docstr) +{ + return p.doc(std::move(docstr)); +} +//--------------------------------------------------------- +template +inline T&& +operator % (token&& p, doc_string docstr) +{ + return std::move(p.doc(std::move(docstr))); +} + + + + +/*************************************************************************//** + * + * @brief sets documentation strings on a token + * + *****************************************************************************/ +template +inline T& +doc(doc_string docstr, token& p) +{ + return p.doc(std::move(docstr)); +} +//--------------------------------------------------------- +template +inline T&& +doc(doc_string docstr, token&& p) +{ + return std::move(p.doc(std::move(docstr))); +} + + + +} // namespace detail + + + +/*************************************************************************//** + * + * @brief contains parameter matching functions and function classes + * + *****************************************************************************/ +namespace match { + + +/*************************************************************************//** + * + * @brief predicate that is always true + * + *****************************************************************************/ +inline bool +any(const arg_string&) { return true; } + +/*************************************************************************//** + * + * @brief predicate that is always false + * + *****************************************************************************/ +inline bool +none(const arg_string&) { return false; } + + + +/*************************************************************************//** + * + * @brief predicate that returns true if the argument string is non-empty string + * + *****************************************************************************/ +inline bool +nonempty(const arg_string& s) { + return !s.empty(); +} + + + +/*************************************************************************//** + * + * @brief predicate that returns true if the argument is a non-empty + * string that consists only of alphanumeric characters + * + *****************************************************************************/ +inline bool +alphanumeric(const arg_string& s) { + if(s.empty()) return false; + return std::all_of(s.begin(), s.end(), [](char c) {return std::isalnum(c); }); +} + + + +/*************************************************************************//** + * + * @brief predicate that returns true if the argument is a non-empty + * string that consists only of alphabetic characters + * + *****************************************************************************/ +inline bool +alphabetic(const arg_string& s) { + return std::all_of(s.begin(), s.end(), [](char c) {return std::isalpha(c); }); +} + + + +/*************************************************************************//** + * + * @brief predicate that returns false if the argument string is + * equal to any string from the exclusion list + * + *****************************************************************************/ +class none_of +{ +public: + none_of(arg_list strs): + excluded_{std::move(strs)} + {} + + template + none_of(arg_string str, Strings&&... strs): + excluded_{std::move(str), std::forward(strs)...} + {} + + template + none_of(const char* str, Strings&&... strs): + excluded_{arg_string(str), std::forward(strs)...} + {} + + bool operator () (const arg_string& arg) const { + return (std::find(begin(excluded_), end(excluded_), arg) + == end(excluded_)); + } + +private: + arg_list excluded_; +}; + + + +/*************************************************************************//** + * + * @brief predicate that returns the first substring match within the input + * string that rmeepresents a number + * (with at maximum one decimal point and digit separators) + * + *****************************************************************************/ +class numbers +{ +public: + explicit + numbers(char decimalPoint = '.', + char digitSeparator = ' ', + char exponentSeparator = 'e') + : + decpoint_{decimalPoint}, separator_{digitSeparator}, + exp_{exponentSeparator} + {} + + subrange operator () (const arg_string& s) const { + return str::first_number_match(s, separator_, decpoint_, exp_); + } + +private: + char decpoint_; + char separator_; + char exp_; +}; + + + +/*************************************************************************//** + * + * @brief predicate that returns true if the input string represents an integer + * (with optional digit separators) + * + *****************************************************************************/ +class integers { +public: + explicit + integers(char digitSeparator = ' '): separator_{digitSeparator} {} + + subrange operator () (const arg_string& s) const { + return str::first_integer_match(s, separator_); + } + +private: + char separator_; +}; + + + +/*************************************************************************//** + * + * @brief predicate that returns true if the input string represents + * a non-negative integer (with optional digit separators) + * + *****************************************************************************/ +class positive_integers { +public: + explicit + positive_integers(char digitSeparator = ' '): separator_{digitSeparator} {} + + subrange operator () (const arg_string& s) const { + auto match = str::first_integer_match(s, separator_); + if(!match) return subrange{}; + if(s[match.at()] == '-') return subrange{}; + return match; + } + +private: + char separator_; +}; + + + +/*************************************************************************//** + * + * @brief predicate that returns true if the input string + * contains a given substring + * + *****************************************************************************/ +class substring +{ +public: + explicit + substring(arg_string str): str_{std::move(str)} {} + + subrange operator () (const arg_string& s) const { + return str::substring_match(s, str_); + } + +private: + arg_string str_; +}; + + + +/*************************************************************************//** + * + * @brief predicate that returns true if the input string starts + * with a given prefix + * + *****************************************************************************/ +class prefix { +public: + explicit + prefix(arg_string p): prefix_{std::move(p)} {} + + bool operator () (const arg_string& s) const { + return s.find(prefix_) == 0; + } + +private: + arg_string prefix_; +}; + + + +/*************************************************************************//** + * + * @brief predicate that returns true if the input string does not start + * with a given prefix + * + *****************************************************************************/ +class prefix_not { +public: + explicit + prefix_not(arg_string p): prefix_{std::move(p)} {} + + bool operator () (const arg_string& s) const { + return s.find(prefix_) != 0; + } + +private: + arg_string prefix_; +}; + + +/** @brief alias for prefix_not */ +using noprefix = prefix_not; + + + +/*************************************************************************//** + * + * @brief predicate that returns true if the length of the input string + * is wihtin a given interval + * + *****************************************************************************/ +class length { +public: + explicit + length(std::size_t exact): + min_{exact}, max_{exact} + {} + + explicit + length(std::size_t min, std::size_t max): + min_{min}, max_{max} + {} + + bool operator () (const arg_string& s) const { + return s.size() >= min_ && s.size() <= max_; + } + +private: + std::size_t min_; + std::size_t max_; +}; + + +/*************************************************************************//** + * + * @brief makes function object that returns true if the input string has a + * given minimum length + * + *****************************************************************************/ +inline length min_length(std::size_t min) +{ + return length{min, arg_string::npos-1}; +} + +/*************************************************************************//** + * + * @brief makes function object that returns true if the input string is + * not longer than a given maximum length + * + *****************************************************************************/ +inline length max_length(std::size_t max) +{ + return length{0, max}; +} + + +} // namespace match + + + + + +/*************************************************************************//** + * + * @brief command line parameter that can match one or many arguments. + * + *****************************************************************************/ +class parameter : + public detail::token, + public detail::action_provider +{ + /** @brief adapts a 'match_predicate' to the 'match_function' interface */ + class predicate_adapter { + public: + explicit + predicate_adapter(match_predicate pred): match_{std::move(pred)} {} + + subrange operator () (const arg_string& arg) const { + return match_(arg) ? subrange{0,arg.size()} : subrange{}; + } + + private: + match_predicate match_; + }; + +public: + //--------------------------------------------------------------- + /** @brief makes default parameter, that will match nothing */ + parameter(): + flags_{}, + matcher_{predicate_adapter{match::none}}, + label_{}, required_{false}, greedy_{false} + {} + + /** @brief makes "flag" parameter */ + template + explicit + parameter(arg_string str, Strings&&... strs): + flags_{}, + matcher_{predicate_adapter{match::none}}, + label_{}, required_{false}, greedy_{false} + { + add_flags(std::move(str), std::forward(strs)...); + } + + /** @brief makes "flag" parameter from range of strings */ + explicit + parameter(const arg_list& flaglist): + flags_{}, + matcher_{predicate_adapter{match::none}}, + label_{}, required_{false}, greedy_{false} + { + add_flags(flaglist); + } + + //----------------------------------------------------- + /** @brief makes "value" parameter with custom match predicate + * (= yes/no matcher) + */ + explicit + parameter(match_predicate filter): + flags_{}, + matcher_{predicate_adapter{std::move(filter)}}, + label_{}, required_{false}, greedy_{false} + {} + + /** @brief makes "value" parameter with custom match function + * (= partial matcher) + */ + explicit + parameter(match_function filter): + flags_{}, + matcher_{std::move(filter)}, + label_{}, required_{false}, greedy_{false} + {} + + + //--------------------------------------------------------------- + /** @brief returns if a parameter is required */ + bool + required() const noexcept { + return required_; + } + + /** @brief determines if a parameter is required */ + parameter& + required(bool yes) noexcept { + required_ = yes; + return *this; + } + + + //--------------------------------------------------------------- + /** @brief returns if a parameter should match greedily */ + bool + greedy() const noexcept { + return greedy_; + } + + /** @brief determines if a parameter should match greedily */ + parameter& + greedy(bool yes) noexcept { + greedy_ = yes; + return *this; + } + + + //--------------------------------------------------------------- + /** @brief returns parameter label; + * will be used for documentation, if flags are empty + */ + const doc_string& + label() const { + return label_; + } + + /** @brief sets parameter label; + * will be used for documentation, if flags are empty + */ + parameter& + label(const doc_string& lbl) { + label_ = lbl; + return *this; + } + + /** @brief sets parameter label; + * will be used for documentation, if flags are empty + */ + parameter& + label(doc_string&& lbl) { + label_ = lbl; + return *this; + } + + + //--------------------------------------------------------------- + /** @brief returns either longest matching prefix of 'arg' in any + * of the flags or the result of the custom match operation + */ + subrange + match(const arg_string& arg) const + { + if(flags_.empty()) { + return matcher_(arg); + } + else { + //empty flags are not allowed + if(arg.empty()) return subrange{}; + + if(std::find(flags_.begin(), flags_.end(), arg) != flags_.end()) { + return subrange{0,arg.size()}; + } + return str::longest_prefix_match(arg, flags_); + } + } + + + //--------------------------------------------------------------- + /** @brief access range of flag strings */ + const arg_list& + flags() const noexcept { + return flags_; + } + + /** @brief access custom match operation */ + const match_function& + matcher() const noexcept { + return matcher_; + } + + + //--------------------------------------------------------------- + /** @brief prepend prefix to each flag */ + inline friend parameter& + with_prefix(const arg_string& prefix, parameter& p) + { + if(prefix.empty() || p.flags().empty()) return p; + + for(auto& f : p.flags_) { + if(f.find(prefix) != 0) f.insert(0, prefix); + } + return p; + } + + + /** @brief prepend prefix to each flag + */ + inline friend parameter& + with_prefixes_short_long( + const arg_string& shortpfx, const arg_string& longpfx, + parameter& p) + { + if(shortpfx.empty() && longpfx.empty()) return p; + if(p.flags().empty()) return p; + + for(auto& f : p.flags_) { + if(f.size() == 1) { + if(f.find(shortpfx) != 0) f.insert(0, shortpfx); + } else { + if(f.find(longpfx) != 0) f.insert(0, longpfx); + } + } + return p; + } + + + //--------------------------------------------------------------- + /** @brief prepend suffix to each flag */ + inline friend parameter& + with_suffix(const arg_string& suffix, parameter& p) + { + if(suffix.empty() || p.flags().empty()) return p; + + for(auto& f : p.flags_) { + if(f.find(suffix) + suffix.size() != f.size()) { + f.insert(f.end(), suffix.begin(), suffix.end()); + } + } + return p; + } + + + /** @brief prepend suffix to each flag + */ + inline friend parameter& + with_suffixes_short_long( + const arg_string& shortsfx, const arg_string& longsfx, + parameter& p) + { + if(shortsfx.empty() && longsfx.empty()) return p; + if(p.flags().empty()) return p; + + for(auto& f : p.flags_) { + if(f.size() == 1) { + if(f.find(shortsfx) + shortsfx.size() != f.size()) { + f.insert(f.end(), shortsfx.begin(), shortsfx.end()); + } + } else { + if(f.find(longsfx) + longsfx.size() != f.size()) { + f.insert(f.end(), longsfx.begin(), longsfx.end()); + } + } + } + return p; + } + +private: + //--------------------------------------------------------------- + void add_flags(arg_string str) { + //empty flags are not allowed + str::remove_ws(str); + if(!str.empty()) flags_.push_back(std::move(str)); + } + + //--------------------------------------------------------------- + void add_flags(const arg_list& strs) { + if(strs.empty()) return; + flags_.reserve(flags_.size() + strs.size()); + for(const auto& s : strs) add_flags(s); + } + + template + void + add_flags(String1&& s1, String2&& s2, Strings&&... ss) { + flags_.reserve(2 + sizeof...(ss)); + add_flags(std::forward(s1)); + add_flags(std::forward(s2), std::forward(ss)...); + } + + arg_list flags_; + match_function matcher_; + doc_string label_; + bool required_ = false; + bool greedy_ = false; +}; + + + + +/*************************************************************************//** + * + * @brief makes required non-blocking exact match parameter + * + *****************************************************************************/ +template +inline parameter +command(String&& flag, Strings&&... flags) +{ + return parameter{std::forward(flag), std::forward(flags)...} + .required(true).blocking(true).repeatable(false); +} + + + +/*************************************************************************//** + * + * @brief makes required non-blocking exact match parameter + * + *****************************************************************************/ +template +inline parameter +required(String&& flag, Strings&&... flags) +{ + return parameter{std::forward(flag), std::forward(flags)...} + .required(true).blocking(false).repeatable(false); +} + + + +/*************************************************************************//** + * + * @brief makes optional, non-blocking exact match parameter + * + *****************************************************************************/ +template +inline parameter +option(String&& flag, Strings&&... flags) +{ + return parameter{std::forward(flag), std::forward(flags)...} + .required(false).blocking(false).repeatable(false); +} + + + +/*************************************************************************//** + * + * @brief makes required, blocking, repeatable value parameter; + * matches any non-empty string + * + *****************************************************************************/ +template +inline parameter +value(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::nonempty} + .label(label) + .target(std::forward(tgts)...) + .required(true).blocking(true).repeatable(false); +} + +template::value || + traits::is_callable::value>::type> +inline parameter +value(Filter&& filter, doc_string label, Targets&&... tgts) +{ + return parameter{std::forward(filter)} + .label(label) + .target(std::forward(tgts)...) + .required(true).blocking(true).repeatable(false); +} + + + +/*************************************************************************//** + * + * @brief makes required, blocking, repeatable value parameter; + * matches any non-empty string + * + *****************************************************************************/ +template +inline parameter +values(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::nonempty} + .label(label) + .target(std::forward(tgts)...) + .required(true).blocking(true).repeatable(true); +} + +template::value || + traits::is_callable::value>::type> +inline parameter +values(Filter&& filter, doc_string label, Targets&&... tgts) +{ + return parameter{std::forward(filter)} + .label(label) + .target(std::forward(tgts)...) + .required(true).blocking(true).repeatable(true); +} + + + +/*************************************************************************//** + * + * @brief makes optional, blocking value parameter; + * matches any non-empty string + * + *****************************************************************************/ +template +inline parameter +opt_value(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::nonempty} + .label(label) + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(false); +} + +template::value || + traits::is_callable::value>::type> +inline parameter +opt_value(Filter&& filter, doc_string label, Targets&&... tgts) +{ + return parameter{std::forward(filter)} + .label(label) + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(false); +} + + + +/*************************************************************************//** + * + * @brief makes optional, blocking, repeatable value parameter; + * matches any non-empty string + * + *****************************************************************************/ +template +inline parameter +opt_values(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::nonempty} + .label(label) + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(true); +} + +template::value || + traits::is_callable::value>::type> +inline parameter +opt_values(Filter&& filter, doc_string label, Targets&&... tgts) +{ + return parameter{std::forward(filter)} + .label(label) + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(true); +} + + + +/*************************************************************************//** + * + * @brief makes required, blocking value parameter; + * matches any string consisting of alphanumeric characters + * + *****************************************************************************/ +template +inline parameter +word(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::alphanumeric} + .label(label) + .target(std::forward(tgts)...) + .required(true).blocking(true).repeatable(false); +} + + + +/*************************************************************************//** + * + * @brief makes required, blocking, repeatable value parameter; + * matches any string consisting of alphanumeric characters + * + *****************************************************************************/ +template +inline parameter +words(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::alphanumeric} + .label(label) + .target(std::forward(tgts)...) + .required(true).blocking(true).repeatable(true); +} + + + +/*************************************************************************//** + * + * @brief makes optional, blocking value parameter; + * matches any string consisting of alphanumeric characters + * + *****************************************************************************/ +template +inline parameter +opt_word(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::alphanumeric} + .label(label) + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(false); +} + + + +/*************************************************************************//** + * + * @brief makes optional, blocking, repeatable value parameter; + * matches any string consisting of alphanumeric characters + * + *****************************************************************************/ +template +inline parameter +opt_words(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::alphanumeric} + .label(label) + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(true); +} + + + +/*************************************************************************//** + * + * @brief makes required, blocking value parameter; + * matches any string that represents a number + * + *****************************************************************************/ +template +inline parameter +number(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::numbers{}} + .label(label) + .target(std::forward(tgts)...) + .required(true).blocking(true).repeatable(false); +} + + + +/*************************************************************************//** + * + * @brief makes required, blocking, repeatable value parameter; + * matches any string that represents a number + * + *****************************************************************************/ +template +inline parameter +numbers(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::numbers{}} + .label(label) + .target(std::forward(tgts)...) + .required(true).blocking(true).repeatable(true); +} + + + +/*************************************************************************//** + * + * @brief makes optional, blocking value parameter; + * matches any string that represents a number + * + *****************************************************************************/ +template +inline parameter +opt_number(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::numbers{}} + .label(label) + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(false); +} + + + +/*************************************************************************//** + * + * @brief makes optional, blocking, repeatable value parameter; + * matches any string that represents a number + * + *****************************************************************************/ +template +inline parameter +opt_numbers(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::numbers{}} + .label(label) + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(true); +} + + + +/*************************************************************************//** + * + * @brief makes required, blocking value parameter; + * matches any string that represents an integer + * + *****************************************************************************/ +template +inline parameter +integer(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::integers{}} + .label(label) + .target(std::forward(tgts)...) + .required(true).blocking(true).repeatable(false); +} + + + +/*************************************************************************//** + * + * @brief makes required, blocking, repeatable value parameter; + * matches any string that represents an integer + * + *****************************************************************************/ +template +inline parameter +integers(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::integers{}} + .label(label) + .target(std::forward(tgts)...) + .required(true).blocking(true).repeatable(true); +} + + + +/*************************************************************************//** + * + * @brief makes optional, blocking value parameter; + * matches any string that represents an integer + * + *****************************************************************************/ +template +inline parameter +opt_integer(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::integers{}} + .label(label) + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(false); +} + + + +/*************************************************************************//** + * + * @brief makes optional, blocking, repeatable value parameter; + * matches any string that represents an integer + * + *****************************************************************************/ +template +inline parameter +opt_integers(const doc_string& label, Targets&&... tgts) +{ + return parameter{match::integers{}} + .label(label) + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(true); +} + + + +/*************************************************************************//** + * + * @brief makes catch-all value parameter + * + *****************************************************************************/ +template +inline parameter +any_other(Targets&&... tgts) +{ + return parameter{match::any} + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(true); +} + + + +/*************************************************************************//** + * + * @brief makes catch-all value parameter with custom filter + * + *****************************************************************************/ +template::value || + traits::is_callable::value>::type> +inline parameter +any(Filter&& filter, Targets&&... tgts) +{ + return parameter{std::forward(filter)} + .target(std::forward(tgts)...) + .required(false).blocking(false).repeatable(true); +} + + + + +/*************************************************************************//** + * + * @brief group of parameters and/or other groups; + * can be configured to act as a group of alternatives (exclusive match) + * + *****************************************************************************/ +class group : + public detail::token +{ + //--------------------------------------------------------------- + /** + * @brief tagged union type that either stores a parameter or a group + * and provides a common interface to them + * could be replaced by std::variant in the future + * + * Note to future self: do NOT try again to do this with + * dynamic polymorphism; there are a couple of + * nasty problems associated with it and the implementation + * becomes bloated and needlessly complicated. + */ + template + struct child_t { + enum class type : char {param, group}; + public: + + explicit + child_t(const Param& v) : m_{v}, type_{type::param} {} + child_t( Param&& v) noexcept : m_{std::move(v)}, type_{type::param} {} + + explicit + child_t(const Group& g) : m_{g}, type_{type::group} {} + child_t( Group&& g) noexcept : m_{std::move(g)}, type_{type::group} {} + + child_t(const child_t& src): type_{src.type_} { + switch(type_) { + default: + case type::param: new(&m_)data{src.m_.param}; break; + case type::group: new(&m_)data{src.m_.group}; break; + } + } + + child_t(child_t&& src) noexcept : type_{src.type_} { + switch(type_) { + default: + case type::param: new(&m_)data{std::move(src.m_.param)}; break; + case type::group: new(&m_)data{std::move(src.m_.group)}; break; + } + } + + child_t& operator = (const child_t& src) { + destroy_content(); + type_ = src.type_; + switch(type_) { + default: + case type::param: new(&m_)data{src.m_.param}; break; + case type::group: new(&m_)data{src.m_.group}; break; + } + return *this; + } + + child_t& operator = (child_t&& src) noexcept { + destroy_content(); + type_ = src.type_; + switch(type_) { + default: + case type::param: new(&m_)data{std::move(src.m_.param)}; break; + case type::group: new(&m_)data{std::move(src.m_.group)}; break; + } + return *this; + } + + ~child_t() { + destroy_content(); + } + + const doc_string& + doc() const noexcept { + switch(type_) { + default: + case type::param: return m_.param.doc(); + case type::group: return m_.group.doc(); + } + } + + bool blocking() const noexcept { + switch(type_) { + case type::param: return m_.param.blocking(); + case type::group: return m_.group.blocking(); + default: return false; + } + } + bool repeatable() const noexcept { + switch(type_) { + case type::param: return m_.param.repeatable(); + case type::group: return m_.group.repeatable(); + default: return false; + } + } + bool required() const noexcept { + switch(type_) { + case type::param: return m_.param.required(); + case type::group: + return (m_.group.exclusive() && m_.group.all_required() ) || + (!m_.group.exclusive() && m_.group.any_required() ); + default: return false; + } + } + bool exclusive() const noexcept { + switch(type_) { + case type::group: return m_.group.exclusive(); + case type::param: + default: return false; + } + } + std::size_t param_count() const noexcept { + switch(type_) { + case type::group: return m_.group.param_count(); + case type::param: + default: return std::size_t(1); + } + } + std::size_t depth() const noexcept { + switch(type_) { + case type::group: return m_.group.depth(); + case type::param: + default: return std::size_t(0); + } + } + + void execute_actions(const arg_string& arg) const { + switch(type_) { + default: + case type::group: return; + case type::param: m_.param.execute_actions(arg); break; + } + + } + + void notify_repeated(arg_index idx) const { + switch(type_) { + default: + case type::group: return; + case type::param: m_.param.notify_repeated(idx); break; + } + } + void notify_missing(arg_index idx) const { + switch(type_) { + default: + case type::group: return; + case type::param: m_.param.notify_missing(idx); break; + } + } + void notify_blocked(arg_index idx) const { + switch(type_) { + default: + case type::group: return; + case type::param: m_.param.notify_blocked(idx); break; + } + } + void notify_conflict(arg_index idx) const { + switch(type_) { + default: + case type::group: return; + case type::param: m_.param.notify_conflict(idx); break; + } + } + + bool is_param() const noexcept { return type_ == type::param; } + bool is_group() const noexcept { return type_ == type::group; } + + Param& as_param() noexcept { return m_.param; } + Group& as_group() noexcept { return m_.group; } + + const Param& as_param() const noexcept { return m_.param; } + const Group& as_group() const noexcept { return m_.group; } + + private: + void destroy_content() { + switch(type_) { + default: + case type::param: m_.param.~Param(); break; + case type::group: m_.group.~Group(); break; + } + } + + union data { + data() {} + + data(const Param& v) : param{v} {} + data( Param&& v) noexcept : param{std::move(v)} {} + + data(const Group& g) : group{g} {} + data( Group&& g) noexcept : group{std::move(g)} {} + ~data() {} + + Param param; + Group group; + }; + + data m_; + type type_; + }; + + +public: + //--------------------------------------------------------------- + using child = child_t; + using value_type = child; + +private: + using children_store = std::vector; + +public: + using const_iterator = children_store::const_iterator; + using iterator = children_store::iterator; + using size_type = children_store::size_type; + + + //--------------------------------------------------------------- + /** + * @brief recursively iterates over all nodes + */ + class depth_first_traverser + { + public: + //----------------------------------------------------- + struct context { + context() = default; + context(const group& p): + parent{&p}, cur{p.begin()}, end{p.end()} + {} + const group* parent = nullptr; + const_iterator cur; + const_iterator end; + }; + using context_list = std::vector; + + //----------------------------------------------------- + class memento { + friend class depth_first_traverser; + int level_; + context context_; + public: + int level() const noexcept { return level_; } + const child* param() const noexcept { return &(*context_.cur); } + }; + + depth_first_traverser() = default; + + explicit + depth_first_traverser(const group& cur): stack_{} { + if(!cur.empty()) stack_.emplace_back(cur); + } + + explicit operator bool() const noexcept { + return !stack_.empty(); + } + + int level() const noexcept { + return int(stack_.size()); + } + + bool is_first_in_parent() const noexcept { + if(stack_.empty()) return false; + return (stack_.back().cur == stack_.back().parent->begin()); + } + + bool is_last_in_parent() const noexcept { + if(stack_.empty()) return false; + return (stack_.back().cur+1 == stack_.back().end); + } + + bool is_last_in_path() const noexcept { + if(stack_.empty()) return false; + for(const auto& t : stack_) { + if(t.cur+1 != t.end) return false; + } + const auto& top = stack_.back(); + //if we have to descend into group on next ++ => not last in path + if(top.cur->is_group()) return false; + return true; + } + + /** @brief inside a group of alternatives >= minlevel */ + bool is_alternative(int minlevel = 0) const noexcept { + if(stack_.empty()) return false; + if(minlevel > 0) minlevel -= 1; + if(minlevel >= int(stack_.size())) return false; + return std::any_of(stack_.begin() + minlevel, stack_.end(), + [](const context& c) { return c.parent->exclusive(); }); + } + + /** @brief repeatable or inside a repeatable group >= minlevel */ + bool is_repeatable(int minlevel = 0) const noexcept { + if(stack_.empty()) return false; + if(stack_.back().cur->repeatable()) return true; + if(minlevel > 0) minlevel -= 1; + if(minlevel >= int(stack_.size())) return false; + return std::any_of(stack_.begin() + minlevel, stack_.end(), + [](const context& c) { return c.parent->repeatable(); }); + } + + /** @brief inside a particular group */ + bool is_inside(const group* g) const noexcept { + if(!g) return false; + return std::any_of(stack_.begin(), stack_.end(), + [g](const context& c) { return c.parent == g; }); + } + + /** @brief inside group with joinable flags */ + bool joinable() const noexcept { + if(stack_.empty()) return false; + return std::any_of(stack_.begin(), stack_.end(), + [](const context& c) { return c.parent->joinable(); }); + } + + const context_list& + stack() const { + return stack_; + } + + /** @brief innermost repeat group */ + const group* + innermost_repeat_group() const noexcept { + auto i = std::find_if(stack_.rbegin(), stack_.rend(), + [](const context& c) { return c.parent->repeatable(); }); + return i != stack_.rend() ? i->parent : nullptr; + } + + /** @brief innermost exclusive (alternatives) group */ + const group* + innermost_exclusive_group() const noexcept { + auto i = std::find_if(stack_.rbegin(), stack_.rend(), + [](const context& c) { return c.parent->exclusive(); }); + return i != stack_.rend() ? i->parent : nullptr; + } + + /** @brief innermost blocking group */ + const group* + innermost_blocking_group() const noexcept { + auto i = std::find_if(stack_.rbegin(), stack_.rend(), + [](const context& c) { return c.parent->blocking(); }); + return i != stack_.rend() ? i->parent : nullptr; + } + + /** @brief returns the outermost group that will be left on next ++*/ + const group* + outermost_blocking_group_fully_explored() const noexcept { + if(stack_.empty()) return nullptr; + + const group* g = nullptr; + for(auto i = stack_.rbegin(); i != stack_.rend(); ++i) { + if(i->cur+1 == i->end) { + if(i->parent->blocking()) g = i->parent; + } else { + return g; + } + } + return g; + } + + /** @brief outermost join group */ + const group* + outermost_join_group() const noexcept { + auto i = std::find_if(stack_.begin(), stack_.end(), + [](const context& c) { return c.parent->joinable(); }); + return i != stack_.end() ? i->parent : nullptr; + } + + const group* root() const noexcept { + return stack_.empty() ? nullptr : stack_.front().parent; + } + + /** @brief common flag prefix of all flags in current group */ + arg_string common_flag_prefix() const noexcept { + if(stack_.empty()) return ""; + auto g = outermost_join_group(); + return g ? g->common_flag_prefix() : arg_string(""); + } + + const child& + operator * () const noexcept { + return *stack_.back().cur; + } + + const child* + operator -> () const noexcept { + return &(*stack_.back().cur); + } + + const group& + parent() const noexcept { + return *(stack_.back().parent); + } + + + /** @brief go to next element of depth first search */ + depth_first_traverser& + operator ++ () { + if(stack_.empty()) return *this; + //at group -> decend into group + if(stack_.back().cur->is_group()) { + stack_.emplace_back(stack_.back().cur->as_group()); + } + else { + next_sibling(); + } + return *this; + } + + /** @brief go to next sibling of current */ + depth_first_traverser& + next_sibling() { + if(stack_.empty()) return *this; + ++stack_.back().cur; + //at the end of current group? + while(stack_.back().cur == stack_.back().end) { + //go to parent + stack_.pop_back(); + if(stack_.empty()) return *this; + //go to next sibling in parent + ++stack_.back().cur; + } + return *this; + } + + /** @brief go to next position after siblings of current */ + depth_first_traverser& + next_after_siblings() { + if(stack_.empty()) return *this; + stack_.back().cur = stack_.back().end-1; + next_sibling(); + return *this; + } + + /** + * @brief + */ + depth_first_traverser& + back_to_ancestor(const group* g) { + if(!g) return *this; + while(!stack_.empty()) { + const auto& top = stack_.back().cur; + if(top->is_group() && &(top->as_group()) == g) return *this; + stack_.pop_back(); + } + return *this; + } + + /** @brief don't visit next siblings, go back to parent on next ++ + * note: renders siblings unreachable for *this + **/ + depth_first_traverser& + skip_siblings() { + if(stack_.empty()) return *this; + //future increments won't visit subsequent siblings: + stack_.back().end = stack_.back().cur+1; + return *this; + } + + /** @brief skips all other alternatives in surrounding exclusive groups + * on next ++ + * note: renders alternatives unreachable for *this + */ + depth_first_traverser& + skip_alternatives() { + if(stack_.empty()) return *this; + + //exclude all other alternatives in surrounding groups + //by making their current position the last one + for(auto& c : stack_) { + if(c.parent && c.parent->exclusive() && c.cur < c.end) + c.end = c.cur+1; + } + + return *this; + } + + void invalidate() { + stack_.clear(); + } + + inline friend bool operator == (const depth_first_traverser& a, + const depth_first_traverser& b) + { + if(a.stack_.empty() || b.stack_.empty()) return false; + + //parents not the same -> different position + if(a.stack_.back().parent != b.stack_.back().parent) return false; + + bool aEnd = a.stack_.back().cur == a.stack_.back().end; + bool bEnd = b.stack_.back().cur == b.stack_.back().end; + //either both at the end of the same parent => same position + if(aEnd && bEnd) return true; + //or only one at the end => not at the same position + if(aEnd || bEnd) return false; + return std::addressof(*a.stack_.back().cur) == + std::addressof(*b.stack_.back().cur); + } + inline friend bool operator != (const depth_first_traverser& a, + const depth_first_traverser& b) + { + return !(a == b); + } + + memento + undo_point() const { + memento m; + m.level_ = int(stack_.size()); + if(!stack_.empty()) m.context_ = stack_.back(); + return m; + } + + void undo(const memento& m) { + if(m.level_ < 1) return; + if(m.level_ <= int(stack_.size())) { + stack_.erase(stack_.begin() + m.level_, stack_.end()); + stack_.back() = m.context_; + } + else if(stack_.empty() && m.level_ == 1) { + stack_.push_back(m.context_); + } + } + + private: + context_list stack_; + }; + + + //--------------------------------------------------------------- + group() = default; + + template + explicit + group(doc_string docstr, Param param, Params... params): + children_{}, exclusive_{false}, joinable_{false}, scoped_{true} + { + doc(std::move(docstr)); + push_back(std::move(param), std::move(params)...); + } + + template + explicit + group(parameter param, Params... params): + children_{}, exclusive_{false}, joinable_{false}, scoped_{true} + { + push_back(std::move(param), std::move(params)...); + } + + template + explicit + group(group p1, P2 p2, Ps... ps): + children_{}, exclusive_{false}, joinable_{false}, scoped_{true} + { + push_back(std::move(p1), std::move(p2), std::move(ps)...); + } + + + //----------------------------------------------------- + group(const group&) = default; + group(group&&) = default; + + + //--------------------------------------------------------------- + group& operator = (const group&) = default; + group& operator = (group&&) = default; + + + //--------------------------------------------------------------- + /** @brief determines if a command line argument can be matched by a + * combination of (partial) matches through any number of children + */ + group& joinable(bool yes) { + joinable_ = yes; + return *this; + } + + /** @brief returns if a command line argument can be matched by a + * combination of (partial) matches through any number of children + */ + bool joinable() const noexcept { + return joinable_; + } + + + //--------------------------------------------------------------- + /** @brief turns explicit scoping on or off + * operators , & | and other combinating functions will + * not merge groups that are marked as scoped + */ + group& scoped(bool yes) { + scoped_ = yes; + return *this; + } + + /** @brief returns true if operators , & | and other combinating functions + * will merge groups and false otherwise + */ + bool scoped() const noexcept + { + return scoped_; + } + + + //--------------------------------------------------------------- + /** @brief determines if children are mutually exclusive alternatives */ + group& exclusive(bool yes) { + exclusive_ = yes; + return *this; + } + /** @brief returns if children are mutually exclusive alternatives */ + bool exclusive() const noexcept { + return exclusive_; + } + + + //--------------------------------------------------------------- + /** @brief returns true, if any child is required to match */ + bool any_required() const + { + return std::any_of(children_.begin(), children_.end(), + [](const child& n){ return n.required(); }); + } + /** @brief returns true, if all children are required to match */ + bool all_required() const + { + return std::all_of(children_.begin(), children_.end(), + [](const child& n){ return n.required(); }); + } + + + //--------------------------------------------------------------- + /** @brief returns true if any child is optional (=non-required) */ + bool any_optional() const { + return !all_required(); + } + /** @brief returns true if all children are optional (=non-required) */ + bool all_optional() const { + return !any_required(); + } + + + //--------------------------------------------------------------- + /** @brief returns if the entire group is blocking / positional */ + bool blocking() const noexcept { + return token::blocking() || (exclusive() && all_blocking()); + } + //----------------------------------------------------- + /** @brief determines if the entire group is blocking / positional */ + group& blocking(bool yes) { + return token::blocking(yes); + } + + //--------------------------------------------------------------- + /** @brief returns true if any child is blocking */ + bool any_blocking() const + { + return std::any_of(children_.begin(), children_.end(), + [](const child& n){ return n.blocking(); }); + } + //--------------------------------------------------------------- + /** @brief returns true if all children is blocking */ + bool all_blocking() const + { + return std::all_of(children_.begin(), children_.end(), + [](const child& n){ return n.blocking(); }); + } + + + //--------------------------------------------------------------- + /** @brief returns if any child is a value parameter (recursive) */ + bool any_flagless() const + { + return std::any_of(children_.begin(), children_.end(), + [](const child& p){ + return p.is_param() && p.as_param().flags().empty(); + }); + } + /** @brief returns if all children are value parameters (recursive) */ + bool all_flagless() const + { + return std::all_of(children_.begin(), children_.end(), + [](const child& p){ + return p.is_param() && p.as_param().flags().empty(); + }); + } + + + //--------------------------------------------------------------- + /** @brief adds child parameter at the end */ + group& + push_back(const parameter& v) { + children_.emplace_back(v); + return *this; + } + //----------------------------------------------------- + /** @brief adds child parameter at the end */ + group& + push_back(parameter&& v) { + children_.emplace_back(std::move(v)); + return *this; + } + //----------------------------------------------------- + /** @brief adds child group at the end */ + group& + push_back(const group& g) { + children_.emplace_back(g); + return *this; + } + //----------------------------------------------------- + /** @brief adds child group at the end */ + group& + push_back(group&& g) { + children_.emplace_back(std::move(g)); + return *this; + } + + + //----------------------------------------------------- + /** @brief adds children (groups and/or parameters) */ + template + group& + push_back(Param1&& param1, Param2&& param2, Params&&... params) + { + children_.reserve(children_.size() + 2 + sizeof...(params)); + push_back(std::forward(param1)); + push_back(std::forward(param2), std::forward(params)...); + return *this; + } + + + //--------------------------------------------------------------- + /** @brief adds child parameter at the beginning */ + group& + push_front(const parameter& v) { + children_.emplace(children_.begin(), v); + return *this; + } + //----------------------------------------------------- + /** @brief adds child parameter at the beginning */ + group& + push_front(parameter&& v) { + children_.emplace(children_.begin(), std::move(v)); + return *this; + } + //----------------------------------------------------- + /** @brief adds child group at the beginning */ + group& + push_front(const group& g) { + children_.emplace(children_.begin(), g); + return *this; + } + //----------------------------------------------------- + /** @brief adds child group at the beginning */ + group& + push_front(group&& g) { + children_.emplace(children_.begin(), std::move(g)); + return *this; + } + + + //--------------------------------------------------------------- + /** @brief adds all children of other group at the end */ + group& + merge(group&& g) + { + children_.insert(children_.end(), + std::make_move_iterator(g.begin()), + std::make_move_iterator(g.end())); + return *this; + } + //----------------------------------------------------- + /** @brief adds all children of several other groups at the end */ + template + group& + merge(group&& g1, group&& g2, Groups&&... gs) + { + merge(std::move(g1)); + merge(std::move(g2), std::forward(gs)...); + return *this; + } + + + //--------------------------------------------------------------- + /** @brief indexed, nutable access to child */ + child& operator [] (size_type index) noexcept { + return children_[index]; + } + /** @brief indexed, non-nutable access to child */ + const child& operator [] (size_type index) const noexcept { + return children_[index]; + } + + //--------------------------------------------------------------- + /** @brief mutable access to first child */ + child& front() noexcept { return children_.front(); } + /** @brief non-mutable access to first child */ + const child& front() const noexcept { return children_.front(); } + //----------------------------------------------------- + /** @brief mutable access to last child */ + child& back() noexcept { return children_.back(); } + /** @brief non-mutable access to last child */ + const child& back() const noexcept { return children_.back(); } + + + //--------------------------------------------------------------- + /** @brief returns true, if group has no children, false otherwise */ + bool empty() const noexcept { return children_.empty(); } + + /** @brief returns number of children */ + size_type size() const noexcept { return children_.size(); } + + /** @brief returns number of nested levels; 1 for a flat group */ + size_type depth() const { + size_type n = 0; + for(const auto& c : children_) { + auto l = 1 + c.depth(); + if(l > n) n = l; + } + return n; + } + + + //--------------------------------------------------------------- + /** @brief returns mutating iterator to position of first element */ + iterator begin() noexcept { return children_.begin(); } + /** @brief returns non-mutating iterator to position of first element */ + const_iterator begin() const noexcept { return children_.begin(); } + /** @brief returns non-mutating iterator to position of first element */ + const_iterator cbegin() const noexcept { return children_.begin(); } + + /** @brief returns mutating iterator to position one past the last element */ + iterator end() noexcept { return children_.end(); } + /** @brief returns non-mutating iterator to position one past the last element */ + const_iterator end() const noexcept { return children_.end(); } + /** @brief returns non-mutating iterator to position one past the last element */ + const_iterator cend() const noexcept { return children_.end(); } + + + //--------------------------------------------------------------- + /** @brief returns augmented iterator for depth first searches + * @details traverser knows end of iteration and can skip over children + */ + depth_first_traverser + begin_dfs() const noexcept { + return depth_first_traverser{*this}; + } + + + //--------------------------------------------------------------- + /** @brief returns recursive parameter count */ + size_type param_count() const { + size_type c = 0; + for(const auto& n : children_) { + c += n.param_count(); + } + return c; + } + + + //--------------------------------------------------------------- + /** @brief returns range of all flags (recursive) */ + arg_list all_flags() const + { + std::vector all; + gather_flags(children_, all); + return all; + } + + /** @brief returns true, if no flag occurs as true + * prefix of any other flag (identical flags will be ignored) */ + bool flags_are_prefix_free() const + { + const auto fs = all_flags(); + + using std::begin; using std::end; + for(auto i = begin(fs), e = end(fs); i != e; ++i) { + if(!i->empty()) { + for(auto j = i+1; j != e; ++j) { + if(!j->empty() && *i != *j) { + if(i->find(*j) == 0) return false; + if(j->find(*i) == 0) return false; + } + } + } + } + + return true; + } + + + //--------------------------------------------------------------- + /** @brief returns longest common prefix of all flags */ + arg_string common_flag_prefix() const + { + arg_list prefixes; + gather_prefixes(children_, prefixes); + return str::longest_common_prefix(prefixes); + } + + +private: + //--------------------------------------------------------------- + static void + gather_flags(const children_store& nodes, arg_list& all) + { + for(const auto& p : nodes) { + if(p.is_group()) { + gather_flags(p.as_group().children_, all); + } + else { + const auto& pf = p.as_param().flags(); + using std::begin; + using std::end; + if(!pf.empty()) all.insert(end(all), begin(pf), end(pf)); + } + } + } + //--------------------------------------------------------------- + static void + gather_prefixes(const children_store& nodes, arg_list& all) + { + for(const auto& p : nodes) { + if(p.is_group()) { + gather_prefixes(p.as_group().children_, all); + } + else if(!p.as_param().flags().empty()) { + auto pfx = str::longest_common_prefix(p.as_param().flags()); + if(!pfx.empty()) all.push_back(std::move(pfx)); + } + } + } + + //--------------------------------------------------------------- + children_store children_; + bool exclusive_ = false; + bool joinable_ = false; + bool scoped_ = false; +}; + + + +/*************************************************************************//** + * + * @brief group or parameter + * + *****************************************************************************/ +using pattern = group::child; + + + +/*************************************************************************//** + * + * @brief apply an action to all parameters in a group + * + *****************************************************************************/ +template +void for_all_params(group& g, Action&& action) +{ + for(auto& p : g) { + if(p.is_group()) { + for_all_params(p.as_group(), action); + } + else { + action(p.as_param()); + } + } +} + +template +void for_all_params(const group& g, Action&& action) +{ + for(auto& p : g) { + if(p.is_group()) { + for_all_params(p.as_group(), action); + } + else { + action(p.as_param()); + } + } +} + + + +/*************************************************************************//** + * + * @brief makes a group of parameters and/or groups + * + *****************************************************************************/ +inline group +operator , (parameter a, parameter b) +{ + return group{std::move(a), std::move(b)}.scoped(false); +} + +//--------------------------------------------------------- +inline group +operator , (parameter a, group b) +{ + return !b.scoped() && !b.blocking() && !b.exclusive() && !b.repeatable() + && !b.joinable() && (b.doc().empty() || b.doc() == a.doc()) + ? b.push_front(std::move(a)) + : group{std::move(a), std::move(b)}.scoped(false); +} + +//--------------------------------------------------------- +inline group +operator , (group a, parameter b) +{ + return !a.scoped() && !a.blocking() && !a.exclusive() && !a.repeatable() + && !a.joinable() && (a.doc().empty() || a.doc() == b.doc()) + ? a.push_back(std::move(b)) + : group{std::move(a), std::move(b)}.scoped(false); +} + +//--------------------------------------------------------- +inline group +operator , (group a, group b) +{ + return !a.scoped() && !a.blocking() && !a.exclusive() && !a.repeatable() + && !a.joinable() && (a.doc().empty() || a.doc() == b.doc()) + ? a.push_back(std::move(b)) + : group{std::move(a), std::move(b)}.scoped(false); +} + + + +/*************************************************************************//** + * + * @brief makes a group of alternative parameters or groups + * + *****************************************************************************/ +template +inline group +one_of(Param param, Params... params) +{ + return group{std::move(param), std::move(params)...}.exclusive(true); +} + + +/*************************************************************************//** + * + * @brief makes a group of alternative parameters or groups + * + *****************************************************************************/ +inline group +operator | (parameter a, parameter b) +{ + return group{std::move(a), std::move(b)}.scoped(false).exclusive(true); +} + +//------------------------------------------------------------------- +inline group +operator | (parameter a, group b) +{ + return !b.scoped() && !b.blocking() && b.exclusive() && !b.repeatable() + && !b.joinable() + && (b.doc().empty() || b.doc() == a.doc()) + ? b.push_front(std::move(a)) + : group{std::move(a), std::move(b)}.scoped(false).exclusive(true); +} + +//------------------------------------------------------------------- +inline group +operator | (group a, parameter b) +{ + return !a.scoped() && a.exclusive() && !a.repeatable() && !a.joinable() + && a.blocking() == b.blocking() + && (a.doc().empty() || a.doc() == b.doc()) + ? a.push_back(std::move(b)) + : group{std::move(a), std::move(b)}.scoped(false).exclusive(true); +} + +inline group +operator | (group a, group b) +{ + return !a.scoped() && a.exclusive() &&!a.repeatable() && !a.joinable() + && a.blocking() == b.blocking() + && (a.doc().empty() || a.doc() == b.doc()) + ? a.push_back(std::move(b)) + : group{std::move(a), std::move(b)}.scoped(false).exclusive(true); +} + + + +/*************************************************************************//** + * + * @brief helpers (NOT FOR DIRECT USE IN CLIENT CODE!) + * no interface guarantees; might be changed or removed in the future + * + *****************************************************************************/ +namespace detail { + +inline void set_blocking(bool) {} + +template +void set_blocking(bool yes, P& p, Ps&... ps) { + p.blocking(yes); + set_blocking(yes, ps...); +} + +} // namespace detail + + +/*************************************************************************//** + * + * @brief makes a parameter/group sequence by making all input objects blocking + * + *****************************************************************************/ +template +inline group +in_sequence(Param param, Params... params) +{ + detail::set_blocking(true, param, params...); + return group{std::move(param), std::move(params)...}.scoped(true); +} + + +/*************************************************************************//** + * + * @brief makes a parameter/group sequence by making all input objects blocking + * + *****************************************************************************/ +inline group +operator & (parameter a, parameter b) +{ + a.blocking(true); + b.blocking(true); + return group{std::move(a), std::move(b)}.scoped(true); +} + +//--------------------------------------------------------- +inline group +operator & (parameter a, group b) +{ + a.blocking(true); + return group{std::move(a), std::move(b)}.scoped(true); +} + +//--------------------------------------------------------- +inline group +operator & (group a, parameter b) +{ + b.blocking(true); + if(a.all_blocking() && !a.exclusive() && !a.repeatable() && !a.joinable() + && (a.doc().empty() || a.doc() == b.doc())) + { + return a.push_back(std::move(b)); + } + else { + if(!a.all_blocking()) a.blocking(true); + return group{std::move(a), std::move(b)}.scoped(true); + } +} + +inline group +operator & (group a, group b) +{ + if(!b.all_blocking()) b.blocking(true); + if(a.all_blocking() && !a.exclusive() && !a.repeatable() + && !a.joinable() && (a.doc().empty() || a.doc() == b.doc())) + { + return a.push_back(std::move(b)); + } + else { + if(!a.all_blocking()) a.blocking(true); + return group{std::move(a), std::move(b)}.scoped(true); + } +} + + + +/*************************************************************************//** + * + * @brief makes a group of parameters and/or groups + * where all single char flag params ("-a", "b", ...) are joinable + * + *****************************************************************************/ +inline group +joinable(group g) { + return g.joinable(true); +} + +//------------------------------------------------------------------- +template +inline group +joinable(parameter param, Params... params) +{ + return group{std::move(param), std::move(params)...}.joinable(true); +} + +template +inline group +joinable(group p1, P2 p2, Ps... ps) +{ + return group{std::move(p1), std::move(p2), std::move(ps)...}.joinable(true); +} + +template +inline group +joinable(doc_string docstr, Param param, Params... params) +{ + return group{std::move(param), std::move(params)...} + .joinable(true).doc(std::move(docstr)); +} + + + +/*************************************************************************//** + * + * @brief makes a repeatable copy of a parameter + * + *****************************************************************************/ +inline parameter +repeatable(parameter p) { + return p.repeatable(true); +} + +/*************************************************************************//** + * + * @brief makes a repeatable copy of a group + * + *****************************************************************************/ +inline group +repeatable(group g) { + return g.repeatable(true); +} + + + +/*************************************************************************//** + * + * @brief makes a group of parameters and/or groups + * that is repeatable as a whole + * Note that a repeatable group consisting entirely of non-blocking + * children is equivalent to a non-repeatable group of + * repeatable children. + * + *****************************************************************************/ +template +inline group +repeatable(parameter p1, P2 p2, Ps... ps) +{ + return group{std::move(p1), std::move(p2), + std::move(ps)...}.repeatable(true); +} + +template +inline group +repeatable(group p1, P2 p2, Ps... ps) +{ + return group{std::move(p1), std::move(p2), + std::move(ps)...}.repeatable(true); +} + + + +/*************************************************************************//** + * + * @brief makes a parameter greedy (match with top priority) + * + *****************************************************************************/ +inline parameter +greedy(parameter p) { + return p.greedy(true); +} + +inline parameter +operator ! (parameter p) { + return greedy(p); +} + + + +/*************************************************************************//** + * + * @brief recursively prepends a prefix to all flags + * + *****************************************************************************/ +inline parameter&& +with_prefix(const arg_string& prefix, parameter&& p) { + return std::move(with_prefix(prefix, p)); +} + + +//------------------------------------------------------------------- +inline group& +with_prefix(const arg_string& prefix, group& g) +{ + for(auto& p : g) { + if(p.is_group()) { + with_prefix(prefix, p.as_group()); + } else { + with_prefix(prefix, p.as_param()); + } + } + return g; +} + + +inline group&& +with_prefix(const arg_string& prefix, group&& params) +{ + return std::move(with_prefix(prefix, params)); +} + + +template +inline group +with_prefix(arg_string prefix, Param&& param, Params&&... params) +{ + return with_prefix(prefix, group{std::forward(param), + std::forward(params)...}); +} + + + +/*************************************************************************//** + * + * @brief recursively prepends a prefix to all flags + * + * @param shortpfx : used for single-letter flags + * @param longpfx : used for flags with length > 1 + * + *****************************************************************************/ +inline parameter&& +with_prefixes_short_long(const arg_string& shortpfx, const arg_string& longpfx, + parameter&& p) +{ + return std::move(with_prefixes_short_long(shortpfx, longpfx, p)); +} + + +//------------------------------------------------------------------- +inline group& +with_prefixes_short_long(const arg_string& shortFlagPrefix, + const arg_string& longFlagPrefix, + group& g) +{ + for(auto& p : g) { + if(p.is_group()) { + with_prefixes_short_long(shortFlagPrefix, longFlagPrefix, p.as_group()); + } else { + with_prefixes_short_long(shortFlagPrefix, longFlagPrefix, p.as_param()); + } + } + return g; +} + + +inline group&& +with_prefixes_short_long(const arg_string& shortFlagPrefix, + const arg_string& longFlagPrefix, + group&& params) +{ + return std::move(with_prefixes_short_long(shortFlagPrefix, longFlagPrefix, + params)); +} + + +template +inline group +with_prefixes_short_long(const arg_string& shortFlagPrefix, + const arg_string& longFlagPrefix, + Param&& param, Params&&... params) +{ + return with_prefixes_short_long(shortFlagPrefix, longFlagPrefix, + group{std::forward(param), + std::forward(params)...}); +} + + + +/*************************************************************************//** + * + * @brief recursively prepends a suffix to all flags + * + *****************************************************************************/ +inline parameter&& +with_suffix(const arg_string& suffix, parameter&& p) { + return std::move(with_suffix(suffix, p)); +} + + +//------------------------------------------------------------------- +inline group& +with_suffix(const arg_string& suffix, group& g) +{ + for(auto& p : g) { + if(p.is_group()) { + with_suffix(suffix, p.as_group()); + } else { + with_suffix(suffix, p.as_param()); + } + } + return g; +} + + +inline group&& +with_suffix(const arg_string& suffix, group&& params) +{ + return std::move(with_suffix(suffix, params)); +} + + +template +inline group +with_suffix(arg_string suffix, Param&& param, Params&&... params) +{ + return with_suffix(suffix, group{std::forward(param), + std::forward(params)...}); +} + + + +/*************************************************************************//** + * + * @brief recursively prepends a suffix to all flags + * + * @param shortsfx : used for single-letter flags + * @param longsfx : used for flags with length > 1 + * + *****************************************************************************/ +inline parameter&& +with_suffixes_short_long(const arg_string& shortsfx, const arg_string& longsfx, + parameter&& p) +{ + return std::move(with_suffixes_short_long(shortsfx, longsfx, p)); +} + + +//------------------------------------------------------------------- +inline group& +with_suffixes_short_long(const arg_string& shortFlagSuffix, + const arg_string& longFlagSuffix, + group& g) +{ + for(auto& p : g) { + if(p.is_group()) { + with_suffixes_short_long(shortFlagSuffix, longFlagSuffix, p.as_group()); + } else { + with_suffixes_short_long(shortFlagSuffix, longFlagSuffix, p.as_param()); + } + } + return g; +} + + +inline group&& +with_suffixes_short_long(const arg_string& shortFlagSuffix, + const arg_string& longFlagSuffix, + group&& params) +{ + return std::move(with_suffixes_short_long(shortFlagSuffix, longFlagSuffix, + params)); +} + + +template +inline group +with_suffixes_short_long(const arg_string& shortFlagSuffix, + const arg_string& longFlagSuffix, + Param&& param, Params&&... params) +{ + return with_suffixes_short_long(shortFlagSuffix, longFlagSuffix, + group{std::forward(param), + std::forward(params)...}); +} + + + + + + + + +/*************************************************************************//** + * + * @brief parsing implementation details + * + *****************************************************************************/ + +namespace detail { + + +/*************************************************************************//** + * + * @brief DFS traverser that keeps track of 'scopes' + * scope = all parameters that are either bounded by + * two blocking parameters on the same depth level + * or the beginning/end of the outermost group + * + *****************************************************************************/ +class scoped_dfs_traverser +{ +public: + using dfs_traverser = group::depth_first_traverser; + + scoped_dfs_traverser() = default; + + explicit + scoped_dfs_traverser(const group& g): + pos_{g}, lastMatch_{}, posAfterLastMatch_{}, scopes_{}, + ignoreBlocks_{false}, + repeatGroupStarted_{false}, repeatGroupContinues_{false} + {} + + const dfs_traverser& base() const noexcept { return pos_; } + const dfs_traverser& last_match() const noexcept { return lastMatch_; } + + const group& parent() const noexcept { return pos_.parent(); } + + const group* innermost_repeat_group() const noexcept { + return pos_.innermost_repeat_group(); + } + const group* outermost_join_group() const noexcept { + return pos_.outermost_join_group(); + } + const group* innermost_blocking_group() const noexcept { + return pos_.innermost_blocking_group(); + } + const group* innermost_exclusive_group() const noexcept { + return pos_.innermost_exclusive_group(); + } + + const pattern* operator ->() const noexcept { return pos_.operator->(); } + const pattern& operator *() const noexcept { return *pos_; } + + const pattern* ptr() const noexcept { return pos_.operator->(); } + + explicit operator bool() const noexcept { return bool(pos_); } + + bool joinable() const noexcept { return pos_.joinable(); } + arg_string common_flag_prefix() const { return pos_.common_flag_prefix(); } + + void ignore_blocking(bool yes) { ignoreBlocks_ = yes; } + + void invalidate() { + pos_.invalidate(); + } + + bool matched() const noexcept { + return (pos_ == lastMatch_); + } + + bool start_of_repeat_group() const noexcept { return repeatGroupStarted_; } + + //----------------------------------------------------- + scoped_dfs_traverser& + next_sibling() { pos_.next_sibling(); return *this; } + + scoped_dfs_traverser& + next_after_siblings() { pos_.next_after_siblings(); return *this; } + + + //----------------------------------------------------- + scoped_dfs_traverser& + operator ++ () + { + if(!pos_) return *this; + + if(pos_.is_last_in_path()) { + return_to_outermost_scope(); + return *this; + } + + //current pattern can block if it didn't match already + if(ignoreBlocks_ || matched()) { + ++pos_; + } + else if(!pos_->is_group()) { + //current group can block if we didn't have any match in it + const group* g = pos_.outermost_blocking_group_fully_explored(); + //no match in 'g' before -> skip to after its siblings + if(g && !lastMatch_.is_inside(g)) { + pos_.back_to_ancestor(g).next_after_siblings(); + if(!pos_) return_to_outermost_scope(); + } + else if(pos_->blocking()) { + if(pos_.parent().exclusive()) { + pos_.next_sibling(); + } else { + //no match => skip siblings of blocking param + pos_.next_after_siblings(); + } + if(!pos_) return_to_outermost_scope(); + } else { + ++pos_; + } + } else { + ++pos_; + } + check_if_left_scope(); + return *this; + } + + //----------------------------------------------------- + void next_after_match(scoped_dfs_traverser match) + { + if(!match || ignoreBlocks_) return; + + check_repeat_group_start(match); + + lastMatch_ = match.base(); + + // if there is a blocking ancestor -> go back to it + if(!match->blocking()) { + match.pos_.back_to_ancestor(match.innermost_blocking_group()); + } + + //if match is not in current position & current position is blocking + //=> current position has to be advanced by one so that it is + //no longer reachable within current scope + //(can happen for repeatable, blocking parameters) + if(match.base() != pos_ && pos_->blocking()) pos_.next_sibling(); + + if(match->blocking()) { + if(match.pos_.is_alternative()) { + //discard other alternatives + match.pos_.skip_alternatives(); + } + + if(is_last_in_current_scope(match.pos_)) { + //if current param is not repeatable -> back to previous scope + if(!match->repeatable() && !match->is_group()) { + pos_ = std::move(match.pos_); + if(!scopes_.empty()) pos_.undo(scopes_.top()); + } + else { //stay at match position + pos_ = std::move(match.pos_); + } + } + else { //not last in current group + //if current param is not repeatable, go directly to next + if(!match->repeatable() && !match->is_group()) { + ++match.pos_; + } + + if(match.pos_.level() > pos_.level()) { + scopes_.push(pos_.undo_point()); + pos_ = std::move(match.pos_); + } + else if(match.pos_.level() < pos_.level()) { + return_to_level(match.pos_.level()); + } + else { + pos_ = std::move(match.pos_); + } + } + posAfterLastMatch_ = pos_; + } + else { + if(match.pos_.level() < pos_.level()) { + return_to_level(match.pos_.level()); + } + posAfterLastMatch_ = pos_; + } + repeatGroupContinues_ = repeat_group_continues(); + } + +private: + //----------------------------------------------------- + bool is_last_in_current_scope(const dfs_traverser& pos) const + { + if(scopes_.empty()) return pos.is_last_in_path(); + //check if we would leave the current scope on ++ + auto p = pos; + ++p; + return p.level() < scopes_.top().level(); + } + + //----------------------------------------------------- + void check_repeat_group_start(const scoped_dfs_traverser& newMatch) + { + const auto newrg = newMatch.innermost_repeat_group(); + if(!newrg) { + repeatGroupStarted_ = false; + } + else if(lastMatch_.innermost_repeat_group() != newrg) { + repeatGroupStarted_ = true; + } + else if(!repeatGroupContinues_ || !newMatch.repeatGroupContinues_) { + repeatGroupStarted_ = true; + } + else { + //special case: repeat group is outermost group + //=> we can never really 'leave' and 'reenter' it + //but if the current scope is the first element, then we are + //conceptually at a position 'before' the group + repeatGroupStarted_ = scopes_.empty() || ( + newrg == pos_.root() && + scopes_.top().param() == &(*pos_.root()->begin()) ); + } + repeatGroupContinues_ = repeatGroupStarted_; + } + + //----------------------------------------------------- + bool repeat_group_continues() const + { + if(!repeatGroupContinues_) return false; + const auto curRepGroup = pos_.innermost_repeat_group(); + if(!curRepGroup) return false; + if(curRepGroup != lastMatch_.innermost_repeat_group()) return false; + if(!posAfterLastMatch_) return false; + return true; + } + + //----------------------------------------------------- + void check_if_left_scope() + { + if(posAfterLastMatch_) { + if(pos_.level() < posAfterLastMatch_.level()) { + while(!scopes_.empty() && scopes_.top().level() >= pos_.level()) { + pos_.undo(scopes_.top()); + scopes_.pop(); + } + posAfterLastMatch_.invalidate(); + } + } + while(!scopes_.empty() && scopes_.top().level() > pos_.level()) { + pos_.undo(scopes_.top()); + scopes_.pop(); + } + repeatGroupContinues_ = repeat_group_continues(); + } + + //----------------------------------------------------- + void return_to_outermost_scope() + { + posAfterLastMatch_.invalidate(); + + if(scopes_.empty()) { + pos_.invalidate(); + repeatGroupContinues_ = false; + return; + } + + while(!scopes_.empty() && (!pos_ || pos_.level() >= 1)) { + pos_.undo(scopes_.top()); + scopes_.pop(); + } + while(!scopes_.empty()) scopes_.pop(); + + repeatGroupContinues_ = repeat_group_continues(); + } + + //----------------------------------------------------- + void return_to_level(int level) + { + if(pos_.level() <= level) return; + while(!scopes_.empty() && pos_.level() > level) { + pos_.undo(scopes_.top()); + scopes_.pop(); + } + }; + + dfs_traverser pos_; + dfs_traverser lastMatch_; + dfs_traverser posAfterLastMatch_; + std::stack scopes_; + bool ignoreBlocks_ = false; + bool repeatGroupStarted_ = false; + bool repeatGroupContinues_ = false; +}; + + + + +/***************************************************************************** + * + * some parameter property predicates + * + *****************************************************************************/ +struct select_all { + bool operator () (const parameter&) const noexcept { return true; } +}; + +struct select_flags { + bool operator () (const parameter& p) const noexcept { + return !p.flags().empty(); + } +}; + +struct select_values { + bool operator () (const parameter& p) const noexcept { + return p.flags().empty(); + } +}; + + + +/*************************************************************************//** + * + * @brief result of a matching operation + * + *****************************************************************************/ +class match_t { +public: + using size_type = arg_string::size_type; + + match_t() = default; + + match_t(arg_string s, scoped_dfs_traverser p): + str_{std::move(s)}, pos_{std::move(p)} + {} + + size_type length() const noexcept { return str_.size(); } + + const arg_string& str() const noexcept { return str_; } + const scoped_dfs_traverser& pos() const noexcept { return pos_; } + + explicit operator bool() const noexcept { return bool(pos_); } + +private: + arg_string str_; + scoped_dfs_traverser pos_; +}; + + + +/*************************************************************************//** + * + * @brief finds the first parameter that matches a given string; + * candidate parameters are traversed using a scoped DFS traverser + * + *****************************************************************************/ +template +match_t +full_match(scoped_dfs_traverser pos, const arg_string& arg, + const ParamSelector& select) +{ + while(pos) { + if(pos->is_param()) { + const auto& param = pos->as_param(); + if(select(param)) { + const auto match = param.match(arg); + if(match && match.length() == arg.size()) { + return match_t{arg, std::move(pos)}; + } + } + } + ++pos; + } + return match_t{}; +} + + + +/*************************************************************************//** + * + * @brief finds the first parameter that matches any (non-empty) prefix + * of a given string; + * candidate parameters are traversed using a scoped DFS traverser + * + *****************************************************************************/ +template +match_t +longest_prefix_match(scoped_dfs_traverser pos, const arg_string& arg, + const ParamSelector& select) +{ + match_t longest; + + while(pos) { + if(pos->is_param()) { + const auto& param = pos->as_param(); + if(select(param)) { + auto match = param.match(arg); + if(match.prefix()) { + if(match.length() == arg.size()) { + return match_t{arg, std::move(pos)}; + } + else if(match.length() > longest.length()) { + longest = match_t{arg.substr(match.at(), match.length()), + pos}; + } + } + } + } + ++pos; + } + return longest; +} + + + +/*************************************************************************//** + * + * @brief finds the first parameter that partially matches a given string; + * candidate parameters are traversed using a scoped DFS traverser + * + *****************************************************************************/ +template +match_t +partial_match(scoped_dfs_traverser pos, const arg_string& arg, + const ParamSelector& select) +{ + while(pos) { + if(pos->is_param()) { + const auto& param = pos->as_param(); + if(select(param)) { + const auto match = param.match(arg); + if(match) { + return match_t{arg.substr(match.at(), match.length()), + std::move(pos)}; + } + } + } + ++pos; + } + return match_t{}; +} + +} //namespace detail + + + + + + +/***************************************************************//** + * + * @brief default command line arguments parser + * + *******************************************************************/ +class parser +{ +public: + using dfs_traverser = group::depth_first_traverser; + using scoped_dfs_traverser = detail::scoped_dfs_traverser; + + + /*****************************************************//** + * @brief arg -> parameter mapping + *********************************************************/ + class arg_mapping { + public: + friend class parser; + + explicit + arg_mapping(arg_index idx, arg_string s, + const dfs_traverser& match) + : + index_{idx}, arg_{std::move(s)}, match_{match}, + repeat_{0}, startsRepeatGroup_{false}, + blocked_{false}, conflict_{false} + {} + + explicit + arg_mapping(arg_index idx, arg_string s) : + index_{idx}, arg_{std::move(s)}, match_{}, + repeat_{0}, startsRepeatGroup_{false}, + blocked_{false}, conflict_{false} + {} + + arg_index index() const noexcept { return index_; } + const arg_string& arg() const noexcept { return arg_; } + + const parameter* param() const noexcept { + return match_ && match_->is_param() + ? &(match_->as_param()) : nullptr; + } + + std::size_t repeat() const noexcept { return repeat_; } + + bool blocked() const noexcept { return blocked_; } + bool conflict() const noexcept { return conflict_; } + + bool bad_repeat() const noexcept { + if(!param()) return false; + return repeat_ > 0 && !param()->repeatable() + && !match_.innermost_repeat_group(); + } + + bool any_error() const noexcept { + return !match_ || blocked() || conflict() || bad_repeat(); + } + + private: + arg_index index_; + arg_string arg_; + dfs_traverser match_; + std::size_t repeat_; + bool startsRepeatGroup_; + bool blocked_; + bool conflict_; + }; + + /*****************************************************//** + * @brief references a non-matched, required parameter + *********************************************************/ + class missing_event { + public: + explicit + missing_event(const parameter* p, arg_index after): + param_{p}, aftIndex_{after} + {} + + const parameter* param() const noexcept { return param_; } + + arg_index after_index() const noexcept { return aftIndex_; } + + private: + const parameter* param_; + arg_index aftIndex_; + }; + + //----------------------------------------------------- + using missing_events = std::vector; + using arg_mappings = std::vector; + + +private: + struct miss_candidate { + miss_candidate(dfs_traverser p, arg_index idx, + bool firstInRepeatGroup = false): + pos{std::move(p)}, index{idx}, + startsRepeatGroup{firstInRepeatGroup} + {} + + dfs_traverser pos; + arg_index index; + bool startsRepeatGroup; + }; + using miss_candidates = std::vector; + + +public: + //--------------------------------------------------------------- + /** @brief initializes parser with a command line interface + * @param offset = argument index offset used for reports + * */ + explicit + parser(const group& root, arg_index offset = 0): + root_{&root}, pos_{root}, + index_{offset-1}, eaten_{0}, + args_{}, missCand_{}, blocked_{false} + { + for_each_potential_miss(dfs_traverser{root}, + [this](const dfs_traverser& p){ + missCand_.emplace_back(p, index_); + }); + } + + + //--------------------------------------------------------------- + /** @brief processes one command line argument */ + bool operator() (const arg_string& arg) + { + ++eaten_; + ++index_; + + if(!valid()) return false; + + if(!blocked_ && try_match(arg)) return true; + + if(try_match_blocked(arg)) return false; + + //skipping of blocking & required patterns is not allowed + if(!blocked_ && !pos_.matched() && pos_->required() && pos_->blocking()) { + blocked_ = true; + } + + add_nomatch(arg); + return false; + } + + + //--------------------------------------------------------------- + /** @brief returns range of argument -> parameter mappings */ + const arg_mappings& args() const { + return args_; + } + + /** @brief returns list of missing events */ + missing_events missed() const { + missing_events misses; + misses.reserve(missCand_.size()); + for(auto i = missCand_.begin(); i != missCand_.end(); ++i) { + misses.emplace_back(&(i->pos->as_param()), i->index); + } + return misses; + } + + /** @brief returns number of processed command line arguments */ + arg_index parse_count() const noexcept { return eaten_; } + + /** @brief returns false if previously processed command line arguments + * lead to an invalid / inconsistent parsing result + */ + bool valid() const noexcept { return bool(pos_); } + + /** @brief returns false if previously processed command line arguments + * lead to an invalid / inconsistent parsing result + */ + explicit operator bool() const noexcept { return valid(); } + + +private: + //--------------------------------------------------------------- + using match_t = detail::match_t; + + + //--------------------------------------------------------------- + /** @brief try to match argument with unreachable parameter */ + bool try_match_blocked(const arg_string& arg) + { + //try to match ahead (using temporary parser) + if(pos_) { + auto ahead = *this; + if(try_match_blocked(std::move(ahead), arg)) return true; + } + + //try to match from the beginning (using temporary parser) + if(root_) { + parser all{*root_, index_+1}; + if(try_match_blocked(std::move(all), arg)) return true; + } + + return false; + } + + //--------------------------------------------------------------- + bool try_match_blocked(parser&& parse, const arg_string& arg) + { + const auto nold = int(parse.args_.size()); + + parse.pos_.ignore_blocking(true); + + if(!parse.try_match(arg)) return false; + + for(auto i = parse.args_.begin() + nold; i != parse.args_.end(); ++i) { + args_.push_back(*i); + args_.back().blocked_ = true; + } + return true; + } + + //--------------------------------------------------------------- + /** @brief try to find a parameter/pattern that matches 'arg' */ + bool try_match(const arg_string& arg) + { + //match greedy parameters before everything else + if(pos_->is_param() && pos_->blocking() && pos_->as_param().greedy()) { + const auto match = pos_->as_param().match(arg); + if(match && match.length() == arg.size()) { + add_match(detail::match_t{arg,pos_}); + return true; + } + } + + //try flags first (alone, joinable or strict sequence) + if(try_match_full(arg, detail::select_flags{})) return true; + if(try_match_joined_flags(arg)) return true; + if(try_match_joined_sequence(arg, detail::select_flags{})) return true; + //try value params (alone or strict sequence) + if(try_match_full(arg, detail::select_values{})) return true; + if(try_match_joined_sequence(arg, detail::select_all{})) return true; + //try joinable params + values in any order + if(try_match_joined_params(arg)) return true; + return false; + } + + //--------------------------------------------------------------- + /** + * @brief try to match full argument + * @param select : predicate that candidate parameters must satisfy + */ + template + bool try_match_full(const arg_string& arg, const ParamSelector& select) + { + auto match = detail::full_match(pos_, arg, select); + if(!match) return false; + add_match(match); + return true; + } + + //--------------------------------------------------------------- + /** + * @brief try to match argument as blocking sequence of parameters + * @param select : predicate that a parameter matching the prefix of + * 'arg' must satisfy + */ + template + bool try_match_joined_sequence(arg_string arg, + const ParamSelector& acceptFirst) + { + auto fstMatch = detail::longest_prefix_match(pos_, arg, acceptFirst); + + if(!fstMatch) return false; + + if(fstMatch.str().size() == arg.size()) { + add_match(fstMatch); + return true; + } + + if(!fstMatch.pos()->blocking()) return false; + + auto pos = fstMatch.pos(); + pos.ignore_blocking(true); + const auto parent = &pos.parent(); + if(!pos->repeatable()) ++pos; + + arg.erase(0, fstMatch.str().size()); + std::vector matches { std::move(fstMatch) }; + + while(!arg.empty() && pos && + pos->blocking() && pos->is_param() && + (&pos.parent() == parent)) + { + auto match = pos->as_param().match(arg); + + if(match.prefix()) { + matches.emplace_back(arg.substr(0,match.length()), pos); + arg.erase(0, match.length()); + if(!pos->repeatable()) ++pos; + } + else { + if(!pos->repeatable()) return false; + ++pos; + } + + } + //if arg not fully covered => discard temporary matches + if(!arg.empty() || matches.empty()) return false; + + for(const auto& m : matches) add_match(m); + return true; + } + + //----------------------------------------------------- + /** @brief try to match 'arg' as a concatenation of joinable flags */ + bool try_match_joined_flags(const arg_string& arg) + { + return find_join_group(pos_, [&](const group& g) { + return try_match_joined(g, arg, detail::select_flags{}, + g.common_flag_prefix()); + }); + } + + //--------------------------------------------------------------- + /** @brief try to match 'arg' as a concatenation of joinable parameters */ + bool try_match_joined_params(const arg_string& arg) + { + return find_join_group(pos_, [&](const group& g) { + return try_match_joined(g, arg, detail::select_all{}); + }); + } + + //----------------------------------------------------- + /** @brief try to match 'arg' as concatenation of joinable parameters + * that are all contained within one group + */ + template + bool try_match_joined(const group& joinGroup, arg_string arg, + const ParamSelector& select, + const arg_string& prefix = "") + { + //temporary parser with 'joinGroup' as top-level group + parser parse {joinGroup}; + //records temporary matches + std::vector matches; + + while(!arg.empty()) { + auto match = detail::longest_prefix_match(parse.pos_, arg, select); + + if(!match) return false; + + arg.erase(0, match.str().size()); + //make sure prefix is always present after the first match + //so that, e.g., flags "-a" and "-b" will be found in "-ab" + if(!arg.empty() && !prefix.empty() && arg.find(prefix) != 0 && + prefix != match.str()) + { + arg.insert(0,prefix); + } + + parse.add_match(match); + matches.push_back(std::move(match)); + } + + if(!arg.empty() || matches.empty()) return false; + + if(!parse.missCand_.empty()) return false; + for(const auto& a : parse.args_) if(a.any_error()) return false; + + //replay matches onto *this + for(const auto& m : matches) add_match(m); + return true; + } + + //----------------------------------------------------- + template + bool find_join_group(const scoped_dfs_traverser& start, + const GroupSelector& accept) const + { + if(start && start.parent().joinable()) { + const auto& g = start.parent(); + if(accept(g)) return true; + return false; + } + + auto pos = start; + while(pos) { + if(pos->is_group() && pos->as_group().joinable()) { + const auto& g = pos->as_group(); + if(accept(g)) return true; + pos.next_sibling(); + } + else { + ++pos; + } + } + return false; + } + + + //--------------------------------------------------------------- + void add_nomatch(const arg_string& arg) { + args_.emplace_back(index_, arg); + } + + + //--------------------------------------------------------------- + void add_match(const match_t& match) + { + const auto& pos = match.pos(); + if(!pos || !pos->is_param()) return; + + pos_.next_after_match(pos); + + arg_mapping newArg{index_, match.str(), pos.base()}; + newArg.repeat_ = occurrences_of(&pos->as_param()); + newArg.conflict_ = check_conflicts(pos.base()); + newArg.startsRepeatGroup_ = pos_.start_of_repeat_group(); + args_.push_back(std::move(newArg)); + + add_miss_candidates_after(pos); + clean_miss_candidates_for(pos.base()); + discard_alternative_miss_candidates(pos.base()); + + } + + //----------------------------------------------------- + bool check_conflicts(const dfs_traverser& match) + { + if(pos_.start_of_repeat_group()) return false; + bool conflict = false; + for(const auto& m : match.stack()) { + if(m.parent->exclusive()) { + for(auto i = args_.rbegin(); i != args_.rend(); ++i) { + if(!i->blocked()) { + for(const auto& c : i->match_.stack()) { + //sibling within same exclusive group => conflict + if(c.parent == m.parent && c.cur != m.cur) { + conflict = true; + i->conflict_ = true; + } + } + } + //check for conflicts only within current repeat cycle + if(i->startsRepeatGroup_) break; + } + } + } + return conflict; + } + + //----------------------------------------------------- + void clean_miss_candidates_for(const dfs_traverser& match) + { + auto i = std::find_if(missCand_.rbegin(), missCand_.rend(), + [&](const miss_candidate& m) { + return &(*m.pos) == &(*match); + }); + + if(i != missCand_.rend()) { + missCand_.erase(prev(i.base())); + } + } + + //----------------------------------------------------- + void discard_alternative_miss_candidates(const dfs_traverser& match) + { + if(missCand_.empty()) return; + //find out, if miss candidate is sibling of one of the same + //alternative groups that the current match is a member of + //if so, we can discard the miss + + //go through all exclusive groups of matching pattern + for(const auto& m : match.stack()) { + if(m.parent->exclusive()) { + for(auto i = int(missCand_.size())-1; i >= 0; --i) { + bool removed = false; + for(const auto& c : missCand_[i].pos.stack()) { + //sibling within same exclusive group => discard + if(c.parent == m.parent && c.cur != m.cur) { + missCand_.erase(missCand_.begin() + i); + if(missCand_.empty()) return; + removed = true; + break; + } + } + //remove miss candidates only within current repeat cycle + if(i > 0 && removed) { + if(missCand_[i-1].startsRepeatGroup) break; + } else { + if(missCand_[i].startsRepeatGroup) break; + } + } + } + } + } + + //----------------------------------------------------- + void add_miss_candidates_after(const scoped_dfs_traverser& match) + { + auto npos = match.base(); + if(npos.is_alternative()) npos.skip_alternatives(); + ++npos; + //need to add potential misses if: + //either new repeat group was started + const auto newRepGroup = match.innermost_repeat_group(); + if(newRepGroup) { + if(pos_.start_of_repeat_group()) { + for_each_potential_miss(std::move(npos), + [&,this](const dfs_traverser& pos) { + //only add candidates within repeat group + if(newRepGroup == pos.innermost_repeat_group()) { + missCand_.emplace_back(pos, index_, true); + } + }); + } + } + //... or an optional blocking param was hit + else if(match->blocking() && !match->required() && + npos.level() >= match.base().level()) + { + for_each_potential_miss(std::move(npos), + [&,this](const dfs_traverser& pos) { + //only add new candidates + if(std::find_if(missCand_.begin(), missCand_.end(), + [&](const miss_candidate& c){ + return &(*c.pos) == &(*pos); + }) == missCand_.end()) + { + missCand_.emplace_back(pos, index_); + } + }); + } + + } + + //----------------------------------------------------- + template + static void + for_each_potential_miss(dfs_traverser pos, Action&& action) + { + const auto level = pos.level(); + while(pos && pos.level() >= level) { + if(pos->is_group() ) { + const auto& g = pos->as_group(); + if(g.all_optional() || (g.exclusive() && g.any_optional())) { + pos.next_sibling(); + } else { + ++pos; + } + } else { //param + if(pos->required()) { + action(pos); + ++pos; + } else if(pos->blocking()) { //optional + blocking + pos.next_after_siblings(); + } else { + ++pos; + } + } + } + } + + + //--------------------------------------------------------------- + std::size_t occurrences_of(const parameter* p) const + { + if(!p) return 0; + + auto i = std::find_if(args_.rbegin(), args_.rend(), + [p](const arg_mapping& a){ return a.param() == p; }); + + if(i != args_.rend()) return i->repeat() + 1; + return 0; + } + + + //--------------------------------------------------------------- + const group* root_; + scoped_dfs_traverser pos_; + arg_index index_; + arg_index eaten_; + arg_mappings args_; + miss_candidates missCand_; + bool blocked_; +}; + + + + +/*************************************************************************//** + * + * @brief contains argument -> parameter mappings + * and missing parameters + * + *****************************************************************************/ +class parsing_result +{ +public: + using arg_mapping = parser::arg_mapping; + using arg_mappings = parser::arg_mappings; + using missing_event = parser::missing_event; + using missing_events = parser::missing_events; + using iterator = arg_mappings::const_iterator; + + //----------------------------------------------------- + /** @brief default: empty result */ + parsing_result() = default; + + parsing_result(arg_mappings arg2param, missing_events misses): + arg2param_{std::move(arg2param)}, missing_{std::move(misses)} + {} + + //----------------------------------------------------- + /** @brief returns number of arguments that could not be mapped to + * a parameter + */ + arg_mappings::size_type + unmapped_args_count() const noexcept { + return std::count_if(arg2param_.begin(), arg2param_.end(), + [](const arg_mapping& a){ return !a.param(); }); + } + + /** @brief returns if any argument could only be matched by an + * unreachable parameter + */ + bool any_blocked() const noexcept { + return std::any_of(arg2param_.begin(), arg2param_.end(), + [](const arg_mapping& a){ return a.blocked(); }); + } + + /** @brief returns if any argument matched more than one parameter + * that were mutually exclusive */ + bool any_conflict() const noexcept { + return std::any_of(arg2param_.begin(), arg2param_.end(), + [](const arg_mapping& a){ return a.conflict(); }); + } + + /** @brief returns if any parameter matched repeatedly although + * it was not allowed to */ + bool any_bad_repeat() const noexcept { + return std::any_of(arg2param_.begin(), arg2param_.end(), + [](const arg_mapping& a){ return a.bad_repeat(); }); + } + + /** @brief returns true if any parsing error / violation of the + * command line interface definition occurred */ + bool any_error() const noexcept { + return unmapped_args_count() > 0 || !missing().empty() || + any_blocked() || any_conflict() || any_bad_repeat(); + } + + /** @brief returns true if no parsing error / violation of the + * command line interface definition occurred */ + explicit operator bool() const noexcept { return !any_error(); } + + /** @brief access to range of missing parameter match events */ + const missing_events& missing() const noexcept { return missing_; } + + /** @brief returns non-mutating iterator to position of + * first argument -> parameter mapping */ + iterator begin() const noexcept { return arg2param_.begin(); } + /** @brief returns non-mutating iterator to position one past the + * last argument -> parameter mapping */ + iterator end() const noexcept { return arg2param_.end(); } + +private: + //----------------------------------------------------- + arg_mappings arg2param_; + missing_events missing_; +}; + + + + +namespace detail { +namespace { + +/*************************************************************************//** + * + * @brief correct some common problems + * does not - and MUST NOT - change the number of arguments + * (no insertions or deletions allowed) + * + *****************************************************************************/ +void sanitize_args(arg_list& args) +{ + //e.g. {"-o12", ".34"} -> {"-o", "12.34"} + + if(args.empty()) return; + + for(auto i = begin(args)+1; i != end(args); ++i) { + if(i != begin(args) && i->size() > 1 && + i->find('.') == 0 && std::isdigit((*i)[1]) ) + { + //find trailing digits in previous arg + using std::prev; + auto& prv = *prev(i); + auto fstDigit = std::find_if_not(prv.rbegin(), prv.rend(), + [](arg_string::value_type c){ + return std::isdigit(c); + }).base(); + + //handle leading sign + if(fstDigit > prv.begin() && + (*prev(fstDigit) == '+' || *prev(fstDigit) == '-')) + { + --fstDigit; + } + + //prepend digits from previous arg + i->insert(begin(*i), fstDigit, end(prv)); + + //erase digits in previous arg + prv.erase(fstDigit, end(prv)); + } + } +} + + + +/*************************************************************************//** + * + * @brief executes actions based on a parsing result + * + *****************************************************************************/ +void execute_actions(const parsing_result& res) +{ + for(const auto& m : res) { + if(m.param()) { + const auto& param = *(m.param()); + + if(m.repeat() > 0) param.notify_repeated(m.index()); + if(m.blocked()) param.notify_blocked(m.index()); + if(m.conflict()) param.notify_conflict(m.index()); + //main action + if(!m.any_error()) param.execute_actions(m.arg()); + } + } + + for(auto m : res.missing()) { + if(m.param()) m.param()->notify_missing(m.after_index()); + } +} + + + +/*************************************************************************//** + * + * @brief parses input args + * + *****************************************************************************/ +static parsing_result +parse_args(const arg_list& args, const group& cli, + arg_index offset = 0) +{ + //parse args and store unrecognized arg indices + parser parse{cli, offset}; + for(const auto& arg : args) { + parse(arg); + if(!parse.valid()) break; + } + + return parsing_result{parse.args(), parse.missed()}; +} + +/*************************************************************************//** + * + * @brief parses input args & executes actions + * + *****************************************************************************/ +static parsing_result +parse_and_execute(const arg_list& args, const group& cli, + arg_index offset = 0) +{ + auto result = parse_args(args, cli, offset); + + execute_actions(result); + + return result; +} + +} //anonymous namespace +} // namespace detail + + + + +/*************************************************************************//** + * + * @brief parses vector of arg strings and executes actions + * + *****************************************************************************/ +inline parsing_result +parse(arg_list args, const group& cli) +{ + detail::sanitize_args(args); + return detail::parse_and_execute(args, cli); +} + + +/*************************************************************************//** + * + * @brief parses initializer_list of C-style arg strings and executes actions + * + *****************************************************************************/ +inline parsing_result +parse(std::initializer_list arglist, const group& cli) +{ + arg_list args; + args.reserve(arglist.size()); + for(auto a : arglist) { + args.push_back(a); + } + + return parse(std::move(args), cli); +} + + +/*************************************************************************//** + * + * @brief parses range of arg strings and executes actions + * + *****************************************************************************/ +template +inline parsing_result +parse(InputIterator first, InputIterator last, const group& cli) +{ + return parse(arg_list(first,last), cli); +} + + +/*************************************************************************//** + * + * @brief parses the standard array of command line arguments; omits argv[0] + * + *****************************************************************************/ +inline parsing_result +parse(const int argc, char* argv[], const group& cli, arg_index offset = 1) +{ + arg_list args; + if(offset < argc) args.assign(argv+offset, argv+argc); + detail::sanitize_args(args); + return detail::parse_and_execute(args, cli, offset); +} + + + + + + +/*************************************************************************//** + * + * @brief filter predicate for parameters and groups; + * Can be used to limit documentation generation to parameter subsets. + * + *****************************************************************************/ +class param_filter +{ +public: + /** @brief only allow parameters with given prefix */ + param_filter& prefix(const arg_string& p) noexcept { + prefix_ = p; return *this; + } + /** @brief only allow parameters with given prefix */ + param_filter& prefix(arg_string&& p) noexcept { + prefix_ = std::move(p); return *this; + } + const arg_string& prefix() const noexcept { return prefix_; } + + /** @brief only allow parameters with given requirement status */ + param_filter& required(tri t) noexcept { required_ = t; return *this; } + tri required() const noexcept { return required_; } + + /** @brief only allow parameters with given blocking status */ + param_filter& blocking(tri t) noexcept { blocking_ = t; return *this; } + tri blocking() const noexcept { return blocking_; } + + /** @brief only allow parameters with given repeatable status */ + param_filter& repeatable(tri t) noexcept { repeatable_ = t; return *this; } + tri repeatable() const noexcept { return repeatable_; } + + /** @brief only allow parameters with given docstring status */ + param_filter& has_doc(tri t) noexcept { hasDoc_ = t; return *this; } + tri has_doc() const noexcept { return hasDoc_; } + + + /** @brief returns true, if parameter satisfies all filters */ + bool operator() (const parameter& p) const noexcept { + if(!prefix_.empty()) { + if(!std::any_of(p.flags().begin(), p.flags().end(), + [&](const arg_string& flag){ + return str::has_prefix(flag, prefix_); + })) return false; + } + if(required() != p.required()) return false; + if(blocking() != p.blocking()) return false; + if(repeatable() != p.repeatable()) return false; + if(has_doc() != !p.doc().empty()) return false; + return true; + } + +private: + arg_string prefix_; + tri required_ = tri::either; + tri blocking_ = tri::either; + tri repeatable_ = tri::either; + tri hasDoc_ = tri::yes; +}; + + + + + + +/*************************************************************************//** + * + * @brief documentation formatting options + * + *****************************************************************************/ +class doc_formatting +{ +public: + using string = doc_string; + + /** @brief same as 'first_column' */ +#if __cplusplus >= 201402L + [[deprecated]] +#endif + doc_formatting& start_column(int col) { return first_column(col); } +#if __cplusplus >= 201402L + [[deprecated]] +#endif + int start_column() const noexcept { return first_column(); } + + /** @brief determines column where documentation printing starts */ + doc_formatting& + first_column(int col) { + //limit to [0,last_column] but push doc_column to the right if necessary + if(col < 0) col = 0; + else if(col > last_column()) col = last_column(); + if(col > doc_column()) doc_column(first_column()); + firstCol_ = col; + return *this; + } + int first_column() const noexcept { + return firstCol_; + } + + /** @brief determines column where docstrings start */ + doc_formatting& + doc_column(int col) { + //limit to [first_column,last_column] + if(col < 0) col = 0; + else if(col < first_column()) col = first_column(); + else if(col > last_column()) col = last_column(); + docCol_ = col; + return *this; + } + int doc_column() const noexcept { + return docCol_; + } + + /** @brief determines column that no documentation text must exceed; + * (text should be wrapped appropriately after this column) + */ + doc_formatting& + last_column(int col) { + //limit to [first_column,oo] but push doc_column to the left if necessary + if(col < first_column()) col = first_column(); + if(col < doc_column()) doc_column(col); + lastCol_ = col; + return *this; + } + + int last_column() const noexcept { + return lastCol_; + } + + /** @brief determines indent of documentation lines + * for children of a documented group */ + doc_formatting& indent_size(int indent) { indentSize_ = indent; return *this; } + int indent_size() const noexcept { return indentSize_; } + + /** @brief determines string to be used + * if a parameter has no flags and no label */ + doc_formatting& empty_label(const string& label) { + emptyLabel_ = label; + return *this; + } + const string& empty_label() const noexcept { return emptyLabel_; } + + /** @brief determines string for separating parameters */ + doc_formatting& param_separator(const string& sep) { + paramSep_ = sep; + return *this; + } + const string& param_separator() const noexcept { return paramSep_; } + + /** @brief determines string for separating groups (in usage lines) */ + doc_formatting& group_separator(const string& sep) { + groupSep_ = sep; + return *this; + } + const string& group_separator() const noexcept { return groupSep_; } + + /** @brief determines string for separating alternative parameters */ + doc_formatting& alternative_param_separator(const string& sep) { + altParamSep_ = sep; + return *this; + } + const string& alternative_param_separator() const noexcept { return altParamSep_; } + + /** @brief determines string for separating alternative groups */ + doc_formatting& alternative_group_separator(const string& sep) { + altGroupSep_ = sep; + return *this; + } + const string& alternative_group_separator() const noexcept { return altGroupSep_; } + + /** @brief determines string for separating flags of the same parameter */ + doc_formatting& flag_separator(const string& sep) { + flagSep_ = sep; + return *this; + } + const string& flag_separator() const noexcept { return flagSep_; } + + /** @brief determines strings surrounding parameter labels */ + doc_formatting& + surround_labels(const string& prefix, const string& postfix) { + labelPre_ = prefix; + labelPst_ = postfix; + return *this; + } + const string& label_prefix() const noexcept { return labelPre_; } + const string& label_postfix() const noexcept { return labelPst_; } + + /** @brief determines strings surrounding optional parameters/groups */ + doc_formatting& + surround_optional(const string& prefix, const string& postfix) { + optionPre_ = prefix; + optionPst_ = postfix; + return *this; + } + const string& optional_prefix() const noexcept { return optionPre_; } + const string& optional_postfix() const noexcept { return optionPst_; } + + /** @brief determines strings surrounding repeatable parameters/groups */ + doc_formatting& + surround_repeat(const string& prefix, const string& postfix) { + repeatPre_ = prefix; + repeatPst_ = postfix; + return *this; + } + const string& repeat_prefix() const noexcept { return repeatPre_; } + const string& repeat_postfix() const noexcept { return repeatPst_; } + + /** @brief determines strings surrounding exclusive groups */ + doc_formatting& + surround_alternatives(const string& prefix, const string& postfix) { + alternPre_ = prefix; + alternPst_ = postfix; + return *this; + } + const string& alternatives_prefix() const noexcept { return alternPre_; } + const string& alternatives_postfix() const noexcept { return alternPst_; } + + /** @brief determines strings surrounding alternative flags */ + doc_formatting& + surround_alternative_flags(const string& prefix, const string& postfix) { + alternFlagPre_ = prefix; + alternFlagPst_ = postfix; + return *this; + } + const string& alternative_flags_prefix() const noexcept { return alternFlagPre_; } + const string& alternative_flags_postfix() const noexcept { return alternFlagPst_; } + + /** @brief determines strings surrounding non-exclusive groups */ + doc_formatting& + surround_group(const string& prefix, const string& postfix) { + groupPre_ = prefix; + groupPst_ = postfix; + return *this; + } + const string& group_prefix() const noexcept { return groupPre_; } + const string& group_postfix() const noexcept { return groupPst_; } + + /** @brief determines strings surrounding joinable groups */ + doc_formatting& + surround_joinable(const string& prefix, const string& postfix) { + joinablePre_ = prefix; + joinablePst_ = postfix; + return *this; + } + const string& joinable_prefix() const noexcept { return joinablePre_; } + const string& joinable_postfix() const noexcept { return joinablePst_; } + + /** @brief determines maximum number of flags per parameter to be printed + * in detailed parameter documentation lines */ + doc_formatting& max_flags_per_param_in_doc(int max) { + maxAltInDocs_ = max > 0 ? max : 0; + return *this; + } + int max_flags_per_param_in_doc() const noexcept { return maxAltInDocs_; } + + /** @brief determines maximum number of flags per parameter to be printed + * in usage lines */ + doc_formatting& max_flags_per_param_in_usage(int max) { + maxAltInUsage_ = max > 0 ? max : 0; + return *this; + } + int max_flags_per_param_in_usage() const noexcept { return maxAltInUsage_; } + + /** @brief determines number of empty rows after one single-line + * documentation entry */ + doc_formatting& line_spacing(int lines) { + lineSpc_ = lines > 0 ? lines : 0; + return *this; + } + int line_spacing() const noexcept { return lineSpc_; } + + /** @brief determines number of empty rows before and after a paragraph; + * a paragraph is defined by a documented group or if + * a parameter documentation entry used more than one line */ + doc_formatting& paragraph_spacing(int lines) { + paragraphSpc_ = lines > 0 ? lines : 0; + return *this; + } + int paragraph_spacing() const noexcept { return paragraphSpc_; } + + /** @brief determines if alternative flags with a common prefix should + * be printed in a merged fashion */ + doc_formatting& merge_alternative_flags_with_common_prefix(bool yes = true) { + mergeAltCommonPfx_ = yes; + return *this; + } + bool merge_alternative_flags_with_common_prefix() const noexcept { + return mergeAltCommonPfx_; + } + + /** @brief determines if joinable flags with a common prefix should + * be printed in a merged fashion */ + doc_formatting& merge_joinable_with_common_prefix(bool yes = true) { + mergeJoinableCommonPfx_ = yes; + return *this; + } + bool merge_joinable_with_common_prefix() const noexcept { + return mergeJoinableCommonPfx_; + } + + /** @brief determines if children of exclusive groups should be printed + * on individual lines if the exceed 'alternatives_min_split_size' + */ + doc_formatting& split_alternatives(bool yes = true) { + splitTopAlt_ = yes; + return *this; + } + bool split_alternatives() const noexcept { + return splitTopAlt_; + } + + /** @brief determines how many children exclusive groups can have before + * their children are printed on individual usage lines */ + doc_formatting& alternatives_min_split_size(int size) { + groupSplitSize_ = size > 0 ? size : 0; + return *this; + } + int alternatives_min_split_size() const noexcept { return groupSplitSize_; } + + /** @brief determines whether to ignore new line characters in docstrings + */ + doc_formatting& ignore_newline_chars(bool yes = true) { + ignoreNewlines_ = yes; + return *this; + } + bool ignore_newline_chars() const noexcept { + return ignoreNewlines_; + } + +private: + string paramSep_ = string(" "); + string groupSep_ = string(" "); + string altParamSep_ = string("|"); + string altGroupSep_ = string(" | "); + string flagSep_ = string(", "); + string labelPre_ = string("<"); + string labelPst_ = string(">"); + string optionPre_ = string("["); + string optionPst_ = string("]"); + string repeatPre_ = string(""); + string repeatPst_ = string("..."); + string groupPre_ = string("("); + string groupPst_ = string(")"); + string alternPre_ = string("("); + string alternPst_ = string(")"); + string alternFlagPre_ = string(""); + string alternFlagPst_ = string(""); + string joinablePre_ = string("("); + string joinablePst_ = string(")"); + string emptyLabel_ = string(""); + int firstCol_ = 8; + int docCol_ = 20; + int lastCol_ = 100; + int indentSize_ = 4; + int maxAltInUsage_ = 1; + int maxAltInDocs_ = 32; + int lineSpc_ = 0; + int paragraphSpc_ = 1; + int groupSplitSize_ = 3; + bool splitTopAlt_ = true; + bool mergeAltCommonPfx_ = false; + bool mergeJoinableCommonPfx_ = true; + bool ignoreNewlines_ = false; +}; + + + +namespace detail { + +/*************************************************************************//** + * + * @brief stream decorator + * that applies formatting like line wrapping + * + *****************************************************************************/ +template +class formatting_ostream +{ +public: + using string_type = StringT; + using size_type = typename string_type::size_type; + using char_type = typename string_type::value_type; + + formatting_ostream(OStream& os): + os_(os), + curCol_{0}, firstCol_{0}, lastCol_{100}, + hangingIndent_{0}, paragraphSpacing_{0}, paragraphSpacingThreshold_{2}, + curBlankLines_{0}, curParagraphLines_{1}, + totalNonBlankLines_{0}, + ignoreInputNls_{false} + {} + + + //--------------------------------------------------------------- + const OStream& base() const noexcept { return os_; } + OStream& base() noexcept { return os_; } + + bool good() const { return os_.good(); } + + + //--------------------------------------------------------------- + /** @brief determines the leftmost border of the text body */ + formatting_ostream& first_column(int c) { + firstCol_ = c < 0 ? 0 : c; + return *this; + } + int first_column() const noexcept { return firstCol_; } + + /** @brief determines the rightmost border of the text body */ + formatting_ostream& last_column(int c) { + lastCol_ = c < 0 ? 0 : c; + return *this; + } + + int last_column() const noexcept { return lastCol_; } + + int text_width() const noexcept { + return lastCol_ - firstCol_; + } + + /** @brief additional indentation for the 2nd, 3rd, ... line of + a paragraph (sequence of soft-wrapped lines) */ + formatting_ostream& hanging_indent(int amount) { + hangingIndent_ = amount; + return *this; + } + int hanging_indent() const noexcept { + return hangingIndent_; + } + + /** @brief amount of blank lines between paragraphs */ + formatting_ostream& paragraph_spacing(int lines) { + paragraphSpacing_ = lines; + return *this; + } + int paragraph_spacing() const noexcept { + return paragraphSpacing_; + } + + /** @brief insert paragraph spacing + if paragraph is at least 'lines' lines long */ + formatting_ostream& min_paragraph_lines_for_spacing(int lines) { + paragraphSpacingThreshold_ = lines; + return *this; + } + int min_paragraph_lines_for_spacing() const noexcept { + return paragraphSpacingThreshold_; + } + + /** @brief if set to true, newline characters will be ignored */ + formatting_ostream& ignore_newline_chars(bool yes) { + ignoreInputNls_ = yes; + return *this; + } + + bool ignore_newline_chars() const noexcept { + return ignoreInputNls_; + } + + + //--------------------------------------------------------------- + /* @brief insert 'n' spaces */ + void write_spaces(int n) { + if(n < 1) return; + os_ << string_type(size_type(n), ' '); + curCol_ += n; + } + + /* @brief go to new line, but continue current paragraph */ + void wrap_soft(int times = 1) { + if(times < 1) return; + if(times > 1) { + os_ << string_type(size_type(times), '\n'); + } else { + os_ << '\n'; + } + curCol_ = 0; + ++curParagraphLines_; + } + + /* @brief go to new line, and start a new paragraph */ + void wrap_hard(int times = 1) { + if(times < 1) return; + + if(paragraph_spacing() > 0 && + paragraph_lines() >= min_paragraph_lines_for_spacing()) + { + times = paragraph_spacing() + 1; + } + + if(times > 1) { + os_ << string_type(size_type(times), '\n'); + curBlankLines_ += times - 1; + } else { + os_ << '\n'; + } + if(at_begin_of_line()) { + ++curBlankLines_; + } + curCol_ = 0; + curParagraphLines_ = 1; + } + + + //--------------------------------------------------------------- + bool at_begin_of_line() const noexcept { + return curCol_ <= current_line_begin(); + } + int current_line_begin() const noexcept { + return in_hanging_part_of_paragraph() + ? firstCol_ + hangingIndent_ + : firstCol_; + } + + int current_column() const noexcept { + return curCol_; + } + + int total_non_blank_lines() const noexcept { + return totalNonBlankLines_; + } + int paragraph_lines() const noexcept { + return curParagraphLines_; + } + int blank_lines_before_paragraph() const noexcept { + return curBlankLines_; + } + + + //--------------------------------------------------------------- + template + friend formatting_ostream& + operator << (formatting_ostream& os, const T& x) { + os.write(x); + return os; + } + + void flush() { + os_.flush(); + } + + +private: + bool in_hanging_part_of_paragraph() const noexcept { + return hanging_indent() > 0 && paragraph_lines() > 1; + } + bool current_line_empty() const noexcept { + return curCol_ < 1; + } + bool left_of_text_area() const noexcept { + return curCol_ < current_line_begin(); + } + bool right_of_text_area() const noexcept { + return curCol_ > lastCol_; + } + int columns_left_in_line() const noexcept { + return lastCol_ - std::max(current_line_begin(), curCol_); + } + + void fix_indent() { + if(left_of_text_area()) { + const auto fst = current_line_begin(); + write_spaces(fst - curCol_); + curCol_ = fst; + } + } + + template + bool only_whitespace(Iter first, Iter last) const { + return last == std::find_if_not(first, last, + [](char_type c) { return std::isspace(c); }); + } + + /** @brief write any object */ + template + void write(const T& x) { + std::ostringstream ss; + ss << x; + write(std::move(ss).str()); + } + + /** @brief write a stringstream */ + void write(const std::ostringstream& s) { + write(s.str()); + } + + /** @brief write a string */ + void write(const string_type& s) { + write(s.begin(), s.end()); + } + + /** @brief partition output into lines */ + template + void write(Iter first, Iter last) + { + if(first == last) return; + if(*first == '\n') { + if(!ignore_newline_chars()) wrap_hard(); + ++first; + if(first == last) return; + } + auto i = std::find(first, last, '\n'); + if(i != last) { + if(ignore_newline_chars()) ++i; + if(i != last) { + write_line(first, i); + write(i, last); + } + } + else { + write_line(first, last); + } + } + + /** @brief handle line wrapping due to column constraints */ + template + void write_line(Iter first, Iter last) + { + if(first == last) return; + if(only_whitespace(first, last)) return; + + if(right_of_text_area()) wrap_soft(); + + if(at_begin_of_line()) { + //discard whitespace, it we start a new line + first = std::find_if(first, last, + [](char_type c) { return !std::isspace(c); }); + if(first == last) return; + } + + const auto n = int(std::distance(first,last)); + const auto m = columns_left_in_line(); + //if text to be printed is too long for one line -> wrap + if(n > m) { + //break before word, if break is mid-word + auto breakat = first + m; + while(breakat > first && !std::isspace(*breakat)) --breakat; + //could not find whitespace before word -> try after the word + if(!std::isspace(*breakat) && breakat == first) { + breakat = std::find_if(first+m, last, + [](char_type c) { return std::isspace(c); }); + } + if(breakat > first) { + if(curCol_ < 1) ++totalNonBlankLines_; + fix_indent(); + std::copy(first, breakat, std::ostream_iterator(os_)); + curBlankLines_ = 0; + } + if(breakat < last) { + wrap_soft(); + write_line(breakat, last); + } + } + else { + if(curCol_ < 1) ++totalNonBlankLines_; + fix_indent(); + std::copy(first, last, std::ostream_iterator(os_)); + curCol_ += n; + curBlankLines_ = 0; + } + } + + /** @brief write a single character */ + void write(char_type c) + { + if(c == '\n') { + if(!ignore_newline_chars()) wrap_hard(); + } + else { + if(at_begin_of_line()) ++totalNonBlankLines_; + fix_indent(); + os_ << c; + ++curCol_; + } + } + + OStream& os_; + int curCol_; + int firstCol_; + int lastCol_; + int hangingIndent_; + int paragraphSpacing_; + int paragraphSpacingThreshold_; + int curBlankLines_; + int curParagraphLines_; + int totalNonBlankLines_; + bool ignoreInputNls_; +}; + + +} + + + + +/*************************************************************************//** + * + * @brief generates usage lines + * + * @details lazily evaluated + * + *****************************************************************************/ +class usage_lines +{ +public: + using string = doc_string; + + usage_lines(const group& cli, string prefix = "", + const doc_formatting& fmt = doc_formatting{}) + : + cli_(cli), fmt_(fmt), prefix_(std::move(prefix)) + { + if(!prefix_.empty()) prefix_ += ' '; + } + + usage_lines(const group& cli, const doc_formatting& fmt): + usage_lines(cli, "", fmt) + {} + + usage_lines& ommit_outermost_group_surrounders(bool yes) { + ommitOutermostSurrounders_ = yes; + return *this; + } + bool ommit_outermost_group_surrounders() const { + return ommitOutermostSurrounders_; + } + + template + inline friend OStream& operator << (OStream& os, const usage_lines& p) { + p.write(os); + return os; + } + + string str() const { + std::ostringstream os; os << *this; return os.str(); + } + + +private: + using stream_t = detail::formatting_ostream<>; + const group& cli_; + doc_formatting fmt_; + string prefix_; + bool ommitOutermostSurrounders_ = false; + + + //----------------------------------------------------- + struct context { + group::depth_first_traverser pos; + std::stack separators; + std::stack postfixes; + int level = 0; + const group* outermost = nullptr; + bool linestart = false; + bool useOutermost = true; + int line = 0; + + bool is_singleton() const noexcept { + return linestart && pos.is_last_in_path(); + } + bool is_alternative() const noexcept { + return pos.parent().exclusive(); + } + }; + + + /***************************************************************//** + * + * @brief writes usage text for command line parameters + * + *******************************************************************/ + template + void write(OStream& os) const + { + detail::formatting_ostream fos(os); + fos.first_column(fmt_.first_column()); + fos.last_column(fmt_.last_column()); + + auto hindent = int(prefix_.size()); + if(fos.first_column() + hindent >= int(0.4 * fos.text_width())) { + hindent = fmt_.indent_size(); + } + fos.hanging_indent(hindent); + + fos.paragraph_spacing(fmt_.paragraph_spacing()); + fos.min_paragraph_lines_for_spacing(2); + fos.ignore_newline_chars(fmt_.ignore_newline_chars()); + + context cur; + cur.pos = cli_.begin_dfs(); + cur.linestart = true; + cur.level = cur.pos.level(); + cur.outermost = &cli_; + + write(fos, cur, prefix_); + } + + + /***************************************************************//** + * + * @brief writes usage text for command line parameters + * + * @param prefix all that goes in front of current things to print + * + *******************************************************************/ + template + void write(OStream& os, context cur, string prefix) const + { + if(!cur.pos) return; + + std::ostringstream buf; + if(cur.linestart) buf << prefix; + const auto initPos = buf.tellp(); + + cur.level = cur.pos.level(); + + if(cur.useOutermost) { + //we cannot start outside of the outermost group + //so we have to treat it separately + start_group(buf, cur.pos.parent(), cur); + if(!cur.pos) { + os << buf.str(); + return; + } + } + else { + //don't visit siblings of starter node + cur.pos.skip_siblings(); + } + check_end_group(buf, cur); + + do { + if(buf.tellp() > initPos) cur.linestart = false; + if(!cur.linestart && !cur.pos.is_first_in_parent()) { + buf << cur.separators.top(); + } + if(cur.pos->is_group()) { + start_group(buf, cur.pos->as_group(), cur); + if(!cur.pos) { + os << buf.str(); + return; + } + } + else { + buf << param_label(cur.pos->as_param(), cur); + ++cur.pos; + } + check_end_group(buf, cur); + } while(cur.pos); + + os << buf.str(); + } + + + /***************************************************************//** + * + * @brief handles pattern group surrounders and separators + * and alternative splitting + * + *******************************************************************/ + void start_group(std::ostringstream& os, + const group& group, context& cur) const + { + //does cur.pos already point to a member or to group itself? + //needed for special treatment of outermost group + const bool alreadyInside = &(cur.pos.parent()) == &group; + + auto lbl = joined_label(group, cur); + if(!lbl.empty()) { + os << lbl; + cur.linestart = false; + //skip over entire group as its label has already been created + if(alreadyInside) { + cur.pos.next_after_siblings(); + } else { + cur.pos.next_sibling(); + } + } + else { + const bool splitAlternatives = group.exclusive() && + fmt_.split_alternatives() && + std::any_of(group.begin(), group.end(), + [this](const pattern& p) { + return int(p.param_count()) >= fmt_.alternatives_min_split_size(); + }); + + if(splitAlternatives) { + cur.postfixes.push(""); + cur.separators.push(""); + //recursively print alternative paths in decision-DAG + //enter group? + if(!alreadyInside) ++cur.pos; + cur.linestart = true; + cur.useOutermost = false; + auto pfx = os.str(); + os.str(""); + //print paths in DAG starting at each group member + for(std::size_t i = 0; i < group.size(); ++i) { + std::stringstream buf; + cur.outermost = cur.pos->is_group() ? &(cur.pos->as_group()) : nullptr; + write(buf, cur, pfx); + if(buf.tellp() > int(pfx.size())) { + os << buf.str(); + if(i < group.size()-1) { + if(cur.line > 0) { + os << string(fmt_.line_spacing(), '\n'); + } + ++cur.line; + os << '\n'; + } + } + cur.pos.next_sibling(); //do not descend into members + } + cur.pos.invalidate(); //signal end-of-path + return; + } + else { + //pre & postfixes, separators + auto surround = group_surrounders(group, cur); + os << surround.first; + cur.postfixes.push(std::move(surround.second)); + cur.separators.push(group_separator(group, fmt_)); + //descend into group? + if(!alreadyInside) ++cur.pos; + } + } + cur.level = cur.pos.level(); + } + + + /***************************************************************//** + * + *******************************************************************/ + void check_end_group(std::ostringstream& os, context& cur) const + { + for(; cur.level > cur.pos.level(); --cur.level) { + os << cur.postfixes.top(); + cur.postfixes.pop(); + cur.separators.pop(); + } + cur.level = cur.pos.level(); + } + + + /***************************************************************//** + * + * @brief makes usage label for one command line parameter + * + *******************************************************************/ + string param_label(const parameter& p, const context& cur) const + { + const auto& parent = cur.pos.parent(); + + const bool startsOptionalSequence = + parent.size() > 1 && p.blocking() && cur.pos.is_first_in_parent(); + + const bool outermost = + ommitOutermostSurrounders_ && cur.outermost == &parent; + + const bool showopt = !cur.is_alternative() && !p.required() + && !startsOptionalSequence && !outermost; + + const bool showrep = p.repeatable() && !outermost; + + string lbl; + + if(showrep) lbl += fmt_.repeat_prefix(); + if(showopt) lbl += fmt_.optional_prefix(); + + const auto& flags = p.flags(); + if(!flags.empty()) { + const int n = std::min(fmt_.max_flags_per_param_in_usage(), + int(flags.size())); + + const bool surrAlt = n > 1 && !showopt && !cur.is_singleton(); + + if(surrAlt) lbl += fmt_.alternative_flags_prefix(); + bool sep = false; + for(int i = 0; i < n; ++i) { + if(sep) { + if(cur.is_singleton()) + lbl += fmt_.alternative_group_separator(); + else + lbl += fmt_.flag_separator(); + } + lbl += flags[i]; + sep = true; + } + if(surrAlt) lbl += fmt_.alternative_flags_postfix(); + } + else { + if(!p.label().empty()) { + lbl += fmt_.label_prefix() + + p.label() + + fmt_.label_postfix(); + } else if(!fmt_.empty_label().empty()) { + lbl += fmt_.label_prefix() + + fmt_.empty_label() + + fmt_.label_postfix(); + } else { + return ""; + } + } + + if(showopt) lbl += fmt_.optional_postfix(); + if(showrep) lbl += fmt_.repeat_postfix(); + + return lbl; + } + + + /***************************************************************//** + * + * @brief prints flags in one group in a merged fashion + * + *******************************************************************/ + string joined_label(const group& g, const context& cur) const + { + if(!fmt_.merge_alternative_flags_with_common_prefix() && + !fmt_.merge_joinable_with_common_prefix()) return ""; + + const bool flagsonly = std::all_of(g.begin(), g.end(), + [](const pattern& p){ + return p.is_param() && !p.as_param().flags().empty(); + }); + + if(!flagsonly) return ""; + + const bool showOpt = g.all_optional() && + !(ommitOutermostSurrounders_ && cur.outermost == &g); + + auto pfx = g.common_flag_prefix(); + if(pfx.empty()) return ""; + + const auto n = pfx.size(); + if(g.exclusive() && + fmt_.merge_alternative_flags_with_common_prefix()) + { + string lbl; + if(showOpt) lbl += fmt_.optional_prefix(); + lbl += pfx + fmt_.alternatives_prefix(); + bool first = true; + for(const auto& p : g) { + if(p.is_param()) { + if(first) + first = false; + else + lbl += fmt_.alternative_param_separator(); + lbl += p.as_param().flags().front().substr(n); + } + } + lbl += fmt_.alternatives_postfix(); + if(showOpt) lbl += fmt_.optional_postfix(); + return lbl; + } + //no alternatives, but joinable flags + else if(g.joinable() && + fmt_.merge_joinable_with_common_prefix()) + { + const bool allSingleChar = std::all_of(g.begin(), g.end(), + [&](const pattern& p){ + return p.is_param() && + p.as_param().flags().front().substr(n).size() == 1; + }); + + if(allSingleChar) { + string lbl; + if(showOpt) lbl += fmt_.optional_prefix(); + lbl += pfx; + for(const auto& p : g) { + if(p.is_param()) + lbl += p.as_param().flags().front().substr(n); + } + if(showOpt) lbl += fmt_.optional_postfix(); + return lbl; + } + } + + return ""; + } + + + /***************************************************************//** + * + * @return symbols with which to surround a group + * + *******************************************************************/ + std::pair + group_surrounders(const group& group, const context& cur) const + { + string prefix; + string postfix; + + const bool isOutermost = &group == cur.outermost; + if(isOutermost && ommitOutermostSurrounders_) + return {string{}, string{}}; + + if(group.exclusive()) { + if(group.all_optional()) { + prefix = fmt_.optional_prefix(); + postfix = fmt_.optional_postfix(); + if(group.all_flagless()) { + prefix += fmt_.label_prefix(); + postfix = fmt_.label_prefix() + postfix; + } + } else if(group.all_flagless()) { + prefix = fmt_.label_prefix(); + postfix = fmt_.label_postfix(); + } else if(!cur.is_singleton() || !isOutermost) { + prefix = fmt_.alternatives_prefix(); + postfix = fmt_.alternatives_postfix(); + } + } + else if(group.size() > 1 && + group.front().blocking() && !group.front().required()) + { + prefix = fmt_.optional_prefix(); + postfix = fmt_.optional_postfix(); + } + else if(group.size() > 1 && cur.is_alternative() && + &group != cur.outermost) + { + prefix = fmt_.group_prefix(); + postfix = fmt_.group_postfix(); + } + else if(!group.exclusive() && + group.joinable() && !cur.linestart) + { + prefix = fmt_.joinable_prefix(); + postfix = fmt_.joinable_postfix(); + } + + if(group.repeatable()) { + if(prefix.empty()) prefix = fmt_.group_prefix(); + prefix = fmt_.repeat_prefix() + prefix; + if(postfix.empty()) postfix = fmt_.group_postfix(); + postfix += fmt_.repeat_postfix(); + } + + return {std::move(prefix), std::move(postfix)}; + } + + + /***************************************************************//** + * + * @return symbol that separates members of a group + * + *******************************************************************/ + static string + group_separator(const group& group, const doc_formatting& fmt) + { + const bool only1ParamPerMember = std::all_of(group.begin(), group.end(), + [](const pattern& p) { return p.param_count() < 2; }); + + if(only1ParamPerMember) { + if(group.exclusive()) { + return fmt.alternative_param_separator(); + } else { + return fmt.param_separator(); + } + } + else { //there is at least one large group inside + if(group.exclusive()) { + return fmt.alternative_group_separator(); + } else { + return fmt.group_separator(); + } + } + } +}; + + + + +/*************************************************************************//** + * + * @brief generates parameter and group documentation from docstrings + * + * @details lazily evaluated + * + *****************************************************************************/ +class documentation +{ +public: + using string = doc_string; + using filter_function = std::function; + + documentation(const group& cli, + const doc_formatting& fmt = doc_formatting{}, + filter_function filter = param_filter{}) + : + cli_(cli), fmt_{fmt}, usgFmt_{fmt}, filter_{std::move(filter)} + { + //necessary, because we re-use "usage_lines" to generate + //labels for documented groups + usgFmt_.max_flags_per_param_in_usage( + usgFmt_.max_flags_per_param_in_doc()); + } + + documentation(const group& cli, filter_function filter) : + documentation{cli, doc_formatting{}, std::move(filter)} + {} + + documentation(const group& cli, const param_filter& filter) : + documentation{cli, doc_formatting{}, + [filter](const parameter& p) { return filter(p); }} + {} + + template + inline friend OStream& operator << (OStream& os, const documentation& p) { + p.write(os); + return os; + } + + string str() const { + std::ostringstream os; + write(os); + return os.str(); + } + + +private: + using dfs_traverser = group::depth_first_traverser; + + const group& cli_; + doc_formatting fmt_; + doc_formatting usgFmt_; + filter_function filter_; + enum class paragraph { param, group }; + + + /***************************************************************//** + * + * @brief writes documentation to output stream + * + *******************************************************************/ + template + void write(OStream& os) const { + detail::formatting_ostream fos(os); + fos.first_column(fmt_.first_column()); + fos.last_column(fmt_.last_column()); + fos.hanging_indent(0); + fos.paragraph_spacing(0); + fos.ignore_newline_chars(fmt_.ignore_newline_chars()); + print_doc(fos, cli_); + } + + + /***************************************************************//** + * + * @brief writes full documentation text for command line parameters + * + *******************************************************************/ + template + void print_doc(detail::formatting_ostream& os, + const group& cli, int indentLvl = 0) const + { + if(cli.empty()) return; + + //if group itself doesn't have docstring + if(cli.doc().empty()) { + for(const auto& p : cli) { + print_doc(os, p, indentLvl); + } + } + else { //group itself does have docstring + bool anyDocInside = std::any_of(cli.begin(), cli.end(), + [](const pattern& p){ return !p.doc().empty(); }); + + if(anyDocInside) { //group docstring as title, then child entries + handle_spacing(os, paragraph::group, indentLvl); + os << cli.doc(); + for(const auto& p : cli) { + print_doc(os, p, indentLvl + 1); + } + } + else { //group label first then group docstring + auto lbl = usage_lines(cli, usgFmt_) + .ommit_outermost_group_surrounders(true).str(); + + str::trim(lbl); + handle_spacing(os, paragraph::param, indentLvl); + print_entry(os, lbl, cli.doc()); + } + } + } + + + /***************************************************************//** + * + * @brief writes documentation text for one group or parameter + * + *******************************************************************/ + template + void print_doc(detail::formatting_ostream& os, + const pattern& ptrn, int indentLvl) const + { + if(ptrn.is_group()) { + print_doc(os, ptrn.as_group(), indentLvl); + } + else { + const auto& p = ptrn.as_param(); + if(!filter_(p)) return; + + handle_spacing(os, paragraph::param, indentLvl); + print_entry(os, param_label(p, fmt_), p.doc()); + } + } + + /***************************************************************//** + * + * @brief handles line and paragraph spacings + * + *******************************************************************/ + template + void handle_spacing(detail::formatting_ostream& os, + paragraph p, int indentLvl) const + { + const auto oldIndent = os.first_column(); + const auto indent = fmt_.first_column() + indentLvl * fmt_.indent_size(); + + if(os.total_non_blank_lines() < 1) { + os.first_column(indent); + return; + } + + if(os.paragraph_lines() > 1 || indent < oldIndent) { + os.wrap_hard(fmt_.paragraph_spacing() + 1); + } else { + os.wrap_hard(); + } + + if(p == paragraph::group) { + if(os.blank_lines_before_paragraph() < fmt_.paragraph_spacing()) { + os.wrap_hard(fmt_.paragraph_spacing() - os.blank_lines_before_paragraph()); + } + } + else if(os.blank_lines_before_paragraph() < fmt_.line_spacing()) { + os.wrap_hard(fmt_.line_spacing() - os.blank_lines_before_paragraph()); + } + os.first_column(indent); + } + + /*********************************************************************//** + * + * @brief prints one entry = label + docstring + * + ************************************************************************/ + template + void print_entry(detail::formatting_ostream& os, + const string& label, const string& docstr) const + { + if(label.empty()) return; + + os << label; + + if(!docstr.empty()) { + if(os.current_column() >= fmt_.doc_column()) os.wrap_soft(); + const auto oldcol = os.first_column(); + os.first_column(fmt_.doc_column()); + os << docstr; + os.first_column(oldcol); + } + } + + + /*********************************************************************//** + * + * @brief makes label for one parameter + * + ************************************************************************/ + static doc_string + param_label(const parameter& param, const doc_formatting& fmt) + { + doc_string lbl; + + if(param.repeatable()) lbl += fmt.repeat_prefix(); + + const auto& flags = param.flags(); + if(!flags.empty()) { + lbl += flags[0]; + const int n = std::min(fmt.max_flags_per_param_in_doc(), + int(flags.size())); + for(int i = 1; i < n; ++i) { + lbl += fmt.flag_separator() + flags[i]; + } + } + else if(!param.label().empty() || !fmt.empty_label().empty()) { + lbl += fmt.label_prefix(); + if(!param.label().empty()) { + lbl += param.label(); + } else { + lbl += fmt.empty_label(); + } + lbl += fmt.label_postfix(); + } + + if(param.repeatable()) lbl += fmt.repeat_postfix(); + + return lbl; + } + +}; + + + + +/*************************************************************************//** + * + * @brief stores strings for man page sections + * + *****************************************************************************/ +class man_page +{ +public: + //--------------------------------------------------------------- + using string = doc_string; + + //--------------------------------------------------------------- + /** @brief man page section */ + class section { + public: + using string = doc_string; + + section(string stitle, string scontent): + title_{std::move(stitle)}, content_{std::move(scontent)} + {} + + const string& title() const noexcept { return title_; } + const string& content() const noexcept { return content_; } + + private: + string title_; + string content_; + }; + +private: + using section_store = std::vector

; + +public: + //--------------------------------------------------------------- + using value_type = section; + using const_iterator = section_store::const_iterator; + using size_type = section_store::size_type; + + + //--------------------------------------------------------------- + man_page& + append_section(string title, string content) + { + sections_.emplace_back(std::move(title), std::move(content)); + return *this; + } + //----------------------------------------------------- + man_page& + prepend_section(string title, string content) + { + sections_.emplace(sections_.begin(), + std::move(title), std::move(content)); + return *this; + } + + + //--------------------------------------------------------------- + const section& operator [] (size_type index) const noexcept { + return sections_[index]; + } + + //--------------------------------------------------------------- + size_type size() const noexcept { return sections_.size(); } + + bool empty() const noexcept { return sections_.empty(); } + + + //--------------------------------------------------------------- + const_iterator begin() const noexcept { return sections_.begin(); } + const_iterator end() const noexcept { return sections_.end(); } + + + //--------------------------------------------------------------- + man_page& program_name(const string& n) { + progName_ = n; + return *this; + } + man_page& program_name(string&& n) { + progName_ = std::move(n); + return *this; + } + const string& program_name() const noexcept { + return progName_; + } + + + //--------------------------------------------------------------- + man_page& section_row_spacing(int rows) { + sectionSpc_ = rows > 0 ? rows : 0; + return *this; + } + int section_row_spacing() const noexcept { return sectionSpc_; } + + +private: + int sectionSpc_ = 1; + section_store sections_; + string progName_; +}; + + + +/*************************************************************************//** + * + * @brief generates man sections from command line parameters + * with sections "synopsis" and "options" + * + *****************************************************************************/ +inline man_page +make_man_page(const group& cli, + doc_string progname = "", + const doc_formatting& fmt = doc_formatting{}) +{ + man_page man; + man.append_section("SYNOPSIS", usage_lines(cli,progname,fmt).str()); + man.append_section("OPTIONS", documentation(cli,fmt).str()); + return man; +} + + + +/*************************************************************************//** + * + * @brief generates man page based on command line parameters + * + *****************************************************************************/ +template +OStream& +operator << (OStream& os, const man_page& man) +{ + bool first = true; + const auto secSpc = doc_string(man.section_row_spacing() + 1, '\n'); + for(const auto& section : man) { + if(!section.content().empty()) { + if(first) first = false; else os << secSpc; + if(!section.title().empty()) os << section.title() << '\n'; + os << section.content(); + } + } + os << '\n'; + return os; +} + + + + + +/*************************************************************************//** + * + * @brief printing methods for debugging command line interfaces + * + *****************************************************************************/ +namespace debug { + + +/*************************************************************************//** + * + * @brief prints first flag or value label of a parameter + * + *****************************************************************************/ +inline doc_string doc_label(const parameter& p) +{ + if(!p.flags().empty()) return p.flags().front(); + if(!p.label().empty()) return p.label(); + return doc_string{""}; +} + +inline doc_string doc_label(const group&) +{ + return ""; +} + +inline doc_string doc_label(const pattern& p) +{ + return p.is_group() ? doc_label(p.as_group()) : doc_label(p.as_param()); +} + + +/*************************************************************************//** + * + * @brief prints parsing result + * + *****************************************************************************/ +template +void print(OStream& os, const parsing_result& result) +{ + for(const auto& m : result) { + os << "#" << m.index() << " " << m.arg() << " -> "; + auto p = m.param(); + if(p) { + os << doc_label(*p) << " \t"; + if(m.repeat() > 0) { + os << (m.bad_repeat() ? "[bad repeat " : "[repeat ") + << m.repeat() << "]"; + } + if(m.blocked()) os << " [blocked]"; + if(m.conflict()) os << " [conflict]"; + os << '\n'; + } + else { + os << " [unmapped]\n"; + } + } + + for(const auto& m : result.missing()) { + auto p = m.param(); + if(p) { + os << doc_label(*p) << " \t"; + os << " [missing after " << m.after_index() << "]\n"; + } + } +} + + +/*************************************************************************//** + * + * @brief prints parameter label and some properties + * + *****************************************************************************/ +template +void print(OStream& os, const parameter& p) +{ + if(p.greedy()) os << '!'; + if(p.blocking()) os << '~'; + if(!p.required()) os << '['; + os << doc_label(p); + if(p.repeatable()) os << "..."; + if(!p.required()) os << "]"; +} + + +//------------------------------------------------------------------- +template +void print(OStream& os, const group& g, int level = 0); + + +/*************************************************************************//** + * + * @brief prints group or parameter; uses indentation + * + *****************************************************************************/ +template +void print(OStream& os, const pattern& param, int level = 0) +{ + if(param.is_group()) { + print(os, param.as_group(), level); + } + else { + os << doc_string(4*level, ' '); + print(os, param.as_param()); + } +} + + +/*************************************************************************//** + * + * @brief prints group and its contents; uses indentation + * + *****************************************************************************/ +template +void print(OStream& os, const group& g, int level) +{ + auto indent = doc_string(4*level, ' '); + os << indent; + if(g.blocking()) os << '~'; + if(g.joinable()) os << 'J'; + os << (g.exclusive() ? "(|\n" : "(\n"); + for(const auto& p : g) { + print(os, p, level+1); + } + os << '\n' << indent << (g.exclusive() ? "|)" : ")"); + if(g.repeatable()) os << "..."; + os << '\n'; +} + + +} // namespace debug +} //namespace clipp + +#endif +