diff --git a/include/blt/parse/argparse.h b/include/blt/parse/argparse.h index 7a6d453..79a56db 100755 --- a/include/blt/parse/argparse.h +++ b/include/blt/parse/argparse.h @@ -77,7 +77,7 @@ namespace blt } // returns the first flag that starts with '--' otherwise return the first '-' flag - [[nodiscard]] std::string getFirstFullFlag(); + [[nodiscard]] std::string getFirstFullFlag() const; }; class arg_nargs_t @@ -127,13 +127,22 @@ namespace blt std::string a_version{}; std::string a_metavar{}; bool a_required = true; + bool a_disable_help = false; }; class arg_builder { + private: arg_properties_t properties; public: - arg_builder(const arg_vector_t& flags): properties(flags) + explicit arg_builder(const arg_vector_t& flags): properties(flags) + {} + + arg_builder(const std::initializer_list& flags): properties(flags) + {} + + template + explicit arg_builder(string_args... flags): properties({flags...}) {} inline arg_properties_t build() @@ -171,6 +180,12 @@ namespace blt return *this; } + inline arg_builder& disableHelp() + { + properties.a_disable_help = true; + return *this; + } + inline arg_builder& setHelp(const std::string& help) { properties.a_help = help; @@ -203,7 +218,7 @@ namespace blt std::vector args; size_t currentIndex = 0; public: - arg_tokenizer(std::vector args): args(std::move(args)) + explicit arg_tokenizer(std::vector args): args(std::move(args)) {} // returns the current arg @@ -265,11 +280,11 @@ namespace blt friend arg_parse; private: // stores dest value not the flag/name! - HASHSET found_args; + HASHSET found_args; std::vector unrecognized_args; public: std::string program_name; - HASHMAP data; + HASHMAP data; inline arg_data_t& operator[](const std::string& key) { @@ -295,9 +310,12 @@ namespace blt return data.find(key) != data.end(); } } loaded_args; - + + bool help_disabled = false; + std::string help_inclusion; private: static std::string getMetavar(const arg_properties_t* const& arg); + static std::string getFlagHelp(const arg_properties_t* const& arg); static bool takesArgs(const arg_properties_t* const& arg); @@ -311,7 +329,7 @@ namespace blt // expects that the current flag has already been consumed (advanced past), leaves tokenizer in a state where the next element is 'current' bool consumeArguments( arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t& properties, std::vector& v_out - ) const; + ) const; void handlePositionalArgument(arg_tokenizer& tokenizer, size_t& last_pos); @@ -319,6 +337,8 @@ namespace blt void processFlag(arg_tokenizer& tokenizer, const std::string& flag); + void handleFlag(arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t* properties); + public: template @@ -398,6 +418,11 @@ namespace blt user_args.max_line_length = size; } + inline void setHelpExtras(std::string str) + { + help_inclusion = std::move(str); + } + static std::string filename(const std::string& path); ~arg_parse() diff --git a/libraries/parallel-hashmap b/libraries/parallel-hashmap index 93201da..77cab81 160000 --- a/libraries/parallel-hashmap +++ b/libraries/parallel-hashmap @@ -1 +1 @@ -Subproject commit 93201da2ba5a6aba0a6e57ada64973555629b3e3 +Subproject commit 77cab8192a879e5d27188f97e8f2080dd7e36ca8 diff --git a/src/blt/parse/argparse.cpp b/src/blt/parse/argparse.cpp index 09ba022..70dec5f 100755 --- a/src/blt/parse/argparse.cpp +++ b/src/blt/parse/argparse.cpp @@ -68,7 +68,7 @@ namespace blt name = str; } - std::string arg_vector_t::getFirstFullFlag() + std::string arg_vector_t::getFirstFullFlag() const { // assign flag so it always exists, will be first '-' flag if we fail to find a '--' flag std::string flag = flags[0]; @@ -156,7 +156,7 @@ namespace blt bool arg_parse::consumeArguments( arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t& properties, std::vector& v_out - ) const + ) const { switch (properties.a_nargs.flags) { @@ -231,8 +231,26 @@ namespace blt loaded_args.unrecognized_args.push_back(tokenizer.get()); else { - loaded_args.data[user_args.name_associations[index]->a_dest] = tokenizer.get(); - loaded_args.found_args.insert(user_args.name_associations[index]->a_dest); + bool found = false; + for (const auto& pos_properties : user_args.name_associations) + { + const auto& flag = tokenizer.get(); + if (pos_properties->a_flags.contains(flag)) + { + tokenizer.advance(); + handleFlag(tokenizer, flag, pos_properties); + found = true; + break; + } + } + if (!found) + { + const auto& arg_property = user_args.name_associations[index]; + if (arg_property->a_disable_help) + help_disabled = true; + loaded_args.data[arg_property->a_dest] = tokenizer.get(); + loaded_args.found_args.insert(arg_property->a_dest); + } } tokenizer.advance(); } @@ -282,6 +300,11 @@ namespace blt const auto* const properties = user_args.flag_associations.at(flag); + handleFlag(tokenizer, flag, properties); + } + + void arg_parse::handleFlag(arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t* properties) + { if (properties->a_dest.empty()) { loaded_args.unrecognized_args.push_back(flag); @@ -291,6 +314,9 @@ namespace blt loaded_args.found_args.insert(dest); + if (properties->a_disable_help) + help_disabled = true; + switch (properties->a_action) { case arg_action_t::HELP: @@ -438,6 +464,8 @@ namespace blt void arg_parse::printHelp() const { + if (help_disabled) + return; if (!user_args.prefix.empty()) { std::cout << "\n"; @@ -452,7 +480,8 @@ namespace blt { if (!arg->a_flags.isFlag()) max_length = std::max(arg->a_flags.name.size(), max_length); - else { + else + { auto tmp = getFlagHelp(arg); max_length = std::max(tmp.size(), max_length); } @@ -495,7 +524,9 @@ namespace blt void arg_parse::printUsage() const { - std::string usage = "Usage: " + filename(loaded_args.program_name) + " "; + if (help_disabled) + return; + std::string usage = "Usage: " + filename(loaded_args.program_name) + " " + help_inclusion + " "; std::cout << usage; size_t current_line_length = 0; @@ -566,7 +597,7 @@ namespace blt } tmp += ", "; } - tmp = tmp.substr(0, tmp.size()-2); + tmp = tmp.substr(0, tmp.size() - 2); return tmp; } } \ No newline at end of file