codemirror-rails 5.7 → 5.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +54 -33
  4. data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +20 -7
  5. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +77 -23
  6. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +3 -6
  7. data/vendor/assets/javascripts/codemirror/addons/mode/multiplex.js +3 -3
  8. data/vendor/assets/javascripts/codemirror/addons/wrap/hardwrap.js +9 -6
  9. data/vendor/assets/javascripts/codemirror/keymaps/sublime.js +3 -1
  10. data/vendor/assets/javascripts/codemirror/modes/clike.js +140 -15
  11. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +0 -11
  12. data/vendor/assets/javascripts/codemirror/modes/css.js +2 -0
  13. data/vendor/assets/javascripts/codemirror/modes/cypher.js +3 -3
  14. data/vendor/assets/javascripts/codemirror/modes/dart.js +81 -1
  15. data/vendor/assets/javascripts/codemirror/modes/haxe.js +13 -4
  16. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +2 -2
  17. data/vendor/assets/javascripts/codemirror/modes/javascript.js +20 -5
  18. data/vendor/assets/javascripts/codemirror/modes/markdown.js +58 -47
  19. data/vendor/assets/javascripts/codemirror/modes/nsis.js +63 -0
  20. data/vendor/assets/javascripts/codemirror/modes/rpm.js +17 -9
  21. data/vendor/assets/stylesheets/codemirror/themes/abcdef.css +1 -1
  22. data/vendor/assets/stylesheets/codemirror/themes/base16-dark.css +1 -1
  23. data/vendor/assets/stylesheets/codemirror/themes/base16-light.css +1 -1
  24. data/vendor/assets/stylesheets/codemirror/themes/bespin.css +34 -0
  25. data/vendor/assets/stylesheets/codemirror/themes/hopscotch.css +34 -0
  26. data/vendor/assets/stylesheets/codemirror/themes/isotope.css +34 -0
  27. data/vendor/assets/stylesheets/codemirror/themes/liquibyte.css +14 -14
  28. data/vendor/assets/stylesheets/codemirror/themes/railscasts.css +34 -0
  29. metadata +6 -2
  30. data/vendor/assets/javascripts/codemirror/modes/kotlin.js +0 -284
@@ -32,11 +32,13 @@
32
32
  function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
33
33
  for (var at = column; at > 0; --at)
34
34
  if (wrapOn.test(text.slice(at - 1, at + 1))) break;
35
- if (at == 0) at = column;
36
- var endOfText = at;
37
- if (killTrailingSpace)
38
- while (text.charAt(endOfText - 1) == " ") --endOfText;
39
- return {from: endOfText, to: at};
35
+ for (var first = true;; first = false) {
36
+ var endOfText = at;
37
+ if (killTrailingSpace)
38
+ while (text.charAt(endOfText - 1) == " ") --endOfText;
39
+ if (endOfText == 0 && first) at = column;
40
+ else return {from: endOfText, to: at};
41
+ }
40
42
  }
41
43
 
42
44
  function wrapRange(cm, from, to, options) {
@@ -86,7 +88,8 @@
86
88
  if (changes.length) cm.operation(function() {
87
89
  for (var i = 0; i < changes.length; ++i) {
88
90
  var change = changes[i];
89
- cm.replaceRange(change.text, change.from, change.to);
91
+ if (change.text || CodeMirror.cmpPos(change.from, change.to))
92
+ cm.replaceRange(change.text, change.from, change.to);
90
93
  }
91
94
  });
92
95
  return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;
@@ -240,7 +240,9 @@
240
240
  });
241
241
  };
242
242
 
243
- map[ctrl + "/"] = "toggleComment";
243
+ map[ctrl + "/"] = function(cm) {
244
+ cm.toggleComment({ indent: true });
245
+ }
244
246
 
