mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 19:22:45 +00:00 
			
		
		
		
	LibSyntax+LibGUI+LibJS: Move JS syntax highlighter to LibJS
This is a little bit messy but the basic idea is: Syntax::Highlighter now has a Syntax::HighlighterClient to talk to the outside world. It mostly communicates in LibGUI primitives that are available in headers, so inlineable. GUI::TextEditor inherits from Syntax::HighlighterClient. This let us to move GUI::JSSyntaxHighlighter to JS::SyntaxHighlighter and remove LibGUI's dependency on LibJS.
This commit is contained in:
		
							parent
							
								
									22baa5e64f
								
							
						
					
					
						commit
						ddbf20ecf6
					
				
					 23 changed files with 139 additions and 80 deletions
				
			
		|  | @ -28,13 +28,10 @@ | |||
| #include "ConsoleWidget.h" | ||||
| #include <AK/StringBuilder.h> | ||||
| #include <LibGUI/BoxLayout.h> | ||||
| #include <LibGUI/JSSyntaxHighlighter.h> | ||||
| #include <LibGUI/TextBox.h> | ||||
| #include <LibWeb/DOM/DocumentType.h> | ||||
| #include <LibWeb/DOM/ElementFactory.h> | ||||
| #include <LibWeb/DOM/Text.h> | ||||
| #include <LibWeb/DOMTreeModel.h> | ||||
| #include <LibWeb/HTML/HTMLBodyElement.h> | ||||
| 
 | ||||
