mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 09:00:22 +00:00
LibCore: Support fine-grained failure behavior for ArgsParser
This commit is contained in:
parent
1dc31842cb
commit
250f8eccf3
Notes:
sideshowbarker
2024-07-18 12:39:16 +09:00
Author: https://github.com/gmta Commit: https://github.com/SerenityOS/serenity/commit/250f8eccf31 Pull-request: https://github.com/SerenityOS/serenity/pull/7896 Reviewed-by: https://github.com/awesomekling
4 changed files with 38 additions and 30 deletions
|
@ -30,11 +30,12 @@ ArgsParser::ArgsParser()
|
|||
add_option(m_show_help, "Display this message", "help", 0);
|
||||
}
|
||||
|
||||
bool ArgsParser::parse(int argc, char** argv, bool exit_on_failure)
|
||||
bool ArgsParser::parse(int argc, char* const* argv, FailureBehavior failure_behavior)
|
||||
{
|
||||
auto print_usage_and_exit = [this, argv, exit_on_failure] {
|
||||
print_usage(stderr, argv[0]);
|
||||
if (exit_on_failure)
|
||||
auto fail = [this, argv, failure_behavior] {
|
||||
if (failure_behavior == FailureBehavior::PrintUsage || failure_behavior == FailureBehavior::PrintUsageAndExit)
|
||||
print_usage(stderr, argv[0]);
|
||||
if (failure_behavior == FailureBehavior::Exit || failure_behavior == FailureBehavior::PrintUsageAndExit)
|
||||
exit(1);
|
||||
};
|
||||
|
||||
|
@ -76,7 +77,7 @@ bool ArgsParser::parse(int argc, char** argv, bool exit_on_failure)
|
|||
} else if (c == '?') {
|
||||
// There was an error, and getopt() has already
|
||||
// printed its error message.
|
||||
print_usage_and_exit();
|
||||
fail();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -98,7 +99,7 @@ bool ArgsParser::parse(int argc, char** argv, bool exit_on_failure)
|
|||
const char* arg = found_option->requires_argument ? optarg : nullptr;
|
||||
if (!found_option->accept_value(arg)) {
|
||||
warnln("\033[31mInvalid value for option \033[1m{}\033[22m, dude\033[0m", found_option->name_for_display());
|
||||
print_usage_and_exit();
|
||||
fail();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +117,7 @@ bool ArgsParser::parse(int argc, char** argv, bool exit_on_failure)
|
|||
}
|
||||
|
||||
if (total_values_required > values_left) {
|
||||
print_usage_and_exit();
|
||||
fail();
|
||||
return false;
|
||||
}
|
||||
int extra_values_to_distribute = values_left - total_values_required;
|
||||
|
@ -132,7 +133,7 @@ bool ArgsParser::parse(int argc, char** argv, bool exit_on_failure)
|
|||
|
||||
if (extra_values_to_distribute > 0) {
|
||||
// We still have too many values :(
|
||||
print_usage_and_exit();
|
||||
fail();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -142,7 +143,7 @@ bool ArgsParser::parse(int argc, char** argv, bool exit_on_failure)
|
|||
const char* value = argv[optind++];
|
||||
if (!arg.accept_value(value)) {
|
||||
warnln("Invalid value for argument {}", arg.name);
|
||||
print_usage_and_exit();
|
||||
fail();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +153,7 @@ bool ArgsParser::parse(int argc, char** argv, bool exit_on_failure)
|
|||
// Now let's show help if requested.
|
||||
if (m_show_help) {
|
||||
print_usage(stdout, argv[0]);
|
||||
if (exit_on_failure)
|
||||
if (failure_behavior == FailureBehavior::Exit || failure_behavior == FailureBehavior::PrintUsageAndExit)
|
||||
exit(0);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,13 @@ public:
|
|||
No
|
||||
};
|
||||
|
||||
enum class FailureBehavior {
|
||||
PrintUsageAndExit,
|
||||
PrintUsage,
|
||||
Exit,
|
||||
Ignore,
|
||||
};
|
||||
|
||||
struct Option {
|
||||
bool requires_argument { true };
|
||||
const char* help_string { nullptr };
|
||||
|
@ -46,7 +53,7 @@ public:
|
|||
Function<bool(const char*)> accept_value;
|
||||
};
|
||||
|
||||
bool parse(int argc, char** argv, bool exit_on_failure = true);
|
||||
bool parse(int argc, char* const* argv, FailureBehavior failure_behavior = FailureBehavior::PrintUsageAndExit);
|
||||
// *Without* trailing newline!
|
||||
void set_general_help(const char* help_string) { m_general_help = help_string; };
|
||||
void print_usage(FILE*, const char* argv0);
|
||||
|
|
|
@ -39,7 +39,7 @@ int Shell::builtin_alias(int argc, const char** argv)
|
|||
Core::ArgsParser parser;
|
||||
parser.add_positional_argument(arguments, "List of name[=values]'s", "name[=value]", Core::ArgsParser::Required::No);
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
if (arguments.is_empty()) {
|
||||
|
@ -96,7 +96,7 @@ int Shell::builtin_bg(int argc, const char** argv)
|
|||
return false;
|
||||
} });
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
if (job_id == -1 && !jobs.is_empty())
|
||||
|
@ -141,7 +141,7 @@ int Shell::builtin_type(int argc, const char** argv)
|
|||
parser.add_positional_argument(commands, "Command(s) to list info about", "command");
|
||||
parser.add_option(dont_show_function_source, "Do not show functions source.", "no-fn-source", 'f');
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
bool something_not_found = false;
|
||||
|
@ -207,7 +207,7 @@ int Shell::builtin_cd(int argc, const char** argv)
|
|||
Core::ArgsParser parser;
|
||||
parser.add_positional_argument(arg_path, "Path to change to", "path", Core::ArgsParser::Required::No);
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
String new_path;
|
||||
|
@ -258,7 +258,7 @@ int Shell::builtin_cdh(int argc, const char** argv)
|
|||
Core::ArgsParser parser;
|
||||
parser.add_positional_argument(index, "Index of the cd history entry (leave out for a list)", "index", Core::ArgsParser::Required::No);
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
if (index == -1) {
|
||||
|
@ -300,7 +300,7 @@ int Shell::builtin_dirs(int argc, const char** argv)
|
|||
parser.add_option(number_when_printing, "Number the directories in the stack when printing", "number", 'v');
|
||||
parser.add_positional_argument(paths, "Extra paths to put on the stack", "path", Core::ArgsParser::Required::No);
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
// -v implies -p
|
||||
|
@ -382,7 +382,7 @@ int Shell::builtin_export(int argc, const char** argv)
|
|||
Core::ArgsParser parser;
|
||||
parser.add_positional_argument(vars, "List of variable[=value]'s", "values", Core::ArgsParser::Required::No);
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
if (vars.is_empty()) {
|
||||
|
@ -427,7 +427,7 @@ int Shell::builtin_glob(int argc, const char** argv)
|
|||
Core::ArgsParser parser;
|
||||
parser.add_positional_argument(globs, "Globs to resolve", "glob");
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
for (auto& glob : globs) {
|
||||
|
@ -467,7 +467,7 @@ int Shell::builtin_fg(int argc, const char** argv)
|
|||
return false;
|
||||
} });
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
if (job_id == -1 && !jobs.is_empty())
|
||||
|
@ -538,7 +538,7 @@ int Shell::builtin_disown(int argc, const char** argv)
|
|||
return false;
|
||||
} });
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
if (job_ids.is_empty()) {
|
||||
|
@ -593,7 +593,7 @@ int Shell::builtin_jobs(int argc, const char** argv)
|
|||
parser.add_option(list, "List all information about jobs", "list", 'l');
|
||||
parser.add_option(show_pid, "Display the PID of the jobs", "pid", 'p');
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
Job::PrintStatusMode mode = Job::PrintStatusMode::Basic;
|
||||
|
@ -625,7 +625,7 @@ int Shell::builtin_popd(int argc, const char** argv)
|
|||
Core::ArgsParser parser;
|
||||
parser.add_option(should_not_switch, "Do not switch dirs", "no-switch", 'n');
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
bool should_switch = !should_not_switch;
|
||||
|
@ -792,7 +792,7 @@ int Shell::builtin_setopt(int argc, const char** argv)
|
|||
|
||||
#undef __ENUMERATE_SHELL_OPTION
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
#define __ENUMERATE_SHELL_OPTION(name, default_, description) \
|
||||
|
@ -815,7 +815,7 @@ int Shell::builtin_shift(int argc, const char** argv)
|
|||
Core::ArgsParser parser;
|
||||
parser.add_positional_argument(count, "Shift count", "count", Core::ArgsParser::Required::No);
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
if (count < 1)
|
||||
|
@ -880,7 +880,7 @@ int Shell::builtin_time(int argc, const char** argv)
|
|||
Core::ArgsParser parser;
|
||||
parser.add_positional_argument(args, "Command to execute with arguments", "command", Core::ArgsParser::Required::Yes);
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
AST::Command command;
|
||||
|
@ -907,7 +907,7 @@ int Shell::builtin_umask(int argc, const char** argv)
|
|||
Core::ArgsParser parser;
|
||||
parser.add_positional_argument(mask_text, "New mask (omit to get current mask)", "octal-mask", Core::ArgsParser::Required::No);
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
if (!mask_text) {
|
||||
|
@ -957,7 +957,7 @@ int Shell::builtin_wait(int argc, const char** argv)
|
|||
return false;
|
||||
} });
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
Vector<NonnullRefPtr<Job>> jobs_to_wait_for;
|
||||
|
@ -992,7 +992,7 @@ int Shell::builtin_unset(int argc, const char** argv)
|
|||
Core::ArgsParser parser;
|
||||
parser.add_positional_argument(vars, "List of variables", "variables", Core::ArgsParser::Required::Yes);
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), false))
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
for (auto& value : vars) {
|
||||
|
|
|
@ -58,7 +58,7 @@ int main(int argc, char** argv)
|
|||
outln("Event type can be one of: sample, context_switch, page_fault, kmalloc and kfree.");
|
||||
};
|
||||
|
||||
if (!args_parser.parse(argc, argv, false)) {
|
||||
if (!args_parser.parse(argc, argv, Core::ArgsParser::FailureBehavior::PrintUsage)) {
|
||||
print_types();
|
||||
exit(1);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue