~ubuntu-branches/ubuntu/utopic/codemirror-js/utopic

« back to all changes in this revision

Viewing changes to mode/rst/rst.js

  • Committer: Package Import Robot
  • Author(s): David Paleino
  • Date: 2012-04-12 12:25:28 UTC
  • Revision ID: package-import@ubuntu.com-20120412122528-8xp5a8frj4h1d3ee
Tags: upstream-2.23
ImportĀ upstreamĀ versionĀ 2.23

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
CodeMirror.defineMode('rst', function(config, options) {
 
2
    function setState(state, fn, ctx) {
 
3
        state.fn = fn;
 
4
        setCtx(state, ctx);
 
5
    }
 
6
 
 
7
    function setCtx(state, ctx) {
 
8
        state.ctx = ctx || {};
 
9
    }
 
10
 
 
11
    function setNormal(state, ch) {
 
12
        if (ch && (typeof ch !== 'string')) {
 
13
            var str = ch.current();
 
14
            ch = str[str.length-1];
 
15
        }
 
16
 
 
17
        setState(state, normal, {back: ch});
 
18
    }
 
19
 
 
20
    function hasMode(mode) {
 
21
        if (mode) {
 
22
            var modes = CodeMirror.listModes();
 
23
 
 
24
            for (var i in modes) {
 
25
                if (modes[i] == mode) {
 
26
                    return true;
 
27
                }
 
28
            }
 
29
        }
 
30
 
 
31
        return false;
 
32
    }
 
33
 
 
34
    function getMode(mode) {
 
35
        if (hasMode(mode)) {
 
36
            return CodeMirror.getMode(config, mode);
 
37
        } else {
 
38
            return null;
 
39
        }
 
40
    }
 
41
 
 
42
    var verbatimMode = getMode(options.verbatim);
 
43
    var pythonMode = getMode('python');
 
44
 
 
45
    var reSection = /^[!"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~]/;
 
46
    var reDirective = /^\s*\w([-:.\w]*\w)?::(\s|$)/;
 
47
    var reHyperlink = /^\s*_[\w-]+:(\s|$)/;
 
48
    var reFootnote = /^\s*\[(\d+|#)\](\s|$)/;
 
49
    var reCitation = /^\s*\[[A-Za-z][\w-]*\](\s|$)/;
 
50
    var reFootnoteRef = /^\[(\d+|#)\]_/;
 
51
    var reCitationRef = /^\[[A-Za-z][\w-]*\]_/;
 
52
    var reDirectiveMarker = /^\.\.(\s|$)/;
 
53
    var reVerbatimMarker = /^::\s*$/;
 
54
    var rePreInline = /^[-\s"([{</:]/;
 
55
    var rePostInline = /^[-\s`'")\]}>/:.,;!?\\_]/;
 
56
    var reEnumeratedList = /^\s*((\d+|[A-Za-z#])[.)]|\((\d+|[A-Z-a-z#])\))\s/;
 
57
    var reBulletedList = /^\s*[-\+\*]\s/;
 
58
    var reExamples = /^\s+(>>>|In \[\d+\]:)\s/;
 
59
 
 
60
    function normal(stream, state) {
 
61
        var ch, sol, i;
 
62
 
 
63
        if (stream.eat(/\\/)) {
 
64
            ch = stream.next();
 
65
            setNormal(state, ch);
 
66
            return null;
 
67
        }
 
68
 
 
69
        sol = stream.sol();
 
70
 
 
71
        if (sol && (ch = stream.eat(reSection))) {
 
72
            for (i = 0; stream.eat(ch); i++);
 
73
 
 
74
            if (i >= 3 && stream.match(/^\s*$/)) {
 
75
                setNormal(state, null);
 
76
                return 'header';
 
77
            } else {
 
78
                stream.backUp(i + 1);
 
79
            }
 
80
        }
 
81
 
 
82
        if (sol && stream.match(reDirectiveMarker)) {
 
83
            if (!stream.eol()) {
 
84
                setState(state, directive);
 
85
            }
 
86
            return 'meta';
 
87
        }
 
88
 
 
89
        if (stream.match(reVerbatimMarker)) {
 
90
            if (!verbatimMode) {
 
91
                setState(state, verbatim);
 
92
            } else {
 
93
                var mode = verbatimMode;
 
94
 
 
95
                setState(state, verbatim, {
 
96
                    mode: mode,
 
97
                    local: mode.startState()
 
98
                });
 
99
            }
 
100
            return 'meta';
 
101
        }
 
102
 
 
103
        if (sol && stream.match(reExamples, false)) {
 
104
            if (!pythonMode) {
 
105
                setState(state, verbatim);
 
106
                return 'meta';
 
107
            } else {
 
108
                var mode = pythonMode;
 
109
 
 
110
                setState(state, verbatim, {
 
111
                    mode: mode,
 
112
                    local: mode.startState()
 
113
                });
 
114
 
 
115
                return null;
 
116
            }
 
117
        }
 
118
 
 
119
        function testBackward(re) {
 
120
            return sol || !state.ctx.back || re.test(state.ctx.back);
 
121
        }
 
122
 
 
123
        function testForward(re) {
 
124
            return stream.eol() || stream.match(re, false);
 
125
        }
 
126
 
 
127
        function testInline(re) {
 
128
            return stream.match(re) && testBackward(/\W/) && testForward(/\W/);
 
129
        }
 
130
 
 
131
        if (testInline(reFootnoteRef)) {
 
132
            setNormal(state, stream);
 
133
            return 'footnote';
 
134
        }
 
135
 
 
136
        if (testInline(reCitationRef)) {
 
137
            setNormal(state, stream);
 
138
            return 'citation';
 
139
        }
 
140
 
 
141
        ch = stream.next();
 
142
 
 
143
        if (testBackward(rePreInline)) {
 
144
            if ((ch === ':' || ch === '|') && stream.eat(/\S/)) {
 
145
                var token;
 
146
 
 
147
                if (ch === ':') {
 
148
                    token = 'builtin';
 
149
                } else {
 
150
                    token = 'atom';
 
151
                }
 
152
 
 
153
                setState(state, inline, {
 
154
                    ch: ch,
 
155
                    wide: false,
 
156
                    prev: null,
 
157
                    token: token
 
158
                });
 
159
 
 
160
                return token;
 
161
            }
 
162
 
 
163
            if (ch === '*' || ch === '`') {
 
164
                var orig = ch,
 
165
                    wide = false;
 
166
 
 
167
                ch = stream.next();
 
168
 
 
169
                if (ch == orig) {
 
170
                    wide = true;
 
171
                    ch = stream.next();
 
172
                }
 
173
 
 
174
                if (ch && !/\s/.test(ch)) {
 
175
                    var token;
 
176
 
 
177
                    if (orig === '*') {
 
178
                        token = wide ? 'strong' : 'em';
 
179
                    } else {
 
180
                        token = wide ? 'string' : 'string-2';
 
181
                    }
 
182
 
 
183
                    setState(state, inline, {
 
184
                        ch: orig,               // inline() has to know what to search for
 
185
                        wide: wide,             // are we looking for `ch` or `chch`
 
186
                        prev: null,             // terminator must not be preceeded with whitespace
 
187
                        token: token            // I don't want to recompute this all the time
 
188
                    });
 
189
 
 
190
                    return token;
 
191
                }
 
192
            }
 
193
        }
 
194
 
 
195
        setNormal(state, ch);
 
196
        return null;
 
197
    }
 
198
 
 
199
    function inline(stream, state) {
 
200
        var ch = stream.next(),
 
201
            token = state.ctx.token;
 
202
 
 
203
        function finish(ch) {
 
204
            state.ctx.prev = ch;
 
205
            return token;
 
206
        }
 
207
 
 
208
        if (ch != state.ctx.ch) {
 
209
            return finish(ch);
 
210
        }
 
211
 
 
212
        if (/\s/.test(state.ctx.prev)) {
 
213
            return finish(ch);
 
214
        }
 
215
 
 
216
        if (state.ctx.wide) {
 
217
            ch = stream.next();
 
218
 
 
219
            if (ch != state.ctx.ch) {
 
220
                return finish(ch);
 
221
            }
 
222
        }
 
223
 
 
224
        if (!stream.eol() && !rePostInline.test(stream.peek())) {
 
225
            if (state.ctx.wide) {
 
226
                stream.backUp(1);
 
227
            }
 
228
 
 
229
            return finish(ch);
 
230
        }
 
231
 
 
232
        setState(state, normal);
 
233
        setNormal(state, ch);
 
234
 
 
235
        return token;
 
236
    }
 
237
 
 
238
    function directive(stream, state) {
 
239
        var token = null;
 
240
 
 
241
        if (stream.match(reDirective)) {
 
242
            token = 'attribute';
 
243
        } else if (stream.match(reHyperlink)) {
 
244
            token = 'link';
 
245
        } else if (stream.match(reFootnote)) {
 
246
            token = 'quote';
 
247
        } else if (stream.match(reCitation)) {
 
248
            token = 'quote';
 
249
        } else {
 
250
            stream.eatSpace();
 
251
 
 
252
            if (stream.eol()) {
 
253
                setNormal(state, stream);
 
254
                return null;
 
255
            } else {
 
256
                stream.skipToEnd();
 
257
                setState(state, comment);
 
258
                return 'comment';
 
259
            }
 
260
        }
 
261
 
 
262
        // FIXME this is unreachable
 
263
        setState(state, body, {start: true});
 
264
        return token;
 
265
    }
 
266
 
 
267
    function body(stream, state) {
 
268
        var token = 'body';
 
269
 
 
270
        if (!state.ctx.start || stream.sol()) {
 
271
            return block(stream, state, token);
 
272
        }
 
273
 
 
274
        stream.skipToEnd();
 
275
        setCtx(state);
 
276
 
 
277
        return token;
 
278
    }
 
279
 
 
280
    function comment(stream, state) {
 
281
        return block(stream, state, 'comment');
 
282
    }
 
283
 
 
284
    function verbatim(stream, state) {
 
285
        if (!verbatimMode) {
 
286
            return block(stream, state, 'meta');
 
287
        } else {
 
288
            if (stream.sol()) {
 
289
                if (!stream.eatSpace()) {
 
290
                    setNormal(state, stream);
 
291
                }
 
292
 
 
293
                return null;
 
294
            }
 
295
 
 
296
            return verbatimMode.token(stream, state.ctx.local);
 
297
        }
 
298
    }
 
299
 
 
300
    function block(stream, state, token) {
 
301
        if (stream.eol() || stream.eatSpace()) {
 
302
            stream.skipToEnd();
 
303
            return token;
 
304
        } else {
 
305
            setNormal(state, stream);
 
306
            return null;
 
307
        }
 
308
    }
 
309
 
 
310
    return {
 
311
        startState: function() {
 
312
            return {fn: normal, ctx: {}};
 
313
        },
 
314
 
 
315
        copyState: function(state) {
 
316
            return {fn: state.fn, ctx: state.ctx};
 
317
        },
 
318
 
 
319
        token: function(stream, state) {
 
320
            var token = state.fn(stream, state);
 
321
            return token;
 
322
        }
 
323
    };
 
324
});
 
325
 
 
326
CodeMirror.defineMIME("text/x-rst", "rst");