QSyntaxHighlighter和多行注释

时间:2018-06-24 18:50:00

标签: c++ qt syntax-highlighting

我正在使用Qt的QSyntaxHighlighter在QML TextEdit中为某些类似于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);
    }
}

它起作用,直到我接受已经着色的多行注释,并且一开始就删除了/*。仅对包含/*的块进行处理并重新上色,而对随后的块不进行处理并重新上色,这意味着它们在没有出现时会继续显示注释。

是否有一种简单的方法告诉QSyntaxHighlighter重新处理以下块以防止出现这种错误的颜色?

1 个答案:

答案 0 :(得分:0)

我最近遇到了同样的问题,并发现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中的contentsChange信号触发)将从刚刚修改的块开始遍历每个块(行)。假设块的状态基于刚刚发生的类型更改而改变,它将继续处理以下块。这意味着您需要正确设置每一行的userState,而Qt应该处理其余的内容。

给出示例

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

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

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