Browse Source

HackStudio: Assorted improvements to C++ highlighting

Add a list of hard-coded standard types (including AK types) and show
them in a different style.

Rehighligt the file whenever it changes. (This is very inefficient but
makes it much easier to experiment.)

Also keep tweaking the colors. :^)
Andreas Kling 5 years ago
parent
commit
ed242d538a
3 changed files with 111 additions and 36 deletions
  1. 71 14
      DevTools/HackStudio/CppLexer.cpp
  2. 1 0
      DevTools/HackStudio/CppLexer.h
  3. 39 22
      DevTools/HackStudio/main.cpp

+ 71 - 14
DevTools/HackStudio/CppLexer.cpp

@@ -48,28 +48,22 @@ static bool is_keyword(const StringView& string)
         keywords.set("and");
         keywords.set("and_eq");
         keywords.set("asm");
-        keywords.set("auto");
         keywords.set("bitand");
         keywords.set("bitor");
         keywords.set("bool");
         keywords.set("break");
         keywords.set("case");
         keywords.set("catch");
-        keywords.set("char");
-        keywords.set("char8_t");
-        keywords.set("char16_t");
-        keywords.set("char32_t");
         keywords.set("class");
         keywords.set("compl");
         keywords.set("const");
-        keywords.set("constexpr");
         keywords.set("const_cast");
+        keywords.set("constexpr");
         keywords.set("continue");
         keywords.set("decltype");
         keywords.set("default");
         keywords.set("delete");
         keywords.set("do");
-        keywords.set("double");
         keywords.set("dynamic_cast");
         keywords.set("else");
         keywords.set("enum");
@@ -77,14 +71,12 @@ static bool is_keyword(const StringView& string)
         keywords.set("export");
         keywords.set("extern");
         keywords.set("false");
-        keywords.set("float");
+        keywords.set("final");
         keywords.set("for");
         keywords.set("friend");
         keywords.set("goto");
         keywords.set("if");
         keywords.set("inline");
-        keywords.set("int");
-        keywords.set("long");
         keywords.set("mutable");
         keywords.set("namespace");
         keywords.set("new");
@@ -95,13 +87,13 @@ static bool is_keyword(const StringView& string)
         keywords.set("operator");
         keywords.set("or");
         keywords.set("or_eq");
+        keywords.set("override");
         keywords.set("private");
         keywords.set("protected");
         keywords.set("public");
         keywords.set("register");
         keywords.set("reinterpret_cast");
         keywords.set("return");
-        keywords.set("short");
         keywords.set("signed");
         keywords.set("sizeof");
         keywords.set("static");
@@ -119,12 +111,9 @@ static bool is_keyword(const StringView& string)
         keywords.set("typeid");
         keywords.set("typename");
         keywords.set("union");
-        keywords.set("unsigned");
         keywords.set("using");
         keywords.set("virtual");
-        keywords.set("void");
         keywords.set("volatile");
-        keywords.set("wchar_t");
         keywords.set("while");
         keywords.set("xor");
         keywords.set("xor_eq");
@@ -132,6 +121,72 @@ static bool is_keyword(const StringView& string)
     return keywords.contains(string);
 }
 
