0
|
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
2 // Distributed under an MIT license: https://codemirror.net/5/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 });
|