| namespace Browser { | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,13 +28,13 @@ | |||
| #include <AK/StringBuilder.h> | ||||
| #include <LibGUI/BoxLayout.h> | ||||
| #include <LibGUI/Button.h> | ||||
| #include <LibGUI/JSSyntaxHighlighter.h> | ||||
| #include <LibGUI/TextBox.h> | ||||
| #include <LibGfx/FontDatabase.h> | ||||
| #include <LibJS/Interpreter.h> | ||||
| #include <LibJS/MarkupGenerator.h> | ||||
| #include <LibJS/Parser.h> | ||||
| #include <LibJS/Runtime/Error.h> | ||||
| #include <LibJS/SyntaxHighlighter.h> | ||||
| #include <LibWeb/DOM/DocumentType.h> | ||||
| #include <LibWeb/DOM/ElementFactory.h> | ||||
| #include <LibWeb/DOM/Text.h> | ||||
|  | @ -66,7 +66,7 @@ ConsoleWidget::ConsoleWidget() | |||
|     bottom_container.set_fixed_height(22); | ||||
| 
 | ||||
|     m_input = bottom_container.add<GUI::TextBox>(); | ||||
|     m_input->set_syntax_highlighter(make<GUI::JSSyntaxHighlighter>()); | ||||
|     m_input->set_syntax_highlighter(make<JS::SyntaxHighlighter>()); | ||||
|     // FIXME: Syntax Highlighting breaks the cursor's position on non fixed-width fonts.
 | ||||
|     m_input->set_font(Gfx::FontDatabase::default_fixed_width_font()); | ||||
|     m_input->set_history_enabled(true); | ||||
|  |  | |||
|  | @ -25,7 +25,6 @@ | |||
|  */ | ||||
| 
 | ||||
| #include "CellSyntaxHighlighter.h" | ||||
| #include <LibGUI/JSSyntaxHighlighter.h> | ||||
| #include <LibGUI/TextEditor.h> | ||||
| #include <LibGfx/Palette.h> | ||||
| #include <LibJS/Lexer.h> | ||||
|  | @ -34,18 +33,17 @@ namespace Spreadsheet { | |||
| 
 | ||||
| void CellSyntaxHighlighter::rehighlight(Gfx::Palette palette) | ||||
| { | ||||
|     ASSERT(m_editor); | ||||
|     auto text = m_editor->text(); | ||||
|     m_editor->document().spans().clear(); | ||||
|     auto text = m_client->get_text(); | ||||
|     m_client->spans().clear(); | ||||
|     if (!text.starts_with('=')) { | ||||
|         m_editor->update(); | ||||
|         m_client->do_update(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     JSSyntaxHighlighter::rehighlight(palette); | ||||
|     JS::SyntaxHighlighter::rehighlight(palette); | ||||
| 
 | ||||
|     // Highlight the '='
 | ||||
|     m_editor->document().spans().empend( | ||||
|     m_client->spans().empend( | ||||
|         GUI::TextRange { { 0, 0 }, { 0, 1 } }, | ||||
|         Gfx::TextAttributes { | ||||
|             palette.syntax_keyword(), | ||||
|  | @ -59,7 +57,7 @@ void CellSyntaxHighlighter::rehighlight(Gfx::Palette palette) | |||
|     if (m_cell && m_cell->exception()) { | ||||
|         auto range = m_cell->exception()->source_ranges().first(); | ||||
|         GUI::TextRange text_range { { range.start.line - 1, range.start.column }, { range.end.line - 1, range.end.column - 1 } }; | ||||
|         m_editor->document().spans().prepend( | ||||
|         m_client->spans().prepend( | ||||
|             GUI::TextDocumentSpan { | ||||
|                 text_range, | ||||
|                 Gfx::TextAttributes { | ||||
|  | @ -71,7 +69,7 @@ void CellSyntaxHighlighter::rehighlight(Gfx::Palette palette) | |||
|                 nullptr, | ||||
|                 false }); | ||||
|     } | ||||
|     m_editor->update(); | ||||
|     m_client->do_update(); | ||||
| } | ||||
| 
 | ||||
| CellSyntaxHighlighter::~CellSyntaxHighlighter() | ||||
|  |  | |||
|  | @ -27,11 +27,11 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include "Cell.h" | ||||
| #include <LibGUI/JSSyntaxHighlighter.h> | ||||
| #include <LibJS/SyntaxHighlighter.h> | ||||
| 
 | ||||
| namespace Spreadsheet { | ||||
| 
 | ||||
| class CellSyntaxHighlighter final : public GUI::JSSyntaxHighlighter { | ||||
| class CellSyntaxHighlighter final : public JS::SyntaxHighlighter { | ||||
| public: | ||||
|     CellSyntaxHighlighter() { } | ||||
|     virtual ~CellSyntaxHighlighter() override; | ||||
|  |  | |||
|  | @ -36,7 +36,6 @@ | |||
| #include <LibGUI/ColorInput.h> | ||||
| #include <LibGUI/ComboBox.h> | ||||
| #include <LibGUI/ItemListModel.h> | ||||
| #include <LibGUI/JSSyntaxHighlighter.h> | ||||
| #include <LibGUI/Label.h> | ||||
| #include <LibGUI/ListView.h> | ||||
| #include <LibGUI/SpinBox.h> | ||||
|  | @ -44,6 +43,7 @@ | |||
| #include <LibGUI/TextEditor.h> | ||||
| #include <LibGUI/Widget.h> | ||||
| #include <LibGfx/FontDatabase.h> | ||||
| #include <LibJS/SyntaxHighlighter.h> | ||||
| 
 | ||||
| REGISTER_WIDGET(Spreadsheet, ConditionsView); | ||||
| 
 | ||||
|  | @ -425,7 +425,7 @@ ConditionView::ConditionView(ConditionalFormat& fmt) | |||
|         m_format.background_color = bg_input.color(); | ||||
|     }; | ||||
| 
 | ||||
|     formula_editor.set_syntax_highlighter(make<GUI::JSSyntaxHighlighter>()); | ||||
|     formula_editor.set_syntax_highlighter(make<JS::SyntaxHighlighter>()); | ||||
|     formula_editor.set_should_hide_unnecessary_scrollbars(true); | ||||
|     formula_editor.set_font(&Gfx::FontDatabase::default_fixed_width_font()); | ||||
|     formula_editor.on_change = [&] { | ||||
|  |  | |||
|  | @ -7,4 +7,4 @@ set(SOURCES | |||
| ) | ||||
| 
 | ||||
| serenity_app(TextEditor ICON app-text-editor) | ||||
| target_link_libraries(TextEditor LibWeb LibMarkdown LibGUI LibShell LibRegex LibDesktop LibCpp) | ||||
| target_link_libraries(TextEditor LibWeb LibMarkdown LibGUI LibShell LibRegex LibDesktop LibCpp LibJS) | ||||
|  |  | |||
|  | @ -43,7 +43,6 @@ | |||
| #include <LibGUI/FontPicker.h> | ||||
| #include <LibGUI/GMLSyntaxHighlighter.h> | ||||
| #include <LibGUI/INISyntaxHighlighter.h> | ||||
| #include <LibGUI/JSSyntaxHighlighter.h> | ||||
| #include <LibGUI/Menu.h> | ||||
| #include <LibGUI/MenuBar.h> | ||||
| #include <LibGUI/MessageBox.h> | ||||
|  | @ -57,6 +56,7 @@ | |||
| #include <LibGUI/ToolBarContainer.h> | ||||
| #include <LibGUI/VimEditingEngine.h> | ||||
| #include <LibGfx/Font.h> | ||||
| #include <LibJS/SyntaxHighlighter.h> | ||||
| #include <LibMarkdown/Document.h> | ||||
| #include <LibWeb/OutOfProcessWebView.h> | ||||
| #include <string.h> | ||||
|  | @ -476,7 +476,7 @@ TextEditorWidget::TextEditorWidget() | |||
|     syntax_menu.add_action(*m_cpp_highlight); | ||||
| 
 | ||||
|     m_js_highlight = GUI::Action::create_checkable("JavaScript", [&](auto&) { | ||||
|         m_editor->set_syntax_highlighter(make<GUI::JSSyntaxHighlighter>()); | ||||
|         m_editor->set_syntax_highlighter(make<JS::SyntaxHighlighter>()); | ||||
|         m_editor->update(); | ||||
|     }); | ||||
|     syntax_actions.add_action(*m_js_highlight); | ||||
|  |  | |||
|  | @ -38,12 +38,12 @@ | |||
| #include <LibGUI/Application.h> | ||||
| #include <LibGUI/GMLSyntaxHighlighter.h> | ||||
| #include <LibGUI/INISyntaxHighlighter.h> | ||||
| #include <LibGUI/JSSyntaxHighlighter.h> | ||||
| #include <LibGUI/Label.h> | ||||
| #include <LibGUI/Painter.h> | ||||
| #include <LibGUI/ScrollBar.h> | ||||
| #include <LibGUI/ShellSyntaxHighlighter.h> | ||||
| #include <LibGUI/Window.h> | ||||
| #include <LibJS/SyntaxHighlighter.h> | ||||
| #include <LibMarkdown/Document.h> | ||||
| #include <LibWeb/DOM/ElementFactory.h> | ||||
| #include <LibWeb/DOM/Text.h> | ||||
|  | @ -424,7 +424,7 @@ void Editor::set_document(GUI::TextDocument& doc) | |||
|         set_syntax_highlighter(make<GUI::GMLSyntaxHighlighter>()); | ||||
|         break; | ||||
|     case Language::JavaScript: | ||||
|         set_syntax_highlighter(make<GUI::JSSyntaxHighlighter>()); | ||||
|         set_syntax_highlighter(make<JS::SyntaxHighlighter>()); | ||||
|         break; | ||||
|     case Language::Ini: | ||||
|         set_syntax_highlighter(make<GUI::IniSyntaxHighlighter>()); | ||||
|  |  | |||
|  | @ -77,8 +77,7 @@ bool SyntaxHighlighter::is_navigatable(void* token) const | |||
| 
 | ||||
| void SyntaxHighlighter::rehighlight(Gfx::Palette palette) | ||||
| { | ||||
|     ASSERT(m_editor); | ||||
|     auto text = m_editor->text(); | ||||
|     auto text = m_client->get_text(); | ||||
|     Cpp::Lexer lexer(text); | ||||
|     auto tokens = lexer.lex(); | ||||
| 
 | ||||
|  | @ -95,12 +94,12 @@ void SyntaxHighlighter::rehighlight(Gfx::Palette palette) | |||
|         span.data = reinterpret_cast<void*>(token.m_type); | ||||
|         spans.append(span); | ||||
|     } | ||||
|     m_editor->document().set_spans(spans); | ||||
|     m_client->do_set_spans(move(spans)); | ||||
| 
 | ||||
|     m_has_brace_buddies = false; | ||||
|     highlight_matching_token_pair(); | ||||
| 
 | ||||
|     m_editor->update(); | ||||
|     m_client->do_update(); | ||||
| } | ||||
| 
 | ||||
| Vector<SyntaxHighlighter::MatchingTokenPair> SyntaxHighlighter::matching_token_pairs() const | ||||
|  |  | |||
|  | @ -48,7 +48,6 @@ set(SOURCES | |||
|     IconView.cpp | ||||
|     ImageWidget.cpp | ||||
|     InputBox.cpp | ||||
|     JSSyntaxHighlighter.cpp | ||||
|     JsonArrayModel.cpp | ||||
|     Label.cpp | ||||
|     Layout.cpp | ||||
|  | @ -109,4 +108,4 @@ set(GENERATED_SOURCES | |||
| ) | ||||
| 
 | ||||
| serenity_lib(LibGUI gui) | ||||
| target_link_libraries(LibGUI LibCore LibGfx LibIPC LibThread LibShell LibRegex LibJS LibSyntax) | ||||
| target_link_libraries(LibGUI LibCore LibGfx LibIPC LibThread LibShell LibRegex LibSyntax) | ||||
|  |  | |||
|  | @ -82,6 +82,7 @@ class TableView; | |||
| class TextBox; | ||||
| class TextDocument; | ||||
| class TextDocumentLine; | ||||
| struct TextDocumentSpan; | ||||
| class TextDocumentUndoCommand; | ||||
| class TextEditor; | ||||
| class ThemeChangeEvent; | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ | |||
| 
 | ||||
| namespace GUI { | ||||
| 
 | ||||
| static Syntax::TextStyle style_for_token_type(Gfx::Palette palette, GMLToken::Type type) | ||||
| static Syntax::TextStyle style_for_token_type(const Gfx::Palette& palette, GMLToken::Type type) | ||||
| { | ||||
|     switch (type) { | ||||
|     case GMLToken::Type::LeftCurly: | ||||
|  | @ -61,8 +61,7 @@ bool GMLSyntaxHighlighter::is_identifier(void* token) const | |||
| 
 | ||||
| void GMLSyntaxHighlighter::rehighlight(Gfx::Palette palette) | ||||
| { | ||||
|     ASSERT(m_editor); | ||||
|     auto text = m_editor->text(); | ||||
|     auto text = m_client->get_text(); | ||||
|     GMLLexer lexer(text); | ||||
|     auto tokens = lexer.lex(); | ||||
| 
 | ||||
|  | @ -78,12 +77,12 @@ void GMLSyntaxHighlighter::rehighlight(Gfx::Palette palette) | |||
|         span.data = reinterpret_cast<void*>(token.m_type); | ||||
|         spans.append(span); | ||||
|     } | ||||
|     m_editor->document().set_spans(spans); | ||||
|     m_client->do_set_spans(move(spans)); | ||||
| 
 | ||||
|     m_has_brace_buddies = false; | ||||
|     highlight_matching_token_pair(); | ||||
| 
 | ||||
|     m_editor->update(); | ||||
|     m_client->do_update(); | ||||
| } | ||||
| 
 | ||||
| Vector<GMLSyntaxHighlighter::MatchingTokenPair> GMLSyntaxHighlighter::matching_token_pairs() const | ||||
|  |  | |||
|  | @ -60,8 +60,7 @@ bool IniSyntaxHighlighter::is_identifier(void* token) const | |||
| 
 | ||||
| void IniSyntaxHighlighter::rehighlight(Gfx::Palette palette) | ||||
| { | ||||
|     ASSERT(m_editor); | ||||
|     auto text = m_editor->text(); | ||||
|     auto text = m_client->get_text(); | ||||
|     IniLexer lexer(text); | ||||
|     auto tokens = lexer.lex(); | ||||
| 
 | ||||
|  | @ -77,12 +76,12 @@ void IniSyntaxHighlighter::rehighlight(Gfx::Palette palette) | |||
|         span.data = reinterpret_cast<void*>(token.m_type); | ||||
|         spans.append(span); | ||||
|     } | ||||
|     m_editor->document().set_spans(spans); | ||||
|     m_client->do_set_spans(move(spans)); | ||||
| 
 | ||||
|     m_has_brace_buddies = false; | ||||
|     highlight_matching_token_pair(); | ||||
| 
 | ||||
|     m_editor->update(); | ||||
|     m_client->do_update(); | ||||
| } | ||||
| 
 | ||||
| Vector<IniSyntaxHighlighter::MatchingTokenPair> IniSyntaxHighlighter::matching_token_pairs() const | ||||
|  |  | |||
|  | @ -502,25 +502,24 @@ bool ShellSyntaxHighlighter::is_navigatable(void* token) const | |||
| 
 | ||||
| void ShellSyntaxHighlighter::rehighlight(Gfx::Palette palette) | ||||
| { | ||||
|     ASSERT(m_editor); | ||||
|     auto text = m_editor->text(); | ||||
|     auto text = m_client->get_text(); | ||||
| 
 | ||||
|     Parser parser(text); | ||||
|     auto ast = parser.parse(); | ||||
| 
 | ||||
|     Vector<GUI::TextDocumentSpan> spans; | ||||
|     GUI::TextPosition position { 0, 0 }; | ||||
|     HighlightVisitor visitor { spans, palette, m_editor->document() }; | ||||
|     HighlightVisitor visitor { spans, palette, m_client->get_document() }; | ||||
| 
 | ||||
|     if (ast) | ||||
|         ast->visit(visitor); | ||||
| 
 | ||||
|     quick_sort(spans, [](auto& a, auto& b) { return a.range.start() < b.range.start(); }); | ||||
| 
 | ||||
|     m_editor->document().set_spans(spans); | ||||
|     m_client->do_set_spans(move(spans)); | ||||
|     m_has_brace_buddies = false; | ||||
|     highlight_matching_token_pair(); | ||||
|     m_editor->update(); | ||||
|     m_client->do_update(); | ||||
| } | ||||
| 
 | ||||
| Vector<Syntax::Highlighter::MatchingTokenPair> ShellSyntaxHighlighter::matching_token_pairs() const | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> | ||||
|  * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  | @ -79,7 +79,7 @@ public: | |||
|     const TextDocumentLine& line(size_t line_index) const { return m_lines[line_index]; } | ||||
|     TextDocumentLine& line(size_t line_index) { return m_lines[line_index]; } | ||||
| 
 | ||||
|     void set_spans(const Vector<TextDocumentSpan>& spans) { m_spans = spans; } | ||||
|     void set_spans(Vector<TextDocumentSpan> spans) { m_spans = move(spans); } | ||||
| 
 | ||||
|     void set_text(const StringView&); | ||||
| 
 | ||||
|  |  | |||
|  | @ -37,13 +37,15 @@ | |||
| #include <LibGUI/TextRange.h> | ||||
| #include <LibGfx/TextAlignment.h> | ||||
| #include <LibSyntax/Forward.h> | ||||
| #include <LibSyntax/HighlighterClient.h> | ||||
| 
 | ||||
| namespace GUI { | ||||
| 
 | ||||
| class TextEditor | ||||
|     : public ScrollableWidget | ||||
|     , public TextDocument::Client { | ||||
|     C_OBJECT(TextEditor) | ||||
|     , public TextDocument::Client | ||||
|     , public Syntax::HighlighterClient { | ||||
|     C_OBJECT(TextEditor); | ||||
| 
 | ||||
| public: | ||||
|     enum Type { | ||||
|  | @ -241,6 +243,16 @@ private: | |||
|     virtual void document_did_set_text() override; | ||||
|     virtual void document_did_set_cursor(const TextPosition&) override; | ||||
| 
 | ||||
|     // ^Syntax::HighlighterClient
 | ||||
|     virtual Vector<TextDocumentSpan>& spans() final { return document().spans(); } | ||||
|     virtual const Vector<TextDocumentSpan>& spans() const final { return document().spans(); } | ||||
|     virtual void highlighter_did_set_spans(Vector<TextDocumentSpan> spans) { document().set_spans(move(spans)); } | ||||
|     virtual void set_span_at_index(size_t index, TextDocumentSpan span) final { document().set_span_at_index(index, move(span)); } | ||||
|     virtual void highlighter_did_request_update() final { update(); } | ||||
|     virtual String highlighter_did_request_text() const final { return text(); } | ||||
|     virtual GUI::TextDocument& highlighter_did_request_document() final { return document(); } | ||||
|     virtual GUI::TextPosition highlighter_did_request_cursor() const final { return m_cursor; } | ||||
| 
 | ||||
|     void create_actions(); | ||||
|     void paint_ruler(Painter&); | ||||
|     void update_content_size(); | ||||
|  |  | |||
|  | @ -81,8 +81,9 @@ set(SOURCES | |||
|     Runtime/VM.cpp | ||||
|     Runtime/Value.cpp | ||||
|     Runtime/WithScope.cpp | ||||
|     SyntaxHighlighter.cpp | ||||
|     Token.cpp | ||||
| ) | ||||
| 
 | ||||
| serenity_lib(LibJS js) | ||||
| target_link_libraries(LibJS LibM LibCore LibCrypto LibRegex) | ||||
| target_link_libraries(LibJS LibM LibCore LibCrypto LibRegex LibSyntax) | ||||
|  |  | |||
|  | @ -25,16 +25,16 @@ | |||
|  */ | ||||
| 
 | ||||
| #include <AK/Debug.h> | ||||
| #include <LibGUI/JSSyntaxHighlighter.h> | ||||
| #include <LibGUI/TextEditor.h> | ||||
| #include <LibGfx/Font.h> | ||||
| #include <LibGfx/Palette.h> | ||||
| #include <LibJS/Lexer.h> | ||||
| #include <LibJS/SyntaxHighlighter.h> | ||||
| #include <LibJS/Token.h> | ||||
| 
 | ||||
| namespace GUI { | ||||
| namespace JS { | ||||
| 
 | ||||
| static Syntax::TextStyle style_for_token_type(Gfx::Palette palette, JS::TokenType type) | ||||
| static Syntax::TextStyle style_for_token_type(const Gfx::Palette& palette, JS::TokenType type) | ||||
| { | ||||
|     switch (JS::Token::category(type)) { | ||||
|     case JS::TokenCategory::Invalid: | ||||
|  | @ -58,21 +58,20 @@ static Syntax::TextStyle style_for_token_type(Gfx::Palette palette, JS::TokenTyp | |||
|     } | ||||
| } | ||||
| 
 | ||||
| bool JSSyntaxHighlighter::is_identifier(void* token) const | ||||
| bool SyntaxHighlighter::is_identifier(void* token) const | ||||
| { | ||||
|     auto js_token = static_cast<JS::TokenType>(reinterpret_cast<size_t>(token)); | ||||
|     return js_token == JS::TokenType::Identifier; | ||||
| } | ||||
| 
 | ||||
| bool JSSyntaxHighlighter::is_navigatable([[maybe_unused]] void* token) const | ||||
| bool SyntaxHighlighter::is_navigatable([[maybe_unused]] void* token) const | ||||
| { | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| void JSSyntaxHighlighter::rehighlight(Gfx::Palette palette) | ||||
| void SyntaxHighlighter::rehighlight(Gfx::Palette palette) | ||||
| { | ||||
|     ASSERT(m_editor); | ||||
|     auto text = m_editor->text(); | ||||
|     auto text = m_client->get_text(); | ||||
| 
 | ||||
|     JS::Lexer lexer(text); | ||||
| 
 | ||||
|  | @ -125,15 +124,15 @@ void JSSyntaxHighlighter::rehighlight(Gfx::Palette palette) | |||
|             was_eof = true; | ||||
|     } | ||||
| 
 | ||||
|     m_editor->document().set_spans(spans); | ||||
|     m_client->do_set_spans(move(spans)); | ||||
| 
 | ||||
|     m_has_brace_buddies = false; | ||||
|     highlight_matching_token_pair(); | ||||
| 
 | ||||
|     m_editor->update(); | ||||
|     m_client->do_update(); | ||||
| } | ||||
| 
 | ||||
| Vector<Syntax::Highlighter::MatchingTokenPair> JSSyntaxHighlighter::matching_token_pairs() const | ||||
| Vector<Syntax::Highlighter::MatchingTokenPair> SyntaxHighlighter::matching_token_pairs() const | ||||
| { | ||||
|     static Vector<Syntax::Highlighter::MatchingTokenPair> pairs; | ||||
|     if (pairs.is_empty()) { | ||||
|  | @ -144,12 +143,12 @@ Vector<Syntax::Highlighter::MatchingTokenPair> JSSyntaxHighlighter::matching_tok | |||
|     return pairs; | ||||
| } | ||||
| 
 | ||||
| bool JSSyntaxHighlighter::token_types_equal(void* token1, void* token2) const | ||||
| bool SyntaxHighlighter::token_types_equal(void* token1, void* token2) const | ||||
| { | ||||
|     return static_cast<JS::TokenType>(reinterpret_cast<size_t>(token1)) == static_cast<JS::TokenType>(reinterpret_cast<size_t>(token2)); | ||||
| } | ||||
| 
 | ||||
| JSSyntaxHighlighter::~JSSyntaxHighlighter() | ||||
| SyntaxHighlighter::~SyntaxHighlighter() | ||||
| { | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,12 +28,12 @@ | |||
| 
 | ||||
| #include <LibSyntax/Highlighter.h> | ||||
| 
 | ||||
| namespace GUI { | ||||
| namespace JS { | ||||
| 
 | ||||
| class JSSyntaxHighlighter : public Syntax::Highlighter { | ||||
| class SyntaxHighlighter : public Syntax::Highlighter { | ||||
| public: | ||||
|     JSSyntaxHighlighter() { } | ||||
|     virtual ~JSSyntaxHighlighter() override; | ||||
|     SyntaxHighlighter() { } | ||||
|     virtual ~SyntaxHighlighter() override; | ||||
| 
 | ||||
|     virtual bool is_identifier(void*) const override; | ||||
|     virtual bool is_navigatable(void*) const override; | ||||
|  |  | |||
|  | @ -29,5 +29,6 @@ | |||
| namespace Syntax { | ||||
| 
 | ||||
| class Highlighter; | ||||
| class HighlighterClient; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ | |||
|  */ | ||||
| 
 | ||||
| #include <LibGUI/TextEditor.h> | ||||
| #include <LibGfx/Color.h> | ||||
| #include <LibSyntax/Highlighter.h> | ||||
| 
 | ||||
| namespace Syntax { | ||||
|  | @ -35,8 +36,7 @@ Highlighter::~Highlighter() | |||
| 
 | ||||
| void Highlighter::highlight_matching_token_pair() | ||||
| { | ||||
|     ASSERT(m_editor); | ||||
|     auto& document = m_editor->document(); | ||||
|     auto& document = m_client->get_document(); | ||||
| 
 | ||||
|     enum class Direction { | ||||
|         Forward, | ||||
|  | @ -93,7 +93,7 @@ void Highlighter::highlight_matching_token_pair() | |||
|         buddy1.attributes.background_color = Color::DarkCyan; | ||||
|         buddy0.attributes.color = Color::White; | ||||
|         buddy1.attributes.color = Color::White; | ||||
|         m_editor->update(); | ||||
|         m_client->do_update(); | ||||
|     }; | ||||
| 
 | ||||
|     auto pairs = matching_token_pairs(); | ||||
|  | @ -103,7 +103,7 @@ void Highlighter::highlight_matching_token_pair() | |||
|         auto token_type = span.data; | ||||
| 
 | ||||
|         for (auto& pair : pairs) { | ||||
|             if (token_types_equal(token_type, pair.open) && span.range.start() == m_editor->cursor()) { | ||||
|             if (token_types_equal(token_type, pair.open) && span.range.start() == m_client->get_cursor()) { | ||||
|                 auto buddy = find_span_of_type(i, pair.close, pair.open, Direction::Forward); | ||||
|                 if (buddy.has_value()) | ||||
|                     make_buddies(i, buddy.value()); | ||||
|  | @ -115,7 +115,7 @@ void Highlighter::highlight_matching_token_pair() | |||
|         right_of_end.set_column(right_of_end.column() + 1); | ||||
| 
 | ||||
|         for (auto& pair : pairs) { | ||||
|             if (token_types_equal(token_type, pair.close) && right_of_end == m_editor->cursor()) { | ||||
|             if (token_types_equal(token_type, pair.close) && right_of_end == m_client->get_cursor()) { | ||||
|                 auto buddy = find_span_of_type(i, pair.open, pair.close, Direction::Backward); | ||||
|                 if (buddy.has_value()) | ||||
|                     make_buddies(i, buddy.value()); | ||||
|  | @ -125,29 +125,27 @@ void Highlighter::highlight_matching_token_pair() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void Highlighter::attach(GUI::TextEditor& editor) | ||||
| void Highlighter::attach(HighlighterClient& client) | ||||
| { | ||||
|     ASSERT(!m_editor); | ||||
|     m_editor = editor; | ||||
|     ASSERT(!m_client); | ||||
|     m_client = &client; | ||||
| } | ||||
| 
 | ||||
| void Highlighter::detach() | ||||
| { | ||||
|     ASSERT(m_editor); | ||||
|     m_editor = nullptr; | ||||
|     m_client = nullptr; | ||||
| } | ||||
| 
 | ||||
| void Highlighter::cursor_did_change() | ||||
| { | ||||
|     ASSERT(m_editor); | ||||
|     auto& document = m_editor->document(); | ||||
|     auto& document = m_client->get_document(); | ||||
|     if (m_has_brace_buddies) { | ||||
|         if (m_brace_buddies[0].index >= 0 && m_brace_buddies[0].index < static_cast<int>(document.spans().size())) | ||||
|             document.set_span_at_index(m_brace_buddies[0].index, m_brace_buddies[0].span_backup); | ||||
|         if (m_brace_buddies[1].index >= 0 && m_brace_buddies[1].index < static_cast<int>(document.spans().size())) | ||||
|             document.set_span_at_index(m_brace_buddies[1].index, m_brace_buddies[1].span_backup); | ||||
|         m_has_brace_buddies = false; | ||||
|         m_editor->update(); | ||||
|         m_client->do_update(); | ||||
|     } | ||||
|     highlight_matching_token_pair(); | ||||
| } | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ | |||
| #include <AK/WeakPtr.h> | ||||
| #include <LibGUI/TextDocument.h> | ||||
| #include <LibGfx/Palette.h> | ||||
| #include <LibSyntax/HighlighterClient.h> | ||||
| 
 | ||||
| namespace Syntax { | ||||
| 
 | ||||
|  | @ -61,14 +62,15 @@ public: | |||
|     virtual bool is_identifier(void*) const { return false; }; | ||||
|     virtual bool is_navigatable(void*) const { return false; }; | ||||
| 
 | ||||
|     void attach(GUI::TextEditor& editor); | ||||
|     void attach(HighlighterClient&); | ||||
|     void detach(); | ||||
|     void cursor_did_change(); | ||||
| 
 | ||||
| protected: | ||||
|     Highlighter() { } | ||||
| 
 | ||||
|     WeakPtr<GUI::TextEditor> m_editor; | ||||
|     // FIXME: This should be WeakPtr somehow
 | ||||
|     HighlighterClient* m_client { nullptr }; | ||||
| 
 | ||||
|     struct MatchingTokenPair { | ||||
|         void* open; | ||||
|  |  | |||
							
								
								
									
										55
									
								
								Userland/Libraries/LibSyntax/HighlighterClient.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								Userland/Libraries/LibSyntax/HighlighterClient.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  * | ||||
|  * 1. Redistributions of source code must retain the above copyright notice, this | ||||
|  *    list of conditions and the following disclaimer. | ||||
|  * | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||
|  *    this list of conditions and the following disclaimer in the documentation | ||||
|  *    and/or other materials provided with the distribution. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
|  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
|  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
|  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
|  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
|  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <LibGUI/Forward.h> | ||||
| 
 | ||||
| namespace Syntax { | ||||
| 
 | ||||
| class HighlighterClient { | ||||
| public: | ||||
|     virtual ~HighlighterClient() = default; | ||||
| 
 | ||||
|     virtual Vector<GUI::TextDocumentSpan>& spans() = 0; | ||||
|     virtual const Vector<GUI::TextDocumentSpan>& spans() const = 0; | ||||
|     virtual void set_span_at_index(size_t index, GUI::TextDocumentSpan span) = 0; | ||||
| 
 | ||||
|     virtual String highlighter_did_request_text() const = 0; | ||||
|     virtual void highlighter_did_request_update() = 0; | ||||
|     virtual GUI::TextDocument& highlighter_did_request_document() = 0; | ||||
|     virtual GUI::TextPosition highlighter_did_request_cursor() const = 0; | ||||
|     virtual void highlighter_did_set_spans(Vector<GUI::TextDocumentSpan>) = 0; | ||||
| 
 | ||||
|     void do_set_spans(Vector<GUI::TextDocumentSpan> spans) { highlighter_did_set_spans(move(spans)); } | ||||
|     void do_update() { highlighter_did_request_update(); } | ||||
| 
 | ||||
|     String get_text() const { return highlighter_did_request_text(); } | ||||
|     GUI::TextDocument& get_document() { return highlighter_did_request_document(); } | ||||
|     GUI::TextPosition get_cursor() const { return highlighter_did_request_cursor(); } | ||||
| }; | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling