all repos — NoPaste @ 3e3c433f026c49e04d0efa0f0f39fc688ed32bb1

Resurrected - The PussTheCat.org fork of NoPaste

scripts/CodeMirror/mode/smalltalk/smalltalk.js (view raw)

  1// CodeMirror, copyright (c) by Marijn Haverbeke and others
  2// Distributed under an MIT license: https://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
 14CodeMirror.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
166CodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'});
167
168});