1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | (function(mod) {
|
10 | if (typeof exports == "object" && typeof module == "object")
|
11 | mod(require("../../lib/codemirror"));
|
12 | else if (typeof define == "function" && define.amd)
|
13 | define(["../../lib/codemirror"], mod);
|
14 | else
|
15 | mod(CodeMirror);
|
16 | })(function(CodeMirror) {
|
17 | "use strict";
|
18 |
|
19 | CodeMirror.defineMode("stex", function(_config, parserConfig) {
|
20 | "use strict";
|
21 |
|
22 | function pushCommand(state, command) {
|
23 | state.cmdState.push(command);
|
24 | }
|
25 |
|
26 | function peekCommand(state) {
|
27 | if (state.cmdState.length > 0) {
|
28 | return state.cmdState[state.cmdState.length - 1];
|
29 | } else {
|
30 | return null;
|
31 | }
|
32 | }
|
33 |
|
34 | function popCommand(state) {
|
35 | var plug = state.cmdState.pop();
|
36 | if (plug) {
|
37 | plug.closeBracket();
|
38 | }
|
39 | }
|
40 |
|
41 |
|
42 | function getMostPowerful(state) {
|
43 | var context = state.cmdState;
|
44 | for (var i = context.length - 1; i >= 0; i--) {
|
45 | var plug = context[i];
|
46 | if (plug.name == "DEFAULT") {
|
47 | continue;
|
48 | }
|
49 | return plug;
|
50 | }
|
51 | return { styleIdentifier: function() { return null; } };
|
52 | }
|
53 |
|
54 | function addPluginPattern(pluginName, cmdStyle, styles) {
|
55 | return function () {
|
56 | this.name = pluginName;
|
57 | this.bracketNo = 0;
|
58 | this.style = cmdStyle;
|
59 | this.styles = styles;
|
60 | this.argument = null;
|
61 |
|
62 | this.styleIdentifier = function() {
|
63 | return this.styles[this.bracketNo - 1] || null;
|
64 | };
|
65 | this.openBracket = function() {
|
66 | this.bracketNo++;
|
67 | return "bracket";
|
68 | };
|
69 | this.closeBracket = function() {};
|
70 | };
|
71 | }
|
72 |
|
73 | var plugins = {};
|
74 |
|
75 | plugins["importmodule"] = addPluginPattern("importmodule", "tag", ["string", "builtin"]);
|
76 | plugins["documentclass"] = addPluginPattern("documentclass", "tag", ["", "atom"]);
|
77 | plugins["usepackage"] = addPluginPattern("usepackage", "tag", ["atom"]);
|
78 | plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]);
|
79 | plugins["end"] = addPluginPattern("end", "tag", ["atom"]);
|
80 |
|
81 | plugins["label" ] = addPluginPattern("label" , "tag", ["atom"]);
|
82 | plugins["ref" ] = addPluginPattern("ref" , "tag", ["atom"]);
|
83 | plugins["eqref" ] = addPluginPattern("eqref" , "tag", ["atom"]);
|
84 | plugins["cite" ] = addPluginPattern("cite" , "tag", ["atom"]);
|
85 | plugins["bibitem" ] = addPluginPattern("bibitem" , "tag", ["atom"]);
|
86 | plugins["Bibitem" ] = addPluginPattern("Bibitem" , "tag", ["atom"]);
|
87 | plugins["RBibitem" ] = addPluginPattern("RBibitem" , "tag", ["atom"]);
|
88 |
|
89 | plugins["DEFAULT"] = function () {
|
90 | this.name = "DEFAULT";
|
91 | this.style = "tag";
|
92 |
|
93 | this.styleIdentifier = this.openBracket = this.closeBracket = function() {};
|
94 | };
|
95 |
|
96 | function setState(state, f) {
|
97 | state.f = f;
|
98 | }
|
99 |
|
100 |
|
101 | function normal(source, state) {
|
102 | var plug;
|
103 |
|
104 | if (source.match(/^\\[a-zA-Z@]+/)) {
|
105 | var cmdName = source.current().slice(1);
|
106 | plug = plugins.hasOwnProperty(cmdName) ? plugins[cmdName] : plugins["DEFAULT"];
|
107 | plug = new plug();
|
108 | pushCommand(state, plug);
|
109 | setState(state, beginParams);
|
110 | return plug.style;
|
111 | }
|
112 |
|
113 |
|
114 | if (source.match(/^\\[$&%#{}_]/)) {
|
115 | return "tag";
|
116 | }
|
117 |
|
118 |
|
119 | if (source.match(/^\\[,;!\/\\]/)) {
|
120 | return "tag";
|
121 | }
|
122 |
|
123 |
|
124 | if (source.match("\\[")) {
|
125 | setState(state, function(source, state){ return inMathMode(source, state, "\\]"); });
|
126 | return "keyword";
|
127 | }
|
128 | if (source.match("\\(")) {
|
129 | setState(state, function(source, state){ return inMathMode(source, state, "\\)"); });
|
130 | return "keyword";
|
131 | }
|
132 | if (source.match("$$")) {
|
133 | setState(state, function(source, state){ return inMathMode(source, state, "$$"); });
|
134 | return "keyword";
|
135 | }
|
136 | if (source.match("$")) {
|
137 | setState(state, function(source, state){ return inMathMode(source, state, "$"); });
|
138 | return "keyword";
|
139 | }
|
140 |
|
141 | var ch = source.next();
|
142 | if (ch == "%") {
|
143 | source.skipToEnd();
|
144 | return "comment";
|
145 | } else if (ch == '}' || ch == ']') {
|
146 | plug = peekCommand(state);
|
147 | if (plug) {
|
148 | plug.closeBracket(ch);
|
149 | setState(state, beginParams);
|
150 | } else {
|
151 | return "error";
|
152 | }
|
153 | return "bracket";
|
154 | } else if (ch == '{' || ch == '[') {
|
155 | plug = plugins["DEFAULT"];
|
156 | plug = new plug();
|
157 | pushCommand(state, plug);
|
158 | return "bracket";
|
159 | } else if (/\d/.test(ch)) {
|
160 | source.eatWhile(/[\w.%]/);
|
161 | return "atom";
|
162 | } else {
|
163 | source.eatWhile(/[\w\-_]/);
|
164 | plug = getMostPowerful(state);
|
165 | if (plug.name == 'begin') {
|
166 | plug.argument = source.current();
|
167 | }
|
168 | return plug.styleIdentifier();
|
169 | }
|
170 | }
|
171 |
|
172 | function inMathMode(source, state, endModeSeq) {
|
173 | if (source.eatSpace()) {
|
174 | return null;
|
175 | }
|
176 | if (endModeSeq && source.match(endModeSeq)) {
|
177 | setState(state, normal);
|
178 | return "keyword";
|
179 | }
|
180 | if (source.match(/^\\[a-zA-Z@]+/)) {
|
181 | return "tag";
|
182 | }
|
183 | if (source.match(/^[a-zA-Z]+/)) {
|
184 | return "variable-2";
|
185 | }
|
186 |
|
187 | if (source.match(/^\\[$&%#{}_]/)) {
|
188 | return "tag";
|
189 | }
|
190 |
|
191 | if (source.match(/^\\[,;!\/]/)) {
|
192 | return "tag";
|
193 | }
|
194 |
|
195 | if (source.match(/^[\^_&]/)) {
|
196 | return "tag";
|
197 | }
|
198 |
|
199 | if (source.match(/^[+\-<>|=,\/@!*:;'"`~#?]/)) {
|
200 | return null;
|
201 | }
|
202 | if (source.match(/^(\d+\.\d*|\d*\.\d+|\d+)/)) {
|
203 | return "number";
|
204 | }
|
205 | var ch = source.next();
|
206 | if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") {
|
207 | return "bracket";
|
208 | }
|
209 |
|
210 | if (ch == "%") {
|
211 | source.skipToEnd();
|
212 | return "comment";
|
213 | }
|
214 | return "error";
|
215 | }
|
216 |
|
217 | function beginParams(source, state) {
|
218 | var ch = source.peek(), lastPlug;
|
219 | if (ch == '{' || ch == '[') {
|
220 | lastPlug = peekCommand(state);
|
221 | lastPlug.openBracket(ch);
|
222 | source.eat(ch);
|
223 | setState(state, normal);
|
224 | return "bracket";
|
225 | }
|
226 | if (/[ \t\r]/.test(ch)) {
|
227 | source.eat(ch);
|
228 | return null;
|
229 | }
|
230 | setState(state, normal);
|
231 | popCommand(state);
|
232 |
|
233 | return normal(source, state);
|
234 | }
|
235 |
|
236 | return {
|
237 | startState: function() {
|
238 | var f = parserConfig.inMathMode ? function(source, state){ return inMathMode(source, state); } : normal;
|
239 | return {
|
240 | cmdState: [],
|
241 | f: f
|
242 | };
|
243 | },
|
244 | copyState: function(s) {
|
245 | return {
|
246 | cmdState: s.cmdState.slice(),
|
247 | f: s.f
|
248 | };
|
249 | },
|
250 | token: function(stream, state) {
|
251 | return state.f(stream, state);
|
252 | },
|
253 | blankLine: function(state) {
|
254 | state.f = normal;
|
255 | state.cmdState.length = 0;
|
256 | },
|
257 | lineComment: "%"
|
258 | };
|
259 | });
|
260 |
|
261 | CodeMirror.defineMIME("text/x-stex", "stex");
|
262 | CodeMirror.defineMIME("text/x-latex", "stex");
|
263 |
|
264 | });
|