codemirror-rails 4.6 → 4.7

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +24 -25
  4. data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +1 -1
  5. data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +4 -1
  6. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +7 -6
  7. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +21 -8
  8. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +54 -20
  9. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +10 -15
  10. data/vendor/assets/javascripts/codemirror/addons/mode/simple.js +210 -0
  11. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode-standalone.js +5 -1
  12. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.node.js +2 -4
  13. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +425 -554
  14. data/vendor/assets/javascripts/codemirror/modes/clike.js +28 -5
  15. data/vendor/assets/javascripts/codemirror/modes/clojure.js +5 -3
  16. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +8 -7
  17. data/vendor/assets/javascripts/codemirror/modes/d.js +1 -1
  18. data/vendor/assets/javascripts/codemirror/modes/dtd.js +1 -1
  19. data/vendor/assets/javascripts/codemirror/modes/gherkin.js +1 -1
  20. data/vendor/assets/javascripts/codemirror/modes/go.js +1 -1
  21. data/vendor/assets/javascripts/codemirror/modes/haskell.js +1 -1
  22. data/vendor/assets/javascripts/codemirror/modes/javascript.js +3 -3
  23. data/vendor/assets/javascripts/codemirror/modes/julia.js +1 -1
  24. data/vendor/assets/javascripts/codemirror/modes/markdown.js +4 -3
  25. data/vendor/assets/javascripts/codemirror/modes/octave.js +1 -1
  26. data/vendor/assets/javascripts/codemirror/modes/perl.js +2 -2
  27. data/vendor/assets/javascripts/codemirror/modes/php.js +37 -44
  28. data/vendor/assets/javascripts/codemirror/modes/python.js +17 -4
  29. data/vendor/assets/javascripts/codemirror/modes/ruby.js +12 -11
  30. data/vendor/assets/javascripts/codemirror/modes/rust.js +2 -2
  31. data/vendor/assets/javascripts/codemirror/modes/smartymixed.js +5 -1
  32. data/vendor/assets/javascripts/codemirror/modes/sql.js +2 -1
  33. data/vendor/assets/javascripts/codemirror/modes/stex.js +2 -1
  34. data/vendor/assets/javascripts/codemirror/modes/tcl.js +1 -1
  35. data/vendor/assets/javascripts/codemirror/modes/textile.js +553 -0
  36. data/vendor/assets/javascripts/codemirror/modes/tornado.js +68 -0
  37. data/vendor/assets/javascripts/codemirror/modes/verilog.js +14 -9
  38. data/vendor/assets/stylesheets/codemirror.css +1 -1
  39. data/vendor/assets/stylesheets/codemirror/themes/base16-dark.css +2 -2
  40. data/vendor/assets/stylesheets/codemirror/themes/mdn-like.css +1 -1
  41. metadata +4 -1
@@ -20,7 +20,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
20
20
  blockKeywords = parserConfig.blockKeywords || {},
21
21
  atoms = parserConfig.atoms || {},
22
22
  hooks = parserConfig.hooks || {},
23
- multiLineStrings = parserConfig.multiLineStrings;
23
+ multiLineStrings = parserConfig.multiLineStrings,
24
+ indentStatements = parserConfig.indentStatements !== false;
24
25
  var isOperatorChar = /[+\-*&%=<>!?|\/]/;
25
26
 
26
27
  var curPunc;
@@ -57,7 +58,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
57
58
  stream.eatWhile(isOperatorChar);
58
59
  return "operator";
59
60
  }
60
- stream.eatWhile(/[\w\$_]/);
61
+ stream.eatWhile(/[\w\$_\xa1-\uffff]/);
61
62
  var cur = stream.current();
62
63
  if (keywords.propertyIsEnumerable(cur)) {
63
64
  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
@@ -151,7 +152,9 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
151
152
  while (ctx.type == "statement") ctx = popContext(state);
152
153
  }
153
154
  else if (curPunc == ctx.type) popContext(state);
