Serenity Operating System
at hosted 126 lines 5.1 kB view raw
1/* 2 * Copyright (c) 2020, the SerenityOS developers. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <LibGUI/CppLexer.h> 28#include <LibGUI/CppSyntaxHighlighter.h> 29#include <LibGUI/TextEditor.h> 30#include <LibGfx/Font.h> 31#include <LibGfx/Palette.h> 32 33namespace GUI { 34 35static TextStyle style_for_token_type(Gfx::Palette palette, CppToken::Type type) 36{ 37 switch (type) { 38 case CppToken::Type::Keyword: 39 return { palette.syntax_keyword(), &Gfx::Font::default_bold_fixed_width_font() }; 40 case CppToken::Type::KnownType: 41 return { palette.syntax_type(), &Gfx::Font::default_bold_fixed_width_font() }; 42 case CppToken::Type::Identifier: 43 return { palette.syntax_identifier() }; 44 case CppToken::Type::DoubleQuotedString: 45 case CppToken::Type::SingleQuotedString: 46 return { palette.syntax_string() }; 47 case CppToken::Type::Integer: 48 case CppToken::Type::Float: 49 return { palette.syntax_number() }; 50 case CppToken::Type::IncludePath: 51 return { palette.syntax_preprocessor_value() }; 52 case CppToken::Type::EscapeSequence: 53 return { palette.syntax_keyword(), &Gfx::Font::default_bold_fixed_width_font() }; 54 case CppToken::Type::PreprocessorStatement: 55 case CppToken::Type::IncludeStatement: 56 return { palette.syntax_preprocessor_statement() }; 57 case CppToken::Type::Comment: 58 return { palette.syntax_comment() }; 59 default: 60 return { palette.base_text() }; 61 } 62} 63 64bool CppSyntaxHighlighter::is_identifier(void* token) const 65{ 66 auto cpp_token = static_cast<GUI::CppToken::Type>(reinterpret_cast<size_t>(token)); 67 return cpp_token == GUI::CppToken::Type::Identifier; 68} 69 70bool CppSyntaxHighlighter::is_navigatable(void* token) const 71{ 72 auto cpp_token = static_cast<GUI::CppToken::Type>(reinterpret_cast<size_t>(token)); 73 return cpp_token == GUI::CppToken::Type::IncludePath; 74} 75 76void CppSyntaxHighlighter::rehighlight(Gfx::Palette palette) 77{ 78 ASSERT(m_editor); 79 auto text = m_editor->text(); 80 CppLexer lexer(text); 81 auto tokens = lexer.lex(); 82 83 Vector<GUI::TextDocumentSpan> spans; 84 for (auto& token : tokens) { 85#ifdef DEBUG_SYNTAX_HIGHLIGHTING 86 dbg() << token.to_string() << " @ " << token.m_start.line << ":" << token.m_start.column << " - " << token.m_end.line << ":" << token.m_end.column; 87#endif 88 GUI::TextDocumentSpan span; 89 span.range.set_start({ token.m_start.line, token.m_start.column }); 90 span.range.set_end({ token.m_end.line, token.m_end.column }); 91 auto style = style_for_token_type(palette, token.m_type); 92 span.color = style.color; 93 span.font = style.font; 94 span.is_skippable = token.m_type == CppToken::Type::Whitespace; 95 span.data = reinterpret_cast<void*>(token.m_type); 96 spans.append(span); 97 } 98 m_editor->document().set_spans(spans); 99 100 m_has_brace_buddies = false; 101 highlight_matching_token_pair(); 102 103 m_editor->update(); 104} 105 106Vector<SyntaxHighlighter::MatchingTokenPair> CppSyntaxHighlighter::matching_token_pairs() const 107{ 108 static Vector<SyntaxHighlighter::MatchingTokenPair> pairs; 109 if (pairs.is_empty()) { 110 pairs.append({ reinterpret_cast<void*>(CppToken::Type::LeftCurly), reinterpret_cast<void*>(CppToken::Type::RightCurly) }); 111 pairs.append({ reinterpret_cast<void*>(CppToken::Type::LeftParen), reinterpret_cast<void*>(CppToken::Type::RightParen) }); 112 pairs.append({ reinterpret_cast<void*>(CppToken::Type::LeftBracket), reinterpret_cast<void*>(CppToken::Type::RightBracket) }); 113 } 114 return pairs; 115} 116 117bool CppSyntaxHighlighter::token_types_equal(void* token1, void* token2) const 118{ 119 return static_cast<GUI::CppToken::Type>(reinterpret_cast<size_t>(token1)) == static_cast<GUI::CppToken::Type>(reinterpret_cast<size_t>(token2)); 120} 121 122CppSyntaxHighlighter::~CppSyntaxHighlighter() 123{ 124} 125 126}