bool terminal = false;
};
class help_entry_t {
public:
help_entry_t(const char *arg, const char *message)
: m_arg(arg), m_message(message) {}
void push(char sh) { m_opt_short.push_back(sh); }
void push(const char *lg) { m_opt_long.push_back(lg); }
const auto arg() const { return m_arg; }
const auto message() const { return m_message; }
const auto &opt_short() const { return m_opt_short; }
const auto &opt_long() const { return m_opt_long; }
bool operator<(const help_entry_t &rhs) const {
if (m_opt_long.empty() && rhs.m_opt_long.empty())
return m_opt_short.front() < rhs.m_opt_short.front();
if (m_opt_long.empty())
return m_opt_short.front() <= rhs.m_opt_long.front()[0];
if (rhs.m_opt_long.empty())
return m_opt_long.front()[0] <= rhs.m_opt_short.front();
return std::strcmp(m_opt_long.front(), rhs.m_opt_long.front()) < 0;
}
private:
const char *m_arg = nullptr;
const char *m_message = nullptr;
std::vector<char> m_opt_short;
std::vector<const char *> m_opt_long;
};
void help(const char *name) {
std::cout << std::format("Usage: {} [OPTIONS...] {}\n\n", name,
argp->doc ? argp->doc : "");
for (const auto &entry : help_entries) {
std::size_t count = 0;
bool prev = false;
std::cout << " ";
for (const char c : entry.opt_short()) {
if (!prev) prev = true;
else
std::cout << ", ", count += 2;
const std::string message = std::format("-{}", c);
std::cout << message;
count += size(message);
}
if (!prev) std::cout << " ", count += 4;
for (const auto l : entry.opt_long()) {
if (!prev) prev = true;
else
std::cout << ", ", count += 2;
std::string message = std::format("--{}", l);
if (entry.arg()) message += std::format("[={}]", entry.arg());
std::cout << message;
count += size(message);
}
static const std::size_t limit = 30;
if (count < limit) std::cout << std::string(limit - count, ' ');
if (entry.message()) {
std::cout << std::format(" {}", entry.message());
}
std::cout << std::endl;
}
exit(0);
}
const argp_t *argp;
std::unordered_map<int, const option_t *> options;
std::vector<help_entry_t> help_entries;
trie_t trie;
};