codemirror-rails 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -49,17 +49,20 @@
49
49
  state.curMode = phpMode;
50
50
  state.curState = state.php;
51
51
  state.curClose = /^\?>/;
52
+ state.mode = 'php';
52
53
  }
53
54
  else if (style == "tag" && stream.current() == ">" && state.curState.context) {
54
55
  if (/^script$/i.test(state.curState.context.tagName)) {
55
56
  state.curMode = jsMode;
56
57
  state.curState = jsMode.startState(htmlMode.indent(state.curState, ""));
57
58
  state.curClose = /^<\/\s*script\s*>/i;
59
+ state.mode = 'javascript';
58
60
  }
59
61
  else if (/^style$/i.test(state.curState.context.tagName)) {
60
62
  state.curMode = cssMode;
61
63
  state.curState = cssMode.startState(htmlMode.indent(state.curState, ""));
62
64
  state.curClose = /^<\/\s*style\s*>/i;
65
+ state.mode = 'css';
63
66
  }
64
67
  }
65
68
  return style;
@@ -68,6 +71,7 @@
68
71
  state.curMode = htmlMode;
69
72
  state.curState = state.html;
70
73
  state.curClose = null;
74
+ state.mode = 'html';
71
75
  return dispatch(stream, state);
72
76
  }
73
77
  else return state.curMode.token(stream, state.curState);
@@ -80,7 +84,8 @@
80
84
  php: phpMode.startState(),
81
85
  curMode: parserConfig.startOpen ? phpMode : htmlMode,
82
86
  curState: parserConfig.startOpen ? phpMode.startState() : html,
83
- curClose: parserConfig.startOpen ? /^\?>/ : null}
87
+ curClose: parserConfig.startOpen ? /^\?>/ : null,
88
+ mode: parserConfig.startOpen ? 'php' : 'html'}
84
89
  },
85
90
 
