codemirror-rails 5.7 → 5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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) {