SectionNode.cpp 3.1 KB

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