File indexing completed on 2024-04-21 03:57:43

0001 /*
0002     SPDX-FileCopyrightText: 2001, 2002 Joseph Wenninger <jowenn@kde.org>
0003     SPDX-FileCopyrightText: 2001 Christoph Cullmann <cullmann@kde.org>
0004     SPDX-FileCopyrightText: 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #ifndef KATE_HIGHLIGHT_H
0010 #define KATE_HIGHLIGHT_H
0011 
0012 #include <KSyntaxHighlighting/AbstractHighlighter>
0013 #include <KSyntaxHighlighting/Definition>
0014 #include <KSyntaxHighlighting/FoldingRegion>
0015 #include <KSyntaxHighlighting/Format>
0016 #include <KSyntaxHighlighting/Theme>
0017 
0018 #include <KTextEditor/Attribute>
0019 #include <KTextEditor/Range>
0020 
0021 #include "spellcheck/prefixstore.h"
0022 
0023 #include <QHash>
0024 #include <QList>
0025 
0026 #include <QRegularExpression>
0027 #include <QStringList>
0028 
0029 #include <unordered_map>
0030 #include <vector>
0031 
0032 namespace KTextEditor
0033 {
0034 class DocumentPrivate;
0035 }
0036 namespace Kate
0037 {
0038 class TextLine;
0039 }
0040 
0041 class KateHighlighting : private KSyntaxHighlighting::AbstractHighlighter
0042 {
0043 public:
0044     explicit KateHighlighting(const KSyntaxHighlighting::Definition &def);
0045 
0046     /**
0047      * Folding storage
0048      */
0049     class Folding
0050     {
0051     public:
0052         /**
0053          * Construct folding.
0054          * @param _offset offset of the folding start
0055          * @param _length length of the folding
0056          * @param _foldingRegion folding region, includes if we start or end a region and the id
0057          */
0058         Folding(int _offset, int _length, KSyntaxHighlighting::FoldingRegion _foldingRegion)
0059             : offset(_offset)
0060             , length(_length)
0061             , foldingRegion(_foldingRegion)
0062         {
0063         }
0064 
0065         /**
0066          * offset
0067          */
0068         int offset = 0;
0069 
0070         /**
0071          * length
0072          */
0073         int length = 0;
0074 
0075         /**
0076          * folding region, includes if we start or end a region and the id
0077          */
0078         KSyntaxHighlighting::FoldingRegion foldingRegion;
0079     };
0080 
0081     /**
0082      * Folding vector used to pass out folding knowledge
0083      */
0084     typedef std::vector<Folding> Foldings;
0085 
0086 protected:
0087     /**
0088      * Reimplement this to apply formats to your output. The provided @p format
0089      * is valid for the interval [@p offset, @p offset + @p length).
0090      *
0091      * @param offset The start column of the interval for which @p format matches
0092      * @param length The length of the matching text
0093      * @param format The Format that applies to the range [offset, offset + length)
0094      *
0095      * @note Make sure to set a valid Definition, otherwise the parameter
0096      *       @p format is invalid for the entire line passed to highlightLine()
0097      *       (cf. Format::isValid()).
0098      *
0099      * @see applyFolding(), highlightLine()
0100      */
0101     void applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format) override;
0102 
0103     /**
0104      * Reimplement this to apply folding to your output. The provided
0105      * FoldingRegion @p region either stars or ends a code folding region in the
0106      * interval [@p offset, @p offset + @p length).
0107      *
0108      * @param offset The start column of the FoldingRegion
0109      * @param length The length of the matching text that starts / ends a
0110      *       folding region
0111      * @param region The FoldingRegion that applies to the range [offset, offset + length)
0112      *
0113      * @note The FoldingRegion @p region is @e always either of type
0114      *       FoldingRegion::Type::Begin or FoldingRegion::Type::End.
0115      *
0116      * @see applyFormat(), highlightLine(), FoldingRegion
0117      */
0118     void applyFolding(int offset, int length, KSyntaxHighlighting::FoldingRegion region) override;
0119 
0120 public:
0121     /**
0122      * Parse the text and fill in the context array and folding list array
0123      *
0124      * @param prevLine The previous line, the context array is picked up from that if present.
0125      * @param textLine The text line to parse
0126      * @param ctxChanged will be set to reflect if the context changed
0127      * @param foldings foldings vector to fill, if that is wanted
0128      */
0129     void doHighlight(const Kate::TextLine *prevLine, Kate::TextLine *textLine, bool &ctxChanged, Foldings *foldings = nullptr);
0130 
0131     const QString &name() const
0132     {
0133         return iName;
0134     }
0135     const QString &section() const
0136     {
0137         return iSection;
0138     }
0139     bool hidden() const
0140     {
0141         return iHidden;
0142     }
0143     const QString &style() const
0144     {
0145         return iStyle;
0146     }
0147     const QString &getIdentifier() const
0148     {
0149         return identifier;
0150     }
0151 
0152     /**
0153      * @return true if the character @p c is not a deliminator character
0154      *     for the corresponding highlight.
0155      */
0156     bool isInWord(QChar c, int attrib = 0) const;
0157 
0158     /**
0159      * @return true if the character @p c is a wordwrap deliminator as specified
0160      * in the general keyword section of the xml file.
0161      */
0162     bool canBreakAt(QChar c, int attrib = 0) const;
0163     /**
0164      *
0165      */
0166     const QList<QRegularExpression> &emptyLines(int attribute = 0) const;
0167 
0168     bool isEmptyLine(const Kate::TextLine *textline) const;
0169 
0170     /**
0171      * @return true if @p beginAttr and @p endAttr are members of the same
0172      * highlight, and there are comment markers of either type in that.
0173      */
0174     bool canComment(int startAttr, int endAttr) const;
0175 
0176     /**
0177      * @return the mulitiline comment start marker for the highlight
0178      * corresponding to @p attrib.
0179      */
0180     QString getCommentStart(int attrib = 0) const;
0181 
0182     /**
0183      * @return the muiltiline comment end marker for the highlight corresponding
0184      * to @p attrib.
0185      */
0186     QString getCommentEnd(int attrib = 0) const;
0187 
0188     /**
0189      * @return the single comment marker for the highlight corresponding
0190      * to @p attrib.
0191      */
0192     QString getCommentSingleLineStart(int attrib = 0) const;
0193 
0194     const QHash<QString, QChar> &characterEncodings(int attrib = 0) const;
0195 
0196     /**
0197      * @return the single comment marker position for the highlight corresponding
0198      * to @p attrib.
0199      */
0200     KSyntaxHighlighting::CommentPosition getCommentSingleLinePosition(int attrib = 0) const;
0201 
0202     bool attributeRequiresSpellchecking(int attr);
0203 
0204     /**
0205      * map attribute to its name
0206      * @return name of the attribute
0207      */
0208     QString nameForAttrib(int attrib) const;
0209 
0210     /**
0211      * Get attribute for the given cursor position.
0212      * @param doc document to use
0213      * @param cursor cursor position in the given document
0214      * @return attribute valid at that location, default is 0
0215      */
0216     int attributeForLocation(KTextEditor::DocumentPrivate *doc, const KTextEditor::Cursor cursor);
0217 
0218     /**
0219      * Get all keywords valid for the given cursor position.
0220      * @param doc document to use
0221      * @param cursor cursor position in the given document
0222      * @return all keywords valid at that location
0223      */
0224     QStringList keywordsForLocation(KTextEditor::DocumentPrivate *doc, const KTextEditor::Cursor cursor);
0225 
0226     /**
0227      * Is spellchecking required for the tiven cursor position?
0228      * @param doc document to use
0229      * @param cursor cursor position in the given document
0230      * @return spell checking required?
0231      */
0232     bool spellCheckingRequiredForLocation(KTextEditor::DocumentPrivate *doc, const KTextEditor::Cursor cursor);
0233 
0234     /**
0235      * Get highlighting mode for the given cursor position.
0236      * @param doc document to use
0237      * @param cursor cursor position in the given document
0238      * @return mode valid at that location
0239      */
0240     QString higlightingModeForLocation(KTextEditor::DocumentPrivate *doc, const KTextEditor::Cursor cursor);
0241 
0242     KSyntaxHighlighting::Theme::TextStyle defaultStyleForAttribute(int attr) const;
0243 
0244     void clearAttributeArrays();
0245 
0246     QList<KTextEditor::Attribute::Ptr> attributes(const QString &schema);
0247 
0248     inline bool noHighlighting() const
0249     {
0250         return noHl;
0251     }
0252 
0253     /**
0254      * Indentation mode, e.g. c-style, ....
0255      * @return indentation mode
0256      */
0257     const QString &indentation() const
0258     {
0259         return m_indentation;
0260     }
0261 
0262     const QHash<QString, QChar> &getCharacterEncodings(int attrib) const;
0263     const KatePrefixStore &getCharacterEncodingsPrefixStore(int attrib) const;
0264     const QHash<QChar, QString> &getReverseCharacterEncodings(int attrib) const;
0265 
0266     /**
0267      * Returns a list of names of embedded modes.
0268      */
0269     QStringList getEmbeddedHighlightingModes() const;
0270 
0271     /**
0272      * create list of attributes from internal formats with properties as defined in syntax file
0273      * @param schema The id of the chosen schema
0274      * @return attributes list with attributes as defined in syntax file
0275      */
0276     QList<KTextEditor::Attribute::Ptr> attributesForDefinition(const QString &schema) const;
0277 
0278     /**
0279      * Retrieve all formats for this highlighting.
0280      * @return all formats for the highlighting definition of this highlighting includes included formats
0281      */
0282     const std::vector<KSyntaxHighlighting::Format> &formats() const
0283     {
0284         return m_formats;
0285     }
0286 
0287 private:
0288     int sanitizeFormatIndex(int attrib) const;
0289 
0290 private:
0291     QStringList embeddedHighlightingModes;
0292 
0293     bool noHl = true;
0294     bool folding = false;
0295 
0296     QString iName;
0297     QString iSection;
0298     bool iHidden = false;
0299     QString identifier;
0300     QString iStyle;
0301 
0302     /**
0303      * Indentation mode, e.g. c-style, ....
0304      */
0305     QString m_indentation;
0306 
0307     bool m_foldingIndentationSensitive = false;
0308 
0309     // map schema name to attributes...
0310     QHash<QString, QList<KTextEditor::Attribute::Ptr>> m_attributeArrays;
0311 
0312     /**
0313      * This class holds the additional properties for one highlight
0314      * definition, such as comment strings, deliminators etc.
0315      */
0316     class HighlightPropertyBag
0317     {
0318     public:
0319         KSyntaxHighlighting::Definition definition;
0320         QString singleLineCommentMarker;
0321         QString multiLineCommentStart;
0322         QString multiLineCommentEnd;
0323         KSyntaxHighlighting::CommentPosition singleLineCommentPosition;
0324         QList<QRegularExpression> emptyLines;
0325         QHash<QString, QChar> characterEncodings;
0326         KatePrefixStore characterEncodingsPrefixStore;
0327         QHash<QChar, QString> reverseCharacterEncodings;
0328     };
0329 
0330 public:
0331     inline bool foldingIndentationSensitive()
0332     {
0333         return m_foldingIndentationSensitive;
0334     }
0335     inline bool allowsFolding()
0336     {
0337         return folding;
0338     }
0339 
0340     /**
0341      * Highlight properties for this definition and each included highlight definition.
0342      */
0343     std::vector<HighlightPropertyBag> m_properties;
0344 
0345     /**
0346      * all formats for the highlighting definition of this highlighting
0347      * includes included formats
0348      */
0349     std::vector<KSyntaxHighlighting::Format> m_formats;
0350 
0351     /**
0352      * for each format, pointer to the matching HighlightPropertyBag in m_properties
0353      */
0354     std::vector<const HighlightPropertyBag *> m_propertiesForFormat;
0355 
0356     /**
0357      * mapping of format id => index into m_formats
0358      */
0359     std::unordered_map<int, int> m_formatsIdToIndex;
0360 
0361     /**
0362      * textline to do updates on during doHighlight
0363      */
0364     Kate::TextLine *m_textLineToHighlight = nullptr;
0365 
0366     /**
0367      * foldings vector to do updates on during doHighlight
0368      * might not be set, then we ignor that
0369      */
0370     Foldings *m_foldings = nullptr;
0371 
0372     /**
0373      * check if the folding begin/ends are balanced!
0374      * updated during doHighlight
0375      */
0376     QHash<int, int> m_foldingStartToCount;
0377 };
0378 
0379 #endif