rssguard/src/librssguard/gui/reusable/jssyntaxhighlighter.cpp
2023-08-04 11:06:04 +02:00

108 lines
4.5 KiB
C++
Executable file

// For license of this file, see <project-root-folder>/LICENSE.md.
#include "gui/reusable/jssyntaxhighlighter.h"
#include "3rd-party/boolinq/boolinq.h"
#include "definitions/definitions.h"
JsSyntaxHighlighter::JsSyntaxHighlighter(QTextDocument* parent) : QSyntaxHighlighter(parent) {
HighlightingRule rule;
m_keywordFormat.setForeground(Qt::GlobalColor::magenta);
m_keywordFormat.setFontWeight(QFont::Weight::Bold);
QStringList keywords = jsKeywords();
auto std_keywords = boolinq::from(keywords)
.select([](const QString& kw) {
return QSL("\\b%1\\b").arg(kw);
})
.toStdList();
keywords = FROM_STD_LIST(QStringList, std_keywords);
for (const QString& pattern : keywords) {
rule.m_pattern = QRegularExpression(pattern);
rule.m_format = m_keywordFormat;
m_highlightingRules.append(rule);
}
m_classFormat.setFontWeight(QFont::Weight::Bold);
m_classFormat.setForeground(Qt::GlobalColor::darkMagenta);
rule.m_pattern = QRegularExpression(QStringLiteral("\\bQ[A-Za-z]+\\b"));
rule.m_format = m_classFormat;
m_highlightingRules.append(rule);
m_singleLineCommentFormat.setForeground(Qt::GlobalColor::red);
rule.m_pattern = QRegularExpression(QStringLiteral("//[^\n]*"));
rule.m_format = m_singleLineCommentFormat;
m_highlightingRules.append(rule);
m_multiLineCommentFormat.setForeground(Qt::GlobalColor::red);
m_quotationFormat.setForeground(Qt::GlobalColor::darkGreen);
rule.m_pattern = QRegularExpression(QStringLiteral("\".*\""));
rule.m_format = m_quotationFormat;
m_highlightingRules.append(rule);
m_functionFormat.setFontItalic(true);
m_functionFormat.setForeground(Qt::GlobalColor::green);
rule.m_pattern = QRegularExpression(QStringLiteral("\\b[A-Za-z0-9_]+(?=\\()"));
rule.m_format = m_functionFormat;
m_highlightingRules.append(rule);
m_commentStartExpression = QRegularExpression(QStringLiteral("/\\*"));
m_commentEndExpression = QRegularExpression(QStringLiteral("\\*/"));
}
QStringList JsSyntaxHighlighter::jsKeywords() const {
return {QSL("abstract"), QSL("arguments"), QSL("await\\*"), QSL("boolean"), QSL("break"), QSL("byte"),
QSL("case"), QSL("catch"), QSL("char"), QSL("class\\*"), QSL("const"), QSL("continue"),
QSL("debugger"), QSL("default"), QSL("delete"), QSL("do"), QSL("double"), QSL("else"),
QSL("enum\\*"), QSL("eval"), QSL("export\\*"), QSL("extends\\*"), QSL("false"), QSL("final"),
QSL("finally"), QSL("float"), QSL("for"), QSL("function"), QSL("goto"), QSL("if"),
QSL("implements"), QSL("import\\*"), QSL("in"), QSL("instanceof"), QSL("int"), QSL("interface"),
QSL("let\\*"), QSL("long"), QSL("native"), QSL("new"), QSL("null"), QSL("package"),
QSL("private"), QSL("protected"), QSL("public"), QSL("return"), QSL("short"), QSL("static"),
QSL("super\\*"), QSL("switch"), QSL("synchronized"), QSL("this"), QSL("throw"), QSL("throws"),
QSL("transient"), QSL("true"), QSL("try"), QSL("typeof"), QSL("var"), QSL("void"),
QSL("volatile"), QSL("while"), QSL("with"), QSL("yield")};
}
void JsSyntaxHighlighter::highlightBlock(const QString& text) {
for (const HighlightingRule& rule : std::as_const(m_highlightingRules)) {
QRegularExpressionMatchIterator matchIterator = rule.m_pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.m_format);
}
}
setCurrentBlockState(0);
int start_index = 0;
if (previousBlockState() != 1) {
start_index = text.indexOf(m_commentStartExpression);
}
while (start_index >= 0) {
QRegularExpressionMatch match = m_commentEndExpression.match(text, start_index);
int end_index = match.capturedStart();
int comment_length = 0;
if (end_index == -1) {
setCurrentBlockState(1);
comment_length = text.length() - start_index;
}
else {
comment_length = end_index - start_index + match.capturedLength();
}
setFormat(start_index, comment_length, m_multiLineCommentFormat);
start_index = text.indexOf(m_commentStartExpression, start_index + comment_length);
}
}