diff options
author | kleines Filmröllchen <filmroellchen@serenityos.org> | 2022-07-12 20:23:28 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-12-11 16:05:23 +0000 |
commit | b65258c093a14a8bac082aa3580ae70b78f92283 (patch) | |
tree | ce644524fe8534f579ea06522802b18a6aba5392 /Userland/Libraries/LibManual | |
parent | 64ca546a06c7bfd0ad1d75beb068aa63d90282ac (diff) | |
download | serenity-b65258c093a14a8bac082aa3580ae70b78f92283.zip |
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.
Diffstat (limited to 'Userland/Libraries/LibManual')
-rw-r--r-- | Userland/Libraries/LibManual/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibManual/Node.cpp | 70 | ||||
-rw-r--r-- | Userland/Libraries/LibManual/Node.h | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibManual/SectionNode.cpp | 11 | ||||
-rw-r--r-- | Userland/Libraries/LibManual/SectionNode.h | 2 |
5 files changed, 91 insertions, 0 deletions
diff --git a/Userland/Libraries/LibManual/CMakeLists.txt b/Userland/Libraries/LibManual/CMakeLists.txt index 0bc2104a03..56258cf52b 100644 --- a/Userland/Libraries/LibManual/CMakeLists.txt +++ b/Userland/Libraries/LibManual/CMakeLists.txt @@ -1,4 +1,5 @@ set(SOURCES + Node.cpp PageNode.cpp Path.cpp SectionNode.cpp diff --git a/Userland/Libraries/LibManual/Node.cpp b/Userland/Libraries/LibManual/Node.cpp new file mode 100644 index 0000000000..e8720f88ab --- /dev/null +++ b/Userland/Libraries/LibManual/Node.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2022, kleines Filmröllchen <filmroellchen@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "Node.h" +#include "PageNode.h" +#include "SectionNode.h" +#include <AK/Assertions.h> +#include <AK/LexicalPath.h> +#include <AK/Optional.h> +#include <AK/StringView.h> +#include <LibCore/File.h> +#include <LibCore/Stream.h> +#include <LibManual/Path.h> + +namespace Manual { + +ErrorOr<NonnullRefPtr<PageNode>> Node::try_create_from_query(Vector<StringView, 2> const& query_parameters) +{ + if (query_parameters.size() > 2) + return Error::from_string_literal("Queries longer than 2 strings are not supported yet"); + + auto query_parameter_iterator = query_parameters.begin(); + + if (query_parameter_iterator.is_end()) + // BUG! No query was given. + VERIFY_NOT_REACHED(); + + auto first_query_parameter = *query_parameter_iterator; + ++query_parameter_iterator; + if (query_parameter_iterator.is_end()) { + // [/path/to/docs.md] + auto path_from_query = LexicalPath { first_query_parameter }; + if (path_from_query.is_absolute() + && path_from_query.is_child_of(manual_base_path) + && path_from_query.extension() == "md"sv) { + auto section_directory = path_from_query.parent(); + auto man_string_location = section_directory.basename().find("man"sv); + if (!man_string_location.has_value()) + return Error::from_string_literal("Page is inside invalid section"); + auto section_name = section_directory.basename().substring_view(man_string_location.value() + 3); + auto section = TRY(SectionNode::try_create_from_number(section_name)); + return try_make_ref_counted<PageNode>(section, TRY(String::from_utf8(path_from_query.title()))); + } + + // [page] (in any section) + Optional<NonnullRefPtr<PageNode>> maybe_page; + for (auto const& section : sections) { + auto const page = TRY(try_make_ref_counted<PageNode>(section, TRY(String::from_utf8(first_query_parameter)))); + if (Core::File::exists(TRY(page->path()))) { + maybe_page = page; + break; + } + } + if (maybe_page.has_value()) + return maybe_page.release_value(); + return Error::from_string_literal("Page not found"); + } + // [section] [name] + auto second_query_parameter = *query_parameter_iterator; + auto section = TRY(SectionNode::try_create_from_number(first_query_parameter)); + auto const page = TRY(try_make_ref_counted<PageNode>(section, TRY(String::from_utf8(second_query_parameter)))); + if (Core::File::exists(TRY(page->path()))) + return page; + return Error::from_string_literal("Page doesn't exist in section"); +} + +} diff --git a/Userland/Libraries/LibManual/Node.h b/Userland/Libraries/LibManual/Node.h index 9b56aaab94..46347bd8e4 100644 --- a/Userland/Libraries/LibManual/Node.h +++ b/Userland/Libraries/LibManual/Node.h @@ -25,6 +25,13 @@ public: virtual ErrorOr<String> name() const = 0; virtual bool is_page() const { return false; } virtual bool is_open() const { return false; } + + // Backend for the command-line argument format that Help and man accept. Handles: + // [/path/to/documentation.md] (no second argument) + // [page] (no second argument) - will find first section with that page + // [section] [page] + // Help can also (externally) handle search queries, which is not possible (yet) in man. + static ErrorOr<NonnullRefPtr<PageNode>> try_create_from_query(Vector<StringView, 2> const& query_parameters); }; } diff --git a/Userland/Libraries/LibManual/SectionNode.cpp b/Userland/Libraries/LibManual/SectionNode.cpp index deae4a482d..1d18e77613 100644 --- a/Userland/Libraries/LibManual/SectionNode.cpp +++ b/Userland/Libraries/LibManual/SectionNode.cpp @@ -13,6 +13,17 @@ namespace Manual { +ErrorOr<NonnullRefPtr<SectionNode>> SectionNode::try_create_from_number(StringView section) +{ + auto maybe_section_number = section.to_uint<u32>(); + if (!maybe_section_number.has_value()) + return Error::from_string_literal("Section is not a number"); + auto section_number = maybe_section_number.release_value(); + if (section_number > number_of_sections) + return Error::from_string_literal("Section number too large"); + return sections[section_number - 1]; +} + ErrorOr<String> SectionNode::path() const { return String::formatted("{}/{}{}", manual_base_path, top_level_section_prefix, m_section); diff --git a/Userland/Libraries/LibManual/SectionNode.h b/Userland/Libraries/LibManual/SectionNode.h index 04bd7a568d..414e03b17c 100644 --- a/Userland/Libraries/LibManual/SectionNode.h +++ b/Userland/Libraries/LibManual/SectionNode.h @@ -37,6 +37,8 @@ public: virtual bool is_open() const override { return m_open; } void set_open(bool open); + static ErrorOr<NonnullRefPtr<SectionNode>> try_create_from_number(StringView section_number); + protected: String m_section; String m_name; |