diff --git a/CMakeLists.txt b/CMakeLists.txt index 40d5617..165118a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ set(INCLUDE_FILES include/QSyntaxStyle include/QGLSLCompleter include/QGLSLHighlighter + include/QJavaHighlighter include/QLanguage include/QXMLHighlighter include/QJSONHighlighter @@ -35,6 +36,7 @@ set(INCLUDE_FILES include/internal/QHighlightBlockRule.hpp include/internal/QCodeEditor.hpp include/internal/QCXXHighlighter.hpp + include/internal/QJavaHighlighter.hpp include/internal/QLineNumberArea.hpp include/internal/QStyleSyntaxHighlighter.hpp include/internal/QSyntaxStyle.hpp @@ -58,6 +60,7 @@ set(SOURCE_FILES src/internal/QStyleSyntaxHighlighter.cpp src/internal/QGLSLCompleter.cpp src/internal/QGLSLHighlighter.cpp + src/internal/QJavaHighlighter.cpp src/internal/QLanguage.cpp src/internal/QXMLHighlighter.cpp src/internal/QJSONHighlighter.cpp diff --git a/example/resources/code_samples/java.java b/example/resources/code_samples/java.java new file mode 100644 index 0000000..8124220 --- /dev/null +++ b/example/resources/code_samples/java.java @@ -0,0 +1,32 @@ +import java.util.Scanner; + +/* This program is simply for demonstrating + * the highlighting of Java syntax. + */ + +class Animal { } + +class Dog extends Animal { } + +public class Example { + /** Prompts the user for a string and returns what they entered. + * @param message The message to display to the user. + * @return The string that the user entered. + * */ + static String prompt(String message) { + + Scanner scanner = new Scanner(System.in); + + System.out.printf("%s: ", message); + + return scanner.nextLine(); + } + public static void main(String[] args) { + + double pi = 3.1415; + + String name = prompt("Enter your name"); + + System.out.println("Nice to meet you, " + name + "!"); + } +} diff --git a/example/resources/demo_resources.qrc b/example/resources/demo_resources.qrc index 146657b..5c8a966 100644 --- a/example/resources/demo_resources.qrc +++ b/example/resources/demo_resources.qrc @@ -4,6 +4,7 @@ code_samples/cxx.cpp code_samples/shader.glsl code_samples/xml.xml + code_samples/java.java code_samples/json.json code_samples/lua.lua code_samples/python.py diff --git a/example/src/MainWindow.cpp b/example/src/MainWindow.cpp index 5552835..c568294 100644 --- a/example/src/MainWindow.cpp +++ b/example/src/MainWindow.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,7 @@ void MainWindow::initData() {"C++", loadCode(":/code_samples/cxx.cpp")}, {"GLSL", loadCode(":/code_samples/shader.glsl")}, {"XML", loadCode(":/code_samples/xml.xml")}, + {"Java", loadCode(":/code_samples/java.java")}, {"JSON", loadCode(":/code_samples/json.json")}, {"LUA", loadCode(":/code_samples/lua.lua")}, {"Python", loadCode(":/code_samples/python.py")} @@ -70,6 +72,7 @@ void MainWindow::initData() {"C++", new QCXXHighlighter}, {"GLSL", new QGLSLHighlighter}, {"XML", new QXMLHighlighter}, + {"Java", new QJavaHighlighter }, {"JSON", new QJSONHighlighter}, {"LUA", new QLuaHighlighter}, {"Python", new QPythonHighlighter}, diff --git a/include/QJavaHighlighter b/include/QJavaHighlighter new file mode 100644 index 0000000..724e567 --- /dev/null +++ b/include/QJavaHighlighter @@ -0,0 +1,3 @@ +#pragma once + +#include diff --git a/include/internal/QJavaHighlighter.hpp b/include/internal/QJavaHighlighter.hpp new file mode 100644 index 0000000..54222fd --- /dev/null +++ b/include/internal/QJavaHighlighter.hpp @@ -0,0 +1,42 @@ +#pragma once + +// QCodeEditor +#include // Required for inheritance +#include + +// Qt +#include +#include + +class QSyntaxStyle; + +/** + * @brief Derived to implement highlighting of Java code. + */ +class QJavaHighlighter : public QStyleSyntaxHighlighter +{ + Q_OBJECT +public: + + /** + * @brief Constructs a new instance of a Java highlighter. + * @param document The text document to be highlighted. + * This may be a null pointer. + */ + explicit QJavaHighlighter(QTextDocument* document=nullptr); + +protected: + /** + * @brief Derived to highlight blocks of Java code. + * @param text The block of text containing Java code. + */ + void highlightBlock(const QString& text) override; + +private: + + QVector m_highlightRules; + + QRegularExpression m_commentStartPattern; + QRegularExpression m_commentEndPattern; +}; + diff --git a/resources/languages/glsl.xml b/resources/languages/glsl.xml index b543233..595a8fe 100644 --- a/resources/languages/glsl.xml +++ b/resources/languages/glsl.xml @@ -351,4 +351,4 @@ iimage2DMSArray uimage2DMSArray - \ No newline at end of file + diff --git a/resources/languages/java.xml b/resources/languages/java.xml new file mode 100644 index 0000000..3fbbdbb --- /dev/null +++ b/resources/languages/java.xml @@ -0,0 +1,62 @@ + + +
+ abstract + assert + break + case + catch + const + continue + default + do + else + extends + final + finally + for + if + goto + implements + import + instanceof + native + new + package + private + protected + public + return + static + strictfp + super + switch + synchronized + this + throw + throws + transient + try + volatile + while + + true + false + null + +
+
+ boolean + byte + char + class + double + enum + float + int + interface + long + short + void +
+
diff --git a/resources/qcodeeditor_resources.qrc b/resources/qcodeeditor_resources.qrc index ff73feb..bade058 100644 --- a/resources/qcodeeditor_resources.qrc +++ b/resources/qcodeeditor_resources.qrc @@ -3,6 +3,7 @@ default_style.xml languages/glsl.xml languages/cpp.xml + languages/java.xml languages/lua.xml languages/python.xml diff --git a/src/internal/QJavaHighlighter.cpp b/src/internal/QJavaHighlighter.cpp new file mode 100644 index 0000000..79ad79b --- /dev/null +++ b/src/internal/QJavaHighlighter.cpp @@ -0,0 +1,114 @@ +// QCodeEditor +#include +#include +#include + +// Qt +#include + + +QJavaHighlighter::QJavaHighlighter(QTextDocument* document) : + QStyleSyntaxHighlighter(document), + m_highlightRules (), + m_commentStartPattern(QRegularExpression(R"(/\*)")), + m_commentEndPattern (QRegularExpression(R"(\*/)")) +{ + Q_INIT_RESOURCE(qcodeeditor_resources); + + QFile fl(":/languages/java.xml"); + + if (!fl.open(QIODevice::ReadOnly)) + { + return; + } + + QLanguage language(&fl); + + if (!language.isLoaded()) + { + return; + } + + auto keys = language.keys(); + for (auto&& key : keys) + { + auto names = language.names(key); + for (auto&& name : names) + { + m_highlightRules.append({ + QRegularExpression(QString(R"(\b%1\b)").arg(name)), + key + }); + } + } + + // Numbers + m_highlightRules.append({ + QRegularExpression(R"((?<=\b|\s|^)(?i)(?:(?:(?:(?:(?:\d+(?:'\d+)*)?\.(?:\d+(?:'\d+)*)(?:e[+-]?(?:\d+(?:'\d+)*))?)|(?:(?:\d+(?:'\d+)*)\.(?:e[+-]?(?:\d+(?:'\d+)*))?)|(?:(?:\d+(?:'\d+)*)(?:e[+-]?(?:\d+(?:'\d+)*)))|(?:0x(?:[0-9a-f]+(?:'[0-9a-f]+)*)?\.(?:[0-9a-f]+(?:'[0-9a-f]+)*)(?:p[+-]?(?:\d+(?:'\d+)*)))|(?:0x(?:[0-9a-f]+(?:'[0-9a-f]+)*)\.?(?:p[+-]?(?:\d+(?:'\d+)*))))[lf]?)|(?:(?:(?:[1-9]\d*(?:'\d+)*)|(?:0[0-7]*(?:'[0-7]+)*)|(?:0x[0-9a-f]+(?:'[0-9a-f]+)*)|(?:0b[01]+(?:'[01]+)*))(?:u?l{0,2}|l{0,2}u?)))(?=\b|\s|$))"), + "Number" + }); + + // Strings + m_highlightRules.append({ + QRegularExpression(R"("[^\n"]*")"), + "String" + }); + + // Single line + m_highlightRules.append({ + QRegularExpression(R"(//[^\n]*)"), + "Comment" + }); +} + +void QJavaHighlighter::highlightBlock(const QString& text) +{ + for (auto& rule : m_highlightRules) + { + auto matchIterator = rule.pattern.globalMatch(text); + + while (matchIterator.hasNext()) + { + auto match = matchIterator.next(); + + setFormat( + match.capturedStart(), + match.capturedLength(), + syntaxStyle()->getFormat(rule.formatName) + ); + } + } + + setCurrentBlockState(0); + + int startIndex = 0; + if (previousBlockState() != 1) + { + startIndex = text.indexOf(m_commentStartPattern); + } + + while (startIndex >= 0) + { + auto match = m_commentEndPattern.match(text, startIndex); + + int endIndex = match.capturedStart(); + int commentLength = 0; + + if (endIndex == -1) + { + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } + else + { + commentLength = endIndex - startIndex + match.capturedLength(); + } + + setFormat( + startIndex, + commentLength, + syntaxStyle()->getFormat("Comment") + ); + startIndex = text.indexOf(m_commentStartPattern, startIndex + commentLength); + } +}