diff options
Diffstat (limited to 'imports/codemirror/mode/velocity/velocity.js')
-rwxr-xr-x | imports/codemirror/mode/velocity/velocity.js | 146 |
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 @@ | |||
1 | CodeMirror.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 | |||
146 | CodeMirror.defineMIME("text/velocity", "velocity"); | ||