chore: add tests for input highlighting (#6779)

Reviewed-by: Arne <78976058+4rneee@users.noreply.github.com>
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
Nerixyz
2026-01-31 10:18:43 +01:00
committed by GitHub
parent cb2800fa06
commit cebe7e415c
5 changed files with 345 additions and 8 deletions
+42 -7
View File
@@ -69,12 +69,24 @@ bool isIgnoredWord(TwitchChannel *twitch, const QString &word)
namespace chatterino {
namespace inputhighlight::detail {
// FIXME: this also matches URLs - this probably needs to be some function like Firefox' mozEnglishWordUtils::FindNextWord
QRegularExpression wordRegex()
{
static QRegularExpression regex{
R"(\p{L}(?:\P{Z}+\p{L}+)*)",
QRegularExpression::PatternOption::UseUnicodePropertiesOption,
};
return regex;
}
} // namespace inputhighlight::detail
InputHighlighter::InputHighlighter(SpellChecker &spellChecker, QObject *parent)
: QSyntaxHighlighter(parent)
, spellChecker(spellChecker)
// FIXME: this also matches URLs - this probably needs to be some function like Firefox' mozEnglishWordUtils::FindNextWord
, wordRegex(R"(\p{L}(?:\P{Z}+\p{L}+)*)",
QRegularExpression::PatternOption::UseUnicodePropertiesOption)
, wordRegex(inputhighlight::detail::wordRegex())
{
this->spellFmt.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline);
this->spellFmt.setUnderlineColor(Qt::red);
@@ -88,12 +100,36 @@ void InputHighlighter::setChannel(const std::shared_ptr<Channel> &channel)
this->rehighlight();
}
std::vector<QString> InputHighlighter::getSpellCheckedWords(const QString &text)
{
std::vector<QString> words;
this->visitWords(text, [&](const QString &word, qsizetype /*start*/,
qsizetype /*count*/) {
words.emplace_back(word);
});
return words;
}
void InputHighlighter::highlightBlock(const QString &text)
{
if (!this->spellChecker.isLoaded())
{
return;
}
this->visitWords(
text, [&](const QString &word, qsizetype start, qsizetype count) {
if (!this->spellChecker.check(word))
{
this->setFormat(static_cast<int>(start),
static_cast<int>(count), this->spellFmt);
}
});
}
void InputHighlighter::visitWords(
const QString &text,
std::invocable<const QString &, qsizetype, qsizetype> auto &&cb)
{
auto *channel = this->channel.lock().get();
QStringView textView = text;
@@ -112,11 +148,10 @@ void InputHighlighter::highlightBlock(const QString &text)
{
auto match = it.next();
auto text = match.captured();
if (!isIgnoredWord(channel, text) && !this->spellChecker.check(text))
if (!isIgnoredWord(channel, text))
{
this->setFormat(
static_cast<int>(match.capturedStart() + cmdTriggerLen),
static_cast<int>(text.size()), this->spellFmt);
cb(text, static_cast<int>(match.capturedStart() + cmdTriggerLen),
static_cast<int>(text.size()));
}
}
}
+17
View File
@@ -8,6 +8,7 @@
#include <QString>
#include <QSyntaxHighlighter>
#include <concepts>
#include <memory>
class QTextDocument;
@@ -18,6 +19,12 @@ class Channel;
class TwitchChannel;
class SpellChecker;
namespace inputhighlight::detail {
QRegularExpression wordRegex();
} // namespace inputhighlight::detail
/// This highlights the text in the split input.
/// Currently, it only does spell checking.
class InputHighlighter : public QSyntaxHighlighter
@@ -32,10 +39,20 @@ public:
void setChannel(const std::shared_ptr<Channel> &channel);
/// Do a pass over the whole text and filter out all words that will be
/// checked by the spell checker.
std::vector<QString> getSpellCheckedWords(const QString &text);
protected:
void highlightBlock(const QString &text) override;
private:
/// Visit all words that are not ignored
void visitWords(
const QString &text,
std::invocable</*word=*/const QString &, /*start=*/qsizetype,
/*count=*/qsizetype> auto &&cb);
SpellChecker &spellChecker;
QTextCharFormat spellFmt;