Theme improvements (#1382)
[geany-mirror.git] / scintilla / lexers / LexMake.cxx
blob9e8dadf1bd8910c788e784dffd589af3f13017b8
1 // Scintilla source code edit control
2 /** @file LexMake.cxx
3 ** Lexer for make files.
4 **/
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.
8 #include <stdlib.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdarg.h>
12 #include <assert.h>
13 #include <ctype.h>
15 #include "ILexer.h"
16 #include "Scintilla.h"
17 #include "SciLexer.h"
19 #include "WordList.h"
20 #include "LexAccessor.h"
21 #include "Accessor.h"
22 #include "StyleContext.h"
23 #include "CharacterSet.h"
24 #include "LexerModule.h"
26 #ifdef SCI_NAMESPACE
27 using namespace Scintilla;
28 #endif
30 static inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
31 return (styler[i] == '\n') ||
32 ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
35 static void ColouriseMakeLine(
36 char *lineBuffer,
37 Sci_PositionU lengthLine,
38 Sci_PositionU startLine,
39 Sci_PositionU endPos,
40 Accessor &styler) {
42 Sci_PositionU i = 0;
43 Sci_Position lastNonSpace = -1;
44 unsigned int state = SCE_MAKE_DEFAULT;
45 bool bSpecial = false;
47 // check for a tab character in column 0 indicating a command
48 bool bCommand = false;
49 if ((lengthLine > 0) && (lineBuffer[0] == '\t'))
50 bCommand = true;
52 // Skip initial spaces
53 while ((i < lengthLine) && isspacechar(lineBuffer[i])) {
54 i++;
56 if (i < lengthLine) {
57 if (lineBuffer[i] == '#') { // Comment
58 styler.ColourTo(endPos, SCE_MAKE_COMMENT);
59 return;
61 if (lineBuffer[i] == '!') { // Special directive
62 styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR);
63 return;
66 int varCount = 0;
67 while (i < lengthLine) {
68 if (((i + 1) < lengthLine) && (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(')) {
69 styler.ColourTo(startLine + i - 1, state);
70 state = SCE_MAKE_IDENTIFIER;
71 varCount++;
72 } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') {
73 if (--varCount == 0) {
74 styler.ColourTo(startLine + i, state);
75 state = SCE_MAKE_DEFAULT;
79 // skip identifier and target styling if this is a command line
80 if (!bSpecial && !bCommand) {
81 if (lineBuffer[i] == ':') {
82 if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) {
83 // it's a ':=', so style as an identifier
84 if (lastNonSpace >= 0)
85 styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
86 styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
87 styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR);
88 } else {
89 // We should check that no colouring was made since the beginning of the line,
90 // to avoid colouring stuff like /OUT:file
91 if (lastNonSpace >= 0)
92 styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET);
93 styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
94 styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
96 bSpecial = true; // Only react to the first ':' of the line
97 state = SCE_MAKE_DEFAULT;
98 } else if (lineBuffer[i] == '=') {
99 if (lastNonSpace >= 0)
100 styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
101 styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
102 styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
103 bSpecial = true; // Only react to the first '=' of the line
104 state = SCE_MAKE_DEFAULT;
107 if (!isspacechar(lineBuffer[i])) {
108 lastNonSpace = i;
110 i++;
112 if (state == SCE_MAKE_IDENTIFIER) {
113 styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended
114 } else {
115 styler.ColourTo(endPos, SCE_MAKE_DEFAULT);
119 static void ColouriseMakeDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) {
120 char lineBuffer[1024];
121 styler.StartAt(startPos);
122 styler.StartSegment(startPos);
123 Sci_PositionU linePos = 0;
124 Sci_PositionU startLine = startPos;
125 for (Sci_PositionU i = startPos; i < startPos + length; i++) {
126 lineBuffer[linePos++] = styler[i];
127 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
128 // End of line (or of line buffer) met, colourise it
129 lineBuffer[linePos] = '\0';
130 ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler);
131 linePos = 0;
132 startLine = i + 1;
135 if (linePos > 0) { // Last line does not have ending characters
136 ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
140 static const char *const emptyWordListDesc[] = {
144 LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc);