Changeset View
Changeset View
Standalone View
Standalone View
src/backends/python/pythonhighlighter.cpp
Show All 21 Lines | |||||
22 | #include "pythonkeywords.h" | 22 | #include "pythonkeywords.h" | ||
23 | 23 | | |||
24 | #include <QTextEdit> | 24 | #include <QTextEdit> | ||
25 | #include <QDebug> | 25 | #include <QDebug> | ||
26 | 26 | | |||
27 | PythonHighlighter::PythonHighlighter(QObject* parent) : Cantor::DefaultHighlighter(parent) | 27 | PythonHighlighter::PythonHighlighter(QObject* parent) : Cantor::DefaultHighlighter(parent) | ||
28 | { | 28 | { | ||
29 | qDebug() << "PythonHighlighter construtor"; | 29 | qDebug() << "PythonHighlighter construtor"; | ||
30 | addRule(QRegExp(QLatin1String("\\b[A-Za-z0-9_]+(?=\\()")), functionFormat()); | 30 | addRule(QRegExp(QLatin1String("\\b\\w+(?=\\()")), functionFormat()); | ||
31 | 31 | | |||
32 | //Code highlighting the different keywords | 32 | //Code highlighting the different keywords | ||
33 | addKeywords(PythonKeywords::instance()->keywords()); | 33 | addKeywords(PythonKeywords::instance()->keywords()); | ||
34 | | ||||
35 | addRule(QLatin1String("FIXME"), commentFormat()); | | |||
36 | addRule(QLatin1String("TODO"), commentFormat()); | | |||
37 | | ||||
38 | addFunctions(PythonKeywords::instance()->functions()); | 34 | addFunctions(PythonKeywords::instance()->functions()); | ||
39 | addVariables(PythonKeywords::instance()->variables()); | 35 | addVariables(PythonKeywords::instance()->variables()); | ||
40 | | ||||
41 | addRule(QRegExp(QLatin1String("\".*\"")), stringFormat()); | | |||
42 | addRule(QRegExp(QLatin1String("'.*'")), stringFormat()); | | |||
43 | addRule(QRegExp(QLatin1String("#[^\n]*")), commentFormat()); | | |||
44 | | ||||
45 | commentStartExpression = QRegExp(QLatin1String("'''[^\n]*")); | | |||
46 | commentEndExpression = QRegExp(QLatin1String("'''")); | | |||
47 | } | 36 | } | ||
48 | 37 | | |||
49 | PythonHighlighter::~PythonHighlighter() | 38 | PythonHighlighter::~PythonHighlighter() | ||
50 | { | 39 | { | ||
51 | } | 40 | } | ||
52 | 41 | | |||
53 | void PythonHighlighter::highlightBlock(const QString& text) | 42 | void PythonHighlighter::highlightBlock(const QString &text) | ||
54 | { | 43 | { | ||
55 | qDebug() << "PythonHighlighter::highlightBlock"; | | |||
56 | qDebug() << "text: " << text; | | |||
57 | | ||||
58 | if (skipHighlighting(text)){ | 44 | if (skipHighlighting(text)) { | ||
59 | qDebug() << "skipHighlighting(" << text << " ) " << "== true"; | | |||
60 | return; | 45 | return; | ||
61 | } | 46 | } | ||
62 | 47 | | |||
63 | //Do some backend independent highlighting (brackets etc.) | 48 | // Do some backend independent highlighting (brackets etc.) | ||
64 | DefaultHighlighter::highlightBlock(text); | 49 | DefaultHighlighter::highlightBlock(text); | ||
65 | 50 | | |||
66 | setCurrentBlockState(0); | 51 | const int IN_MULTILINE_COMMENT = 1; | ||
67 | 52 | const int IN_SMALL_QUOTE_STRING = 2; | |||
68 | int startIndex = 0; | 53 | const int IN_SINGLE_QUOTE_STRING = 4; | ||
69 | if (previousBlockState() != 1) | 54 | const int IN_TRIPLE_QUOTE_STRING = 8; | ||
70 | startIndex = commentStartExpression.indexIn(text); | 55 | | ||
71 | 56 | QRegExp multiLineCommentStartEnd(QLatin1String("'''")); | |||
72 | while (startIndex >= 0) { | 57 | QRegExp smallQuoteStartEnd(QLatin1String("'")); | ||
73 | 58 | QRegExp singleQuoteStringStartEnd(QLatin1String("\"")); | |||
74 | int endIndex = commentEndExpression.indexIn(text, startIndex); | 59 | QRegExp tripleQuoteStringStartEnd(QLatin1String("\"\"\"")); | ||
75 | int commentLength; | 60 | QRegExp singleLineCommentStart(QLatin1String("#")); | ||
76 | if (endIndex == -1) { | 61 | | ||
62 | int state = previousBlockState(); | ||||
63 | if (state == -1) { | ||||
64 | state = 0; | ||||
65 | } | ||||
66 | | ||||
67 | QList<int> flags = { | ||||
68 | IN_TRIPLE_QUOTE_STRING, | ||||
69 | IN_SINGLE_QUOTE_STRING, | ||||
70 | IN_SMALL_QUOTE_STRING, | ||||
71 | IN_MULTILINE_COMMENT | ||||
72 | }; | ||||
73 | QList<QRegExp> regexps = { | ||||
74 | tripleQuoteStringStartEnd, | ||||
75 | singleQuoteStringStartEnd, | ||||
76 | smallQuoteStartEnd, | ||||
77 | multiLineCommentStartEnd | ||||
78 | }; | ||||
79 | QList<QTextCharFormat> formats = { | ||||
80 | stringFormat(), | ||||
81 | stringFormat(), | ||||
82 | stringFormat(), | ||||
83 | commentFormat() | ||||
84 | }; | ||||
85 | | ||||
86 | int pos = 0; | ||||
87 | while (pos < text.length()) { | ||||
88 | // Trying to close current environments | ||||
89 | bool triggered = false; | ||||
90 | for (int i = 0; i < flags.size() and not triggered; i++) { | ||||
91 | int flag = flags[i]; | ||||
92 | QRegExp ®exp = regexps[i]; | ||||
93 | QTextCharFormat &format = formats[i]; | ||||
94 | if (state & flag) { | ||||
95 | int new_pos = regexp.indexIn(text, pos); | ||||
96 | int length; | ||||
97 | if (new_pos == -1) { | ||||
98 | length = text.length() - pos; | ||||
99 | } else { | ||||
100 | length = new_pos - pos + regexp.matchedLength(); | ||||
101 | state -= flag; | ||||
102 | } | ||||
103 | setFormat(pos, length, format); | ||||
104 | pos = pos + length; | ||||
105 | triggered = true; | ||||
106 | } | ||||
107 | } | ||||
108 | if (triggered) { | ||||
109 | continue; | ||||
110 | } | ||||
111 | | ||||
112 | QRegExp *minRegexp = nullptr; | ||||
113 | int minPos = INT_MAX; | ||||
114 | int minIdx = -1; | ||||
115 | for (int i = 0; i < regexps.size(); i++) { | ||||
116 | QRegExp ®exp = regexps[i]; | ||||
117 | int newPos = regexp.indexIn(text, pos); | ||||
118 | if (newPos != -1) { | ||||
119 | minPos = qMin(minPos, newPos); | ||||
120 | minRegexp = ®exp; | ||||
121 | minIdx = i; | ||||
122 | } | ||||
123 | } | ||||
77 | 124 | | |||
78 | setCurrentBlockState(1); | 125 | int singleLineCommentStartPos = | ||
79 | commentLength = text.length() - startIndex; | 126 | singleLineCommentStart.indexIn(text, pos); | ||
127 | | ||||
128 | if (singleLineCommentStartPos != -1 | ||||
129 | and singleLineCommentStartPos < minPos) { | ||||
130 | setFormat(pos, text.length() - pos, commentFormat()); | ||||
131 | break; | ||||
132 | } else if (minRegexp) { | ||||
133 | state += flags[minIdx]; | ||||
134 | pos = minPos + minRegexp->matchedLength(); | ||||
135 | setFormat(minPos, minRegexp->matchedLength(), formats[minIdx]); | ||||
80 | } else { | 136 | } else { | ||
81 | commentLength = endIndex - startIndex | 137 | break; | ||
82 | + commentEndExpression.matchedLength(); | | |||
83 | } | 138 | } | ||
84 | setFormat(startIndex, commentLength, commentFormat()); | | |||
85 | startIndex = commentStartExpression.indexIn(text, startIndex + commentLength); | | |||
86 | } | 139 | } | ||
140 | | ||||
141 | setCurrentBlockState(state); | ||||
87 | } | 142 | } | ||
88 | 143 | | |||
89 | void PythonHighlighter::updateHighlight() | 144 | void PythonHighlighter::updateHighlight() | ||
90 | { | 145 | { | ||
91 | qDebug(); | 146 | qDebug(); | ||
92 | 147 | | |||
93 | addVariables(PythonKeywords::instance()->variables()); | 148 | addVariables(PythonKeywords::instance()->variables()); | ||
94 | rehighlight(); | 149 | rehighlight(); | ||
95 | } | 150 | } | ||
96 | | ||||
97 | QString PythonHighlighter::nonSeparatingCharacters() const | | |||
98 | { | | |||
99 | qDebug() << "PythonHighlighter::nonSeparatingCharacters() function"; | | |||
100 | return QLatin1String("[%]"); | | |||
101 | } | |