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:
@@ -0,0 +1,17 @@
|
||||
/* hallo */
|
||||
|
||||
int a; /* hallo */
|
||||
|
||||
int b = 6/3/2; /* hallo */
|
||||
|
||||
//*
|
||||
int c;
|
||||
//*/
|
||||
|
||||
// /*
|
||||
int d;
|
||||
// */
|
||||
|
||||
/*
|
||||
hallo
|
||||
// */ int e = 0;
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user