86
91
  copyState: function(state) {
@@ -171,7 +171,7 @@ CodeMirror.defineMode("python", function(conf) {
171
171
  }
172
172
  if (singleline) {
173
173
  if (conf.mode.singleLineStringErrors) {
174
- OUTCLASS = ERRORCLASS
174
+ return ERRORCLASS;
175
175
  } else {
176
176
  state.tokenize = tokenBase;
177
177
  }
@@ -0,0 +1,134 @@
1
+ CodeMirror.defineMode("r", function(config) {
2
+ function wordObj(str) {
3
+ var words = str.split(" "), res = {};
4
+ for (var i = 0; i < words.length; ++i) res[words[i]] = true;
5
+ return res;
6
+ }
7
+ var atoms = wordObj("NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_");
8
+ var builtins = wordObj("list quote bquote eval return call parse deparse");
9
+ var keywords = wordObj("if else repeat while function for in next break");
10
+ var blockkeywords = wordObj("if else repeat while function for");
11
+ var opChars = /[+\-*\/^<>=!&|~$:]/;
12
+ var curPunc;
13
+
14
+ function tokenBase(stream, state) {
15
+ curPunc = null;
16
+ var ch = stream.next();
17
+ if (ch == "#") {
18
+ stream.skipToEnd();
19
+ return "comment";
20
+ } else if (ch == "0" && stream.eat("x")) {
21
+ stream.eatWhile(/[\da-f]/i);
22
+ return "number";
23
+ } else if (ch == "." && stream.eat(/\d/)) {
24
+ stream.match(/\d*(?:e[+\-]?\d+)?/);
25
+ return "number";
26
+ } else if (/\d/.test(ch)) {
27
+ stream.match(/\d*(?:\.\d+)?(?:e[+\-]\d+)?L?/);
28
+ return "number";
29
+ } else if (ch == "'" || ch == '"') {
30
+ state.tokenize = tokenString(ch);
31
+ return "string";
32
+ } else if (ch == "." && stream.match(/.[.\d]+/)) {
33
+ return "keyword";
34
+ } else if (/[\w\.]/.test(ch) && ch != "_") {
35
+ stream.eatWhile(/[\w\.]/);
36
+ var word = stream.current();
37
+ if (atoms.propertyIsEnumerable(word)) return "atom";
38
+ if (keywords.propertyIsEnumerable(word)) {
39
+ if (blockkeywords.propertyIsEnumerable(word)) curPunc = "block";
40
+ return "keyword";
41
+ }
42
+ if (builtins.propertyIsEnumerable(word)) return "builtin";
43
+ return "variable";
44
+ } else if (ch == "%") {
45
+ if (stream.skipTo("%")) stream.next();
46
+ return "variable-2";
47
+ } else if (ch == "<" && stream.eat("-")) {
48
+ return "arrow";
49
+ } else if (opChars.test(ch)) {
50
+ if (ch == "$") return "dollar";
51
+ stream.eatWhile(opChars);
52
+ return "operator";
53
+ } else if (/[\(\){}\[\];]/.test(ch)) {
54
+ curPunc = ch;
55
+ if (ch == ";") return "semi";
56
+ return null;
57
+ } else {
58
+ return null;
59
+ }
60
+ }
61
+
62
+ function tokenString(quote) {
63
+ return function(stream, state) {
64
+ if (stream.eat("\\")) {
65
+ var ch = stream.next();
66
+ if (ch == "x") stream.match(/^[a-f0-9]{2}/i);
67
+ else if ((ch == "u" || ch == "U") && stream.eat("{") && stream.skipTo("}")) stream.next();
68
+ else if (ch == "u") stream.match(/^[a-f0-9]{4}/i);
69
+ else if (ch == "U") stream.match(/^[a-f0-9]{8}/i);
70
+ else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/);
71
+ return "string-2";
72
+ } else {
73
+ var next;
74
+ while ((next = stream.next()) != null) {
75
+ if (next == quote) { state.tokenize = tokenBase; break; }
76
+ if (next == "\\") { stream.backUp(1); break; }
77
+ }
78
+ return "string";
79
+ }
80
+ };
81
+ }
82
+
83
+ function push(state, type, stream) {
84
+ state.ctx = {type: type,
85
+ indent: state.indent,
86
+ align: null,
87
+ column: stream.column(),
88
+ prev: state.ctx};
89
+ }
90
+ function pop(state) {
91
+ state.indent = state.ctx.indent;
92
+ state.ctx = state.ctx.prev;
93
+ }
94
+
95
+ return {
96
+ startState: function(base) {
97
+ return {tokenize: tokenBase,
98
+ ctx: {type: "top",
99
+ indent: -config.indentUnit,
100
+ align: false},
101
+ indent: 0};
102
+ },
103
+
104
+ token: function(stream, state) {
105
+ if (stream.sol()) {
106
+ if (state.ctx.align == null) state.ctx.align = false;
107
+ state.indent = stream.indentation();
108
+ }
109
+ if (stream.eatSpace()) return null;
110
+ var style = state.tokenize(stream, state);
111
+ if (style != "comment" && state.ctx.align == null) state.ctx.align = true;
112
+
113
+ var ctype = state.ctx.type;
114
+ if ((curPunc == ";" || curPunc == "{" || curPunc == "}") && ctype == "block") pop(state);
115
+ if (curPunc == "{") push(state, "}", stream);
116
+ else if (curPunc == "(") push(state, ")", stream);
117
+ else if (curPunc == "[") push(state, "]", stream);
118
+ else if (curPunc == "block") push(state, "block", stream);
119
+ else if (curPunc == ctype) pop(state);
120
+ return style;
121
+ },
122
+
123
+ indent: function(state, textAfter) {
124
+ if (state.tokenize != tokenBase) return 0;
125
+ var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx,
126
+ closing = firstChar == ctx.type;
127
+ if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit);
128
+ else if (ctx.align) return ctx.column + (closing ? 0 : 1);
129
+ else return ctx.indent + (closing ? 0 : config.indentUnit);
130
+ }
131
+ };
132
+ });
133
+
134
+ CodeMirror.defineMIME("text/x-rsrc", "r");
@@ -0,0 +1,182 @@
1
+ CodeMirror.defineMode("ruby", function(config, parserConfig) {
2
+ function wordObj(words) {
3
+ var o = {};
4
+ for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
5
+ return o;
6
+ }
7
+ var keywords = wordObj([
8
+ "alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else",
9
+ "elsif", "END", "end", "ensure", "false", "for", "if", "in", "module", "next", "not", "or",
10
+ "redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless",
11
+ "until", "when", "while", "yield", "nil", "raise", "throw", "catch", "fail", "loop", "callcc",
12
+ "caller", "lambda", "proc", "public", "protected", "private", "require", "load",
13
+ "require_relative", "extend", "autoload"
14
+ ]);
15
+ var indentWords = wordObj(["def", "class", "case", "for", "while", "do", "module", "then",
16
+ "unless", "catch", "loop", "proc"]);
17
+ var dedentWords = wordObj(["end", "until"]);
18
+ var matching = {"[": "]", "{": "}", "(": ")"};
19
+ var curPunc;
20
+
21
+ function chain(newtok, stream, state) {
22
+ state.tokenize = newtok;
23
+ return newtok(stream, state);
24
+ }
25
+
26
+ function tokenBase(stream, state) {
27
+ curPunc = null;
28
+ if (stream.sol() && stream.match("=begin") && stream.eol()) {
29
+ state.tokenize = readBlockComment;
30
+ return "comment";
31
+ }
32
+ if (stream.eatSpace()) return null;
33
+ var ch = stream.next();
34
+ if (ch == "`" || ch == "'" || ch == '"' || ch == "/") {
35
+ return chain(readQuoted(ch, "string"), stream, state);
36
+ } else if (ch == "%") {
37
+ var style;
38
+ if (stream.eat("s")) style = "atom";
39
+ else if (stream.eat(/[wWxqQr]/)) style = "string";
40
+ var delim = stream.eat(/[^\w\s]/);
41
+ if (!delim) return "operator";
42
+ if (matching.propertyIsEnumerable(delim)) delim = matching[delim];
43
+ return chain(readPercentQuoted(delim, style), stream, state);
44
+ } else if (ch == "#") {
45
+ stream.skipToEnd();
46
+ return "comment";
47
+ } else if (ch == "<" && stream.eat("<")) {
48
+ stream.eat("-");
49
+ stream.eat(/[\'\"\`]/);
50
+ var match = stream.match(/^\w+/);
51
+ stream.eat(/[\'\"\`]/);
52
+ if (match) return chain(readHereDoc(match[0]), stream, state);
53
+ return null;
54
+ } else if (ch == "0") {
55
+ if (stream.eat("x")) stream.eatWhile(/[\da-fA-F]/);
56
+ else if (stream.eat("b")) stream.eatWhile(/[01]/);
57
+ else stream.eatWhile(/[0-7]/);
58
+ return "number";
59
+ } else if (/\d/.test(ch)) {
60
+ stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+\-]?[\d_]+)?/);
61
+ return "number";
62
+ } else if (ch == "?") {
63
+ while (stream.match(/^\\[CM]-/)) {}
64
+ if (stream.eat("\\")) stream.eatWhile(/\w/);
65
+ else stream.next();
66
+ return "string";
67
+ } else if (ch == ":") {
68
+ if (stream.eat("'")) return chain(readQuoted("'", "atom"), stream, state);
69
+ if (stream.eat('"')) return chain(readQuoted('"', "atom"), stream, state);
70
+ stream.eatWhile(/[\w\?]/);
71
+ return "atom";
72
+ } else if (ch == "@") {
73
+ stream.eat("@");
74
+ stream.eatWhile(/[\w\?]/);
75
+ return "variable-2";
76
+ } else if (ch == "$") {
77
+ stream.next();
78
+ stream.eatWhile(/[\w\?]/);
79
+ return "variable-3";
80
+ } else if (/\w/.test(ch)) {
81
+ stream.eatWhile(/[\w\?]/);
82
+ if (stream.eat(":")) return "atom";
83
+ return "ident";
84
+ } else if (ch == "|" && (state.varList || state.lastTok == "{" || state.lastTok == "do")) {
85
+ curPunc = "|";
86
+ return null;
87
+ } else if (/[\(\)\[\]{}\\;]/.test(ch)) {
88
+ curPunc = ch;
89
+ return null;
90
+ } else if (ch == "-" && stream.eat(">")) {
91
+ return "arrow";
92
+ } else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) {
93
+ stream.eatWhile(/[=+\-\/*:\.^%<>~|]/);
94
+ return "operator";
95
+ } else {
96
+ return null;
97
+ }
98
+ }
99
+
100
+ function readQuoted(quote, style) {
101
+ return function(stream, state) {
102
+ var escaped = false, ch;
103
+ while ((ch = stream.next()) != null) {
104
+ if (ch == quote && !escaped) {
105
+ state.tokenize = tokenBase;
106
+ break;
107
+ }
108
+ escaped = !escaped && ch == "\\";
109
+ }
110
+ return style;
111
+ };
112
+ }
113
+ function readPercentQuoted(quote, style) {
114
+ return function(stream, state) {
115
+ if (stream.skipTo(quote)) {stream.next(); state.tokenize = tokenBase;}
116
+ else stream.skipToEnd();
117
+ return style;
118
+ };
119
+ }
120
+ function readHereDoc(phrase) {
121
+ return function(stream, state) {
122
+ if (stream.match(phrase)) state.tokenize = tokenBase;
123
+ else stream.skipToEnd();
124
+ return "string";
125
+ };
126
+ }
127
+ function readBlockComment(stream, state) {
128
+ if (stream.sol() && stream.match("=end") && stream.eol())
129
+ state.tokenize = tokenBase;
130
+ stream.skipToEnd();
131
+ return "comment";
132
+ }
133
+
134
+ return {
135
+ startState: function() {
136
+ return {tokenize: tokenBase,
137
+ indented: 0,
138
+ context: {type: "top", indented: -config.indentUnit},
139
+ continuedLine: false,
140
+ lastTok: null,
141
+ varList: false};
142
+ },
143
+
144
+ token: function(stream, state) {
145
+ if (stream.sol()) state.indented = stream.indentation();
146
+ var style = state.tokenize(stream, state), kwtype;
147
+ if (style == "ident") {
148
+ var word = stream.current();
149
+ style = keywords.propertyIsEnumerable(stream.current()) ? "keyword"
150
+ : /^[A-Z]/.test(word) ? "tag"
151
+ : (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def"
152
+ : "variable";
153
+ if (indentWords.propertyIsEnumerable(word)) kwtype = "indent";
154
+ else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";
155
+ else if (word == "if" && stream.column() == stream.indentation()) kwtype = "indent";
156
+ }
157
+ if (curPunc || (style && style != "comment")) state.lastTok = word || curPunc || style;
158
+ if (curPunc == "|") state.varList = !state.varList;
159
+
160
+ if (kwtype == "indent" || /[\(\[\{]/.test(curPunc))
161
+ state.context = {prev: state.context, type: curPunc || style, indented: state.indented};
162
+ else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev)
163
+ state.context = state.context.prev;
164
+
165
+ if (stream.eol())
166
+ state.continuedLine = (curPunc == "\\" || style == "operator");
167
+ return style;
168
+ },
169
+
170
+ indent: function(state, textAfter) {
171
+ if (state.tokenize != tokenBase) return 0;
172
+ var firstChar = textAfter && textAfter.charAt(0);
173
+ var ct = state.context;
174
+ var closing = ct.type == matching[firstChar] ||
175
+ ct.type == "keyword" && /^(?:end|until|else|elsif|when)\b/.test(textAfter);
176
+ return ct.indented + (closing ? 0 : config.indentUnit) +
177
+ (state.continuedLine ? config.indentUnit : 0);
178
+ }
179
+ };
180
+ });
181
+
182
+ CodeMirror.defineMIME("text/x-ruby", "ruby");
@@ -1,181 +1,182 @@
1
- /**
2
- * Author: Koh Zi Han, based on implementation by Koh Zi Chun
3
- */
4
- CodeMirror.defineMode("scheme", function (config, mode) {
5
- var numRegex = /[0-9]/;
6
- var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
7
- ATOM = "atom", NUMBER = "number", BRACKET = "bracket";
8
- var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;
9
-
10
- function makeKeywords(str) {
11
- var obj = {}, words = str.split(" ");
12
- for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
13
- return obj;
14
- }
15
-
16
- var keywords = makeKeywords("case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt #f floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string<? string=? string>=? string>? string? substring symbol->string symbol? #t tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?");
17
- var indentKeys = makeKeywords("define let letrec let* lambda begin");
18
-
19
-
20
- function stateStack(indent, type, prev) { // represents a state stack object
21
- this.indent = indent;
22
- this.type = type;
23
- this.prev = prev;
24
- }
25
-
26
- function pushStack(state, indent, type) {
27
- state.indentStack = new stateStack(indent, type, state.indentStack);
28
- }
29
-
30
- function popStack(state) {
31
- state.indentStack = state.indentStack.prev;
32
- }
33
-
34
- return {
35
- startState: function () {
36
- return {
37
- indentStack: null,
38
- indentation: 0,
39
- mode: false,
40
- sExprComment: false
41
- };
42
- },
43
-
44
- token: function (stream, state) {
45
- if (state.indentStack == null && stream.sol()) {
46
- // update indentation, but only if indentStack is empty
47
- state.indentation = stream.indentation();
48
- }
49
-
50
- // skip spaces
51
- if (stream.eatSpace()) {
52
- return null;
53
- }
54
- var returnType = null;
55
-
56
- switch(state.mode){
57
- case "string": // multi-line string parsing mode
58
- var next, escaped = false;
59
- while ((next = stream.next()) != null) {
60
- if (next == "\"" && !escaped) {
61
-
62
- state.mode = false;
63
- break;
64
- }
65
- escaped = !escaped && next == "\\";
66
- }
67
- returnType = STRING; // continue on in scheme-string mode
68
- break;
69
- case "comment": // comment parsing mode
70
- var next, maybeEnd = false;
71
- while ((next = stream.next()) != null) {
72
- if (next == "#" && maybeEnd) {
73
-
74
- state.mode = false;
75
- break;
76
- }
77
- maybeEnd = (next == "|");
78
- }
79
- returnType = COMMENT;
80
- break;
81
- case "s-expr-comment": // s-expr commenting mode
82
- state.mode = false;
83
- if(stream.peek() == "(" || stream.peek() == "["){
84
- // actually start scheme s-expr commenting mode
85
- state.sExprComment = 0;
86
- }else{
87
- // if not we just comment the entire of the next token
88
- stream.eatWhile(/[^/s]/); // eat non spaces
89
- returnType = COMMENT;
90
- break;
91
- }
92
- default: // default parsing mode
93
- var ch = stream.next();
94
-
95
- if (ch == "\"") {
96
- state.mode = "string";
97
- returnType = STRING;
98
-
99
- } else if (ch == "'") {
100
- returnType = ATOM;
101
- } else if (ch == '#') {
102
- if (stream.eat("|")) { // Multi-line comment
103
- state.mode = "comment"; // toggle to comment mode
104
- returnType = COMMENT;
105
- } else if (stream.eat(/[tf]/)) { // #t/#f (atom)
106
- returnType = ATOM;
107
- } else if (stream.eat(';')) { // S-Expr comment
108
- state.mode = "s-expr-comment";
109
- returnType = COMMENT;
110
- }
111
-
112
- } else if (ch == ";") { // comment
113
- stream.skipToEnd(); // rest of the line is a comment
114
- returnType = COMMENT;
115
-
116
- } else if (numRegex.exec(ch) != null) { // numbers
117
- returnType = NUMBER;
118
-
119
- } else if (ch == "(" || ch == "[") {
120
- var keyWord = ''; var indentTemp = stream.column();
121
- /**
122
- Either
123
- (indent-word ..
124
- (non-indent-word ..
125
- (;something else, bracket, etc.
126
- */
127
-
128
- while ((letter = stream.eat(/[^\s\(\[\;\)\]]/)) != null) {
129
- keyWord += letter;
130
- }
131
-
132
- if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word
133
-
134
- pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
135
- } else { // non-indent word
136
- // we continue eating the spaces
137
- stream.eatSpace();
138
- if (stream.eol() || stream.peek() == ";") {
139
- // nothing significant after
140
- // we restart indentation 1 space after
141
- pushStack(state, indentTemp + 1, ch);
142
- } else {
143
- pushStack(state, indentTemp + stream.current().length, ch); // else we match
144
- }
145
- }
146
- stream.backUp(stream.current().length - 1); // undo all the eating
147
-
148
- if(typeof state.sExprComment == "number") state.sExprComment++;
149
-
150
- returnType = BRACKET;
151
- } else if (ch == ")" || ch == "]") {
152
- returnType = BRACKET;
153
- if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) {
154
- popStack(state);
155
-
156
- if(typeof state.sExprComment == "number"){
157
- if(--state.sExprComment == 0){
158
- returnType = COMMENT; // final closing bracket
159
- state.sExprComment = false; // turn off s-expr commenting mode
160
- }
161
- }
162
- }
163
- } else {
164
- stream.eatWhile(/[\w\$_]/);
165
-
166
- if (keywords && keywords.propertyIsEnumerable(stream.current())) {
167
- returnType = BUILTIN;
168
- } else returnType = null;
169
- }
170
- }
171
- return (typeof state.sExprComment == "number") ? COMMENT : returnType;
172
- },
173
-
174
- indent: function (state, textAfter) {
175
- if (state.indentStack == null) return state.indentation;
176
- return state.indentStack.indent;
177
- }
178
- };
179
- });
180
-
181
- CodeMirror.defineMIME("text/x-scheme", "css");
1
+ /**
2
+ * Author: Koh Zi Han, based on implementation by Koh Zi Chun
3
+ */
4
+ CodeMirror.defineMode("scheme", function (config, mode) {
5
+ var numRegex = /[0-9]/;
6
+ var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
7
+ ATOM = "atom", NUMBER = "number", BRACKET = "bracket";
8
+ var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;
9
+
10
+ function makeKeywords(str) {
11
+ var obj = {}, words = str.split(" ");
12
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
13
+ return obj;
14
+ }
15
+ var keywords = makeKeywords("λ case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt #f floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string<? string=? string>=? string>? string? substring symbol->string symbol? #t tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?");
16
+ var indentKeys = makeKeywords("define let letrec let* lambda begin");
17
+
18
+ function stateStack(indent, type, prev) { // represents a state stack object
19
+ this.indent = indent;
20
+ this.type = type;
21
+ this.prev = prev;
22
+ }
23
+ function pushStack(state, indent, type) {
24
+ state.indentStack = new stateStack(indent, type, state.indentStack);
25
+ }
26
+ function popStack(state) {
27
+ state.indentStack = state.indentStack.prev;
28
+ }
29
+ return {
30
+ startState: function () {
31
+ return {
32
+ indentStack: null,
33
+ indentation: 0,
34
+ mode: false,
35
+ sExprComment: false
36
+ };
37
+ },
38
+ token: function (stream, state) {
39
+ if (state.indentStack == null && stream.sol()) {
40
+ // update indentation, but only if indentStack is empty
41
+ state.indentation = stream.indentation();
42
+ }
43
+ // skip spaces
44
+ if (stream.eatSpace()) {
45
+ return null;
46
+ }
47
+ var returnType = null;
48
+
49
+ switch(state.mode){
50
+ case "string": // multi-line string parsing mode
51
+ var next, escaped = false;
52
+ while ((next = stream.next()) != null) {
53
+ if (next == "\"" && !escaped) {
54
+
55
+ state.mode = false;
56
+ break;
57
+ }
58
+ escaped = !escaped && next == "\\";
59
+ }
60
+ returnType = STRING; // continue on in scheme-string mode
61
+ break;
62
+ case "comment": // comment parsing mode
63
+ var next, maybeEnd = false;
64
+ while ((next = stream.next()) != null) {
65
+ if (next == "#" && maybeEnd) {
66
+
67
+ state.mode = false;
68
+ break;
69
+ }
70
+ maybeEnd = (next == "|");
71
+ }
72
+ returnType = COMMENT;
73
+ break;
74
+ case "s-expr-comment": // s-expr commenting mode
75
+ state.mode = false;
76
+ if(stream.peek() == "(" || stream.peek() == "["){
77
+ // actually start scheme s-expr commenting mode
78
+ state.sExprComment = 0;
79
+ }else{
80
+ // if not we just comment the entire of the next token
81
+ stream.eatWhile(/[^/s]/); // eat non spaces
82
+ returnType = COMMENT;
83
+ break;
84
+ }
85
+ default: // default parsing mode
86
+ var ch = stream.next();
87
+
88
+ if (ch == "\"") {
89
+ state.mode = "string";
90
+ returnType = STRING;
91
+
92
+ } else if (ch == "'") {
93
+ returnType = ATOM;
94
+ } else if (ch == '#') {
95
+ if (stream.eat("|")) { // Multi-line comment
96
+ state.mode = "comment"; // toggle to comment mode
97
+ returnType = COMMENT;
98
+ } else if (stream.eat(/[tf]/)) { // #t/#f (atom)
99
+ returnType = ATOM;
100
+ } else if (stream.eat(';')) { // S-Expr comment
101
+ state.mode = "s-expr-comment";
102
+ returnType = COMMENT;
103
+ }
104
+
105
+ } else if (ch == ";") { // comment
106
+ stream.skipToEnd(); // rest of the line is a comment
107
+ returnType = COMMENT;
108
+ } else if (ch == "-"){
109
+
110
+ if(stream.eat(/\d/)) {
111
+ stream.eatWhile(/[\/0-9]/);
112
+ returnType = NUMBER;
113
+ }else{
114
+
115
+ returnType = null;
116
+ }
117
+ } else if (numRegex.exec(ch) != null) { // numbers
118
+ stream.eatWhile(/[\/0-9]/);
119
+ returnType = NUMBER;
120
+
121
+ } else if (ch == "(" || ch == "[") {
122
+ var keyWord = ''; var indentTemp = stream.column();
123
+ /**
124
+ Either
125
+ (indent-word ..
126
+ (non-indent-word ..
127
+ (;something else, bracket, etc.
128
+ */
129
+
130
+ while ((letter = stream.eat(/[^\s\(\[\;\)\]]/)) != null) {
131
+ keyWord += letter;
132
+ }
133
+
134
+ if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word
135
+
136
+ pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
137
+ } else { // non-indent word
138
+ // we continue eating the spaces
139
+ stream.eatSpace();
140
+ if (stream.eol() || stream.peek() == ";") {
141
+ // nothing significant after
142
+ // we restart indentation 1 space after
143
+ pushStack(state, indentTemp + 1, ch);
144
+ } else {
145
+ pushStack(state, indentTemp + stream.current().length, ch); // else we match
146
+ }
147
+ }
148
+ stream.backUp(stream.current().length - 1); // undo all the eating
149
+
150
+ if(typeof state.sExprComment == "number") state.sExprComment++;
151
+
152
+ returnType = BRACKET;
153
+ } else if (ch == ")" || ch == "]") {
154
+ returnType = BRACKET;
155
+ if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) {
156
+ popStack(state);
157
+
158
+ if(typeof state.sExprComment == "number"){
159
+ if(--state.sExprComment == 0){
160
+ returnType = COMMENT; // final closing bracket
161
+ state.sExprComment = false; // turn off s-expr commenting mode
162
+ }
163
+ }
164
+ }
165
+ } else {
166
+ stream.eatWhile(/[\w\$_\-]/);
167
+
168
+ if (keywords && keywords.propertyIsEnumerable(stream.current())) {
169
+
170
+ returnType = BUILTIN;
171
+ } else returnType = null;
172
+ }
173
+ }
174
+ return (typeof state.sExprComment == "number") ? COMMENT : returnType;
175
+ },
176
+ indent: function (state, textAfter) {
177
+ if (state.indentStack == null) return state.indentation;
178
+ return state.indentStack.indent;
179
+ }
180
+ };
181
+ });
182
+ CodeMirror.defineMIME("text/x-scheme", "scheme");