| 776 |
lars |
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.defineMode('smalltalk', function(config) {
|
|
|
15 |
|
|
|
16 |
var specialChars = /[+\-\/\\*~<>=@%|&?!.,:;^]/;
|
|
|
17 |
var keywords = /true|false|nil|self|super|thisContext/;
|
|
|
18 |
|
|
|
19 |
var Context = function(tokenizer, parent) {
|
|
|
20 |
this.next = tokenizer;
|
|
|
21 |
this.parent = parent;
|
|
|
22 |
};
|
|
|
23 |
|
|
|
24 |
var Token = function(name, context, eos) {
|
|
|
25 |
this.name = name;
|
|
|
26 |
this.context = context;
|
|
|
27 |
this.eos = eos;
|
|
|
28 |
};
|
|
|
29 |
|
|
|
30 |
var State = function() {
|
|
|
31 |
this.context = new Context(next, null);
|
|
|
32 |
this.expectVariable = true;
|
|
|
33 |
this.indentation = 0;
|
|
|
34 |
this.userIndentationDelta = 0;
|
|
|
35 |
};
|
|
|
36 |
|
|
|
37 |
State.prototype.userIndent = function(indentation) {
|
|
|
38 |
this.userIndentationDelta = indentation > 0 ? (indentation / config.indentUnit - this.indentation) : 0;
|
|
|
39 |
};
|
|
|
40 |
|
|
|
41 |
var next = function(stream, context, state) {
|
|
|
42 |
var token = new Token(null, context, false);
|
|
|
43 |
var aChar = stream.next();
|
|
|
44 |
|
|
|
45 |
if (aChar === '"') {
|
|
|
46 |
token = nextComment(stream, new Context(nextComment, context));
|
|
|
47 |
|
|
|
48 |
} else if (aChar === '\'') {
|
|
|
49 |
token = nextString(stream, new Context(nextString, context));
|
|
|
50 |
|
|
|
51 |
} else if (aChar === '#') {
|
|
|
52 |
if (stream.peek() === '\'') {
|
|
|
53 |
stream.next();
|
|
|
54 |
token = nextSymbol(stream, new Context(nextSymbol, context));
|
|
|
55 |
} else {
|
|
|
56 |
if (stream.eatWhile(/[^\s.{}\[\]()]/))
|
|
|
57 |
token.name = 'string-2';
|
|
|
58 |
else
|
|
|
59 |
token.name = 'meta';
|
|
|
60 |
}
|
|
|
61 |
|
|
|
62 |
} else if (aChar === '$') {
|
|
|
63 |
if (stream.next() === '<') {
|
|
|
64 |
stream.eatWhile(/[^\s>]/);
|
|
|
65 |
stream.next();
|
|
|
66 |
}
|
|
|
67 |
token.name = 'string-2';
|
|
|
68 |
|
|
|
69 |
} else if (aChar === '|' && state.expectVariable) {
|
|
|
70 |
token.context = new Context(nextTemporaries, context);
|
|
|
71 |
|
|
|
72 |
} else if (/[\[\]{}()]/.test(aChar)) {
|
|
|
73 |
token.name = 'bracket';
|
|
|
74 |
token.eos = /[\[{(]/.test(aChar);
|
|
|
75 |
|
|
|
76 |
if (aChar === '[') {
|
|
|
77 |
state.indentation++;
|
|
|
78 |
} else if (aChar === ']') {
|
|
|
79 |
state.indentation = Math.max(0, state.indentation - 1);
|
|
|
80 |
}
|
|
|
81 |
|
|
|
82 |
} else if (specialChars.test(aChar)) {
|
|
|
83 |
stream.eatWhile(specialChars);
|
|
|
84 |
token.name = 'operator';
|
|
|
85 |
token.eos = aChar !== ';'; // ; cascaded message expression
|
|
|
86 |
|
|
|
87 |
} else if (/\d/.test(aChar)) {
|
|
|
88 |
stream.eatWhile(/[\w\d]/);
|
|
|
89 |
token.name = 'number';
|
|
|
90 |
|
|
|
91 |
} else if (/[\w_]/.test(aChar)) {
|
|
|
92 |
stream.eatWhile(/[\w\d_]/);
|
|
|
93 |
token.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null;
|
|
|
94 |
|
|
|
95 |
} else {
|
|
|
96 |
token.eos = state.expectVariable;
|
|
|
97 |
}
|
|
|
98 |
|
|
|
99 |
return token;
|
|
|
100 |
};
|
|
|
101 |
|
|
|
102 |
var nextComment = function(stream, context) {
|
|
|
103 |
stream.eatWhile(/[^"]/);
|
|
|
104 |
return new Token('comment', stream.eat('"') ? context.parent : context, true);
|
|
|
105 |
};
|
|
|
106 |
|
|
|
107 |
var nextString = function(stream, context) {
|
|
|
108 |
stream.eatWhile(/[^']/);
|
|
|
109 |
return new Token('string', stream.eat('\'') ? context.parent : context, false);
|
|
|
110 |
};
|
|
|
111 |
|
|
|
112 |
var nextSymbol = function(stream, context) {
|
|
|
113 |
stream.eatWhile(/[^']/);
|
|
|
114 |
return new Token('string-2', stream.eat('\'') ? context.parent : context, false);
|
|
|
115 |
};
|
|
|
116 |
|
|
|
117 |
var nextTemporaries = function(stream, context) {
|
|
|
118 |
var token = new Token(null, context, false);
|
|
|
119 |
var aChar = stream.next();
|
|
|
120 |
|
|
|
121 |
if (aChar === '|') {
|
|
|
122 |
token.context = context.parent;
|
|
|
123 |
token.eos = true;
|
|
|
124 |
|
|
|
125 |
} else {
|
|
|
126 |
stream.eatWhile(/[^|]/);
|
|
|
127 |
token.name = 'variable';
|
|
|
128 |
}
|
|
|
129 |
|
|
|
130 |
return token;
|
|
|
131 |
};
|
|
|
132 |
|
|
|
133 |
return {
|
|
|
134 |
startState: function() {
|
|
|
135 |
return new State;
|
|
|
136 |
},
|
|
|
137 |
|
|
|
138 |
token: function(stream, state) {
|
|
|
139 |
state.userIndent(stream.indentation());
|
|
|
140 |
|
|
|
141 |
if (stream.eatSpace()) {
|
|
|
142 |
return null;
|
|
|
143 |
}
|
|
|
144 |
|
|
|
145 |
var token = state.context.next(stream, state.context, state);
|
|
|
146 |
state.context = token.context;
|
|
|
147 |
state.expectVariable = token.eos;
|
|
|
148 |
|
|
|
149 |
return token.name;
|
|
|
150 |
},
|
|
|
151 |
|
|
|
152 |
blankLine: function(state) {
|
|
|
153 |
state.userIndent(0);
|
|
|
154 |
},
|
|
|
155 |
|
|
|
156 |
indent: function(state, textAfter) {
|
|
|
157 |
var i = state.context.next === next && textAfter && textAfter.charAt(0) === ']' ? -1 : state.userIndentationDelta;
|
|
|
158 |
return (state.indentation + i) * config.indentUnit;
|
|
|
159 |
},
|
|
|
160 |
|
|
|
161 |
electricChars: ']'
|
|
|
162 |
};
|
|
|
163 |
|
|
|
164 |
});
|
|
|
165 |
|
|
|
166 |
CodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'});
|
|
|
167 |
|
|
|
168 |
});
|