Highlighter.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Copyright (c) 2020-2021, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Noncopyable.h>
  8. #include <AK/WeakPtr.h>
  9. #include <LibGUI/TextDocument.h>
  10. #include <LibGfx/Palette.h>
  11. #include <LibSyntax/HighlighterClient.h>
  12. namespace Syntax {
  13. enum class Language {
  14. Cpp,
  15. CSS,
  16. GML,
  17. HTML,
  18. INI,
  19. JavaScript,
  20. PlainText,
  21. SQL,
  22. Shell,
  23. };
  24. struct TextStyle {
  25. const Gfx::Color color;
  26. const bool bold { false };
  27. };
  28. class Highlighter {
  29. AK_MAKE_NONCOPYABLE(Highlighter);
  30. AK_MAKE_NONMOVABLE(Highlighter);
  31. public:
  32. virtual ~Highlighter();
  33. virtual Language language() const = 0;
  34. virtual void rehighlight(const Palette&) = 0;
  35. virtual void highlight_matching_token_pair();
  36. virtual bool is_identifier(u64) const { return false; };
  37. virtual bool is_navigatable(u64) const { return false; };
  38. void attach(HighlighterClient&);
  39. void detach();
  40. void cursor_did_change();
  41. struct MatchingTokenPair {
  42. u64 open;
  43. u64 close;
  44. };
  45. Vector<MatchingTokenPair> matching_token_pairs() const;
  46. protected:
  47. Highlighter() { }
  48. // FIXME: This should be WeakPtr somehow
  49. HighlighterClient* m_client { nullptr };
  50. virtual Vector<MatchingTokenPair> matching_token_pairs_impl() const = 0;
  51. virtual bool token_types_equal(u64, u64) const = 0;
  52. void register_nested_token_pairs(Vector<MatchingTokenPair>);
  53. void clear_nested_token_pairs() { m_nested_token_pairs.clear(); }
  54. size_t first_free_token_kind_serial_value() const { return m_nested_token_pairs.size(); }
  55. struct BuddySpan {
  56. int index { -1 };
  57. GUI::TextDocumentSpan span_backup;
  58. };
  59. bool m_has_brace_buddies { false };
  60. BuddySpan m_brace_buddies[2];
  61. HashTable<MatchingTokenPair> m_nested_token_pairs;
  62. };
  63. class ProxyHighlighterClient final : public Syntax::HighlighterClient {
  64. public:
  65. ProxyHighlighterClient(Syntax::HighlighterClient& client, GUI::TextPosition start, u64 nested_kind_start_value, StringView source)
  66. : m_document(client.get_document())
  67. , m_text(source)
  68. , m_start(start)
  69. , m_nested_kind_start_value(nested_kind_start_value)
  70. {
  71. }
  72. Vector<GUI::TextDocumentSpan> corrected_spans() const
  73. {
  74. Vector<GUI::TextDocumentSpan> spans { m_spans };
  75. for (auto& entry : spans) {
  76. entry.range.start() = {
  77. entry.range.start().line() + m_start.line(),
  78. entry.range.start().line() == 0 ? entry.range.start().column() + m_start.column() : entry.range.start().column(),
  79. };
  80. entry.range.end() = {
  81. entry.range.end().line() + m_start.line(),
  82. entry.range.end().line() == 0 ? entry.range.end().column() + m_start.column() : entry.range.end().column(),
  83. };
  84. if (entry.data != (u64)-1)
  85. entry.data += m_nested_kind_start_value;
  86. }
  87. return spans;
  88. }
  89. Vector<Syntax::Highlighter::MatchingTokenPair> corrected_token_pairs(Vector<Syntax::Highlighter::MatchingTokenPair> pairs) const
  90. {
  91. for (auto& pair : pairs) {
  92. pair.close += m_nested_kind_start_value;
  93. pair.open += m_nested_kind_start_value;
  94. }
  95. return pairs;
  96. }
  97. private:
  98. virtual Vector<GUI::TextDocumentSpan>& spans() override { return m_spans; }
  99. virtual const Vector<GUI::TextDocumentSpan>& spans() const override { return m_spans; }
  100. virtual void set_span_at_index(size_t index, GUI::TextDocumentSpan span) override { m_spans.at(index) = move(span); }
  101. virtual String highlighter_did_request_text() const override { return m_text; }
  102. virtual void highlighter_did_request_update() override { }
  103. virtual GUI::TextDocument& highlighter_did_request_document() override { return m_document; }
  104. virtual GUI::TextPosition highlighter_did_request_cursor() const override { return {}; }
  105. virtual void highlighter_did_set_spans(Vector<GUI::TextDocumentSpan> spans) override { m_spans = move(spans); }
  106. Vector<GUI::TextDocumentSpan> m_spans;
  107. GUI::TextDocument& m_document;
  108. StringView m_text;
  109. GUI::TextPosition m_start;
  110. u64 m_nested_kind_start_value { 0 };
  111. };
  112. }
  113. template<>
  114. struct AK::Traits<Syntax::Highlighter::MatchingTokenPair> : public AK::GenericTraits<Syntax::Highlighter::MatchingTokenPair> {
  115. static unsigned hash(Syntax::Highlighter::MatchingTokenPair const& pair)
  116. {
  117. return pair_int_hash(u64_hash(pair.open), u64_hash(pair.close));
  118. }
  119. static bool equals(Syntax::Highlighter::MatchingTokenPair const& a, Syntax::Highlighter::MatchingTokenPair const& b)
  120. {
  121. return a.open == b.open && a.close == b.close;
  122. }
  123. };