]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexPython.cxx
df8b7085bfde7ca13d0d1cc19c7acd7f5d64cfe4
[wxWidgets.git] / src / stc / scintilla / src / LexPython.cxx
1 // SciTE - Scintilla based Text Editor
2 // LexPython.cxx - lexer for Python
3 // Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
4 // The License.txt file describes the conditions under which this software may be distributed.
5
6 #include <stdlib.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <stdarg.h>
11
12 #include "Platform.h"
13
14 #include "PropSet.h"
15 #include "Accessor.h"
16 #include "KeyWords.h"
17 #include "Scintilla.h"
18 #include "SciLexer.h"
19
20 static void ClassifyWordPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) {
21 char s[100];
22 bool wordIsNumber = isdigit(styler[start]);
23 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
24 s[i] = styler[start + i];
25 s[i + 1] = '\0';
26 }
27 char chAttr = SCE_P_IDENTIFIER;
28 if (0 == strcmp(prevWord, "class"))
29 chAttr = SCE_P_CLASSNAME;
30 else if (0 == strcmp(prevWord, "def"))
31 chAttr = SCE_P_DEFNAME;
32 else if (wordIsNumber)
33 chAttr = SCE_P_NUMBER;
34 else if (keywords.InList(s))
35 chAttr = SCE_P_WORD;
36 styler.ColourTo(end, chAttr);
37 strcpy(prevWord, s);
38 }
39
40 static bool IsPyComment(Accessor &styler, int pos, int len) {
41 return len>0 && styler[pos]=='#';
42 }
43
44 static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
45 WordList *keywordlists[], Accessor &styler) {
46
47 int lengthDoc = startPos + length;
48
49 // Backtrack to previous line in case need to fix its fold status or tab whinging
50 int lineCurrent = styler.GetLine(startPos);
51 if (startPos > 0) {
52 if (lineCurrent > 0) {
53 lineCurrent--;
54 startPos = styler.LineStart(lineCurrent);
55 if (startPos == 0)
56 initStyle = SCE_P_DEFAULT;
57 else
58 initStyle = styler.StyleAt(startPos-1);
59 }
60 }
61
62 // Python uses a different mask because bad indentation is marked by oring with 32
63 styler.StartAt(startPos, 127);
64
65 WordList &keywords = *keywordlists[0];
66
67 bool fold = styler.GetPropertyInt("fold");
68 int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
69 char prevWord[200];
70 prevWord[0] = '\0';
71 if (length == 0)
72 return ;
73 int spaceFlags = 0;
74
75 int state = initStyle & 31;
76
77 int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
78 if ((state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE))
79 indentCurrent |= SC_FOLDLEVELWHITEFLAG;
80
81 char chPrev = ' ';
82 char chPrev2 = ' ';
83 char chNext = styler[startPos];
84 styler.StartSegment(startPos);
85 bool atStartLine = true;
86 for (int i = startPos; i < lengthDoc; i++) {
87
88 if (atStartLine) {
89 char chBad = static_cast<char>(64);
90 char chGood = static_cast<char>(0);
91 char chFlags = chGood;
92 if (whingeLevel == 1) {
93 chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood;
94 } else if (whingeLevel == 2) {
95 chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood;
96 } else if (whingeLevel == 3) {
97 chFlags = (spaceFlags & wsSpace) ? chBad : chGood;
98 } else if (whingeLevel == 4) {
99 chFlags = (spaceFlags & wsTab) ? chBad : chGood;
100 }
101 styler.SetFlags(chFlags, static_cast<char>(state));
102 atStartLine = false;
103 }
104
105 char ch = chNext;
106 chNext = styler.SafeGetCharAt(i + 1);
107 char chNext2 = styler.SafeGetCharAt(i + 2);
108
109 if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {
110 if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) {
111 // Perform colourisation of white space and triple quoted strings at end of each line to allow
112 // tab marking to work inside white space and triple quoted strings
113 styler.ColourTo(i, state);
114 }
115
116 int lev = indentCurrent;
117 int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsPyComment);
118 if ((state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE))
119 indentNext |= SC_FOLDLEVELWHITEFLAG;
120 if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
121 // Only non whitespace lines can be headers
122 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
123 lev |= SC_FOLDLEVELHEADERFLAG;
124 } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
125 // Line after is blank so check the next - maybe should continue further?
126 int spaceFlags2 = 0;
127 int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsPyComment);
128 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
129 lev |= SC_FOLDLEVELHEADERFLAG;
130 }
131 }
132 }
133 indentCurrent = indentNext;
134 if (fold) {
135 styler.SetLevel(lineCurrent, lev);
136 }
137 lineCurrent++;
138 atStartLine = true;
139 }
140
141 if (styler.IsLeadByte(ch)) {
142 chNext = styler.SafeGetCharAt(i + 2);
143 chPrev = ' ';
144 chPrev2 = ' ';
145 i += 1;
146 continue;
147 }
148
149 if (state == SCE_P_STRINGEOL) {
150 if (ch != '\r' && ch != '\n') {
151 styler.ColourTo(i - 1, state);
152 state = SCE_P_DEFAULT;
153 }
154 }
155 if (state == SCE_P_DEFAULT) {
156 if (iswordstart(ch)) {
157 styler.ColourTo(i - 1, state);
158 state = SCE_P_WORD;
159 } else if (ch == '#') {
160 styler.ColourTo(i - 1, state);
161 state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
162 } else if (ch == '\"') {
163 styler.ColourTo(i - 1, state);
164 if (chNext == '\"' && chNext2 == '\"') {
165 i += 2;
166 state = SCE_P_TRIPLEDOUBLE;
167 ch = ' ';
168 chPrev = ' ';
169 chNext = styler.SafeGetCharAt(i + 1);
170 } else {
171 state = SCE_P_STRING;
172 }
173 } else if (ch == '\'') {
174 styler.ColourTo(i - 1, state);
175 if (chNext == '\'' && chNext2 == '\'') {
176 i += 2;
177 state = SCE_P_TRIPLE;
178 ch = ' ';
179 chPrev = ' ';
180 chNext = styler.SafeGetCharAt(i + 1);
181 } else {
182 state = SCE_P_CHARACTER;
183 }
184 } else if (isoperator(ch)) {
185 styler.ColourTo(i - 1, state);
186 styler.ColourTo(i, SCE_P_OPERATOR);
187 }
188 } else if (state == SCE_P_WORD) {
189 if (!iswordchar(ch)) {
190 ClassifyWordPy(styler.GetStartSegment(), i - 1, keywords, styler, prevWord);
191 state = SCE_P_DEFAULT;
192 if (ch == '#') {
193 state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
194 } else if (ch == '\"') {
195 if (chNext == '\"' && chNext2 == '\"') {
196 i += 2;
197 state = SCE_P_TRIPLEDOUBLE;
198 ch = ' ';
199 chPrev = ' ';
200 chNext = styler.SafeGetCharAt(i + 1);
201 } else {
202 state = SCE_P_STRING;
203 }
204 } else if (ch == '\'') {
205 if (chNext == '\'' && chNext2 == '\'') {
206 i += 2;
207 state = SCE_P_TRIPLE;
208 ch = ' ';
209 chPrev = ' ';
210 chNext = styler.SafeGetCharAt(i + 1);
211 } else {
212 state = SCE_P_CHARACTER;
213 }
214 } else if (isoperator(ch)) {
215 styler.ColourTo(i, SCE_P_OPERATOR);
216 }
217 }
218 } else {
219 if (state == SCE_P_COMMENTLINE || state == SCE_P_COMMENTBLOCK) {
220 if (ch == '\r' || ch == '\n') {
221 styler.ColourTo(i - 1, state);
222 state = SCE_P_DEFAULT;
223 }
224 } else if (state == SCE_P_STRING) {
225 if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
226 styler.ColourTo(i - 1, state);
227 state = SCE_P_STRINGEOL;
228 } else if (ch == '\\') {
229 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
230 i++;
231 ch = chNext;
232 chNext = styler.SafeGetCharAt(i + 1);
233 }
234 } else if (ch == '\"') {
235 styler.ColourTo(i, state);
236 state = SCE_P_DEFAULT;
237 }
238 } else if (state == SCE_P_CHARACTER) {
239 if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
240 styler.ColourTo(i - 1, state);
241 state = SCE_P_STRINGEOL;
242 } else if (ch == '\\') {
243 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
244 i++;
245 ch = chNext;
246 chNext = styler.SafeGetCharAt(i + 1);
247 }
248 } else if (ch == '\'') {
249 styler.ColourTo(i, state);
250 state = SCE_P_DEFAULT;
251 }
252 } else if (state == SCE_P_TRIPLE) {
253 if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
254 styler.ColourTo(i, state);
255 state = SCE_P_DEFAULT;
256 }
257 } else if (state == SCE_P_TRIPLEDOUBLE) {
258 if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
259 styler.ColourTo(i, state);
260 state = SCE_P_DEFAULT;
261 }
262 }
263 }
264 chPrev2 = chPrev;
265 chPrev = ch;
266 }
267 if (state == SCE_P_WORD) {
268 ClassifyWordPy(styler.GetStartSegment(), lengthDoc, keywords, styler, prevWord);
269 } else {
270 styler.ColourTo(lengthDoc, state);
271 }
272 }
273
274 LexerModule lmPython(SCLEX_PYTHON, ColourisePyDoc);