diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2023-05-15 14:59:26 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-05-16 12:54:18 +0200 |
commit | 45c429853ac1e2626edfe38f96613216d450ec0e (patch) | |
tree | 15c7ae42ab41e92d8275e3be7d41ed9d84a1ab63 /Userland/Utilities | |
parent | a6e701a67bf9d21ede5ccecbce3b3c9fef6ce8c4 (diff) | |
download | serenity-45c429853ac1e2626edfe38f96613216d450ec0e.zip |
ps: Allow `-q` option multiple times, and separated by spaces or commas
Several differences here:
- Passing `-q` multiple times will add them together, instead of the
last one overwriting the previous ones.
- `-q` PIDs can be separated by commas as well as spaces.
- We check that the PIDs are integers while parsing the arguments,
instead of later on.
The "parse a list of things as an option" is extracted into a helper
function, because we're going to want the same logic for `-g`, `-G`,
`-p`, `-t`, `-u`, and `-U`.
Diffstat (limited to 'Userland/Utilities')
-rw-r--r-- | Userland/Utilities/ps.cpp | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/Userland/Utilities/ps.cpp b/Userland/Utilities/ps.cpp index 75195171cd..33b5c36502 100644 --- a/Userland/Utilities/ps.cpp +++ b/Userland/Utilities/ps.cpp @@ -30,6 +30,28 @@ static ErrorOr<String> determine_tty_pseudo_name() return "n/a"_short_string; } +template<typename Value, typename ParseValue> +Core::ArgsParser::Option make_list_option(Vector<Value>& value_list, char const* help_string, char const* long_name, char short_name, char const* value_name, ParseValue parse_value) +{ + return Core::ArgsParser::Option { + .argument_mode = Core::ArgsParser::OptionArgumentMode::Required, + .help_string = help_string, + .long_name = long_name, + .short_name = short_name, + .value_name = value_name, + .accept_value = [&](StringView s) { + auto parts = s.split_view_if([](char c) { return c == ',' || c == ' '; }); + for (auto const& part : parts) { + auto value = parse_value(part); + if (!value.has_value()) + return false; + value_list.append(value.value()); + } + return true; + }, + }; +} + ErrorOr<int> serenity_main(Main::Arguments arguments) { TRY(Core::System::pledge("stdio rpath tty")); @@ -56,14 +78,19 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) bool every_process_flag = false; bool every_terminal_process_flag = false; bool full_format_flag = false; - StringView pid_list; + Vector<pid_t> pid_list; Core::ArgsParser args_parser; args_parser.add_option(every_terminal_process_flag, "Show every process associated with terminals", nullptr, 'a'); args_parser.add_option(every_process_flag, "Show every process", nullptr, 'A'); args_parser.add_option(every_process_flag, "Show every process (Equivalent to -A)", nullptr, 'e'); args_parser.add_option(full_format_flag, "Full format", nullptr, 'f'); - args_parser.add_option(pid_list, "A comma-separated list of PIDs. Only processes matching those PIDs will be selected", nullptr, 'q', "pid-list"); + args_parser.add_option(make_list_option(pid_list, "A comma- or space-separated list of PIDs. Only processes matching those PIDs will be selected", nullptr, 'q', "pid-list", [](StringView pid_string) { + auto pid = pid_string.to_int(); + if (!pid.has_value()) + warnln("Could not parse '{}' as a PID.", pid_string); + return pid; + })); args_parser.parse(arguments); Vector<Column> columns; @@ -105,26 +132,11 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) if (!pid_list.is_empty()) { every_process_flag = true; - auto string_parts = pid_list.split_view(','); - Vector<pid_t> selected_pids; - selected_pids.ensure_capacity(string_parts.size()); - - for (size_t i = 0; i < string_parts.size(); i++) { - auto pid = string_parts[i].to_int(); - - if (!pid.has_value()) { - warnln("Invalid value for -q: {}", pid_list); - warnln("Could not parse '{}' as a PID.", string_parts[i]); - return 1; - } - - selected_pids.append(pid.value()); - } - processes.remove_all_matching([&](auto& a) { return selected_pids.find(a.pid) == selected_pids.end(); }); + processes.remove_all_matching([&](auto& a) { return !pid_list.contains_slow(a.pid); }); - auto processes_sort_predicate = [&selected_pids](auto& a, auto& b) { - return selected_pids.find_first_index(a.pid).value() < selected_pids.find_first_index(b.pid).value(); + auto processes_sort_predicate = [&pid_list](auto& a, auto& b) { + return pid_list.find_first_index(a.pid).value() < pid_list.find_first_index(b.pid).value(); }; quick_sort(processes, processes_sort_predicate); } else { |