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
This commit is contained in:
Eberhard Graether
2015-11-25 14:05:03 +01:00
parent 0144c44d1d
commit f29a966504
3 changed files with 158 additions and 52 deletions
+17
View File
@@ -0,0 +1,17 @@
/* hallo */
int a; /* hallo */
int b = 6/3/2; /* hallo */
//*
int c;
//*/
// /*
int d;
// */
/*
hallo
// */ int e = 0;
+125 -49
View File
@@ -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<std::pair<int, int>> 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<std::pair<int, int>>* 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<int, int>(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<std::pair<int, int>>& ranges) const
{
for (const std::pair<int, int> p : ranges)
{
if (pos >= p.first && pos <= p.second)
{
return true;
}
}
return false;
}
void QtHighlighter::formatBlock(
const QTextBlock& block, const HighlightingRule& rule, std::vector<std::pair<int, int>>* ranges, bool saveRange
){
QRegExp expression(rule.pattern);
int pos = block.position();
int index = expression.indexIn(block.text());
std::vector<std::pair<int, int>> 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<int, int>(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);
}
+16 -3
View File
@@ -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<std::pair<int, int>>* ranges);
void addHighlightingRule(const QColor& color, const QRegExp& regExp);
QVector<HighlightingRule> highlightingRules;
bool isInRange(int index, const std::vector<std::pair<int, int>>& ranges) const;
void formatBlock(const QTextBlock& block, const HighlightingRule& rule, std::vector<std::pair<int, int>>* ranges, bool saveRange);
void applyFormat(int startPosition, int endPosition, const QTextCharFormat& format);
QVector<HighlightingRule> m_highlightingRules;
HighlightingRule m_quotationRule;
HighlightingRule m_commentRule;
};
#endif // QT_HIGHLIGHTER_H