summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibCore/ArgsParser.cpp
diff options
context:
space:
mode:
authorBen Wiederhake <BenWiederhake.GitHub@gmx.de>2021-10-23 13:22:06 +0200
committerLinus Groh <mail@linusgroh.de>2021-11-01 21:12:58 +0100
commit0372f051e90ece2044ab99b89803008cfc605e93 (patch)
tree71cea43112a4586d172fe550a0d5befcebd8996f /Userland/Libraries/LibCore/ArgsParser.cpp
parentd2f9fee4abd2535beb5aef3d3e4e687ea7ddb967 (diff)
downloadserenity-0372f051e90ece2044ab99b89803008cfc605e93.zip
LibCore: Enable emitting markdown from ArgsParser
ArgsParser will now automatically look for an environment variable 'ARGSPARSER_EMIT_MARKDOWN', and if it is set to exactly the string "1" (i.e. mere presence or values like "ON" or "yes" are not enough), then ArgsParser will emit a Markdown-formatted help message, instead of the regular help message designed for consumption through a terminal.
Diffstat (limited to 'Userland/Libraries/LibCore/ArgsParser.cpp')
-rw-r--r--Userland/Libraries/LibCore/ArgsParser.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/Userland/Libraries/LibCore/ArgsParser.cpp b/Userland/Libraries/LibCore/ArgsParser.cpp
index 139eba3439..31ef98803d 100644
--- a/Userland/Libraries/LibCore/ArgsParser.cpp
+++ b/Userland/Libraries/LibCore/ArgsParser.cpp
@@ -174,6 +174,16 @@ bool ArgsParser::parse(int argc, char* const* argv, FailureBehavior failure_beha
void ArgsParser::print_usage(FILE* file, const char* argv0)
{
+ char const* env_preference = getenv("ARGSPARSER_EMIT_MARKDOWN");
+ if (env_preference != nullptr && env_preference[0] == '1' && env_preference[1] == 0) {
+ print_usage_markdown(file, argv0);
+ } else {
+ print_usage_terminal(file, argv0);
+ }
+}
+
+void ArgsParser::print_usage_terminal(FILE* file, const char* argv0)
+{
out(file, "Usage:\n\t\033[1m{}\033[0m", argv0);
for (auto& opt : m_options) {
@@ -243,6 +253,79 @@ void ArgsParser::print_usage(FILE* file, const char* argv0)
}
}
+void ArgsParser::print_usage_markdown(FILE* file, const char* argv0)
+{
+ outln(file, "## Name\n\n{}", argv0);
+
+ out(file, "\n## Synopsis\n\n```sh\n$ {}", argv0);
+ for (auto& opt : m_options) {
+ if (opt.long_name != nullptr && (!strcmp(opt.long_name, "help") || !strcmp(opt.long_name, "version")))
+ continue;
+ if (opt.requires_argument)
+ out(file, " [{} {}]", opt.name_for_display(), opt.value_name);
+ else
+ out(file, " [{}]", opt.name_for_display());
+ }
+ for (auto& arg : m_positional_args) {
+ bool required = arg.min_values > 0;
+ bool repeated = arg.max_values > 1;
+
+ if (required && repeated)
+ out(file, " <{}...>", arg.name);
+ else if (required && !repeated)
+ out(file, " <{}>", arg.name);
+ else if (!required && repeated)
+ out(file, " [{}...]", arg.name);
+ else if (!required && !repeated)
+ out(file, " [{}]", arg.name);
+ }
+ outln(file, "\n```");
+
+ if (m_general_help != nullptr && m_general_help[0] != '\0') {
+ outln(file, "\n## Description\n\n{}", m_general_help);
+ }
+
+ if (!m_options.is_empty())
+ outln(file, "\n## Options:\n");
+ for (auto& opt : m_options) {
+ auto print_argument = [&]() {
+ if (opt.value_name != nullptr) {
+ if (opt.requires_argument)
+ out(file, " {}", opt.value_name);
+ else
+ out(file, " [{}]", opt.value_name);
+ }
+ };
+ out(file, "* ");
+ if (opt.short_name != '\0') {
+ out(file, "`-{}", opt.short_name);
+ print_argument();
+ out(file, "`");
+ }
+ if (opt.short_name != '\0' && opt.long_name != nullptr)
+ out(file, ", ");
+ if (opt.long_name != nullptr) {
+ out(file, "`--{}", opt.long_name);
+ print_argument();
+ out(file, "`");
+ }
+
+ if (opt.help_string != nullptr)
+ out(file, ": {}", opt.help_string);
+ outln(file);
+ }
+
+ if (!m_positional_args.is_empty())
+ outln(file, "\n## Arguments:\n");
+
+ for (auto& arg : m_positional_args) {
+ out(file, "* `{}`", arg.name);
+ if (arg.help_string != nullptr)
+ out(file, ": {}", arg.help_string);
+ outln(file);
+ }
+}
+
void ArgsParser::print_version(FILE* file)
{
outln(file, Core::Version::SERENITY_VERSION);