154
- else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
155
+ else if (indentStatements &&
156
+ (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') ||
157
+ (ctx.type == "statement" && curPunc == "newstatement")))
155
158
  pushContext(state, stream.column(), "statement");
156
159
  state.startOfLine = false;
157
160
  return style;
@@ -298,6 +301,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
298
301
  },
299
302
  modeProps: {fold: ["brace", "include"]}
300
303
  });
304
+
301
305
  def("text/x-java", {
302
306
  name: "clike",
303
307
  keywords: words("abstract assert boolean break byte case catch char class const continue default " +
@@ -315,6 +319,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
315
319
  },
316
320
  modeProps: {fold: ["brace", "import"]}
317
321
  });
322
+
318
323
  def("text/x-csharp", {
319
324
  name: "clike",
320
325
  keywords: words("abstract as base break case catch checked class const continue" +
@@ -341,6 +346,19 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
341
346
  }
342
347
  }
343
348
  });
349
+
350
+ function tokenTripleString(stream, state) {
351
+ var escaped = false;
352
+ while (!stream.eol()) {
353
+ if (!escaped && stream.match('"""')) {
354
+ state.tokenize = null;
355
+ break;
356
+ }
357
+ escaped = stream.next() != "\\" && !escaped;
358
+ }
359
+ return "string";
360
+ }
361
+
344
362
  def("text/x-scala", {
345
363
  name: "clike",
346
364
  keywords: words(
@@ -366,19 +384,24 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
366
384
  "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
367
385
  "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
368
386
  "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
369
-
370
-
371
387
  ),
372
388
  multiLineStrings: true,
373
389
  blockKeywords: words("catch class do else finally for forSome if match switch try while"),
374
390
  atoms: words("true false null"),
391
+ indentStatements: false,
375
392
  hooks: {
376
393
  "@": function(stream) {
377
394
  stream.eatWhile(/[\w\$_]/);
378
395
  return "meta";
396
+ },
397
+ '"': function(stream, state) {
398
+ if (!stream.match('""')) return false;
399
+ state.tokenize = tokenTripleString;
400
+ return state.tokenize(stream, state);
379
401
  }
380
402
  }
381
403
  });
