QtCreator plugin: syntax highlighting resets document format
-
Problem
I am writing AI-assistant plugin for QtCreator. As part of this plugin I need to show code completion suggestion, which can be multiline.
I am attempting to show AI-suggestion as code inline and then de-highlight it using customQSyntaxHighlighter
, it works fine in regularQTextEdit
, but if I apply this to QtCreator's editor, then all formatting inQTextDocument
resets to plain-text (i.e. all C++ coloring reverts to "regular text" with excepton of a few class names).Here is how it looks normally and with my highlighter:
Attempted solutions
To achieve this I subclassed
QSyntaxHighlighter
and written simple range-matching code that would grey-out part ofQTextDocument
fromhighlight_start
tohighlight_end
I have tried inserting html tags around AI-suggestion, it works, but not 100% of the time. Sometimes QtCreator's highlighter re-highlights suggested code snippet which I have no control over.
I have tried doing nothing in
highlightBlock
function, and formatting still resets.Code
Highlighter Class definition looks like this:
class CompletionHighlighter : public QSyntaxHighlighter { Q_OBJECT QTextCharFormat completionFormat; int highlight_start; int highlight_end; public: CompletionHighlighter(QTextDocument *parent = 0); public slots: void setCompletionPosition(int start, int end); protected: void highlightBlock(const QString &text) override; };
Simple implementation looks like this
#include "completion_highlighter.h" CompletionHighlighter::CompletionHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) { completionFormat.setForeground(Qt::gray); } void CompletionHighlighter::setCompletionPosition(int start, int end) { highlight_start = start; highlight_end = end; } void CompletionHighlighter::highlightBlock(const QString &text) { int block_highlight_start = std::min( std::max(highlight_start - currentBlock().position(), 0), currentBlock().length() - 1); int block_highlight_end = std::min( std::max(highlight_end - currentBlock().position(), 0), currentBlock().length() - 1); if (block_highlight_start == block_highlight_end) { return; } setFormat(block_highlight_start, block_highlight_end-block_highlight_start, completionFormat); }
To use this highlighter I get current QtCreator's editor with
Core::IEditor *editor = Core::EditorManager::currentEditor(); QPlainTextEdit *plain_text_edit = qobject_cast<QPlainTextEdit *>(editor->widget());
and then create highlighter class with
new CompletionHighlighter(plain_text_edit->document());
Any ideas how I can highlight part of code without affecting entire document?
-
C Christian Ehrlicher moved this topic from General and Desktop on
-
Problem
I am writing AI-assistant plugin for QtCreator. As part of this plugin I need to show code completion suggestion, which can be multiline.
I am attempting to show AI-suggestion as code inline and then de-highlight it using customQSyntaxHighlighter
, it works fine in regularQTextEdit
, but if I apply this to QtCreator's editor, then all formatting inQTextDocument
resets to plain-text (i.e. all C++ coloring reverts to "regular text" with excepton of a few class names).Here is how it looks normally and with my highlighter:
Attempted solutions
To achieve this I subclassed
QSyntaxHighlighter
and written simple range-matching code that would grey-out part ofQTextDocument
fromhighlight_start
tohighlight_end
I have tried inserting html tags around AI-suggestion, it works, but not 100% of the time. Sometimes QtCreator's highlighter re-highlights suggested code snippet which I have no control over.
I have tried doing nothing in
highlightBlock
function, and formatting still resets.Code
Highlighter Class definition looks like this:
class CompletionHighlighter : public QSyntaxHighlighter { Q_OBJECT QTextCharFormat completionFormat; int highlight_start; int highlight_end; public: CompletionHighlighter(QTextDocument *parent = 0); public slots: void setCompletionPosition(int start, int end); protected: void highlightBlock(const QString &text) override; };
Simple implementation looks like this
#include "completion_highlighter.h" CompletionHighlighter::CompletionHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) { completionFormat.setForeground(Qt::gray); } void CompletionHighlighter::setCompletionPosition(int start, int end) { highlight_start = start; highlight_end = end; } void CompletionHighlighter::highlightBlock(const QString &text) { int block_highlight_start = std::min( std::max(highlight_start - currentBlock().position(), 0), currentBlock().length() - 1); int block_highlight_end = std::min( std::max(highlight_end - currentBlock().position(), 0), currentBlock().length() - 1); if (block_highlight_start == block_highlight_end) { return; } setFormat(block_highlight_start, block_highlight_end-block_highlight_start, completionFormat); }
To use this highlighter I get current QtCreator's editor with
Core::IEditor *editor = Core::EditorManager::currentEditor(); QPlainTextEdit *plain_text_edit = qobject_cast<QPlainTextEdit *>(editor->widget());
and then create highlighter class with
new CompletionHighlighter(plain_text_edit->document());
Any ideas how I can highlight part of code without affecting entire document?
Simple experiment with two
QSyntaxHighlighter
shows that last one overrides whatever changes is made by previous ones. In order to add my highlights to whatever is already highlighted I need to call setFormat with all existing formatting somehow. -
Simple experiment with two
QSyntaxHighlighter
shows that last one overrides whatever changes is made by previous ones. In order to add my highlights to whatever is already highlighted I need to call setFormat with all existing formatting somehow.I've found the "solution", there is a way to apply all previous formats in a block:
for(QTextLayout::FormatRange &range : currentBlock().layout()->formats()) { setFormat(range.start, range.length, range.format); }
One would think, that's what all code highlighters supposed to do.
That won't work consistently though, as there is no way that I am aware of to set highlighter priority in QtCreator, so one is messing up another's highlights.
-
I've found the "solution", there is a way to apply all previous formats in a block:
for(QTextLayout::FormatRange &range : currentBlock().layout()->formats()) { setFormat(range.start, range.length, range.format); }
One would think, that's what all code highlighters supposed to do.
That won't work consistently though, as there is no way that I am aware of to set highlighter priority in QtCreator, so one is messing up another's highlights.
Hi @Vladimir-Looze,
I guess the best is to contact the QtCreator developers on the mailing list: https://lists.qt-project.org/listinfo/qt-creator
You should get a definite answer there.
Regards
-
I've found the "solution", there is a way to apply all previous formats in a block:
for(QTextLayout::FormatRange &range : currentBlock().layout()->formats()) { setFormat(range.start, range.length, range.format); }
One would think, that's what all code highlighters supposed to do.
That won't work consistently though, as there is no way that I am aware of to set highlighter priority in QtCreator, so one is messing up another's highlights.
@Vladimir-Looze
I have never experimented with two different highlighters working on the same document, and as you have already encountered various problems I guess it was never the intention that this works.But if you want to have multiline suggestion I would like to encourage you to have a look at the copilot integration, and how the suggestions are handled there.