commit fc5fd6d67d7b63502daeaad8e19df559d782a209
parent c45774b431a3c3f91c0f6e2400265cb16395ccf1
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Sat, 8 Jun 2024 20:42:51 +0200
Add --usage option
Diffstat:
M | args.hpp | | | 75 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 75 insertions(+), 0 deletions(-)
diff --git a/args.hpp b/args.hpp
@@ -104,6 +104,10 @@ class Parser {
help_entries.emplace_back(nullptr, "Give this help list", false);
help_entries.back().push("help");
help_entries.back().push('?');
+
+ help_entries.emplace_back(nullptr, "Give a short usage message",
+ false);
+ help_entries.back().push("usage");
}
int parse(int argc, char *argv[], void *input) {
@@ -161,6 +165,11 @@ class Parser {
help(argv[0]);
}
+ if (opt_s == "usage") {
+ if (eq) goto excess;
+ usage(argv[0]);
+ }
+
const int key = trie.get(opt_s);
if (!key) goto unknown;
@@ -364,6 +373,72 @@ class Parser {
exit(0);
}
+ void usage(const char *name) const {
+ static const std::size_t limit = 60;
+ static std::size_t count = 0;
+
+ static const auto print = [](const std::string &message) {
+ if (count + size(message) > limit) {
+ std::cout << "\n ";
+ count = 6;
+ }
+ std::cout << message;
+ count += size(message);
+ };
+
+ std::string message = std::format("Usage: {}", name);
+
+ message += " [-";
+ for (int i = 0; true; i++) {
+ const auto &opt = argp->options[i];
+ if (!opt.name && !opt.key) break;
+ if (!std::isprint(opt.key)) continue;
+ if (opt.arg) continue;
+
+ message += (char)opt.key;
+ }
+ message += "?]";
+
+ std::cout << message;
+ count = size(message);
+
+ for (int i = 0; true; i++) {
+ const auto &opt = argp->options[i];
+ if (!opt.name && !opt.key) break;
+ if (!std::isprint(opt.key)) continue;
+ if (!opt.arg) continue;
+
+ if (opt.options & Option::ARG_OPTIONAL) {
+ print(std::format(" [-{}[{}]]", (char)opt.key, opt.arg));
+ } else {
+ print(std::format(" [-{} {}]", (char)opt.key, opt.arg));
+ }
+ }
+
+ for (int i = 0; true; i++) {
+ const auto &opt = argp->options[i];
+ if (!opt.name && !opt.key) break;
+ if (!opt.name) continue;
+
+ if (!opt.arg) print(std::format(" [--{}]", opt.name));
+ else {
+ if (opt.options & Option::ARG_OPTIONAL) {
+ print(std::format(" [--{}[={}]]", opt.name, opt.arg));
+ } else {
+ print(std::format(" [--{}={}]", opt.name, opt.arg));
+ }
+ }
+ }
+
+ print(" [--help]");
+ print(" [--usage] ");
+ if (argp->doc) print(argp->doc);
+
+ std::cout << std::endl;
+
+ exit(0);
+ }
+
const argp_t *argp;
std::unordered_map<int, const option_t *> options;