245
247
  cmds[map[ctrl + "J"] = "joinLines"] = function(cm) {
246
248
  var ranges = cm.listSelections(), joined = [];
@@ -25,8 +25,11 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
25
25
  multiLineStrings = parserConfig.multiLineStrings,
26
26
  indentStatements = parserConfig.indentStatements !== false,
27
27
  indentSwitch = parserConfig.indentSwitch !== false,
28
- namespaceSeparator = parserConfig.namespaceSeparator;
29
- var isOperatorChar = /[+\-*&%=<>!?|\/]/;
28
+ namespaceSeparator = parserConfig.namespaceSeparator,
29
+ isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/,
30
+ isNumberChar = parserConfig.isNumberChar || /\d/,
31
+ isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/,
32
+ endStatement = parserConfig.endStatement || /^[;:,]$/;
30
33
 
31
34
  var curPunc, isDefKeyword;
32
35
 
@@ -40,11 +43,11 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
40
43
  state.tokenize = tokenString(ch);
41
44
  return state.tokenize(stream, state);
42
45
  }
43
- if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
46
+ if (isPunctuationChar.test(ch)) {
44
47
  curPunc = ch;
45
48
  return null;
46
49
  }
47
- if (/\d/.test(ch)) {
50
+ if (isNumberChar.test(ch)) {
48
51
  stream.eatWhile(/[\w\.]/);
49
52
  return "number";
50
53
  }
@@ -67,17 +70,17 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
67
70
  stream.eatWhile(/[\w\$_\xa1-\uffff]/);
68
71
 
69
72
  var cur = stream.current();
70
- if (keywords.propertyIsEnumerable(cur)) {
71
- if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
72
- if (defKeywords.propertyIsEnumerable(cur)) isDefKeyword = true;
73
+ if (contains(keywords, cur)) {
74
+ if (contains(blockKeywords, cur)) curPunc = "newstatement";
75
+ if (contains(defKeywords, cur)) isDefKeyword = true;
73
76
  return "keyword";
74
77
  }
75
- if (types.propertyIsEnumerable(cur)) return "variable-3";
76
- if (builtin.propertyIsEnumerable(cur)) {
77
- if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
78
+ if (contains(types, cur)) return "variable-3";
79
+ if (contains(builtin, cur)) {
80
+ if (contains(blockKeywords, cur)) curPunc = "newstatement";
78
81
  return "builtin";
79
82
  }
80
- if (atoms.propertyIsEnumerable(cur)) return "atom";
83
+ if (contains(atoms, cur)) return "atom";
81
84
  return "variable";
82
85
  }
83
86
 
@@ -168,8 +171,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
168
171
  if (style == "comment" || style == "meta") return style;
169
172
  if (ctx.align == null) ctx.align = true;
170
173
 
171
- if ((curPunc == ";" || curPunc == ":" || curPunc == ","))
172
- while (isStatement(state.context.type)) popContext(state);
174
+ if (endStatement.test(curPunc)) while (isStatement(state.context.type)) popContext(state);
173
175
  else if (curPunc == "{") pushContext(state, stream.column(), "}");
174
176
  else if (curPunc == "[") pushContext(state, stream.column(), "]");
175
177
  else if (curPunc == "(") pushContext(state, stream.column(), ")");
@@ -212,6 +214,10 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
212
214
  if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
213
215
  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
214
216
  if (isStatement(ctx.type) && firstChar == "}") ctx = ctx.prev;
217
+ if (hooks.indent) {
218
+ var hook = hooks.indent(state, ctx, textAfter);
219
+ if (typeof hook == "number") return hook
220
+ }
215
221
  var closing = firstChar == ctx.type;
216
222
  var switchBlock = ctx.prev && ctx.prev.type == "switchstatement";
217
223
  if (isStatement(ctx.type))
@@ -238,6 +244,13 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
238
244
  for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
239
245
  return obj;
240
246
  }
247
+ function contains(words, word) {
248
+ if (typeof words === "function") {
249
+ return words(word);
250
+ } else {
251
+ return words.propertyIsEnumerable(word);
252
+ }
253
+ }
241
254
  var cKeywords = "auto if break case register continue return default do sizeof " +
242
255
  "static else struct switch extern typedef float union for " +
243
256
  "goto while enum const volatile";
@@ -413,6 +426,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
413
426
  defKeywords: words("class interface package enum"),
414
427
  typeFirstDefinitions: true,
415
428
  atoms: words("true false null"),
429
+ endStatement: /^[;:]$/,
416
430
  hooks: {
417
431
  "@": function(stream) {
418
432
  stream.eatWhile(/[\w\$_]/);
@@ -468,7 +482,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
468
482
  keywords: words(
469
483
 
470
484
  /* scala */
471
- "abstract case catch class def do else extends false final finally for forSome if " +
485
+ "abstract case catch class def do else extends final finally for forSome if " +
472
486
  "implicit import lazy match new null object override package private protected return " +
473
487
  "sealed super this throw trait try type val var while with yield _ : = => <- <: " +
474
488
  "<% >: # @ " +
@@ -516,6 +530,34 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
516
530
  modeProps: {closeBrackets: {triples: '"'}}
517
531
  });
518
532
 
533
+ def("text/x-kotlin", {
534
+ name: "clike",
535
+ keywords: words(
536
+ /*keywords*/
537
+ "package as typealias class interface this super val " +
538
+ "var fun for is in This throw return " +
539
+ "break continue object if else while do try when !in !is as?" +
540
+
541
+ /*soft keywords*/
542
+ "file import where by get set abstract enum open inner override private public internal " +
543
+ "protected catch finally out final vararg reified dynamic companion constructor init " +
544
+ "sealed field property receiver param sparam lateinit data inline noinline tailrec " +
545
+ "external annotation crossinline"
546
+ ),
547
+ types: words(
548
+ /* package java.lang */
549
+ "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
550
+ "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
551
+ "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
552
+ "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
553
+ ),
554
+ multiLineStrings: true,
555
+ blockKeywords: words("catch class do else finally for if where try while enum"),
556
+ defKeywords: words("class val var object package interface fun"),
557
+ atoms: words("true false null this"),
558
+ modeProps: {closeBrackets: {triples: '"'}}
559
+ });
560
+
519
561
  def(["x-shader/x-vertex", "x-shader/x-fragment"], {
520
562
  name: "clike",
521
563
  keywords: words("sampler1D sampler2D sampler3D samplerCube " +
@@ -598,7 +640,10 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
598
640
  stream.eatWhile(/[\w\$]/);
599
641
  return "keyword";
600
642
  },
601
- "#": cppHook
643
+ "#": cppHook,
644
+ indent: function(_state, ctx, textAfter) {
645
+ if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented
646
+ }
602
647
  },
603
648
  modeProps: {fold: "brace"}
604
649
  });
@@ -616,4 +661,84 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
616
661
  modeProps: {fold: ["brace", "include"]}
617
662
  });
