1 // Scintilla source code edit control
2 /** @file LexOthers.cxx
3 ** Lexers for batch files, diff results, properties files, make files and error lists.
5 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
16 #include "Scintilla.h"
20 #include "LexAccessor.h"
22 #include "StyleContext.h"
23 #include "CharacterSet.h"
24 #include "LexerModule.h"
27 using namespace Scintilla
;
30 static bool strstart(const char *haystack
, const char *needle
) {
31 return strncmp(haystack
, needle
, strlen(needle
)) == 0;
34 static bool Is0To9(char ch
) {
35 return (ch
>= '0') && (ch
<= '9');
38 static bool Is1To9(char ch
) {
39 return (ch
>= '1') && (ch
<= '9');
42 static bool IsAlphabetic(int ch
) {
43 return IsASCII(ch
) && isalpha(ch
);
46 static inline bool AtEOL(Accessor
&styler
, unsigned int i
) {
47 return (styler
[i
] == '\n') ||
48 ((styler
[i
] == '\r') && (styler
.SafeGetCharAt(i
+ 1) != '\n'));
51 // Tests for BATCH Operators
52 static bool IsBOperator(char ch
) {
53 return (ch
== '=') || (ch
== '+') || (ch
== '>') || (ch
== '<') ||
54 (ch
== '|') || (ch
== '?') || (ch
== '*');
57 // Tests for BATCH Separators
58 static bool IsBSeparator(char ch
) {
59 return (ch
== '\\') || (ch
== '.') || (ch
== ';') ||
60 (ch
== '\"') || (ch
== '\'') || (ch
== '/');
63 static void ColouriseBatchLine(
65 unsigned int lengthLine
,
66 unsigned int startLine
,
68 WordList
*keywordlists
[],
71 unsigned int offset
= 0; // Line Buffer Offset
72 unsigned int cmdLoc
; // External Command / Program Location
73 char wordBuffer
[81]; // Word Buffer - large to catch long paths
74 unsigned int wbl
; // Word Buffer Length
75 unsigned int wbo
; // Word Buffer Offset - also Special Keyword Buffer Length
76 WordList
&keywords
= *keywordlists
[0]; // Internal Commands
77 WordList
&keywords2
= *keywordlists
[1]; // External Commands (optional)
79 // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords
80 // Toggling Regular Keyword Checking off improves readability
81 // Other Regular Keywords and External Commands / Programs might also benefit from toggling
82 // Need a more robust algorithm to properly toggle Regular Keyword Checking
83 bool continueProcessing
= true; // Used to toggle Regular Keyword Checking
84 // Special Keywords are those that allow certain characters without whitespace after the command
85 // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path=
86 // Special Keyword Buffer used to determine if the first n characters is a Keyword
87 char sKeywordBuffer
[10]; // Special Keyword Buffer
88 bool sKeywordFound
; // Exit Special Keyword for-loop if found
90 // Skip initial spaces
91 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
94 // Colorize Default Text
95 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
96 // Set External Command / Program Location
99 // Check for Fake Label (Comment) or Real Label - return if found
100 if (lineBuffer
[offset
] == ':') {
101 if (lineBuffer
[offset
+ 1] == ':') {
102 // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
103 styler
.ColourTo(endPos
, SCE_BAT_COMMENT
);
105 // Colorize Real Label
106 styler
.ColourTo(endPos
, SCE_BAT_LABEL
);
109 // Check for Drive Change (Drive Change is internal command) - return if found
110 } else if ((IsAlphabetic(lineBuffer
[offset
])) &&
111 (lineBuffer
[offset
+ 1] == ':') &&
112 ((isspacechar(lineBuffer
[offset
+ 2])) ||
113 (((lineBuffer
[offset
+ 2] == '\\')) &&
114 (isspacechar(lineBuffer
[offset
+ 3]))))) {
115 // Colorize Regular Keyword
116 styler
.ColourTo(endPos
, SCE_BAT_WORD
);
120 // Check for Hide Command (@ECHO OFF/ON)
121 if (lineBuffer
[offset
] == '@') {
122 styler
.ColourTo(startLine
+ offset
, SCE_BAT_HIDE
);
126 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
130 // Read remainder of line word-at-a-time or remainder-of-word-at-a-time
131 while (offset
< lengthLine
) {
132 if (offset
> startLine
) {
133 // Colorize Default Text
134 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
136 // Copy word from Line Buffer into Word Buffer
138 for (; offset
< lengthLine
&& wbl
< 80 &&
139 !isspacechar(lineBuffer
[offset
]); wbl
++, offset
++) {
140 wordBuffer
[wbl
] = static_cast<char>(tolower(lineBuffer
[offset
]));
142 wordBuffer
[wbl
] = '\0';
145 // Check for Comment - return if found
146 if (CompareCaseInsensitive(wordBuffer
, "rem") == 0) {
147 styler
.ColourTo(endPos
, SCE_BAT_COMMENT
);
150 // Check for Separator
151 if (IsBSeparator(wordBuffer
[0])) {
152 // Check for External Command / Program
153 if ((cmdLoc
== offset
- wbl
) &&
154 ((wordBuffer
[0] == ':') ||
155 (wordBuffer
[0] == '\\') ||
156 (wordBuffer
[0] == '.'))) {
157 // Reset Offset to re-process remainder of word
159 // Colorize External Command / Program
161 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
162 } else if (keywords2
.InList(wordBuffer
)) {
163 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
165 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
167 // Reset External Command / Program Location
170 // Reset Offset to re-process remainder of word
172 // Colorize Default Text
173 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
175 // Check for Regular Keyword in list
176 } else if ((keywords
.InList(wordBuffer
)) &&
177 (continueProcessing
)) {
178 // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking
179 if ((CompareCaseInsensitive(wordBuffer
, "echo") == 0) ||
180 (CompareCaseInsensitive(wordBuffer
, "goto") == 0) ||
181 (CompareCaseInsensitive(wordBuffer
, "prompt") == 0) ||
182 (CompareCaseInsensitive(wordBuffer
, "set") == 0)) {
183 continueProcessing
= false;
185 // Identify External Command / Program Location for ERRORLEVEL, and EXIST
186 if ((CompareCaseInsensitive(wordBuffer
, "errorlevel") == 0) ||
187 (CompareCaseInsensitive(wordBuffer
, "exist") == 0)) {
188 // Reset External Command / Program Location
191 while ((cmdLoc
< lengthLine
) &&
192 (isspacechar(lineBuffer
[cmdLoc
]))) {
196 while ((cmdLoc
< lengthLine
) &&
197 (!isspacechar(lineBuffer
[cmdLoc
]))) {
201 while ((cmdLoc
< lengthLine
) &&
202 (isspacechar(lineBuffer
[cmdLoc
]))) {
205 // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH
206 } else if ((CompareCaseInsensitive(wordBuffer
, "call") == 0) ||
207 (CompareCaseInsensitive(wordBuffer
, "do") == 0) ||
208 (CompareCaseInsensitive(wordBuffer
, "loadhigh") == 0) ||
209 (CompareCaseInsensitive(wordBuffer
, "lh") == 0)) {
210 // Reset External Command / Program Location
213 while ((cmdLoc
< lengthLine
) &&
214 (isspacechar(lineBuffer
[cmdLoc
]))) {
218 // Colorize Regular keyword
219 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_WORD
);
220 // No need to Reset Offset
221 // Check for Special Keyword in list, External Command / Program, or Default Text
222 } else if ((wordBuffer
[0] != '%') &&
223 (wordBuffer
[0] != '!') &&
224 (!IsBOperator(wordBuffer
[0])) &&
225 (continueProcessing
)) {
226 // Check for Special Keyword
227 // Affected Commands are in Length range 2-6
228 // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected
229 sKeywordFound
= false;
230 for (unsigned int keywordLength
= 2; keywordLength
< wbl
&& keywordLength
< 7 && !sKeywordFound
; keywordLength
++) {
232 // Copy Keyword Length from Word Buffer into Special Keyword Buffer
233 for (; wbo
< keywordLength
; wbo
++) {
234 sKeywordBuffer
[wbo
] = static_cast<char>(wordBuffer
[wbo
]);
236 sKeywordBuffer
[wbo
] = '\0';
237 // Check for Special Keyword in list
238 if ((keywords
.InList(sKeywordBuffer
)) &&
239 ((IsBOperator(wordBuffer
[wbo
])) ||
240 (IsBSeparator(wordBuffer
[wbo
])))) {
241 sKeywordFound
= true;
242 // ECHO requires no further Regular Keyword Checking
243 if (CompareCaseInsensitive(sKeywordBuffer
, "echo") == 0) {
244 continueProcessing
= false;
246 // Colorize Special Keyword as Regular Keyword
247 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_WORD
);
248 // Reset Offset to re-process remainder of word
249 offset
-= (wbl
- wbo
);
252 // Check for External Command / Program or Default Text
253 if (!sKeywordFound
) {
255 // Check for External Command / Program
256 if (cmdLoc
== offset
- wbl
) {
257 // Read up to %, Operator or Separator
258 while ((wbo
< wbl
) &&
259 (wordBuffer
[wbo
] != '%') &&
260 (wordBuffer
[wbo
] != '!') &&
261 (!IsBOperator(wordBuffer
[wbo
])) &&
262 (!IsBSeparator(wordBuffer
[wbo
]))) {
265 // Reset External Command / Program Location
266 cmdLoc
= offset
- (wbl
- wbo
);
267 // Reset Offset to re-process remainder of word
268 offset
-= (wbl
- wbo
);
269 // CHOICE requires no further Regular Keyword Checking
270 if (CompareCaseInsensitive(wordBuffer
, "choice") == 0) {
271 continueProcessing
= false;
273 // Check for START (and its switches) - What follows is External Command \ Program
274 if (CompareCaseInsensitive(wordBuffer
, "start") == 0) {
275 // Reset External Command / Program Location
278 while ((cmdLoc
< lengthLine
) &&
279 (isspacechar(lineBuffer
[cmdLoc
]))) {
282 // Reset External Command / Program Location if command switch detected
283 if (lineBuffer
[cmdLoc
] == '/') {
284 // Skip command switch
285 while ((cmdLoc
< lengthLine
) &&
286 (!isspacechar(lineBuffer
[cmdLoc
]))) {
290 while ((cmdLoc
< lengthLine
) &&
291 (isspacechar(lineBuffer
[cmdLoc
]))) {
296 // Colorize External Command / Program
298 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
299 } else if (keywords2
.InList(wordBuffer
)) {
300 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
302 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
304 // No need to Reset Offset
305 // Check for Default Text
307 // Read up to %, Operator or Separator
308 while ((wbo
< wbl
) &&
309 (wordBuffer
[wbo
] != '%') &&
310 (wordBuffer
[wbo
] != '!') &&
311 (!IsBOperator(wordBuffer
[wbo
])) &&
312 (!IsBSeparator(wordBuffer
[wbo
]))) {
315 // Colorize Default Text
316 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_DEFAULT
);
317 // Reset Offset to re-process remainder of word
318 offset
-= (wbl
- wbo
);
321 // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a)
322 } else if (wordBuffer
[0] == '%') {
323 // Colorize Default Text
324 styler
.ColourTo(startLine
+ offset
- 1 - wbl
, SCE_BAT_DEFAULT
);
326 // Search to end of word for second % (can be a long path)
327 while ((wbo
< wbl
) &&
328 (wordBuffer
[wbo
] != '%') &&
329 (!IsBOperator(wordBuffer
[wbo
])) &&
330 (!IsBSeparator(wordBuffer
[wbo
]))) {
333 // Check for Argument (%n) or (%*)
334 if (((Is0To9(wordBuffer
[1])) || (wordBuffer
[1] == '*')) &&
335 (wordBuffer
[wbo
] != '%')) {
336 // Check for External Command / Program
337 if (cmdLoc
== offset
- wbl
) {
338 cmdLoc
= offset
- (wbl
- 2);
341 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 2), SCE_BAT_IDENTIFIER
);
342 // Reset Offset to re-process remainder of word
344 // Check for Expanded Argument (%~...) / Variable (%%~...)
345 } else if (((wbl
> 1) && (wordBuffer
[1] == '~')) ||
346 ((wbl
> 2) && (wordBuffer
[1] == '%') && (wordBuffer
[2] == '~'))) {
347 // Check for External Command / Program
348 if (cmdLoc
== offset
- wbl
) {
349 cmdLoc
= offset
- (wbl
- wbo
);
351 // Colorize Expanded Argument / Variable
352 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_IDENTIFIER
);
353 // Reset Offset to re-process remainder of word
354 offset
-= (wbl
- wbo
);
355 // Check for Environment Variable (%x...%)
356 } else if ((wordBuffer
[1] != '%') &&
357 (wordBuffer
[wbo
] == '%')) {
359 // Check for External Command / Program
360 if (cmdLoc
== offset
- wbl
) {
361 cmdLoc
= offset
- (wbl
- wbo
);
363 // Colorize Environment Variable
364 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_IDENTIFIER
);
365 // Reset Offset to re-process remainder of word
366 offset
-= (wbl
- wbo
);
367 // Check for Local Variable (%%a)
370 (wordBuffer
[1] == '%') &&
371 (wordBuffer
[2] != '%') &&
372 (!IsBOperator(wordBuffer
[2])) &&
373 (!IsBSeparator(wordBuffer
[2]))) {
374 // Check for External Command / Program
375 if (cmdLoc
== offset
- wbl
) {
376 cmdLoc
= offset
- (wbl
- 3);
378 // Colorize Local Variable
379 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 3), SCE_BAT_IDENTIFIER
);
380 // Reset Offset to re-process remainder of word
383 // Check for Environment Variable (!x...!)
384 } else if (wordBuffer
[0] == '!') {
385 // Colorize Default Text
386 styler
.ColourTo(startLine
+ offset
- 1 - wbl
, SCE_BAT_DEFAULT
);
388 // Search to end of word for second ! (can be a long path)
389 while ((wbo
< wbl
) &&
390 (wordBuffer
[wbo
] != '!') &&
391 (!IsBOperator(wordBuffer
[wbo
])) &&
392 (!IsBSeparator(wordBuffer
[wbo
]))) {
395 if (wordBuffer
[wbo
] == '!') {
397 // Check for External Command / Program
398 if (cmdLoc
== offset
- wbl
) {
399 cmdLoc
= offset
- (wbl
- wbo
);
401 // Colorize Environment Variable
402 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_IDENTIFIER
);
403 // Reset Offset to re-process remainder of word
404 offset
-= (wbl
- wbo
);
406 // Check for Operator
407 } else if (IsBOperator(wordBuffer
[0])) {
408 // Colorize Default Text
409 styler
.ColourTo(startLine
+ offset
- 1 - wbl
, SCE_BAT_DEFAULT
);
410 // Check for Comparison Operator
411 if ((wordBuffer
[0] == '=') && (wordBuffer
[1] == '=')) {
412 // Identify External Command / Program Location for IF
415 while ((cmdLoc
< lengthLine
) &&
416 (isspacechar(lineBuffer
[cmdLoc
]))) {
419 // Colorize Comparison Operator
420 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 2), SCE_BAT_OPERATOR
);
421 // Reset Offset to re-process remainder of word
423 // Check for Pipe Operator
424 } else if (wordBuffer
[0] == '|') {
425 // Reset External Command / Program Location
426 cmdLoc
= offset
- wbl
+ 1;
428 while ((cmdLoc
< lengthLine
) &&
429 (isspacechar(lineBuffer
[cmdLoc
]))) {
432 // Colorize Pipe Operator
433 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 1), SCE_BAT_OPERATOR
);
434 // Reset Offset to re-process remainder of word
436 // Check for Other Operator
438 // Check for > Operator
439 if (wordBuffer
[0] == '>') {
440 // Turn Keyword and External Command / Program checking back on
441 continueProcessing
= true;
443 // Colorize Other Operator
444 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 1), SCE_BAT_OPERATOR
);
445 // Reset Offset to re-process remainder of word
448 // Check for Default Text
450 // Read up to %, Operator or Separator
451 while ((wbo
< wbl
) &&
452 (wordBuffer
[wbo
] != '%') &&
453 (wordBuffer
[wbo
] != '!') &&
454 (!IsBOperator(wordBuffer
[wbo
])) &&
455 (!IsBSeparator(wordBuffer
[wbo
]))) {
458 // Colorize Default Text
459 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_DEFAULT
);
460 // Reset Offset to re-process remainder of word
461 offset
-= (wbl
- wbo
);
463 // Skip next spaces - nothing happens if Offset was Reset
464 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
468 // Colorize Default Text for remainder of line - currently not lexed
469 styler
.ColourTo(endPos
, SCE_BAT_DEFAULT
);
472 static void ColouriseBatchDoc(
473 unsigned int startPos
,
476 WordList
*keywordlists
[],
479 char lineBuffer
[1024];
481 styler
.StartAt(startPos
);
482 styler
.StartSegment(startPos
);
483 unsigned int linePos
= 0;
484 unsigned int startLine
= startPos
;
485 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
486 lineBuffer
[linePos
++] = styler
[i
];
487 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
488 // End of line (or of line buffer) met, colourise it
489 lineBuffer
[linePos
] = '\0';
490 ColouriseBatchLine(lineBuffer
, linePos
, startLine
, i
, keywordlists
, styler
);
495 if (linePos
> 0) { // Last line does not have ending characters
496 lineBuffer
[linePos
] = '\0';
497 ColouriseBatchLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1,
498 keywordlists
, styler
);
502 #define DIFF_BUFFER_START_SIZE 16
503 // Note that ColouriseDiffLine analyzes only the first DIFF_BUFFER_START_SIZE
504 // characters of each line to classify the line.
506 static void ColouriseDiffLine(char *lineBuffer
, int endLine
, Accessor
&styler
) {
507 // It is needed to remember the current state to recognize starting
508 // comment lines before the first "diff " or "--- ". If a real
509 // difference starts then each line starting with ' ' is a whitespace
510 // otherwise it is considered a comment (Only in..., Binary file...)
511 if (0 == strncmp(lineBuffer
, "diff ", 5)) {
512 styler
.ColourTo(endLine
, SCE_DIFF_COMMAND
);
513 } else if (0 == strncmp(lineBuffer
, "Index: ", 7)) { // For subversion's diff
514 styler
.ColourTo(endLine
, SCE_DIFF_COMMAND
);
515 } else if (0 == strncmp(lineBuffer
, "---", 3) && lineBuffer
[3] != '-') {
516 // In a context diff, --- appears in both the header and the position markers
517 if (lineBuffer
[3] == ' ' && atoi(lineBuffer
+ 4) && !strchr(lineBuffer
, '/'))
518 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
519 else if (lineBuffer
[3] == '\r' || lineBuffer
[3] == '\n')
520 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
522 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
523 } else if (0 == strncmp(lineBuffer
, "+++ ", 4)) {
524 // I don't know of any diff where "+++ " is a position marker, but for
525 // consistency, do the same as with "--- " and "*** ".
526 if (atoi(lineBuffer
+4) && !strchr(lineBuffer
, '/'))
527 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
529 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
530 } else if (0 == strncmp(lineBuffer
, "====", 4)) { // For p4's diff
531 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
532 } else if (0 == strncmp(lineBuffer
, "***", 3)) {
533 // In a context diff, *** appears in both the header and the position markers.
534 // Also ******** is a chunk header, but here it's treated as part of the
535 // position marker since there is no separate style for a chunk header.
536 if (lineBuffer
[3] == ' ' && atoi(lineBuffer
+4) && !strchr(lineBuffer
, '/'))
537 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
538 else if (lineBuffer
[3] == '*')
539 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
541 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
542 } else if (0 == strncmp(lineBuffer
, "? ", 2)) { // For difflib
543 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
544 } else if (lineBuffer
[0] == '@') {
545 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
546 } else if (lineBuffer
[0] >= '0' && lineBuffer
[0] <= '9') {
547 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
548 } else if (lineBuffer
[0] == '-' || lineBuffer
[0] == '<') {
549 styler
.ColourTo(endLine
, SCE_DIFF_DELETED
);
550 } else if (lineBuffer
[0] == '+' || lineBuffer
[0] == '>') {
551 styler
.ColourTo(endLine
, SCE_DIFF_ADDED
);
552 } else if (lineBuffer
[0] == '!') {
553 styler
.ColourTo(endLine
, SCE_DIFF_CHANGED
);
554 } else if (lineBuffer
[0] != ' ') {
555 styler
.ColourTo(endLine
, SCE_DIFF_COMMENT
);
557 styler
.ColourTo(endLine
, SCE_DIFF_DEFAULT
);
561 static void ColouriseDiffDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
562 char lineBuffer
[DIFF_BUFFER_START_SIZE
] = "";
563 styler
.StartAt(startPos
);
564 styler
.StartSegment(startPos
);
565 unsigned int linePos
= 0;
566 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
567 if (AtEOL(styler
, i
)) {
568 if (linePos
< DIFF_BUFFER_START_SIZE
) {
569 lineBuffer
[linePos
] = 0;
571 ColouriseDiffLine(lineBuffer
, i
, styler
);
573 } else if (linePos
< DIFF_BUFFER_START_SIZE
- 1) {
574 lineBuffer
[linePos
++] = styler
[i
];
575 } else if (linePos
== DIFF_BUFFER_START_SIZE
- 1) {
576 lineBuffer
[linePos
++] = 0;
579 if (linePos
> 0) { // Last line does not have ending characters
580 if (linePos
< DIFF_BUFFER_START_SIZE
) {
581 lineBuffer
[linePos
] = 0;
583 ColouriseDiffLine(lineBuffer
, startPos
+ length
- 1, styler
);
587 static void FoldDiffDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
588 int curLine
= styler
.GetLine(startPos
);
589 int curLineStart
= styler
.LineStart(curLine
);
590 int prevLevel
= curLine
> 0 ? styler
.LevelAt(curLine
- 1) : SC_FOLDLEVELBASE
;
594 int lineType
= styler
.StyleAt(curLineStart
);
595 if (lineType
== SCE_DIFF_COMMAND
)
596 nextLevel
= SC_FOLDLEVELBASE
| SC_FOLDLEVELHEADERFLAG
;
597 else if (lineType
== SCE_DIFF_HEADER
)
598 nextLevel
= (SC_FOLDLEVELBASE
+ 1) | SC_FOLDLEVELHEADERFLAG
;
599 else if (lineType
== SCE_DIFF_POSITION
&& styler
[curLineStart
] != '-')
600 nextLevel
= (SC_FOLDLEVELBASE
+ 2) | SC_FOLDLEVELHEADERFLAG
;
601 else if (prevLevel
& SC_FOLDLEVELHEADERFLAG
)
602 nextLevel
= (prevLevel
& SC_FOLDLEVELNUMBERMASK
) + 1;
604 nextLevel
= prevLevel
;
606 if ((nextLevel
& SC_FOLDLEVELHEADERFLAG
) && (nextLevel
== prevLevel
))
607 styler
.SetLevel(curLine
-1, prevLevel
& ~SC_FOLDLEVELHEADERFLAG
);
609 styler
.SetLevel(curLine
, nextLevel
);
610 prevLevel
= nextLevel
;
612 curLineStart
= styler
.LineStart(++curLine
);
613 } while (static_cast<int>(startPos
) + length
> curLineStart
);
616 static inline bool isassignchar(unsigned char ch
) {
617 return (ch
== '=') || (ch
== ':');
620 static void ColourisePropsLine(
622 unsigned int lengthLine
,
623 unsigned int startLine
,
626 bool allowInitialSpaces
) {
629 if (allowInitialSpaces
) {
630 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) // Skip initial spaces
633 if (isspacechar(lineBuffer
[i
])) // don't allow initial spaces
637 if (i
< lengthLine
) {
638 if (lineBuffer
[i
] == '#' || lineBuffer
[i
] == '!' || lineBuffer
[i
] == ';') {
639 styler
.ColourTo(endPos
, SCE_PROPS_COMMENT
);
640 } else if (lineBuffer
[i
] == '[') {
641 styler
.ColourTo(endPos
, SCE_PROPS_SECTION
);
642 } else if (lineBuffer
[i
] == '@') {
643 styler
.ColourTo(startLine
+ i
, SCE_PROPS_DEFVAL
);
644 if (isassignchar(lineBuffer
[i
++]))
645 styler
.ColourTo(startLine
+ i
, SCE_PROPS_ASSIGNMENT
);
646 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
648 // Search for the '=' character
649 while ((i
< lengthLine
) && !isassignchar(lineBuffer
[i
]))
651 if ((i
< lengthLine
) && isassignchar(lineBuffer
[i
])) {
652 styler
.ColourTo(startLine
+ i
- 1, SCE_PROPS_KEY
);
653 styler
.ColourTo(startLine
+ i
, SCE_PROPS_ASSIGNMENT
);
654 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
656 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
660 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
664 static void ColourisePropsDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
665 char lineBuffer
[1024];
666 styler
.StartAt(startPos
);
667 styler
.StartSegment(startPos
);
668 unsigned int linePos
= 0;
669 unsigned int startLine
= startPos
;
671 // property lexer.props.allow.initial.spaces
672 // For properties files, set to 0 to style all lines that start with whitespace in the default style.
673 // This is not suitable for SciTE .properties files which use indentation for flow control but
674 // can be used for RFC2822 text where indentation is used for continuation lines.
675 bool allowInitialSpaces
= styler
.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0;
677 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
678 lineBuffer
[linePos
++] = styler
[i
];
679 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
680 // End of line (or of line buffer) met, colourise it
681 lineBuffer
[linePos
] = '\0';
682 ColourisePropsLine(lineBuffer
, linePos
, startLine
, i
, styler
, allowInitialSpaces
);
687 if (linePos
> 0) { // Last line does not have ending characters
688 ColourisePropsLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
, allowInitialSpaces
);
692 // adaption by ksc, using the "} else {" trick of 1.53
694 static void FoldPropsDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
695 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
697 unsigned int endPos
= startPos
+ length
;
698 int visibleChars
= 0;
699 int lineCurrent
= styler
.GetLine(startPos
);
701 char chNext
= styler
[startPos
];
702 int styleNext
= styler
.StyleAt(startPos
);
703 bool headerPoint
= false;
706 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
708 chNext
= styler
[i
+1];
710 int style
= styleNext
;
711 styleNext
= styler
.StyleAt(i
+ 1);
712 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
714 if (style
== SCE_PROPS_SECTION
) {
719 lev
= SC_FOLDLEVELBASE
;
721 if (lineCurrent
> 0) {
722 int levelPrevious
= styler
.LevelAt(lineCurrent
- 1);
724 if (levelPrevious
& SC_FOLDLEVELHEADERFLAG
) {
725 lev
= SC_FOLDLEVELBASE
+ 1;
727 lev
= levelPrevious
& SC_FOLDLEVELNUMBERMASK
;
732 lev
= SC_FOLDLEVELBASE
;
734 if (visibleChars
== 0 && foldCompact
)
735 lev
|= SC_FOLDLEVELWHITEFLAG
;
738 lev
|= SC_FOLDLEVELHEADERFLAG
;
740 if (lev
!= styler
.LevelAt(lineCurrent
)) {
741 styler
.SetLevel(lineCurrent
, lev
);
748 if (!isspacechar(ch
))
752 if (lineCurrent
> 0) {
753 int levelPrevious
= styler
.LevelAt(lineCurrent
- 1);
754 if (levelPrevious
& SC_FOLDLEVELHEADERFLAG
) {
755 lev
= SC_FOLDLEVELBASE
+ 1;
757 lev
= levelPrevious
& SC_FOLDLEVELNUMBERMASK
;
760 lev
= SC_FOLDLEVELBASE
;
762 int flagsNext
= styler
.LevelAt(lineCurrent
);
763 styler
.SetLevel(lineCurrent
, lev
| (flagsNext
& ~SC_FOLDLEVELNUMBERMASK
));
766 static void ColouriseMakeLine(
768 unsigned int lengthLine
,
769 unsigned int startLine
,
774 int lastNonSpace
= -1;
775 unsigned int state
= SCE_MAKE_DEFAULT
;
776 bool bSpecial
= false;
778 // check for a tab character in column 0 indicating a command
779 bool bCommand
= false;
780 if ((lengthLine
> 0) && (lineBuffer
[0] == '\t'))
783 // Skip initial spaces
784 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) {
787 if (i
< lengthLine
) {
788 if (lineBuffer
[i
] == '#') { // Comment
789 styler
.ColourTo(endPos
, SCE_MAKE_COMMENT
);
792 if (lineBuffer
[i
] == '!') { // Special directive
793 styler
.ColourTo(endPos
, SCE_MAKE_PREPROCESSOR
);
798 while (i
< lengthLine
) {
799 if (((i
+ 1) < lengthLine
) && (lineBuffer
[i
] == '$' && lineBuffer
[i
+ 1] == '(')) {
800 styler
.ColourTo(startLine
+ i
- 1, state
);
801 state
= SCE_MAKE_IDENTIFIER
;
803 } else if (state
== SCE_MAKE_IDENTIFIER
&& lineBuffer
[i
] == ')') {
804 if (--varCount
== 0) {
805 styler
.ColourTo(startLine
+ i
, state
);
806 state
= SCE_MAKE_DEFAULT
;
810 // skip identifier and target styling if this is a command line
811 if (!bSpecial
&& !bCommand
) {
812 if (lineBuffer
[i
] == ':') {
813 if (((i
+ 1) < lengthLine
) && (lineBuffer
[i
+ 1] == '=')) {
814 // it's a ':=', so style as an identifier
815 if (lastNonSpace
>= 0)
816 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
817 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
818 styler
.ColourTo(startLine
+ i
+ 1, SCE_MAKE_OPERATOR
);
820 // We should check that no colouring was made since the beginning of the line,
821 // to avoid colouring stuff like /OUT:file
822 if (lastNonSpace
>= 0)
823 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_TARGET
);
824 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
825 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
827 bSpecial
= true; // Only react to the first ':' of the line
828 state
= SCE_MAKE_DEFAULT
;
829 } else if (lineBuffer
[i
] == '=') {
830 if (lastNonSpace
>= 0)
831 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
832 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
833 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
834 bSpecial
= true; // Only react to the first '=' of the line
835 state
= SCE_MAKE_DEFAULT
;
838 if (!isspacechar(lineBuffer
[i
])) {
843 if (state
== SCE_MAKE_IDENTIFIER
) {
844 styler
.ColourTo(endPos
, SCE_MAKE_IDEOL
); // Error, variable reference not ended
846 styler
.ColourTo(endPos
, SCE_MAKE_DEFAULT
);
850 static void ColouriseMakeDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
851 char lineBuffer
[1024];
852 styler
.StartAt(startPos
);
853 styler
.StartSegment(startPos
);
854 unsigned int linePos
= 0;
855 unsigned int startLine
= startPos
;
856 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
857 lineBuffer
[linePos
++] = styler
[i
];
858 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
859 // End of line (or of line buffer) met, colourise it
860 lineBuffer
[linePos
] = '\0';
861 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, i
, styler
);
866 if (linePos
> 0) { // Last line does not have ending characters
867 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
871 static int RecogniseErrorListLine(const char *lineBuffer
, unsigned int lengthLine
, int &startValue
) {
872 if (lineBuffer
[0] == '>') {
873 // Command or return status
875 } else if (lineBuffer
[0] == '<') {
877 return SCE_ERR_DIFF_DELETION
;
878 } else if (lineBuffer
[0] == '!') {
879 return SCE_ERR_DIFF_CHANGED
;
880 } else if (lineBuffer
[0] == '+') {
881 if (strstart(lineBuffer
, "+++ ")) {
882 return SCE_ERR_DIFF_MESSAGE
;
884 return SCE_ERR_DIFF_ADDITION
;
886 } else if (lineBuffer
[0] == '-') {
887 if (strstart(lineBuffer
, "--- ")) {
888 return SCE_ERR_DIFF_MESSAGE
;
890 return SCE_ERR_DIFF_DELETION
;
892 } else if (strstart(lineBuffer
, "cf90-")) {
893 // Absoft Pro Fortran 90/95 v8.2 error and/or warning message
895 } else if (strstart(lineBuffer
, "fortcom:")) {
896 // Intel Fortran Compiler v8.0 error/warning message
897 return SCE_ERR_IFORT
;
898 } else if (strstr(lineBuffer
, "File \"") && strstr(lineBuffer
, ", line ")) {
899 return SCE_ERR_PYTHON
;
900 } else if (strstr(lineBuffer
, " in ") && strstr(lineBuffer
, " on line ")) {
902 } else if ((strstart(lineBuffer
, "Error ") ||
903 strstart(lineBuffer
, "Warning ")) &&
904 strstr(lineBuffer
, " at (") &&
905 strstr(lineBuffer
, ") : ") &&
906 (strstr(lineBuffer
, " at (") < strstr(lineBuffer
, ") : "))) {
907 // Intel Fortran Compiler error/warning message
909 } else if (strstart(lineBuffer
, "Error ")) {
910 // Borland error message
911 return SCE_ERR_BORLAND
;
912 } else if (strstart(lineBuffer
, "Warning ")) {
913 // Borland warning message
914 return SCE_ERR_BORLAND
;
915 } else if (strstr(lineBuffer
, "at line ") &&
916 (strstr(lineBuffer
, "at line ") < (lineBuffer
+ lengthLine
)) &&
917 strstr(lineBuffer
, "file ") &&
918 (strstr(lineBuffer
, "file ") < (lineBuffer
+ lengthLine
))) {
919 // Lua 4 error message
921 } else if (strstr(lineBuffer
, " at ") &&
922 (strstr(lineBuffer
, " at ") < (lineBuffer
+ lengthLine
)) &&
923 strstr(lineBuffer
, " line ") &&
924 (strstr(lineBuffer
, " line ") < (lineBuffer
+ lengthLine
)) &&
925 (strstr(lineBuffer
, " at ") + 4 < (strstr(lineBuffer
, " line ")))) {
926 // perl error message:
927 // <message> at <file> line <line>
929 } else if ((memcmp(lineBuffer
, " at ", 6) == 0) &&
930 strstr(lineBuffer
, ":line ")) {
933 } else if (strstart(lineBuffer
, "Line ") &&
934 strstr(lineBuffer
, ", file ")) {
935 // Essential Lahey Fortran error message
937 } else if (strstart(lineBuffer
, "line ") &&
938 strstr(lineBuffer
, " column ")) {
939 // HTML tidy style: line 42 column 1
941 } else if (strstart(lineBuffer
, "\tat ") &&
942 strstr(lineBuffer
, "(") &&
943 strstr(lineBuffer
, ".java:")) {
944 // Java stack back trace
945 return SCE_ERR_JAVA_STACK
;
946 } else if (strstart(lineBuffer
, "In file included from ") ||
947 strstart(lineBuffer
, " from ")) {
948 // GCC showing include path to following error
949 return SCE_ERR_GCC_INCLUDED_FROM
;
951 // Look for one of the following formats:
952 // GCC: <filename>:<line>:<message>
953 // Microsoft: <filename>(<line>) :<message>
954 // Common: <filename>(<line>): warning|error|note|remark|catastrophic|fatal
955 // Common: <filename>(<line>) warning|error|note|remark|catastrophic|fatal
956 // Microsoft: <filename>(<line>,<column>)<message>
957 // CTags: <identifier>\t<filename>\t<message>
958 // Lua 5 traceback: \t<filename>:<line>:<message>
959 // Lua 5.1: <exe>: <filename>:<line>:<message>
960 bool initialTab
= (lineBuffer
[0] == '\t');
961 bool initialColonPart
= false;
962 bool canBeCtags
= !initialTab
; // For ctags must have an identifier with no spaces then a tab
964 stGccStart
, stGccDigit
, stGccColumn
, stGcc
,
965 stMsStart
, stMsDigit
, stMsBracket
, stMsVc
, stMsDigitComma
, stMsDotNet
,
966 stCtagsStart
, stCtagsFile
, stCtagsStartString
, stCtagsStringDollar
, stCtags
,
969 for (unsigned int i
= 0; i
< lengthLine
; i
++) {
970 char ch
= lineBuffer
[i
];
972 if ((i
+ 1) < lengthLine
)
973 chNext
= lineBuffer
[i
+ 1];
974 if (state
== stInitial
) {
976 // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix)
977 if ((chNext
!= '\\') && (chNext
!= '/') && (chNext
!= ' ')) {
978 // This check is not completely accurate as may be on
979 // GTK+ with a file name that includes ':'.
981 } else if (chNext
== ' ') { // indicates a Lua 5.1 error message
982 initialColonPart
= true;
984 } else if ((ch
== '(') && Is1To9(chNext
) && (!initialTab
)) {
986 // Check against '0' often removes phone numbers
988 } else if ((ch
== '\t') && canBeCtags
) {
990 state
= stCtagsStart
;
991 } else if (ch
== ' ') {
994 } else if (state
== stGccStart
) { // <filename>:
995 state
= Is1To9(ch
) ? stGccDigit
: stUnrecognized
;
996 } else if (state
== stGccDigit
) { // <filename>:<line>
998 state
= stGccColumn
; // :9.*: is GCC
1000 } else if (!Is0To9(ch
)) {
1001 state
= stUnrecognized
;
1003 } else if (state
== stGccColumn
) { // <filename>:<line>:<column>
1010 } else if (state
== stMsStart
) { // <filename>(
1011 state
= Is0To9(ch
) ? stMsDigit
: stUnrecognized
;
1012 } else if (state
== stMsDigit
) { // <filename>(<line>
1014 state
= stMsDigitComma
;
1015 } else if (ch
== ')') {
1016 state
= stMsBracket
;
1017 } else if ((ch
!= ' ') && !Is0To9(ch
)) {
1018 state
= stUnrecognized
;
1020 } else if (state
== stMsBracket
) { // <filename>(<line>)
1021 if ((ch
== ' ') && (chNext
== ':')) {
1023 } else if ((ch
== ':' && chNext
== ' ') || (ch
== ' ')) {
1024 // Possibly Delphi.. don't test against chNext as it's one of the strings below.
1026 unsigned int j
, chPos
;
1030 numstep
= 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i.
1032 numstep
= 2; // otherwise add 2.
1033 for (j
= i
+ numstep
; j
< lengthLine
&& IsAlphabetic(lineBuffer
[j
]) && chPos
< sizeof(word
) - 1; j
++)
1034 word
[chPos
++] = lineBuffer
[j
];
1036 if (!CompareCaseInsensitive(word
, "error") || !CompareCaseInsensitive(word
, "warning") ||
1037 !CompareCaseInsensitive(word
, "fatal") || !CompareCaseInsensitive(word
, "catastrophic") ||
1038 !CompareCaseInsensitive(word
, "note") || !CompareCaseInsensitive(word
, "remark")) {
1041 state
= stUnrecognized
;
1044 state
= stUnrecognized
;
1046 } else if (state
== stMsDigitComma
) { // <filename>(<line>,
1050 } else if ((ch
!= ' ') && !Is0To9(ch
)) {
1051 state
= stUnrecognized
;
1053 } else if (state
== stCtagsStart
) {
1055 state
= stCtagsFile
;
1057 } else if (state
== stCtagsFile
) {
1058 if ((lineBuffer
[i
- 1] == '\t') &&
1059 ((ch
== '/' && chNext
== '^') || Is0To9(ch
))) {
1062 } else if ((ch
== '/') && (chNext
== '^')) {
1063 state
= stCtagsStartString
;
1065 } else if ((state
== stCtagsStartString
) && ((lineBuffer
[i
] == '$') && (lineBuffer
[i
+ 1] == '/'))) {
1066 state
= stCtagsStringDollar
;
1070 if (state
== stGcc
) {
1071 return initialColonPart
? SCE_ERR_LUA
: SCE_ERR_GCC
;
1072 } else if ((state
== stMsVc
) || (state
== stMsDotNet
)) {
1074 } else if ((state
== stCtagsStringDollar
) || (state
== stCtags
)) {
1075 return SCE_ERR_CTAG
;
1077 return SCE_ERR_DEFAULT
;
1082 static void ColouriseErrorListLine(
1084 unsigned int lengthLine
,
1085 unsigned int endPos
,
1087 bool valueSeparate
) {
1088 int startValue
= -1;
1089 int style
= RecogniseErrorListLine(lineBuffer
, lengthLine
, startValue
);
1090 if (valueSeparate
&& (startValue
>= 0)) {
1091 styler
.ColourTo(endPos
- (lengthLine
- startValue
), style
);
1092 styler
.ColourTo(endPos
, SCE_ERR_VALUE
);
1094 styler
.ColourTo(endPos
, style
);
1098 static void ColouriseErrorListDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
1099 char lineBuffer
[10000];
1100 styler
.StartAt(startPos
);
1101 styler
.StartSegment(startPos
);
1102 unsigned int linePos
= 0;
1104 // property lexer.errorlist.value.separate
1105 // For lines in the output pane that are matches from Find in Files or GCC-style
1106 // diagnostics, style the path and line number separately from the rest of the
1107 // line with style 21 used for the rest of the line.
1108 // This allows matched text to be more easily distinguished from its location.
1109 bool valueSeparate
= styler
.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0;
1110 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
1111 lineBuffer
[linePos
++] = styler
[i
];
1112 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
1113 // End of line (or of line buffer) met, colourise it
1114 lineBuffer
[linePos
] = '\0';
1115 ColouriseErrorListLine(lineBuffer
, linePos
, i
, styler
, valueSeparate
);
1119 if (linePos
> 0) { // Last line does not have ending characters
1120 ColouriseErrorListLine(lineBuffer
, linePos
, startPos
+ length
- 1, styler
, valueSeparate
);
1124 static const char *const batchWordListDesc
[] = {
1125 "Internal Commands",
1126 "External Commands",
1130 static const char *const emptyWordListDesc
[] = {
1134 static void ColouriseNullDoc(unsigned int startPos
, int length
, int, WordList
*[],
1136 // Null language means all style bytes are 0 so just mark the end - no need to fill in.
1138 styler
.StartAt(startPos
+ length
- 1);
1139 styler
.StartSegment(startPos
+ length
- 1);
1140 styler
.ColourTo(startPos
+ length
- 1, 0);
1144 LexerModule
lmBatch(SCLEX_BATCH
, ColouriseBatchDoc
, "batch", 0, batchWordListDesc
);
1145 LexerModule
lmDiff(SCLEX_DIFF
, ColouriseDiffDoc
, "diff", FoldDiffDoc
, emptyWordListDesc
);
1146 LexerModule
lmProps(SCLEX_PROPERTIES
, ColourisePropsDoc
, "props", FoldPropsDoc
, emptyWordListDesc
);
1147 LexerModule
lmMake(SCLEX_MAKEFILE
, ColouriseMakeDoc
, "makefile", 0, emptyWordListDesc
);
1148 LexerModule
lmErrorList(SCLEX_ERRORLIST
, ColouriseErrorListDoc
, "errorlist", 0, emptyWordListDesc
);
1149 LexerModule
lmNull(SCLEX_NULL
, ColouriseNullDoc
, "null");