1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 22:27:35 +00:00

Help+man+LibManual: Move argument handling to LibManual

This deduplicates argument handling logic from Help and man and makes it
more modular for future use cases. The argument handling works as
before: two arguments specify section and page (in this order), one
argument specifies either a page (the first section that it's found in
is used) or a path to a manpage markdown file.
This commit is contained in:
kleines Filmröllchen 2022-07-12 20:23:28 +02:00 committed by Linus Groh
parent 64ca546a06
commit b65258c093
9 changed files with 149 additions and 125 deletions

View file

@ -192,47 +192,22 @@ MainWidget::MainWidget()
};
}
ErrorOr<void> MainWidget::set_start_page(StringView start_page, u32 section)
ErrorOr<void> MainWidget::set_start_page(Vector<StringView, 2> query_parameters)
{
bool set_start_page = false;
if (!start_page.is_null()) {
if (section != 0 && section < Manual::number_of_sections) {
// > Help [section] [name]
String const path = TRY(TRY(try_make_ref_counted<Manual::PageNode>(Manual::sections[section - 1], TRY(String::from_utf8(start_page))))->path());
m_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"sv)) {
// > Help [/path/to/documentation/file.md]
m_history.push(url.path());
open_page(TRY(String::from_deprecated_string(url.path())));
set_start_page = true;
} else {
// > Help [query]
// First, see if we can find the page by name
for (auto const& section : Manual::sections) {
String const path = TRY(TRY(try_make_ref_counted<Manual::PageNode>(section, TRY(String::from_utf8(start_page))))->path());
if (Core::File::exists(path)) {
m_history.push(path);
open_page(path);
set_start_page = true;
break;
}
}
// No match, so treat the input as a search query
if (!set_start_page) {
m_tab_widget->set_active_widget(m_search_container);
m_search_box->set_focus(true);
m_search_box->set_text(start_page);
m_search_box->select_all();
m_filter_model->set_filter_term(m_search_box->text());
}
}
}
if (!set_start_page)
auto result = Manual::Node::try_create_from_query(query_parameters);
if (result.is_error()) {
// No match, so treat the input as a search query
m_tab_widget->set_active_widget(m_search_container);
m_search_box->set_focus(true);
m_search_box->set_text(query_parameters.first_matching([](auto&) { return true; }).value_or(""sv));
m_search_box->select_all();
m_filter_model->set_filter_term(m_search_box->text());
m_go_home_action->activate();
} else {
auto const page = TRY(result.value()->path());
m_history.push(page);
open_page(page);
}
return {};
}

View file

@ -20,7 +20,7 @@ public:
virtual ~MainWidget() override = default;
ErrorOr<void> initialize_fallibles(GUI::Window&);
ErrorOr<void> set_start_page(StringView page, u32 section);
ErrorOr<void> set_start_page(Vector<StringView, 2> query_parameters);
private:
MainWidget();

View file

@ -2,6 +2,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>
* Copyright (c) 2022, kleines Filmröllchen <filmroellchen@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -17,15 +18,6 @@
using namespace Help;
static DeprecatedString parse_input(StringView input)
{
AK::URL url = URL::create_with_url_or_path(input);
if (url.is_valid())
return url.basename();
return input;
}
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
TRY(Core::System::pledge("stdio recvfd sendfd rpath unix"));
@ -40,44 +32,27 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
TRY(Core::System::unveil("/tmp/session/%sid/portal/webcontent", "rw"));
TRY(Core::System::unveil(nullptr, nullptr));
DeprecatedString start_page;
u32 section = 0;
DeprecatedString first_query_parameter;
DeprecatedString second_query_parameter;
Core::ArgsParser args_parser;
// 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_ptr) {
StringView input { input_ptr, strlen(input_ptr) };
// If it's a number, use it as the section
if (auto number = input.to_int(); number.has_value()) {
section = number.value();
return true;
}
// Otherwise, use it as the start_page
start_page = parse_input(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_ptr) {
StringView input { input_ptr, strlen(input_ptr) };
// If start_page was already set by our section arg, then it can't be set again
if (!start_page.is_empty())
return false;
start_page = parse_input(input);
return true;
} });
// The actual "page query" parsing happens when we set the main widget's start page.
args_parser.add_positional_argument(
first_query_parameter,
"Section of the man page",
"section",
Core::ArgsParser::Required::No);
args_parser.add_positional_argument(
second_query_parameter,
"Help page to open. Either an absolute path to the markdown file, or a search query",
"page",
Core::ArgsParser::Required::No);
args_parser.parse(arguments);
Vector<StringView, 2> query_parameters;
if (!first_query_parameter.is_empty())
query_parameters.append(first_query_parameter);
if (!second_query_parameter.is_empty())
query_parameters.append(second_query_parameter);
auto app_icon = GUI::Icon::default_icon("app-help"sv);
@ -88,7 +63,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
auto main_widget = TRY(window->try_set_main_widget<MainWidget>());
TRY(main_widget->initialize_fallibles(window));
TRY(main_widget->set_start_page(start_page, section));
TRY(main_widget->set_start_page(query_parameters));
window->show();