1 CodeMirror.defineMode('smalltalk', function(config) {
3 var specialChars = /[+\-\/\\*~<>=@%|&?!.,:;^]/;
4 var keywords = /true|false|nil|self|super|thisContext/;
6 var Context = function(tokenizer, parent) {
11 var Token = function(name, context, eos) {
13 this.context = context;
17 var State = function() {
18 this.context = new Context(next, null);
19 this.expectVariable = true;
21 this.userIndentationDelta = 0;
24 State.prototype.userIndent = function(indentation) {
25 this.userIndentationDelta = indentation > 0 ? (indentation / config.indentUnit - this.indentation) : 0;
28 var next = function(stream, context, state) {
29 var token = new Token(null, context, false);
30 var aChar = stream.next();
33 token = nextComment(stream, new Context(nextComment, context));
35 } else if (aChar === '\'') {
36 token = nextString(stream, new Context(nextString, context));
38 } else if (aChar === '#') {
39 if (stream.peek() === '\'') {
41 token = nextSymbol(stream, new Context(nextSymbol, context));
43 stream.eatWhile(/[^ .\[\]()]/);
44 token.name = 'string-2';
47 } else if (aChar === '$') {
48 if (stream.next() === '<') {
49 stream.eatWhile(/[^ >]/);
52 token.name = 'string-2';
54 } else if (aChar === '|' && state.expectVariable) {
55 token.context = new Context(nextTemporaries, context);
57 } else if (/[\[\]{}()]/.test(aChar)) {
58 token.name = 'bracket';
59 token.eos = /[\[{(]/.test(aChar);
63 } else if (aChar === ']') {
64 state.indentation = Math.max(0, state.indentation - 1);
67 } else if (specialChars.test(aChar)) {
68 stream.eatWhile(specialChars);
69 token.name = 'operator';
70 token.eos = aChar !== ';'; // ; cascaded message expression
72 } else if (/\d/.test(aChar)) {
73 stream.eatWhile(/[\w\d]/);
74 token.name = 'number';
76 } else if (/[\w_]/.test(aChar)) {
77 stream.eatWhile(/[\w\d_]/);
78 token.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null;
81 token.eos = state.expectVariable;
87 var nextComment = function(stream, context) {
88 stream.eatWhile(/[^"]/);
89 return new Token('comment', stream.eat('"') ? context.parent : context, true);
92 var nextString = function(stream, context) {
93 stream.eatWhile(/[^']/);
94 return new Token('string', stream.eat('\'') ? context.parent : context, false);
97 var nextSymbol = function(stream, context) {
98 stream.eatWhile(/[^']/);
99 return new Token('string-2', stream.eat('\'') ? context.parent : context, false);
102 var nextTemporaries = function(stream, context) {
103 var token = new Token(null, context, false);
104 var aChar = stream.next();
107 token.context = context.parent;
111 stream.eatWhile(/[^|]/);
112 token.name = 'variable';
119 startState: function() {
123 token: function(stream, state) {
124 state.userIndent(stream.indentation());
126 if (stream.eatSpace()) {
130 var token = state.context.next(stream, state.context, state);
131 state.context = token.context;
132 state.expectVariable = token.eos;
137 blankLine: function(state) {
141 indent: function(state, textAfter) {
142 var i = state.context.next === next && textAfter && textAfter.charAt(0) === ']' ? -1 : state.userIndentationDelta;
143 return (state.indentation + i) * config.indentUnit;
151 CodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'});