diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2021-12-19 15:35:21 +0000 |
---|---|---|
committer | Brian Gianforcaro <b.gianfo@gmail.com> | 2021-12-20 10:58:41 -0800 |
commit | 8461f8c1cd16240217b64c875d1fa8c6d428486f (patch) | |
tree | c1ba8b9c14837df683aed0a97dc458482b8fe220 /Userland/Applications/Help/main.cpp | |
parent | 4c91f736c74207efb044a788c3488153e65c5406 (diff) | |
download | serenity-8461f8c1cd16240217b64c875d1fa8c6d428486f.zip |
Help: Add support for launching with a section and page, like man
I found it strange that `man` and `Help` did not accept the same command
line arguments since they are so similar. So... now they do. :^)
This means you can now open for example the `tar` man page in Help with
`Help tar`, or `Help 1 tar` if you want to disambiguate between pages in
different sections.
If the result is not found, it falls back to the previous behavior,
treating the input as a search query.
Initially I had this written as two optional positional arguments, but
when told to parse `[optional int] [optional string]`, and then given a
string input, ArgsParser forwards it to the [optional int], which then
fails to parse. Ideally it would pass it to the second, [optional
string] arg instead, but that looks like a fairly big change to make to
ArgsParser's internals, and risk breaking things. Maybe this ugly hack
will be an incentive to fix it. :^)
Diffstat (limited to 'Userland/Applications/Help/main.cpp')
-rw-r--r-- | Userland/Applications/Help/main.cpp | 79 |
1 files changed, 71 insertions, 8 deletions
diff --git a/Userland/Applications/Help/main.cpp b/Userland/Applications/Help/main.cpp index 73e134cdc4..f57cd2ece7 100644 --- a/Userland/Applications/Help/main.cpp +++ b/Userland/Applications/Help/main.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org> * Copyright (c) 2021, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -45,9 +46,40 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) TRY(Core::System::unveil(nullptr, nullptr)); char const* start_page = nullptr; + unsigned section = 0; Core::ArgsParser args_parser; - args_parser.add_positional_argument(start_page, "Page to open at launch", "page", Core::ArgsParser::Required::No); + // FIXME: These custom Args are a hack. What we want to do is have an optional int arg, then an optional string. + // However, when only a string is provided, it gets forwarded to the int argument since that is first, and + // parsing fails. This hack instead forwards it to the start_page in that case. + args_parser.add_positional_argument(Core::ArgsParser::Arg { + .help_string = "Section of the man page", + .name = "section", + .min_values = 0, + .max_values = 1, + .accept_value = [&](char const* input) { + // If it's a number, use it as the section + if (auto number = StringView(input).to_int(); number.has_value()) { + section = number.value(); + return true; + } + + // Otherwise, use it as the start_page + start_page = input; + return true; + } }); + args_parser.add_positional_argument(Core::ArgsParser::Arg { + .help_string = "Help page to open. Either an absolute path to the markdown file, or a search query", + .name = "page", + .min_values = 0, + .max_values = 1, + .accept_value = [&](char const* input) { + // If start_page was already set by our section arg, then it can't be set again + if (start_page) + return false; + start_page = input; + return true; + } }); args_parser.parse(arguments); auto app_icon = GUI::Icon::default_icon("app-help"); @@ -268,17 +300,48 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) bool set_start_page = false; if (start_page) { - URL url = URL::create_with_url_or_path(start_page); - if (url.is_valid() && url.path().ends_with(".md")) { + if (section != 0) { + // > Help [section] [name] + String path = String::formatted("/usr/share/man/man{}/{}.md", section, start_page); + history.push(path); + open_page(path); + set_start_page = true; + } else if (URL url = URL::create_with_url_or_path(start_page); url.is_valid() && url.path().ends_with(".md")) { + // > Help [/path/to/documentation/file.md] history.push(url.path()); open_page(url.path()); set_start_page = true; } else { - left_tab_bar->set_active_widget(search_view); - search_box->set_text(start_page); - if (auto* model = search_list_view->model()) { - auto& search_model = *static_cast<GUI::FilteringProxyModel*>(model); - search_model.set_filter_term(search_box->text()); + // > Help [query] + + // First, see if we can find the page by name + char const* sections[] = { + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8" + }; + for (auto s : sections) { + String path = String::formatted("/usr/share/man/man{}/{}.md", s, start_page); + if (Core::File::exists(path)) { + history.push(path); + open_page(path); + set_start_page = true; + } + } + + // No match, so treat the input as a search query + if (!set_start_page) { + left_tab_bar->set_active_widget(search_view); + search_box->set_text(start_page); + if (auto* model = search_list_view->model()) { + auto& search_model = *static_cast<GUI::FilteringProxyModel*>(model); + search_model.set_filter_term(search_box->text()); + } } } } |