From f92b5a516eddbdf33a69e95da6678eb9c9ef8c8c Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Tue, 4 Jun 2019 13:31:28 +0200 Subject: Add support for printing automatically generated help texts. --- getoptpp.hpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) (limited to 'getoptpp.hpp') diff --git a/getoptpp.hpp b/getoptpp.hpp index 8788dde..a2dca7f 100644 --- a/getoptpp.hpp +++ b/getoptpp.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include namespace dg { @@ -16,19 +17,22 @@ class Options { /// @param name name of the option /// @param has_arg kind of arguments that are used (no_argument, required_argument, optional_argument) /// @param val identifies the option (see getopt documentation) + /// @param help_text help text for this option /// @param handle lambda that is invoked when the option occures - void add(std::string const & name, int has_arg, int val, Handle handle) { - add(name, has_arg, nullptr, val, handle); + void add(std::string const & name, int has_arg, int val, std::string const & help_text, Handle handle) { + add(name, has_arg, nullptr, val, help_text, handle); } /// @param name name of the option /// @param has_arg kind of arguments that are used (no_argument, required_argument, optional_argument) /// @param flag pointer that is set after the option occured /// @param val value for the flag to be set + /// @param help_text help text for this option /// @param handle lambda that is invoked when the option occures - void add(std::string const & name, int has_arg, int* flag, int val, Handle handle) { + void add(std::string const & name, int has_arg, int* flag, int val, std::string const & help_text, Handle handle) { // create a new option from the args options.push_back({name.data(), has_arg, flag, val}); + help_texts.push_back(help_text); int index = val; // let val be the option's unique identifier if (flag != nullptr) { @@ -95,14 +99,59 @@ class Options { // remove terminating option options.pop_back(); assert(options.size() == handles.size()); + assert(options.size() == help_texts.size()); return 0; } const std::vector arguments() const { return args; } + void help() { + std::size_t width = 0; + for(auto const & opt : options) { + if(opt.name == nullptr) { + continue; // skip terminating option + } + width = std::max(width, std::strlen(opt.name) + (opt.has_arg != no_argument ? 0 : 3)); + } + width += 1; + + int index = 0; + for(auto const & help_text : help_texts) { + auto const & opt = options.at(index); + std::string args; + switch(opt.has_arg) { + case required_argument: + args = ""; + break; + case optional_argument: + args = "[x]"; + break; + case no_argument: + default: + break; + } + + std::string padding; + std::size_t pad_size = width - (std::strlen(opt.name) + args.size()); + padding.append(pad_size, ' '); + if(opt.val >= 33 && opt.val <= 126) + { + std::cout << " -" << static_cast(opt.val) << ", --" << opt.name << " " << args << padding; + } + else + { + std::cout << " --" << opt.name << " " << args << padding; + } + + std::cout << help_text << std::endl; + ++index; + } + } + private: std::size_t num_flags{}; std::vector