| Index: third_party/WebKit/Source/devtools/front_end/cm_modes/python.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/python.js b/third_party/WebKit/Source/devtools/front_end/cm_modes/python.js
|
| index 45dd63ba48a365fc3776467fc674b97135de75e1..be65ad76876c7723da96cae9f14c02ddc1e8a873 100644
|
| --- a/third_party/WebKit/Source/devtools/front_end/cm_modes/python.js
|
| +++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/python.js
|
| @@ -15,12 +15,12 @@
|
| return new RegExp("^((" + words.join(")|(") + "))\\b");
|
| }
|
|
|
| - var wordOperators = wordRegexp(["and", "or", "not", "is", "in"]);
|
| + var wordOperators = wordRegexp(["and", "or", "not", "is"]);
|
| var commonKeywords = ["as", "assert", "break", "class", "continue",
|
| "def", "del", "elif", "else", "except", "finally",
|
| "for", "from", "global", "if", "import",
|
| "lambda", "pass", "raise", "return",
|
| - "try", "while", "with", "yield"];
|
| + "try", "while", "with", "yield", "in"];
|
| var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr",
|
| "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod",
|
| "enumerate", "eval", "filter", "float", "format", "frozenset",
|
| @@ -32,13 +32,6 @@
|
| "sorted", "staticmethod", "str", "sum", "super", "tuple",
|
| "type", "vars", "zip", "__import__", "NotImplemented",
|
| "Ellipsis", "__debug__"];
|
| - var py2 = {builtins: ["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
|
| - "file", "intern", "long", "raw_input", "reduce", "reload",
|
| - "unichr", "unicode", "xrange", "False", "True", "None"],
|
| - keywords: ["exec", "print"]};
|
| - var py3 = {builtins: ["ascii", "bytes", "exec", "print"],
|
| - keywords: ["nonlocal", "False", "True", "None"]};
|
| -
|
| CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins));
|
|
|
| function top(state) {
|
| @@ -48,28 +41,35 @@
|
| CodeMirror.defineMode("python", function(conf, parserConf) {
|
| var ERRORCLASS = "error";
|
|
|
| - var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
|
| - var singleDelimiters = parserConf.singleDelimiters || new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]");
|
| - var doubleOperators = parserConf.doubleOperators || new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
|
| - var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
|
| - var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
|
| - var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
|
| + var singleDelimiters = parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.]/;
|
| + var doubleOperators = parserConf.doubleOperators || /^([!<>]==|<>|<<|>>|\/\/|\*\*)/;
|
| + var doubleDelimiters = parserConf.doubleDelimiters || /^(\+=|\-=|\*=|%=|\/=|&=|\|=|\^=)/;
|
| + var tripleDelimiters = parserConf.tripleDelimiters || /^(\/\/=|>>=|<<=|\*\*=)/;
|
| +
|
| var hangingIndent = parserConf.hangingIndent || conf.indentUnit;
|
|
|
| var myKeywords = commonKeywords, myBuiltins = commonBuiltins;
|
| - if(parserConf.extra_keywords != undefined){
|
| + if (parserConf.extra_keywords != undefined)
|
| myKeywords = myKeywords.concat(parserConf.extra_keywords);
|
| - }
|
| - if(parserConf.extra_builtins != undefined){
|
| +
|
| + if (parserConf.extra_builtins != undefined)
|
| myBuiltins = myBuiltins.concat(parserConf.extra_builtins);
|
| - }
|
| - if (parserConf.version && parseInt(parserConf.version, 10) == 3) {
|
| - myKeywords = myKeywords.concat(py3.keywords);
|
| - myBuiltins = myBuiltins.concat(py3.builtins);
|
| - var stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i");
|
| +
|
| + var py3 = parserConf.version && parseInt(parserConf.version, 10) == 3
|
| + if (py3) {
|
| + // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator
|
| + var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!@]/;
|
| + var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/;
|
| + myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]);
|
| + myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]);
|
| + var stringPrefixes = new RegExp("^(([rbuf]|(br))?('{3}|\"{3}|['\"]))", "i");
|
| } else {
|
| - myKeywords = myKeywords.concat(py2.keywords);
|
| - myBuiltins = myBuiltins.concat(py2.builtins);
|
| + var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!]/;
|
| + var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/;
|
| + myKeywords = myKeywords.concat(["exec", "print"]);
|
| + myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
|
| + "file", "intern", "long", "raw_input", "reduce", "reload",
|
| + "unichr", "unicode", "xrange", "False", "True", "None"]);
|
| var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
|
| }
|
| var keywords = wordRegexp(myKeywords);
|
| @@ -77,13 +77,14 @@
|
|
|
| // tokenizers
|
| function tokenBase(stream, state) {
|
| + if (stream.sol()) state.indent = stream.indentation()
|
| // Handle scope changes
|
| if (stream.sol() && top(state).type == "py") {
|
| var scopeOffset = top(state).offset;
|
| if (stream.eatSpace()) {
|
| var lineOffset = stream.indentation();
|
| if (lineOffset > scopeOffset)
|
| - pushScope(stream, state, "py");
|
| + pushPyScope(state);
|
| else if (lineOffset < scopeOffset && dedent(stream, state))
|
| state.errorToken = true;
|
| return null;
|
| @@ -152,17 +153,18 @@
|
|
|
| // Handle operators and Delimiters
|
| if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters))
|
| - return null;
|
| + return "punctuation";
|
|
|
| - if (stream.match(doubleOperators)
|
| - || stream.match(singleOperators)
|
| - || stream.match(wordOperators))
|
| + if (stream.match(doubleOperators) || stream.match(singleOperators))
|
| return "operator";
|
|
|
| if (stream.match(singleDelimiters))
|
| - return null;
|
| + return "punctuation";
|
|
|
| - if (stream.match(keywords))
|
| + if (state.lastToken == "." && stream.match(identifiers))
|
| + return "property";
|
| +
|
| + if (stream.match(keywords) || stream.match(wordOperators))
|
| return "keyword";
|
|
|
| if (stream.match(builtins))
|
| @@ -215,21 +217,23 @@
|
| return tokenString;
|
| }
|
|
|
| - function pushScope(stream, state, type) {
|
| - var offset = 0, align = null;
|
| - if (type == "py") {
|
| - while (top(state).type != "py")
|
| - state.scopes.pop();
|
| - }
|
| - offset = top(state).offset + (type == "py" ? conf.indentUnit : hangingIndent);
|
| - if (type != "py" && !stream.match(/^(\s|#.*)*$/, false))
|
| - align = stream.column() + 1;
|
| - state.scopes.push({offset: offset, type: type, align: align});
|
| + function pushPyScope(state) {
|
| + while (top(state).type != "py") state.scopes.pop()
|
| + state.scopes.push({offset: top(state).offset + conf.indentUnit,
|
| + type: "py",
|
| + align: null})
|
| + }
|
| +
|
| + function pushBracketScope(stream, state, type) {
|
| + var align = stream.match(/^([\s\[\{\(]|#.*)*$/, false) ? null : stream.column() + 1
|
| + state.scopes.push({offset: state.indent + hangingIndent,
|
| + type: type,
|
| + align: align})
|
| }
|
|
|
| function dedent(stream, state) {
|
| var indented = stream.indentation();
|
| - while (top(state).offset > indented) {
|
| + while (state.scopes.length > 1 && top(state).offset > indented) {
|
| if (top(state).type != "py") return true;
|
| state.scopes.pop();
|
| }
|
| @@ -237,26 +241,19 @@
|
| }
|
|
|
| function tokenLexer(stream, state) {
|
| + if (stream.sol()) state.beginningOfLine = true;
|
| +
|
| var style = state.tokenize(stream, state);
|
| var current = stream.current();
|
|
|
| - // Handle '.' connected identifiers
|
| - if (current == ".") {
|
| - style = stream.match(identifiers, false) ? null : ERRORCLASS;
|
| - if (style == null && state.lastStyle == "meta") {
|
| - // Apply 'meta' style to '.' connected identifiers when
|
| - // appropriate.
|
| - style = "meta";
|
| - }
|
| - return style;
|
| - }
|
| -
|
| // Handle decorators
|
| - if (current == "@")
|
| - return stream.match(identifiers, false) ? "meta" : ERRORCLASS;
|
| + if (state.beginningOfLine && current == "@")
|
| + return stream.match(identifiers, false) ? "meta" : py3 ? "operator" : ERRORCLASS;
|
| +
|
| + if (/\S/.test(current)) state.beginningOfLine = false;
|
|
|
| if ((style == "variable" || style == "builtin")
|
| - && state.lastStyle == "meta")
|
| + && state.lastToken == "meta")
|
| style = "meta";
|
|
|
| // Handle scope changes.
|
| @@ -265,15 +262,15 @@
|
|
|
| if (current == "lambda") state.lambda = true;
|
| if (current == ":" && !state.lambda && top(state).type == "py")
|
| - pushScope(stream, state, "py");
|
| + pushPyScope(state);
|
|
|
| var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1;
|
| if (delimiter_index != -1)
|
| - pushScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
|
| + pushBracketScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
|
|
|
| delimiter_index = "])}".indexOf(current);
|
| if (delimiter_index != -1) {
|
| - if (top(state).type == current) state.scopes.pop();
|
| + if (top(state).type == current) state.indent = state.scopes.pop().offset - hangingIndent
|
| else return ERRORCLASS;
|
| }
|
| if (state.dedent > 0 && stream.eol() && top(state).type == "py") {
|
| @@ -289,7 +286,7 @@
|
| return {
|
| tokenize: tokenBase,
|
| scopes: [{offset: basecolumn || 0, type: "py", align: null}],
|
| - lastStyle: null,
|
| + indent: basecolumn || 0,
|
| lastToken: null,
|
| lambda: false,
|
| dedent: 0
|
| @@ -301,11 +298,9 @@
|
| if (addErr) state.errorToken = false;
|
| var style = tokenLexer(stream, state);
|
|
|
| - state.lastStyle = style;
|
| -
|
| - var current = stream.current();
|
| - if (current && style)
|
| - state.lastToken = current;
|
| + if (style && style != "comment")
|
| + state.lastToken = (style == "keyword" || style == "punctuation") ? stream.current() : style;
|
| + if (style == "punctuation") style = null;
|
|
|
| if (stream.eol() && state.lambda)
|
| state.lambda = false;
|
| @@ -316,16 +311,15 @@
|
| if (state.tokenize != tokenBase)
|
| return state.tokenize.isString ? CodeMirror.Pass : 0;
|
|
|
| - var scope = top(state);
|
| - var closing = textAfter && textAfter.charAt(0) == scope.type;
|
| + var scope = top(state), closing = scope.type == textAfter.charAt(0)
|
| if (scope.align != null)
|
| - return scope.align - (closing ? 1 : 0);
|
| - else if (closing && state.scopes.length > 1)
|
| - return state.scopes[state.scopes.length - 2].offset;
|
| + return scope.align - (closing ? 1 : 0)
|
| else
|
| - return scope.offset;
|
| + return scope.offset - (closing ? hangingIndent : 0)
|
| },
|
|
|
| + electricInput: /^\s*[\}\]\)]$/,
|
| + closeBrackets: {triples: "'\""},
|
| lineComment: "#",
|
| fold: "indent"
|
| };
|
|
|