File indexing completed on 2023-05-30 09:03:12
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-or-later 0003 SPDX-FileCopyrightText: 2013 Filipe Saraiva <filipe@kde.org> 0004 */ 0005 0006 #include "pythonhighlighter.h" 0007 #include "pythonkeywords.h" 0008 #include "pythonsession.h" 0009 0010 PythonHighlighter::PythonHighlighter(QObject* parent, PythonSession* session) : Cantor::DefaultHighlighter(parent, session) 0011 { 0012 addRule(QRegularExpression(QStringLiteral("\\b\\w+(?=\\()")), functionFormat()); 0013 0014 //Code highlighting the different keywords 0015 addKeywords(PythonKeywords::instance()->keywords()); 0016 addFunctions(PythonKeywords::instance()->functions()); 0017 addVariables(PythonKeywords::instance()->variables()); 0018 } 0019 0020 void PythonHighlighter::highlightBlock(const QString &text) 0021 { 0022 if (skipHighlighting(text)) 0023 return; 0024 0025 // Do some backend independent highlighting (brackets etc.) 0026 DefaultHighlighter::highlightBlock(text); 0027 0028 const int IN_MULTILINE_COMMENT = 1; 0029 const int IN_SMALL_QUOTE_STRING = 2; 0030 const int IN_SINGLE_QUOTE_STRING = 4; 0031 const int IN_TRIPLE_QUOTE_STRING = 8; 0032 0033 static const QRegularExpression multiLineCommentStartEnd(QStringLiteral("'''")); 0034 static const QRegularExpression smallQuoteStartEnd(QStringLiteral("'")); 0035 static const QRegularExpression singleQuoteStringStartEnd(QStringLiteral("\"")); 0036 static const QRegularExpression tripleQuoteStringStartEnd(QStringLiteral("\"\"\"")); 0037 static const QRegularExpression singleLineCommentStart(QStringLiteral("#")); 0038 0039 int state = previousBlockState(); 0040 if (state == -1) { 0041 state = 0; 0042 } 0043 0044 QList<int> flags = { 0045 IN_TRIPLE_QUOTE_STRING, 0046 IN_SINGLE_QUOTE_STRING, 0047 IN_SMALL_QUOTE_STRING, 0048 IN_MULTILINE_COMMENT 0049 }; 0050 const QVector<QRegularExpression> regexps = { 0051 tripleQuoteStringStartEnd, 0052 singleQuoteStringStartEnd, 0053 smallQuoteStartEnd, 0054 multiLineCommentStartEnd 0055 }; 0056 QList<QTextCharFormat> formats = { 0057 stringFormat(), 0058 stringFormat(), 0059 stringFormat(), 0060 commentFormat() 0061 }; 0062 0063 int pos = 0; 0064 while (pos < text.length()) { 0065 // Trying to close current environments 0066 bool triggered = false; 0067 for (int i = 0; i < flags.size() && !triggered; i++) { 0068 int flag = flags[i]; 0069 QTextCharFormat &format = formats[i]; 0070 if (state & flag) { 0071 const QRegularExpressionMatch match = regexps.at(i).match(text, pos); 0072 int length; 0073 if (!match.hasMatch()) { 0074 length = text.length() - pos; 0075 } else { // found a match 0076 length = match.capturedStart(0) - pos + match.capturedLength(0); 0077 state -= flag; 0078 } 0079 setFormat(pos, length, format); 0080 pos = pos + length; 0081 triggered = true; 0082 } 0083 } 0084 if (triggered) { 0085 continue; 0086 } 0087 0088 QRegularExpressionMatch minMatch; 0089 int minPos = INT_MAX; 0090 int minIdx = -1; 0091 for (int i = 0; i < regexps.size(); i++) { 0092 const QRegularExpressionMatch match = regexps.at(i).match(text, pos); 0093 if (match.hasMatch()) { 0094 minPos = qMin(minPos, match.capturedStart(0)); 0095 minIdx = i; 0096 minMatch = match; 0097 } 0098 } 0099 0100 const int singleLineCommentStartPos = text.indexOf(singleLineCommentStart, pos); 0101 0102 if (singleLineCommentStartPos != -1 0103 && singleLineCommentStartPos < minPos) { 0104 setFormat(singleLineCommentStartPos, text.length() - singleLineCommentStartPos, commentFormat()); 0105 break; 0106 } else if (minMatch.hasMatch()) { 0107 state += flags[minIdx]; 0108 pos = minPos + minMatch.capturedLength(0); 0109 setFormat(minPos, minMatch.capturedLength(0), formats[minIdx]); 0110 } else { 0111 break; 0112 } 0113 } 0114 0115 setCurrentBlockState(state); 0116 }