diff --git a/autotests/syntaxrepository_test.cpp b/autotests/syntaxrepository_test.cpp --- a/autotests/syntaxrepository_test.cpp +++ b/autotests/syntaxrepository_test.cpp @@ -286,6 +286,7 @@ QCOMPARE(def.singleLineCommentPosition(), KSyntaxHighlighting::CommentPosition::StartOfLine); const auto emptyPair = QPair(); QCOMPARE(def.multiLineCommentMarker(), emptyPair); + QVERIFY(def.characterEncodings().isEmpty()); for (QChar c : QStringLiteral("\t !%&()*+,-./:;<=>?[\\]^{|}~")) { @@ -341,6 +342,16 @@ QVERIFY(def.foldingEnabled()); QVERIFY(def.indentationBasedFoldingEnabled()); } + + void testCharacterEncodings() + { + auto def = m_repo.definitionForName(QLatin1String("LaTeX")); + QVERIFY(def.isValid()); + const auto encodings = def.characterEncodings(); + QVERIFY(!encodings.isEmpty()); + QVERIFY(encodings.contains({ QChar(196), QLatin1String("\\\"{A}") })); + QVERIFY(encodings.contains({ QChar(227), QLatin1String("\\~{a}") })); + } }; } diff --git a/src/lib/definition.h b/src/lib/definition.h --- a/src/lib/definition.h +++ b/src/lib/definition.h @@ -305,6 +305,14 @@ */ QPair multiLineCommentMarker() const; + /** + * Returns a list of character/string mapping that can be used for spell + * checking. This is useful for instance when spell checking LaTeX, where + * the string \"{A} represents the character Ä. + * @since 5.50 + */ + QVector> characterEncodings() const; + private: friend class DefinitionData; friend class DefinitionRef; diff --git a/src/lib/definition.cpp b/src/lib/definition.cpp --- a/src/lib/definition.cpp +++ b/src/lib/definition.cpp @@ -286,6 +286,12 @@ return { d->multiLineCommentStartMarker, d->multiLineCommentEndMarker }; } +QVector> Definition::characterEncodings() const +{ + d->load(); + return d->characterEncodings; +} + Context* DefinitionData::initialContext() const { Q_ASSERT(!contexts.isEmpty()); @@ -580,6 +586,8 @@ loadFoldingIgnoreList(reader); } else if (reader.name() == QLatin1String("comments")) { loadComments(reader); + } else if (reader.name() == QLatin1String("spellchecking")) { + loadSpellchecking(reader); } else { reader.skipCurrentElement(); } @@ -668,6 +676,41 @@ } } +void DefinitionData::loadSpellchecking(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("spellchecking")); + Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement); + reader.readNext(); + + // reference counter to count XML child elements, to not return too early + int elementRefCounter = 1; + + while (!reader.atEnd()) { + switch (reader.tokenType()) { + case QXmlStreamReader::StartElement: + ++elementRefCounter; + if (reader.name() == QLatin1String("encoding")) { + const auto charRef = reader.attributes().value(QStringLiteral("char")); + if (!charRef.isEmpty()) { + const auto str = reader.attributes().value(QStringLiteral("string")).toString(); + characterEncodings.push_back({ charRef[0], str }); + } + } + reader.readNext(); + break; + case QXmlStreamReader::EndElement: + --elementRefCounter; + if (elementRefCounter == 0) + return; + reader.readNext(); + break; + default: + reader.readNext(); + break; + } + } +} + bool DefinitionData::checkKateVersion(const QStringRef& verStr) { const auto idx = verStr.indexOf(QLatin1Char('.')); diff --git a/src/lib/definition_p.h b/src/lib/definition_p.h --- a/src/lib/definition_p.h +++ b/src/lib/definition_p.h @@ -56,6 +56,7 @@ void loadGeneral(QXmlStreamReader &reader); void loadComments(QXmlStreamReader &reader); void loadFoldingIgnoreList(QXmlStreamReader &reader); + void loadSpellchecking(QXmlStreamReader &reader); bool checkKateVersion(const QStringRef &verStr); KeywordList keywordList(const QString &name) const; @@ -83,6 +84,7 @@ CommentPosition singleLineCommentPosition = CommentPosition::StartOfLine; QString multiLineCommentStartMarker; QString multiLineCommentEndMarker; + QVector> characterEncodings; QString fileName; QString name = QStringLiteral(QT_TRANSLATE_NOOP("Syntax highlighting", "None"));