Serenity Operating System
1/*
2 * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include "SectionNode.h"
8#include "PageNode.h"
9#include "Path.h"
10#include "SubsectionNode.h"
11#include <AK/LexicalPath.h>
12#include <AK/QuickSort.h>
13#include <LibCore/DeprecatedFile.h>
14#include <LibCore/DirIterator.h>
15
16namespace Manual {
17
18ErrorOr<NonnullRefPtr<SectionNode>> SectionNode::try_create_from_number(StringView section)
19{
20 auto maybe_section_number = section.to_uint<u32>();
21 if (!maybe_section_number.has_value())
22 return Error::from_string_literal("Section is not a number");
23 auto section_number = maybe_section_number.release_value();
24 if (section_number > number_of_sections)
25 return Error::from_string_literal("Section number too large");
26 return sections[section_number - 1];
27}
28
29ErrorOr<String> SectionNode::path() const
30{
31 return String::formatted("{}/{}{}", manual_base_path, top_level_section_prefix, m_section);
32}
33
34ErrorOr<String> SectionNode::name() const
35{
36 return String::formatted("{}. {}", m_section, m_name);
37}
38
39ErrorOr<void> SectionNode::reify_if_needed() const
40{
41 if (m_reified)
42 return {};
43 m_reified = true;
44
45 auto own_path = TRY(path());
46 Core::DirIterator dir_iter { own_path.to_deprecated_string(), Core::DirIterator::Flags::SkipDots };
47
48 struct Child {
49 NonnullRefPtr<Node const> node;
50 String name_for_sorting;
51 };
52 Vector<Child> children;
53
54 while (dir_iter.has_next()) {
55 LexicalPath lexical_path(dir_iter.next_path());
56 if (lexical_path.extension() != "md") {
57 if (Core::DeprecatedFile::is_directory(LexicalPath::absolute_path(own_path.to_deprecated_string(), lexical_path.string()))) {
58 dbgln("Found subsection {}", lexical_path);
59 children.append({ .node = TRY(try_make_ref_counted<SubsectionNode>(*this, lexical_path.title())),
60 .name_for_sorting = TRY(String::from_utf8(lexical_path.title())) });
61 }
62 } else {
63 children.append({ .node = TRY(try_make_ref_counted<PageNode>(*this, TRY(String::from_utf8(lexical_path.title())))),
64 .name_for_sorting = TRY(String::from_utf8(lexical_path.title())) });
65 }
66 }
67
68 quick_sort(children, [](auto const& a, auto const& b) { return a.name_for_sorting < b.name_for_sorting; });
69
70 m_children.ensure_capacity(children.size());
71 for (auto child : children)
72 m_children.unchecked_append(move(child.node));
73
74 return {};
75}
76
77void SectionNode::set_open(bool open)
78{
79 if (m_open == open)
80 return;
81 m_open = open;
82}
83
84Array<NonnullRefPtr<SectionNode>, number_of_sections> const sections = { {
85 make_ref_counted<SectionNode>("1"sv, "User Programs"sv),
86 make_ref_counted<SectionNode>("2"sv, "System Calls"sv),
87 make_ref_counted<SectionNode>("3"sv, "Library Functions"sv),
88 make_ref_counted<SectionNode>("4"sv, "Special Files"sv),
89 make_ref_counted<SectionNode>("5"sv, "File Formats"sv),
90 make_ref_counted<SectionNode>("6"sv, "Games"sv),
91 make_ref_counted<SectionNode>("7"sv, "Miscellanea"sv),
92 make_ref_counted<SectionNode>("8"sv, "Sysadmin Tools"sv),
93} };
94
95}