/* * Copyright (c) 2019-2020, Sergey Bugaev * * SPDX-License-Identifier: BSD-2-Clause */ #include "SectionNode.h" #include "PageNode.h" #include "Path.h" #include "SubsectionNode.h" #include #include #include #include #include namespace Manual { ErrorOr> SectionNode::try_create_from_number(StringView section) { auto maybe_section_number = section.to_uint(); 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 SectionNode::path() const { return String::formatted("{}/{}{}", manual_base_path, top_level_section_prefix, m_section); } ErrorOr SectionNode::name() const { return String::formatted("{}. {}", m_section, m_name); } ErrorOr SectionNode::reify_if_needed() const { if (m_reified) return {}; m_reified = true; auto own_path = TRY(path()); Core::DirIterator dir_iterator { own_path.to_deprecated_string(), Core::DirIterator::Flags::SkipDots }; Vector directories; HashTable files; while (dir_iterator.has_next()) { auto entry = dir_iterator.next(); if (entry->type == Core::DirectoryEntry::Type::Directory) TRY(directories.try_append(entry->name)); else if (entry->type == Core::DirectoryEntry::Type::File && entry->name.ends_with(".md"sv, CaseSensitivity::CaseInsensitive)) TRY(files.try_set(entry->name)); } struct Child { NonnullRefPtr node; String name_for_sorting; }; Vector children; for (auto const& directory : directories) { LexicalPath lexical_path(directory); RefPtr associated_page; auto matching_page_name = DeprecatedString::formatted("{}.md", directory); if (files.remove(matching_page_name)) associated_page = TRY(try_make_ref_counted(*this, TRY(String::from_utf8(lexical_path.title())))); TRY(children.try_append({ .node = TRY(try_make_ref_counted(*this, lexical_path.title(), associated_page)), .name_for_sorting = TRY(String::from_utf8(lexical_path.title())) })); } for (auto const& file : files) { LexicalPath lexical_path(file); children.append({ .node = TRY(try_make_ref_counted(*this, TRY(String::from_utf8(lexical_path.title())))), .name_for_sorting = TRY(String::from_utf8(lexical_path.title())) }); } quick_sort(children, [](auto const& a, auto const& b) { return a.name_for_sorting < b.name_for_sorting; }); m_children.ensure_capacity(children.size()); for (auto child : children) m_children.unchecked_append(move(child.node)); return {}; } void SectionNode::set_open(bool open) { if (m_open == open) return; m_open = open; } Array, number_of_sections> const sections = { { make_ref_counted("1"sv, "User Programs"sv), make_ref_counted("2"sv, "System Calls"sv), make_ref_counted("3"sv, "Library Functions"sv), make_ref_counted("4"sv, "Special Files"sv), make_ref_counted("5"sv, "File Formats"sv), make_ref_counted("6"sv, "Games"sv), make_ref_counted("7"sv, "Miscellanea"sv), make_ref_counted("8"sv, "Sysadmin Tools"sv), } }; }