//----------------------------------------------------------------------------- // optionparser.h -- A Header-Only commandline argument parser // Author: Luke de Oliveira // License: MIT //----------------------------------------------------------------------------- #ifndef OPTIONPARSER_H_ #define OPTIONPARSER_H_ #include #include #include #include #include #include #include #include #include const std::string ARGS_END = "- "; namespace optionparser { enum StorageMode { STORE_TRUE, STORE_VALUE, STORE_MULT_VALUES }; enum OptionType { LONG_OPT = 0, SHORT_OPT, POSITIONAL_OPT, EMPTY_OPT }; struct DictionaryEntry { unsigned int pos; std::string name; }; struct Option { Option() {} void help_doc() { std::string h = " "; if (m_long_flag != "") { h += m_long_flag; if (m_short_flag != "") { h += ", "; } } if (m_short_flag != "") { h += m_short_flag; } printf("%-25s%s\n", h.c_str(), m_help.c_str()); } bool &found() { return m_found; } Option &required(bool req) { m_required = req; return *this; } bool &required() { return m_required; } std::string &short_flag() { return m_short_flag; } std::string &long_flag() { return m_long_flag; } std::string &pos_flag() { return m_pos_flag; } std::string m_short_flag = "", m_long_flag = "", m_pos_flag = ""; StorageMode &mode() { return m_mode; } Option &mode(const StorageMode &mode) { m_mode = mode; return *this; } std::string &help() { return m_help; } Option &help(const std::string &help) { m_help = help; return *this; } std::string &dest() { return m_dest; } Option &dest(const std::string &dest) { m_dest = dest; return *this; } std::string &default_value() { return m_default_value; } Option &default_value(const std::string &default_value) { m_default_value = default_value; return *this; } Option &default_value(const char *default_value) { m_default_value = std::string(default_value); return *this; } template Option &default_value(const T &default_value) { m_default_value = std::to_string(default_value); return *this; } bool m_found = false; bool m_required = false; StorageMode m_mode = STORE_TRUE; std::string m_help = ""; std::string m_dest = ""; std::string m_default_value = ""; static OptionType get_type(std::string opt); static std::string get_destination(std::string opt1, std::string opt2, OptionType ft, OptionType st); }; //---------------------------------------------------------------------------- std::string remove_character(std::string str, const char c) { // dummy way to remove -- and - from args auto pos = str.find("--"); if (pos == 0) { str.erase(0, 2); } pos = str.find('-'); if (pos == 0) { str.erase(0, 1); } return str; } typedef std::map> Archive; typedef std::map Dictionary; OptionType Option::get_type(std::string opt) { if (opt == "") { return OptionType::EMPTY_OPT; } if (opt[0] == '-') { if (opt.size() == 2) { return OptionType::SHORT_OPT; } else { return OptionType::LONG_OPT; } } return OptionType::POSITIONAL_OPT; } std::string Option::get_destination(std::string first_option, std::string second_option, OptionType first_opt_type, OptionType second_opt_type) { std::string dest; if (first_opt_type == OptionType::LONG_OPT) { dest = remove_character(first_option, '-'); } else if (second_opt_type == OptionType::LONG_OPT) { dest = remove_character(second_option, '-'); } else { if (first_opt_type == OptionType::SHORT_OPT) { dest = remove_character(first_option, '-') + "_option"; } else if (second_opt_type == OptionType::SHORT_OPT) { dest = remove_character(second_option, '-') + "_option"; } else { if (first_opt_type == OptionType::POSITIONAL_OPT) { dest = first_option; } else if (second_opt_type == OptionType::POSITIONAL_OPT) { dest = second_option; } } } return dest; } //----------------------------------------------------------------------------- // OptionParser Class //----------------------------------------------------------------------------- class OptionParser { public: OptionParser(std::string description = "", bool create_help = true) : m_options(0), m_description(description) { if (create_help) { add_option("--help", "-h").help("Display this help message and exit."); } } ~OptionParser() = default; void eat_arguments(unsigned int argc, char const *argv[]); Option &add_option(std::string first_option, std::string second_option = ""); template T get_value(std::string key); void help(); private: Option &add_option_internal(std::string longoption, std::string shortoption); void error(const std::string &e); Archive m_values; std::vector