Improve JavaScriptHighlighter

* Fix greediness for string highlighting
* Adjust colors
* Port to QRegularExpression
This commit is contained in:
Martchus 2018-08-15 22:23:57 +02:00
parent db2f178542
commit a32db9e33d
2 changed files with 46 additions and 35 deletions

View File

@ -7,69 +7,78 @@ JavaScriptHighlighter::JavaScriptHighlighter(QTextDocument *parent)
{ {
HighlightingRule rule; HighlightingRule rule;
m_keywordFormat.setForeground(Qt::darkBlue);
m_keywordFormat.setFontWeight(QFont::Bold); m_keywordFormat.setFontWeight(QFont::Bold);
static const QStringList keywordPatterns{ QStringLiteral("\\bvar\\b"), QStringLiteral("\\bArray\\b"), QStringLiteral("\\bfunction\\b"), static const QStringList keywordPatterns{ QStringLiteral("\\bvar\\b"), QStringLiteral("\\bArray\\b"), QStringLiteral("\\bfunction\\b"),
QStringLiteral("\\breturn\\b"), QStringLiteral("\\barguments\\b"), QStringLiteral("\\bif\\b"), QStringLiteral("\\belse\\b"), QStringLiteral("\\breturn\\b"), QStringLiteral("\\barguments\\b"), QStringLiteral("\\bif\\b"), QStringLiteral("\\belse\\b"),
QStringLiteral("\\bfor\\b"), QStringLiteral("\\bswitch\\b"), QStringLiteral("\\bcase\\b"), QStringLiteral("\\bbreak\\b"), QStringLiteral("\\bfor\\b"), QStringLiteral("\\bswitch\\b"), QStringLiteral("\\bcase\\b"), QStringLiteral("\\bbreak\\b"),
QStringLiteral("\\bwhile\\b"), QStringLiteral("\\bundefined\\b"), QStringLiteral("\\continue\\b") }; QStringLiteral("\\bwhile\\b"), QStringLiteral("\\bundefined\\b"), QStringLiteral("\\continue\\b") };
for (const QString &pattern : keywordPatterns) { for (const auto &pattern : keywordPatterns) {
rule.pattern = QRegExp(pattern); rule.pattern = QRegularExpression(pattern);
rule.pattern.setPatternOptions(QRegularExpression::InvertedGreedinessOption);
rule.format = m_keywordFormat; rule.format = m_keywordFormat;
m_highlightingRules.append(rule); m_highlightingRules.append(rule);
} }
m_singleLineCommentFormat.setForeground(Qt::red); m_singleLineCommentFormat.setForeground(Qt::darkGray);
rule.pattern = QRegExp(QStringLiteral("//[^\n]*")); rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*"));
rule.format = m_singleLineCommentFormat; rule.format = m_singleLineCommentFormat;
m_highlightingRules.append(rule); m_highlightingRules.append(rule);
m_multiLineCommentFormat.setForeground(Qt::red); m_multiLineCommentFormat.setForeground(Qt::darkGray);
m_quotationFormat.setForeground(Qt::darkGreen); m_regexFormat.setForeground(Qt::darkMagenta);
rule.pattern = QRegExp(QStringLiteral("\".*\"")); rule.pattern = QRegularExpression(QStringLiteral("/.*/"));
rule.format = m_quotationFormat; rule.pattern.setPatternOptions(QRegularExpression::InvertedGreedinessOption);
rule.format = m_regexFormat;
m_highlightingRules.append(rule); m_highlightingRules.append(rule);
m_functionFormat.setFontItalic(true); m_stringFormat.setForeground(Qt::darkGreen);
m_functionFormat.setForeground(Qt::blue); rule.pattern = QRegularExpression(QStringLiteral("\".*\""));
rule.pattern = QRegExp(QStringLiteral("(?!if)\\b[A-Za-z0-9_]+(?=\\()")); rule.pattern.setPatternOptions(QRegularExpression::InvertedGreedinessOption);
rule.format = m_stringFormat;
m_highlightingRules.append(rule);
m_functionFormat.setForeground(Qt::darkBlue);
rule.pattern = QRegularExpression(QStringLiteral("(?!if)\\b[A-Za-z0-9_]+(?=\\()"));
rule.pattern.setPatternOptions(QRegularExpression::InvertedGreedinessOption);
rule.format = m_functionFormat; rule.format = m_functionFormat;
m_highlightingRules.append(rule); m_highlightingRules.append(rule);
m_commentStartExpression = QRegExp(QStringLiteral("/\\*")); m_commentStartExpression = QRegularExpression(QStringLiteral("/\\*"));
m_commentEndExpression = QRegExp(QStringLiteral("\\*/")); m_commentEndExpression = QRegularExpression(QStringLiteral("\\*/"));
} }
void JavaScriptHighlighter::highlightBlock(const QString &text) void JavaScriptHighlighter::highlightBlock(const QString &text)
{ {
for (const HighlightingRule &rule : m_highlightingRules) { for (const auto &rule : m_highlightingRules) {
QRegExp expression(rule.pattern); const auto &expression(rule.pattern);
int index = expression.indexIn(text); auto match = expression.match(text);
while (index >= 0) { while (match.hasMatch()) {
int length = expression.matchedLength(); const auto index = match.capturedStart();
const auto length = match.capturedLength();
setFormat(index, length, rule.format); setFormat(index, length, rule.format);
index = expression.indexIn(text, index + length); match = expression.match(text, index + length);
} }
} }
setCurrentBlockState(0); setCurrentBlockState(0);
int startIndex = 0; auto startIndex = 0;
if (previousBlockState() != 1) { if (previousBlockState() != 1) {
startIndex = m_commentStartExpression.indexIn(text); startIndex = m_commentStartExpression.match(text).capturedStart();
} }
while (startIndex >= 0) { while (startIndex >= 0) {
int endIndex = m_commentEndExpression.indexIn(text, startIndex); const auto endMatch = m_commentEndExpression.match(text, startIndex);
int commentLength; const auto endIndex = endMatch.capturedStart();
if (endIndex == -1) { const auto commentLength = [&] {
if (endIndex >= 0) {
return endIndex - startIndex + endMatch.capturedLength();
}
setCurrentBlockState(1); setCurrentBlockState(1);
commentLength = text.length() - startIndex; return text.length() - startIndex;
} else { }();
commentLength = endIndex - startIndex + m_commentEndExpression.matchedLength();
}
setFormat(startIndex, commentLength, m_multiLineCommentFormat); setFormat(startIndex, commentLength, m_multiLineCommentFormat);
startIndex = m_commentStartExpression.indexIn(text, startIndex + commentLength); startIndex = m_commentStartExpression.match(text, startIndex + commentLength).capturedStart();
} }
} }