404
+
382
405
  def(["x-shader/x-vertex", "x-shader/x-fragment"], {
383
406
  name: "clike",
384
407
  keywords: words("float int bool void " +
@@ -18,7 +18,7 @@
18
18
 
19
19
  CodeMirror.defineMode("clojure", function (options) {
20
20
  var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2",
21
- ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword";
21
+ ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword", VAR = "variable";
22
22
  var INDENT_WORD_SKIP = options.indentUnit || 2;
23
23
  var NORMAL_INDENT_UNIT = options.indentUnit || 2;
24
24
 
@@ -59,7 +59,7 @@ CodeMirror.defineMode("clojure", function (options) {
59
59
  sign: /[+-]/,
60
60
  exponent: /e/i,
61
61
  keyword_char: /[^\s\(\[\;\)\]]/,
62
- symbol: /[\w*+!\-\._?:<>\/]/
62
+ symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/
63
63
  };
64
64
 
65
65
  function stateStack(indent, type, prev) { // represents a state stack object
@@ -220,7 +220,9 @@ CodeMirror.defineMode("clojure", function (options) {
220
220
  returnType = BUILTIN;
221
221
  } else if (atoms && atoms.propertyIsEnumerable(stream.current())) {
222
222
  returnType = ATOM;
223
- } else returnType = null;
223
+ } else {
224
+ returnType = VAR;
225
+ }
224
226
  }
225
227
  }
226
228
 
@@ -22,7 +22,7 @@ CodeMirror.defineMode("coffeescript", function(conf) {
22
22
  return new RegExp("^((" + words.join(")|(") + "))\\b");
23
23
  }
24
24
 
25
- var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?)/;
25
+ var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/;
26
26
  var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/;
27
27
  var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;
28
28
  var properties = /^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*/;
@@ -34,7 +34,7 @@ CodeMirror.defineMode("coffeescript", function(conf) {
34
34
  "switch", "try", "catch", "finally", "class"];
35
35
  var commonKeywords = ["break", "by", "continue", "debugger", "delete",
36
36
  "do", "in", "of", "new", "return", "then",
37
- "this", "throw", "when", "until"];
37
+ "this", "@", "throw", "when", "until", "extends"];
38
38
 
39
39
  var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
40
40
 
@@ -217,7 +217,7 @@ CodeMirror.defineMode("coffeescript", function(conf) {
217
217
  type = type || "coffee";
218
218
  var offset = 0, align = false, alignOffset = null;
219
219
  for (var scope = state.scope; scope; scope = scope.prev) {
220
- if (scope.type === "coffee") {
220
+ if (scope.type === "coffee" || scope.type == "}") {
221
221
  offset = scope.offset + conf.indentUnit;
222
222
  break;
223
223
  }
@@ -278,7 +278,7 @@ CodeMirror.defineMode("coffeescript", function(conf) {
278
278
 
279
279
  // Handle scope changes.
280
280
  if (current === "return") {
281
- state.dedent += 1;
281
+ state.dedent = true;
282
282
  }
283
283
  if (((current === "->" || current === "=>") &&
284
284
  !state.lambda &&
@@ -310,9 +310,10 @@ CodeMirror.defineMode("coffeescript", function(conf) {
310
310
  if (state.scope.type == current)
311
311
  state.scope = state.scope.prev;
312
312
  }
313
- if (state.dedent > 0 && stream.eol() && state.scope.type == "coffee") {
314
- if (state.scope.prev) state.scope = state.scope.prev;
315
- state.dedent -= 1;
313
+ if (state.dedent && stream.eol()) {
314
+ if (state.scope.type == "coffee" && state.scope.prev)
315
+ state.scope = state.scope.prev;
316
+ state.dedent = false;
316
317
  }
317
318
 
318
319
  return style;
@@ -60,7 +60,7 @@ CodeMirror.defineMode("d", function(config, parserConfig) {
60
60
  stream.eatWhile(isOperatorChar);
61
61
  return "operator";
62
62
  }
63
- stream.eatWhile(/[\w\$_]/);
63
+ stream.eatWhile(/[\w\$_\xa1-\uffff]/);
64
64
  var cur = stream.current();
65
65
  if (keywords.propertyIsEnumerable(cur)) {
66
66
  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
@@ -4,7 +4,7 @@
4
4
  /*
5
5
  DTD mode
6
6
  Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>
7
- Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues
7
+ Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues
8
8
  GitHub: @peterkroon
9
9
  */
10
10
 
@@ -3,7 +3,7 @@
3
3
 
4
4
  /*
5
5
  Gherkin mode - http://www.cukes.info/
6
- Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues
6
+ Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues
7
7
  */
8
8
 
9
9
  // Following Objs from Brackets implementation: https://github.com/tregusti/brackets-gherkin/blob/master/main.js
@@ -71,7 +71,7 @@ CodeMirror.defineMode("go", function(config) {
71
71
  stream.eatWhile(isOperatorChar);
72
72
  return "operator";
73
73
  }
74
- stream.eatWhile(/[\w\$_]/);
74
+ stream.eatWhile(/[\w\$_\xa1-\uffff]/);
75
75
  var cur = stream.current();
76
76
  if (keywords.propertyIsEnumerable(cur)) {
77
77
  if (cur == "case" || cur == "default") curPunc = "case";
@@ -24,7 +24,7 @@ CodeMirror.defineMode("haskell", function(_config, modeConfig) {
24
24
  var digitRE = /\d/;
25
25
  var hexitRE = /[0-9A-Fa-f]/;
26
26
  var octitRE = /[0-7]/;
27
- var idRE = /[a-z_A-Z0-9']/;
27
+ var idRE = /[a-z_A-Z0-9'\xa1-\uffff]/;
28
28
  var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/;
29
29
  var specialRE = /[(),;[\]`{}]/;
30
30
  var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer
@@ -19,7 +19,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
19
19
  var jsonldMode = parserConfig.jsonld;
20
20
  var jsonMode = parserConfig.json || jsonldMode;
21
21
  var isTS = parserConfig.typescript;
22
- var wordRE = parserConfig.wordCharacters || /[\w$]/;
22
+ var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
23
23
 
24
24
  // Tokenizer
25
25
 
@@ -590,7 +590,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
590
590
  }
591
591
  function maybeArrayComprehension(type) {
592
592
  if (type == "for") return pass(comprehension, expect("]"));
593
- if (type == ",") return cont(commasep(expressionNoComma, "]"));
593
+ if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
594
594
  return pass(commasep(expressionNoComma, "]"));
595
595
  }
596
596
  function comprehension(type) {
@@ -656,7 +656,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
656
656
  else return lexical.indented + (closing ? 0 : indentUnit);
657
657
  },
658
658
 
659
- electricChars: ":{}",
659
+ electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
660
660
  blockCommentStart: jsonMode ? null : "/*",
661
661
  blockCommentEnd: jsonMode ? null : "*/",
662
662
  lineComment: jsonMode ? null : "//",
@@ -20,7 +20,7 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
20
20
 
21
21
  var operators = parserConf.operators || /^\.?[|&^\\%*+\-<>!=\/]=?|\?|~|:|\$|\.[<>]|<<=?|>>>?=?|\.[<>=]=|->?|\/\/|\bin\b/;
22
22
  var delimiters = parserConf.delimiters || /^[;,()[\]{}]/;
23
- var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*!*/;
23
+ var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*!*/;
24
24
  var blockOpeners = ["begin", "function", "type", "immutable", "let", "macro", "for", "while", "quote", "if", "else", "elseif", "try", "finally", "catch", "do"];
25
25
  var blockClosers = ["end", "else", "elseif", "catch", "finally"];
26
26
  var keywordList = ['if', 'else', 'elseif', 'while', 'for', 'begin', 'let', 'end', 'do', 'try', 'catch', 'finally', 'return', 'break', 'continue', 'global', 'local', 'const', 'export', 'import', 'importall', 'using', 'function', 'macro', 'module', 'baremodule', 'type', 'immutable', 'quote', 'typealias', 'abstract', 'bitstype', 'ccall'];
@@ -700,14 +700,15 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
700
700
  state.formatting = false;
701
701
 
702
702
  if (stream.sol()) {
703
- var forceBlankLine = stream.match(/^\s*$/, true) || state.header;
703
+ var forceBlankLine = !!state.header;
704
704
 
705
705
  // Reset state.header
706
706
  state.header = 0;
707
707
 
708
- if (forceBlankLine) {
708
+ if (stream.match(/^\s*$/, true) || forceBlankLine) {
709
709
  state.prevLineHasContent = false;
710
- return blankLine(state);
710
+ blankLine(state);
711
+ return forceBlankLine ? this.token(stream, state) : null;
711
712
  } else {
712
713
  state.prevLineHasContent = state.thisLineHasContent;
713
714
  state.thisLineHasContent = true;
@@ -22,7 +22,7 @@ CodeMirror.defineMode("octave", function() {
22
22
  var doubleDelimiters = new RegExp("^((!=)|(\\+=)|(\\-=)|(\\*=)|(/=)|(&=)|(\\|=)|(\\^=))");
23
23
  var tripleDelimiters = new RegExp("^((>>=)|(<<=))");
24
24
  var expressionEnd = new RegExp("^[\\]\\)]");
25
- var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
25
+ var identifiers = new RegExp("^[_A-Za-z\xa1-\uffff][_A-Za-z0-9\xa1-\uffff]*");
26
26
 
27
27
  var builtins = wordRegexp([
28
28
  'error', 'eval', 'function', 'abs', 'acos', 'atan', 'asin', 'cos',
@@ -788,8 +788,8 @@ CodeMirror.defineMode("perl",function(){
788
788
  style:null,
789
789
  tail:null};},
790
790
  token:function(stream,state){
791
- return (state.tokenize||tokenPerl)(stream,state);},
792
- electricChars:"{}"};});
791
+ return (state.tokenize||tokenPerl)(stream,state);}
792
+ };});
793
793
 
794
794
  CodeMirror.registerHelper("wordChars", "perl", /[\w$]/);
795
795
 
@@ -16,32 +16,24 @@
16
16
  for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
17
17
  return obj;
18
18
  }
19
- function heredoc(delim) {
20
- return function(stream, state) {
21
- if (stream.match(delim)) state.tokenize = null;
22
- else stream.skipToEnd();
23
- return "string";
24
- };
25
- }
26
19
 
27
20
  // Helper for stringWithEscapes
28
- function matchSequence(list) {
29
- if (list.length == 0) return stringWithEscapes;
21
+ function matchSequence(list, end) {
22
+ if (list.length == 0) return stringWithEscapes(end);
30
23
  return function (stream, state) {
31
24
  var patterns = list[0];
32
25
  for (var i = 0; i < patterns.length; i++) if (stream.match(patterns[i][0])) {
33
- state.tokenize = matchSequence(list.slice(1));
26
+ state.tokenize = matchSequence(list.slice(1), end);
34
27
  return patterns[i][1];
35
28
  }
36
- state.tokenize = stringWithEscapes;
29
+ state.tokenize = stringWithEscapes(end);
37
30
  return "string";
38
31
  };
39
32
  }
40
- function stringWithEscapes(stream, state) {
41
- var escaped = false, next, end = false;
42
-
43
- if (stream.current() == '"') return "string";
44
-
33
+ function stringWithEscapes(closing) {
34
+ return function(stream, state) { return stringWithEscapes_(stream, state, closing); };
35
+ }
36
+ function stringWithEscapes_(stream, state, closing) {
45
37
  // "Complex" syntax
46
38
  if (stream.match("${", false) || stream.match("{$", false)) {
47
39
  state.tokenize = null;
@@ -49,7 +41,7 @@
49
41
  }
50
42
 
51
43
  // Simple syntax
52
- if (stream.match(/\$[a-zA-Z_][a-zA-Z0-9_]*/)) {
44
+ if (stream.match(/^\$[a-zA-Z_][a-zA-Z0-9_]*/)) {
53
45
  // After the variable name there may appear array or object operator.
54
46
  if (stream.match("[", false)) {
55
47
  // Match array operator
@@ -59,31 +51,29 @@
59
51
  [/\$[a-zA-Z_][a-zA-Z0-9_]*/, "variable-2"],
60
52
  [/[\w\$]+/, "variable"]],
61
53
  [["]", null]]
62
- ]);
54
+ ], closing);
63
55
  }
64
56
  if (stream.match(/\-\>\w/, false)) {
65
57
  // Match object operator
66
58
  state.tokenize = matchSequence([
67
59
  [["->", null]],
68
60
  [[/[\w]+/, "variable"]]
69
- ]);
61
+ ], closing);
70
62
  }
71
63
  return "variable-2";
72
64
  }
73
65
 
66
+ var escaped = false;
74
67
  // Normal string
75
- while (
76
- !stream.eol() &&
77
- (!stream.match("{$", false)) &&
78
- (!stream.match(/(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/, false) || escaped)
79
- ) {
80
- next = stream.next();
81
- if (!escaped && next == '"') { end = true; break; }
82
- escaped = !escaped && next == "\\";
83
- }
84
- if (end) {
85
- state.tokenize = null;
86
- state.phpEncapsStack.pop();
68
+ while (!stream.eol() &&
69
+ (escaped || (!stream.match("{$", false) &&
70
+ !stream.match(/^(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/, false)))) {
71
+ if (!escaped && stream.match(closing)) {
72
+ state.tokenize = null;
73
+ state.tokStack.pop(); state.tokStack.pop();
74
+ break;
75
+ }
76
+ escaped = stream.next() == "\\" && !escaped;
87
77
  }
88
78
  return "string";
89
79
  }
@@ -115,8 +105,12 @@
115
105
  "<": function(stream, state) {
116
106
  if (stream.match(/<</)) {
117
107
  stream.eatWhile(/[\w\.]/);
118
- state.tokenize = heredoc(stream.current().slice(3));
119
- return state.tokenize(stream, state);
108
+ var delim = stream.current().slice(3);
109
+ if (delim) {
110
+ (state.tokStack || (state.tokStack = [])).push(delim, 0);
111
+ state.tokenize = stringWithEscapes(delim);
112
+ return "string";
113
+ }
120
114
  }
121
115
  return false;
122
116
  },
@@ -131,22 +125,21 @@
131
125
  }
132
126
  return false;
133
127
  },
134
- '"': function(stream, state) {
135
- if (!state.phpEncapsStack)
136
- state.phpEncapsStack = [];
137
- state.phpEncapsStack.push(0);
138
- state.tokenize = stringWithEscapes;
139
- return state.tokenize(stream, state);
128
+ '"': function(_stream, state) {
129
+ (state.tokStack || (state.tokStack = [])).push('"', 0);
130
+ state.tokenize = stringWithEscapes('"');
131
+ return "string";
140
132
  },
141
133
  "{": function(_stream, state) {
142
- if (state.phpEncapsStack && state.phpEncapsStack.length > 0)
143
- state.phpEncapsStack[state.phpEncapsStack.length - 1]++;
134
+ if (state.tokStack && state.tokStack.length)
135
+ state.tokStack[state.tokStack.length - 1]++;
144
136
  return false;
145
137
  },
146
138
  "}": function(_stream, state) {
147
- if (state.phpEncapsStack && state.phpEncapsStack.length > 0)
148
- if (--state.phpEncapsStack[state.phpEncapsStack.length - 1] == 0)
149
- state.tokenize = stringWithEscapes;
139
+ if (state.tokStack && state.tokStack.length > 0 &&
140
+ !--state.tokStack[state.tokStack.length - 1]) {
141
+ state.tokenize = stringWithEscapes(state.tokStack[state.tokStack.length - 2]);
142
+ }
150
143
  return false;
151
144
  }
152
145
  }
@@ -48,12 +48,20 @@
48
48
  CodeMirror.defineMode("python", function(conf, parserConf) {
49
49
  var ERRORCLASS = "error";
50
50
 
51
- var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
52
51
  var singleDelimiters = parserConf.singleDelimiters || new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]");
53
52
  var doubleOperators = parserConf.doubleOperators || new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
54
53
  var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
55
54
  var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
56
- var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
55
+
56
+ if (parserConf.version && parseInt(parserConf.version, 10) == 3){
57
+ // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator
58
+ var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!@]");
59
+ var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*");
60
+ } else {
61
+ var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
62
+ var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
63
+ }
64
+
57
65
  var hangingIndent = parserConf.hangingIndent || conf.indentUnit;
58
66
 
59
67
  var myKeywords = commonKeywords, myBuiltins = commonBuiltins;
@@ -252,8 +260,13 @@
252
260
  }
253
261
 
254
262
  // Handle decorators
255
- if (current == "@")
256
- return stream.match(identifiers, false) ? "meta" : ERRORCLASS;
263
+ if (current == "@"){
264
+ if(parserConf.version && parseInt(parserConf.version, 10) == 3){
265
+ return stream.match(identifiers, false) ? "meta" : "operator";
266
+ } else {
267
+ return stream.match(identifiers, false) ? "meta" : ERRORCLASS;
268
+ }
269
+ }
257
270
 
258
271
  if ((style == "variable" || style == "builtin")
259
272
  && state.lastStyle == "meta")