| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 | CodeMirror.defineMode('smalltalk', function(config, modeConfig) {	var specialChars = /[+\-/\\*~<>=@%|&?!.:;^]/;	var keywords = /true|false|nil|self|super|thisContext/;	var Context = function(tokenizer, parent) {		this.next = tokenizer;		this.parent = parent;	};	var Token = function(name, context, eos) {		this.name = name;		this.context = context;		this.eos = eos;	};	var State = function() {		this.context = new Context(next, null);		this.expectVariable = true;		this.indentation = 0;		this.userIndentationDelta = 0;	};	State.prototype.userIndent = function(indentation) {		this.userIndentationDelta = indentation > 0 ? (indentation / config.indentUnit - this.indentation) : 0;	};	var next = function(stream, context, state) {		var token = new Token(null, context, false);		var aChar = stream.next();		if (aChar === '"') {			token = nextComment(stream, new Context(nextComment, context));		} else if (aChar === '\'') {			token = nextString(stream, new Context(nextString, context));		} else if (aChar === '#') {			stream.eatWhile(/[^ .]/);			token.name = 'string-2';		} else if (aChar === '$') {			stream.eatWhile(/[^ ]/);			token.name = 'string-2';		} else if (aChar === '|' && state.expectVariable) {			token.context = new Context(nextTemporaries, context);		} else if (/[\[\]{}()]/.test(aChar)) {			token.name = 'bracket';			token.eos = /[\[{(]/.test(aChar);			if (aChar === '[') {				state.indentation++;			} else if (aChar === ']') {				state.indentation = Math.max(0, state.indentation - 1);			}		} else if (specialChars.test(aChar)) {			stream.eatWhile(specialChars);			token.name = 'operator';			token.eos = aChar !== ';'; // ; cascaded message expression		} else if (/\d/.test(aChar)) {			stream.eatWhile(/[\w\d]/);			token.name = 'number';		} else if (/[\w_]/.test(aChar)) {			stream.eatWhile(/[\w\d_]/);			token.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null;		} else {			token.eos = state.expectVariable;		}		return token;	};	var nextComment = function(stream, context) {		stream.eatWhile(/[^"]/);		return new Token('comment', stream.eat('"') ? context.parent : context, true);	};	var nextString = function(stream, context) {		stream.eatWhile(/[^']/);		return new Token('string', stream.eat('\'') ? context.parent : context, false);	};	var nextTemporaries = function(stream, context, state) {		var token = new Token(null, context, false);		var aChar = stream.next();		if (aChar === '|') {			token.context = context.parent;			token.eos = true;		} else {			stream.eatWhile(/[^|]/);			token.name = 'variable';		}		return token;	};	return {		startState: function() {			return new State;		},		token: function(stream, state) {			state.userIndent(stream.indentation());			if (stream.eatSpace()) {				return null;			}			var token = state.context.next(stream, state.context, state);			state.context = token.context;			state.expectVariable = token.eos;			state.lastToken = token;			return token.name;		},		blankLine: function(state) {			state.userIndent(0);		},		indent: function(state, textAfter) {			var i = state.context.next === next && textAfter && textAfter.charAt(0) === ']' ? -1 : state.userIndentationDelta;			return (state.indentation + i) * config.indentUnit;		},		electricChars: ']'	};});CodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'});
 |