618
663
 
664
+ // Ceylon Strings need to deal with interpolation
665
+ var stringTokenizer = null;
666
+ function tokenCeylonString(type) {
667
+ return function(stream, state) {
668
+ var escaped = false, next, end = false;
669
+ while (!stream.eol()) {
670
+ if (!escaped && stream.match('"') &&
671
+ (type == "single" || stream.match('""'))) {
672
+ end = true;
673
+ break;
674
+ }
675
+ if (!escaped && stream.match('``')) {
676
+ stringTokenizer = tokenCeylonString(type);
677
+ end = true;
678
+ break;
679
+ }
680
+ next = stream.next();
681
+ escaped = type == "single" && !escaped && next == "\\";
682
+ }
683
+ if (end)
684
+ state.tokenize = null;
685
+ return "string";
686
+ }
687
+ }
688
+
689
+ def("text/x-ceylon", {
690
+ name: "clike",
691
+ keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" +
692
+ " exists extends finally for function given if import in interface is let module new" +
693
+ " nonempty object of out outer package return satisfies super switch then this throw" +
694
+ " try value void while"),
695
+ types: function(word) {
696
+ // In Ceylon all identifiers that start with an uppercase are types
697
+ var first = word.charAt(0);
698
+ return (first === first.toUpperCase() && first !== first.toLowerCase());
699
+ },
700
+ blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"),
701
+ defKeywords: words("class dynamic function interface module object package value"),
702
+ builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" +
703
+ " native optional sealed see serializable shared suppressWarnings tagged throws variable"),
704
+ isPunctuationChar: /[\[\]{}\(\),;\:\.`]/,
705
+ isOperatorChar: /[+\-*&%=<>!?|^~:\/]/,
706
+ isNumberChar: /[\d#$]/,
707
+ multiLineStrings: true,
708
+ typeFirstDefinitions: true,
709
+ atoms: words("true false null larger smaller equal empty finished"),
710
+ indentSwitch: false,
711
+ styleDefs: false,
712
+ hooks: {
713
+ "@": function(stream) {
714
+ stream.eatWhile(/[\w\$_]/);
715
+ return "meta";
716
+ },
717
+ '"': function(stream, state) {
718
+ state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single");
719
+ return state.tokenize(stream, state);
720
+ },
721
+ '`': function(stream, state) {
722
+ if (!stringTokenizer || !stream.match('`')) return false;
723
+ state.tokenize = stringTokenizer;
724
+ stringTokenizer = null;
725
+ return state.tokenize(stream, state);
726
+ },
727
+ "'": function(stream) {
728
+ stream.eatWhile(/[\w\$_\xa1-\uffff]/);
729
+ return "atom";
730
+ },
731
+ token: function(_stream, state, style) {
732
+ if ((style == "variable" || style == "variable-3") &&
733
+ state.prevToken == ".") {
734
+ return "variable-2";
735
+ }
736
+ }
737
+ },
738
+ modeProps: {
739
+ fold: ["brace", "import"],
740
+ closeBrackets: {triples: '"'}
741
+ }
742
+ });
743
+
619
744
  });
