summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example.cpp81
-rw-r--r--getoptpp.hpp55
2 files changed, 101 insertions, 35 deletions
diff --git a/example.cpp b/example.cpp
index e273c2f..bd94585 100644
--- a/example.cpp
+++ b/example.cpp
@@ -6,38 +6,55 @@ int main(int argc, char* argv[]) {
int verbose_flag;
dg::Options opt;
- opt.add("verbose", no_argument, &verbose_flag, 1, [&]() {
- std::cout << "verbose: " << verbose_flag << "\n";
- return 0;
- });
- opt.add("brief", no_argument, &verbose_flag, 0, [&]() {
- std::cout << "brief: " << verbose_flag << "\n";
- return 0;
- });
- opt.add("add", no_argument, 'a', [&]() {
- std::cout << "add\n";
- return 0;
- });
- opt.add("append", no_argument, 'b', [&]() {
- std::cout << "append\n";
- return 0;
- });
- opt.add("delete", required_argument, 'd', [&]() {
- std::cout << "delete: " << optarg << "\n";
- return 0;
- });
- opt.add("create", required_argument, 'c', [&]() {
- std::cout << "create: " << optarg << "\n";
- return 0;
- });
- opt.add("file", required_argument, 'f', [&]() {
- std::cout << "file: " << optarg << "\n";
- return 0;
- });
- opt.add("help", no_argument, '?', [&]() {
- std::cout << "usage stuff\n";
- return 0;
- });
+ opt.add("verbose", no_argument, &verbose_flag, 1,
+ "Be verbose.",
+ [&]() {
+ std::cout << "verbose: " << verbose_flag << "\n";
+ return 0;
+ });
+ opt.add("brief", no_argument, &verbose_flag, 0,
+ "Be brief.",
+ [&]() {
+ std::cout << "brief: " << verbose_flag << "\n";
+ return 0;
+ });
+ opt.add("add", no_argument, 'a',
+ "Add an entry.",
+ [&]() {
+ std::cout << "add\n";
+ return 0;
+ });
+ opt.add("append", no_argument, 'b',
+ "Append an entry.",
+ [&]() {
+ std::cout << "append\n";
+ return 0;
+ });
+ opt.add("delete", optional_argument, 'd',
+ "Delete an entry.",
+ [&]() {
+ std::cout << "delete: " << optarg << "\n";
+ return 0;
+ });
+ opt.add("create", required_argument, 'c',
+ "Create an entry.",
+ [&]() {
+ std::cout << "create: " << optarg << "\n";
+ return 0;
+ });
+ opt.add("file", required_argument, 'f',
+ "Some file argument.",
+ [&]() {
+ std::cout << "file: " << optarg << "\n";
+ return 0;
+ });
+ opt.add("help", no_argument, 'h',
+ "Print this help text.",
+ [&]() {
+ std::cout << "usage stuff\n";
+ opt.help();
+ return 0;
+ });
opt.process(argc, argv);
for(auto const &arg : opt.arguments())
diff --git a/getoptpp.hpp b/getoptpp.hpp
index 8788dde..a2dca7f 100644
--- a/getoptpp.hpp
+++ b/getoptpp.hpp
@@ -5,6 +5,7 @@
#include <vector>
#include <unordered_map>
#include <string>
+#include <cstring>
#include <getopt.h>
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<std::string> 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 = "<x>";
+ 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<char>(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<option> options{};
+ std::vector<std::string> help_texts{};
std::vector<std::string> args;
std::unordered_map<int, Handle> handles{};
};