From f29a9665042e133ced996c171dcee18077c0405b Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Wed, 25 Nov 2015 14:05:03 +0100 Subject: [PATCH] ui: fixed syntax highlighting * fixed strings and number highlights within comments * fixed quotations not considering escaped quotations within strings * fixed quotations spanning till last quotation in line * fixed tag quotations only used after blank space * fixed multiline comments using correct start and end * fixed single line comments interfering with multiline comments --- bin/app/data/src/sample/comment.cpp | 17 +++ src/app/qt/utility/QtHighlighter.cpp | 174 +++++++++++++++++++-------- src/app/qt/utility/QtHighlighter.h | 19 ++- 3 files changed, 158 insertions(+), 52 deletions(-) create mode 100644 bin/app/data/src/sample/comment.cpp diff --git a/bin/app/data/src/sample/comment.cpp b/bin/app/data/src/sample/comment.cpp new file mode 100644 index 00000000..8d4983e5 --- /dev/null +++ b/bin/app/data/src/sample/comment.cpp @@ -0,0 +1,17 @@ +/* hallo */ + +int a; /* hallo */ + +int b = 6/3/2; /* hallo */ + +//* + int c; +//*/ + +// /* + int d; +// */ + +/* + hallo +// */ int e = 0; diff --git a/src/app/qt/utility/QtHighlighter.cpp b/src/app/qt/utility/QtHighlighter.cpp index 626e4fde..3fdcb7d3 100644 --- a/src/app/qt/utility/QtHighlighter.cpp +++ b/src/app/qt/utility/QtHighlighter.cpp @@ -25,21 +25,21 @@ QtHighlighter::QtHighlighter(QTextDocument *parent) << "struct" << "union" << "unsigned" << "void"; QRegExp directiveRegExp = QRegExp("#[a-z]+\\b"); - QRegExp commentRegExp = QRegExp("//[^\n]*"); - QRegExp quotationRegExp = QRegExp("\".*\""); - QRegExp quotation2RegExp = QRegExp("<.*>"); QRegExp numberRegExp = QRegExp("\\b[0-9]+\\b"); QRegExp functionRegExp = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); + QRegExp quotationRegExp = QRegExp("\"([^\"]|\\\\.)*\""); + QRegExp quotation2RegExp = QRegExp(" <.*>"); + QRegExp commentRegExp = QRegExp("//[^\n]*"); ColorScheme* scheme = ColorScheme::getInstance().get(); QColor directiveColor(scheme->getSyntaxColor("directive").c_str()); QColor keywordColor(scheme->getSyntaxColor("keyword").c_str()); QColor typeColor(scheme->getSyntaxColor("type").c_str()); - QColor commentColor(scheme->getSyntaxColor("comment").c_str()); QColor numberColor(scheme->getSyntaxColor("number").c_str()); - QColor quotationColor(scheme->getSyntaxColor("quotation").c_str()); QColor functionColor(scheme->getSyntaxColor("function").c_str()); + QColor quotationColor(scheme->getSyntaxColor("quotation").c_str()); + QColor commentColor = scheme->getSyntaxColor("comment").c_str(); foreach (const QString &pattern, keywordPatterns) { @@ -52,72 +52,148 @@ QtHighlighter::QtHighlighter(QTextDocument *parent) } addHighlightingRule(directiveColor, directiveRegExp); - addHighlightingRule(commentColor, commentRegExp); - addHighlightingRule(quotationColor, quotationRegExp); - addHighlightingRule(quotationColor, quotation2RegExp); addHighlightingRule(numberColor, numberRegExp); addHighlightingRule(functionColor, functionRegExp); + addHighlightingRule(quotationColor, quotation2RegExp); + + m_quotationRule = HighlightingRule(quotationColor, quotationRegExp); + m_commentRule = HighlightingRule(commentColor, commentRegExp); } -void QtHighlighter::highlightBlock(const QString &text) +void QtHighlighter::highlightBlock(const QString& text) { - foreach (const HighlightingRule &rule, highlightingRules) + if (currentBlock().blockNumber() == 0) { - QRegExp expression(rule.pattern); - int index = expression.indexIn(text); - while (index >= 0) + highlightDocument(); + } +} + +void QtHighlighter::highlightDocument() +{ + QTextDocument* doc = document(); + + std::vector> ranges; + + for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next()) + { + formatBlock(it, m_quotationRule, &ranges, true); + } + + for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next()) + { + foreach (const HighlightingRule &rule, m_highlightingRules) { - int length = expression.matchedLength(); - setFormat(index, length, rule.format); - index = expression.indexIn(text, index + length); + formatBlock(it, rule, &ranges, false); } } - setCurrentBlockState(0); - QRegExp commentStartExpression = QRegExp("/\\*"); + highlightMultiLineComments(&ranges); + + for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next()) + { + formatBlock(it, m_commentRule, &ranges, true); + } +} + +void QtHighlighter::highlightMultiLineComments(std::vector>* ranges) +{ + QTextDocument* doc = document(); + + QRegExp commentStartExpression = QRegExp("(^([^/]|/[^/])*)/\\*"); QRegExp commentEndExpression = QRegExp("\\*/"); - QTextCursor cursorStart = document()->find(commentStartExpression); - QTextCursor cursorEnd = document()->find(commentEndExpression); + QTextCursor cursorStart(doc); + QTextCursor cursorEnd(doc); - int startIndex = 0; - if (!cursorEnd.isNull() && (cursorStart.isNull() || cursorEnd < cursorStart) - && currentBlock().blockNumber() <= cursorEnd.blockNumber()) + while (true) { - startIndex = 0; - } - else if (previousBlockState() != 1) - { - startIndex = commentStartExpression.indexIn(text); - } - - QTextCharFormat multiLineCommentFormat; - multiLineCommentFormat.setForeground(Qt::gray); - - while (startIndex >= 0) - { - int endIndex = commentEndExpression.indexIn(text, startIndex); - int commentLength; - - if (endIndex == -1) + do { - setCurrentBlockState(1); - commentLength = text.length() - startIndex; + cursorStart = document()->find(commentStartExpression, cursorStart); + if (!cursorStart.isNull()) + { + cursorStart.setPosition(cursorStart.selectionEnd() - 2); + } } - else + while (isInRange(cursorStart.position(), *ranges)); + + if (cursorStart.isNull()) { - commentLength = endIndex - startIndex + commentEndExpression.matchedLength(); + break; } - setFormat(startIndex, commentLength, multiLineCommentFormat); - startIndex = commentStartExpression.indexIn(text, startIndex + commentLength); + cursorEnd = document()->find(commentEndExpression, cursorStart); + if (cursorEnd.isNull()) + { + break; + } + + applyFormat(cursorStart.selectionStart(), cursorEnd.position(), m_commentRule.format); + ranges->push_back(std::pair(cursorStart.selectionStart(), cursorEnd.position())); + + cursorStart = cursorEnd; } } +QtHighlighter::HighlightingRule::HighlightingRule() +{ +} + +QtHighlighter::HighlightingRule::HighlightingRule(const QColor& color, const QRegExp& regExp) +{ + format.setForeground(color); + pattern = regExp; +} + void QtHighlighter::addHighlightingRule(const QColor& color, const QRegExp& regExp) { - HighlightingRule rule; - rule.format.setForeground(color); - rule.pattern = regExp; - highlightingRules.append(rule); + m_highlightingRules.append(HighlightingRule(color, regExp)); +} + +bool QtHighlighter::isInRange(int pos, const std::vector>& ranges) const +{ + for (const std::pair p : ranges) + { + if (pos >= p.first && pos <= p.second) + { + return true; + } + } + + return false; +} + +void QtHighlighter::formatBlock( + const QTextBlock& block, const HighlightingRule& rule, std::vector>* ranges, bool saveRange +){ + QRegExp expression(rule.pattern); + int pos = block.position(); + int index = expression.indexIn(block.text()); + std::vector> newRanges; + + while (index >= 0) + { + int length = expression.matchedLength(); + + if (!isInRange(pos + index, *ranges)) + { + applyFormat(pos + index, pos + index + length, rule.format); + } + + newRanges.push_back(std::pair(pos + index, pos + index + length)); + index = expression.indexIn(block.text(), index + length); + } + + if (saveRange) + { + ranges->insert(ranges->end(), newRanges.begin(), newRanges.end()); + } +} + +void QtHighlighter::applyFormat(int startPosition, int endPosition, const QTextCharFormat& format) +{ + QTextCursor cursor(document()); + cursor.setPosition(startPosition); + cursor.setPosition(endPosition, QTextCursor::KeepAnchor); + cursor.setCharFormat(format); } diff --git a/src/app/qt/utility/QtHighlighter.h b/src/app/qt/utility/QtHighlighter.h index c8d794d5..82ebd7cb 100644 --- a/src/app/qt/utility/QtHighlighter.h +++ b/src/app/qt/utility/QtHighlighter.h @@ -6,7 +6,8 @@ class QTextDocument; -class QtHighlighter : public QSyntaxHighlighter +class QtHighlighter + : public QSyntaxHighlighter { Q_OBJECT @@ -14,18 +15,30 @@ public: QtHighlighter(QTextDocument *parent = 0); protected: - void highlightBlock(const QString &text); + void highlightBlock(const QString& text); private: struct HighlightingRule { + HighlightingRule(); + HighlightingRule(const QColor& color, const QRegExp& regExp); + QRegExp pattern; QTextCharFormat format; }; + void highlightDocument(); + void highlightMultiLineComments(std::vector>* ranges); + void addHighlightingRule(const QColor& color, const QRegExp& regExp); - QVector highlightingRules; + bool isInRange(int index, const std::vector>& ranges) const; + void formatBlock(const QTextBlock& block, const HighlightingRule& rule, std::vector>* ranges, bool saveRange); + void applyFormat(int startPosition, int endPosition, const QTextCharFormat& format); + + QVector m_highlightingRules; + HighlightingRule m_quotationRule; + HighlightingRule m_commentRule; }; #endif // QT_HIGHLIGHTER_H