codemirror-rails 4.6 → 4.7

Sign up to get free protection for your applications and to get access to all the features.
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")