QSyntax荧光笔和多行注释

QSyntaxHighlighter and multiline comments

本文关键字:多行注释 荧光笔 QSyntax      更新时间:2023-10-16

我正在使用Qt的QSyntaxHighlight在QML文本编辑中为一些类似C的语法着色

除了多行评论外,一切都很好。

我以这种方式检测它们:

void highlightBlock(QString const& text) override {
bool inMultilineComment = previousBlockState() == STATES::COMMENT;
bool inSingleLineComment = false;
int previousIndex = 0;
QRegularExpression expr("(\/\*|\*\/|\/\/|n)"); // will match either /**, /**, // or n
QRegularExpressionMatchIterator it = expr.globalMatch(text);
while(it.hasNext()) {
QRegularExpressionMatch match = it.next();
const QString captured = match.captured(1);
if(captured == "/*" && !inSingleLineComment) {
inMultilineComment = true;
previousIndex = match.capturedStart(1);
}
if(captured == "*/" && inMultilineComment) {
inMultilineComment = false;
setFormat(previousIndex, match.capturedEnd(1) - previousIndex, _commentFormat);
}
if(captured == "//" && !inMultilineComment) {
inSingleLineComment = true;
}
if(captured == "n" && inSingleLineComment) {
inSingleLineComment = false;
}
}
if(inMultilineComment) {
setFormat(previousIndex, text.size() - previousIndex, _commentFormat);
setCurrentBlockState(STATES::COMMENT);
}
else {
setCurrentBlockState(STATES::NONE);
}
}

它一直有效,直到我采用已经着色的多行注释并在开始时删除/*。仅处理包含/*的块并重新着色,但不会处理和重新着色以下块,这意味着当它们未被注释时,它们将继续显示为注释。

有没有一种简单的方法可以告诉QSyntaxHighlight重新处理以下块以防止这种错误着色?

我最近遇到了同样的问题,发现Qt实际上应该为你处理这个问题,假设你正确地设置了blockState。

如果你在Qt5源代码中查看QSyntaxHighlighterPrivate::reformatBlocks的源代码,你会看到

while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
const int stateBeforeHighlight = block.userState();
reformatBlock(block);
forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
block = block.next();
}

从 https://code.woboq.org/qt5/qtbase/src/gui/text/qsyntaxhighlighter.cpp.html#165 检索

该代码(由突出显示器所在的 QTextDocument 中的 contentChange 信号触发(将从刚刚修改的块开始遍历每个块(行(。假设块的状态根据刚刚发生的类型更改而更改,它将继续处理以下块。这意味着你需要让你的用户状态对每一行都正确,Qt应该处理其余的。

给定示例

/*
* This is a comment
*
* That I made
*/

您可能希望从每行都设置了STATES::COMMENT的条件开始,最后一行应设置为STATES::NONE。执行删除初始/*之类的操作后,您需要确保块状态重置为STATES::NONE。这将触发Qt重新运行下一个区块,该区块也需要更改其状态等。

在我的(python(代码中,我最终使用打印语句和实际调试的组合来跟踪状态更改的传播,并找出它没有正确更新和破坏更新链的地方。您的代码表面上看起来是正确的,尽管我没有尝试编译和运行它,但我怀疑在某些情况下触发了编辑后状态未正确更新的情况。