View File

@ -1,6 +1,7 @@
#ifndef JAVASCRIPTHIGHLIGHTER_H #ifndef JAVASCRIPTHIGHLIGHTER_H
#define JAVASCRIPTHIGHLIGHTER_H #define JAVASCRIPTHIGHLIGHTER_H
#include <QRegularExpression>
#include <QSyntaxHighlighter> #include <QSyntaxHighlighter>
namespace QtGui { namespace QtGui {
@ -12,23 +13,24 @@ public:
JavaScriptHighlighter(QTextDocument *parent = nullptr); JavaScriptHighlighter(QTextDocument *parent = nullptr);
protected: protected:
void highlightBlock(const QString &text); void highlightBlock(const QString &text) override;
private: private:
struct HighlightingRule { struct HighlightingRule {
QRegExp pattern; QRegularExpression pattern;
QTextCharFormat format; QTextCharFormat format;
}; };
QVector<HighlightingRule> m_highlightingRules; QVector<HighlightingRule> m_highlightingRules;
QRegExp m_commentStartExpression; QRegularExpression m_commentStartExpression;
QRegExp m_commentEndExpression; QRegularExpression m_commentEndExpression;
QTextCharFormat m_keywordFormat; QTextCharFormat m_keywordFormat;
QTextCharFormat m_classFormat; QTextCharFormat m_classFormat;
QTextCharFormat m_singleLineCommentFormat; QTextCharFormat m_singleLineCommentFormat;
QTextCharFormat m_multiLineCommentFormat; QTextCharFormat m_multiLineCommentFormat;
QTextCharFormat m_quotationFormat; QTextCharFormat m_stringFormat;
QTextCharFormat m_regexFormat;
QTextCharFormat m_functionFormat; QTextCharFormat m_functionFormat;
}; };