@@ -267,17 +267,6 @@ CodeMirror.defineMode("coffeescript", function(conf, parserConf) {
267
267
  var style = state.tokenize(stream, state);
268
268
  var current = stream.current();
269
269
 
270
- // Handle "." connected identifiers
271
- if (false && current === ".") {
272
- style = state.tokenize(stream, state);
273
- current = stream.current();
274
- if (/^\.[\w$]+$/.test(current)) {
275
- return "variable";
276
- } else {
277
- return ERRORCLASS;
278
- }
279
- }
280
-
281
270
  // Handle scope changes.
282
271
  if (current === "return") {
283
272
  state.dedent = true;
@@ -275,6 +275,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
275
275
  if (type == "}" || type == ";") return popAndPass(type, stream, state);
276
276
  if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
277
277
 
278
+ if (type == "interpolation") return pushContext(state, stream, "interpolation");
279
+
278
280
  if (type == "word") {
279
281
  var word = stream.current().toLowerCase();
280
282
  if (word == "only" || word == "not" || word == "and" || word == "or")
@@ -60,9 +60,9 @@
60
60
  };
61
61
  var indentUnit = config.indentUnit;
62
62
  var curPunc;
63
- var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "right", "round", "rtrim", "shortestPath", "sign", "sin", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "trim", "type", "upper"]);
64
- var preds = wordRegexp(["all", "and", "any", "has", "in", "none", "not", "or", "single", "xor", "like", "ilike", "exists"]);
65
- var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "join", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);
63
+ var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "reverse", "right", "round", "rtrim", "shortestPath", "sign", "sin", "size", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "toString", "trim", "type", "upper"]);
64
+ var preds = wordRegexp(["all", "and", "any", "contains", "exists", "has", "in", "none", "not", "or", "single", "xor"]);
65
+ var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "detach", "distinct", "drop", "else", "end", "ends", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "join", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "starts", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);
66
66
  var operatorChars = /[*+\-<>=&|~%^]/;
67
67
 
68
68
  return {
@@ -26,10 +26,21 @@
26
26
  return obj;
27
27
  }
28
28
 
29
+ function pushInterpolationStack(state) {
30
+ (state.interpolationStack || (state.interpolationStack = [])).push(state.tokenize);
31
+ }
32
+
33
+ function popInterpolationStack(state) {
34
+ return (state.interpolationStack || (state.interpolationStack = [])).pop();
35
+ }
36
+
37
+ function sizeInterpolationStack(state) {
38
+ return state.interpolationStack ? state.interpolationStack.length : 0;
39
+ }
40
+
29
41
  CodeMirror.defineMIME("application/dart", {
30
42
  name: "clike",
31
43
  keywords: set(keywords),
32
- multiLineStrings: true,
33
44
  blockKeywords: set(blockKeywords),
34
45
  builtin: set(builtins),
35
46
  atoms: set(atoms),
@@ -37,10 +48,79 @@
37
48
  "@": function(stream) {
38
49
  stream.eatWhile(/[\w\$_]/);
39
50
  return "meta";
51
+ },
52
+
53
+ // custom string handling to deal with triple-quoted strings and string interpolation
54
+ "'": function(stream, state) {
55
+ return tokenString("'", stream, state, false);
56
+ },
57
+ "\"": function(stream, state) {
58
+ return tokenString("\"", stream, state, false);
59
+ },
60
+ "r": function(stream, state) {
61
+ var peek = stream.peek();
62
+ if (peek == "'" || peek == "\"") {
63
+ return tokenString(stream.next(), stream, state, true);
64
+ }
65
+ return false;
66
+ },
67
+
68
+ "}": function(_stream, state) {
69
+ // "}" is end of interpolation, if interpolation stack is non-empty
70
+ if (sizeInterpolationStack(state) > 0) {
71
+ state.tokenize = popInterpolationStack(state);
72
+ return null;
73
+ }
74
+ return false;
40
75
  }
41
76
  }
42
77
  });
