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" |
}; |