1 // Scintilla source code edit control
2 /** @file LexCrontab.cxx
3 ** Lexer to use with extended crontab files used by a powerful
4 ** Windows scheduler/event monitor/automation manager nnCron.
5 ** (http://nemtsev.eserv.ru/)
7 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
8 // The License.txt file describes the conditions under which this software may be distributed.
18 #include "Scintilla.h"
22 #include "LexAccessor.h"
24 #include "StyleContext.h"
25 #include "CharacterSet.h"
26 #include "LexerModule.h"
29 using namespace Scintilla
;
32 static void ColouriseNncrontabDoc(unsigned int startPos
, int length
, int, WordList
33 *keywordLists
[], Accessor
&styler
)
35 int state
= SCE_NNCRONTAB_DEFAULT
;
36 char chNext
= styler
[startPos
];
37 int lengthDoc
= startPos
+ length
;
38 // create a buffer large enough to take the largest chunk...
39 char *buffer
= new char[length
];
41 // used when highliting environment variables inside quoted string:
42 bool insideString
= false;
44 // this assumes that we have 3 keyword list in conf.properties
45 WordList
§ion
= *keywordLists
[0];
46 WordList
&keyword
= *keywordLists
[1];
47 WordList
&modifier
= *keywordLists
[2];
49 // go through all provided text segment
50 // using the hand-written state machine shown below
51 styler
.StartAt(startPos
);
52 styler
.StartSegment(startPos
);
53 for (int i
= startPos
; i
< lengthDoc
; i
++) {
55 chNext
= styler
.SafeGetCharAt(i
+ 1);
57 if (styler
.IsLeadByte(ch
)) {
58 chNext
= styler
.SafeGetCharAt(i
+ 2);
63 case SCE_NNCRONTAB_DEFAULT
:
64 if( ch
== '\n' || ch
== '\r' || ch
== '\t' || ch
== ' ') {
65 // whitespace is simply ignored here...
66 styler
.ColourTo(i
,SCE_NNCRONTAB_DEFAULT
);
68 } else if( ch
== '#' && styler
.SafeGetCharAt(i
+1) == '(') {
69 // signals the start of a task...
70 state
= SCE_NNCRONTAB_TASK
;
71 styler
.ColourTo(i
,SCE_NNCRONTAB_TASK
);
73 else if( ch
== '\\' && (styler
.SafeGetCharAt(i
+1) == ' ' ||
74 styler
.SafeGetCharAt(i
+1) == '\t')) {
75 // signals the start of an extended comment...
76 state
= SCE_NNCRONTAB_COMMENT
;
77 styler
.ColourTo(i
,SCE_NNCRONTAB_COMMENT
);
78 } else if( ch
== '#' ) {
79 // signals the start of a plain comment...
80 state
= SCE_NNCRONTAB_COMMENT
;
81 styler
.ColourTo(i
,SCE_NNCRONTAB_COMMENT
);
82 } else if( ch
== ')' && styler
.SafeGetCharAt(i
+1) == '#') {
83 // signals the end of a task...
84 state
= SCE_NNCRONTAB_TASK
;
85 styler
.ColourTo(i
,SCE_NNCRONTAB_TASK
);
86 } else if( ch
== '"') {
87 state
= SCE_NNCRONTAB_STRING
;
88 styler
.ColourTo(i
,SCE_NNCRONTAB_STRING
);
89 } else if( ch
== '%') {
90 // signals environment variables
91 state
= SCE_NNCRONTAB_ENVIRONMENT
;
92 styler
.ColourTo(i
,SCE_NNCRONTAB_ENVIRONMENT
);
93 } else if( ch
== '<' && styler
.SafeGetCharAt(i
+1) == '%') {
94 // signals environment variables
95 state
= SCE_NNCRONTAB_ENVIRONMENT
;
96 styler
.ColourTo(i
,SCE_NNCRONTAB_ENVIRONMENT
);
97 } else if( ch
== '*' ) {
98 // signals an asterisk
99 // no state jump necessary for this simple case...
100 styler
.ColourTo(i
,SCE_NNCRONTAB_ASTERISK
);
101 } else if( (isascii(ch
) && isalpha(ch
)) || ch
== '<' ) {
102 // signals the start of an identifier
104 buffer
[bufferCount
++] = ch
;
105 state
= SCE_NNCRONTAB_IDENTIFIER
;
106 } else if( isascii(ch
) && isdigit(ch
) ) {
107 // signals the start of a number
109 buffer
[bufferCount
++] = ch
;
110 state
= SCE_NNCRONTAB_NUMBER
;
112 // style it the default style..
113 styler
.ColourTo(i
,SCE_NNCRONTAB_DEFAULT
);
117 case SCE_NNCRONTAB_COMMENT
:
118 // if we find a newline here,
119 // we simply go to default state
120 // else continue to work on it...
121 if( ch
== '\n' || ch
== '\r' ) {
122 state
= SCE_NNCRONTAB_DEFAULT
;
124 styler
.ColourTo(i
,SCE_NNCRONTAB_COMMENT
);
128 case SCE_NNCRONTAB_TASK
:
129 // if we find a newline here,
130 // we simply go to default state
131 // else continue to work on it...
132 if( ch
== '\n' || ch
== '\r' ) {
133 state
= SCE_NNCRONTAB_DEFAULT
;
135 styler
.ColourTo(i
,SCE_NNCRONTAB_TASK
);
139 case SCE_NNCRONTAB_STRING
:
141 state
= SCE_NNCRONTAB_ENVIRONMENT
;
143 styler
.ColourTo(i
-1,SCE_NNCRONTAB_STRING
);
146 // if we find the end of a string char, we simply go to default state
147 // else we're still dealing with an string...
148 if( (ch
== '"' && styler
.SafeGetCharAt(i
-1)!='\\') ||
149 (ch
== '\n') || (ch
== '\r') ) {
150 state
= SCE_NNCRONTAB_DEFAULT
;
152 styler
.ColourTo(i
,SCE_NNCRONTAB_STRING
);
155 case SCE_NNCRONTAB_ENVIRONMENT
:
156 // if we find the end of a string char, we simply go to default state
157 // else we're still dealing with an string...
158 if( ch
== '%' && insideString
) {
159 state
= SCE_NNCRONTAB_STRING
;
160 insideString
= false;
163 if( (ch
== '%' && styler
.SafeGetCharAt(i
-1)!='\\')
164 || (ch
== '\n') || (ch
== '\r') || (ch
== '>') ) {
165 state
= SCE_NNCRONTAB_DEFAULT
;
166 styler
.ColourTo(i
,SCE_NNCRONTAB_ENVIRONMENT
);
169 styler
.ColourTo(i
+1,SCE_NNCRONTAB_ENVIRONMENT
);
172 case SCE_NNCRONTAB_IDENTIFIER
:
173 // stay in CONF_IDENTIFIER state until we find a non-alphanumeric
174 if( (isascii(ch
) && isalnum(ch
)) || (ch
== '_') || (ch
== '-') || (ch
== '/') ||
175 (ch
== '$') || (ch
== '.') || (ch
== '<') || (ch
== '>') ||
177 buffer
[bufferCount
++] = ch
;
179 state
= SCE_NNCRONTAB_DEFAULT
;
180 buffer
[bufferCount
] = '\0';
182 // check if the buffer contains a keyword,
183 // and highlight it if it is a keyword...
184 if(section
.InList(buffer
)) {
185 styler
.ColourTo(i
,SCE_NNCRONTAB_SECTION
);
186 } else if(keyword
.InList(buffer
)) {
187 styler
.ColourTo(i
-1,SCE_NNCRONTAB_KEYWORD
);
188 } // else if(strchr(buffer,'/') || strchr(buffer,'.')) {
189 // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION);
191 else if(modifier
.InList(buffer
)) {
192 styler
.ColourTo(i
-1,SCE_NNCRONTAB_MODIFIER
);
194 styler
.ColourTo(i
-1,SCE_NNCRONTAB_DEFAULT
);
196 // push back the faulty character
197 chNext
= styler
[i
--];
201 case SCE_NNCRONTAB_NUMBER
:
202 // stay in CONF_NUMBER state until we find a non-numeric
203 if( isascii(ch
) && isdigit(ch
) /* || ch == '.' */ ) {
204 buffer
[bufferCount
++] = ch
;
206 state
= SCE_NNCRONTAB_DEFAULT
;
207 buffer
[bufferCount
] = '\0';
208 // Colourize here... (normal number)
209 styler
.ColourTo(i
-1,SCE_NNCRONTAB_NUMBER
);
210 // push back a character
211 chNext
= styler
[i
--];
219 static const char * const cronWordListDesc
[] = {
220 "Section keywords and Forth words",
221 "nnCrontab keywords",
226 LexerModule
lmNncrontab(SCLEX_NNCRONTAB
, ColouriseNncrontabDoc
, "nncrontab", 0, cronWordListDesc
);