43
78
 
79
+ function tokenString(quote, stream, state, raw) {
80
+ var tripleQuoted = false;
81
+ if (stream.eat(quote)) {
82
+ if (stream.eat(quote)) tripleQuoted = true;
83
+ else return "string"; //empty string
84
+ }
85
+ function tokenStringHelper(stream, state) {
86
+ var escaped = false;
87
+ while (!stream.eol()) {
88
+ if (!raw && !escaped && stream.peek() == "$") {
89
+ pushInterpolationStack(state);
90
+ state.tokenize = tokenInterpolation;
91
+ return "string";
92
+ }
93
+ var next = stream.next();
94
+ if (next == quote && !escaped && (!tripleQuoted || stream.match(quote + quote))) {
95
+ state.tokenize = null;
96
+ break;
97
+ }
98
+ escaped = !escaped && next == "\\";
99
+ }
100
+ return "string";
101
+ }
102
+ state.tokenize = tokenStringHelper;
103
+ return tokenStringHelper(stream, state);
104
+ }
105
+
106
+ function tokenInterpolation(stream, state) {
107
+ stream.eat("$");
108
+ if (stream.eat("{")) {
109
+ // let clike handle the content of ${...},
110
+ // we take over again when "}" appears (see hooks).
111
+ state.tokenize = null;
112
+ } else {
113
+ state.tokenize = tokenInterpolationIdentifier;
114
+ }
115
+ return null;
116
+ }
117
+
118
+ function tokenInterpolationIdentifier(stream, state) {
119
+ stream.eatWhile(/[\w_]/);
120
+ state.tokenize = popInterpolationStack(state);
121
+ return "variable";
122
+ }
123
+
44
124
  CodeMirror.registerHelper("hintWords", "application/dart", keywords.concat(atoms).concat(builtins));
45
125
 
46
126
  // This is needed to make loading through meta.js work.
@@ -191,13 +191,20 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
191
191
  pass.apply(null, arguments);
192
192
  return true;
193
193
  }
194
+ function inList(name, list) {
195
+ for (var v = list; v; v = v.next)
196
+ if (v.name == name) return true;
197
+ return false;
198
+ }
194
199
  function register(varname) {
195
200
  var state = cx.state;
196
201
  if (state.context) {
197
202
  cx.marked = "def";
198
- for (var v = state.localVars; v; v = v.next)
199
- if (v.name == varname) return;
203
+ if (inList(varname, state.localVars)) return;
200
204
  state.localVars = {name: varname, next: state.localVars};
205
+ } else if (state.globalVars) {
206
+ if (inList(varname, state.globalVars)) return;
207
+ state.globalVars = {name: varname, next: state.globalVars};
201
208
  }
202
209
  }
203
210
 
@@ -380,11 +387,10 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
380
387
  }
381
388
 
382
389
  // Interface
383
-
384
390
  return {
385
391
  startState: function(basecolumn) {
386
392
  var defaulttypes = ["Int", "Float", "String", "Void", "Std", "Bool", "Dynamic", "Array"];
387
- return {
393
+ var state = {
388
394
  tokenize: haxeTokenBase,
389
395
  reAllowed: true,
390
396
  kwAllowed: true,
@@ -395,6 +401,9 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
395
401
  context: parserConfig.localVars && {vars: parserConfig.localVars},
396
402
  indented: 0
397
403
  };
404
+ if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
405
+ state.globalVars = parserConfig.globalVars;
406
+ return state;
398
407
  },
399
408
 
400
409
  token: function(stream, state) {