Only replace template filename matching start of word on saving.
[geany-mirror.git] / scintilla / LexCrontab.cxx
blob62044c3709831510c23925cef552026bf9d60534
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/)
6 **/
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.
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <stdio.h>
14 #include <stdarg.h>
16 #include "Platform.h"
18 #include "PropSet.h"
19 #include "Accessor.h"
20 #include "KeyWords.h"
21 #include "Scintilla.h"
22 #include "SciLexer.h"
24 #ifdef SCI_NAMESPACE
25 using namespace Scintilla;
26 #endif
28 static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordList
29 *keywordLists[], Accessor &styler)
31 int state = SCE_NNCRONTAB_DEFAULT;
32 char chNext = styler[startPos];
33 int lengthDoc = startPos + length;
34 // create a buffer large enough to take the largest chunk...
35 char *buffer = new char[length];
36 int bufferCount = 0;
37 // used when highliting environment variables inside quoted string:
38 bool insideString = false;
40 // this assumes that we have 3 keyword list in conf.properties
41 WordList &section = *keywordLists[0];
42 WordList &keyword = *keywordLists[1];
43 WordList &modifier = *keywordLists[2];
45 // go through all provided text segment
46 // using the hand-written state machine shown below
47 styler.StartAt(startPos);
48 styler.StartSegment(startPos);
49 for (int i = startPos; i < lengthDoc; i++) {
50 char ch = chNext;
51 chNext = styler.SafeGetCharAt(i + 1);
53 if (styler.IsLeadByte(ch)) {
54 chNext = styler.SafeGetCharAt(i + 2);
55 i++;
56 continue;
58 switch(state) {
59 case SCE_NNCRONTAB_DEFAULT:
60 if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') {
61 // whitespace is simply ignored here...
62 styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT);
63 break;
64 } else if( ch == '#' && styler.SafeGetCharAt(i+1) == '(') {
65 // signals the start of a task...
66 state = SCE_NNCRONTAB_TASK;
67 styler.ColourTo(i,SCE_NNCRONTAB_TASK);
69 else if( ch == '\\' && (styler.SafeGetCharAt(i+1) == ' ' ||
70 styler.SafeGetCharAt(i+1) == '\t')) {
71 // signals the start of an extended comment...
72 state = SCE_NNCRONTAB_COMMENT;
73 styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
74 } else if( ch == '#' ) {
75 // signals the start of a plain comment...
76 state = SCE_NNCRONTAB_COMMENT;
77 styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
78 } else if( ch == ')' && styler.SafeGetCharAt(i+1) == '#') {
79 // signals the end of a task...
80 state = SCE_NNCRONTAB_TASK;
81 styler.ColourTo(i,SCE_NNCRONTAB_TASK);
82 } else if( ch == '"') {
83 state = SCE_NNCRONTAB_STRING;
84 styler.ColourTo(i,SCE_NNCRONTAB_STRING);
85 } else if( ch == '%') {
86 // signals environment variables
87 state = SCE_NNCRONTAB_ENVIRONMENT;
88 styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
89 } else if( ch == '<' && styler.SafeGetCharAt(i+1) == '%') {
90 // signals environment variables
91 state = SCE_NNCRONTAB_ENVIRONMENT;
92 styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
93 } else if( ch == '*' ) {
94 // signals an asterisk
95 // no state jump necessary for this simple case...
96 styler.ColourTo(i,SCE_NNCRONTAB_ASTERISK);
97 } else if( isalpha(ch) || ch == '<' ) {
98 // signals the start of an identifier
99 bufferCount = 0;
100 buffer[bufferCount++] = ch;
101 state = SCE_NNCRONTAB_IDENTIFIER;
102 } else if( isdigit(ch) ) {
103 // signals the start of a number
104 bufferCount = 0;
105 buffer[bufferCount++] = ch;
106 state = SCE_NNCRONTAB_NUMBER;
107 } else {
108 // style it the default style..
109 styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT);
111 break;
113 case SCE_NNCRONTAB_COMMENT:
114 // if we find a newline here,
115 // we simply go to default state
116 // else continue to work on it...
117 if( ch == '\n' || ch == '\r' ) {
118 state = SCE_NNCRONTAB_DEFAULT;
119 } else {
120 styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
122 break;
124 case SCE_NNCRONTAB_TASK:
125 // if we find a newline here,
126 // we simply go to default state
127 // else continue to work on it...
128 if( ch == '\n' || ch == '\r' ) {
129 state = SCE_NNCRONTAB_DEFAULT;
130 } else {
131 styler.ColourTo(i,SCE_NNCRONTAB_TASK);
133 break;
135 case SCE_NNCRONTAB_STRING:
136 if( ch == '%' ) {
137 state = SCE_NNCRONTAB_ENVIRONMENT;
138 insideString = true;
139 styler.ColourTo(i-1,SCE_NNCRONTAB_STRING);
140 break;
142 // if we find the end of a string char, we simply go to default state
143 // else we're still dealing with an string...
144 if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') ||
145 (ch == '\n') || (ch == '\r') ) {
146 state = SCE_NNCRONTAB_DEFAULT;
148 styler.ColourTo(i,SCE_NNCRONTAB_STRING);
149 break;
151 case SCE_NNCRONTAB_ENVIRONMENT:
152 // if we find the end of a string char, we simply go to default state
153 // else we're still dealing with an string...
154 if( ch == '%' && insideString ) {
155 state = SCE_NNCRONTAB_STRING;
156 insideString = false;
157 break;
159 if( (ch == '%' && styler.SafeGetCharAt(i-1)!='\\')
160 || (ch == '\n') || (ch == '\r') || (ch == '>') ) {
161 state = SCE_NNCRONTAB_DEFAULT;
162 styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
163 break;
165 styler.ColourTo(i+1,SCE_NNCRONTAB_ENVIRONMENT);
166 break;
168 case SCE_NNCRONTAB_IDENTIFIER:
169 // stay in CONF_IDENTIFIER state until we find a non-alphanumeric
170 if( isalnum(ch) || (ch == '_') || (ch == '-') || (ch == '/') ||
171 (ch == '$') || (ch == '.') || (ch == '<') || (ch == '>') ||
172 (ch == '@') ) {
173 buffer[bufferCount++] = ch;
174 } else {
175 state = SCE_NNCRONTAB_DEFAULT;
176 buffer[bufferCount] = '\0';
178 // check if the buffer contains a keyword,
179 // and highlight it if it is a keyword...
180 if(section.InList(buffer)) {
181 styler.ColourTo(i,SCE_NNCRONTAB_SECTION );
182 } else if(keyword.InList(buffer)) {
183 styler.ColourTo(i-1,SCE_NNCRONTAB_KEYWORD );
184 } // else if(strchr(buffer,'/') || strchr(buffer,'.')) {
185 // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION);
186 // }
187 else if(modifier.InList(buffer)) {
188 styler.ColourTo(i-1,SCE_NNCRONTAB_MODIFIER );
189 } else {
190 styler.ColourTo(i-1,SCE_NNCRONTAB_DEFAULT);
192 // push back the faulty character
193 chNext = styler[i--];
195 break;
197 case SCE_NNCRONTAB_NUMBER:
198 // stay in CONF_NUMBER state until we find a non-numeric
199 if( isdigit(ch) /* || ch == '.' */ ) {
200 buffer[bufferCount++] = ch;
201 } else {
202 state = SCE_NNCRONTAB_DEFAULT;
203 buffer[bufferCount] = '\0';
204 // Colourize here... (normal number)
205 styler.ColourTo(i-1,SCE_NNCRONTAB_NUMBER);
206 // push back a character
207 chNext = styler[i--];
209 break;
212 delete []buffer;
215 static const char * const cronWordListDesc[] = {
216 "Section keywords and Forth words",
217 "nnCrontab keywords",
218 "Modifiers",
222 LexerModule lmNncrontab(SCLEX_NNCRONTAB, ColouriseNncrontabDoc, "nncrontab", 0, cronWordListDesc);