summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorkleines Filmröllchen <filmroellchen@serenityos.org>2022-07-13 00:20:27 +0200
committerLinus Groh <mail@linusgroh.de>2022-12-11 16:05:23 +0000
commitad6a55e1f088f525b1bd2ee7e926fcafedead4c1 (patch)
tree792679e2cb56a14ac5e2b176c07668be20888960 /Userland/Libraries
parent78353ec184b8fb5feeaafeba1ded99ca2d102282 (diff)
downloadserenity-ad6a55e1f088f525b1bd2ee7e926fcafedead4c1.zip
Help+LibManual: Move non-UI-specific manual handling to LibManual
This is a first step in deduplicating code within and across Help and man. Because LibManual also doesn't contain any DeprecatedString, some adjustments to Help's string handling is included, just to interoperate with LibManual better. Further work in this area mostly requires String APIs in LibGUI.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/CMakeLists.txt1
-rw-r--r--Userland/Libraries/LibManual/CMakeLists.txt7
-rw-r--r--Userland/Libraries/LibManual/Node.h30
-rw-r--r--Userland/Libraries/LibManual/PageNode.cpp29
-rw-r--r--Userland/Libraries/LibManual/PageNode.h38
-rw-r--r--Userland/Libraries/LibManual/SectionNode.cpp62
-rw-r--r--Userland/Libraries/LibManual/SectionNode.h65
7 files changed, 232 insertions, 0 deletions
diff --git a/Userland/Libraries/CMakeLists.txt b/Userland/Libraries/CMakeLists.txt
index dde02378b1..c1e7ac418a 100644
--- a/Userland/Libraries/CMakeLists.txt
+++ b/Userland/Libraries/CMakeLists.txt
@@ -35,6 +35,7 @@ add_subdirectory(LibKeyboard)
add_subdirectory(LibLine)
add_subdirectory(LibLocale)
add_subdirectory(LibMain)
+add_subdirectory(LibManual)
add_subdirectory(LibMarkdown)
add_subdirectory(LibPartition)
add_subdirectory(LibPCIDB)
diff --git a/Userland/Libraries/LibManual/CMakeLists.txt b/Userland/Libraries/LibManual/CMakeLists.txt
new file mode 100644
index 0000000000..13f0454acb
--- /dev/null
+++ b/Userland/Libraries/LibManual/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(SOURCES
+ PageNode.cpp
+ SectionNode.cpp
+)
+
+serenity_lib(LibManual manual)
+target_link_libraries(LibManual PRIVATE LibCore)
diff --git a/Userland/Libraries/LibManual/Node.h b/Userland/Libraries/LibManual/Node.h
new file mode 100644
index 0000000000..232a7c3094
--- /dev/null
+++ b/Userland/Libraries/LibManual/Node.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
+ * Copyright (c) 2022, the SerenityOS developers.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/NonnullRefPtrVector.h>
+#include <AK/RefCounted.h>
+#include <AK/String.h>
+#include <AK/StringView.h>
+
+namespace Manual {
+
+class PageNode;
+
+class Node : public RefCounted<Node> {
+public:
+ virtual ~Node() = default;
+
+ virtual NonnullRefPtrVector<Node>& children() const = 0;
+ virtual Node const* parent() const = 0;
+ virtual String name() const = 0;
+ virtual bool is_page() const { return false; }
+ virtual bool is_open() const { return false; }
+};
+
+}
diff --git a/Userland/Libraries/LibManual/PageNode.cpp b/Userland/Libraries/LibManual/PageNode.cpp
new file mode 100644
index 0000000000..0b44ee97c0
--- /dev/null
+++ b/Userland/Libraries/LibManual/PageNode.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
+ * Copyright (c) 2022, the SerenityOS developers.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "PageNode.h"
+#include "SectionNode.h"
+
+namespace Manual {
+
+Node const* PageNode::parent() const
+{
+ return m_section.ptr();
+}
+
+NonnullRefPtrVector<Node>& PageNode::children() const
+{
+ static NonnullRefPtrVector<Node> empty_vector;
+ return empty_vector;
+}
+
+ErrorOr<String> PageNode::path() const
+{
+ return TRY(String::formatted("{}/{}.md", TRY(m_section->path()), m_page));
+}
+
+}
diff --git a/Userland/Libraries/LibManual/PageNode.h b/Userland/Libraries/LibManual/PageNode.h
new file mode 100644
index 0000000000..f74e78fb2f
--- /dev/null
+++ b/Userland/Libraries/LibManual/PageNode.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/NonnullRefPtr.h>
+#include <LibManual/Node.h>
+
+namespace Manual {
+
+class SectionNode;
+
+class PageNode : public Node {
+public:
+ virtual ~PageNode() override = default;
+
+ PageNode(NonnullRefPtr<SectionNode> section, String page)
+ : m_section(move(section))
+ , m_page(move(page))
+ {
+ }
+
+ virtual NonnullRefPtrVector<Node>& children() const override;
+ virtual Node const* parent() const override;
+ virtual String name() const override { return m_page; };
+ virtual bool is_page() const override { return true; }
+
+ ErrorOr<String> path() const;
+
+private:
+ NonnullRefPtr<SectionNode> m_section;
+ String m_page;
+};
+
+}
diff --git a/Userland/Libraries/LibManual/SectionNode.cpp b/Userland/Libraries/LibManual/SectionNode.cpp
new file mode 100644
index 0000000000..8ab6c89380
--- /dev/null
+++ b/Userland/Libraries/LibManual/SectionNode.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "SectionNode.h"
+#include "PageNode.h"
+#include <AK/LexicalPath.h>
+#include <AK/QuickSort.h>
+#include <LibCore/DirIterator.h>
+
+namespace Manual {
+
+ErrorOr<String> SectionNode::path() const
+{
+ return String::formatted("/usr/share/man/man{}", m_section);
+}
+
+ErrorOr<void> SectionNode::reify_if_needed() const
+{
+ if (m_reified)
+ return {};
+ m_reified = true;
+
+ Core::DirIterator dir_iter { TRY(path()).to_deprecated_string(), Core::DirIterator::Flags::SkipDots };
+
+ Vector<String> page_names;
+ while (dir_iter.has_next()) {
+ LexicalPath lexical_path(dir_iter.next_path());
+ if (lexical_path.extension() != "md")
+ continue;
+ page_names.append(TRY(String::from_utf8(lexical_path.title())));
+ }
+
+ quick_sort(page_names);
+
+ for (auto& page_name : page_names)
+ m_children.append(TRY(try_make_ref_counted<PageNode>(*this, move(page_name))));
+
+ return {};
+}
+
+void SectionNode::set_open(bool open)
+{
+ if (m_open == open)
+ return;
+ m_open = open;
+}
+
+Array<NonnullRefPtr<SectionNode>, number_of_sections> const sections = { {
+ make_ref_counted<SectionNode>("1"sv, "User Programs"sv),
+ make_ref_counted<SectionNode>("2"sv, "System Calls"sv),
+ make_ref_counted<SectionNode>("3"sv, "Library Functions"sv),
+ make_ref_counted<SectionNode>("4"sv, "Special Files"sv),
+ make_ref_counted<SectionNode>("5"sv, "File Formats"sv),
+ make_ref_counted<SectionNode>("6"sv, "Games"sv),
+ make_ref_counted<SectionNode>("7"sv, "Miscellanea"sv),
+ make_ref_counted<SectionNode>("8"sv, "Sysadmin Tools"sv),
+} };
+
+}
diff --git a/Userland/Libraries/LibManual/SectionNode.h b/Userland/Libraries/LibManual/SectionNode.h
new file mode 100644
index 0000000000..cc7546f8e1
--- /dev/null
+++ b/Userland/Libraries/LibManual/SectionNode.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
+ * Copyright (c) 2022, the SerenityOS developers.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Error.h>
+#include <AK/String.h>
+#include <LibManual/Node.h>
+
+namespace Manual {
+
+class SectionNode : public Node {
+public:
+ virtual ~SectionNode() override = default;
+
+ SectionNode(StringView section, StringView name)
+ : m_section(MUST(String::from_utf8(section)))
+ , m_full_name(MUST(String::formatted("{}. {}", section, name)))
+ {
+ }
+
+ virtual NonnullRefPtrVector<Node>& children() const override
+ {
+ MUST(reify_if_needed());
+ return m_children;
+ }
+
+ virtual Node const* parent() const override { return nullptr; }
+ virtual String name() const override { return m_full_name; }
+ virtual bool is_open() const override { return m_open; }
+ void set_open(bool open);
+
+ String const& section_name() const { return m_section; }
+ ErrorOr<String> path() const;
+
+private:
+ ErrorOr<void> reify_if_needed() const;
+
+ String m_section;
+ String m_full_name;
+ mutable NonnullRefPtrVector<Node> m_children;
+ mutable bool m_reified { false };
+ bool m_open { false };
+};
+
+constexpr size_t number_of_sections = 8;
+
+extern Array<NonnullRefPtr<SectionNode>, number_of_sections> const sections;
+
+constexpr Array<StringView, number_of_sections> const section_numbers = {
+ "1"sv,
+ "2"sv,
+ "3"sv,
+ "4"sv,
+ "5"sv,
+ "6"sv,
+ "7"sv,
+ "8"sv,
+};
+
+}