diff --git a/QMLComponents/controls/rsyntaxhighlighter.cpp b/QMLComponents/controls/rsyntaxhighlighter.cpp index 3b0787e63f..d09472d7f0 100644 --- a/QMLComponents/controls/rsyntaxhighlighter.cpp +++ b/QMLComponents/controls/rsyntaxhighlighter.cpp @@ -19,76 +19,86 @@ #include "rsyntaxhighlighter.h" RSyntaxHighlighter::RSyntaxHighlighter(QTextDocument *parent) - : QSyntaxHighlighter(parent) + : QSyntaxHighlighter(parent), VariableInfoConsumer(), _textDocument(parent) { + if(VariableInfo::info()) + { + connect(VariableInfo::info(), &VariableInfo::namesChanged, this, &RSyntaxHighlighter::handleNamesChanged); + connect(VariableInfo::info(), &VariableInfo::rowCountChanged, this, &RSyntaxHighlighter::handleRowCountChanged); + } HighlightingRule rule; - // all these R regExp are copied from: https://github.com/PrismJS/prism/blob/master/components/prism-r.js + // most of these R regExp are copied from: https://github.com/PrismJS/prism/blob/master/components/prism-r.js // operators - operatorFormat.setForeground(Qt::red); + _operatorFormat.setForeground(Qt::red); rule.pattern = QRegularExpression(R"(->?>?|<(?:=|=!]=?|::?|&&?|\|\|?|[+*\/^$@~]|%[^%\s]*%)"); - rule.format = operatorFormat; - highlightingRules.append(rule); + rule.format = _operatorFormat; + _highlightingRules.append(rule); // variables - variableFormat.setToolTip("variable"); + _variableFormat.setToolTip("variable"); rule.pattern = QRegularExpression(R"(\b\w*\b)"); - rule.format = variableFormat; - highlightingRules.append(rule); + rule.format = _variableFormat; + _highlightingRules.append(rule); // string - stringFormat.setForeground(Qt::darkGreen); - rule.pattern = QRegularExpression(R"((['"])(?:\\.|(?!\1)[^\\\r\n])*\1)"); - rule.format = stringFormat; - highlightingRules.append(rule); + _stringFormat.setForeground(Qt::darkGreen); + rule.pattern = QRegularExpression(R"(([`'"])(?:\\.|(?!\1)[^\\\r\n])*\1)"); + rule.format = _stringFormat; + _highlightingRules.append(rule); // keyword - keywordFormat.setForeground(Qt::darkCyan); + _keywordFormat.setForeground(Qt::darkCyan); rule.pattern = QRegularExpression(R"(\b(?:NA|NA_character_|NA_complex_|NA_integer_|NA_real_|NULL|break|else|for|function|if|in|next|repeat|while)\b)"); - rule.format = keywordFormat; - highlightingRules.append(rule); + rule.format = _keywordFormat; + _highlightingRules.append(rule); // boolean and special number - booleanFormat.setForeground(Qt::magenta); + _booleanFormat.setForeground(Qt::magenta); rule.pattern = QRegularExpression(R"(\b(?:FALSE|TRUE|Inf|NaN)\b)"); - rule.format = booleanFormat; - highlightingRules.append(rule); + rule.format = _booleanFormat; + _highlightingRules.append(rule); // number - numberFormat.setForeground(Qt::darkMagenta); + _numberFormat.setForeground(Qt::darkMagenta); rule.pattern = QRegularExpression(R"((?:\b0x[\dA-Fa-f]+(?:\.\d*)?|\b\d+(?:\.\d*)?|\B\.\d+)(?:[EePp][+-]?\d+)?[iL]?)"); - rule.format = numberFormat; - highlightingRules.append(rule); + rule.format = _numberFormat; + _highlightingRules.append(rule); // punctuation - punctuationFormat.setForeground(Qt::blue); + _punctuationFormat.setForeground(Qt::blue); rule.pattern = QRegularExpression(R"([(){}\[\],;])"); - rule.format = punctuationFormat; - highlightingRules.append(rule); + rule.format = _punctuationFormat; + _highlightingRules.append(rule); // comments - commentFormat.setForeground(Qt::darkGray); - commentFormat.setFontItalic(true); - rule.pattern = QRegularExpression(R"(#.*)"); - rule.format = commentFormat; - highlightingRules.append(rule); + _commentFormat.setForeground(Qt::darkGray); + _commentFormat.setFontItalic(true); + _commentRule.pattern = QRegularExpression(R"(#[^\n]*)"); + _commentRule.format = _commentFormat; + + // columns + _columnFormat.setForeground(Qt::blue); + _columnFormat.setFontItalic(true); } void RSyntaxHighlighter::highlightBlock(const QString &text) { - for (const HighlightingRule &rule : highlightingRules) - { - QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); - - while (matchIterator.hasNext()) - { - QRegularExpressionMatch match = matchIterator.next(); - setFormat(match.capturedStart(), match.capturedLength(), rule.format); - setStringsFormat(text, '"'); - setStringsFormat(text, '\''); - } - } + setStringsFormat(text, '"'); + setStringsFormat(text, '\''); + setStringsFormat(text, '`'); + + for (const HighlightingRule & rule : _highlightingRules) + applyRule(text, rule); + + //Do columns + QStringList names = requestInfo(VariableInfo::InfoType::VariableNames).toStringList(); + + for(const QString & name : names) + applyRule(text, QRegularExpression(QString(R"(%1)").arg(name)), _columnFormat); + + applyRule(text, _commentRule); } void RSyntaxHighlighter::setStringsFormat(const QString &text, QChar c) @@ -102,13 +112,24 @@ void RSyntaxHighlighter::setStringsFormat(const QString &text, QChar c) start = i; else { - setFormat(start, i - start + 1, stringFormat); + setFormat(start, i - start + 1, _stringFormat); start = -1; } } } } +void RSyntaxHighlighter::applyRule(const QString & text, const QRegularExpression & pattern, const QTextCharFormat & format) +{ + QRegularExpressionMatchIterator matchIterator = pattern.globalMatch(text); + + while (matchIterator.hasNext()) + { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), format); + } +} + void RSyntaxHighlighterQuick::setTextDocument(QQuickTextDocument *textDocument) { if(_textDocument == textDocument) diff --git a/QMLComponents/controls/rsyntaxhighlighter.h b/QMLComponents/controls/rsyntaxhighlighter.h index 19236f46d7..0bfe8f1fd2 100644 --- a/QMLComponents/controls/rsyntaxhighlighter.h +++ b/QMLComponents/controls/rsyntaxhighlighter.h @@ -24,31 +24,49 @@ #include #include #include +#include "variableinfo.h" -class RSyntaxHighlighter : public QSyntaxHighlighter +class RSyntaxHighlighter : public QSyntaxHighlighter, public VariableInfoConsumer { + Q_OBJECT + + struct HighlightingRule + { + QRegularExpression pattern; + QTextCharFormat format; + }; + public: RSyntaxHighlighter(QTextDocument *parent); void highlightBlock(const QString &text) override; void setStringsFormat(const QString &text, QChar c); + + void applyRule(const QString & text, const HighlightingRule & rule) { applyRule(text, rule.pattern, rule.format); } + void applyRule(const QString & text, const QRegularExpression & pattern, const QTextCharFormat & format); + + + +protected slots: + void handleNamesChanged(QMap changedNames) { rehighlight(); } + void handleRowCountChanged() { rehighlight(); } private: - struct HighlightingRule - { - QRegularExpression pattern; - QTextCharFormat format; - }; + + + QTextDocument * _textDocument = nullptr; - QVector highlightingRules; - QTextCharFormat operatorFormat, - variableFormat, - commentFormat, - keywordFormat, - stringFormat, - booleanFormat, - numberFormat, - punctuationFormat; + QVector _highlightingRules; + QTextCharFormat _punctuationFormat, + _operatorFormat, + _variableFormat, + _commentFormat, + _keywordFormat, + _stringFormat, + _booleanFormat, + _numberFormat, + _columnFormat; + HighlightingRule _commentRule; }; class RSyntaxHighlighterQuick : public QQuickItem @@ -62,7 +80,7 @@ class RSyntaxHighlighterQuick : public QQuickItem QQuickTextDocument * textDocument() { return _textDocument; } void setTextDocument(QQuickTextDocument * textDocument); - + signals: void textDocumentChanged();