Commit | Line | Data |
---|---|---|
77b7b761 TD |
1 | /* Just enough of CodeMirror to run runMode under node.js */ |
2 | ||
837afb80 TD |
3 | // declare global: StringStream |
4 | ||
77b7b761 TD |
5 | function splitLines(string){ return string.split(/\r?\n|\r/); }; |
6 | ||
7 | function StringStream(string) { | |
8 | this.pos = this.start = 0; | |
9 | this.string = string; | |
837afb80 | 10 | this.lineStart = 0; |
77b7b761 TD |
11 | } |
12 | StringStream.prototype = { | |
13 | eol: function() {return this.pos >= this.string.length;}, | |
14 | sol: function() {return this.pos == 0;}, | |
15 | peek: function() {return this.string.charAt(this.pos) || null;}, | |
16 | next: function() { | |
17 | if (this.pos < this.string.length) | |
18 | return this.string.charAt(this.pos++); | |
19 | }, | |
20 | eat: function(match) { | |
21 | var ch = this.string.charAt(this.pos); | |
22 | if (typeof match == "string") var ok = ch == match; | |
23 | else var ok = ch && (match.test ? match.test(ch) : match(ch)); | |
24 | if (ok) {++this.pos; return ch;} | |
25 | }, | |
26 | eatWhile: function(match) { | |
27 | var start = this.pos; | |
28 | while (this.eat(match)){} | |
29 | return this.pos > start; | |
30 | }, | |
31 | eatSpace: function() { | |
32 | var start = this.pos; | |
33 | while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; | |
34 | return this.pos > start; | |
35 | }, | |
36 | skipToEnd: function() {this.pos = this.string.length;}, | |
37 | skipTo: function(ch) { | |
38 | var found = this.string.indexOf(ch, this.pos); | |
39 | if (found > -1) {this.pos = found; return true;} | |
40 | }, | |
41 | backUp: function(n) {this.pos -= n;}, | |
837afb80 | 42 | column: function() {return this.start - this.lineStart;}, |
77b7b761 TD |
43 | indentation: function() {return 0;}, |
44 | match: function(pattern, consume, caseInsensitive) { | |
45 | if (typeof pattern == "string") { | |
46 | var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; | |
837afb80 TD |
47 | var substr = this.string.substr(this.pos, pattern.length); |
48 | if (cased(substr) == cased(pattern)) { | |
77b7b761 TD |
49 | if (consume !== false) this.pos += pattern.length; |
50 | return true; | |
51 | } | |
52 | } else { | |
53 | var match = this.string.slice(this.pos).match(pattern); | |
837afb80 | 54 | if (match && match.index > 0) return null; |
77b7b761 TD |
55 | if (match && consume !== false) this.pos += match[0].length; |
56 | return match; | |
57 | } | |
58 | }, | |
837afb80 TD |
59 | current: function(){return this.string.slice(this.start, this.pos);}, |
60 | hideFirstChars: function(n, inner) { | |
61 | this.lineStart += n; | |
62 | try { return inner(); } | |
63 | finally { this.lineStart -= n; } | |
64 | } | |
77b7b761 TD |
65 | }; |
66 | exports.StringStream = StringStream; | |
67 | ||
68 | exports.startState = function(mode, a1, a2) { | |
69 | return mode.startState ? mode.startState(a1, a2) : true; | |
70 | }; | |
71 | ||
72 | var modes = exports.modes = {}, mimeModes = exports.mimeModes = {}; | |
73 | exports.defineMode = function(name, mode) { | |
74 | if (arguments.length > 2) { | |
75 | mode.dependencies = []; | |
76 | for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]); | |
77 | } | |
78 | modes[name] = mode; | |
79 | }; | |
80 | exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; }; | |
81 | ||
82 | exports.defineMode("null", function() { | |
83 | return {token: function(stream) {stream.skipToEnd();}}; | |
84 | }); | |
85 | exports.defineMIME("text/plain", "null"); | |
86 | ||
837afb80 TD |
87 | exports.resolveMode = function(spec) { |
88 | if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { | |
77b7b761 | 89 | spec = mimeModes[spec]; |
837afb80 TD |
90 | } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { |
91 | spec = mimeModes[spec.name]; | |
92 | } | |
93 | if (typeof spec == "string") return {name: spec}; | |
94 | else return spec || {name: "null"}; | |
95 | }; | |
96 | exports.getMode = function(options, spec) { | |
97 | spec = exports.resolveMode(spec); | |
98 | var mfactory = modes[spec.name]; | |
77b7b761 | 99 | if (!mfactory) throw new Error("Unknown mode: " + spec); |
837afb80 | 100 | return mfactory(options, spec); |
77b7b761 | 101 | }; |
837afb80 | 102 | exports.registerHelper = exports.registerGlobalHelper = Math.min; |
77b7b761 | 103 | |
837afb80 | 104 | exports.runMode = function(string, modespec, callback, options) { |
77b7b761 | 105 | var mode = exports.getMode({indentUnit: 2}, modespec); |
837afb80 | 106 | var lines = splitLines(string), state = (options && options.state) || exports.startState(mode); |
77b7b761 TD |
107 | for (var i = 0, e = lines.length; i < e; ++i) { |
108 | if (i) callback("\n"); | |
109 | var stream = new exports.StringStream(lines[i]); | |
110 | while (!stream.eol()) { | |
111 | var style = mode.token(stream, state); | |
837afb80 | 112 | callback(stream.current(), style, i, stream.start, state); |
77b7b761 TD |
113 | stream.start = stream.pos; |
114 | } | |
115 | } | |
116 | }; | |
837afb80 TD |
117 | |
118 | require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")]; |