1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-28 08:07:44 +00:00

Userland+AK: Stop using getopt() for ArgsParser

This commit moves the implementation of getopt into AK, and converts its
API to understand and use StringView instead of char*.
Everything else is caught in the crossfire of making
Option::accept_value() take a StringView instead of a char const*.

With this, we must now pass a Span<StringView> to ArgsParser::parse(),
applications using LibMain are unaffected, but anything not using that
or taking its own argc/argv has to construct a Vector<StringView> for
this method.
This commit is contained in:
Ali Mohammad Pur 2023-02-21 15:14:41 +03:30 committed by Ali Mohammad Pur
parent b2b851b361
commit db886fe18b
43 changed files with 673 additions and 584 deletions

View file

@ -31,15 +31,15 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
"preserve",
'p',
"attributes",
[&preserve](char const* s) {
if (!s) {
[&preserve](StringView s) {
if (s.is_empty()) {
preserve = Core::DeprecatedFile::PreserveMode::Permissions | Core::DeprecatedFile::PreserveMode::Ownership | Core::DeprecatedFile::PreserveMode::Timestamps;
return true;
}
bool values_ok = true;
StringView { s, strlen(s) }.for_each_split_view(',', SplitBehavior::Nothing, [&](StringView value) {
s.for_each_split_view(',', SplitBehavior::Nothing, [&](StringView value) {
if (value == "mode"sv) {
preserve |= Core::DeprecatedFile::PreserveMode::Permissions;
} else if (value == "ownership"sv) {

View file

@ -169,19 +169,19 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
if (selected_options_count == 0) {
warnln("cut: you must specify a list of bytes, or fields");
args_parser.print_usage(stderr, arguments.strings[0].characters_without_null_termination());
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}
if (selected_options_count > 1) {
warnln("cut: you must specify only one of bytes, or fields");
args_parser.print_usage(stderr, arguments.strings[0].characters_without_null_termination());
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}
if (delimiter.length() != 1) {
warnln("cut: the delimiter must be a single character");
args_parser.print_usage(stderr, arguments.strings[0].characters_without_null_termination());
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}
@ -200,7 +200,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
auto expansion_successful = expand_list(ranges_list, ranges_vector);
if (!expansion_successful) {
args_parser.print_usage(stderr, arguments.strings[0].characters_without_null_termination());
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}

View file

@ -66,8 +66,7 @@ ErrorOr<void> parse_args(Main::Arguments arguments, Vector<DeprecatedString>& fi
"time",
0,
"time-type",
[&du_option](auto const* option_ptr) {
StringView option { option_ptr, strlen(option_ptr) };
[&du_option](StringView option) {
if (option == "mtime"sv || option == "modification"sv)
du_option.time_type = DuOption::TimeType::Modification;
else if (option == "ctime"sv || option == "status"sv || option == "use"sv)
@ -87,7 +86,7 @@ ErrorOr<void> parse_args(Main::Arguments arguments, Vector<DeprecatedString>& fi
nullptr,
'k',
nullptr,
[&du_option](auto const*) {
[&du_option](StringView) {
du_option.block_size = 1024;
return true;
}

View file

@ -83,7 +83,7 @@ ErrorOr<int> serenity_main(Main::Arguments args)
.long_name = "regexp",
.short_name = 'e',
.value_name = "Pattern",
.accept_value = [&](auto* str) {
.accept_value = [&](StringView str) {
patterns.append(str);
return true;
},
@ -97,7 +97,7 @@ ErrorOr<int> serenity_main(Main::Arguments args)
.argument_mode = Core::ArgsParser::OptionArgumentMode::Required,
.help_string = "Action to take for binary files ([binary], text, skip)",
.long_name = "binary-mode",
.accept_value = [&](auto* str) {
.accept_value = [&](StringView str) {
if ("text"sv == str)
binary_mode = BinaryFileMode::Text;
else if ("binary"sv == str)
@ -135,7 +135,7 @@ ErrorOr<int> serenity_main(Main::Arguments args)
.long_name = "color",
.short_name = 0,
.value_name = "WHEN",
.accept_value = [&](auto* str) {
.accept_value = [&](StringView str) {
if ("never"sv == str)
colored_output = false;
else if ("always"sv == str)

View file

@ -45,8 +45,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
"monochrome",
'm',
nullptr,
[](char const* s) {
VERIFY(s == nullptr);
[](StringView s) {
VERIFY(s.is_empty());
use_color = false;
return true;
},

View file

@ -227,7 +227,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
return 0;
}
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}

View file

@ -33,7 +33,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
args_parser.parse(arguments);
if (paths.size() < 2) {
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}

View file

@ -35,12 +35,12 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
"body-numbering",
'b',
"style",
[&number_style](char const* s) {
if (!strcmp(s, "t"))
[&number_style](StringView s) {
if (s == "t"sv)
number_style = NumberNonEmptyLines;
else if (!strcmp(s, "a"))
else if (s == "a"sv)
number_style = NumberAllLines;
else if (!strcmp(s, "n"))
else if (s == "n"sv)
number_style = NumberNoLines;
else
return false;

View file

@ -63,7 +63,7 @@ ErrorOr<int> serenity_main(Main::Arguments args)
auto number = StringView { omit_pid_value, strlen(omit_pid_value) }.to_uint();
if (!number.has_value()) {
warnln("Invalid value for -o");
args_parser.print_usage(stderr, args.argv[0]);
args_parser.print_usage(stderr, args.strings[0]);
return 1;
}
pid_to_omit = number.value();

View file

@ -172,8 +172,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
.long_name = "header",
.short_name = 'H',
.value_name = "key:value",
.accept_value = [&](auto* s) {
StringView header { s, strlen(s) };
.accept_value = [&](StringView header) {
auto split = header.find(':');
if (!split.has_value())
return false;
@ -186,8 +185,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
.long_name = "auth",
.short_name = 'u',
.value_name = "username:password",
.accept_value = [&](auto* s) {
StringView input { s, strlen(s) };
.accept_value = [&](StringView input) {
if (!input.contains(':'))
return false;

View file

@ -72,7 +72,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
}
if (pid_argument.is_empty() && command.is_empty() && !all_processes) {
args_parser.print_usage(stdout, arguments.argv[0]);
args_parser.print_usage(stdout, arguments.strings[0]);
print_types();
return 0;
}

View file

@ -242,7 +242,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
args_parser.parse(arguments);
if (arguments.argc < 3) {
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
return Error::from_errno(EINVAL);
}

View file

@ -32,7 +32,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
args_parser.parse(arguments);
if (!force && paths.is_empty()) {
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}

View file

@ -326,7 +326,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
.help_string = "Show progress with OSC 9 (true, false)",
.long_name = "show-progress",
.short_name = 'p',
.accept_value = [&](auto* str) {
.accept_value = [&](StringView str) {
if ("true"sv == str)
print_progress = true;
else if ("false"sv == str)

View file

@ -108,8 +108,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
nullptr,
't',
"format",
[&string_offset_format](char const* s) {
StringView value = { s, strlen(s) };
[&string_offset_format](StringView value) {
if (value == "d") {
string_offset_format = StringOffsetFormat::Decimal;
} else if (value == "o") {

View file

@ -69,7 +69,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
}
if (syscall_arguments.is_empty()) {
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
exit(1);
}

View file

@ -107,7 +107,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
args_parser.parse(arguments);
if (!show_all && variables.is_empty()) {
args_parser.print_usage(stdout, arguments.argv[0]);
args_parser.print_usage(stdout, arguments.strings[0]);
return 1;
}

View file

@ -150,7 +150,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
args_parser.parse(arguments);
if (arguments.strings.size() <= 2 && arguments.strings[1] != "list"sv) {
args_parser.print_usage_terminal(stderr, arguments.argv[0]);
args_parser.print_usage_terminal(stderr, arguments.strings[0]);
return 0;
}

View file

@ -25,8 +25,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
.long_name = "unveil",
.short_name = 'u',
.value_name = "path",
.accept_value = [&](auto* s) {
StringView path { s, strlen(s) };
.accept_value = [&](StringView path) {
if (path.is_empty())
return false;
auto maybe_error = Core::System::unveil(path, permissions);
@ -41,7 +40,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
.help_string = "Lock the veil",
.long_name = "lock",
.short_name = 'l',
.accept_value = [&](auto*) {
.accept_value = [&](StringView) {
auto maybe_error = Core::System::unveil(nullptr, nullptr);
if (maybe_error.is_error()) {
warnln("unveil(nullptr, nullptr): {}", maybe_error.error());
@ -54,8 +53,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
.name = "path",
.min_values = 0,
.max_values = INT_MAX,
.accept_value = [&](auto* s) {
auto maybe_error = Core::System::access({ s, strlen(s) }, X_OK);
.accept_value = [&](StringView s) {
auto maybe_error = Core::System::access(s, X_OK);
if (maybe_error.is_error())
warnln("'{}' - fail: {}", s, maybe_error.error());
else

View file

@ -141,8 +141,7 @@ static void parse_args(Main::Arguments arguments, TopOption& top_option)
"sort-by",
's',
nullptr,
[&top_option](char const* s) {
StringView sort_by_option { s, strlen(s) };
[&top_option](StringView sort_by_option) {
if (sort_by_option == "pid"sv)
top_option.sort_by = TopOption::SortBy::Pid;
else if (sort_by_option == "tid"sv)

View file

@ -111,19 +111,19 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
if (!transform_flag && !delete_flag && !squeeze_flag) {
warnln("tr: Missing operand");
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}
if (delete_flag && squeeze_flag && to_chars.is_empty()) {
warnln("tr: Combined delete and squeeze operations need two sets of characters");
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}
if (delete_flag && !squeeze_flag && !to_chars.is_empty()) {
warnln("tr: Only one set of characters may be given when deleting without squeezing");
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}

View file

@ -33,12 +33,12 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
args_parser.parse(arguments);
if (resize.is_empty() && reference.is_empty()) {
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}
if (!resize.is_empty() && !reference.is_empty()) {
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}
@ -61,7 +61,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
auto size_opt = str.to_int<off_t>();
if (!size_opt.has_value()) {
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}
size = size_opt.value();

View file

@ -48,7 +48,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
if (*test_name == 'k')
return kill_test();
if (*test_name != 'n') {
args_parser.print_usage(stdout, arguments.argv[0]);
args_parser.print_usage(stdout, arguments.strings[0]);
return 1;
}

View file

@ -190,7 +190,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
}
if (!s_disassembly_attempted) {
args_parser.print_usage(stderr, arguments.argv[0]);
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}
return 0;

View file

@ -296,9 +296,9 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
.long_name = "link",
.short_name = 'l',
.value_name = "file",
.accept_value = [&](char const* str) {
if (auto v = StringView { str, strlen(str) }; !v.is_empty()) {
modules_to_link_in.append(v);
.accept_value = [&](StringView str) {
if (!str.is_empty()) {
modules_to_link_in.append(str);
return true;
}
return false;
@ -310,8 +310,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
.long_name = "arg",
.short_name = 0,
.value_name = "u64",
.accept_value = [&](char const* str) -> bool {
if (auto v = StringView { str, strlen(str) }.to_uint<u64>(); v.has_value()) {
.accept_value = [&](StringView str) -> bool {
if (auto v = str.to_uint<u64>(); v.has_value()) {
values_to_push.append(v.value());
return true;
}