aboutsummaryrefslogtreecommitdiff
path: root/imports/codemirror/mode/velocity/velocity.js
diff options
context:
space:
mode:
Diffstat (limited to 'imports/codemirror/mode/velocity/velocity.js')
-rwxr-xr-ximports/codemirror/mode/velocity/velocity.js146
1 files changed, 146 insertions, 0 deletions
diff --git a/imports/codemirror/mode/velocity/velocity.js b/imports/codemirror/mode/velocity/velocity.js
new file mode 100755
index 00000000..0b80c758
--- /dev/null
+++ b/imports/codemirror/mode/velocity/velocity.js
@@ -0,0 +1,146 @@
1CodeMirror.defineMode("velocity", function(config) {
2 function parseWords(str) {
3 var obj = {}, words = str.split(" ");
4 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
5 return obj;
6 }
7
8 var indentUnit = config.indentUnit
9 var keywords = parseWords("#end #else #break #stop #[[ #]] " +
10 "#{end} #{else} #{break} #{stop}");
11 var functions = parseWords("#if #elseif #foreach #set #include #parse #macro #define #evaluate " +
12 "#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}");
13 var specials = parseWords("$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent $velocityCount");
14 var isOperatorChar = /[+\-*&%=<>!?:\/|]/;
15 var multiLineStrings =true;
16
17 function chain(stream, state, f) {
18 state.tokenize = f;
19 return f(stream, state);
20 }
21 function tokenBase(stream, state) {
22 var beforeParams = state.beforeParams;
23 state.beforeParams = false;
24 var ch = stream.next();
25 // start of string?
26 if ((ch == '"' || ch == "'") && state.inParams)
27 return chain(stream, state, tokenString(ch));
28 // is it one of the special signs []{}().,;? Seperator?
29 else if (/[\[\]{}\(\),;\.]/.test(ch)) {
30 if (ch == "(" && beforeParams) state.inParams = true;
31 else if (ch == ")") state.inParams = false;
32 return null;
33 }
34 // start of a number value?
35 else if (/\d/.test(ch)) {
36 stream.eatWhile(/[\w\.]/);
37 return "number";
38 }
39 // multi line comment?
40 else if (ch == "#" && stream.eat("*")) {
41 return chain(stream, state, tokenComment);
42 }
43 // unparsed content?
44 else if (ch == "#" && stream.match(/ *\[ *\[/)) {
45 return chain(stream, state, tokenUnparsed);
46 }
47 // single line comment?
48 else if (ch == "#" && stream.eat("#")) {
49 stream.skipToEnd();
50 return "comment";
51 }
52 // variable?
53 else if (ch == "$") {
54 stream.eatWhile(/[\w\d\$_\.{}]/);
55 // is it one of the specials?
56 if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) {
57 return "keyword";
58 }
59 else {
60 state.beforeParams = true;
61 return "builtin";
62 }
63 }
64 // is it a operator?
65 else if (isOperatorChar.test(ch)) {
66 stream.eatWhile(isOperatorChar);
67 return "operator";
68 }
69 else {
70 // get the whole word
71 stream.eatWhile(/[\w\$_{}]/);
72 var word = stream.current().toLowerCase();
73 // is it one of the listed keywords?
74 if (keywords && keywords.propertyIsEnumerable(word))
75 return "keyword";
76 // is it one of the listed functions?
77 if (functions && functions.propertyIsEnumerable(word) ||
78 stream.current().match(/^#[a-z0-9_]+ *$/i) && stream.peek()=="(") {
79 state.beforeParams = true;
80 return "keyword";
81 }
82 // default: just a "word"
83 return null;
84 }
85 }
86
87 function tokenString(quote) {
88 return function(stream, state) {
89 var escaped = false, next, end = false;
90 while ((next = stream.next()) != null) {
91 if (next == quote && !escaped) {
92 end = true;
93 break;
94 }
95 escaped = !escaped && next == "\\";
96 }
97 if (end) state.tokenize = tokenBase;
98 return "string";
99 };
100 }
101
102 function tokenComment(stream, state) {
103 var maybeEnd = false, ch;
104 while (ch = stream.next()) {
105 if (ch == "#" && maybeEnd) {
106 state.tokenize = tokenBase;
107 break;
108 }
109 maybeEnd = (ch == "*");
110 }
111 return "comment";
112 }
113
114 function tokenUnparsed(stream, state) {
115 var maybeEnd = 0, ch;
116 while (ch = stream.next()) {
117 if (ch == "#" && maybeEnd == 2) {
118 state.tokenize = tokenBase;
119 break;
120 }
121 if (ch == "]")
122 maybeEnd++;
123 else if (ch != " ")
124 maybeEnd = 0;
125 }
126 return "meta";
127 }
128 // Interface
129
130 return {
131 startState: function(basecolumn) {
132 return {
133 tokenize: tokenBase,
134 beforeParams: false,
135 inParams: false
136 };
137 },
138
139 token: function(stream, state) {
140 if (stream.eatSpace()) return null;
141 return state.tokenize(stream, state);
142 }
143 };
144});
145
146CodeMirror.defineMIME("text/velocity", "velocity");