PageRenderTime 60ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/static/ace-editor/src-noconflict/mode-python.js

https://bitbucket.org/berlotto/asciiblog
JavaScript | 397 lines | 321 code | 36 blank | 40 comment | 36 complexity | 0cb415628cc5201e9212d4ce6b4b295c MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is Ajax.org Code Editor (ACE).
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Ajax.org B.V.
  18. * Portions created by the Initial Developer are Copyright (C) 2010
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * Fabian Jakobs <fabian AT ajax DOT org>
  23. * Colin Gourlay <colin DOT j DOT gourlay AT gmail DOT com>
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * either the GNU General Public License Version 2 or later (the "GPL"), or
  27. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. * in which case the provisions of the GPL or the LGPL are applicable instead
  29. * of those above. If you wish to allow use of your version of this file only
  30. * under the terms of either the GPL or the LGPL, and not to allow others to
  31. * use your version of this file under the terms of the MPL, indicate your
  32. * decision by deleting the provisions above and replace them with the notice
  33. * and other provisions required by the GPL or the LGPL. If you do not delete
  34. * the provisions above, a recipient may use your version of this file under
  35. * the terms of any one of the MPL, the GPL or the LGPL.
  36. *
  37. * ***** END LICENSE BLOCK ***** */
  38. ace.define('ace/mode/python', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/python_highlight_rules', 'ace/mode/folding/pythonic', 'ace/range'], function(require, exports, module) {
  39. var oop = require("../lib/oop");
  40. var TextMode = require("./text").Mode;
  41. var Tokenizer = require("../tokenizer").Tokenizer;
  42. var PythonHighlightRules = require("./python_highlight_rules").PythonHighlightRules;
  43. var PythonFoldMode = require("./folding/pythonic").FoldMode;
  44. var Range = require("../range").Range;
  45. var Mode = function() {
  46. this.$tokenizer = new Tokenizer(new PythonHighlightRules().getRules());
  47. this.foldingRules = new PythonFoldMode("\\:");
  48. };
  49. oop.inherits(Mode, TextMode);
  50. (function() {
  51. this.toggleCommentLines = function(state, doc, startRow, endRow) {
  52. var outdent = true;
  53. var re = /^(\s*)#/;
  54. for (var i=startRow; i<= endRow; i++) {
  55. if (!re.test(doc.getLine(i))) {
  56. outdent = false;
  57. break;
  58. }
  59. }
  60. if (outdent) {
  61. var deleteRange = new Range(0, 0, 0, 0);
  62. for (var i=startRow; i<= endRow; i++)
  63. {
  64. var line = doc.getLine(i);
  65. var m = line.match(re);
  66. deleteRange.start.row = i;
  67. deleteRange.end.row = i;
  68. deleteRange.end.column = m[0].length;
  69. doc.replace(deleteRange, m[1]);
  70. }
  71. }
  72. else {
  73. doc.indentRows(startRow, endRow, "#");
  74. }
  75. };
  76. this.getNextLineIndent = function(state, line, tab) {
  77. var indent = this.$getIndent(line);
  78. var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
  79. var tokens = tokenizedLine.tokens;
  80. if (tokens.length && tokens[tokens.length-1].type == "comment") {
  81. return indent;
  82. }
  83. if (state == "start") {
  84. var match = line.match(/^.*[\{\(\[\:]\s*$/);
  85. if (match) {
  86. indent += tab;
  87. }
  88. }
  89. return indent;
  90. };
  91. var outdents = {
  92. "pass": 1,
  93. "return": 1,
  94. "raise": 1,
  95. "break": 1,
  96. "continue": 1
  97. };
  98. this.checkOutdent = function(state, line, input) {
  99. if (input !== "\r\n" && input !== "\r" && input !== "\n")
  100. return false;
  101. var tokens = this.$tokenizer.getLineTokens(line.trim(), state).tokens;
  102. if (!tokens)
  103. return false;
  104. // ignore trailing comments
  105. do {
  106. var last = tokens.pop();
  107. } while (last && (last.type == "comment" || (last.type == "text" && last.value.match(/^\s+$/))));
  108. if (!last)
  109. return false;
  110. return (last.type == "keyword" && outdents[last.value]);
  111. };
  112. this.autoOutdent = function(state, doc, row) {
  113. // outdenting in python is slightly different because it always applies
  114. // to the next line and only of a new line is inserted
  115. row += 1;
  116. var indent = this.$getIndent(doc.getLine(row));
  117. var tab = doc.getTabString();
  118. if (indent.slice(-tab.length) == tab)
  119. doc.remove(new Range(row, indent.length-tab.length, row, indent.length));
  120. };
  121. }).call(Mode.prototype);
  122. exports.Mode = Mode;
  123. });
  124. ace.define('ace/mode/python_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
  125. var oop = require("../lib/oop");
  126. var lang = require("../lib/lang");
  127. var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
  128. var PythonHighlightRules = function() {
  129. var keywords = lang.arrayToMap(
  130. ("and|as|assert|break|class|continue|def|del|elif|else|except|exec|" +
  131. "finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|" +
  132. "raise|return|try|while|with|yield").split("|")
  133. );
  134. var builtinConstants = lang.arrayToMap(
  135. ("True|False|None|NotImplemented|Ellipsis|__debug__").split("|")
  136. );
  137. var builtinFunctions = lang.arrayToMap(
  138. ("abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|" +
  139. "eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|" +
  140. "binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|" +
  141. "float|list|raw_input|unichr|callable|format|locals|reduce|unicode|" +
  142. "chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|" +
  143. "cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|" +
  144. "__import__|complex|hash|min|set|apply|delattr|help|next|setattr|" +
  145. "buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern").split("|")
  146. );
  147. var futureReserved = lang.arrayToMap(
  148. ("").split("|")
  149. );
  150. var strPre = "(?:r|u|ur|R|U|UR|Ur|uR)?";
  151. var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
  152. var octInteger = "(?:0[oO]?[0-7]+)";
  153. var hexInteger = "(?:0[xX][\\dA-Fa-f]+)";
  154. var binInteger = "(?:0[bB][01]+)";
  155. var integer = "(?:" + decimalInteger + "|" + octInteger + "|" + hexInteger + "|" + binInteger + ")";
  156. var exponent = "(?:[eE][+-]?\\d+)";
  157. var fraction = "(?:\\.\\d+)";
  158. var intPart = "(?:\\d+)";
  159. var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
  160. var exponentFloat = "(?:(?:" + pointFloat + "|" + intPart + ")" + exponent + ")";
  161. var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")";
  162. this.$rules = {
  163. "start" : [ {
  164. token : "comment",
  165. regex : "#.*$"
  166. }, {
  167. token : "string", // """ string
  168. regex : strPre + '"{3}(?:[^\\\\]|\\\\.)*?"{3}'
  169. }, {
  170. token : "string", // multi line """ string start
  171. merge : true,
  172. regex : strPre + '"{3}.*$',
  173. next : "qqstring"
  174. }, {
  175. token : "string", // " string
  176. regex : strPre + '"(?:[^\\\\]|\\\\.)*?"'
  177. }, {
  178. token : "string", // ''' string
  179. regex : strPre + "'{3}(?:[^\\\\]|\\\\.)*?'{3}"
  180. }, {
  181. token : "string", // multi line ''' string start
  182. merge : true,
  183. regex : strPre + "'{3}.*$",
  184. next : "qstring"
  185. }, {
  186. token : "string", // ' string
  187. regex : strPre + "'(?:[^\\\\]|\\\\.)*?'"
  188. }, {
  189. token : "constant.numeric", // imaginary
  190. regex : "(?:" + floatNumber + "|\\d+)[jJ]\\b"
  191. }, {
  192. token : "constant.numeric", // float
  193. regex : floatNumber
  194. }, {
  195. token : "constant.numeric", // long integer
  196. regex : integer + "[lL]\\b"
  197. }, {
  198. token : "constant.numeric", // integer
  199. regex : integer + "\\b"
  200. }, {
  201. token : function(value) {
  202. if (keywords.hasOwnProperty(value))
  203. return "keyword";
  204. else if (builtinConstants.hasOwnProperty(value))
  205. return "constant.language";
  206. else if (futureReserved.hasOwnProperty(value))
  207. return "invalid.illegal";
  208. else if (builtinFunctions.hasOwnProperty(value))
  209. return "support.function";
  210. else if (value == "debugger")
  211. return "invalid.deprecated";
  212. else
  213. return "identifier";
  214. },
  215. regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
  216. }, {
  217. token : "keyword.operator",
  218. regex : "\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="
  219. }, {
  220. token : "paren.lparen",
  221. regex : "[\\[\\(\\{]"
  222. }, {
  223. token : "paren.rparen",
  224. regex : "[\\]\\)\\}]"
  225. }, {
  226. token : "text",
  227. regex : "\\s+"
  228. } ],
  229. "qqstring" : [ {
  230. token : "string", // multi line """ string end
  231. regex : '(?:[^\\\\]|\\\\.)*?"{3}',
  232. next : "start"
  233. }, {
  234. token : "string",
  235. merge : true,
  236. regex : '.+'
  237. } ],
  238. "qstring" : [ {
  239. token : "string", // multi line ''' string end
  240. regex : "(?:[^\\\\]|\\\\.)*?'{3}",
  241. next : "start"
  242. }, {
  243. token : "string",
  244. merge : true,
  245. regex : '.+'
  246. } ]
  247. };
  248. };
  249. oop.inherits(PythonHighlightRules, TextHighlightRules);
  250. exports.PythonHighlightRules = PythonHighlightRules;
  251. });
  252. ace.define('ace/mode/folding/pythonic', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/folding/fold_mode'], function(require, exports, module) {
  253. var oop = require("../../lib/oop");
  254. var BaseFoldMode = require("./fold_mode").FoldMode;
  255. var FoldMode = exports.FoldMode = function(markers) {
  256. this.foldingStartMarker = new RegExp("([\\[{])(?:\\s*)$|(" + markers + ")(?:\\s*)(?:#.*)?$");
  257. };
  258. oop.inherits(FoldMode, BaseFoldMode);
  259. (function() {
  260. this.getFoldWidgetRange = function(session, foldStyle, row) {
  261. var line = session.getLine(row);
  262. var match = line.match(this.foldingStartMarker);
  263. if (match) {
  264. if (match[1])
  265. return this.openingBracketBlock(session, match[1], row, match.index);
  266. if (match[2])
  267. return this.indentationBlock(session, row, match.index + match[2].length);
  268. return this.indentationBlock(session, row);
  269. }
  270. }
  271. }).call(FoldMode.prototype);
  272. });
  273. ace.define('ace/mode/folding/fold_mode', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
  274. var Range = require("../../range").Range;
  275. var FoldMode = exports.FoldMode = function() {};
  276. (function() {
  277. this.foldingStartMarker = null;
  278. this.foldingStopMarker = null;
  279. // must return "" if there's no fold, to enable caching
  280. this.getFoldWidget = function(session, foldStyle, row) {
  281. var line = session.getLine(row);
  282. if (this.foldingStartMarker.test(line))
  283. return "start";
  284. if (foldStyle == "markbeginend"
  285. && this.foldingStopMarker
  286. && this.foldingStopMarker.test(line))
  287. return "end";
  288. return "";
  289. };
  290. this.getFoldWidgetRange = function(session, foldStyle, row) {
  291. return null;
  292. };
  293. this.indentationBlock = function(session, row, column) {
  294. var re = /\S/;
  295. var line = session.getLine(row);
  296. var startLevel = line.search(re);
  297. if (startLevel == -1)
  298. return;
  299. var startColumn = column || line.length;
  300. var maxRow = session.getLength();
  301. var startRow = row;
  302. var endRow = row;
  303. while (++row < maxRow) {
  304. var level = session.getLine(row).search(re);
  305. if (level == -1)
  306. continue;
  307. if (level <= startLevel)
  308. break;
  309. endRow = row;
  310. }
  311. if (endRow > startRow) {
  312. var endColumn = session.getLine(endRow).length;
  313. return new Range(startRow, startColumn, endRow, endColumn);
  314. }
  315. };
  316. this.openingBracketBlock = function(session, bracket, row, column, typeRe) {
  317. var start = {row: row, column: column + 1};
  318. var end = session.$findClosingBracket(bracket, start, typeRe);
  319. if (!end)
  320. return;
  321. var fw = session.foldWidgets[end.row];
  322. if (fw == null)
  323. fw = this.getFoldWidget(session, end.row);
  324. if (fw == "start" && end.row > start.row) {
  325. end.row --;
  326. end.column = session.getLine(end.row).length;
  327. }
  328. return Range.fromPoints(start, end);
  329. };
  330. }).call(FoldMode.prototype);
  331. });