codemirror-rails 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -33,6 +33,10 @@
33
33
  return state.tokenize(stream, state);
34
34
  }
35
35
  return false;
36
+ },
37
+ "#": function(stream, state) {
38
+ stream.skipToEnd();
39
+ return "comment";
36
40
  }
37
41
  }
38
42
  };
@@ -0,0 +1,395 @@
1
+ CodeMirror.defineMode("rust", function() {
2
+ var indentUnit = 4, altIndentUnit = 2;
3
+ var valKeywords = {
4
+ "if": "if-style", "while": "if-style", "else": "else-style",
5
+ "do": "else-style", "ret": "else-style", "fail": "else-style",
6
+ "break": "atom", "cont": "atom", "const": "let", "resource": "fn",
7
+ "let": "let", "fn": "fn", "for": "for", "alt": "alt", "obj": "fn",
8
+ "lambda": "fn", "type": "type", "tag": "tag", "mod": "mod",
9
+ "as": "op", "true": "atom", "false": "atom", "assert": "op", "check": "op",
10
+ "claim": "op", "native": "ignore", "unsafe": "ignore", "import": "else-style",
11
+ "export": "else-style", "copy": "op", "log": "op", "log_err": "op"
12
+ };
13
+ var typeKeywords = function() {
14
+ var keywords = {"fn": "fn", "block": "fn", "obj": "obj"};
15
+ var atoms = "bool uint int i8 i16 i32 i64 u8 u16 u32 u64 float f32 f64 str char".split(" ");
16
+ for (var i = 0, e = atoms.length; i < e; ++i) keywords[atoms[i]] = "atom";
17
+ return keywords;
18
+ }();
19
+ var operatorChar = /[+\-*&%=<>!?|\.@]/;
20
+
21
+ // Tokenizer
22
+
23
+ // Used as scratch variable to communicate multiple values without
24
+ // consing up tons of objects.
25
+ var tcat, content;
26
+ function r(tc, style) {
27
+ tcat = tc;
28
+ return style;
29
+ }
30
+
31
+ function tokenBase(stream, state) {
32
+ var ch = stream.next();
33
+ if (ch == '"') {
34
+ state.tokenize = tokenString;
35
+ return state.tokenize(stream, state);
36
+ }
37
+ if (ch == "'") {
38
+ tcat = "atom";
39
+ if (stream.eat("\\")) {
40
+ if (stream.skipTo("'")) { stream.next(); return "string"; }
41
+ else { return "error"; }
42
+ } else {
43
+ stream.next();
44
+ return stream.eat("'") ? "string" : "error";
45
+ }
46
+ }
47
+ if (ch == "/") {
48
+ if (stream.eat("/")) { stream.skipToEnd(); return "comment"; }
49
+ if (stream.eat("*")) {
50
+ state.tokenize = tokenComment(1);
51
+ return state.tokenize(stream, state);
52
+ }
53
+ }
54
+ if (ch == "#") {
55
+ if (stream.eat("[")) { tcat = "open-attr"; return null; }
56
+ stream.eatWhile(/\w/);
57
+ return r("macro", "meta");
58
+ }
59
+ if (ch == ":" && stream.match(":<")) {
60
+ return r("op", null);
61
+ }
62
+ if (ch.match(/\d/) || (ch == "." && stream.eat(/\d/))) {
63
+ var flp = false;
64
+ if (!stream.match(/^x[\da-f]+/i) && !stream.match(/^b[01]+/)) {
65
+ stream.eatWhile(/\d/);
66
+ if (stream.eat(".")) { flp = true; stream.eatWhile(/\d/); }
67
+ if (stream.match(/^e[+\-]?\d+/i)) { flp = true; }
68
+ }
69
+ if (flp) stream.match(/^f(?:32|64)/);
70
+ else stream.match(/^[ui](?:8|16|32|64)/);
71
+ return r("atom", "number");
72
+ }
73
+ if (ch.match(/[()\[\]{}:;,]/)) return r(ch, null);
74
+ if (ch == "-" && stream.eat(">")) return r("->", null);
75
+ if (ch.match(operatorChar)) {
76
+ stream.eatWhile(operatorChar);
77
+ return r("op", null);
78
+ }
79
+ stream.eatWhile(/\w/);
80
+ content = stream.current();
81
+ if (stream.match(/^::\w/)) {
82
+ stream.backUp(1);
83
+ return r("prefix", "variable-2");
84
+ }
85
+ if (state.keywords.propertyIsEnumerable(content))
86
+ return r(state.keywords[content], "keyword");
87
+ return r("name", "variable");
88
+ }
89
+
90
+ function tokenString(stream, state) {
91
+ var ch, escaped = false;
92
+ while (ch = stream.next()) {
93
+ if (ch == '"' && !escaped) {
94
+ state.tokenize = tokenBase;
95
+ return r("atom", "string");
96
+ }
97
+ escaped = !escaped && ch == "\\";
98
+ }
99
+ // Hack to not confuse the parser when a string is split in
100
+ // pieces.
101
+ return r("op", "string");
102
+ }
103
+
104
+ function tokenComment(depth) {
105
+ return function(stream, state) {
106
+ var lastCh = null, ch;
107
+ while (ch = stream.next()) {
108
+ if (ch == "/" && lastCh == "*") {
109
+ if (depth == 1) {
110
+ state.tokenize = tokenBase;
111
+ break;
112
+ } else {
113
+ state.tokenize = tokenComment(depth - 1);
114
+ return state.tokenize(stream, state);
115
+ }
116
+ }
117
+ if (ch == "*" && lastCh == "/") {
118
+ state.tokenize = tokenComment(depth + 1);
119
+ return state.tokenize(stream, state);
120
+ }
121
+ lastCh = ch;
122
+ }
123
+ return "comment";
124
+ };
125
+ }
126
+
127
+ // Parser
128
+
129
+ var cx = {state: null, stream: null, marked: null, cc: null};
130
+ function pass() {
131
+ for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
132
+ }
133
+ function cont() {
134
+ pass.apply(null, arguments);
135
+ return true;
136
+ }
137
+
138
+ function pushlex(type, info) {
139
+ var result = function() {
140
+ var state = cx.state;
141
+ state.lexical = {indented: state.indented, column: cx.stream.column(),
142
+ type: type, prev: state.lexical, info: info};
143
+ };
144
+ result.lex = true;
145
+ return result;
146
+ }
147
+ function poplex() {
148
+ var state = cx.state;
149
+ if (state.lexical.prev) {
150
+ if (state.lexical.type == ")")
151
+ state.indented = state.lexical.indented;
152
+ state.lexical = state.lexical.prev;
153
+ }
154
+ }
155
+ function typecx() { cx.state.keywords = typeKeywords; }
156
+ function valcx() { cx.state.keywords = valKeywords; }
157
+ poplex.lex = typecx.lex = valcx.lex = true;
158
+
159
+ function commasep(comb, end) {
160
+ function more(type) {
161
+ if (type == ",") return cont(comb, more);
162
+ if (type == end) return cont();
163
+ return cont(more);
164
+ }
165
+ return function(type) {
166
+ if (type == end) return cont();
167
+ return pass(comb, more);
168
+ };
169
+ }
170
+
171
+ function block(type) {
172
+ if (type == "}") return cont();
173
+ if (type == "let") return cont(pushlex("stat", "let"), letdef, poplex, block);
174
+ if (type == "fn") return cont(pushlex("stat"), fndef, poplex, block);
175
+ if (type == "type") return cont(pushlex("stat"), tydef, endstatement, poplex, block);
176
+ if (type == "tag") return cont(pushlex("stat"), tagdef, poplex, block);
177
+ if (type == "mod") return cont(pushlex("stat"), mod, poplex, block);
178
+ if (type == "open-attr") return cont(pushlex("]"), commasep(expression, "]"), poplex);
179
+ if (type == "ignore") return cont(block);
180
+ return pass(pushlex("stat"), expression, poplex, endstatement, block);
181
+ }
182
+ function endstatement(type) {
183
+ if (type == ";") return cont();
184
+ return pass();
185
+ }
186
+ function expression(type) {
187
+ if (type == "atom" || type == "name") return cont(maybeop);
188
+ if (type == "{") return cont(pushlex("}"), exprbrace, poplex);
189
+ if (type.match(/[\[\(]/)) return matchBrackets(type, expression);
190
+ if (type.match(/[\]\)\};,]/)) return pass();
191
+ if (type == "if-style") return cont(expression, expression);
192
+ if (type == "else-style" || type == "op") return cont(expression);
193
+ if (type == "for") return cont(pattern, maybetype, inop, expression, expression);
194
+ if (type == "alt") return cont(expression, altbody);
195
+ if (type == "fn") return cont(fndef);
196
+ if (type == "macro") return cont(macro);
197
+ return cont();
198
+ }
199
+ function maybeop(type) {
200
+ if (content == ".") return cont(maybeprop);
201
+ if (content == "::<"){return cont(typarams, maybeop);}
202
+ if (type == "op" || content == ":") return cont(expression);
203
+ if (type == "(" || type == "[") return matchBrackets(type, expression);
204
+ return pass();
205
+ }
206
+ function maybeprop(type) {
207
+ if (content.match(/^\w+$/)) {cx.marked = "variable"; return cont(maybeop);}
208
+ return pass(expression);
209
+ }
210
+ function exprbrace(type) {
211
+ if (type == "op") {
212
+ if (content == "|") return cont(blockvars, poplex, pushlex("}", "block"), block);
213
+ if (content == "||") return cont(poplex, pushlex("}", "block"), block);
214
+ }
215
+ if (content == "mutable" || (content.match(/^\w+$/) && cx.stream.peek() == ":"
216
+ && !cx.stream.match("::", false))) return pass(recliteral);
217
+ return pass(block);
218
+ }
219
+ function recliteral(type) {
220
+ if (content == "mutable" || content == "with") {cx.marked = "keyword"; return cont(recliteral);}
221
+ if (content.match(/^\w*$/)) {cx.marked = "variable"; return cont(recliteral);}
222
+ if (type == ":") return cont(expression, recliteral);
223
+ if (type == "}") return cont();
224
+ return cont(recliteral);
225
+ }
226
+ function blockvars(type) {
227
+ if (type == "name") {cx.marked = "def"; return cont(blockvars);}
228
+ if (type == "op" && content == "|") return cont();
229
+ return cont(blockvars);
230
+ }
231
+
232
+ function letdef(type) {
233
+ if (type == ";") return cont();
234
+ if (content == "=") return cont(expression, letdef);
235
+ if (type == ",") return cont(letdef);
236
+ return pass(pattern, maybetype, letdef);
237
+ }
238
+ function maybetype(type) {
239
+ if (type == ":") return cont(typecx, rtype, valcx);
240
+ return pass();
241
+ }
242
+ function inop(type) {
243
+ if (type == "name" && content == "in") {cx.marked = "keyword"; return cont();}
244
+ return pass();
245
+ }
246
+ function fndef(type) {
247
+ if (type == "name") {cx.marked = "def"; return cont(fndef);}
248
+ if (content == "<") return cont(typarams, fndef);
249
+ if (type == "{") return pass(expression);
250
+ if (type == "(") return cont(pushlex(")"), commasep(argdef, ")"), poplex, fndef);
251
+ if (type == "->") return cont(typecx, rtype, valcx, fndef);
252
+ return cont(fndef);
253
+ }
254
+ function tydef(type) {
255
+ if (type == "name") {cx.marked = "def"; return cont(tydef);}
256
+ if (content == "<") return cont(typarams, tydef);
257
+ if (content == "=") return cont(typecx, rtype, valcx);
258
+ return cont(tydef);
259
+ }
260
+ function tagdef(type) {
261
+ if (type == "name") {cx.marked = "def"; return cont(tagdef);}
262
+ if (content == "<") return cont(typarams, tagdef);
263
+ if (content == "=") return cont(typecx, rtype, valcx, endstatement);
264
+ if (type == "{") return cont(pushlex("}"), typecx, tagblock, valcx, poplex);
265
+ return cont(tagdef);
266
+ }
267
+ function tagblock(type) {
268
+ if (type == "}") return cont();
269
+ if (type == "(") return cont(pushlex(")"), commasep(rtype, ")"), poplex, tagblock);
270
+ if (content.match(/^\w+$/)) cx.marked = "def";
271
+ return cont(tagblock);
272
+ }
273
+ function mod(type) {
274
+ if (type == "name") {cx.marked = "def"; return cont(mod);}
275
+ if (type == "{") return cont(pushlex("}"), block, poplex);
276
+ return pass();
277
+ }
278
+ function typarams(type) {
279
+ if (content == ">") return cont();
280
+ if (content == ",") return cont(typarams);
281
+ return pass(rtype, typarams);
282
+ }
283
+ function argdef(type) {
284
+ if (type == "name") {cx.marked = "def"; return cont(argdef);}
285
+ if (type == ":") return cont(typecx, rtype, valcx);
286
+ return pass();
287
+ }
288
+ function rtype(type) {
289
+ if (type == "name") {cx.marked = "variable-3"; return cont(rtypemaybeparam); }
290
+ if (content == "mutable") {cx.marked = "keyword"; return cont(rtype);}
291
+ if (type == "atom") return cont(rtypemaybeparam);
292
+ if (type == "op" || type == "obj") return cont(rtype);
293
+ if (type == "fn") return cont(fntype);
294
+ return matchBrackets(type, rtype);
295
+ }
296
+ function rtypemaybeparam(type) {
297
+ if (content == "<") return cont(typarams);
298
+ return pass();
299
+ }
300
+ function fntype(type) {
301
+ if (type == "(") return cont(pushlex("("), commasep(rtype, ")"), poplex, fntype);
302
+ if (type == "->") return cont(rtype);
303
+ return pass();
304
+ }
305
+ function pattern(type) {
306
+ if (type == "name") {cx.marked = "def"; return cont(patternmaybeop);}
307
+ if (type == "atom") return cont(patternmaybeop);
308
+ if (type == "op") return cont(pattern);
309
+ return matchBrackets(type, pattern);
310
+ }
311
+ function patternmaybeop(type) {
312
+ if (type == "op" && content == ".") return cont();
313
+ if (content == "to") {cx.marked = "keyword"; return cont(pattern);}
314
+ else return pass();
315
+ }
316
+ function altbody(type) {
317
+ if (type == "{") return cont(pushlex("}", "alt"), altblock, poplex);
318
+ return pass();
319
+ }
320
+ function altblock(type) {
321
+ if (type == "}") return cont();
322
+ if (type == "|") return cont(altblock);
323
+ if (content == "when") {cx.marked = "keyword"; return cont(expression, altblock);}
324
+ if (type == "{") return cont(pushlex("}", "alt"), block, poplex, altblock);
325
+ return pass(pattern, altblock);
326
+ }
327
+ function macro(type) {
328
+ if (type.match(/[\[\(\{]/)) return matchBrackets(type, expression);
329
+ return pass();
330
+ }
331
+ function matchBrackets(type, comb) {
332
+ if (type == "[") return cont(pushlex("]"), commasep(comb, "]"), poplex);
333
+ if (type == "(") return cont(pushlex(")"), commasep(comb, ")"), poplex);
334
+ if (type == "{") return cont(pushlex("}"), commasep(comb, "}"), poplex);
335
+ return cont();
336
+ }
337
+
338
+ function parse(state, stream, style) {
339
+ var cc = state.cc;
340
+ // Communicate our context to the combinators.
341
+ // (Less wasteful than consing up a hundred closures on every call.)
342
+ cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
343
+
344
+ while (true) {
345
+ var combinator = cc.length ? cc.pop() : block;
346
+ if (combinator(tcat)) {
347
+ while(cc.length && cc[cc.length - 1].lex)
348
+ cc.pop()();
349
+ return cx.marked || style;
350
+ }
351
+ }
352
+ }
353
+
354
+ return {
355
+ startState: function() {
356
+ return {
357
+ tokenize: tokenBase,
358
+ cc: [],
359
+ lexical: {indented: -indentUnit, column: 0, type: "top", align: false},
360
+ keywords: valKeywords,
361
+ indented: 0
362
+ };
363
+ },
364
+
365
+ token: function(stream, state) {
366
+ if (stream.sol()) {
367
+ if (!state.lexical.hasOwnProperty("align"))
368
+ state.lexical.align = false;
369
+ state.indented = stream.indentation();
370
+ }
371
+ if (stream.eatSpace()) return null;
372
+ tcat = content = null;
373
+ var style = state.tokenize(stream, state);
374
+ if (style == "comment") return style;
375
+ if (!state.lexical.hasOwnProperty("align"))
376
+ state.lexical.align = true;
377
+ if (tcat == "prefix") return style;
378
+ if (!content) content = stream.current();
379
+ return parse(state, stream, style);
380
+ },
381
+
382
+ indent: function(state, textAfter) {
383
+ if (state.tokenize != tokenBase) return 0;
384
+ var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
385
+ type = lexical.type, closing = firstChar == type;
386
+ if (type == "stat") return lexical.indented + indentUnit;
387
+ if (lexical.align) return lexical.column + (closing ? 0 : 1);
388
+ return lexical.indented + (closing ? 0 : (lexical.info == "alt" ? altIndentUnit : indentUnit));
389
+ },
390
+
391
+ electricChars: "{}"
392
+ };
393
+ });
394
+
395
+ CodeMirror.defineMIME("text/x-rustsrc", "rust");
@@ -0,0 +1,374 @@
1
+ /***
2
+ |''Name''|tiddlywiki.js|
3
+ |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror2|
4
+ |''Author''|PMario|
5
+ |''Version''|0.1.6|
6
+ |''Status''|''beta''|
7
+ |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|
8
+ |''Documentation''|http://codemirror.tiddlyspace.com/|
9
+ |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
10
+ |''CoreVersion''|2.5.0|
11
+ |''Requires''|codemirror.js|
12
+ |''Keywords''|syntax highlighting color code mirror codemirror|
13
+ ! Info
14
+ CoreVersion parameter is needed for TiddlyWiki only!
15
+ ***/
16
+ //{{{
17
+ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
18
+ var indentUnit = config.indentUnit;
19
+
20
+ // Tokenizer
21
+ var textwords = function () {
22
+ function kw(type) {
23
+ return {
24
+ type: type,
25
+ style: "text"
26
+ };
27
+ }
28
+ return {};
29
+ }();
30
+
31
+ var keywords = function () {
32
+ function kw(type) {
33
+ return { type: type, style: "macro"};
34
+ }
35
+ return {
36
+ "allTags": kw('allTags'), "closeAll": kw('closeAll'), "list": kw('list'),
37
+ "newJournal": kw('newJournal'), "newTiddler": kw('newTiddler'),
38
+ "permaview": kw('permaview'), "saveChanges": kw('saveChanges'),
39
+ "search": kw('search'), "slider": kw('slider'), "tabs": kw('tabs'),
40
+ "tag": kw('tag'), "tagging": kw('tagging'), "tags": kw('tags'),
41
+ "tiddler": kw('tiddler'), "timeline": kw('timeline'),
42
+ "today": kw('today'), "version": kw('version'), "option": kw('option'),
43
+
44
+ "with": kw('with'),
45
+ "filter": kw('filter')
46
+ };
47
+ }();
48
+
49
+ var isSpaceName = /[\w_\-]/i,
50
+ reHR = /^\-\-\-\-+$/,
51
+ reWikiCommentStart = /^\/\*\*\*$/, // /***
52
+ reWikiCommentStop = /^\*\*\*\/$/, // ***/
53
+ reBlockQuote = /^<<<$/,
54
+
55
+ reJsCodeStart = /^\/\/\{\{\{$/, // //{{{
56
+ reJsCodeStop = /^\/\/\}\}\}$/, // //}}}
57
+ reXmlCodeStart = /^<!--\{\{\{-->$/,
58
+ reXmlCodeStop = /^<!--\}\}\}-->$/,
59
+
60
+ reCodeBlockStart = /^\{\{\{$/,
61
+ reCodeBlockStop = /^\}\}\}$/,
62
+
63
+ reCodeStart = /\{\{\{/,
64
+ reUntilCodeStop = /.*?\}\}\}/;
65
+
66
+ function chain(stream, state, f) {
67
+ state.tokenize = f;
68
+ return f(stream, state);
69
+ }
70
+
71
+ // used for strings
72
+ function nextUntilUnescaped(stream, end) {
73
+ var escaped = false,
74
+ next;
75
+ while ((next = stream.next()) != null) {
76
+ if (next == end && !escaped) return false;
77
+ escaped = !escaped && next == "\\";
78
+ }
79
+ return escaped;
80
+ }
81
+
82
+ // Used as scratch variables to communicate multiple values without
83
+ // consing up tons of objects.
84
+ var type, content;
85
+
86
+ function ret(tp, style, cont) {
87
+ type = tp;
88
+ content = cont;
89
+ return style;
90
+ }
91
+
92
+ function jsTokenBase(stream, state) {
93
+ var sol = stream.sol(),
94
+ ch, tch;
95
+
96
+ state.block = false; // indicates the start of a code block.
97
+
98
+ ch = stream.peek(); // don't eat, to make match simpler
99
+
100
+ // check start of blocks
101
+ if (sol && /[<\/\*{}\-]/.test(ch)) {
102
+ if (stream.match(reCodeBlockStart)) {
103
+ state.block = true;
104
+ return chain(stream, state, twTokenCode);
105
+ }
106
+ if (stream.match(reBlockQuote)) {
107
+ return ret('quote', 'quote');
108
+ }
109
+ if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) {
110
+ return ret('code', 'code');
111
+ }
112
+ if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) {
113
+ return ret('code', 'code');
114
+ }
115
+ if (stream.match(reHR)) {
116
+ return ret('hr', 'hr');
117
+ }
118
+ } // sol
119
+ var ch = stream.next();
120
+
121
+ if (sol && /[\/\*!#;:>|]/.test(ch)) {
122
+ if (ch == "!") { // tw header
123
+ stream.skipToEnd();
124
+ return ret("header", "header");
125
+ }
126
+ if (ch == "*") { // tw list
127
+ stream.eatWhile('*');
128
+ return ret("list", "list");
129
+ }
130
+ if (ch == "#") { // tw numbered list
131
+ stream.eatWhile('#');
132
+ return ret("list", "list");
133
+ }
134
+ if (ch == ";") { // tw list
135
+ stream.eatWhile(';');
136
+ return ret("list", "list");
137
+ }
138
+ if (ch == ":") { // tw list
139
+ stream.eatWhile(':');
140
+ return ret("list", "list");
141
+ }
142
+ if (ch == ">") { // single line quote
143
+ stream.eatWhile(">");
144
+ return ret("quote", "quote");
145
+ }
146
+ if (ch == '|') {
147
+ return ret('table', 'table');
148
+ }
149
+ }
150
+
151
+ if (ch == '{' && stream.match(/\{\{/)) {
152
+ return chain(stream, state, twTokenCode);
153
+ }
154
+
155
+ // rudimentary html:// file:// link matching. TW knows much more ...
156
+ if (/[hf]/i.test(ch)) {
157
+ if (/[ti]/i.test(stream.peek()) && stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i)) {
158
+ return ret("link-external", "link-external");
159
+ }
160
+ }
161
+ // just a little string indicator, don't want to have the whole string covered
162
+ if (ch == '"') {
163
+ return ret('string', 'string');
164
+ }
165
+ if (/[\[\]]/.test(ch)) { // check for [[..]]
166
+ if (stream.peek() == ch) {
167
+ stream.next();
168
+ return ret('brace', 'brace');
169
+ }
170
+ }
171
+ if (ch == "@") { // check for space link. TODO fix @@...@@ highlighting
172
+ stream.eatWhile(isSpaceName);
173
+ return ret("link-external", "link-external");
174
+ }
175
+ if (/\d/.test(ch)) { // numbers
176
+ stream.eatWhile(/\d/);
177
+ return ret("number", "number");
178
+ }
179
+ if (ch == "/") { // tw invisible comment
180
+ if (stream.eat("%")) {
181
+ return chain(stream, state, twTokenComment);
182
+ }
183
+ else if (stream.eat("/")) { //
184
+ return chain(stream, state, twTokenEm);
185
+ }
186
+ }
187
+ if (ch == "_") { // tw underline
188
+ if (stream.eat("_")) {
189
+ return chain(stream, state, twTokenUnderline);
190
+ }
191
+ }
192
+ if (ch == "-") { // tw strikethrough TODO looks ugly .. different handling see below;
193
+ if (stream.eat("-")) {
194
+ return chain(stream, state, twTokenStrike);
195
+ }
196
+ }
197
+ if (ch == "'") { // tw bold
198
+ if (stream.eat("'")) {
199
+ return chain(stream, state, twTokenStrong);
200
+ }
201
+ }
202
+ if (ch == "<") { // tw macro
203
+ if (stream.eat("<")) {
204
+ return chain(stream, state, twTokenMacro);
205
+ }
206
+ }
207
+ else {
208
+ return ret(ch);
209
+ }
210
+
211
+ stream.eatWhile(/[\w\$_]/);
212
+ var word = stream.current(),
213
+ known = textwords.propertyIsEnumerable(word) && textwords[word];
214
+
215
+ return known ? ret(known.type, known.style, word) : ret("text", null, word);
216
+
217
+ } // jsTokenBase()
218
+
219
+ function twTokenString(quote) {
220
+ return function (stream, state) {
221
+ if (!nextUntilUnescaped(stream, quote)) state.tokenize = jsTokenBase;
222
+ return ret("string", "string");
223
+ };
224
+ }
225
+
226
+ // tw invisible comment
227
+ function twTokenComment(stream, state) {
228
+ var maybeEnd = false,
229
+ ch;
230
+ while (ch = stream.next()) {
231
+ if (ch == "/" && maybeEnd) {
232
+ state.tokenize = jsTokenBase;
233
+ break;
234
+ }
235
+ maybeEnd = (ch == "%");
236
+ }
237
+ return ret("comment", "comment");
238
+ }
239
+
240
+ // tw strong / bold
241
+ function twTokenStrong(stream, state) {
242
+ var maybeEnd = false,
243
+ ch;
244
+ while (ch = stream.next()) {
245
+ if (ch == "'" && maybeEnd) {
246
+ state.tokenize = jsTokenBase;
247
+ break;
248
+ }
249
+ maybeEnd = (ch == "'");
250
+ }
251
+ return ret("text", "strong");
252
+ }
253
+
254
+ // tw code
255
+ function twTokenCode(stream, state) {
256
+ var ch, sb = state.block;
257
+
258
+ if (sb && stream.current()) {
259
+ return ret("code", "code");
260
+ }
261
+
262
+ if (!sb && stream.match(reUntilCodeStop)) {
263
+ state.tokenize = jsTokenBase;
264
+ return ret("code", "code-inline");
265
+ }
266
+
267
+ if (sb && stream.sol() && stream.match(reCodeBlockStop)) {
268
+ state.tokenize = jsTokenBase;
269
+ return ret("code", "code");
270
+ }
271
+
272
+ ch = stream.next();
273
+ return (sb) ? ret("code", "code") : ret("code", "code-inline");
274
+ }
275
+
276
+ // tw em / italic
277
+ function twTokenEm(stream, state) {
278
+ var maybeEnd = false,
279
+ ch;
280
+ while (ch = stream.next()) {
281
+ if (ch == "/" && maybeEnd) {
282
+ state.tokenize = jsTokenBase;
283
+ break;
284
+ }
285
+ maybeEnd = (ch == "/");
286
+ }
287
+ return ret("text", "em");
288
+ }
289
+
290
+ // tw underlined text
291
+ function twTokenUnderline(stream, state) {
292
+ var maybeEnd = false,
293
+ ch;
294
+ while (ch = stream.next()) {
295
+ if (ch == "_" && maybeEnd) {
296
+ state.tokenize = jsTokenBase;
297
+ break;
298
+ }
299
+ maybeEnd = (ch == "_");
300
+ }
301
+ return ret("text", "underlined");
302
+ }
303
+
304
+ // tw strike through text looks ugly
305
+ // TODO just strike through the first and last 2 chars if possible.
306
+ function twTokenStrike(stream, state) {
307
+ var maybeEnd = false,
308
+ ch, nr;
309
+
310
+ while (ch = stream.next()) {
311
+ if (ch == "-" && maybeEnd) {
312
+ state.tokenize = jsTokenBase;
313
+ break;
314
+ }
315
+ maybeEnd = (ch == "-");
316
+ }
317
+ return ret("text", "line-through");
318
+ }
319
+
320
+ // macro
321
+ function twTokenMacro(stream, state) {
322
+ var ch, tmp, word, known;
323
+
324
+ if (stream.current() == '<<') {
325
+ return ret('brace', 'macro');
326
+ }
327
+
328
+ ch = stream.next();
329
+ if (!ch) {
330
+ state.tokenize = jsTokenBase;
331
+ return ret(ch);
332
+ }
333
+ if (ch == ">") {
334
+ if (stream.peek() == '>') {
335
+ stream.next();
336
+ state.tokenize = jsTokenBase;
337
+ return ret("brace", "macro");
338
+ }
339
+ }
340
+
341
+ stream.eatWhile(/[\w\$_]/);
342
+ word = stream.current();
343
+ known = keywords.propertyIsEnumerable(word) && keywords[word];
344
+
345
+ if (known) {
346
+ return ret(known.type, known.style, word);
347
+ }
348
+ else {
349
+ return ret("macro", null, word);
350
+ }
351
+ }
352
+
353
+ // Interface
354
+ return {
355
+ startState: function (basecolumn) {
356
+ return {
357
+ tokenize: jsTokenBase,
358
+ indented: 0,
359
+ level: 0
360
+ };
361
+ },
362
+
363
+ token: function (stream, state) {
364
+ if (stream.eatSpace()) return null;
365
+ var style = state.tokenize(stream, state);
366
+ return style;
367
+ },
368
+
369
+ electricChars: ""
370
+ };
371
+ });
372
+
373
+ CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki");
374
+ //}}}