summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibManual
diff options
context:
space:
mode:
authorkleines Filmröllchen <filmroellchen@serenityos.org>2022-07-12 20:23:28 +0200
committerLinus Groh <mail@linusgroh.de>2022-12-11 16:05:23 +0000
commitb65258c093a14a8bac082aa3580ae70b78f92283 (patch)
treece644524fe8534f579ea06522802b18a6aba5392 /Userland/Libraries/LibManual
parent64ca546a06c7bfd0ad1d75beb068aa63d90282ac (diff)
downloadserenity-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.txt1
-rw-r--r--Userland/Libraries/LibManual/Node.cpp70
-rw-r--r--Userland/Libraries/LibManual/Node.h7
-rw-r--r--Userland/Libraries/LibManual/SectionNode.cpp11
-rw-r--r--Userland/Libraries/LibManual/SectionNode.h2
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;