SyntaxHighlighter.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2022, the SerenityOS developers.
  4. * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include "SyntaxHighlighter.h"
  9. #include "Lexer.h"
  10. #include <LibGfx/Palette.h>
  11. namespace GUI::GML {
  12. static Syntax::TextStyle style_for_token_type(Gfx::Palette const& palette, Token::Type type)
  13. {
  14. switch (type) {
  15. case Token::Type::LeftCurly:
  16. case Token::Type::RightCurly:
  17. return { palette.syntax_punctuation() };
  18. case Token::Type::ClassMarker:
  19. return { palette.syntax_keyword() };
  20. case Token::Type::ClassName:
  21. return { palette.syntax_identifier(), true };
  22. case Token::Type::Identifier:
  23. return { palette.syntax_identifier() };
  24. case Token::Type::JsonValue:
  25. return { palette.syntax_string() };
  26. case Token::Type::Comment:
  27. return { palette.syntax_comment() };
  28. default:
  29. return { palette.base_text() };
  30. }
  31. }
  32. bool SyntaxHighlighter::is_identifier(u64 token) const
  33. {
  34. auto ini_token = static_cast<Token::Type>(token);
  35. return ini_token == Token::Type::Identifier;
  36. }
  37. void SyntaxHighlighter::rehighlight(Palette const& palette)
  38. {
  39. auto text = m_client->get_text();
  40. Lexer lexer(text);
  41. auto tokens = lexer.lex();
  42. Vector<Token> folding_region_start_tokens;
  43. Vector<GUI::TextDocumentSpan> spans;
  44. Vector<GUI::TextDocumentFoldingRegion> folding_regions;
  45. for (auto& token : tokens) {
  46. GUI::TextDocumentSpan span;
  47. span.range.set_start({ token.m_start.line, token.m_start.column });
  48. span.range.set_end({ token.m_end.line, token.m_end.column });
  49. auto style = style_for_token_type(palette, token.m_type);
  50. span.attributes.color = style.color;
  51. span.attributes.bold = style.bold;
  52. span.is_skippable = false;
  53. span.data = static_cast<u64>(token.m_type);
  54. spans.append(span);
  55. // Create folding regions for {} blocks
  56. if (token.m_type == Token::Type::LeftCurly) {
  57. folding_region_start_tokens.append(token);
  58. } else if (token.m_type == Token::Type::RightCurly) {
  59. if (!folding_region_start_tokens.is_empty()) {
  60. auto left_curly = folding_region_start_tokens.take_last();
  61. GUI::TextDocumentFoldingRegion region;
  62. region.range.set_start({ left_curly.m_end.line, left_curly.m_end.column });
  63. region.range.set_end({ token.m_start.line, token.m_start.column });
  64. folding_regions.append(region);
  65. }
  66. }
  67. }
  68. m_client->do_set_spans(move(spans));
  69. m_client->do_set_folding_regions(move(folding_regions));
  70. m_has_brace_buddies = false;
  71. highlight_matching_token_pair();
  72. m_client->do_update();
  73. }
  74. Vector<SyntaxHighlighter::MatchingTokenPair> SyntaxHighlighter::matching_token_pairs_impl() const
  75. {
  76. static Vector<MatchingTokenPair> pairs;
  77. if (pairs.is_empty()) {
  78. pairs.append({ static_cast<u64>(Token::Type::LeftCurly), static_cast<u64>(Token::Type::RightCurly) });
  79. }
  80. return pairs;
  81. }
  82. bool SyntaxHighlighter::token_types_equal(u64 token1, u64 token2) const
  83. {
  84. return static_cast<Token::Type>(token1) == static_cast<Token::Type>(token2);
  85. }
  86. }