summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibManual
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries/LibManual')
-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
6 files changed, 231 insertions, 0 deletions
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,
+};
+
+}