diff --git a/autotests/syntaxrepository_test.cpp b/autotests/syntaxrepository_test.cpp --- a/autotests/syntaxrepository_test.cpp +++ b/autotests/syntaxrepository_test.cpp @@ -142,6 +142,12 @@ QVERIFY(def.isValid()); QVERIFY(!def.indentationBasedFoldingEnabled()); + // comment markers + QCOMPARE(def.singleLineCommentMarker(), QLatin1String("//")); + QCOMPARE(def.singleLineCommentPosition(), KSyntaxHighlighting::CommentPosition::StartOfLine); + const auto cppMultiLineCommentMarker = QPair(QLatin1String("/*"), QLatin1String("*/")); + QCOMPARE(def.multiLineCommentMarker(), cppMultiLineCommentMarker); + def = m_repo.definitionForName(QLatin1String("Python")); QVERIFY(def.isValid()); @@ -276,6 +282,11 @@ QVERIFY(def.keywordLists().isEmpty()); QVERIFY(def.formats().isEmpty()); QVERIFY(def.includedDefinitions().isEmpty()); + QVERIFY(def.singleLineCommentMarker().isEmpty()); + QCOMPARE(def.singleLineCommentPosition(), KSyntaxHighlighting::CommentPosition::StartOfLine); + const auto emptyPair = QPair(); + QCOMPARE(def.multiLineCommentMarker(), emptyPair); + for (QChar c : QStringLiteral("\t !%&()*+,-./:;<=>?[\\]^{|}~")) { QVERIFY(def.isWordDelimiter(c)); diff --git a/src/lib/definition.h b/src/lib/definition.h --- a/src/lib/definition.h +++ b/src/lib/definition.h @@ -21,6 +21,7 @@ #include "ksyntaxhighlighting_export.h" #include +#include #include @@ -37,6 +38,20 @@ class DefinitionData; +/** + * Defines the insert position when commenting code. + * @since 5.50 + * @see Definition::singleLineCommentPosition() + */ +enum class CommentPosition +{ + //! The comment marker is inserted at the beginning of a line at column 0 + StartOfLine = 0, + //! The comment marker is inserted after leading whitespaces right befire + //! the first non-whitespace character. + AfterWhitespace +}; + /** * Represents a syntax definition. * @@ -258,6 +273,29 @@ */ QVector includedDefinitions() const; + /** + * Returns the marker that starts a single line comment. + * For instance, in C++ the single line comment marker is "//". + * @since 5.50 + * @see singleLineCommentPosition(); + */ + QString singleLineCommentMarker() const; + + /** + * Returns the insert position of the comment marker for sinle line + * comments. + * @since 5.50 + * @see singleLineCommentMarker(); + */ + CommentPosition singleLineCommentPosition() const; + + /** + * Returns the markers that start and end multiline comments. + * For instance, in XML this is defined as "". + * @since 5.50 + */ + QPair multiLineCommentMarker() 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 @@ -250,6 +250,24 @@ return definitions; } +QString Definition::singleLineCommentMarker() const +{ + d->load(); + return d->singleLineCommentMarker; +} + +CommentPosition Definition::singleLineCommentPosition() const +{ + d->load(); + return d->singleLineCommentPosition; +} + +QPair Definition::multiLineCommentMarker() const +{ + d->load(); + return { d->multiLineCommentStartMarker, d->multiLineCommentEndMarker }; +} + Context* DefinitionData::initialContext() const { Q_ASSERT(!contexts.isEmpty()); @@ -542,6 +560,8 @@ indentationBasedFolding = Xml::attrToBool(reader.attributes().value(QStringLiteral("indentationsensitive"))); } else if (reader.name() == QLatin1String("emptyLines")) { loadFoldingIgnoreList(reader); + } else if (reader.name() == QLatin1String("comments")) { + loadComments(reader); } else { reader.skipCurrentElement(); } @@ -560,6 +580,45 @@ } } +void DefinitionData::loadComments(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("comments")); + 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("comment")) { + const bool isSingleLine = reader.attributes().value(QStringLiteral("name")) == QStringLiteral("singleLine"); + if (isSingleLine) { + singleLineCommentMarker = reader.attributes().value(QStringLiteral("start")).toString(); + const bool afterWhiteSpace = reader.attributes().value(QStringLiteral("position")).toString() == QStringLiteral("afterwhitespace"); + singleLineCommentPosition = afterWhiteSpace ? CommentPosition::AfterWhitespace : CommentPosition::StartOfLine; + } else { + multiLineCommentStartMarker = reader.attributes().value(QStringLiteral("start")).toString(); + multiLineCommentEndMarker = reader.attributes().value(QStringLiteral("end")).toString(); + } + } + reader.readNext(); + break; + case QXmlStreamReader::EndElement: + --elementRefCounter; + if (elementRefCounter == 0) + return; + reader.readNext(); + break; + default: + reader.readNext(); + break; + } + } +} + void DefinitionData::loadFoldingIgnoreList(QXmlStreamReader& reader) { Q_ASSERT(reader.name() == QLatin1String("emptyLines")); 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 @@ -19,6 +19,7 @@ #define KSYNTAXHIGHLIGHTING_DEFINITION_P_H #include "definitionref_p.h" +#include "definition.h" #include #include @@ -31,7 +32,6 @@ namespace KSyntaxHighlighting { -class Definition; class Repository; class DefinitionData @@ -54,6 +54,7 @@ void loadContexts(QXmlStreamReader &reader); void loadItemData(QXmlStreamReader &reader); void loadGeneral(QXmlStreamReader &reader); + void loadComments(QXmlStreamReader &reader); void loadFoldingIgnoreList(QXmlStreamReader &reader); bool checkKateVersion(const QStringRef &verStr); @@ -77,6 +78,10 @@ QString wordWrapDelimiters; bool indentationBasedFolding = false; QStringList foldingIgnoreList; + QString singleLineCommentMarker; + CommentPosition singleLineCommentPosition = CommentPosition::StartOfLine; + QString multiLineCommentStartMarker; + QString multiLineCommentEndMarker; QString fileName; QString name;