##// END OF EJS Templates
codemirror: added simple mode plugin required for certain code modes.
marcink -
r2127:d6d01315 default
parent child Browse files
Show More
@@ -0,0 +1,216 b''
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: http://codemirror.net/LICENSE
3
4 (function(mod) {
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"));
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror"], mod);
9 else // Plain browser env
10 mod(CodeMirror);
11 })(function(CodeMirror) {
12 "use strict";
13
14 CodeMirror.defineSimpleMode = function(name, states) {
15 CodeMirror.defineMode(name, function(config) {
16 return CodeMirror.simpleMode(config, states);
17 });
18 };
19
20 CodeMirror.simpleMode = function(config, states) {
21 ensureState(states, "start");
22 var states_ = {}, meta = states.meta || {}, hasIndentation = false;
23 for (var state in states) if (state != meta && states.hasOwnProperty(state)) {
24 var list = states_[state] = [], orig = states[state];
25 for (var i = 0; i < orig.length; i++) {
26 var data = orig[i];
27 list.push(new Rule(data, states));
28 if (data.indent || data.dedent) hasIndentation = true;
29 }
30 }
31 var mode = {
32 startState: function() {
33 return {state: "start", pending: null,
34 local: null, localState: null,
35 indent: hasIndentation ? [] : null};
36 },
37 copyState: function(state) {
38 var s = {state: state.state, pending: state.pending,
39 local: state.local, localState: null,
40 indent: state.indent && state.indent.slice(0)};
41 if (state.localState)
42 s.localState = CodeMirror.copyState(state.local.mode, state.localState);
43 if (state.stack)
44 s.stack = state.stack.slice(0);
45 for (var pers = state.persistentStates; pers; pers = pers.next)
46 s.persistentStates = {mode: pers.mode,
47 spec: pers.spec,
48 state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state),
49 next: s.persistentStates};
50 return s;
51 },
52 token: tokenFunction(states_, config),
53 innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; },
54 indent: indentFunction(states_, meta)
55 };
56 if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop))
57 mode[prop] = meta[prop];
58 return mode;
59 };
60
61 function ensureState(states, name) {
62 if (!states.hasOwnProperty(name))
63 throw new Error("Undefined state " + name + " in simple mode");
64 }
65
66 function toRegex(val, caret) {
67 if (!val) return /(?:)/;
68 var flags = "";
69 if (val instanceof RegExp) {
70 if (val.ignoreCase) flags = "i";
71 val = val.source;
72 } else {
73 val = String(val);
74 }
75 return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags);
76 }
77
78 function asToken(val) {
79 if (!val) return null;
80 if (val.apply) return val
81 if (typeof val == "string") return val.replace(/\./g, " ");
82 var result = [];
83 for (var i = 0; i < val.length; i++)
84 result.push(val[i] && val[i].replace(/\./g, " "));
85 return result;
86 }
87
88 function Rule(data, states) {
89 if (data.next || data.push) ensureState(states, data.next || data.push);
90 this.regex = toRegex(data.regex);
91 this.token = asToken(data.token);
92 this.data = data;
93 }
94
95 function tokenFunction(states, config) {
96 return function(stream, state) {
97 if (state.pending) {
98 var pend = state.pending.shift();
99 if (state.pending.length == 0) state.pending = null;
100 stream.pos += pend.text.length;
101 return pend.token;
102 }
103
104 if (state.local) {
105 if (state.local.end && stream.match(state.local.end)) {
106 var tok = state.local.endToken || null;
107 state.local = state.localState = null;
108 return tok;
109 } else {
110 var tok = state.local.mode.token(stream, state.localState), m;
111 if (state.local.endScan && (m = state.local.endScan.exec(stream.current())))
112 stream.pos = stream.start + m.index;
113 return tok;
114 }
115 }
116
117 var curState = states[state.state];
118 for (var i = 0; i < curState.length; i++) {
119 var rule = curState[i];
120 var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex);
121 if (matches) {
122 if (rule.data.next) {
123 state.state = rule.data.next;
124 } else if (rule.data.push) {
125 (state.stack || (state.stack = [])).push(state.state);
126 state.state = rule.data.push;
127 } else if (rule.data.pop && state.stack && state.stack.length) {
128 state.state = state.stack.pop();
129 }
130
131 if (rule.data.mode)
132 enterLocalMode(config, state, rule.data.mode, rule.token);
133 if (rule.data.indent)
134 state.indent.push(stream.indentation() + config.indentUnit);
135 if (rule.data.dedent)
136 state.indent.pop();
137 var token = rule.token
138 if (token && token.apply) token = token(matches)
139 if (matches.length > 2 && rule.token && typeof rule.token != "string") {
140 state.pending = [];
141 for (var j = 2; j < matches.length; j++)
142 if (matches[j])
143 state.pending.push({text: matches[j], token: rule.token[j - 1]});
144 stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
145 return token[0];
146 } else if (token && token.join) {
147 return token[0];
148 } else {
149 return token;
150 }
151 }
152 }
153 stream.next();
154 return null;
155 };
156 }
157
158 function cmp(a, b) {
159 if (a === b) return true;
160 if (!a || typeof a != "object" || !b || typeof b != "object") return false;
161 var props = 0;
162 for (var prop in a) if (a.hasOwnProperty(prop)) {
163 if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false;
164 props++;
165 }
166 for (var prop in b) if (b.hasOwnProperty(prop)) props--;
167 return props == 0;
168 }
169
170 function enterLocalMode(config, state, spec, token) {
171 var pers;
172 if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next)
173 if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p;
174 var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec);
175 var lState = pers ? pers.state : CodeMirror.startState(mode);
176 if (spec.persistent && !pers)
177 state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates};
178
179 state.localState = lState;
180 state.local = {mode: mode,
181 end: spec.end && toRegex(spec.end),
182 endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false),
183 endToken: token && token.join ? token[token.length - 1] : token};
184 }
185
186 function indexOf(val, arr) {
187 for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true;
188 }
189
190 function indentFunction(states, meta) {
191 return function(state, textAfter, line) {
192 if (state.local && state.local.mode.indent)
193 return state.local.mode.indent(state.localState, textAfter, line);
194 if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1)
195 return CodeMirror.Pass;
196
197 var pos = state.indent.length - 1, rules = states[state.state];
198 scan: for (;;) {
199 for (var i = 0; i < rules.length; i++) {
200 var rule = rules[i];
201 if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {
202 var m = rule.regex.exec(textAfter);
203 if (m && m[0]) {
204 pos--;
205 if (rule.next || rule.push) rules = states[rule.next || rule.push];
206 textAfter = textAfter.slice(m[0].length);
207 continue scan;
208 }
209 }
210 }
211 break;
212 }
213 return pos < 0 ? 0 : state.indent[pos];
214 };
215 }
216 }); No newline at end of file
@@ -57,6 +57,7 b''
57 57 "<%= dirs.js.src %>/codemirror/codemirror_hint.js",
58 58 "<%= dirs.js.src %>/codemirror/codemirror_overlay.js",
59 59 "<%= dirs.js.src %>/codemirror/codemirror_placeholder.js",
60 "<%= dirs.js.src %>/codemirror/codemirror_simplemode.js",
60 61 "<%= dirs.js.dest %>/mode/meta.js",
61 62 "<%= dirs.js.dest %>/mode/meta_ext.js",
62 63 "<%= dirs.js.src_rc %>/i18n/select2/translations.js",
General Comments 0
You need to be logged in to leave comments. Login now