+static bool is_known_type(const StringView& string)
+{
+    static HashTable<String> types;
+    if (types.is_empty()) {
+        types.set("ByteBuffer");
+        types.set("CircularDeque");
+        types.set("CircularQueue");
+        types.set("Deque");
+        types.set("DoublyLinkedList");
+        types.set("FileSystemPath");
+        types.set("FixedArray");
+        types.set("Function");
+        types.set("HashMap");
+        types.set("HashTable");
+        types.set("IPv4Address");
+        types.set("InlineLinkedList");
+        types.set("IntrusiveList");
+        types.set("JsonArray");
+        types.set("JsonObject");
+        types.set("JsonValue");
+        types.set("MappedFile");
+        types.set("NetworkOrdered");
+        types.set("NonnullOwnPtr");
+        types.set("NonnullOwnPtrVector");
+        types.set("NonnullRefPtr");
+        types.set("NonnullRefPtrVector");
+        types.set("Optional");
+        types.set("OwnPtr");
+        types.set("RefPtr");
+        types.set("Result");
+        types.set("ScopeGuard");
+        types.set("SinglyLinkedList");
+        types.set("String");
+        types.set("StringBuilder");
+        types.set("StringImpl");
+        types.set("StringView");
+        types.set("Utf8View");
+        types.set("Vector");
+        types.set("WeakPtr");
+        types.set("auto");
+        types.set("char");
+        types.set("char16_t");
+        types.set("char32_t");
+        types.set("char8_t");
+        types.set("double");
+        types.set("float");
+        types.set("i16");
+        types.set("i32");
+        types.set("i64");
+        types.set("i8");
+        types.set("int");
+        types.set("int");
+        types.set("long");
+        types.set("short");
+        types.set("signed");
+        types.set("u16");
+        types.set("u32");
+        types.set("u64");
+        types.set("u8");
+        types.set("unsigned");
+        types.set("void");
+        types.set("wchar_t");
+    }
+    return types.contains(string);
+}
+
 Vector<CppToken> CppLexer::lex()
 {
     Vector<CppToken> tokens;
@@ -268,6 +323,8 @@ Vector<CppToken> CppLexer::lex()
             auto token_view = StringView(m_input.characters_without_null_termination() + token_start_index, m_index - token_start_index);
             if (is_keyword(token_view))
                 commit_token(CppToken::Type::Keyword);
+            else if (is_known_type(token_view))
+                commit_token(CppToken::Type::KnownType);
             else
                 commit_token(CppToken::Type::Identifier);
             continue;

+ 1 - 0
DevTools/HackStudio/CppLexer.h

@@ -21,6 +21,7 @@
     __TOKEN(Comment)               \
     __TOKEN(Number)                \
     __TOKEN(Keyword)               \
+    __TOKEN(KnownType)             \
     __TOKEN(Identifier)
 
 struct CppPosition {

+ 39 - 22
DevTools/HackStudio/main.cpp

@@ -178,6 +178,8 @@ int main(int argc, char** argv)
     g_window->set_icon(small_icon);
 
     g_window->show();
+
+    open_file("main.cpp");
     return app.exec();
 }
 
@@ -201,21 +203,46 @@ static TextStyle style_for_token_type(CppToken::Type type)
     switch (type) {
     case CppToken::Type::Keyword:
         return { Color::Black, &Font::default_bold_fixed_width_font() };
+    case CppToken::Type::KnownType:
+        return { Color::from_rgb(0x929200), &Font::default_bold_fixed_width_font() };
     case CppToken::Type::Identifier:
-        return { Color::Blue };
+        return { Color::from_rgb(0x000092), &Font::default_bold_fixed_width_font() };
     case CppToken::Type::DoubleQuotedString:
     case CppToken::Type::SingleQuotedString:
     case CppToken::Type::Number:
-        return { Color::Red };
+        return { Color::from_rgb(0x920000) };
     case CppToken::Type::PreprocessorStatement:
-        return { Color::Magenta };
+        return { Color::from_rgb(0x009292) };
     case CppToken::Type::Comment:
-        return { Color::from_rgb(0x008200) };
+        return { Color::from_rgb(0x009200) };
     default:
         return { Color::Black };
     }
 }
 
+static void rehighlight()
+{
+    auto text = g_text_editor->text();
+    CppLexer lexer(text);
+    auto tokens = lexer.lex();
+
+    Vector<GTextEditor::Span> spans;
+    for (auto& token : tokens) {
+#ifdef DEBUG_SYNTAX_HIGHLIGHTING
+        dbg() << token.to_string() << " @ " << token.m_start.line << ":" << token.m_start.column << " - " << token.m_end.line << ":" << token.m_end.column;
+#endif
+        GTextEditor::Span span;
+        span.start = { token.m_start.line, token.m_start.column };
+        span.end = { token.m_end.line, token.m_end.column };
+        auto style = style_for_token_type(token.m_type);
+        span.color = style.color;
+        span.font = style.font;
+        spans.append(span);
+    }
+    g_text_editor->set_spans(spans);
+    g_text_editor->update();
+}
+
 void open_file(const String& filename)
 {
     auto file = CFile::construct(filename);
@@ -225,25 +252,15 @@ void open_file(const String& filename)
     }
     auto contents = file->read_all();
     g_text_editor->set_text(contents);
-    g_currently_open_file = filename;
-    g_window->set_title(String::format("%s - HackStudio", g_currently_open_file.characters()));
-    g_project_list_view->update();
 
     if (filename.ends_with(".cpp")) {
-        CppLexer lexer(contents);
-        auto tokens = lexer.lex();
-
-        Vector<GTextEditor::Span> spans;
-        for (auto& token : tokens) {
-            dbg() << token.to_string() << " @ " << token.m_start.line << ":" << token.m_start.column << " - " << token.m_end.line << ":" << token.m_end.column;
-            GTextEditor::Span span;
-            span.start = { token.m_start.line, token.m_start.column };
-            span.end = { token.m_end.line, token.m_end.column };
-            auto style = style_for_token_type(token.m_type);
-            span.color = style.color;
-            span.font = style.font;
-            spans.append(span);
-        }
-        g_text_editor->set_spans(spans);
+        g_text_editor->on_change = [] { rehighlight(); };
+        rehighlight();
+    } else {
+        g_text_editor->on_change = nullptr;
     }
+
+    g_currently_open_file = filename;
+    g_window->set_title(String::format("%s - HackStudio", g_currently_open_file.characters()));
+    g_project_list_view->update();
 }