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