From 6a65c061199c975bfc2aaf0eba3bd1ce2b391198 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 27 Sep 2012 09:34:31 -0400 Subject: [PATCH] added Ace editor --- ChangeLog | 2 + client.js | 10 +- lib/client/editor.js | 88 +- lib/client/editor/ace/ChangeLog.txt | 116 + lib/client/editor/ace/LICENSE | 476 + lib/client/editor/ace/README.md | 21 + lib/client/editor/ace/ace.js | 15689 ++++++++++++++++ lib/client/editor/ace/mode-coffee.js | 527 + lib/client/editor/ace/mode-javascript.js | 1069 ++ lib/client/editor/ace/mode-json.js | 588 + lib/client/editor/ace/theme-monokai.js | 194 + .../editor/ace/theme-tomorrow_night_blue.js | 213 + lib/client/editor/ace/worker-coffee.js | 7187 +++++++ lib/client/editor/ace/worker-javascript.js | 10417 ++++++++++ lib/client/editor/ace/worker-json.js | 2920 +++ lib/client/editor/ace_editor.js | 218 + 16 files changed, 39681 insertions(+), 54 deletions(-) create mode 100644 lib/client/editor/ace/ChangeLog.txt create mode 100644 lib/client/editor/ace/LICENSE create mode 100644 lib/client/editor/ace/README.md create mode 100644 lib/client/editor/ace/ace.js create mode 100644 lib/client/editor/ace/mode-coffee.js create mode 100644 lib/client/editor/ace/mode-javascript.js create mode 100644 lib/client/editor/ace/mode-json.js create mode 100644 lib/client/editor/ace/theme-monokai.js create mode 100644 lib/client/editor/ace/theme-tomorrow_night_blue.js create mode 100644 lib/client/editor/ace/worker-coffee.js create mode 100644 lib/client/editor/ace/worker-javascript.js create mode 100644 lib/client/editor/ace/worker-json.js create mode 100644 lib/client/editor/ace_editor.js diff --git a/ChangeLog b/ChangeLog index e4fca388..6ccf4b5d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -74,6 +74,8 @@ disabled in browsers. * Changed version of FuncyBox to 2.1.0. +* Added Ace editor. + 2012.08.24, Version 0.1.6 diff --git a/client.js b/client.js index e27840a9..17e691e2 100644 --- a/client.js +++ b/client.js @@ -395,8 +395,8 @@ CloudClient.Util = (function(){ else if(typeof lFunc === 'object' && typeof lFunc.onload === 'function') lFunc.onload(); - - } + + } return element; }, @@ -409,7 +409,7 @@ CloudClient.Util = (function(){ return this.anyload(pSrc); } - this.anyload({ + return this.anyload({ name : 'script', src : pSrc, func : pFunc @@ -876,6 +876,7 @@ CloudClient.Editor = (function(pCurrentFile, pIsReadOnly) { /* loading CloudMirror plagin */ Util.jsload(CloudClient.LIBDIRCLIENT + 'editor.js',{ + //'editor/ace_editor.js',{ onload:(function(){ cloudcmd.Editor.Keys(pCurrentFile, pIsReadOnly); }) @@ -1458,9 +1459,8 @@ CloudClient._createFileTable = function(pElem, pJSON) /* очищаем панель */ var i = lElem.childNodes.length; - while(i--){ + while(i--) lElem.removeChild(lElem.lastChild); - } /* заполняем панель новыми элементами */ lElem.innerHTML = CloudFunc.buildFromJSON(pJSON,true); diff --git a/lib/client/editor.js b/lib/client/editor.js index b3db2675..926502b1 100644 --- a/lib/client/editor.js +++ b/lib/client/editor.js @@ -8,6 +8,8 @@ var CloudCommander, CloudFunc, CodeMirror; Util = CloudCommander.Util, KeyBinding = CloudCommander.KeyBinding, CodeMirrorEditor = {}, + CodeMirrorLoaded = false, + FM, CodeMirrorElement; cloudcmd.Editor = { @@ -16,6 +18,19 @@ var CloudCommander, CloudFunc, CodeMirror; }) }; + + var createEditorDiv = function(pIsReadOnly){ + if(!FM) + FM = Util.getById('fm'); + + CodeMirrorElement = Util.anyload({ + name : 'div', + id : 'CodeMirrorEditor', + className : 'panel', + parent : FM + }); + }; + cloudcmd.Editor.dir = 'lib/client/editor/'; CodeMirrorEditor.dir = cloudcmd.Editor.dir + 'codemirror/'; @@ -24,26 +39,7 @@ var CloudCommander, CloudFunc, CodeMirror; /* function loads CodeMirror js and css files */ CodeMirrorEditor.load = (function(pCurrentFile, pIsReadOnly){ - /* function shows editor */ - var lThis = this; - var createEditorDiv = function(){ - if (!CodeMirrorElement) { - var lFM = Util.getById('fm'); - if(lFM) - CodeMirrorElement = Util.anyload({ - name : 'div', - id : 'CodeMirrorEditor', - parent : lFM - }); - else - console.log('Error. Something went wrong FM not found'); - - lThis.show(pCurrentFile, pIsReadOnly); - } - }; - /* function loads css files - * of CodeMirror - */ + /* function loads css files of CodeMirror */ var loadAll = function() { Util.cssLoad([ { src : CodeMirrorEditor.dir + 'codemirror.css'}, @@ -63,7 +59,10 @@ var CloudCommander, CloudFunc, CodeMirror; }); Util.jsload(CodeMirrorEditor.dir + - 'mode/javascript.js', createEditorDiv); + 'mode/javascript.js', function(){ + CodeMirrorLoaded = true; + CodeMirrorEditor.show(pIsReadOnly); + }); }; /* load CodeMirror main module */ @@ -71,12 +70,10 @@ var CloudCommander, CloudFunc, CodeMirror; }); /* function shows CodeMirror editor */ - CodeMirrorEditor.show = (function(pCurrentFile, pIsReadOnly){ - + CodeMirrorEditor.show = (function(pIsReadOnly){ /* if CodeMirrorEditor is not loaded - loading him */ - var lCodeMirrorEditor = Util.getById('CodeMirrorEditor'); - if(!lCodeMirrorEditor) - return this.load(pCurrentFile, pIsReadOnly); + if(!CodeMirrorLoaded) + return this.load(pIsReadOnly); /* if CodeMirror function show already * called do not call it again @@ -93,9 +90,8 @@ var CloudCommander, CloudFunc, CodeMirror; var lThis = this; - var initCodeMirror_f = function(pValue){ - lCodeMirrorEditor.className = 'panel'; - new CodeMirror(lCodeMirrorEditor,{ + var initCodeMirror_f = function(pValue){ + new CodeMirror(CodeMirrorElement,{ mode : 'javascript', value : pValue, theme : 'night', @@ -110,18 +106,18 @@ var CloudCommander, CloudFunc, CodeMirror; readOnly : lReadOnly }); }; - - var lA; - + + /* getting link */ - lA = Util.getCurrentLink(pCurrentFile); - lA = lA.href; + var lCurrentFile = Util.getCurrentFile(), + lA = Util.getCurrentLink(lCurrentFile); + lA = lA.href; /* убираем адрес хоста*/ lA = '/' + lA.replace(document.location.href,''); /* checking is this link is to directory */ - var lSize = Util.getByClass('size', pCurrentFile); + var lSize = Util.getByClass('size', lCurrentFile); if(lSize){ lSize = lSize[0].textContent; @@ -136,7 +132,7 @@ var CloudCommander, CloudFunc, CodeMirror; } } } - + this.loading = true; setTimeout(function(){ lThis.loading = false;}, @@ -171,15 +167,11 @@ var CloudCommander, CloudFunc, CodeMirror; /* function hides CodeMirror editor */ CodeMirrorEditor.hide = (function() { - KeyBinding.set(); + var lElem = CodeMirrorElement; + KeyBinding.set(); - if(CodeMirrorElement){ - Util.hide(CodeMirrorElement); - var lCodeMirror = Util.getByClass('CodeMirror', CodeMirrorElement); - - if(lCodeMirror.length) - CodeMirrorElement.removeChild(lCodeMirror[0]); - } + if(lElem && FM) + FM.removeChild(lElem); Util.showPanel(); }); @@ -198,14 +190,12 @@ var CloudCommander, CloudFunc, CodeMirror; var lF4 = cloudcmd.KEY.F4; //var lShow = lThis.show.bind(lThis); var lShow = Util.bind(lThis.show, lThis); - - var lCurrentFile = Util.getCurrentFile(); - + if(!pEvent.shiftKey){ if(pEvent.keyCode === lF4) - lShow(lCurrentFile); + lShow(); else if(pEvent.keyCode === lF3){ - lShow(lCurrentFile, true); + lShow(true); } } } diff --git a/lib/client/editor/ace/ChangeLog.txt b/lib/client/editor/ace/ChangeLog.txt new file mode 100644 index 00000000..76b2313b --- /dev/null +++ b/lib/client/editor/ace/ChangeLog.txt @@ -0,0 +1,116 @@ +2011.08.02, Version 0.2.0 + +* Split view (Julian Viereck) + - split editor area horizontally or vertivally to show two files at the same + time + +* Code Folding (Julian Viereck) + - Unstructured code folding + - Will be the basis for language aware folding + +* Mode behaviours (Chris Spencer) + - Adds mode specific hooks which allow transformations of entered text + - Autoclosing of braces, paranthesis and quotation marks in C style modes + - Autoclosing of angular brackets in XML style modes + +* New language modes + - Clojure (Carin Meier) + - C# (Rob Conery) + - Groovy (Ben Tilford) + - Scala (Ben Tilford) + - JSON + - OCaml (Sergi Mansilla) + - Perl (Panagiotis Astithas) + - SCSS/SASS (Andreas Madsen) + - SVG + - Textile (Kelley van Evert) + - SCAD (Jacob Hansson) + +* Live syntax checks + - Lint for Css using CSS Lint + - CoffeeScript + +* New Themes + - Crimson Editor (iebuggy) + - Merbivore (Michael Schwartz) + - Merbivore soft (Michael Schwartz) + - Solarized dark/light (David Alan + Hjelle) + - Vibrant Ink (Michael Schwartz) + +* Small Features/Enhancements + - Lots of render performance optimizations (Harutyun Amirjanyan) + - Improved Ruby highlighting (Chris Wanstrath, Trent Ogren) + - Improved PHP highlighting (Thomas Hruska) + - Improved CSS highlighting (Sean Kellogg) + - Clicks which cause the editor to be focused don't reset the selection + - Make padding text layer specific so that print margin and active line + highlight are not affected (Irakli Gozalishvili) + - Added setFontSize method + - Improved vi keybindings (Trent Ogren) + - When unfocused make cursor transparent instead of removing it (Harutyun + Amirjanyan) + - Support for matching groups in tokenizer with arrays of tokens (Chris + Spencer) + +* Bug fixes + - Add support for the new OSX scroll bars + - Properly highlight JavaScript regexp literals + - Proper handling of unicode characters in JavaScript identifiers + - Fix remove lines command on last line (Harutyun Amirjanyan) + - Fix scroll wheel sluggishness in Safari + - Make keyboard infrastructure route keys like []^$ the right way (Julian + Viereck) + +2011.02.14, Version 0.1.6 + +* Floating Anchors + - An Anchor is a floating pointer in the document. + - Whenever text is inserted or deleted before the cursor, the position of + the cursor is updated + - Usesd for the cursor and selection + - Basis for bookmarks, multiple cursors and snippets in the future +* Extensive support for Cocoa style keybindings on the Mac +* New commands: + - center selection in viewport + - remove to end/start of line + - split line + - transpose letters +* Refator markers + - Custom code can be used to render markers + - Markers can be in front or behind the text + - Markers are now stored in the session (was in the renderer) +* Lots of IE8 fixes including copy, cut and selections +* Unit tests can also be run in the browser + +* Soft wrap can adapt to the width of the editor (Mike Ratcliffe, Joe Cheng) +* Add minimal node server server.js to run the Ace demo in Chrome +* The top level editor.html demo has been renamed to index.html +* Bug fixes + - Fixed gotoLine to consider wrapped lines when calculating where to scroll to (James Allen) + - Fixed isues when the editor was scrolled in the web page (Eric Allam) + - Highlighting of Python string literals + - Syntax rule for PHP comments + +2011.02.08, Version 0.1.5 + +* Add Coffeescript Mode (Satoshi Murakami) +* Fix word wrap bug (Julian Viereck) +* Fix packaged version of the Eclipse mode +* Loading of workers is more robust +* Fix "click selection" +* Allow tokizing empty lines (Daniel Krech) +* Make PageUp/Down behavior more consistent with native OS (Joe Cheng) + +2011.02.04, Version 0.1.4 + +* Add C/C++ mode contributed by Gastón Kleiman +* Fix exception in key input + +2011.02.04, Version 0.1.3 + +* Let the packaged version play nice with requireJS +* Add Ruby mode contributed by Shlomo Zalman Heigh +* Add Java mode contributed by Tom Tasche +* Fix annotation bug +* Changing a document added a new empty line at the end \ No newline at end of file diff --git a/lib/client/editor/ace/LICENSE b/lib/client/editor/ace/LICENSE new file mode 100644 index 00000000..853e4fd5 --- /dev/null +++ b/lib/client/editor/ace/LICENSE @@ -0,0 +1,476 @@ +Licensed under the tri-license MPL/LGPL/GPL. + + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + + + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 \ No newline at end of file diff --git a/lib/client/editor/ace/README.md b/lib/client/editor/ace/README.md new file mode 100644 index 00000000..e1e0c3b4 --- /dev/null +++ b/lib/client/editor/ace/README.md @@ -0,0 +1,21 @@ +Ace (Ajax.org Cloud9 Editor) +============================ + +Ace is a code editor written in JavaScript. + +This repository has only generated files. +If you want to work on ace please go to https://github.com/ajaxorg/ace instead. + + +here you can find pre-built files for convenience of embedding. +it contains 4 versions + * [src](https://github.com/ajaxorg/ace-builds/tree/master/src) concatenated but not minified + * [src-min](https://github.com/ajaxorg/ace-builds/tree/master/src-min) concatenated and minified with uglify.js + * [src-noconflict](https://github.com/ajaxorg/ace-builds/tree/master/src-noconflict) uses ace.require instead of require + * [src-min-noconflict](https://github.com/ajaxorg/ace-builds/tree/master/src-min-noconflict) - + + +For a simple way of embedding ace into webpage see https://github.com/ajaxorg/ace-builds/blob/master/editor.html +To see ace in action go to [kitchen-sink-demo](http://ajaxorg.github.com/ace-builds/kitchen-sink.html), [scrollable-page-demo](http://ajaxorg.github.com/ace-builds/scrollable-page.html), or [minimal demo](http://ajaxorg.github.com/ace-builds/editor.html) + + diff --git a/lib/client/editor/ace/ace.js b/lib/client/editor/ace/ace.js new file mode 100644 index 00000000..d5f19b2f --- /dev/null +++ b/lib/client/editor/ace/ace.js @@ -0,0 +1,15689 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Ajax.org Code Editor (ACE). + * + * The Initial Developer of the Original Code is + * Ajax.org B.V. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Fabian Jakobs + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/** + * Define a module along with a payload + * @param module a name for the payload + * @param payload a function to call with (require, exports, module) params + */ + +(function() { + +var ACE_NAMESPACE = "ace"; + +var global = (function() { + return this; +})(); + +// take care of the case when requirejs is used and we just need to patch it a little bit +if (!ACE_NAMESPACE && typeof requirejs !== "undefined") { + + var define = global.define; + global.define = function(id, deps, callback) { + if (typeof callback !== "function") + return define.apply(this, arguments); + + return ace.define(id, deps, function(require, exports, module) { + if (deps[2] == "module") + module.packaged = true; + return callback.apply(this, arguments); + }); + }; + global.define.packaged = true; + + return; +} + + +var _define = function(module, deps, payload) { + if (typeof module !== 'string') { + if (_define.original) + _define.original.apply(window, arguments); + else { + console.error('dropping module because define wasn\'t a string.'); + console.trace(); + } + return; + } + + if (arguments.length == 2) + payload = deps; + + if (!_define.modules) + _define.modules = {}; + + _define.modules[module] = payload; +}; +var _require = function(parentId, module, callback) { + if (Object.prototype.toString.call(module) === "[object Array]") { + var params = []; + for (var i = 0, l = module.length; i < l; ++i) { + var dep = lookup(parentId, module[i]); + if (!dep && _require.original) + return _require.original.apply(window, arguments); + params.push(dep); + } + if (callback) { + callback.apply(null, params); + } + } + else if (typeof module === 'string') { + var payload = lookup(parentId, module); + if (!payload && _require.original) + return _require.original.apply(window, arguments); + + if (callback) { + callback(); + } + + return payload; + } + else { + if (_require.original) + return _require.original.apply(window, arguments); + } +}; + +var normalizeModule = function(parentId, moduleName) { + // normalize plugin requires + if (moduleName.indexOf("!") !== -1) { + var chunks = moduleName.split("!"); + return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]); + } + // normalize relative requires + if (moduleName.charAt(0) == ".") { + var base = parentId.split("/").slice(0, -1).join("/"); + moduleName = base + "/" + moduleName; + + while(moduleName.indexOf(".") !== -1 && previous != moduleName) { + var previous = moduleName; + moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); + } + } + + return moduleName; +}; +var lookup = function(parentId, moduleName) { + + moduleName = normalizeModule(parentId, moduleName); + + var module = _define.modules[moduleName]; + if (!module) { + return null; + } + + if (typeof module === 'function') { + var exports = {}; + var mod = { + id: moduleName, + uri: '', + exports: exports, + packaged: true + }; + + var req = function(module, callback) { + return _require(moduleName, module, callback); + }; + + var returnValue = module(req, exports, mod); + exports = returnValue || mod.exports; + + // cache the resulting module object for next time + _define.modules[moduleName] = exports; + return exports; + } + + return module; +}; + +function exportAce(ns) { + var require = function(module, callback) { + return _require("", module, callback); + }; + + var root = global; + if (ns) { + if (!global[ns]) + global[ns] = {}; + root = global[ns]; + } + + if (!root.define || !root.define.packaged) { + _define.original = root.define; + root.define = _define; + root.define.packaged = true; + } + + if (!root.require || !root.require.packaged) { + _require.original = root.require; + root.require = require; + root.require.packaged = true; + } +} + +exportAce(ACE_NAMESPACE); + +})(); + +ace.define('ace/requirejs/text', ['require', 'exports', 'module'], function(require, exports, module) { + // this won't be called it is needed only for included text modules + exports.load = function (name, req, onLoad, config) { + require("ace/lib/net").get(req.toUrl(name), onLoad); + }; +}); + +/** + * class Ace + * + * The main class required to set up an Ace instance in the browser. + * + * + **/ + +ace.define('ace/ace', ['require', 'exports', 'module' , 'ace/lib/fixoldbrowsers', 'ace/lib/dom', 'ace/lib/event', 'ace/editor', 'ace/edit_session', 'ace/undomanager', 'ace/virtual_renderer', 'ace/multi_select', 'ace/worker/worker_client', 'ace/keyboard/hash_handler', 'ace/keyboard/state_handler', 'ace/placeholder', 'ace/config', 'ace/theme/textmate'], function(require, exports, module) { + + +require("./lib/fixoldbrowsers"); + +var Dom = require("./lib/dom"); +var Event = require("./lib/event"); + +var Editor = require("./editor").Editor; +var EditSession = require("./edit_session").EditSession; +var UndoManager = require("./undomanager").UndoManager; +var Renderer = require("./virtual_renderer").VirtualRenderer; +var MultiSelect = require("./multi_select").MultiSelect; + +// The following require()s are for inclusion in the built ace file +require("./worker/worker_client"); +require("./keyboard/hash_handler"); +require("./keyboard/state_handler"); +require("./placeholder"); +exports.config = require("./config"); +exports.edit = function(el) { + if (typeof(el) == "string") { + el = document.getElementById(el); + } + + if (el.env && el.env.editor instanceof Editor) + return el.env.editor; + + var doc = new EditSession(Dom.getInnerText(el)); + doc.setUndoManager(new UndoManager()); + el.innerHTML = ''; + + var editor = new Editor(new Renderer(el, require("./theme/textmate"))); + new MultiSelect(editor); + editor.setSession(doc); + + var env = {}; + env.document = doc; + env.editor = editor; + editor.resize(); + Event.addListener(window, "resize", function() { + editor.resize(); + }); + el.env = env; + // Store env on editor such that it can be accessed later on from + // the returned object. + editor.env = env; + return editor; +}; + +}); +/*! + Copyright (c) 2009, 280 North Inc. http://280north.com/ + MIT License. http://github.com/280north/narwhal/blob/master/README.md +*/ + +ace.define('ace/lib/fixoldbrowsers', ['require', 'exports', 'module' , 'ace/lib/regexp', 'ace/lib/es5-shim'], function(require, exports, module) { + + +require("./regexp"); +require("./es5-shim"); + +}); + +ace.define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, exports, module) { + + + //--------------------------------- + // Private variables + //--------------------------------- + + var real = { + exec: RegExp.prototype.exec, + test: RegExp.prototype.test, + match: String.prototype.match, + replace: String.prototype.replace, + split: String.prototype.split + }, + compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups + compliantLastIndexIncrement = function () { + var x = /^/g; + real.test.call(x, ""); + return !x.lastIndex; + }(); + + if (compliantLastIndexIncrement && compliantExecNpcg) + return; + + //--------------------------------- + // Overriden native methods + //--------------------------------- + + // Adds named capture support (with backreferences returned as `result.name`), and fixes two + // cross-browser issues per ES3: + // - Captured values for nonparticipating capturing groups should be returned as `undefined`, + // rather than the empty string. + // - `lastIndex` should not be incremented after zero-length matches. + RegExp.prototype.exec = function (str) { + var match = real.exec.apply(this, arguments), + name, r2; + if ( typeof(str) == 'string' && match) { + // Fix browsers whose `exec` methods don't consistently return `undefined` for + // nonparticipating capturing groups + if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) { + r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", "")); + // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed + // matching due to characters outside the match + real.replace.call(str.slice(match.index), r2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) + match[i] = undefined; + } + }); + } + // Attach named capture properties + if (this._xregexp && this._xregexp.captureNames) { + for (var i = 1; i < match.length; i++) { + name = this._xregexp.captureNames[i - 1]; + if (name) + match[name] = match[i]; + } + } + // Fix browsers that increment `lastIndex` after zero-length matches + if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + } + return match; + }; + + // Don't override `test` if it won't change anything + if (!compliantLastIndexIncrement) { + // Fix browser bug in native method + RegExp.prototype.test = function (str) { + // Use the native `exec` to skip some processing overhead, even though the overriden + // `exec` would take care of the `lastIndex` fix + var match = real.exec.call(this, str); + // Fix browsers that increment `lastIndex` after zero-length matches + if (match && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + return !!match; + }; + } + + //--------------------------------- + // Private helper functions + //--------------------------------- + + function getNativeFlags (regex) { + return (regex.global ? "g" : "") + + (regex.ignoreCase ? "i" : "") + + (regex.multiline ? "m" : "") + + (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3 + (regex.sticky ? "y" : ""); + } + + function indexOf (array, item, from) { + if (Array.prototype.indexOf) // Use the native array method if available + return array.indexOf(item, from); + for (var i = from || 0; i < array.length; i++) { + if (array[i] === item) + return i; + } + return -1; + } + +}); +/*! + Copyright (c) 2009, 280 North Inc. http://280north.com/ + MIT License. http://github.com/280north/narwhal/blob/master/README.md +*/ + +ace.define('ace/lib/es5-shim', ['require', 'exports', 'module' ], function(require, exports, module) { + +/* + * Brings an environment as close to ECMAScript 5 compliance + * as is possible with the facilities of erstwhile engines. + * + * Annotated ES5: http://es5.github.com/ (specific links below) + * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf + * + * @module + */ + +/*whatsupdoc*/ + +// +// Function +// ======== +// + +// ES-5 15.3.4.5 +// http://es5.github.com/#x15.3.4.5 + +if (!Function.prototype.bind) { + Function.prototype.bind = function bind(that) { // .length is 1 + // 1. Let Target be the this value. + var target = this; + // 2. If IsCallable(Target) is false, throw a TypeError exception. + if (typeof target != "function") + throw new TypeError(); // TODO message + // 3. Let A be a new (possibly empty) internal list of all of the + // argument values provided after thisArg (arg1, arg2 etc), in order. + // XXX slicedArgs will stand in for "A" if used + var args = slice.call(arguments, 1); // for normal call + // 4. Let F be a new native ECMAScript object. + // 11. Set the [[Prototype]] internal property of F to the standard + // built-in Function prototype object as specified in 15.3.3.1. + // 12. Set the [[Call]] internal property of F as described in + // 15.3.4.5.1. + // 13. Set the [[Construct]] internal property of F as described in + // 15.3.4.5.2. + // 14. Set the [[HasInstance]] internal property of F as described in + // 15.3.4.5.3. + var bound = function () { + + if (this instanceof bound) { + // 15.3.4.5.2 [[Construct]] + // When the [[Construct]] internal method of a function object, + // F that was created using the bind function is called with a + // list of arguments ExtraArgs, the following steps are taken: + // 1. Let target be the value of F's [[TargetFunction]] + // internal property. + // 2. If target has no [[Construct]] internal method, a + // TypeError exception is thrown. + // 3. Let boundArgs be the value of F's [[BoundArgs]] internal + // property. + // 4. Let args be a new list containing the same values as the + // list boundArgs in the same order followed by the same + // values as the list ExtraArgs in the same order. + // 5. Return the result of calling the [[Construct]] internal + // method of target providing args as the arguments. + + var F = function(){}; + F.prototype = target.prototype; + var self = new F; + + var result = target.apply( + self, + args.concat(slice.call(arguments)) + ); + if (result !== null && Object(result) === result) + return result; + return self; + + } else { + // 15.3.4.5.1 [[Call]] + // When the [[Call]] internal method of a function object, F, + // which was created using the bind function is called with a + // this value and a list of arguments ExtraArgs, the following + // steps are taken: + // 1. Let boundArgs be the value of F's [[BoundArgs]] internal + // property. + // 2. Let boundThis be the value of F's [[BoundThis]] internal + // property. + // 3. Let target be the value of F's [[TargetFunction]] internal + // property. + // 4. Let args be a new list containing the same values as the + // list boundArgs in the same order followed by the same + // values as the list ExtraArgs in the same order. + // 5. Return the result of calling the [[Call]] internal method + // of target providing boundThis as the this value and + // providing args as the arguments. + + // equiv: target.call(this, ...boundArgs, ...args) + return target.apply( + that, + args.concat(slice.call(arguments)) + ); + + } + + }; + // XXX bound.length is never writable, so don't even try + // + // 15. If the [[Class]] internal property of Target is "Function", then + // a. Let L be the length property of Target minus the length of A. + // b. Set the length own property of F to either 0 or L, whichever is + // larger. + // 16. Else set the length own property of F to 0. + // 17. Set the attributes of the length own property of F to the values + // specified in 15.3.5.1. + + // TODO + // 18. Set the [[Extensible]] internal property of F to true. + + // TODO + // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3). + // 20. Call the [[DefineOwnProperty]] internal method of F with + // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]: + // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and + // false. + // 21. Call the [[DefineOwnProperty]] internal method of F with + // arguments "arguments", PropertyDescriptor {[[Get]]: thrower, + // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false}, + // and false. + + // TODO + // NOTE Function objects created using Function.prototype.bind do not + // have a prototype property or the [[Code]], [[FormalParameters]], and + // [[Scope]] internal properties. + // XXX can't delete prototype in pure-js. + + // 22. Return F. + return bound; + }; +} + +// Shortcut to an often accessed properties, in order to avoid multiple +// dereference that costs universally. +// _Please note: Shortcuts are defined after `Function.prototype.bind` as we +// us it in defining shortcuts. +var call = Function.prototype.call; +var prototypeOfArray = Array.prototype; +var prototypeOfObject = Object.prototype; +var slice = prototypeOfArray.slice; +var toString = call.bind(prototypeOfObject.toString); +var owns = call.bind(prototypeOfObject.hasOwnProperty); + +// If JS engine supports accessors creating shortcuts. +var defineGetter; +var defineSetter; +var lookupGetter; +var lookupSetter; +var supportsAccessors; +if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) { + defineGetter = call.bind(prototypeOfObject.__defineGetter__); + defineSetter = call.bind(prototypeOfObject.__defineSetter__); + lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); + lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); +} + +// +// Array +// ===== +// + +// ES5 15.4.3.2 +// http://es5.github.com/#x15.4.3.2 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray +if (!Array.isArray) { + Array.isArray = function isArray(obj) { + return toString(obj) == "[object Array]"; + }; +} + +// The IsCallable() check in the Array functions +// has been replaced with a strict check on the +// internal class of the object to trap cases where +// the provided function was actually a regular +// expression literal, which in V8 and +// JavaScriptCore is a typeof "function". Only in +// V8 are regular expression literals permitted as +// reduce parameters, so it is desirable in the +// general case for the shim to match the more +// strict and common behavior of rejecting regular +// expressions. + +// ES5 15.4.4.18 +// http://es5.github.com/#x15.4.4.18 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach +if (!Array.prototype.forEach) { + Array.prototype.forEach = function forEach(fun /*, thisp*/) { + var self = toObject(this), + thisp = arguments[1], + i = 0, + length = self.length >>> 0; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + while (i < length) { + if (i in self) { + // Invoke the callback function with call, passing arguments: + // context, property value, property key, thisArg object context + fun.call(thisp, self[i], i, self); + } + i++; + } + }; +} + +// ES5 15.4.4.19 +// http://es5.github.com/#x15.4.4.19 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map +if (!Array.prototype.map) { + Array.prototype.map = function map(fun /*, thisp*/) { + var self = toObject(this), + length = self.length >>> 0, + result = Array(length), + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self) + result[i] = fun.call(thisp, self[i], i, self); + } + return result; + }; +} + +// ES5 15.4.4.20 +// http://es5.github.com/#x15.4.4.20 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter +if (!Array.prototype.filter) { + Array.prototype.filter = function filter(fun /*, thisp */) { + var self = toObject(this), + length = self.length >>> 0, + result = [], + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, self)) + result.push(self[i]); + } + return result; + }; +} + +// ES5 15.4.4.16 +// http://es5.github.com/#x15.4.4.16 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every +if (!Array.prototype.every) { + Array.prototype.every = function every(fun /*, thisp */) { + var self = toObject(this), + length = self.length >>> 0, + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self && !fun.call(thisp, self[i], i, self)) + return false; + } + return true; + }; +} + +// ES5 15.4.4.17 +// http://es5.github.com/#x15.4.4.17 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some +if (!Array.prototype.some) { + Array.prototype.some = function some(fun /*, thisp */) { + var self = toObject(this), + length = self.length >>> 0, + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, self)) + return true; + } + return false; + }; +} + +// ES5 15.4.4.21 +// http://es5.github.com/#x15.4.4.21 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce +if (!Array.prototype.reduce) { + Array.prototype.reduce = function reduce(fun /*, initial*/) { + var self = toObject(this), + length = self.length >>> 0; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + // no value to return if no initial value and an empty array + if (!length && arguments.length == 1) + throw new TypeError(); // TODO message + + var i = 0; + var result; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i++]; + break; + } + + // if array contains no values, no initial value to return + if (++i >= length) + throw new TypeError(); // TODO message + } while (true); + } + + for (; i < length; i++) { + if (i in self) + result = fun.call(void 0, result, self[i], i, self); + } + + return result; + }; +} + +// ES5 15.4.4.22 +// http://es5.github.com/#x15.4.4.22 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight +if (!Array.prototype.reduceRight) { + Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { + var self = toObject(this), + length = self.length >>> 0; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + // no value to return if no initial value, empty array + if (!length && arguments.length == 1) + throw new TypeError(); // TODO message + + var result, i = length - 1; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i--]; + break; + } + + // if array contains no values, no initial value to return + if (--i < 0) + throw new TypeError(); // TODO message + } while (true); + } + + do { + if (i in this) + result = fun.call(void 0, result, self[i], i, self); + } while (i--); + + return result; + }; +} + +// ES5 15.4.4.14 +// http://es5.github.com/#x15.4.4.14 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { + var self = toObject(this), + length = self.length >>> 0; + + if (!length) + return -1; + + var i = 0; + if (arguments.length > 1) + i = toInteger(arguments[1]); + + // handle negative indices + i = i >= 0 ? i : Math.max(0, length + i); + for (; i < length; i++) { + if (i in self && self[i] === sought) { + return i; + } + } + return -1; + }; +} + +// ES5 15.4.4.15 +// http://es5.github.com/#x15.4.4.15 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf +if (!Array.prototype.lastIndexOf) { + Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { + var self = toObject(this), + length = self.length >>> 0; + + if (!length) + return -1; + var i = length - 1; + if (arguments.length > 1) + i = Math.min(i, toInteger(arguments[1])); + // handle negative indices + i = i >= 0 ? i : length - Math.abs(i); + for (; i >= 0; i--) { + if (i in self && sought === self[i]) + return i; + } + return -1; + }; +} + +// +// Object +// ====== +// + +// ES5 15.2.3.2 +// http://es5.github.com/#x15.2.3.2 +if (!Object.getPrototypeOf) { + // https://github.com/kriskowal/es5-shim/issues#issue/2 + // http://ejohn.org/blog/objectgetprototypeof/ + // recommended by fschaefer on github + Object.getPrototypeOf = function getPrototypeOf(object) { + return object.__proto__ || ( + object.constructor ? + object.constructor.prototype : + prototypeOfObject + ); + }; +} + +// ES5 15.2.3.3 +// http://es5.github.com/#x15.2.3.3 +if (!Object.getOwnPropertyDescriptor) { + var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + + "non-object: "; + Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT + object); + // If object does not owns property return undefined immediately. + if (!owns(object, property)) + return; + + var descriptor, getter, setter; + + // If object has a property then it's for sure both `enumerable` and + // `configurable`. + descriptor = { enumerable: true, configurable: true }; + + // If JS engine supports accessor properties then property may be a + // getter or setter. + if (supportsAccessors) { + // Unfortunately `__lookupGetter__` will return a getter even + // if object has own non getter property along with a same named + // inherited getter. To avoid misbehavior we temporary remove + // `__proto__` so that `__lookupGetter__` will return getter only + // if it's owned by an object. + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + + var getter = lookupGetter(object, property); + var setter = lookupSetter(object, property); + + // Once we have getter and setter we can put values back. + object.__proto__ = prototype; + + if (getter || setter) { + if (getter) descriptor.get = getter; + if (setter) descriptor.set = setter; + + // If it was accessor property we're done and return here + // in order to avoid adding `value` to the descriptor. + return descriptor; + } + } + + // If we got this far we know that object has an own property that is + // not an accessor so we set it as a value and return descriptor. + descriptor.value = object[property]; + return descriptor; + }; +} + +// ES5 15.2.3.4 +// http://es5.github.com/#x15.2.3.4 +if (!Object.getOwnPropertyNames) { + Object.getOwnPropertyNames = function getOwnPropertyNames(object) { + return Object.keys(object); + }; +} + +// ES5 15.2.3.5 +// http://es5.github.com/#x15.2.3.5 +if (!Object.create) { + Object.create = function create(prototype, properties) { + var object; + if (prototype === null) { + object = { "__proto__": null }; + } else { + if (typeof prototype != "object") + throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); + var Type = function () {}; + Type.prototype = prototype; + object = new Type(); + // IE has no built-in implementation of `Object.getPrototypeOf` + // neither `__proto__`, but this manually setting `__proto__` will + // guarantee that `Object.getPrototypeOf` will work as expected with + // objects created using `Object.create` + object.__proto__ = prototype; + } + if (properties !== void 0) + Object.defineProperties(object, properties); + return object; + }; +} + +// ES5 15.2.3.6 +// http://es5.github.com/#x15.2.3.6 + +// Patch for WebKit and IE8 standard mode +// Designed by hax +// related issue: https://github.com/kriskowal/es5-shim/issues#issue/5 +// IE8 Reference: +// http://msdn.microsoft.com/en-us/library/dd282900.aspx +// http://msdn.microsoft.com/en-us/library/dd229916.aspx +// WebKit Bugs: +// https://bugs.webkit.org/show_bug.cgi?id=36423 + +function doesDefinePropertyWork(object) { + try { + Object.defineProperty(object, "sentinel", {}); + return "sentinel" in object; + } catch (exception) { + // returns falsy + } +} + +// check whether defineProperty works if it's given. Otherwise, +// shim partially. +if (Object.defineProperty) { + var definePropertyWorksOnObject = doesDefinePropertyWork({}); + var definePropertyWorksOnDom = typeof document == "undefined" || + doesDefinePropertyWork(document.createElement("div")); + if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { + var definePropertyFallback = Object.defineProperty; + } +} + +if (!Object.defineProperty || definePropertyFallback) { + var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; + var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " + var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + + "on this javascript engine"; + + Object.defineProperty = function defineProperty(object, property, descriptor) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT_TARGET + object); + if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) + throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); + + // make a valiant attempt to use the real defineProperty + // for I8's DOM elements. + if (definePropertyFallback) { + try { + return definePropertyFallback.call(Object, object, property, descriptor); + } catch (exception) { + // try the shim if the real one doesn't work + } + } + + // If it's a data property. + if (owns(descriptor, "value")) { + // fail silently if "writable", "enumerable", or "configurable" + // are requested but not supported + /* + // alternate approach: + if ( // can't implement these features; allow false but not true + !(owns(descriptor, "writable") ? descriptor.writable : true) || + !(owns(descriptor, "enumerable") ? descriptor.enumerable : true) || + !(owns(descriptor, "configurable") ? descriptor.configurable : true) + ) + throw new RangeError( + "This implementation of Object.defineProperty does not " + + "support configurable, enumerable, or writable." + ); + */ + + if (supportsAccessors && (lookupGetter(object, property) || + lookupSetter(object, property))) + { + // As accessors are supported only on engines implementing + // `__proto__` we can safely override `__proto__` while defining + // a property to make sure that we don't hit an inherited + // accessor. + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + // Deleting a property anyway since getter / setter may be + // defined on object itself. + delete object[property]; + object[property] = descriptor.value; + // Setting original `__proto__` back now. + object.__proto__ = prototype; + } else { + object[property] = descriptor.value; + } + } else { + if (!supportsAccessors) + throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); + // If we got that far then getters and setters can be defined !! + if (owns(descriptor, "get")) + defineGetter(object, property, descriptor.get); + if (owns(descriptor, "set")) + defineSetter(object, property, descriptor.set); + } + + return object; + }; +} + +// ES5 15.2.3.7 +// http://es5.github.com/#x15.2.3.7 +if (!Object.defineProperties) { + Object.defineProperties = function defineProperties(object, properties) { + for (var property in properties) { + if (owns(properties, property)) + Object.defineProperty(object, property, properties[property]); + } + return object; + }; +} + +// ES5 15.2.3.8 +// http://es5.github.com/#x15.2.3.8 +if (!Object.seal) { + Object.seal = function seal(object) { + // this is misleading and breaks feature-detection, but + // allows "securable" code to "gracefully" degrade to working + // but insecure code. + return object; + }; +} + +// ES5 15.2.3.9 +// http://es5.github.com/#x15.2.3.9 +if (!Object.freeze) { + Object.freeze = function freeze(object) { + // this is misleading and breaks feature-detection, but + // allows "securable" code to "gracefully" degrade to working + // but insecure code. + return object; + }; +} + +// detect a Rhino bug and patch it +try { + Object.freeze(function () {}); +} catch (exception) { + Object.freeze = (function freeze(freezeObject) { + return function freeze(object) { + if (typeof object == "function") { + return object; + } else { + return freezeObject(object); + } + }; + })(Object.freeze); +} + +// ES5 15.2.3.10 +// http://es5.github.com/#x15.2.3.10 +if (!Object.preventExtensions) { + Object.preventExtensions = function preventExtensions(object) { + // this is misleading and breaks feature-detection, but + // allows "securable" code to "gracefully" degrade to working + // but insecure code. + return object; + }; +} + +// ES5 15.2.3.11 +// http://es5.github.com/#x15.2.3.11 +if (!Object.isSealed) { + Object.isSealed = function isSealed(object) { + return false; + }; +} + +// ES5 15.2.3.12 +// http://es5.github.com/#x15.2.3.12 +if (!Object.isFrozen) { + Object.isFrozen = function isFrozen(object) { + return false; + }; +} + +// ES5 15.2.3.13 +// http://es5.github.com/#x15.2.3.13 +if (!Object.isExtensible) { + Object.isExtensible = function isExtensible(object) { + // 1. If Type(O) is not Object throw a TypeError exception. + if (Object(object) === object) { + throw new TypeError(); // TODO message + } + // 2. Return the Boolean value of the [[Extensible]] internal property of O. + var name = ''; + while (owns(object, name)) { + name += '?'; + } + object[name] = true; + var returnValue = owns(object, name); + delete object[name]; + return returnValue; + }; +} + +// ES5 15.2.3.14 +// http://es5.github.com/#x15.2.3.14 +if (!Object.keys) { + // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation + var hasDontEnumBug = true, + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + dontEnumsLength = dontEnums.length; + + for (var key in {"toString": null}) + hasDontEnumBug = false; + + Object.keys = function keys(object) { + + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError("Object.keys called on a non-object"); + + var keys = []; + for (var name in object) { + if (owns(object, name)) { + keys.push(name); + } + } + + if (hasDontEnumBug) { + for (var i = 0, ii = dontEnumsLength; i < ii; i++) { + var dontEnum = dontEnums[i]; + if (owns(object, dontEnum)) { + keys.push(dontEnum); + } + } + } + + return keys; + }; + +} + +// +// Date +// ==== +// + +// ES5 15.9.5.43 +// http://es5.github.com/#x15.9.5.43 +// This function returns a String value represent the instance in time +// represented by this Date object. The format of the String is the Date Time +// string format defined in 15.9.1.15. All fields are present in the String. +// The time zone is always UTC, denoted by the suffix Z. If the time value of +// this object is not a finite Number a RangeError exception is thrown. +if (!Date.prototype.toISOString || (new Date(-62198755200000).toISOString().indexOf('-000001') === -1)) { + Date.prototype.toISOString = function toISOString() { + var result, length, value, year; + if (!isFinite(this)) + throw new RangeError; + + // the date time string format is specified in 15.9.1.15. + result = [this.getUTCMonth() + 1, this.getUTCDate(), + this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()]; + year = this.getUTCFullYear(); + year = (year < 0 ? '-' : (year > 9999 ? '+' : '')) + ('00000' + Math.abs(year)).slice(0 <= year && year <= 9999 ? -4 : -6); + + length = result.length; + while (length--) { + value = result[length]; + // pad months, days, hours, minutes, and seconds to have two digits. + if (value < 10) + result[length] = "0" + value; + } + // pad milliseconds to have three digits. + return year + "-" + result.slice(0, 2).join("-") + "T" + result.slice(2).join(":") + "." + + ("000" + this.getUTCMilliseconds()).slice(-3) + "Z"; + } +} + +// ES5 15.9.4.4 +// http://es5.github.com/#x15.9.4.4 +if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; +} + +// ES5 15.9.5.44 +// http://es5.github.com/#x15.9.5.44 +// This function provides a String representation of a Date object for use by +// JSON.stringify (15.12.3). +if (!Date.prototype.toJSON) { + Date.prototype.toJSON = function toJSON(key) { + // When the toJSON method is called with argument key, the following + // steps are taken: + + // 1. Let O be the result of calling ToObject, giving it the this + // value as its argument. + // 2. Let tv be ToPrimitive(O, hint Number). + // 3. If tv is a Number and is not finite, return null. + // XXX + // 4. Let toISO be the result of calling the [[Get]] internal method of + // O with argument "toISOString". + // 5. If IsCallable(toISO) is false, throw a TypeError exception. + if (typeof this.toISOString != "function") + throw new TypeError(); // TODO message + // 6. Return the result of calling the [[Call]] internal method of + // toISO with O as the this value and an empty argument list. + return this.toISOString(); + + // NOTE 1 The argument is ignored. + + // NOTE 2 The toJSON function is intentionally generic; it does not + // require that its this value be a Date object. Therefore, it can be + // transferred to other kinds of objects for use as a method. However, + // it does require that any such object have a toISOString method. An + // object is free to use the argument key to filter its + // stringification. + }; +} + +// ES5 15.9.4.2 +// http://es5.github.com/#x15.9.4.2 +// based on work shared by Daniel Friesen (dantman) +// http://gist.github.com/303249 +if (Date.parse("+275760-09-13T00:00:00.000Z") !== 8.64e15) { + // XXX global assignment won't work in embeddings that use + // an alternate object for the context. + Date = (function(NativeDate) { + + // Date.length === 7 + var Date = function Date(Y, M, D, h, m, s, ms) { + var length = arguments.length; + if (this instanceof NativeDate) { + var date = length == 1 && String(Y) === Y ? // isString(Y) + // We explicitly pass it through parse: + new NativeDate(Date.parse(Y)) : + // We have to manually make calls depending on argument + // length here + length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) : + length >= 6 ? new NativeDate(Y, M, D, h, m, s) : + length >= 5 ? new NativeDate(Y, M, D, h, m) : + length >= 4 ? new NativeDate(Y, M, D, h) : + length >= 3 ? new NativeDate(Y, M, D) : + length >= 2 ? new NativeDate(Y, M) : + length >= 1 ? new NativeDate(Y) : + new NativeDate(); + // Prevent mixups with unfixed Date object + date.constructor = Date; + return date; + } + return NativeDate.apply(this, arguments); + }; + + // 15.9.1.15 Date Time String Format. + var isoDateExpression = new RegExp("^" + + "(\\d{4}|[\+\-]\\d{6})" + // four-digit year capture or sign + 6-digit extended year + "(?:-(\\d{2})" + // optional month capture + "(?:-(\\d{2})" + // optional day capture + "(?:" + // capture hours:minutes:seconds.milliseconds + "T(\\d{2})" + // hours capture + ":(\\d{2})" + // minutes capture + "(?:" + // optional :seconds.milliseconds + ":(\\d{2})" + // seconds capture + "(?:\\.(\\d{3}))?" + // milliseconds capture + ")?" + + "(?:" + // capture UTC offset component + "Z|" + // UTC capture + "(?:" + // offset specifier +/-hours:minutes + "([-+])" + // sign capture + "(\\d{2})" + // hours offset capture + ":(\\d{2})" + // minutes offset capture + ")" + + ")?)?)?)?" + + "$"); + + // Copy any custom methods a 3rd party library may have added + for (var key in NativeDate) + Date[key] = NativeDate[key]; + + // Copy "native" methods explicitly; they may be non-enumerable + Date.now = NativeDate.now; + Date.UTC = NativeDate.UTC; + Date.prototype = NativeDate.prototype; + Date.prototype.constructor = Date; + + // Upgrade Date.parse to handle simplified ISO 8601 strings + Date.parse = function parse(string) { + var match = isoDateExpression.exec(string); + if (match) { + match.shift(); // kill match[0], the full match + // parse months, days, hours, minutes, seconds, and milliseconds + for (var i = 1; i < 7; i++) { + // provide default values if necessary + match[i] = +(match[i] || (i < 3 ? 1 : 0)); + // match[1] is the month. Months are 0-11 in JavaScript + // `Date` objects, but 1-12 in ISO notation, so we + // decrement. + if (i == 1) + match[i]--; + } + + // parse the UTC offset component + var minuteOffset = +match.pop(), hourOffset = +match.pop(), sign = match.pop(); + + // compute the explicit time zone offset if specified + var offset = 0; + if (sign) { + // detect invalid offsets and return early + if (hourOffset > 23 || minuteOffset > 59) + return NaN; + + // express the provided time zone offset in minutes. The offset is + // negative for time zones west of UTC; positive otherwise. + offset = (hourOffset * 60 + minuteOffset) * 6e4 * (sign == "+" ? -1 : 1); + } + + // Date.UTC for years between 0 and 99 converts year to 1900 + year + // The Gregorian calendar has a 400-year cycle, so + // to Date.UTC(year + 400, .... ) - 12622780800000 == Date.UTC(year, ...), + // where 12622780800000 - number of milliseconds in Gregorian calendar 400 years + var year = +match[0]; + if (0 <= year && year <= 99) { + match[0] = year + 400; + return NativeDate.UTC.apply(this, match) + offset - 12622780800000; + } + + // compute a new UTC date value, accounting for the optional offset + return NativeDate.UTC.apply(this, match) + offset; + } + return NativeDate.parse.apply(this, arguments); + }; + + return Date; + })(Date); +} + +// +// String +// ====== +// + +// ES5 15.5.4.20 +// http://es5.github.com/#x15.5.4.20 +var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + + "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + + "\u2029\uFEFF"; +if (!String.prototype.trim || ws.trim()) { + // http://blog.stevenlevithan.com/archives/faster-trim-javascript + // http://perfectionkills.com/whitespace-deviations/ + ws = "[" + ws + "]"; + var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), + trimEndRegexp = new RegExp(ws + ws + "*$"); + String.prototype.trim = function trim() { + return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); + }; +} + +// +// Util +// ====== +// + +// ES5 9.4 +// http://es5.github.com/#x9.4 +// http://jsperf.com/to-integer +var toInteger = function (n) { + n = +n; + if (n !== n) // isNaN + n = 0; + else if (n !== 0 && n !== (1/0) && n !== -(1/0)) + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + return n; +}; + +var prepareString = "a"[0] != "a", + // ES5 9.9 + // http://es5.github.com/#x9.9 + toObject = function (o) { + if (o == null) { // this matches both null and undefined + throw new TypeError(); // TODO message + } + // If the implementation doesn't support by-index access of + // string characters (ex. IE < 7), split the string + if (prepareString && typeof o == "string" && o) { + return o.split(""); + } + return Object(o); + }; +}); + +ace.define('ace/lib/dom', ['require', 'exports', 'module' ], function(require, exports, module) { + + +var XHTML_NS = "http://www.w3.org/1999/xhtml"; + +exports.createElement = function(tag, ns) { + return document.createElementNS ? + document.createElementNS(ns || XHTML_NS, tag) : + document.createElement(tag); +}; + +exports.setText = function(elem, text) { + if (elem.innerText !== undefined) { + elem.innerText = text; + } + if (elem.textContent !== undefined) { + elem.textContent = text; + } +}; + +exports.hasCssClass = function(el, name) { + var classes = el.className.split(/\s+/g); + return classes.indexOf(name) !== -1; +}; +exports.addCssClass = function(el, name) { + if (!exports.hasCssClass(el, name)) { + el.className += " " + name; + } +}; +exports.removeCssClass = function(el, name) { + var classes = el.className.split(/\s+/g); + while (true) { + var index = classes.indexOf(name); + if (index == -1) { + break; + } + classes.splice(index, 1); + } + el.className = classes.join(" "); +}; + +exports.toggleCssClass = function(el, name) { + var classes = el.className.split(/\s+/g), add = true; + while (true) { + var index = classes.indexOf(name); + if (index == -1) { + break; + } + add = false; + classes.splice(index, 1); + } + if(add) + classes.push(name); + + el.className = classes.join(" "); + return add; +}; +exports.setCssClass = function(node, className, include) { + if (include) { + exports.addCssClass(node, className); + } else { + exports.removeCssClass(node, className); + } +}; + +exports.hasCssString = function(id, doc) { + var index = 0, sheets; + doc = doc || document; + + if (doc.createStyleSheet && (sheets = doc.styleSheets)) { + while (index < sheets.length) + if (sheets[index++].owningElement.id === id) return true; + } else if ((sheets = doc.getElementsByTagName("style"))) { + while (index < sheets.length) + if (sheets[index++].id === id) return true; + } + + return false; +}; + +exports.importCssString = function importCssString(cssText, id, doc) { + doc = doc || document; + // If style is already imported return immediately. + if (id && exports.hasCssString(id, doc)) + return null; + + var style; + + if (doc.createStyleSheet) { + style = doc.createStyleSheet(); + style.cssText = cssText; + if (id) + style.owningElement.id = id; + } else { + style = doc.createElementNS + ? doc.createElementNS(XHTML_NS, "style") + : doc.createElement("style"); + + style.appendChild(doc.createTextNode(cssText)); + if (id) + style.id = id; + + var head = doc.getElementsByTagName("head")[0] || doc.documentElement; + head.appendChild(style); + } +}; + +exports.importCssStylsheet = function(uri, doc) { + if (doc.createStyleSheet) { + doc.createStyleSheet(uri); + } else { + var link = exports.createElement('link'); + link.rel = 'stylesheet'; + link.href = uri; + + var head = doc.getElementsByTagName("head")[0] || doc.documentElement; + head.appendChild(link); + } +}; + +exports.getInnerWidth = function(element) { + return ( + parseInt(exports.computedStyle(element, "paddingLeft"), 10) + + parseInt(exports.computedStyle(element, "paddingRight"), 10) + + element.clientWidth + ); +}; + +exports.getInnerHeight = function(element) { + return ( + parseInt(exports.computedStyle(element, "paddingTop"), 10) + + parseInt(exports.computedStyle(element, "paddingBottom"), 10) + + element.clientHeight + ); +}; + +if (window.pageYOffset !== undefined) { + exports.getPageScrollTop = function() { + return window.pageYOffset; + }; + + exports.getPageScrollLeft = function() { + return window.pageXOffset; + }; +} +else { + exports.getPageScrollTop = function() { + return document.body.scrollTop; + }; + + exports.getPageScrollLeft = function() { + return document.body.scrollLeft; + }; +} + +if (window.getComputedStyle) + exports.computedStyle = function(element, style) { + if (style) + return (window.getComputedStyle(element, "") || {})[style] || ""; + return window.getComputedStyle(element, "") || {}; + }; +else + exports.computedStyle = function(element, style) { + if (style) + return element.currentStyle[style]; + return element.currentStyle; + }; + +exports.scrollbarWidth = function(document) { + + var inner = exports.createElement("p"); + inner.style.width = "100%"; + inner.style.minWidth = "0px"; + inner.style.height = "200px"; + + var outer = exports.createElement("div"); + var style = outer.style; + + style.position = "absolute"; + style.left = "-10000px"; + style.overflow = "hidden"; + style.width = "200px"; + style.minWidth = "0px"; + style.height = "150px"; + + outer.appendChild(inner); + + var body = document.body || document.documentElement; + body.appendChild(outer); + + var noScrollbar = inner.offsetWidth; + + style.overflow = "scroll"; + var withScrollbar = inner.offsetWidth; + + if (noScrollbar == withScrollbar) { + withScrollbar = outer.clientWidth; + } + + body.removeChild(outer); + + return noScrollbar-withScrollbar; +}; +exports.setInnerHtml = function(el, innerHtml) { + var element = el.cloneNode(false);//document.createElement("div"); + element.innerHTML = innerHtml; + el.parentNode.replaceChild(element, el); + return element; +}; + +exports.setInnerText = function(el, innerText) { + var document = el.ownerDocument; + if (document.body && "textContent" in document.body) + el.textContent = innerText; + else + el.innerText = innerText; + +}; + +exports.getInnerText = function(el) { + var document = el.ownerDocument; + if (document.body && "textContent" in document.body) + return el.textContent; + else + return el.innerText || el.textContent || ""; +}; + +exports.getParentWindow = function(document) { + return document.defaultView || document.parentWindow; +}; + +}); + +ace.define('ace/lib/event', ['require', 'exports', 'module' , 'ace/lib/keys', 'ace/lib/useragent', 'ace/lib/dom'], function(require, exports, module) { + + +var keys = require("./keys"); +var useragent = require("./useragent"); +var dom = require("./dom"); + +exports.addListener = function(elem, type, callback) { + if (elem.addEventListener) { + return elem.addEventListener(type, callback, false); + } + if (elem.attachEvent) { + var wrapper = function() { + callback(window.event); + }; + callback._wrapper = wrapper; + elem.attachEvent("on" + type, wrapper); + } +}; + +exports.removeListener = function(elem, type, callback) { + if (elem.removeEventListener) { + return elem.removeEventListener(type, callback, false); + } + if (elem.detachEvent) { + elem.detachEvent("on" + type, callback._wrapper || callback); + } +}; +exports.stopEvent = function(e) { + exports.stopPropagation(e); + exports.preventDefault(e); + return false; +}; + +exports.stopPropagation = function(e) { + if (e.stopPropagation) + e.stopPropagation(); + else + e.cancelBubble = true; +}; + +exports.preventDefault = function(e) { + if (e.preventDefault) + e.preventDefault(); + else + e.returnValue = false; +}; +exports.getButton = function(e) { + if (e.type == "dblclick") + return 0; + if (e.type == "contextmenu" || (e.ctrlKey && useragent.isMac)) + return 2; + + // DOM Event + if (e.preventDefault) { + return e.button; + } + // old IE + else { + return {1:0, 2:2, 4:1}[e.button]; + } +}; + +if (document.documentElement.setCapture) { + exports.capture = function(el, eventHandler, releaseCaptureHandler) { + var called = false; + function onReleaseCapture(e) { + eventHandler(e); + + if (!called) { + called = true; + releaseCaptureHandler(e); + } + + exports.removeListener(el, "mousemove", eventHandler); + exports.removeListener(el, "mouseup", onReleaseCapture); + exports.removeListener(el, "losecapture", onReleaseCapture); + + el.releaseCapture(); + } + + exports.addListener(el, "mousemove", eventHandler); + exports.addListener(el, "mouseup", onReleaseCapture); + exports.addListener(el, "losecapture", onReleaseCapture); + el.setCapture(); + }; +} +else { + exports.capture = function(el, eventHandler, releaseCaptureHandler) { + function onMouseUp(e) { + eventHandler && eventHandler(e); + releaseCaptureHandler && releaseCaptureHandler(e); + + document.removeEventListener("mousemove", eventHandler, true); + document.removeEventListener("mouseup", onMouseUp, true); + + e.stopPropagation(); + } + + document.addEventListener("mousemove", eventHandler, true); + document.addEventListener("mouseup", onMouseUp, true); + }; +} + +exports.addMouseWheelListener = function(el, callback) { + var factor = 8; + var listener = function(e) { + if (e.wheelDelta !== undefined) { + if (e.wheelDeltaX !== undefined) { + e.wheelX = -e.wheelDeltaX / factor; + e.wheelY = -e.wheelDeltaY / factor; + } else { + e.wheelX = 0; + e.wheelY = -e.wheelDelta / factor; + } + } + else { + if (e.axis && e.axis == e.HORIZONTAL_AXIS) { + e.wheelX = (e.detail || 0) * 5; + e.wheelY = 0; + } else { + e.wheelX = 0; + e.wheelY = (e.detail || 0) * 5; + } + } + callback(e); + }; + exports.addListener(el, "DOMMouseScroll", listener); + exports.addListener(el, "mousewheel", listener); +}; + +exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbackName) { + var clicks = 0; + var startX, startY, timer; + var eventNames = { + 2: "dblclick", + 3: "tripleclick", + 4: "quadclick" + }; + + exports.addListener(el, "mousedown", function(e) { + if (exports.getButton(e) != 0) { + clicks = 0; + } else { + var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5; + + if (!timer || isNewClick) + clicks = 0; + + clicks += 1; + + if (timer) + clearTimeout(timer) + timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600); + } + if (clicks == 1) { + startX = e.clientX; + startY = e.clientY; + } + + eventHandler[callbackName]("mousedown", e); + + if (clicks > 4) + clicks = 0; + else if (clicks > 1) + return eventHandler[callbackName](eventNames[clicks], e); + }); + + if (useragent.isOldIE) { + exports.addListener(el, "dblclick", function(e) { + clicks = 2; + if (timer) + clearTimeout(timer); + timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600); + eventHandler[callbackName]("mousedown", e); + eventHandler[callbackName](eventNames[clicks], e); + }); + } +}; + +function normalizeCommandKeys(callback, e, keyCode) { + var hashId = 0; + if ((useragent.isOpera && !("KeyboardEvent" in window)) && useragent.isMac) { + hashId = 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) + | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0); + } else { + hashId = 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) + | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0); + } + + if (keyCode in keys.MODIFIER_KEYS) { + switch (keys.MODIFIER_KEYS[keyCode]) { + case "Alt": + hashId = 2; + break; + case "Shift": + hashId = 4; + break; + case "Ctrl": + hashId = 1; + break; + default: + hashId = 8; + break; + } + keyCode = 0; + } + + if (hashId & 8 && (keyCode == 91 || keyCode == 93)) { + keyCode = 0; + } + + // If there is no hashID and the keyCode is not a function key, then + // we don't call the callback as we don't handle a command key here + // (it's a normal key/character input). + if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) { + return false; + } + return callback(e, hashId, keyCode); +} + +exports.addCommandKeyListener = function(el, callback) { + var addListener = exports.addListener; + if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) { + // Old versions of Gecko aka. Firefox < 4.0 didn't repeat the keydown + // event if the user pressed the key for a longer time. Instead, the + // keydown event was fired once and later on only the keypress event. + // To emulate the 'right' keydown behavior, the keyCode of the initial + // keyDown event is stored and in the following keypress events the + // stores keyCode is used to emulate a keyDown event. + var lastKeyDownKeyCode = null; + addListener(el, "keydown", function(e) { + lastKeyDownKeyCode = e.keyCode; + }); + addListener(el, "keypress", function(e) { + return normalizeCommandKeys(callback, e, lastKeyDownKeyCode); + }); + } else { + var lastDown = null; + + addListener(el, "keydown", function(e) { + lastDown = e.keyIdentifier || e.keyCode; + return normalizeCommandKeys(callback, e, e.keyCode); + }); + } +}; + +if (window.postMessage && !useragent.isOldIE) { + var postMessageId = 1; + exports.nextTick = function(callback, win) { + win = win || window; + var messageName = "zero-timeout-message-" + postMessageId; + exports.addListener(win, "message", function listener(e) { + if (e.data == messageName) { + exports.stopPropagation(e); + exports.removeListener(win, "message", listener); + callback(); + } + }); + win.postMessage(messageName, "*"); + }; +} +else { + exports.nextTick = function(callback, win) { + win = win || window; + window.setTimeout(callback, 0); + }; +} + +}); + +// Most of the following code is taken from SproutCore with a few changes. + +ace.define('ace/lib/keys', ['require', 'exports', 'module' , 'ace/lib/oop'], function(require, exports, module) { + + +var oop = require("./oop"); +var Keys = (function() { + var ret = { + MODIFIER_KEYS: { + 16: 'Shift', 17: 'Ctrl', 18: 'Alt', 224: 'Meta' + }, + + KEY_MODS: { + "ctrl": 1, "alt": 2, "option" : 2, + "shift": 4, "meta": 8, "command": 8 + }, + + FUNCTION_KEYS : { + 8 : "Backspace", + 9 : "Tab", + 13 : "Return", + 19 : "Pause", + 27 : "Esc", + 32 : "Space", + 33 : "PageUp", + 34 : "PageDown", + 35 : "End", + 36 : "Home", + 37 : "Left", + 38 : "Up", + 39 : "Right", + 40 : "Down", + 44 : "Print", + 45 : "Insert", + 46 : "Delete", + 96 : "Numpad0", + 97 : "Numpad1", + 98 : "Numpad2", + 99 : "Numpad3", + 100: "Numpad4", + 101: "Numpad5", + 102: "Numpad6", + 103: "Numpad7", + 104: "Numpad8", + 105: "Numpad9", + 112: "F1", + 113: "F2", + 114: "F3", + 115: "F4", + 116: "F5", + 117: "F6", + 118: "F7", + 119: "F8", + 120: "F9", + 121: "F10", + 122: "F11", + 123: "F12", + 144: "Numlock", + 145: "Scrolllock" + }, + + PRINTABLE_KEYS: { + 32: ' ', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', + 54: '6', 55: '7', 56: '8', 57: '9', 59: ';', 61: '=', 65: 'a', + 66: 'b', 67: 'c', 68: 'd', 69: 'e', 70: 'f', 71: 'g', 72: 'h', + 73: 'i', 74: 'j', 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o', + 80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v', + 87: 'w', 88: 'x', 89: 'y', 90: 'z', 107: '+', 109: '-', 110: '.', + 188: ',', 190: '.', 191: '/', 192: '`', 219: '[', 220: '\\', + 221: ']', 222: '\'' + } + }; + + // A reverse map of FUNCTION_KEYS + for (var i in ret.FUNCTION_KEYS) { + var name = ret.FUNCTION_KEYS[i].toUpperCase(); + ret[name] = parseInt(i, 10); + } + + // Add the MODIFIER_KEYS, FUNCTION_KEYS and PRINTABLE_KEYS to the KEY + // variables as well. + oop.mixin(ret, ret.MODIFIER_KEYS); + oop.mixin(ret, ret.PRINTABLE_KEYS); + oop.mixin(ret, ret.FUNCTION_KEYS); + + return ret; +})(); +oop.mixin(exports, Keys); + +exports.keyCodeToString = function(keyCode) { + return (Keys[keyCode] || String.fromCharCode(keyCode)).toLowerCase(); +} + +}); + +ace.define('ace/lib/oop', ['require', 'exports', 'module' ], function(require, exports, module) { + + +exports.inherits = (function() { + var tempCtor = function() {}; + return function(ctor, superCtor) { + tempCtor.prototype = superCtor.prototype; + ctor.super_ = superCtor.prototype; + ctor.prototype = new tempCtor(); + ctor.prototype.constructor = ctor; + }; +}()); + +exports.mixin = function(obj, mixin) { + for (var key in mixin) { + obj[key] = mixin[key]; + } +}; + +exports.implement = function(proto, mixin) { + exports.mixin(proto, mixin); +}; + +}); + +ace.define('ace/lib/useragent', ['require', 'exports', 'module' ], function(require, exports, module) { + + +var os = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase(); +var ua = navigator.userAgent; + +// Is the user using a browser that identifies itself as Windows +exports.isWin = (os == "win"); + +// Is the user using a browser that identifies itself as Mac OS +exports.isMac = (os == "mac"); + +// Is the user using a browser that identifies itself as Linux +exports.isLinux = (os == "linux"); + +exports.isIE = + navigator.appName == "Microsoft Internet Explorer" + && parseFloat(navigator.userAgent.match(/MSIE ([0-9]+[\.0-9]+)/)[1]); + +exports.isOldIE = exports.isIE && exports.isIE < 9; + +// Is this Firefox or related? +exports.isGecko = exports.isMozilla = window.controllers && window.navigator.product === "Gecko"; + +// oldGecko == rev < 2.0 +exports.isOldGecko = exports.isGecko && parseInt((navigator.userAgent.match(/rv\:(\d+)/)||[])[1], 10) < 4; + +// Is this Opera +exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]"; + +// Is the user using a browser that identifies itself as WebKit +exports.isWebKit = parseFloat(ua.split("WebKit/")[1]) || undefined; + +exports.isChrome = parseFloat(ua.split(" Chrome/")[1]) || undefined; + +exports.isAIR = ua.indexOf("AdobeAIR") >= 0; + +exports.isIPad = ua.indexOf("iPad") >= 0; + +exports.isTouchPad = ua.indexOf("TouchPad") >= 0; +exports.OS = { + LINUX: "LINUX", + MAC: "MAC", + WINDOWS: "WINDOWS" +}; +exports.getOS = function() { + if (exports.isMac) { + return exports.OS.MAC; + } else if (exports.isLinux) { + return exports.OS.LINUX; + } else { + return exports.OS.WINDOWS; + } +}; + +}); + +ace.define('ace/editor', ['require', 'exports', 'module' , 'ace/lib/fixoldbrowsers', 'ace/lib/oop', 'ace/lib/lang', 'ace/lib/useragent', 'ace/keyboard/textinput', 'ace/mouse/mouse_handler', 'ace/mouse/fold_handler', 'ace/keyboard/keybinding', 'ace/edit_session', 'ace/search', 'ace/range', 'ace/lib/event_emitter', 'ace/commands/command_manager', 'ace/commands/default_commands'], function(require, exports, module) { + + +require("./lib/fixoldbrowsers"); + +var oop = require("./lib/oop"); +var lang = require("./lib/lang"); +var useragent = require("./lib/useragent"); +var TextInput = require("./keyboard/textinput").TextInput; +var MouseHandler = require("./mouse/mouse_handler").MouseHandler; +var FoldHandler = require("./mouse/fold_handler").FoldHandler; +//var TouchHandler = require("./touch_handler").TouchHandler; +var KeyBinding = require("./keyboard/keybinding").KeyBinding; +var EditSession = require("./edit_session").EditSession; +var Search = require("./search").Search; +var Range = require("./range").Range; +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var CommandManager = require("./commands/command_manager").CommandManager; +var defaultCommands = require("./commands/default_commands").commands; + +/** + * new Editor(renderer, session) + * - renderer (VirtualRenderer): Associated `VirtualRenderer` that draws everything + * - session (EditSession): The `EditSession` to refer to + * + * Creates a new `Editor` object. + * + **/ +var Editor = function(renderer, session) { + var container = renderer.getContainerElement(); + this.container = container; + this.renderer = renderer; + + this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands); + this.textInput = new TextInput(renderer.getTextAreaContainer(), this); + this.renderer.textarea = this.textInput.getElement(); + this.keyBinding = new KeyBinding(this); + + // TODO detect touch event support + if (useragent.isIPad) { + //this.$mouseHandler = new TouchHandler(this); + } else { + this.$mouseHandler = new MouseHandler(this); + new FoldHandler(this); + } + + this.$blockScrolling = 0; + this.$search = new Search().set({ + wrap: true + }); + + this.setSession(session || new EditSession("")); +}; + +(function(){ + + oop.implement(this, EventEmitter); + this.setKeyboardHandler = function(keyboardHandler) { + this.keyBinding.setKeyboardHandler(keyboardHandler); + }; + this.getKeyboardHandler = function() { + return this.keyBinding.getKeyboardHandler(); + }; + /** + * Editor@changeSession(e) + * - e (Object): An object with two properties, `oldSession` and `session`, that represent the old and new [[EditSession]]s. + * + * Emitted whenever the [[EditSession]] changes. + **/ + this.setSession = function(session) { + if (this.session == session) + return; + + if (this.session) { + var oldSession = this.session; + this.session.removeEventListener("change", this.$onDocumentChange); + this.session.removeEventListener("changeMode", this.$onChangeMode); + this.session.removeEventListener("tokenizerUpdate", this.$onTokenizerUpdate); + this.session.removeEventListener("changeTabSize", this.$onChangeTabSize); + this.session.removeEventListener("changeWrapLimit", this.$onChangeWrapLimit); + this.session.removeEventListener("changeWrapMode", this.$onChangeWrapMode); + this.session.removeEventListener("onChangeFold", this.$onChangeFold); + this.session.removeEventListener("changeFrontMarker", this.$onChangeFrontMarker); + this.session.removeEventListener("changeBackMarker", this.$onChangeBackMarker); + this.session.removeEventListener("changeBreakpoint", this.$onChangeBreakpoint); + this.session.removeEventListener("changeAnnotation", this.$onChangeAnnotation); + this.session.removeEventListener("changeOverwrite", this.$onCursorChange); + this.session.removeEventListener("changeScrollTop", this.$onScrollTopChange); + this.session.removeEventListener("changeLeftTop", this.$onScrollLeftChange); + + var selection = this.session.getSelection(); + selection.removeEventListener("changeCursor", this.$onCursorChange); + selection.removeEventListener("changeSelection", this.$onSelectionChange); + } + + this.session = session; + + this.$onDocumentChange = this.onDocumentChange.bind(this); + session.addEventListener("change", this.$onDocumentChange); + this.renderer.setSession(session); + + this.$onChangeMode = this.onChangeMode.bind(this); + session.addEventListener("changeMode", this.$onChangeMode); + + this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this); + session.addEventListener("tokenizerUpdate", this.$onTokenizerUpdate); + + this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer); + session.addEventListener("changeTabSize", this.$onChangeTabSize); + + this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this); + session.addEventListener("changeWrapLimit", this.$onChangeWrapLimit); + + this.$onChangeWrapMode = this.onChangeWrapMode.bind(this); + session.addEventListener("changeWrapMode", this.$onChangeWrapMode); + + this.$onChangeFold = this.onChangeFold.bind(this); + session.addEventListener("changeFold", this.$onChangeFold); + + this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this); + this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker); + + this.$onChangeBackMarker = this.onChangeBackMarker.bind(this); + this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker); + + this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this); + this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint); + + this.$onChangeAnnotation = this.onChangeAnnotation.bind(this); + this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation); + + this.$onCursorChange = this.onCursorChange.bind(this); + this.session.addEventListener("changeOverwrite", this.$onCursorChange); + + this.$onScrollTopChange = this.onScrollTopChange.bind(this); + this.session.addEventListener("changeScrollTop", this.$onScrollTopChange); + + this.$onScrollLeftChange = this.onScrollLeftChange.bind(this); + this.session.addEventListener("changeScrollLeft", this.$onScrollLeftChange); + + this.selection = session.getSelection(); + this.selection.addEventListener("changeCursor", this.$onCursorChange); + + this.$onSelectionChange = this.onSelectionChange.bind(this); + this.selection.addEventListener("changeSelection", this.$onSelectionChange); + + this.onChangeMode(); + + this.$blockScrolling += 1; + this.onCursorChange(); + this.$blockScrolling -= 1; + + this.onScrollTopChange(); + this.onScrollLeftChange(); + this.onSelectionChange(); + this.onChangeFrontMarker(); + this.onChangeBackMarker(); + this.onChangeBreakpoint(); + this.onChangeAnnotation(); + this.session.getUseWrapMode() && this.renderer.adjustWrapLimit(); + this.renderer.updateFull(); + + this._emit("changeSession", { + session: session, + oldSession: oldSession + }); + }; + this.getSession = function() { + return this.session; + }; + this.setValue = function(val, cursorPos) { + this.session.doc.setValue(val); + + if (!cursorPos) + this.selectAll(); + else if (cursorPos == 1) + this.navigateFileEnd(); + else if (cursorPos == -1) + this.navigateFileStart(); + + return val; + }; + this.getValue = function() { + return this.session.getValue(); + }; + this.getSelection = function() { + return this.selection; + }; + this.resize = function(force) { + this.renderer.onResize(force); + }; + this.setTheme = function(theme) { + this.renderer.setTheme(theme); + }; + this.getTheme = function() { + return this.renderer.getTheme(); + }; + this.setStyle = function(style) { + this.renderer.setStyle(style); + }; + this.unsetStyle = function(style) { + this.renderer.unsetStyle(style); + }; + this.setFontSize = function(size) { + this.container.style.fontSize = size; + this.renderer.updateFontSize(); + }; + this.$highlightBrackets = function() { + if (this.session.$bracketHighlight) { + this.session.removeMarker(this.session.$bracketHighlight); + this.session.$bracketHighlight = null; + } + + if (this.$highlightPending) { + return; + } + + // perform highlight async to not block the browser during navigation + var self = this; + this.$highlightPending = true; + setTimeout(function() { + self.$highlightPending = false; + + var pos = self.session.findMatchingBracket(self.getCursorPosition()); + if (pos) { + var range = new Range(pos.row, pos.column, pos.row, pos.column+1); + self.session.$bracketHighlight = self.session.addMarker(range, "ace_bracket", "text"); + } + }, 10); + }; + this.focus = function() { + // Safari needs the timeout + // iOS and Firefox need it called immediately + // to be on the save side we do both + var _self = this; + setTimeout(function() { + _self.textInput.focus(); + }); + this.textInput.focus(); + }; + this.isFocused = function() { + return this.textInput.isFocused(); + }; + this.blur = function() { + this.textInput.blur(); + }; + this.onFocus = function() { + if (this.$isFocused) + return; + this.$isFocused = true; + this.renderer.showCursor(); + this.renderer.visualizeFocus(); + this._emit("focus"); + }; + this.onBlur = function() { + if (!this.$isFocused) + return; + this.$isFocused = false; + this.renderer.hideCursor(); + this.renderer.visualizeBlur(); + this._emit("blur"); + }; + + this.$cursorChange = function() { + this.renderer.updateCursor(); + }; + this.onDocumentChange = function(e) { + var delta = e.data; + var range = delta.range; + var lastRow; + + if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines") + lastRow = range.end.row; + else + lastRow = Infinity; + this.renderer.updateLines(range.start.row, lastRow); + + this._emit("change", e); + + // update cursor because tab characters can influence the cursor position + this.$cursorChange(); + }; + + this.onTokenizerUpdate = function(e) { + var rows = e.data; + this.renderer.updateLines(rows.first, rows.last); + }; + + + this.onScrollTopChange = function() { + this.renderer.scrollToY(this.session.getScrollTop()); + }; + + this.onScrollLeftChange = function() { + this.renderer.scrollToX(this.session.getScrollLeft()); + }; + this.onCursorChange = function() { + this.$cursorChange(); + + if (!this.$blockScrolling) { + this.renderer.scrollCursorIntoView(); + } + + this.$highlightBrackets(); + this.$updateHighlightActiveLine(); + this._emit("changeSelection"); + }; + this.$updateHighlightActiveLine = function() { + var session = this.getSession(); + + if (session.$highlightLineMarker) + session.removeMarker(session.$highlightLineMarker); + + session.$highlightLineMarker = null; + + if (this.$highlightActiveLine) { + var cursor = this.getCursorPosition(); + var foldLine = this.session.getFoldLine(cursor.row); + + if ((this.getSelectionStyle() != "line" || !this.selection.isMultiLine())) { + var range; + if (foldLine) { + range = new Range(foldLine.start.row, 0, foldLine.end.row + 1, 0); + } else { + range = new Range(cursor.row, 0, cursor.row+1, 0); + } + session.$highlightLineMarker = session.addMarker(range, "ace_active_line", "background"); + } + } + }; + + + this.onSelectionChange = function(e) { + var session = this.session; + + if (session.$selectionMarker) { + session.removeMarker(session.$selectionMarker); + } + session.$selectionMarker = null; + + if (!this.selection.isEmpty()) { + var range = this.selection.getRange(); + var style = this.getSelectionStyle(); + session.$selectionMarker = session.addMarker(range, "ace_selection", style); + } else { + this.$updateHighlightActiveLine(); + } + + var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp() + this.session.highlight(re); + + this._emit("changeSelection"); + }; + + this.$getSelectionHighLightRegexp = function() { + var session = this.session; + + var selection = this.getSelectionRange(); + if (selection.isEmpty() || selection.isMultiLine()) + return; + + var startOuter = selection.start.column - 1; + var endOuter = selection.end.column + 1; + var line = session.getLine(selection.start.row); + var lineCols = line.length; + var needle = line.substring(Math.max(startOuter, 0), + Math.min(endOuter, lineCols)); + + // Make sure the outer characters are not part of the word. + if ((startOuter >= 0 && /^[\w\d]/.test(needle)) || + (endOuter <= lineCols && /[\w\d]$/.test(needle))) + return; + + needle = line.substring(selection.start.column, selection.end.column); + if (!/^[\w\d]+$/.test(needle)) + return; + + var re = this.$search.$assembleRegExp({ + wholeWord: true, + caseSensitive: true, + needle: needle + }); + + return re; + }; + + + this.onChangeFrontMarker = function() { + this.renderer.updateFrontMarkers(); + }; + + this.onChangeBackMarker = function() { + this.renderer.updateBackMarkers(); + }; + + + this.onChangeBreakpoint = function() { + this.renderer.updateBreakpoints(); + }; + + this.onChangeAnnotation = function() { + this.renderer.setAnnotations(this.session.getAnnotations()); + }; + + + this.onChangeMode = function() { + this.renderer.updateText(); + }; + + + this.onChangeWrapLimit = function() { + this.renderer.updateFull(); + }; + + this.onChangeWrapMode = function() { + this.renderer.onResize(true); + }; + + + this.onChangeFold = function() { + // Update the active line marker as due to folding changes the current + // line range on the screen might have changed. + this.$updateHighlightActiveLine(); + // TODO: This might be too much updating. Okay for now. + this.renderer.updateFull(); + }; + /** + * Editor@copy(text) + * - text (String): The copied text + * + * Emitted when text is copied. + **/ + this.getCopyText = function() { + var text = ""; + if (!this.selection.isEmpty()) + text = this.session.getTextRange(this.getSelectionRange()); + + this._emit("copy", text); + return text; + }; + this.onCopy = function() { + this.commands.exec("copy", this); + }; + this.onCut = function() { + this.commands.exec("cut", this); + }; + /** + * Editor@paste(text) + * - text (String): The pasted text + * + * Emitted when text is pasted. + **/ + this.onPaste = function(text) { + // todo this should change when paste becomes a command + if (this.$readOnly) + return; + this._emit("paste", text); + this.insert(text); + }; + this.insert = function(text) { + var session = this.session; + var mode = session.getMode(); + + var cursor = this.getCursorPosition(); + + if (this.getBehavioursEnabled()) { + // Get a transform if the current mode wants one. + var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text); + if (transform) + text = transform.text; + } + + text = text.replace("\t", this.session.getTabString()); + + // remove selected text + if (!this.selection.isEmpty()) { + cursor = this.session.remove(this.getSelectionRange()); + this.clearSelection(); + } + else if (this.session.getOverwrite()) { + var range = new Range.fromPoints(cursor, cursor); + range.end.column += text.length; + this.session.remove(range); + } + + this.clearSelection(); + + var start = cursor.column; + var lineState = session.getState(cursor.row); + var shouldOutdent = mode.checkOutdent(lineState, session.getLine(cursor.row), text); + var line = session.getLine(cursor.row); + var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString()); + var end = session.insert(cursor, text); + + if (transform && transform.selection) { + if (transform.selection.length == 2) { // Transform relative to the current column + this.selection.setSelectionRange( + new Range(cursor.row, start + transform.selection[0], + cursor.row, start + transform.selection[1])); + } else { // Transform relative to the current row. + this.selection.setSelectionRange( + new Range(cursor.row + transform.selection[0], + transform.selection[1], + cursor.row + transform.selection[2], + transform.selection[3])); + } + } + + var lineState = session.getState(cursor.row); + + // TODO disabled multiline auto indent + // possibly doing the indent before inserting the text + // if (cursor.row !== end.row) { + if (session.getDocument().isNewLine(text)) { + this.moveCursorTo(cursor.row+1, 0); + + var size = session.getTabSize(); + var minIndent = Number.MAX_VALUE; + + for (var row = cursor.row + 1; row <= end.row; ++row) { + var indent = 0; + + line = session.getLine(row); + for (var i = 0; i < line.length; ++i) + if (line.charAt(i) == '\t') + indent += size; + else if (line.charAt(i) == ' ') + indent += 1; + else + break; + if (/[^\s]/.test(line)) + minIndent = Math.min(indent, minIndent); + } + + for (var row = cursor.row + 1; row <= end.row; ++row) { + var outdent = minIndent; + + line = session.getLine(row); + for (var i = 0; i < line.length && outdent > 0; ++i) + if (line.charAt(i) == '\t') + outdent -= size; + else if (line.charAt(i) == ' ') + outdent -= 1; + session.remove(new Range(row, 0, row, i)); + } + session.indentRows(cursor.row + 1, end.row, lineIndent); + } + if (shouldOutdent) + mode.autoOutdent(lineState, session, cursor.row); + }; + + this.onTextInput = function(text) { + this.keyBinding.onTextInput(text); + }; + + this.onCommandKey = function(e, hashId, keyCode) { + this.keyBinding.onCommandKey(e, hashId, keyCode); + }; + this.setOverwrite = function(overwrite) { + this.session.setOverwrite(overwrite); + }; + this.getOverwrite = function() { + return this.session.getOverwrite(); + }; + this.toggleOverwrite = function() { + this.session.toggleOverwrite(); + }; + this.setScrollSpeed = function(speed) { + this.$mouseHandler.setScrollSpeed(speed); + }; + this.getScrollSpeed = function() { + return this.$mouseHandler.getScrollSpeed(); + }; + this.setDragDelay = function(dragDelay) { + this.$mouseHandler.setDragDelay(dragDelay); + }; + this.getDragDelay = function() { + return this.$mouseHandler.getDragDelay(); + }; + + this.$selectionStyle = "line"; + /** + * Editor@changeSelectionStyle(data) + * - data (Object): Contains one property, `data`, which indicates the new selection style + * + * Emitted when the selection style changes, via [[Editor.setSelectionStyle]]. + * + **/ + this.setSelectionStyle = function(style) { + if (this.$selectionStyle == style) return; + + this.$selectionStyle = style; + this.onSelectionChange(); + this._emit("changeSelectionStyle", {data: style}); + }; + this.getSelectionStyle = function() { + return this.$selectionStyle; + }; + + this.$highlightActiveLine = true; + this.setHighlightActiveLine = function(shouldHighlight) { + if (this.$highlightActiveLine == shouldHighlight) + return; + + this.$highlightActiveLine = shouldHighlight; + this.$updateHighlightActiveLine(); + }; + this.getHighlightActiveLine = function() { + return this.$highlightActiveLine; + }; + + this.$highlightGutterLine = true; + this.setHighlightGutterLine = function(shouldHighlight) { + if (this.$highlightGutterLine == shouldHighlight) + return; + + this.renderer.setHighlightGutterLine(shouldHighlight); + this.$highlightGutterLine = shouldHighlight; + }; + + this.getHighlightGutterLine = function() { + return this.$highlightGutterLine; + }; + + this.$highlightSelectedWord = true; + this.setHighlightSelectedWord = function(shouldHighlight) { + if (this.$highlightSelectedWord == shouldHighlight) + return; + + this.$highlightSelectedWord = shouldHighlight; + this.$onSelectionChange(); + }; + this.getHighlightSelectedWord = function() { + return this.$highlightSelectedWord; + }; + + this.setAnimatedScroll = function(shouldAnimate){ + this.renderer.setAnimatedScroll(shouldAnimate); + }; + + this.getAnimatedScroll = function(){ + return this.renderer.getAnimatedScroll(); + }; + this.setShowInvisibles = function(showInvisibles) { + this.renderer.setShowInvisibles(showInvisibles); + }; + this.getShowInvisibles = function() { + return this.renderer.getShowInvisibles(); + }; + + this.setDisplayIndentGuides = function(display) { + this.renderer.setDisplayIndentGuides(display); + }; + + this.getDisplayIndentGuides = function() { + return this.renderer.getDisplayIndentGuides(); + }; + this.setShowPrintMargin = function(showPrintMargin) { + this.renderer.setShowPrintMargin(showPrintMargin); + }; + this.getShowPrintMargin = function() { + return this.renderer.getShowPrintMargin(); + }; + this.setPrintMarginColumn = function(showPrintMargin) { + this.renderer.setPrintMarginColumn(showPrintMargin); + }; + this.getPrintMarginColumn = function() { + return this.renderer.getPrintMarginColumn(); + }; + + this.$readOnly = false; + this.setReadOnly = function(readOnly) { + this.$readOnly = readOnly; + }; + this.getReadOnly = function() { + return this.$readOnly; + }; + + this.$modeBehaviours = true; + this.setBehavioursEnabled = function (enabled) { + this.$modeBehaviours = enabled; + }; + this.getBehavioursEnabled = function () { + return this.$modeBehaviours; + }; + this.setShowFoldWidgets = function(show) { + var gutter = this.renderer.$gutterLayer; + if (gutter.getShowFoldWidgets() == show) + return; + + this.renderer.$gutterLayer.setShowFoldWidgets(show); + this.$showFoldWidgets = show; + this.renderer.updateFull(); + }; + this.getShowFoldWidgets = function() { + return this.renderer.$gutterLayer.getShowFoldWidgets(); + }; + + this.setFadeFoldWidgets = function(show) { + this.renderer.setFadeFoldWidgets(show); + }; + + this.getFadeFoldWidgets = function() { + return this.renderer.getFadeFoldWidgets(); + }; + this.remove = function(dir) { + if (this.selection.isEmpty()){ + if (dir == "left") + this.selection.selectLeft(); + else + this.selection.selectRight(); + } + + var range = this.getSelectionRange(); + if (this.getBehavioursEnabled()) { + var session = this.session; + var state = session.getState(range.start.row); + var new_range = session.getMode().transformAction(state, 'deletion', this, session, range); + if (new_range) + range = new_range; + } + + this.session.remove(range); + this.clearSelection(); + }; + this.removeWordRight = function() { + if (this.selection.isEmpty()) + this.selection.selectWordRight(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeWordLeft = function() { + if (this.selection.isEmpty()) + this.selection.selectWordLeft(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeToLineStart = function() { + if (this.selection.isEmpty()) + this.selection.selectLineStart(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeToLineEnd = function() { + if (this.selection.isEmpty()) + this.selection.selectLineEnd(); + + var range = this.getSelectionRange(); + if (range.start.column == range.end.column && range.start.row == range.end.row) { + range.end.column = 0; + range.end.row++; + } + + this.session.remove(range); + this.clearSelection(); + }; + this.splitLine = function() { + if (!this.selection.isEmpty()) { + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + } + + var cursor = this.getCursorPosition(); + this.insert("\n"); + this.moveCursorToPosition(cursor); + }; + this.transposeLetters = function() { + if (!this.selection.isEmpty()) { + return; + } + + var cursor = this.getCursorPosition(); + var column = cursor.column; + if (column === 0) + return; + + var line = this.session.getLine(cursor.row); + var swap, range; + if (column < line.length) { + swap = line.charAt(column) + line.charAt(column-1); + range = new Range(cursor.row, column-1, cursor.row, column+1); + } + else { + swap = line.charAt(column-1) + line.charAt(column-2); + range = new Range(cursor.row, column-2, cursor.row, column); + } + this.session.replace(range, swap); + }; + this.toLowerCase = function() { + var originalRange = this.getSelectionRange(); + if (this.selection.isEmpty()) { + this.selection.selectWord(); + } + + var range = this.getSelectionRange(); + var text = this.session.getTextRange(range); + this.session.replace(range, text.toLowerCase()); + this.selection.setSelectionRange(originalRange); + }; + this.toUpperCase = function() { + var originalRange = this.getSelectionRange(); + if (this.selection.isEmpty()) { + this.selection.selectWord(); + } + + var range = this.getSelectionRange(); + var text = this.session.getTextRange(range); + this.session.replace(range, text.toUpperCase()); + this.selection.setSelectionRange(originalRange); + }; + this.indent = function() { + var session = this.session; + var range = this.getSelectionRange(); + + if (range.start.row < range.end.row || range.start.column < range.end.column) { + var rows = this.$getSelectedRows(); + session.indentRows(rows.first, rows.last, "\t"); + } else { + var indentString; + + if (this.session.getUseSoftTabs()) { + var size = session.getTabSize(), + position = this.getCursorPosition(), + column = session.documentToScreenColumn(position.row, position.column), + count = (size - column % size); + + indentString = lang.stringRepeat(" ", count); + } else + indentString = "\t"; + return this.insert(indentString); + } + }; + this.blockOutdent = function() { + var selection = this.session.getSelection(); + this.session.outdentRows(selection.getRange()); + }; + this.toggleCommentLines = function() { + var state = this.session.getState(this.getCursorPosition().row); + var rows = this.$getSelectedRows(); + this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last); + }; + this.removeLines = function() { + var rows = this.$getSelectedRows(); + var range; + if (rows.first === 0 || rows.last+1 < this.session.getLength()) + range = new Range(rows.first, 0, rows.last+1, 0); + else + range = new Range( + rows.first-1, this.session.getLine(rows.first-1).length, + rows.last, this.session.getLine(rows.last).length + ); + this.session.remove(range); + this.clearSelection(); + }; + + this.duplicateSelection = function() { + var sel = this.selection; + var doc = this.session; + var range = sel.getRange(); + if (range.isEmpty()) { + var row = range.start.row; + doc.duplicateLines(row, row); + } else { + var reverse = sel.isBackwards() + var point = sel.isBackwards() ? range.start : range.end; + var endPoint = doc.insert(point, doc.getTextRange(range), false); + range.start = point; + range.end = endPoint; + + sel.setSelectionRange(range, reverse) + } + }; + this.moveLinesDown = function() { + this.$moveLines(function(firstRow, lastRow) { + return this.session.moveLinesDown(firstRow, lastRow); + }); + }; + this.moveLinesUp = function() { + this.$moveLines(function(firstRow, lastRow) { + return this.session.moveLinesUp(firstRow, lastRow); + }); + }; + this.moveText = function(range, toPosition) { + if (this.$readOnly) + return null; + + return this.session.moveText(range, toPosition); + }; + this.copyLinesUp = function() { + this.$moveLines(function(firstRow, lastRow) { + this.session.duplicateLines(firstRow, lastRow); + return 0; + }); + }; + this.copyLinesDown = function() { + this.$moveLines(function(firstRow, lastRow) { + return this.session.duplicateLines(firstRow, lastRow); + }); + }; + this.$moveLines = function(mover) { + var rows = this.$getSelectedRows(); + var selection = this.selection; + if (!selection.isMultiLine()) { + var range = selection.getRange(); + var reverse = selection.isBackwards(); + } + + var linesMoved = mover.call(this, rows.first, rows.last); + + if (range) { + range.start.row += linesMoved; + range.end.row += linesMoved; + selection.setSelectionRange(range, reverse); + } + else { + selection.setSelectionAnchor(rows.last+linesMoved+1, 0); + selection.$moveSelection(function() { + selection.moveCursorTo(rows.first+linesMoved, 0); + }); + } + }; + this.$getSelectedRows = function() { + var range = this.getSelectionRange().collapseRows(); + + return { + first: range.start.row, + last: range.end.row + }; + }; + + this.onCompositionStart = function(text) { + this.renderer.showComposition(this.getCursorPosition()); + }; + + this.onCompositionUpdate = function(text) { + this.renderer.setCompositionText(text); + }; + + this.onCompositionEnd = function() { + this.renderer.hideComposition(); + }; + this.getFirstVisibleRow = function() { + return this.renderer.getFirstVisibleRow(); + }; + this.getLastVisibleRow = function() { + return this.renderer.getLastVisibleRow(); + }; + this.isRowVisible = function(row) { + return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow()); + }; + this.isRowFullyVisible = function(row) { + return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow()); + }; + this.$getVisibleRowCount = function() { + return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1; + }; + + this.$moveByPage = function(dir, select) { + var renderer = this.renderer; + var config = this.renderer.layerConfig; + var rows = dir * Math.floor(config.height / config.lineHeight); + + this.$blockScrolling++; + if (select == true) { + this.selection.$moveSelection(function(){ + this.moveCursorBy(rows, 0); + }); + } else if (select == false) { + this.selection.moveCursorBy(rows, 0); + this.selection.clearSelection(); + } + this.$blockScrolling--; + + var scrollTop = renderer.scrollTop; + + renderer.scrollBy(0, rows * config.lineHeight); + if (select != null) + renderer.scrollCursorIntoView(null, 0.5); + + renderer.animateScrolling(scrollTop); + }; + this.selectPageDown = function() { + this.$moveByPage(1, true); + }; + this.selectPageUp = function() { + this.$moveByPage(-1, true); + }; + this.gotoPageDown = function() { + this.$moveByPage(1, false); + }; + this.gotoPageUp = function() { + this.$moveByPage(-1, false); + }; + this.scrollPageDown = function() { + this.$moveByPage(1); + }; + this.scrollPageUp = function() { + this.$moveByPage(-1); + }; + this.scrollToRow = function(row) { + this.renderer.scrollToRow(row); + }; + this.scrollToLine = function(line, center, animate, callback) { + this.renderer.scrollToLine(line, center, animate, callback); + }; + this.centerSelection = function() { + var range = this.getSelectionRange(); + var pos = { + row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2), + column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2) + } + this.renderer.alignCursor(pos, 0.5); + }; + this.getCursorPosition = function() { + return this.selection.getCursor(); + }; + this.getCursorPositionScreen = function() { + return this.session.documentToScreenPosition(this.getCursorPosition()); + }; + this.getSelectionRange = function() { + return this.selection.getRange(); + }; + this.selectAll = function() { + this.$blockScrolling += 1; + this.selection.selectAll(); + this.$blockScrolling -= 1; + }; + this.clearSelection = function() { + this.selection.clearSelection(); + }; + this.moveCursorTo = function(row, column) { + this.selection.moveCursorTo(row, column); + }; + this.moveCursorToPosition = function(pos) { + this.selection.moveCursorToPosition(pos); + }; + this.jumpToMatching = function(select) { + var cursor = this.getCursorPosition(); + + var range = this.session.getBracketRange(cursor); + if (!range) { + range = this.find({ + needle: /[{}()\[\]]/g, + preventScroll:true, + start: {row: cursor.row, column: cursor.column - 1} + }); + if (!range) + return; + var pos = range.start; + if (pos.row == cursor.row && Math.abs(pos.column - cursor.column) < 2) + range = this.session.getBracketRange(pos); + } + + pos = range && range.cursor || pos; + if (pos) { + if (select) { + if (range && range.isEqual(this.getSelectionRange())) + this.clearSelection(); + else + this.selection.selectTo(pos.row, pos.column); + } else { + this.clearSelection(); + this.moveCursorTo(pos.row, pos.column); + } + } + }; + this.gotoLine = function(lineNumber, column, animate) { + this.selection.clearSelection(); + this.session.unfold({row: lineNumber - 1, column: column || 0}); + + this.$blockScrolling += 1; + this.moveCursorTo(lineNumber - 1, column || 0); + this.$blockScrolling -= 1; + + if (!this.isRowFullyVisible(lineNumber - 1)) + this.scrollToLine(lineNumber - 1, true, animate); + }; + this.navigateTo = function(row, column) { + this.clearSelection(); + this.moveCursorTo(row, column); + }; + this.navigateUp = function(times) { + this.selection.clearSelection(); + times = times || 1; + this.selection.moveCursorBy(-times, 0); + }; + this.navigateDown = function(times) { + this.selection.clearSelection(); + times = times || 1; + this.selection.moveCursorBy(times, 0); + }; + this.navigateLeft = function(times) { + if (!this.selection.isEmpty()) { + var selectionStart = this.getSelectionRange().start; + this.moveCursorToPosition(selectionStart); + } + else { + times = times || 1; + while (times--) { + this.selection.moveCursorLeft(); + } + } + this.clearSelection(); + }; + this.navigateRight = function(times) { + if (!this.selection.isEmpty()) { + var selectionEnd = this.getSelectionRange().end; + this.moveCursorToPosition(selectionEnd); + } + else { + times = times || 1; + while (times--) { + this.selection.moveCursorRight(); + } + } + this.clearSelection(); + }; + this.navigateLineStart = function() { + this.selection.moveCursorLineStart(); + this.clearSelection(); + }; + this.navigateLineEnd = function() { + this.selection.moveCursorLineEnd(); + this.clearSelection(); + }; + this.navigateFileEnd = function() { + var scrollTop = this.renderer.scrollTop; + this.selection.moveCursorFileEnd(); + this.clearSelection(); + this.renderer.animateScrolling(scrollTop); + }; + this.navigateFileStart = function() { + var scrollTop = this.renderer.scrollTop; + this.selection.moveCursorFileStart(); + this.clearSelection(); + this.renderer.animateScrolling(scrollTop); + }; + this.navigateWordRight = function() { + this.selection.moveCursorWordRight(); + this.clearSelection(); + }; + this.navigateWordLeft = function() { + this.selection.moveCursorWordLeft(); + this.clearSelection(); + }; + this.replace = function(replacement, options) { + if (options) + this.$search.set(options); + + var range = this.$search.find(this.session); + var replaced = 0; + if (!range) + return replaced; + + if (this.$tryReplace(range, replacement)) { + replaced = 1; + } + if (range !== null) { + this.selection.setSelectionRange(range); + this.renderer.scrollSelectionIntoView(range.start, range.end); + } + + return replaced; + }; + this.replaceAll = function(replacement, options) { + if (options) { + this.$search.set(options); + } + + var ranges = this.$search.findAll(this.session); + var replaced = 0; + if (!ranges.length) + return replaced; + + this.$blockScrolling += 1; + + var selection = this.getSelectionRange(); + this.clearSelection(); + this.selection.moveCursorTo(0, 0); + + for (var i = ranges.length - 1; i >= 0; --i) { + if(this.$tryReplace(ranges[i], replacement)) { + replaced++; + } + } + + this.selection.setSelectionRange(selection); + this.$blockScrolling -= 1; + + return replaced; + }; + + this.$tryReplace = function(range, replacement) { + var input = this.session.getTextRange(range); + replacement = this.$search.replace(input, replacement); + if (replacement !== null) { + range.end = this.session.replace(range, replacement); + return range; + } else { + return null; + } + }; + this.getLastSearchOptions = function() { + return this.$search.getOptions(); + }; + this.find = function(needle, options, animate) { + if (!options) + options = {}; + + if (typeof needle == "string" || needle instanceof RegExp) + options.needle = needle; + else if (typeof needle == "object") + oop.mixin(options, needle); + + var range = this.selection.getRange(); + if (options.needle == null) { + needle = this.session.getTextRange(range) + || this.$search.$options.needle; + if (!needle) { + range = this.session.getWordRange(range.start.row, range.start.column); + needle = this.session.getTextRange(range); + } + this.$search.set({needle: needle}); + } + + this.$search.set(options); + if (!options.start) + this.$search.set({start: range}); + + var newRange = this.$search.find(this.session); + if (options.preventScroll) + return newRange; + if (newRange) { + this.revealRange(newRange, animate); + return newRange; + } + // clear selection if nothing is found + if (options.backwards) + range.start = range.end; + else + range.end = range.start; + this.selection.setRange(range); + }; + this.findNext = function(options, animate) { + this.find({skipCurrent: true, backwards: false}, options, animate); + }; + this.findPrevious = function(options, animate) { + this.find(options, {skipCurrent: true, backwards: true}, animate); + }; + + this.revealRange = function(range, animate) { + this.$blockScrolling += 1; + this.session.unfold(range); + this.selection.setSelectionRange(range); + this.$blockScrolling -= 1; + + var scrollTop = this.renderer.scrollTop; + this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5); + if (animate != false) + this.renderer.animateScrolling(scrollTop); + }; + this.undo = function() { + this.$blockScrolling++; + this.session.getUndoManager().undo(); + this.$blockScrolling--; + this.renderer.scrollCursorIntoView(null, 0.5); + }; + this.redo = function() { + this.$blockScrolling++; + this.session.getUndoManager().redo(); + this.$blockScrolling--; + this.renderer.scrollCursorIntoView(null, 0.5); + }; + this.destroy = function() { + this.renderer.destroy(); + }; + +}).call(Editor.prototype); + + +exports.Editor = Editor; +}); + +ace.define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) { + + +exports.stringReverse = function(string) { + return string.split("").reverse().join(""); +}; + +exports.stringRepeat = function (string, count) { + return new Array(count + 1).join(string); +}; + +var trimBeginRegexp = /^\s\s*/; +var trimEndRegexp = /\s\s*$/; + +exports.stringTrimLeft = function (string) { + return string.replace(trimBeginRegexp, ''); +}; + +exports.stringTrimRight = function (string) { + return string.replace(trimEndRegexp, ''); +}; + +exports.copyObject = function(obj) { + var copy = {}; + for (var key in obj) { + copy[key] = obj[key]; + } + return copy; +}; + +exports.copyArray = function(array){ + var copy = []; + for (var i=0, l=array.length; i 1) { + if (value.charAt(0) == PLACEHOLDER) + value = value.substr(1); + else if (value.charAt(value.length - 1) == PLACEHOLDER) + value = value.slice(0, -1); + } + + if (value && value != PLACEHOLDER) { + if (pasted) + host.onPaste(value); + else + host.onTextInput(value); + } + } + } + + copied = false; + pasted = false; + + // Safari doesn't fire copy events if no text is selected + reset(true); + } + + var onTextInput = function(e) { + if (!inCompostion) + sendText(e.data); + setTimeout(function () { + if (!inCompostion) + reset(true); + }, 0); + }; + + var onPropertyChange = function(e) { + setTimeout(function() { + if (!inCompostion) + if(text.value != "") { + sendText(); + } + }, 0); + }; + + var onCompositionStart = function(e) { + inCompostion = true; + host.onCompositionStart(); + setTimeout(onCompositionUpdate, 0); + }; + + var onCompositionUpdate = function() { + if (!inCompostion) return; + host.onCompositionUpdate(text.value); + }; + + var onCompositionEnd = function(e) { + inCompostion = false; + host.onCompositionEnd(); + }; + + var onCopy = function(e) { + copied = true; + var copyText = host.getCopyText(); + if(copyText) + text.value = copyText; + else + e.preventDefault(); + reset(); + setTimeout(function () { + sendText(); + }, 0); + }; + + var onCut = function(e) { + copied = true; + var copyText = host.getCopyText(); + if(copyText) { + text.value = copyText; + host.onCut(); + } else + e.preventDefault(); + reset(); + setTimeout(function () { + sendText(); + }, 0); + }; + + event.addCommandKeyListener(text, host.onCommandKey.bind(host)); + event.addListener(text, "input", onTextInput); + + if (useragent.isOldIE) { + var keytable = { 13:1, 27:1 }; + event.addListener(text, "keyup", function (e) { + if (inCompostion && (!text.value || keytable[e.keyCode])) + setTimeout(onCompositionEnd, 0); + if ((text.value.charCodeAt(0)|0) < 129) { + return; + } + inCompostion ? onCompositionUpdate() : onCompositionStart(); + }); + + event.addListener(text, "propertychange", function() { + if (text.value != PLACEHOLDER) + setTimeout(sendText, 0); + }); + } + + event.addListener(text, "paste", function(e) { + // Mark that the next input text comes from past. + pasted = true; + // Some browsers support the event.clipboardData API. Use this to get + // the pasted content which increases speed if pasting a lot of lines. + if (e.clipboardData && e.clipboardData.getData) { + sendText(e.clipboardData.getData("text/plain")); + e.preventDefault(); + } + else { + // If a browser doesn't support any of the things above, use the regular + // method to detect the pasted input. + onPropertyChange(); + } + }); + + if ("onbeforecopy" in text && typeof clipboardData !== "undefined") { + event.addListener(text, "beforecopy", function(e) { + if (tempStyle) + return; // without this text is copied when contextmenu is shown + var copyText = host.getCopyText(); + if (copyText) + clipboardData.setData("Text", copyText); + else + e.preventDefault(); + }); + event.addListener(parentNode, "keydown", function(e) { + if (e.ctrlKey && e.keyCode == 88) { + var copyText = host.getCopyText(); + if (copyText) { + clipboardData.setData("Text", copyText); + host.onCut(); + } + event.preventDefault(e); + } + }); + event.addListener(text, "cut", onCut); // for ie9 context menu + } + else if (useragent.isOpera && !("KeyboardEvent" in window)) { + event.addListener(parentNode, "keydown", function(e) { + if ((useragent.isMac && !e.metaKey) || !e.ctrlKey) + return; + + if ((e.keyCode == 88 || e.keyCode == 67)) { + var copyText = host.getCopyText(); + if (copyText) { + text.value = copyText; + text.select(); + if (e.keyCode == 88) + host.onCut(); + } + } + }); + } + else { + event.addListener(text, "copy", onCopy); + event.addListener(text, "cut", onCut); + } + + event.addListener(text, "compositionstart", onCompositionStart); + if (useragent.isGecko) { + event.addListener(text, "text", onCompositionUpdate); + } + if (useragent.isWebKit) { + event.addListener(text, "keyup", onCompositionUpdate); + } + event.addListener(text, "compositionend", onCompositionEnd); + + event.addListener(text, "blur", function() { + host.onBlur(); + }); + + event.addListener(text, "focus", function() { + host.onFocus(); + reset(); + }); + + this.focus = function() { + reset(); + text.focus(); + }; + + this.blur = function() { + text.blur(); + }; + + function isFocused() { + return document.activeElement === text; + } + this.isFocused = isFocused; + + this.getElement = function() { + return text; + }; + + this.onContextMenu = function(e) { + if (!tempStyle) + tempStyle = text.style.cssText; + + text.style.cssText = + "position:fixed; z-index:100000;" + + (useragent.isIE ? "background:rgba(0, 0, 0, 0.03); opacity:0.1;" : "") + //"background:rgba(250, 0, 0, 0.3); opacity:1;" + + "left:" + (e.clientX - 2) + "px; top:" + (e.clientY - 2) + "px;"; + + if (host.selection.isEmpty()) + text.value = ""; + else + reset(true); + + if (e.type != "mousedown") + return; + + if (host.renderer.$keepTextAreaAtCursor) + host.renderer.$keepTextAreaAtCursor = null; + + // on windows context menu is opened after mouseup + if (useragent.isWin && (useragent.isGecko || useragent.isIE)) + event.capture(host.container, function(e) { + text.style.left = e.clientX - 2 + "px"; + text.style.top = e.clientY - 2 + "px"; + }, onContextMenuClose); + }; + + function onContextMenuClose() { + setTimeout(function () { + if (tempStyle) { + text.style.cssText = tempStyle; + tempStyle = ''; + } + sendText(); + if (host.renderer.$keepTextAreaAtCursor == null) { + host.renderer.$keepTextAreaAtCursor = true; + host.renderer.$moveTextAreaToCursor(); + } + }, 0); + }; + this.onContextMenuClose = onContextMenuClose; + + // firefox fires contextmenu event after opening it + if (!useragent.isGecko) + event.addListener(text, "contextmenu", function(e) { + host.textInput.onContextMenu(e); + onContextMenuClose() + }); +}; + +exports.TextInput = TextInput; +}); + +ace.define('ace/mouse/mouse_handler', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/lib/useragent', 'ace/mouse/default_handlers', 'ace/mouse/default_gutter_handler', 'ace/mouse/mouse_event', 'ace/mouse/dragdrop'], function(require, exports, module) { + + +var event = require("../lib/event"); +var useragent = require("../lib/useragent"); +var DefaultHandlers = require("./default_handlers").DefaultHandlers; +var DefaultGutterHandler = require("./default_gutter_handler").GutterHandler; +var MouseEvent = require("./mouse_event").MouseEvent; +var DragdropHandler = require("./dragdrop").DragdropHandler; + +var MouseHandler = function(editor) { + this.editor = editor; + + new DefaultHandlers(this); + new DefaultGutterHandler(this); + new DragdropHandler(this); + + event.addListener(editor.container, "mousedown", function(e) { + editor.focus(); + return event.preventDefault(e); + }); + + var mouseTarget = editor.renderer.getMouseEventTarget(); + event.addListener(mouseTarget, "click", this.onMouseEvent.bind(this, "click")); + event.addListener(mouseTarget, "mousemove", this.onMouseMove.bind(this, "mousemove")); + event.addMultiMouseDownListener(mouseTarget, [300, 300, 250], this, "onMouseEvent"); + event.addMouseWheelListener(editor.container, this.onMouseWheel.bind(this, "mousewheel")); + + var gutterEl = editor.renderer.$gutter; + event.addListener(gutterEl, "mousedown", this.onMouseEvent.bind(this, "guttermousedown")); + event.addListener(gutterEl, "click", this.onMouseEvent.bind(this, "gutterclick")); + event.addListener(gutterEl, "dblclick", this.onMouseEvent.bind(this, "gutterdblclick")); + event.addListener(gutterEl, "mousemove", this.onMouseEvent.bind(this, "guttermousemove")); +}; + +(function() { + + this.$scrollSpeed = 1; + this.setScrollSpeed = function(speed) { + this.$scrollSpeed = speed; + }; + + this.getScrollSpeed = function() { + return this.$scrollSpeed; + }; + + this.onMouseEvent = function(name, e) { + this.editor._emit(name, new MouseEvent(e, this.editor)); + }; + + this.$dragDelay = 250; + this.setDragDelay = function(dragDelay) { + this.$dragDelay = dragDelay; + }; + + this.getDragDelay = function() { + return this.$dragDelay; + }; + + this.onMouseMove = function(name, e) { + // optimization, because mousemove doesn't have a default handler. + var listeners = this.editor._eventRegistry && this.editor._eventRegistry.mousemove; + if (!listeners || !listeners.length) + return; + + this.editor._emit(name, new MouseEvent(e, this.editor)); + }; + + this.onMouseWheel = function(name, e) { + var mouseEvent = new MouseEvent(e, this.editor); + mouseEvent.speed = this.$scrollSpeed * 2; + mouseEvent.wheelX = e.wheelX; + mouseEvent.wheelY = e.wheelY; + + this.editor._emit(name, mouseEvent); + }; + + this.setState = function(state) { + this.state = state; + }; + + this.captureMouse = function(ev, state) { + if (state) + this.setState(state); + + this.x = ev.x; + this.y = ev.y; + + // do not move textarea during selection + var renderer = this.editor.renderer; + if (renderer.$keepTextAreaAtCursor) + renderer.$keepTextAreaAtCursor = null; + + var self = this; + var onMouseMove = function(e) { + self.x = e.clientX; + self.y = e.clientY; + }; + + var onCaptureEnd = function(e) { + clearInterval(timerId); + self[self.state + "End"] && self[self.state + "End"](e); + self.$clickSelection = null; + if (renderer.$keepTextAreaAtCursor == null) { + renderer.$keepTextAreaAtCursor = true; + renderer.$moveTextAreaToCursor(); + } + }; + + var onCaptureInterval = function() { + self[self.state] && self[self.state](); + } + + if (useragent.isOldIE && ev.domEvent.type == "dblclick") { + setTimeout(function() { + onCaptureInterval(); + onCaptureEnd(ev.domEvent); + }); + return; + } + + event.capture(this.editor.container, onMouseMove, onCaptureEnd); + var timerId = setInterval(onCaptureInterval, 20); + }; +}).call(MouseHandler.prototype); + +exports.MouseHandler = MouseHandler; +}); + +ace.define('ace/mouse/default_handlers', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/useragent'], function(require, exports, module) { + + +var dom = require("../lib/dom"); +var useragent = require("../lib/useragent"); + +var DRAG_OFFSET = 5; // pixels + +function DefaultHandlers(mouseHandler) { + mouseHandler.$clickSelection = null; + + var editor = mouseHandler.editor; + editor.setDefaultHandler("mousedown", this.onMouseDown.bind(mouseHandler)); + editor.setDefaultHandler("dblclick", this.onDoubleClick.bind(mouseHandler)); + editor.setDefaultHandler("tripleclick", this.onTripleClick.bind(mouseHandler)); + editor.setDefaultHandler("quadclick", this.onQuadClick.bind(mouseHandler)); + editor.setDefaultHandler("mousewheel", this.onScroll.bind(mouseHandler)); + + var exports = ["select", "startSelect", "drag", "dragEnd", "dragWait", + "dragWaitEnd", "startDrag", "focusWait"]; + + exports.forEach(function(x) { + mouseHandler[x] = this[x]; + }, this); + + mouseHandler.selectByLines = this.extendSelectionBy.bind(mouseHandler, "getLineRange"); + mouseHandler.selectByWords = this.extendSelectionBy.bind(mouseHandler, "getWordRange"); + + mouseHandler.$focusWaitTimout = 250; +} + +(function() { + + this.onMouseDown = function(ev) { + var inSelection = ev.inSelection(); + var pos = ev.getDocumentPosition(); + this.mousedownEvent = ev; + var editor = this.editor; + + var button = ev.getButton(); + if (button !== 0) { + var selectionRange = editor.getSelectionRange(); + var selectionEmpty = selectionRange.isEmpty(); + + if (selectionEmpty) { + editor.moveCursorToPosition(pos); + editor.selection.clearSelection(); + } + + // 2: contextmenu, 1: linux paste + editor.textInput.onContextMenu(ev.domEvent); + return; // stopping event here breaks contextmenu on ff mac + } + + // if this click caused the editor to be focused should not clear the + // selection + if (inSelection && !editor.isFocused()) { + editor.focus(); + if (this.$focusWaitTimout && !this.$clickSelection) { + this.setState("focusWait"); + this.captureMouse(ev); + return ev.preventDefault(); + } + } + + if (!inSelection || this.$clickSelection || ev.getShiftKey()) { + // Directly pick STATE_SELECT, since the user is not clicking inside + // a selection. + this.startSelect(pos); + } else if (inSelection) { + this.mousedownEvent.time = (new Date()).getTime(); + this.setState("dragWait"); + } + + this.captureMouse(ev); + return ev.preventDefault(); + }; + + this.startSelect = function(pos) { + pos = pos || this.editor.renderer.screenToTextCoordinates(this.x, this.y); + if (this.mousedownEvent.getShiftKey()) { + this.editor.selection.selectToPosition(pos); + } + else if (!this.$clickSelection) { + this.editor.moveCursorToPosition(pos); + this.editor.selection.clearSelection(); + } + this.setState("select"); + }; + + this.select = function() { + var anchor, editor = this.editor; + var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); + + if (this.$clickSelection) { + var cmp = this.$clickSelection.comparePoint(cursor); + + if (cmp == -1) { + anchor = this.$clickSelection.end; + } else if (cmp == 1) { + anchor = this.$clickSelection.start; + } else { + var orientedRange = calcRangeOrientation(this.$clickSelection, cursor); + cursor = orientedRange.cursor; + anchor = orientedRange.anchor; + } + editor.selection.setSelectionAnchor(anchor.row, anchor.column); + } + editor.selection.selectToPosition(cursor); + + editor.renderer.scrollCursorIntoView(); + }; + + this.extendSelectionBy = function(unitName) { + var anchor, editor = this.editor; + var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); + var range = editor.selection[unitName](cursor.row, cursor.column); + + if (this.$clickSelection) { + var cmpStart = this.$clickSelection.comparePoint(range.start); + var cmpEnd = this.$clickSelection.comparePoint(range.end); + + if (cmpStart == -1 && cmpEnd <= 0) { + anchor = this.$clickSelection.end; + if (range.end.row != cursor.row || range.end.column != cursor.column) + cursor = range.start; + } else if (cmpEnd == 1 && cmpStart >= 0) { + anchor = this.$clickSelection.start; + if (range.start.row != cursor.row || range.start.column != cursor.column) + cursor = range.end; + } else if (cmpStart == -1 && cmpEnd == 1) { + cursor = range.end; + anchor = range.start; + } else { + var orientedRange = calcRangeOrientation(this.$clickSelection, cursor); + cursor = orientedRange.cursor; + anchor = orientedRange.anchor; + } + editor.selection.setSelectionAnchor(anchor.row, anchor.column); + } + editor.selection.selectToPosition(cursor); + + editor.renderer.scrollCursorIntoView(); + }; + + this.startDrag = function() { + var editor = this.editor; + this.setState("drag"); + this.dragRange = editor.getSelectionRange(); + var style = editor.getSelectionStyle(); + this.dragSelectionMarker = editor.session.addMarker(this.dragRange, "ace_selection", style); + editor.clearSelection(); + dom.addCssClass(editor.container, "ace_dragging"); + if (!this.$dragKeybinding) { + this.$dragKeybinding = { + handleKeyboard: function(data, hashId, keyString, keyCode) { + if (keyString == "esc") + return {command: this.command}; + }, + command: { + exec: function(editor) { + var self = editor.$mouseHandler; + self.dragCursor = null; + self.dragEnd(); + self.startSelect(); + } + } + } + } + + editor.keyBinding.addKeyboardHandler(this.$dragKeybinding); + }; + + this.focusWait = function() { + var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + var time = (new Date()).getTime(); + + if (distance > DRAG_OFFSET ||time - this.mousedownEvent.time > this.$focusWaitTimout) + this.startSelect(); + }; + + this.dragWait = function(e) { + var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + var time = (new Date()).getTime(); + var editor = this.editor; + + if (distance > DRAG_OFFSET) { + this.startSelect(this.mousedownEvent.getDocumentPosition()); + } else if (time - this.mousedownEvent.time > editor.getDragDelay()) { + this.startDrag(); + } + }; + + this.dragWaitEnd = function(e) { + this.mousedownEvent.domEvent = e; + this.startSelect(); + }; + + this.drag = function() { + var editor = this.editor; + this.dragCursor = editor.renderer.screenToTextCoordinates(this.x, this.y); + editor.moveCursorToPosition(this.dragCursor); + editor.renderer.scrollCursorIntoView(); + }; + + this.dragEnd = function(e) { + var editor = this.editor; + var dragCursor = this.dragCursor; + var dragRange = this.dragRange; + dom.removeCssClass(editor.container, "ace_dragging"); + editor.session.removeMarker(this.dragSelectionMarker); + editor.keyBinding.removeKeyboardHandler(this.$dragKeybinding); + + if (!dragCursor) + return; + + editor.clearSelection(); + if (e && (e.ctrlKey || e.altKey)) { + var session = editor.session; + var newRange = dragRange; + newRange.end = session.insert(dragCursor, session.getTextRange(dragRange)); + newRange.start = dragCursor; + } else if (dragRange.contains(dragCursor.row, dragCursor.column)) { + return; + } else { + var newRange = editor.moveText(dragRange, dragCursor); + } + + if (!newRange) + return; + + editor.selection.setSelectionRange(newRange); + }; + + this.onDoubleClick = function(ev) { + var pos = ev.getDocumentPosition(); + var editor = this.editor; + var session = editor.session; + + var range = session.getBracketRange(pos); + if (range) { + if (range.isEmpty()) { + range.start.column--; + range.end.column++; + } + this.$clickSelection = range; + this.setState("select"); + return; + } + + this.$clickSelection = editor.selection.getWordRange(pos.row, pos.column); + this.setState("selectByWords"); + }; + + this.onTripleClick = function(ev) { + var pos = ev.getDocumentPosition(); + var editor = this.editor; + + this.setState("selectByLines"); + this.$clickSelection = editor.selection.getLineRange(pos.row); + }; + + this.onQuadClick = function(ev) { + var editor = this.editor; + + editor.selectAll(); + this.$clickSelection = editor.getSelectionRange(); + this.setState("null"); + }; + + this.onScroll = function(ev) { + var editor = this.editor; + var isScrolable = editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); + if (isScrolable) { + this.$passScrollEvent = false; + } else { + if (this.$passScrollEvent) + return; + + if (!this.$scrollStopTimeout) { + var self = this; + this.$scrollStopTimeout = setTimeout(function() { + self.$passScrollEvent = true; + self.$scrollStopTimeout = null; + }, 200); + } + } + + editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); + return ev.preventDefault(); + }; + +}).call(DefaultHandlers.prototype); + +exports.DefaultHandlers = DefaultHandlers; + +function calcDistance(ax, ay, bx, by) { + return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); +} + +function calcRangeOrientation(range, cursor) { + if (range.start.row == range.end.row) + var cmp = 2 * cursor.column - range.start.column - range.end.column; + else + var cmp = 2 * cursor.row - range.start.row - range.end.row; + + if (cmp < 0) + return {cursor: range.start, anchor: range.end}; + else + return {cursor: range.end, anchor: range.start}; +} + +}); + +ace.define('ace/mouse/default_gutter_handler', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/event'], function(require, exports, module) { + +var dom = require("../lib/dom"); +var event = require("../lib/event"); + +function GutterHandler(mouseHandler) { + var editor = mouseHandler.editor; + var gutter = editor.renderer.$gutterLayer; + + mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) { + if (!editor.isFocused()) + return; + var gutterRegion = gutter.getRegion(e); + + if (gutterRegion) + return; + + var row = e.getDocumentPosition().row; + var selection = editor.session.selection; + + if (e.getShiftKey()) + selection.selectTo(row, 0); + else + mouseHandler.$clickSelection = editor.selection.getLineRange(row); + + mouseHandler.captureMouse(e, "selectByLines"); + return e.preventDefault(); + }); + + + var tooltipTimeout, mouseEvent, tooltip, tooltipAnnotation; + function createTooltip() { + tooltip = dom.createElement("div"); + tooltip.className = "ace_gutter_tooltip"; + tooltip.style.maxWidth = "500px"; + tooltip.style.display = "none"; + editor.container.appendChild(tooltip); + } + + function showTooltip() { + if (!tooltip) { + createTooltip(); + } + var row = mouseEvent.getDocumentPosition().row; + var annotation = gutter.$annotations[row]; + if (!annotation) + return hideTooltip(); + + var maxRow = editor.session.getLength(); + if (row == maxRow) { + var screenRow = editor.renderer.pixelToScreenCoordinates(0, mouseEvent.y).row; + var pos = mouseEvent.$pos; + if (screenRow > editor.session.documentToScreenRow(pos.row, pos.column)) + return hideTooltip(); + } + + if (tooltipAnnotation == annotation) + return; + tooltipAnnotation = annotation.text.join("\n"); + + tooltip.style.display = "block"; + tooltip.innerHTML = tooltipAnnotation; + editor.on("mousewheel", hideTooltip); + + moveTooltip(mouseEvent); + } + + function hideTooltip() { + if (tooltipTimeout) + tooltipTimeout = clearTimeout(tooltipTimeout); + if (tooltipAnnotation) { + tooltip.style.display = "none"; + tooltipAnnotation = null; + editor.removeEventListener("mousewheel", hideTooltip); + } + } + + function moveTooltip(e) { + var rect = editor.renderer.$gutter.getBoundingClientRect(); + tooltip.style.left = e.x - rect.left + 15 + "px"; + if (e.y + 3 * editor.renderer.lineHeight + 15 < rect.bottom) { + tooltip.style.bottom = ""; + tooltip.style.top = e.y - rect.top + 15 + "px"; + } else { + tooltip.style.top = ""; + tooltip.style.bottom = rect.bottom - e.y + 5 + "px"; + } + } + + mouseHandler.editor.setDefaultHandler("guttermousemove", function(e) { + var target = e.domEvent.target || e.domEvent.srcElement; + if (dom.hasCssClass(target, "ace_fold-widget")) + return hideTooltip(); + + if (tooltipAnnotation) + moveTooltip(e); + + mouseEvent = e; + if (tooltipTimeout) + return; + tooltipTimeout = setTimeout(function() { + tooltipTimeout = null; + if (mouseEvent) + showTooltip(); + else + hideTooltip(); + }, 50); + }); + + event.addListener(editor.renderer.$gutter, "mouseout", function(e) { + mouseEvent = null; + if (!tooltipAnnotation || tooltipTimeout) + return; + + tooltipTimeout = setTimeout(function() { + tooltipTimeout = null; + hideTooltip(); + }, 50); + }); + +} + +exports.GutterHandler = GutterHandler; + +}); + +ace.define('ace/mouse/mouse_event', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/lib/useragent'], function(require, exports, module) { + + +var event = require("../lib/event"); +var useragent = require("../lib/useragent"); +var MouseEvent = exports.MouseEvent = function(domEvent, editor) { + this.domEvent = domEvent; + this.editor = editor; + + this.x = this.clientX = domEvent.clientX; + this.y = this.clientY = domEvent.clientY; + + this.$pos = null; + this.$inSelection = null; + + this.propagationStopped = false; + this.defaultPrevented = false; +}; + +(function() { + + this.stopPropagation = function() { + event.stopPropagation(this.domEvent); + this.propagationStopped = true; + }; + + this.preventDefault = function() { + event.preventDefault(this.domEvent); + this.defaultPrevented = true; + }; + + this.stop = function() { + this.stopPropagation(); + this.preventDefault(); + }; + this.getDocumentPosition = function() { + if (this.$pos) + return this.$pos; + + this.$pos = this.editor.renderer.screenToTextCoordinates(this.clientX, this.clientY); + return this.$pos; + }; + this.inSelection = function() { + if (this.$inSelection !== null) + return this.$inSelection; + + var editor = this.editor; + + if (editor.getReadOnly()) { + this.$inSelection = false; + } + else { + var selectionRange = editor.getSelectionRange(); + if (selectionRange.isEmpty()) + this.$inSelection = false; + else { + var pos = this.getDocumentPosition(); + this.$inSelection = selectionRange.contains(pos.row, pos.column); + } + } + return this.$inSelection; + }; + this.getButton = function() { + return event.getButton(this.domEvent); + }; + this.getShiftKey = function() { + return this.domEvent.shiftKey; + }; + + this.getAccelKey = useragent.isMac + ? function() { return this.domEvent.metaKey; } + : function() { return this.domEvent.ctrlKey; }; + +}).call(MouseEvent.prototype); + +}); + +ace.define('ace/mouse/dragdrop', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) { + + +var event = require("../lib/event"); + +var DragdropHandler = function(mouseHandler) { + var editor = mouseHandler.editor; + var dragSelectionMarker, x, y; + var timerId, range, isBackwards; + var dragCursor, counter = 0; + + var mouseTarget = editor.container; + event.addListener(mouseTarget, "dragenter", function(e) { + counter++; + if (!dragSelectionMarker) { + range = editor.getSelectionRange(); + isBackwards = editor.selection.isBackwards(); + var style = editor.getSelectionStyle(); + dragSelectionMarker = editor.session.addMarker(range, "ace_selection", style); + editor.clearSelection(); + clearInterval(timerId); + timerId = setInterval(onDragInterval, 20); + } + return event.preventDefault(e); + }); + + event.addListener(mouseTarget, "dragover", function(e) { + x = e.clientX; + y = e.clientY; + return event.preventDefault(e); + }); + + var onDragInterval = function() { + dragCursor = editor.renderer.screenToTextCoordinates(x, y); + editor.moveCursorToPosition(dragCursor); + editor.renderer.scrollCursorIntoView(); + }; + + event.addListener(mouseTarget, "dragleave", function(e) { + counter--; + if (counter > 0) + return; + console.log(e.type, counter,e.target); + clearInterval(timerId); + editor.session.removeMarker(dragSelectionMarker); + dragSelectionMarker = null; + editor.selection.setSelectionRange(range, isBackwards); + return event.preventDefault(e); + }); + + event.addListener(mouseTarget, "drop", function(e) { + console.log(e.type, counter,e.target); + counter = 0; + clearInterval(timerId); + editor.session.removeMarker(dragSelectionMarker); + dragSelectionMarker = null; + + range.end = editor.session.insert(dragCursor, e.dataTransfer.getData('Text')); + range.start = dragCursor; + editor.focus(); + editor.selection.setSelectionRange(range); + return event.preventDefault(e); + }); + +}; + +exports.DragdropHandler = DragdropHandler; +}); + +ace.define('ace/mouse/fold_handler', ['require', 'exports', 'module' ], function(require, exports, module) { + + +function FoldHandler(editor) { + + editor.on("click", function(e) { + var position = e.getDocumentPosition(); + var session = editor.session; + + // If the user clicked on a fold, then expand it. + var fold = session.getFoldAt(position.row, position.column, 1); + if (fold) { + if (e.getAccelKey()) + session.removeFold(fold); + else + session.expandFold(fold); + + e.stop(); + } + }); + + editor.on("gutterclick", function(e) { + var gutterRegion = editor.renderer.$gutterLayer.getRegion(e); + + if (gutterRegion == "foldWidgets") { + var row = e.getDocumentPosition().row; + var session = editor.session; + if (session.foldWidgets && session.foldWidgets[row]) + editor.session.onFoldWidgetClick(row, e); + e.stop(); + } + }); +} + +exports.FoldHandler = FoldHandler; + +}); + +ace.define('ace/keyboard/keybinding', ['require', 'exports', 'module' , 'ace/lib/keys', 'ace/lib/event'], function(require, exports, module) { + + +var keyUtil = require("../lib/keys"); +var event = require("../lib/event"); + +var KeyBinding = function(editor) { + this.$editor = editor; + this.$data = { }; + this.$handlers = []; + this.setDefaultHandler(editor.commands); +}; + +(function() { + this.setDefaultHandler = function(kb) { + this.removeKeyboardHandler(this.$defaultHandler); + this.$defaultHandler = kb; + this.addKeyboardHandler(kb, 0); + this.$data = {editor: this.$editor}; + }; + + this.setKeyboardHandler = function(kb) { + if (this.$handlers[this.$handlers.length - 1] == kb) + return; + + while (this.$handlers[1]) + this.removeKeyboardHandler(this.$handlers[1]); + + this.addKeyboardHandler(kb, 1); + }; + + this.addKeyboardHandler = function(kb, pos) { + if (!kb) + return; + var i = this.$handlers.indexOf(kb); + if (i != -1) + this.$handlers.splice(i, 1); + + if (pos == undefined) + this.$handlers.push(kb); + else + this.$handlers.splice(pos, 0, kb); + + if (i == -1 && kb.attach) + kb.attach(this.$editor); + }; + + this.removeKeyboardHandler = function(kb) { + var i = this.$handlers.indexOf(kb); + if (i == -1) + return false; + this.$handlers.splice(i, 1); + kb.detach && kb.detach(this.$editor); + return true; + }; + + this.getKeyboardHandler = function() { + return this.$handlers[this.$handlers.length - 1]; + }; + + this.$callKeyboardHandlers = function (hashId, keyString, keyCode, e) { + var toExecute; + for (var i = this.$handlers.length; i--;) { + toExecute = this.$handlers[i].handleKeyboard( + this.$data, hashId, keyString, keyCode, e + ); + if (toExecute && toExecute.command) + break; + } + + if (!toExecute || !toExecute.command) + return false; + + var success = false; + var commands = this.$editor.commands; + + // allow keyboardHandler to consume keys + if (toExecute.command != "null") + success = commands.exec(toExecute.command, this.$editor, toExecute.args, e); + else + success = toExecute.passEvent != true; + + // do not stop input events to not break repeating + if (success && e && hashId != -1) + event.stopEvent(e); + + return success; + }; + + this.onCommandKey = function(e, hashId, keyCode) { + var keyString = keyUtil.keyCodeToString(keyCode); + this.$callKeyboardHandlers(hashId, keyString, keyCode, e); + }; + + this.onTextInput = function(text) { + var success = this.$callKeyboardHandlers(-1, text); + if (!success) + this.$editor.commands.exec("insertstring", this.$editor, text); + }; + +}).call(KeyBinding.prototype); + +exports.KeyBinding = KeyBinding; +}); + +ace.define('ace/edit_session', ['require', 'exports', 'module' , 'ace/config', 'ace/lib/oop', 'ace/lib/lang', 'ace/lib/net', 'ace/lib/event_emitter', 'ace/selection', 'ace/mode/text', 'ace/range', 'ace/document', 'ace/background_tokenizer', 'ace/search_highlight', 'ace/edit_session/folding', 'ace/edit_session/bracket_match'], function(require, exports, module) { + + +var config = require("./config"); +var oop = require("./lib/oop"); +var lang = require("./lib/lang"); +var net = require("./lib/net"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var Selection = require("./selection").Selection; +var TextMode = require("./mode/text").Mode; +var Range = require("./range").Range; +var Document = require("./document").Document; +var BackgroundTokenizer = require("./background_tokenizer").BackgroundTokenizer; +var SearchHighlight = require("./search_highlight").SearchHighlight; + +// events +/** + * EditSession@change(e) + * - e (Object): An object containing a `delta` of information about the change. + * + * Emitted when the document changes. + **/ +/** + * EditSession@changeTabSize() + * + * Emitted when the tab size changes, via [[EditSession.setTabSize]]. + **/ +/** + * EditSession@changeOverwrite() + * + * Emitted when the ability to overwrite text changes, via [[EditSession.setOverwrite]]. + **/ +/** + * EditSession@changeBreakpoint() + * + * Emitted when the gutter changes, either by setting or removing breakpoints, or when the gutter decorations change. + **/ +/** + * EditSession@changeFrontMarker() + * + * Emitted when a front marker changes. + **/ +/** + * EditSession@changeBackMarker() + * + * Emitted when a back marker changes. + **/ +/** + * EditSession@changeAnnotation() + * + * Emitted when an annotation changes, like through [[EditSession.setAnnotations]]. + **/ +/** + * EditSession@tokenizerUpdate(e) + * - e (Object): An object containing one property, `"data"`, that contains information about the changing rows + * + * Emitted when a background tokenizer asynchronously processes new rows. + * + **/ +/** hide + * EditSession@loadMode(e) + * + * + * + **/ +/** + * EditSession@changeMode() + * + * Emitted when the current mode changes. + * + **/ +/** + * EditSession@changeWrapMode() + * + * Emitted when the wrap mode changes. + * + **/ +/** + * EditSession@changeWrapLimit() + * + * Emitted when the wrapping limit changes. + * + **/ +/** + * EditSession@changeFold(e) + * + * Emitted when a code fold is added or removed. + * + **/ + /** + * EditSession@changeScrollTop(scrollTop) + * - scrollTop (Number): The new scroll top value + * + * Emitted when the scroll top changes. + **/ +/** + * EditSession@changeScrollLeft(scrollLeft) + * - scrollLeft (Number): The new scroll left value + * + * Emitted when the scroll left changes. + **/ + + +/** + * new EditSession(text, mode) + * - text (Document | String): If `text` is a `Document`, it associates the `EditSession` with it. Otherwise, a new `Document` is created, with the initial text + * - mode (TextMode): The inital language mode to use for the document + * + * Sets up a new `EditSession` and associates it with the given `Document` and `TextMode`. + * + **/ + +var EditSession = function(text, mode) { + this.$modified = true; + this.$breakpoints = []; + this.$decorations = []; + this.$frontMarkers = {}; + this.$backMarkers = {}; + this.$markerId = 1; + this.$resetRowCache(0); + this.$wrapData = []; + this.$foldData = []; + this.$rowLengthCache = []; + this.$undoSelect = true; + this.$foldData.toString = function() { + var str = ""; + this.forEach(function(foldLine) { + str += "\n" + foldLine.toString(); + }); + return str; + } + + if (typeof text == "object" && text.getLine) { + this.setDocument(text); + } else { + this.setDocument(new Document(text)); + } + + this.selection = new Selection(this); + this.setMode(mode); +}; + + +(function() { + + oop.implement(this, EventEmitter); + this.setDocument = function(doc) { + if (this.doc) + throw new Error("Document is already set"); + + this.doc = doc; + doc.on("change", this.onChange.bind(this)); + this.on("changeFold", this.onChangeFold.bind(this)); + + if (this.bgTokenizer) { + this.bgTokenizer.setDocument(this.getDocument()); + this.bgTokenizer.start(0); + } + }; + this.getDocument = function() { + return this.doc; + }; + this.$resetRowCache = function(docRrow) { + if (!docRrow) { + this.$docRowCache = []; + this.$screenRowCache = []; + return; + } + + var i = this.$getRowCacheIndex(this.$docRowCache, docRrow) + 1; + var l = this.$docRowCache.length; + this.$docRowCache.splice(i, l); + this.$screenRowCache.splice(i, l); + + }; + + this.$getRowCacheIndex = function(cacheArray, val) { + var low = 0; + var hi = cacheArray.length - 1; + + while (low <= hi) { + var mid = (low + hi) >> 1; + var c = cacheArray[mid]; + + if (val > c) + low = mid + 1; + else if (val < c) + hi = mid - 1; + else + return mid; + } + + return low && low -1; + }; + + this.onChangeFold = function(e) { + var fold = e.data; + this.$resetRowCache(fold.start.row); + }; + + this.onChange = function(e) { + var delta = e.data; + this.$modified = true; + + this.$resetRowCache(delta.range.start.row); + + var removedFolds = this.$updateInternalDataOnChange(e); + if (!this.$fromUndo && this.$undoManager && !delta.ignore) { + this.$deltasDoc.push(delta); + if (removedFolds && removedFolds.length != 0) { + this.$deltasFold.push({ + action: "removeFolds", + folds: removedFolds + }); + } + + this.$informUndoManager.schedule(); + } + + this.bgTokenizer.$updateOnChange(delta); + this._emit("change", e); + }; + this.setValue = function(text) { + this.doc.setValue(text); + this.selection.moveCursorTo(0, 0); + this.selection.clearSelection(); + + this.$resetRowCache(0); + this.$deltas = []; + this.$deltasDoc = []; + this.$deltasFold = []; + this.getUndoManager().reset(); + }; + /** alias of: EditSession.getValue + * EditSession.toString() -> String + * + * Returns the current [[Document `Document`]] as a string. + * + **/ + this.getValue = + this.toString = function() { + return this.doc.getValue(); + }; + this.getSelection = function() { + return this.selection; + }; + this.getState = function(row) { + return this.bgTokenizer.getState(row); + }; + this.getTokens = function(row) { + return this.bgTokenizer.getTokens(row); + }; + this.getTokenAt = function(row, column) { + var tokens = this.bgTokenizer.getTokens(row); + var token, c = 0; + if (column == null) { + i = tokens.length - 1; + c = this.getLine(row).length; + } else { + for (var i = 0; i < tokens.length; i++) { + c += tokens[i].value.length; + if (c >= column) + break; + } + } + token = tokens[i]; + if (!token) + return null; + token.index = i; + token.start = c - token.value.length; + return token; + }; + + this.highlight = function(re) { + if (!this.$searchHighlight) { + var highlight = new SearchHighlight(null, "ace_selected_word", "text"); + this.$searchHighlight = this.addDynamicMarker(highlight); + } + this.$searchHighlight.setRegexp(re); + } + /** + * EditSession.setUndoManager(undoManager) + * - undoManager (UndoManager): The new undo manager + * + * Sets the undo manager. + **/ + this.setUndoManager = function(undoManager) { + this.$undoManager = undoManager; + this.$deltas = []; + this.$deltasDoc = []; + this.$deltasFold = []; + + if (this.$informUndoManager) + this.$informUndoManager.cancel(); + + if (undoManager) { + var self = this; + this.$syncInformUndoManager = function() { + self.$informUndoManager.cancel(); + + if (self.$deltasFold.length) { + self.$deltas.push({ + group: "fold", + deltas: self.$deltasFold + }); + self.$deltasFold = []; + } + + if (self.$deltasDoc.length) { + self.$deltas.push({ + group: "doc", + deltas: self.$deltasDoc + }); + self.$deltasDoc = []; + } + + if (self.$deltas.length > 0) { + undoManager.execute({ + action: "aceupdate", + args: [self.$deltas, self] + }); + } + + self.$deltas = []; + } + this.$informUndoManager = + lang.deferredCall(this.$syncInformUndoManager); + } + }; + + this.$defaultUndoManager = { + undo: function() {}, + redo: function() {}, + reset: function() {} + }; + this.getUndoManager = function() { + return this.$undoManager || this.$defaultUndoManager; + }, + + /** + * EditSession.getTabString() -> String + * + * Returns the current value for tabs. If the user is using soft tabs, this will be a series of spaces (defined by [[EditSession.getTabSize `getTabSize()`]]); otherwise it's simply `'\t'`. + **/ + this.getTabString = function() { + if (this.getUseSoftTabs()) { + return lang.stringRepeat(" ", this.getTabSize()); + } else { + return "\t"; + } + }; + + this.$useSoftTabs = true; + this.setUseSoftTabs = function(useSoftTabs) { + if (this.$useSoftTabs === useSoftTabs) return; + + this.$useSoftTabs = useSoftTabs; + }; + this.getUseSoftTabs = function() { + return this.$useSoftTabs; + }; + + this.$tabSize = 4; + this.setTabSize = function(tabSize) { + if (isNaN(tabSize) || this.$tabSize === tabSize) return; + + this.$modified = true; + this.$rowLengthCache = []; + this.$tabSize = tabSize; + this._emit("changeTabSize"); + }; + this.getTabSize = function() { + return this.$tabSize; + }; + this.isTabStop = function(position) { + return this.$useSoftTabs && (position.column % this.$tabSize == 0); + }; + + this.$overwrite = false; + this.setOverwrite = function(overwrite) { + if (this.$overwrite == overwrite) return; + + this.$overwrite = overwrite; + this._emit("changeOverwrite"); + }; + this.getOverwrite = function() { + return this.$overwrite; + }; + this.toggleOverwrite = function() { + this.setOverwrite(!this.$overwrite); + }; + this.addGutterDecoration = function(row, className) { + if (!this.$decorations[row]) + this.$decorations[row] = ""; + this.$decorations[row] += " " + className; + this._emit("changeBreakpoint", {}); + }; + this.removeGutterDecoration = function(row, className) { + this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, ""); + this._emit("changeBreakpoint", {}); + }; + this.getBreakpoints = function() { + return this.$breakpoints; + }; + this.setBreakpoints = function(rows) { + this.$breakpoints = []; + for (var i=0; i 0) + inToken = !!line.charAt(column - 1).match(this.tokenRe); + + if (!inToken) + inToken = !!line.charAt(column).match(this.tokenRe); + + if (inToken) + var re = this.tokenRe; + else if (/^\s+$/.test(line.slice(column-1, column+1))) + var re = /\s/; + else + var re = this.nonTokenRe; + + var start = column; + if (start > 0) { + do { + start--; + } + while (start >= 0 && line.charAt(start).match(re)); + start++; + } + + var end = column; + while (end < line.length && line.charAt(end).match(re)) { + end++; + } + + return new Range(row, start, row, end); + }; + this.getAWordRange = function(row, column) { + var wordRange = this.getWordRange(row, column); + var line = this.getLine(wordRange.end.row); + + while (line.charAt(wordRange.end.column).match(/[ \t]/)) { + wordRange.end.column += 1; + } + return wordRange; + }; + this.setNewLineMode = function(newLineMode) { + this.doc.setNewLineMode(newLineMode); + }; + this.getNewLineMode = function() { + return this.doc.getNewLineMode(); + }; + + this.$useWorker = true; + this.setUseWorker = function(useWorker) { + if (this.$useWorker == useWorker) + return; + + this.$useWorker = useWorker; + + this.$stopWorker(); + if (useWorker) + this.$startWorker(); + }; + this.getUseWorker = function() { + return this.$useWorker; + }; + this.onReloadTokenizer = function(e) { + var rows = e.data; + this.bgTokenizer.start(rows.first); + this._emit("tokenizerUpdate", e); + }; + + this.$modes = {}; + this._loadMode = function(mode, callback) { + if (!this.$modes["null"]) + this.$modes["null"] = this.$modes["ace/mode/text"] = new TextMode(); + + if (this.$modes[mode]) + return callback(this.$modes[mode]); + + var _self = this; + var module; + try { + module = require(mode); + } catch (e) {}; + // sometimes require returns empty object (this bug is present in requirejs 2 as well) + if (module && module.Mode) + return done(module); + + // set mode to text until loading is finished + if (!this.$mode) + this.$setModePlaceholder(); + + fetch(mode, function() { + require([mode], done); + }); + + function done(module) { + if (_self.$modes[mode]) + return callback(_self.$modes[mode]); + + _self.$modes[mode] = new module.Mode(); + _self.$modes[mode].$id = mode; + _self._emit("loadmode", { + name: mode, + mode: _self.$modes[mode] + }); + callback(_self.$modes[mode]); + } + + function fetch(name, callback) { + if (!config.get("packaged")) + return callback(); + + net.loadScript(config.moduleUrl(name, "mode"), callback); + } + }; + + this.$setModePlaceholder = function() { + this.$mode = this.$modes["null"]; + var tokenizer = this.$mode.getTokenizer(); + + if (!this.bgTokenizer) { + this.bgTokenizer = new BackgroundTokenizer(tokenizer); + var _self = this; + this.bgTokenizer.addEventListener("update", function(e) { + _self._emit("tokenizerUpdate", e); + }); + } else { + this.bgTokenizer.setTokenizer(tokenizer); + } + this.bgTokenizer.setDocument(this.getDocument()); + + this.tokenRe = this.$mode.tokenRe; + this.nonTokenRe = this.$mode.nonTokenRe; + }; + this.$mode = null; + this.$modeId = null; + this.setMode = function(mode) { + mode = mode || "null"; + // load on demand + if (typeof mode === "string") { + if (this.$modeId == mode) + return; + + this.$modeId = mode; + var _self = this; + this._loadMode(mode, function(module) { + if (_self.$modeId !== mode) + return; + + _self.setMode(module); + }); + return; + } + + if (this.$mode === mode) return; + this.$mode = mode; + this.$modeId = mode.$id; + + this.$stopWorker(); + + if (this.$useWorker) + this.$startWorker(); + + var tokenizer = mode.getTokenizer(); + + if(tokenizer.addEventListener !== undefined) { + var onReloadTokenizer = this.onReloadTokenizer.bind(this); + tokenizer.addEventListener("update", onReloadTokenizer); + } + + if (!this.bgTokenizer) { + this.bgTokenizer = new BackgroundTokenizer(tokenizer); + var _self = this; + this.bgTokenizer.addEventListener("update", function(e) { + _self._emit("tokenizerUpdate", e); + }); + } else { + this.bgTokenizer.setTokenizer(tokenizer); + } + + this.bgTokenizer.setDocument(this.getDocument()); + this.bgTokenizer.start(0); + + this.tokenRe = mode.tokenRe; + this.nonTokenRe = mode.nonTokenRe; + + this.$setFolding(mode.foldingRules); + + this._emit("changeMode"); + }; + this.$stopWorker = function() { + if (this.$worker) + this.$worker.terminate(); + + this.$worker = null; + }; + this.$startWorker = function() { + if (typeof Worker !== "undefined" && !require.noWorker) { + try { + this.$worker = this.$mode.createWorker(this); + } catch (e) { + console.log("Could not load worker"); + console.log(e); + this.$worker = null; + } + } + else + this.$worker = null; + }; + this.getMode = function() { + return this.$mode; + }; + + this.$scrollTop = 0; + this.setScrollTop = function(scrollTop) { + scrollTop = Math.round(Math.max(0, scrollTop)); + if (this.$scrollTop === scrollTop) + return; + + this.$scrollTop = scrollTop; + this._emit("changeScrollTop", scrollTop); + }; + this.getScrollTop = function() { + return this.$scrollTop; + }; + + this.$scrollLeft = 0; + this.setScrollLeft = function(scrollLeft) { + scrollLeft = Math.round(Math.max(0, scrollLeft)); + if (this.$scrollLeft === scrollLeft) + return; + + this.$scrollLeft = scrollLeft; + this._emit("changeScrollLeft", scrollLeft); + }; + this.getScrollLeft = function() { + return this.$scrollLeft; + }; + this.getScreenWidth = function() { + this.$computeWidth(); + return this.screenWidth; + }; + + this.$computeWidth = function(force) { + if (this.$modified || force) { + this.$modified = false; + + if (this.$useWrapMode) + return this.screenWidth = this.$wrapLimit; + + var lines = this.doc.getAllLines(); + var cache = this.$rowLengthCache; + var longestScreenLine = 0; + var foldIndex = 0; + var foldLine = this.$foldData[foldIndex]; + var foldStart = foldLine ? foldLine.start.row : Infinity; + var len = lines.length; + + for (var i = 0; i < len; i++) { + if (i > foldStart) { + i = foldLine.end.row + 1; + if (i >= len) + break; + foldLine = this.$foldData[foldIndex++]; + foldStart = foldLine ? foldLine.start.row : Infinity; + } + + if (cache[i] == null) + cache[i] = this.$getStringScreenWidth(lines[i])[0]; + + if (cache[i] > longestScreenLine) + longestScreenLine = cache[i]; + } + this.screenWidth = longestScreenLine; + } + }; + this.getLine = function(row) { + return this.doc.getLine(row); + }; + this.getLines = function(firstRow, lastRow) { + return this.doc.getLines(firstRow, lastRow); + }; + this.getLength = function() { + return this.doc.getLength(); + }; + this.getTextRange = function(range) { + return this.doc.getTextRange(range || this.selection.getRange()); + }; + this.insert = function(position, text) { + return this.doc.insert(position, text); + }; + this.remove = function(range) { + return this.doc.remove(range); + }; + this.undoChanges = function(deltas, dontSelect) { + if (!deltas.length) + return; + + this.$fromUndo = true; + var lastUndoRange = null; + for (var i = deltas.length - 1; i != -1; i--) { + var delta = deltas[i]; + if (delta.group == "doc") { + this.doc.revertDeltas(delta.deltas); + lastUndoRange = + this.$getUndoSelection(delta.deltas, true, lastUndoRange); + } else { + delta.deltas.forEach(function(foldDelta) { + this.addFolds(foldDelta.folds); + }, this); + } + } + this.$fromUndo = false; + lastUndoRange && + this.$undoSelect && + !dontSelect && + this.selection.setSelectionRange(lastUndoRange); + return lastUndoRange; + }; + this.redoChanges = function(deltas, dontSelect) { + if (!deltas.length) + return; + + this.$fromUndo = true; + var lastUndoRange = null; + for (var i = 0; i < deltas.length; i++) { + var delta = deltas[i]; + if (delta.group == "doc") { + this.doc.applyDeltas(delta.deltas); + lastUndoRange = + this.$getUndoSelection(delta.deltas, false, lastUndoRange); + } + } + this.$fromUndo = false; + lastUndoRange && + this.$undoSelect && + !dontSelect && + this.selection.setSelectionRange(lastUndoRange); + return lastUndoRange; + }; + this.setUndoSelect = function(enable) { + this.$undoSelect = enable; + }; + this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) { + function isInsert(delta) { + var insert = + delta.action == "insertText" || delta.action == "insertLines"; + return isUndo ? !insert : insert; + } + + var delta = deltas[0]; + var range, point; + var lastDeltaIsInsert = false; + if (isInsert(delta)) { + range = delta.range.clone(); + lastDeltaIsInsert = true; + } else { + range = Range.fromPoints(delta.range.start, delta.range.start); + lastDeltaIsInsert = false; + } + + for (var i = 1; i < deltas.length; i++) { + delta = deltas[i]; + if (isInsert(delta)) { + point = delta.range.start; + if (range.compare(point.row, point.column) == -1) { + range.setStart(delta.range.start); + } + point = delta.range.end; + if (range.compare(point.row, point.column) == 1) { + range.setEnd(delta.range.end); + } + lastDeltaIsInsert = true; + } else { + point = delta.range.start; + if (range.compare(point.row, point.column) == -1) { + range = + Range.fromPoints(delta.range.start, delta.range.start); + } + lastDeltaIsInsert = false; + } + } + + // Check if this range and the last undo range has something in common. + // If true, merge the ranges. + if (lastUndoRange != null) { + var cmp = lastUndoRange.compareRange(range); + if (cmp == 1) { + range.setStart(lastUndoRange.start); + } else if (cmp == -1) { + range.setEnd(lastUndoRange.end); + } + } + + return range; + }, + + /** related to: Document.replace + * EditSession.replace(range, text) -> Object + * - range (Range): A specified Range to replace + * - text (String): The new text to use as a replacement + * + (Object): Returns an object containing the final row and column, like this:
+ * ```{row: endRow, column: 0}```
+ * If the text and range are empty, this function returns an object containing the current `range.start` value.
+ * If the text is the exact same as what currently exists, this function returns an object containing the current `range.end` value. + * + * Replaces a range in the document with the new `text`. + * + * + * + **/ + this.replace = function(range, text) { + return this.doc.replace(range, text); + }; + this.moveText = function(fromRange, toPosition) { + var text = this.getTextRange(fromRange); + this.remove(fromRange); + + var toRow = toPosition.row; + var toColumn = toPosition.column; + + // Make sure to update the insert location, when text is removed in + // front of the chosen point of insertion. + if (!fromRange.isMultiLine() && fromRange.start.row == toRow && + fromRange.end.column < toColumn) + toColumn -= text.length; + + if (fromRange.isMultiLine() && fromRange.end.row < toRow) { + var lines = this.doc.$split(text); + toRow -= lines.length - 1; + } + + var endRow = toRow + fromRange.end.row - fromRange.start.row; + var endColumn = fromRange.isMultiLine() ? + fromRange.end.column : + toColumn + fromRange.end.column - fromRange.start.column; + + var toRange = new Range(toRow, toColumn, endRow, endColumn); + + this.insert(toRange.start, text); + + return toRange; + }; + this.indentRows = function(startRow, endRow, indentString) { + indentString = indentString.replace(/\t/g, this.getTabString()); + for (var row=startRow; row<=endRow; row++) + this.insert({row: row, column:0}, indentString); + }; + this.outdentRows = function (range) { + var rowRange = range.collapseRows(); + var deleteRange = new Range(0, 0, 0, 0); + var size = this.getTabSize(); + + for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) { + var line = this.getLine(i); + + deleteRange.start.row = i; + deleteRange.end.row = i; + for (var j = 0; j < size; ++j) + if (line.charAt(j) != ' ') + break; + if (j < size && line.charAt(j) == '\t') { + deleteRange.start.column = j; + deleteRange.end.column = j + 1; + } else { + deleteRange.start.column = 0; + deleteRange.end.column = j; + } + this.remove(deleteRange); + } + }; + this.moveLinesUp = function(firstRow, lastRow) { + if (firstRow <= 0) return 0; + + var removed = this.doc.removeLines(firstRow, lastRow); + this.doc.insertLines(firstRow - 1, removed); + return -1; + }; + this.moveLinesDown = function(firstRow, lastRow) { + if (lastRow >= this.doc.getLength()-1) return 0; + + var removed = this.doc.removeLines(firstRow, lastRow); + this.doc.insertLines(firstRow+1, removed); + return 1; + }; + this.duplicateLines = function(firstRow, lastRow) { + var firstRow = this.$clipRowToDocument(firstRow); + var lastRow = this.$clipRowToDocument(lastRow); + + var lines = this.getLines(firstRow, lastRow); + this.doc.insertLines(firstRow, lines); + + var addedRows = lastRow - firstRow + 1; + return addedRows; + }; + + + this.$clipRowToDocument = function(row) { + return Math.max(0, Math.min(row, this.doc.getLength()-1)); + }; + + this.$clipColumnToRow = function(row, column) { + if (column < 0) + return 0; + return Math.min(this.doc.getLine(row).length, column); + }; + + + this.$clipPositionToDocument = function(row, column) { + column = Math.max(0, column); + + if (row < 0) { + row = 0; + column = 0; + } else { + var len = this.doc.getLength(); + if (row >= len) { + row = len - 1; + column = this.doc.getLine(len-1).length; + } else { + column = Math.min(this.doc.getLine(row).length, column); + } + } + + return { + row: row, + column: column + }; + }; + + this.$clipRangeToDocument = function(range) { + if (range.start.row < 0) { + range.start.row = 0; + range.start.column = 0; + } else { + range.start.column = this.$clipColumnToRow( + range.start.row, + range.start.column + ); + } + + var len = this.doc.getLength() - 1; + if (range.end.row > len) { + range.end.row = len; + range.end.column = this.doc.getLine(len).length; + } else { + range.end.column = this.$clipColumnToRow( + range.end.row, + range.end.column + ); + } + return range; + }; + + // WRAPMODE + this.$wrapLimit = 80; + this.$useWrapMode = false; + this.$wrapLimitRange = { + min : null, + max : null + }; + this.setUseWrapMode = function(useWrapMode) { + if (useWrapMode != this.$useWrapMode) { + this.$useWrapMode = useWrapMode; + this.$modified = true; + this.$resetRowCache(0); + + // If wrapMode is activaed, the wrapData array has to be initialized. + if (useWrapMode) { + var len = this.getLength(); + this.$wrapData = []; + for (var i = 0; i < len; i++) { + this.$wrapData.push([]); + } + this.$updateWrapData(0, len - 1); + } + + this._emit("changeWrapMode"); + } + }; + this.getUseWrapMode = function() { + return this.$useWrapMode; + }; + + // Allow the wrap limit to move freely between min and max. Either + // parameter can be null to allow the wrap limit to be unconstrained + // in that direction. Or set both parameters to the same number to pin + // the limit to that value. + /** + * EditSession.setWrapLimitRange(min, max) + * - min (Number): The minimum wrap value (the left side wrap) + * - max (Number): The maximum wrap value (the right side wrap) + * + * Sets the boundaries of wrap. Either value can be `null` to have an unconstrained wrap, or, they can be the same number to pin the limit. If the wrap limits for `min` or `max` are different, this method also emits the `'changeWrapMode'` event. + **/ + this.setWrapLimitRange = function(min, max) { + if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) { + this.$wrapLimitRange.min = min; + this.$wrapLimitRange.max = max; + this.$modified = true; + // This will force a recalculation of the wrap limit + this._emit("changeWrapMode"); + } + }; + this.adjustWrapLimit = function(desiredLimit) { + var wrapLimit = this.$constrainWrapLimit(desiredLimit); + if (wrapLimit != this.$wrapLimit && wrapLimit > 0) { + this.$wrapLimit = wrapLimit; + this.$modified = true; + if (this.$useWrapMode) { + this.$updateWrapData(0, this.getLength() - 1); + this.$resetRowCache(0); + this._emit("changeWrapLimit"); + } + return true; + } + return false; + }; + this.$constrainWrapLimit = function(wrapLimit) { + var min = this.$wrapLimitRange.min; + if (min) + wrapLimit = Math.max(min, wrapLimit); + + var max = this.$wrapLimitRange.max; + if (max) + wrapLimit = Math.min(max, wrapLimit); + + // What would a limit of 0 even mean? + return Math.max(1, wrapLimit); + }; + this.getWrapLimit = function() { + return this.$wrapLimit; + }; + this.getWrapLimitRange = function() { + // Avoid unexpected mutation by returning a copy + return { + min : this.$wrapLimitRange.min, + max : this.$wrapLimitRange.max + }; + }; + this.$updateInternalDataOnChange = function(e) { + var useWrapMode = this.$useWrapMode; + var len; + var action = e.data.action; + var firstRow = e.data.range.start.row; + var lastRow = e.data.range.end.row; + var start = e.data.range.start; + var end = e.data.range.end; + var removedFolds = null; + + if (action.indexOf("Lines") != -1) { + if (action == "insertLines") { + lastRow = firstRow + (e.data.lines.length); + } else { + lastRow = firstRow; + } + len = e.data.lines ? e.data.lines.length : lastRow - firstRow; + } else { + len = lastRow - firstRow; + } + + if (len != 0) { + if (action.indexOf("remove") != -1) { + this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); + + var foldLines = this.$foldData; + removedFolds = this.getFoldsInRange(e.data.range); + this.removeFolds(removedFolds); + + var foldLine = this.getFoldLine(end.row); + var idx = 0; + if (foldLine) { + foldLine.addRemoveChars(end.row, end.column, start.column - end.column); + foldLine.shiftRow(-len); + + var foldLineBefore = this.getFoldLine(firstRow); + if (foldLineBefore && foldLineBefore !== foldLine) { + foldLineBefore.merge(foldLine); + foldLine = foldLineBefore; + } + idx = foldLines.indexOf(foldLine) + 1; + } + + for (idx; idx < foldLines.length; idx++) { + var foldLine = foldLines[idx]; + if (foldLine.start.row >= end.row) { + foldLine.shiftRow(-len); + } + } + + lastRow = firstRow; + } else { + var args; + if (useWrapMode) { + args = [firstRow, 0]; + for (var i = 0; i < len; i++) args.push([]); + this.$wrapData.splice.apply(this.$wrapData, args); + } else { + args = Array(len); + args.unshift(firstRow, 0); + this.$rowLengthCache.splice.apply(this.$rowLengthCache, args); + } + + // If some new line is added inside of a foldLine, then split + // the fold line up. + var foldLines = this.$foldData; + var foldLine = this.getFoldLine(firstRow); + var idx = 0; + if (foldLine) { + var cmp = foldLine.range.compareInside(start.row, start.column) + // Inside of the foldLine range. Need to split stuff up. + if (cmp == 0) { + foldLine = foldLine.split(start.row, start.column); + foldLine.shiftRow(len); + foldLine.addRemoveChars( + lastRow, 0, end.column - start.column); + } else + // Infront of the foldLine but same row. Need to shift column. + if (cmp == -1) { + foldLine.addRemoveChars(firstRow, 0, end.column - start.column); + foldLine.shiftRow(len); + } + // Nothing to do if the insert is after the foldLine. + idx = foldLines.indexOf(foldLine) + 1; + } + + for (idx; idx < foldLines.length; idx++) { + var foldLine = foldLines[idx]; + if (foldLine.start.row >= firstRow) { + foldLine.shiftRow(len); + } + } + } + } else { + // Realign folds. E.g. if you add some new chars before a fold, the + // fold should "move" to the right. + len = Math.abs(e.data.range.start.column - e.data.range.end.column); + if (action.indexOf("remove") != -1) { + // Get all the folds in the change range and remove them. + removedFolds = this.getFoldsInRange(e.data.range); + this.removeFolds(removedFolds); + + len = -len; + } + var foldLine = this.getFoldLine(firstRow); + if (foldLine) { + foldLine.addRemoveChars(firstRow, start.column, len); + } + } + + if (useWrapMode && this.$wrapData.length != this.doc.getLength()) { + console.error("doc.getLength() and $wrapData.length have to be the same!"); + } + + if (useWrapMode) + this.$updateWrapData(firstRow, lastRow); + else + this.$updateRowLengthCache(firstRow, lastRow); + + return removedFolds; + }; + + this.$updateRowLengthCache = function(firstRow, lastRow, b) { + //console.log(firstRow, lastRow, b) + this.$rowLengthCache[firstRow] = null; + this.$rowLengthCache[lastRow] = null; + //console.log(this.$rowLengthCache) + }; + this.$updateWrapData = function(firstRow, lastRow) { + var lines = this.doc.getAllLines(); + var tabSize = this.getTabSize(); + var wrapData = this.$wrapData; + var wrapLimit = this.$wrapLimit; + var tokens; + var foldLine; + + var row = firstRow; + lastRow = Math.min(lastRow, lines.length - 1); + while (row <= lastRow) { + foldLine = this.getFoldLine(row, foldLine); + if (!foldLine) { + tokens = this.$getDisplayTokens(lang.stringTrimRight(lines[row])); + wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize); + row ++; + } else { + tokens = []; + foldLine.walk( + function(placeholder, row, column, lastColumn) { + var walkTokens; + if (placeholder) { + walkTokens = this.$getDisplayTokens( + placeholder, tokens.length); + walkTokens[0] = PLACEHOLDER_START; + for (var i = 1; i < walkTokens.length; i++) { + walkTokens[i] = PLACEHOLDER_BODY; + } + } else { + walkTokens = this.$getDisplayTokens( + lines[row].substring(lastColumn, column), + tokens.length); + } + tokens = tokens.concat(walkTokens); + }.bind(this), + foldLine.end.row, + lines[foldLine.end.row].length + 1 + ); + // Remove spaces/tabs from the back of the token array. + while (tokens.length != 0 && tokens[tokens.length - 1] >= SPACE) + tokens.pop(); + + wrapData[foldLine.start.row] + = this.$computeWrapSplits(tokens, wrapLimit, tabSize); + row = foldLine.end.row + 1; + } + } + }; + + // "Tokens" + var CHAR = 1, + CHAR_EXT = 2, + PLACEHOLDER_START = 3, + PLACEHOLDER_BODY = 4, + PUNCTUATION = 9, + SPACE = 10, + TAB = 11, + TAB_SPACE = 12; + this.$computeWrapSplits = function(tokens, wrapLimit) { + if (tokens.length == 0) { + return []; + } + + var splits = []; + var displayLength = tokens.length; + var lastSplit = 0, lastDocSplit = 0; + + function addSplit(screenPos) { + var displayed = tokens.slice(lastSplit, screenPos); + + // The document size is the current size - the extra width for tabs + // and multipleWidth characters. + var len = displayed.length; + displayed.join(""). + // Get all the TAB_SPACEs. + replace(/12/g, function() { + len -= 1; + }). + // Get all the CHAR_EXT/multipleWidth characters. + replace(/2/g, function() { + len -= 1; + }); + + lastDocSplit += len; + splits.push(lastDocSplit); + lastSplit = screenPos; + } + + while (displayLength - lastSplit > wrapLimit) { + // This is, where the split should be. + var split = lastSplit + wrapLimit; + + // If there is a space or tab at this split position, then making + // a split is simple. + if (tokens[split] >= SPACE) { + // Include all following spaces + tabs in this split as well. + while (tokens[split] >= SPACE) { + split ++; + } + addSplit(split); + continue; + } + + // === ELSE === + // Check if split is inside of a placeholder. Placeholder are + // not splitable. Therefore, seek the beginning of the placeholder + // and try to place the split beofre the placeholder's start. + if (tokens[split] == PLACEHOLDER_START + || tokens[split] == PLACEHOLDER_BODY) + { + // Seek the start of the placeholder and do the split + // before the placeholder. By definition there always + // a PLACEHOLDER_START between split and lastSplit. + for (split; split != lastSplit - 1; split--) { + if (tokens[split] == PLACEHOLDER_START) { + // split++; << No incremental here as we want to + // have the position before the Placeholder. + break; + } + } + + // If the PLACEHOLDER_START is not the index of the + // last split, then we can do the split + if (split > lastSplit) { + addSplit(split); + continue; + } + + // If the PLACEHOLDER_START IS the index of the last + // split, then we have to place the split after the + // placeholder. So, let's seek for the end of the placeholder. + split = lastSplit + wrapLimit; + for (split; split < tokens.length; split++) { + if (tokens[split] != PLACEHOLDER_BODY) + { + break; + } + } + + // If spilt == tokens.length, then the placeholder is the last + // thing in the line and adding a new split doesn't make sense. + if (split == tokens.length) { + break; // Breaks the while-loop. + } + + // Finally, add the split... + addSplit(split); + continue; + } + + // === ELSE === + // Search for the first non space/tab/placeholder/punctuation token backwards. + var minSplit = Math.max(split - 10, lastSplit - 1); + while (split > minSplit && tokens[split] < PLACEHOLDER_START) { + split --; + } + while (split > minSplit && tokens[split] == PUNCTUATION) { + split --; + } + // If we found one, then add the split. + if (split > minSplit) { + addSplit(++split); + continue; + } + + // === ELSE === + split = lastSplit + wrapLimit; + // The split is inside of a CHAR or CHAR_EXT token and no space + // around -> force a split. + addSplit(split); + } + return splits; + }; + this.$getDisplayTokens = function(str, offset) { + var arr = []; + var tabSize; + offset = offset || 0; + + for (var i = 0; i < str.length; i++) { + var c = str.charCodeAt(i); + // Tab + if (c == 9) { + tabSize = this.getScreenTabSize(arr.length + offset); + arr.push(TAB); + for (var n = 1; n < tabSize; n++) { + arr.push(TAB_SPACE); + } + } + // Space + else if (c == 32) { + arr.push(SPACE); + } else if((c > 39 && c < 48) || (c > 57 && c < 64)) { + arr.push(PUNCTUATION); + } + // full width characters + else if (c >= 0x1100 && isFullWidth(c)) { + arr.push(CHAR, CHAR_EXT); + } else { + arr.push(CHAR); + } + } + return arr; + }; + this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) { + if (maxScreenColumn == 0) + return [0, 0]; + if (maxScreenColumn == null) + maxScreenColumn = Infinity; + screenColumn = screenColumn || 0; + + var c, column; + for (column = 0; column < str.length; column++) { + c = str.charCodeAt(column); + // tab + if (c == 9) { + screenColumn += this.getScreenTabSize(screenColumn); + } + // full width characters + else if (c >= 0x1100 && isFullWidth(c)) { + screenColumn += 2; + } else { + screenColumn += 1; + } + if (screenColumn > maxScreenColumn) { + break; + } + } + + return [screenColumn, column]; + }; + this.getRowLength = function(row) { + if (!this.$useWrapMode || !this.$wrapData[row]) { + return 1; + } else { + return this.$wrapData[row].length + 1; + } + }; + this.getScreenLastRowColumn = function(screenRow) { + var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE); + return this.documentToScreenColumn(pos.row, pos.column); + }; + this.getDocumentLastRowColumn = function(docRow, docColumn) { + var screenRow = this.documentToScreenRow(docRow, docColumn); + return this.getScreenLastRowColumn(screenRow); + }; + this.getDocumentLastRowColumnPosition = function(docRow, docColumn) { + var screenRow = this.documentToScreenRow(docRow, docColumn); + return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10); + }; + this.getRowSplitData = function(row) { + if (!this.$useWrapMode) { + return undefined; + } else { + return this.$wrapData[row]; + } + }; + this.getScreenTabSize = function(screenColumn) { + return this.$tabSize - screenColumn % this.$tabSize; + }; + this.screenToDocumentRow = function(screenRow, screenColumn) { + return this.screenToDocumentPosition(screenRow, screenColumn).row; + }; + this.screenToDocumentColumn = function(screenRow, screenColumn) { + return this.screenToDocumentPosition(screenRow, screenColumn).column; + }; + this.screenToDocumentPosition = function(screenRow, screenColumn) { + if (screenRow < 0) + return {row: 0, column: 0}; + + var line; + var docRow = 0; + var docColumn = 0; + var column; + var row = 0; + var rowLength = 0; + + var rowCache = this.$screenRowCache; + var i = this.$getRowCacheIndex(rowCache, screenRow); + if (0 < i && i < rowCache.length) { + var row = rowCache[i]; + var docRow = this.$docRowCache[i]; + var doCache = screenRow > row || (screenRow == row && i == rowCache.length - 1); + } else { + var doCache = true; + } + + var maxRow = this.getLength() - 1; + var foldLine = this.getNextFoldLine(docRow); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (row <= screenRow) { + rowLength = this.getRowLength(docRow); + if (row + rowLength - 1 >= screenRow || docRow >= maxRow) { + break; + } else { + row += rowLength; + docRow++; + if (docRow > foldStart) { + docRow = foldLine.end.row+1; + foldLine = this.getNextFoldLine(docRow, foldLine); + foldStart = foldLine ? foldLine.start.row : Infinity; + } + } + if (doCache) { + this.$docRowCache.push(docRow); + this.$screenRowCache.push(row); + } + } + + if (foldLine && foldLine.start.row <= docRow) { + line = this.getFoldDisplayLine(foldLine); + docRow = foldLine.start.row; + } else if (row + rowLength <= screenRow || docRow > maxRow) { + // clip at the end of the document + return { + row: maxRow, + column: this.getLine(maxRow).length + } + } else { + line = this.getLine(docRow); + foldLine = null; + } + + if (this.$useWrapMode) { + var splits = this.$wrapData[docRow]; + if (splits) { + column = splits[screenRow - row]; + if(screenRow > row && splits.length) { + docColumn = splits[screenRow - row - 1] || splits[splits.length - 1]; + line = line.substring(docColumn); + } + } + } + + docColumn += this.$getStringScreenWidth(line, screenColumn)[1]; + + // We remove one character at the end so that the docColumn + // position returned is not associated to the next row on the screen. + if (this.$useWrapMode && docColumn >= column) + docColumn = column - 1; + + if (foldLine) + return foldLine.idxToPosition(docColumn); + + return {row: docRow, column: docColumn}; + }; + this.documentToScreenPosition = function(docRow, docColumn) { + // Normalize the passed in arguments. + if (typeof docColumn === "undefined") + var pos = this.$clipPositionToDocument(docRow.row, docRow.column); + else + pos = this.$clipPositionToDocument(docRow, docColumn); + + docRow = pos.row; + docColumn = pos.column; + + var screenRow = 0; + var foldStartRow = null; + var fold = null; + + // Clamp the docRow position in case it's inside of a folded block. + fold = this.getFoldAt(docRow, docColumn, 1); + if (fold) { + docRow = fold.start.row; + docColumn = fold.start.column; + } + + var rowEnd, row = 0; + + + var rowCache = this.$docRowCache; + var i = this.$getRowCacheIndex(rowCache, docRow); + if (0 < i && i < rowCache.length) { + var row = rowCache[i]; + var screenRow = this.$screenRowCache[i]; + var doCache = docRow > row || (docRow == row && i == rowCache.length - 1); + } else { + var doCache = true; + } + + var foldLine = this.getNextFoldLine(row); + var foldStart = foldLine ?foldLine.start.row :Infinity; + + while (row < docRow) { + if (row >= foldStart) { + rowEnd = foldLine.end.row + 1; + if (rowEnd > docRow) + break; + foldLine = this.getNextFoldLine(rowEnd, foldLine); + foldStart = foldLine ?foldLine.start.row :Infinity; + } + else { + rowEnd = row + 1; + } + + screenRow += this.getRowLength(row); + row = rowEnd; + + if (doCache) { + this.$docRowCache.push(row); + this.$screenRowCache.push(screenRow); + } + } + + // Calculate the text line that is displayed in docRow on the screen. + var textLine = ""; + // Check if the final row we want to reach is inside of a fold. + if (foldLine && row >= foldStart) { + textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn); + foldStartRow = foldLine.start.row; + } else { + textLine = this.getLine(docRow).substring(0, docColumn); + foldStartRow = docRow; + } + // Clamp textLine if in wrapMode. + if (this.$useWrapMode) { + var wrapRow = this.$wrapData[foldStartRow]; + var screenRowOffset = 0; + while (textLine.length >= wrapRow[screenRowOffset]) { + screenRow ++; + screenRowOffset++; + } + textLine = textLine.substring( + wrapRow[screenRowOffset - 1] || 0, textLine.length + ); + } + + return { + row: screenRow, + column: this.$getStringScreenWidth(textLine)[0] + }; + }; + this.documentToScreenColumn = function(row, docColumn) { + return this.documentToScreenPosition(row, docColumn).column; + }; + this.documentToScreenRow = function(docRow, docColumn) { + return this.documentToScreenPosition(docRow, docColumn).row; + }; + this.getScreenLength = function() { + var screenRows = 0; + var fold = null; + if (!this.$useWrapMode) { + screenRows = this.getLength(); + + // Remove the folded lines again. + var foldData = this.$foldData; + for (var i = 0; i < foldData.length; i++) { + fold = foldData[i]; + screenRows -= fold.end.row - fold.start.row; + } + } else { + var lastRow = this.$wrapData.length; + var row = 0, i = 0; + var fold = this.$foldData[i++]; + var foldStart = fold ? fold.start.row :Infinity; + + while (row < lastRow) { + screenRows += this.$wrapData[row].length + 1; + row ++; + if (row > foldStart) { + row = fold.end.row+1; + fold = this.$foldData[i++]; + foldStart = fold ?fold.start.row :Infinity; + } + } + } + + return screenRows; + } + + // For every keystroke this gets called once per char in the whole doc!! + // Wouldn't hurt to make it a bit faster for c >= 0x1100 + function isFullWidth(c) { + if (c < 0x1100) + return false; + return c >= 0x1100 && c <= 0x115F || + c >= 0x11A3 && c <= 0x11A7 || + c >= 0x11FA && c <= 0x11FF || + c >= 0x2329 && c <= 0x232A || + c >= 0x2E80 && c <= 0x2E99 || + c >= 0x2E9B && c <= 0x2EF3 || + c >= 0x2F00 && c <= 0x2FD5 || + c >= 0x2FF0 && c <= 0x2FFB || + c >= 0x3000 && c <= 0x303E || + c >= 0x3041 && c <= 0x3096 || + c >= 0x3099 && c <= 0x30FF || + c >= 0x3105 && c <= 0x312D || + c >= 0x3131 && c <= 0x318E || + c >= 0x3190 && c <= 0x31BA || + c >= 0x31C0 && c <= 0x31E3 || + c >= 0x31F0 && c <= 0x321E || + c >= 0x3220 && c <= 0x3247 || + c >= 0x3250 && c <= 0x32FE || + c >= 0x3300 && c <= 0x4DBF || + c >= 0x4E00 && c <= 0xA48C || + c >= 0xA490 && c <= 0xA4C6 || + c >= 0xA960 && c <= 0xA97C || + c >= 0xAC00 && c <= 0xD7A3 || + c >= 0xD7B0 && c <= 0xD7C6 || + c >= 0xD7CB && c <= 0xD7FB || + c >= 0xF900 && c <= 0xFAFF || + c >= 0xFE10 && c <= 0xFE19 || + c >= 0xFE30 && c <= 0xFE52 || + c >= 0xFE54 && c <= 0xFE66 || + c >= 0xFE68 && c <= 0xFE6B || + c >= 0xFF01 && c <= 0xFF60 || + c >= 0xFFE0 && c <= 0xFFE6; + }; + +}).call(EditSession.prototype); + +require("./edit_session/folding").Folding.call(EditSession.prototype); +require("./edit_session/bracket_match").BracketMatch.call(EditSession.prototype); + +exports.EditSession = EditSession; +}); + +ace.define('ace/config', ['require', 'exports', 'module' , 'ace/lib/lang'], function(require, exports, module) { +"no use strict"; + +var lang = require("./lib/lang"); + +var global = (function() { + return this; +})(); + +var options = { + packaged: false, + workerPath: "", + modePath: "", + themePath: "", + suffix: ".js", + $moduleUrls: {} +}; + +exports.get = function(key) { + if (!options.hasOwnProperty(key)) + throw new Error("Unknown config key: " + key); + + return options[key]; +}; + +exports.set = function(key, value) { + if (!options.hasOwnProperty(key)) + throw new Error("Unknown config key: " + key); + + options[key] = value; +}; + +exports.all = function() { + return lang.copyObject(options); +}; + +exports.moduleUrl = function(name, component) { + if (options.$moduleUrls[name]) + return options.$moduleUrls[name]; + + var parts = name.split("/"); + component = component || parts[parts.length - 2] || ""; + var base = parts[parts.length - 1].replace(component, "").replace(/(^[\-_])|([\-_]$)/, ""); + + if (!base && parts.length > 1) + base = parts[parts.length - 2]; + return this.get(component + "Path") + "/" + component + "-" + base + this.get("suffix"); +}; + +exports.setModuleUrl = function(name, subst) { + return options.$moduleUrls[name] = subst; +}; + +exports.init = function() { + options.packaged = require.packaged || module.packaged || (global.define && define.packaged); + + if (!global.document) + return ""; + + var scriptOptions = {}; + var scriptUrl = ""; + + var scripts = document.getElementsByTagName("script"); + for (var i=0; i lead.row || (anchor.row == lead.row && anchor.column > lead.column)); + }; + this.getRange = function() { + var anchor = this.anchor; + var lead = this.lead; + + if (this.isEmpty()) + return Range.fromPoints(lead, lead); + + if (this.isBackwards()) { + return Range.fromPoints(lead, anchor); + } + else { + return Range.fromPoints(anchor, lead); + } + }; + this.clearSelection = function() { + if (!this.$isEmpty) { + this.$isEmpty = true; + this._emit("changeSelection"); + } + }; + this.selectAll = function() { + var lastRow = this.doc.getLength() - 1; + this.setSelectionAnchor(0, 0); + this.moveCursorTo(lastRow, this.doc.getLine(lastRow).length); + }; + this.setRange = + this.setSelectionRange = function(range, reverse) { + if (reverse) { + this.setSelectionAnchor(range.end.row, range.end.column); + this.selectTo(range.start.row, range.start.column); + } else { + this.setSelectionAnchor(range.start.row, range.start.column); + this.selectTo(range.end.row, range.end.column); + } + this.$desiredColumn = null; + }; + + this.$moveSelection = function(mover) { + var lead = this.lead; + if (this.$isEmpty) + this.setSelectionAnchor(lead.row, lead.column); + + mover.call(this); + }; + this.selectTo = function(row, column) { + this.$moveSelection(function() { + this.moveCursorTo(row, column); + }); + }; + this.selectToPosition = function(pos) { + this.$moveSelection(function() { + this.moveCursorToPosition(pos); + }); + }; + this.selectUp = function() { + this.$moveSelection(this.moveCursorUp); + }; + this.selectDown = function() { + this.$moveSelection(this.moveCursorDown); + }; + this.selectRight = function() { + this.$moveSelection(this.moveCursorRight); + }; + this.selectLeft = function() { + this.$moveSelection(this.moveCursorLeft); + }; + this.selectLineStart = function() { + this.$moveSelection(this.moveCursorLineStart); + }; + this.selectLineEnd = function() { + this.$moveSelection(this.moveCursorLineEnd); + }; + this.selectFileEnd = function() { + this.$moveSelection(this.moveCursorFileEnd); + }; + this.selectFileStart = function() { + this.$moveSelection(this.moveCursorFileStart); + }; + this.selectWordRight = function() { + this.$moveSelection(this.moveCursorWordRight); + }; + this.selectWordLeft = function() { + this.$moveSelection(this.moveCursorWordLeft); + }; + this.getWordRange = function(row, column) { + if (typeof column == "undefined") { + var cursor = row || this.lead; + row = cursor.row; + column = cursor.column; + } + return this.session.getWordRange(row, column); + }; + + this.selectWord = function() { + this.setSelectionRange(this.getWordRange()); + }; + this.selectAWord = function() { + var cursor = this.getCursor(); + var range = this.session.getAWordRange(cursor.row, cursor.column); + this.setSelectionRange(range); + }; + + this.getLineRange = function(row, excludeLastChar) { + var rowStart = typeof row == "number" ? row : this.lead.row; + var rowEnd; + + var foldLine = this.session.getFoldLine(rowStart); + if (foldLine) { + rowStart = foldLine.start.row; + rowEnd = foldLine.end.row; + } else { + rowEnd = rowStart; + } + if (excludeLastChar) + return new Range(rowStart, 0, rowEnd, this.session.getLine(rowEnd).length); + else + return new Range(rowStart, 0, rowEnd + 1, 0); + }; + this.selectLine = function() { + this.setSelectionRange(this.getLineRange()); + }; + this.moveCursorUp = function() { + this.moveCursorBy(-1, 0); + }; + this.moveCursorDown = function() { + this.moveCursorBy(1, 0); + }; + this.moveCursorLeft = function() { + var cursor = this.lead.getPosition(), + fold; + + if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) { + this.moveCursorTo(fold.start.row, fold.start.column); + } else if (cursor.column == 0) { + // cursor is a line (start + if (cursor.row > 0) { + this.moveCursorTo(cursor.row - 1, this.doc.getLine(cursor.row - 1).length); + } + } + else { + var tabSize = this.session.getTabSize(); + if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column-tabSize, cursor.column).split(" ").length-1 == tabSize) + this.moveCursorBy(0, -tabSize); + else + this.moveCursorBy(0, -1); + } + }; + this.moveCursorRight = function() { + var cursor = this.lead.getPosition(), + fold; + if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) { + this.moveCursorTo(fold.end.row, fold.end.column); + } + else if (this.lead.column == this.doc.getLine(this.lead.row).length) { + if (this.lead.row < this.doc.getLength() - 1) { + this.moveCursorTo(this.lead.row + 1, 0); + } + } + else { + var tabSize = this.session.getTabSize(); + var cursor = this.lead; + if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(" ").length-1 == tabSize) + this.moveCursorBy(0, tabSize); + else + this.moveCursorBy(0, 1); + } + }; + this.moveCursorLineStart = function() { + var row = this.lead.row; + var column = this.lead.column; + var screenRow = this.session.documentToScreenRow(row, column); + + // Determ the doc-position of the first character at the screen line. + var firstColumnPosition = this.session.screenToDocumentPosition(screenRow, 0); + + // Determ the line + var beforeCursor = this.session.getDisplayLine( + row, null, firstColumnPosition.row, + firstColumnPosition.column + ); + + var leadingSpace = beforeCursor.match(/^\s*/); + if (leadingSpace[0].length == column) { + this.moveCursorTo( + firstColumnPosition.row, firstColumnPosition.column + ); + } + else { + this.moveCursorTo( + firstColumnPosition.row, + firstColumnPosition.column + leadingSpace[0].length + ); + } + }; + this.moveCursorLineEnd = function() { + var lead = this.lead; + var lineEnd = this.session.getDocumentLastRowColumnPosition(lead.row, lead.column); + if (this.lead.column == lineEnd.column) { + var line = this.session.getLine(lineEnd.row); + if (lineEnd.column == line.length) { + var textEnd = line.search(/\s+$/); + if (textEnd > 0) + lineEnd.column = textEnd; + } + } + + this.moveCursorTo(lineEnd.row, lineEnd.column); + }; + this.moveCursorFileEnd = function() { + var row = this.doc.getLength() - 1; + var column = this.doc.getLine(row).length; + this.moveCursorTo(row, column); + }; + this.moveCursorFileStart = function() { + this.moveCursorTo(0, 0); + }; + this.moveCursorLongWordRight = function() { + var row = this.lead.row; + var column = this.lead.column; + var line = this.doc.getLine(row); + var rightOfCursor = line.substring(column); + + var match; + this.session.nonTokenRe.lastIndex = 0; + this.session.tokenRe.lastIndex = 0; + + // skip folds + var fold = this.session.getFoldAt(row, column, 1); + if (fold) { + this.moveCursorTo(fold.end.row, fold.end.column); + return; + } + + // first skip space + if (match = this.session.nonTokenRe.exec(rightOfCursor)) { + column += this.session.nonTokenRe.lastIndex; + this.session.nonTokenRe.lastIndex = 0; + rightOfCursor = line.substring(column); + } + + // if at line end proceed with next line + if (column >= line.length) { + this.moveCursorTo(row, line.length); + this.moveCursorRight(); + if (row < this.doc.getLength() - 1) + this.moveCursorWordRight(); + return; + } + + // advance to the end of the next token + if (match = this.session.tokenRe.exec(rightOfCursor)) { + column += this.session.tokenRe.lastIndex; + this.session.tokenRe.lastIndex = 0; + } + + this.moveCursorTo(row, column); + }; + this.moveCursorLongWordLeft = function() { + var row = this.lead.row; + var column = this.lead.column; + + // skip folds + var fold; + if (fold = this.session.getFoldAt(row, column, -1)) { + this.moveCursorTo(fold.start.row, fold.start.column); + return; + } + + var str = this.session.getFoldStringAt(row, column, -1); + if (str == null) { + str = this.doc.getLine(row).substring(0, column) + } + + var leftOfCursor = lang.stringReverse(str); + var match; + this.session.nonTokenRe.lastIndex = 0; + this.session.tokenRe.lastIndex = 0; + + // skip whitespace + if (match = this.session.nonTokenRe.exec(leftOfCursor)) { + column -= this.session.nonTokenRe.lastIndex; + leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex); + this.session.nonTokenRe.lastIndex = 0; + } + + // if at begin of the line proceed in line above + if (column <= 0) { + this.moveCursorTo(row, 0); + this.moveCursorLeft(); + if (row > 0) + this.moveCursorWordLeft(); + return; + } + + // move to the begin of the word + if (match = this.session.tokenRe.exec(leftOfCursor)) { + column -= this.session.tokenRe.lastIndex; + this.session.tokenRe.lastIndex = 0; + } + + this.moveCursorTo(row, column); + }; + + this.$shortWordEndIndex = function(rightOfCursor) { + var match, index = 0, ch; + var whitespaceRe = /\s/; + var tokenRe = this.session.tokenRe; + + tokenRe.lastIndex = 0; + if (match = this.session.tokenRe.exec(rightOfCursor)) { + index = this.session.tokenRe.lastIndex; + } else { + while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch)) + index ++; + + if (index <= 1) { + tokenRe.lastIndex = 0; + while ((ch = rightOfCursor[index]) && !tokenRe.test(ch)) { + tokenRe.lastIndex = 0; + index ++; + if (whitespaceRe.test(ch)) { + if (index > 2) { + index-- + break; + } else { + while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch)) + index ++; + if (index > 2) + break + } + } + } + } + } + tokenRe.lastIndex = 0; + + return index; + }; + + this.moveCursorShortWordRight = function() { + var row = this.lead.row; + var column = this.lead.column; + var line = this.doc.getLine(row); + var rightOfCursor = line.substring(column); + + var fold = this.session.getFoldAt(row, column, 1); + if (fold) + return this.moveCursorTo(fold.end.row, fold.end.column); + + if (column == line.length) { + var l = this.doc.getLength(); + do { + row++; + rightOfCursor = this.doc.getLine(row) + } while (row < l && /^\s*$/.test(rightOfCursor)) + + if (!/^\s+/.test(rightOfCursor)) + rightOfCursor = "" + column = 0; + } + + var index = this.$shortWordEndIndex(rightOfCursor); + + this.moveCursorTo(row, column + index); + }; + + this.moveCursorShortWordLeft = function() { + var row = this.lead.row; + var column = this.lead.column; + + var fold; + if (fold = this.session.getFoldAt(row, column, -1)) + return this.moveCursorTo(fold.start.row, fold.start.column); + + var line = this.session.getLine(row).substring(0, column); + if (column == 0) { + do { + row--; + line = this.doc.getLine(row); + } while (row > 0 && /^\s*$/.test(line)) + + column = line.length; + if (!/\s+$/.test(line)) + line = "" + } + + var leftOfCursor = lang.stringReverse(line); + var index = this.$shortWordEndIndex(leftOfCursor); + + return this.moveCursorTo(row, column - index); + }; + + this.moveCursorWordRight = function() { + if (this.session.$selectLongWords) + this.moveCursorLongWordRight(); + else + this.moveCursorShortWordRight(); + }; + + this.moveCursorWordLeft = function() { + if (this.session.$selectLongWords) + this.moveCursorLongWordLeft(); + else + this.moveCursorShortWordLeft(); + }; + this.moveCursorBy = function(rows, chars) { + var screenPos = this.session.documentToScreenPosition( + this.lead.row, + this.lead.column + ); + + if (chars === 0) { + if (this.$desiredColumn) + screenPos.column = this.$desiredColumn; + else + this.$desiredColumn = screenPos.column; + } + + var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column); + + // move the cursor and update the desired column + this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0); + }; + this.moveCursorToPosition = function(position) { + this.moveCursorTo(position.row, position.column); + }; + this.moveCursorTo = function(row, column, keepDesiredColumn) { + // Ensure the row/column is not inside of a fold. + var fold = this.session.getFoldAt(row, column, 1); + if (fold) { + row = fold.start.row; + column = fold.start.column; + } + + this.$keepDesiredColumnOnChange = true; + this.lead.setPosition(row, column); + this.$keepDesiredColumnOnChange = false; + + if (!keepDesiredColumn) + this.$desiredColumn = null; + }; + this.moveCursorToScreen = function(row, column, keepDesiredColumn) { + var pos = this.session.screenToDocumentPosition(row, column); + this.moveCursorTo(pos.row, pos.column, keepDesiredColumn); + }; + + // remove listeners from document + this.detach = function() { + this.lead.detach(); + this.anchor.detach(); + this.session = this.doc = null; + } + + this.fromOrientedRange = function(range) { + this.setSelectionRange(range, range.cursor == range.start); + this.$desiredColumn = range.desiredColumn || this.$desiredColumn; + } + + this.toOrientedRange = function(range) { + var r = this.getRange(); + if (range) { + range.start.column = r.start.column; + range.start.row = r.start.row; + range.end.column = r.end.column; + range.end.row = r.end.row; + } else { + range = r; + } + + range.cursor = this.isBackwards() ? range.start : range.end; + range.desiredColumn = this.$desiredColumn; + return range; + } + +}).call(Selection.prototype); + +exports.Selection = Selection; +}); + +ace.define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) { + + +/** + * class Range + * + * This object is used in various places to indicate a region within the editor. To better visualize how this works, imagine a rectangle. Each quadrant of the rectangle is analogus to a range, as ranges contain a starting row and starting column, and an ending row, and ending column. + * + **/ + +/** + * new Range(startRow, startColumn, endRow, endColumn) + * - startRow (Number): The starting row + * - startColumn (Number): The starting column + * - endRow (Number): The ending row + * - endColumn (Number): The ending column + * + * Creates a new `Range` object with the given starting and ending row and column points. + * + **/ +var Range = function(startRow, startColumn, endRow, endColumn) { + this.start = { + row: startRow, + column: startColumn + }; + + this.end = { + row: endRow, + column: endColumn + }; +}; + +(function() { + /** + * Range.isEqual(range) -> Boolean + * - range (Range): A range to check against + * + * Returns `true` if and only if the starting row and column, and ending tow and column, are equivalent to those given by `range`. + * + **/ + this.isEqual = function(range) { + return this.start.row == range.start.row && + this.end.row == range.end.row && + this.start.column == range.start.column && + this.end.column == range.end.column + }; + this.toString = function() { + return ("Range: [" + this.start.row + "/" + this.start.column + + "] -> [" + this.end.row + "/" + this.end.column + "]"); + }; + + this.contains = function(row, column) { + return this.compare(row, column) == 0; + }; + this.compareRange = function(range) { + var cmp, + end = range.end, + start = range.start; + + cmp = this.compare(end.row, end.column); + if (cmp == 1) { + cmp = this.compare(start.row, start.column); + if (cmp == 1) { + return 2; + } else if (cmp == 0) { + return 1; + } else { + return 0; + } + } else if (cmp == -1) { + return -2; + } else { + cmp = this.compare(start.row, start.column); + if (cmp == -1) { + return -1; + } else if (cmp == 1) { + return 42; + } else { + return 0; + } + } + } + + /** related to: Range.compare + * Range.comparePoint(p) -> Number + * - p (Range): A point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `0` if the two points are exactly equal
+ * * `-1` if `p.row` is less then the calling range
+ * * `1` if `p.row` is greater than the calling range
+ *
+ * If the starting row of the calling range is equal to `p.row`, and:
+ * * `p.column` is greater than or equal to the calling range's starting column, this returns `0`
+ * * Otherwise, it returns -1
+ *
+ * If the ending row of the calling range is equal to `p.row`, and:
+ * * `p.column` is less than or equal to the calling range's ending column, this returns `0`
+ * * Otherwise, it returns 1
+ * + * Checks the row and column points of `p` with the row and column points of the calling range. + * + * + * + **/ + this.comparePoint = function(p) { + return this.compare(p.row, p.column); + } + + /** related to: Range.comparePoint + * Range.containsRange(range) -> Boolean + * - range (Range): A range to compare with + * + * Checks the start and end points of `range` and compares them to the calling range. Returns `true` if the `range` is contained within the caller's range. + * + **/ + this.containsRange = function(range) { + return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; + } + + /** + * Range.intersects(range) -> Boolean + * - range (Range): A range to compare with + * + * Returns `true` if passed in `range` intersects with the one calling this method. + * + **/ + this.intersects = function(range) { + var cmp = this.compareRange(range); + return (cmp == -1 || cmp == 0 || cmp == 1); + } + + /** + * Range.isEnd(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the caller's ending row point is the same as `row`, and if the caller's ending column is the same as `column`. + * + **/ + this.isEnd = function(row, column) { + return this.end.row == row && this.end.column == column; + } + + /** + * Range.isStart(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the caller's starting row point is the same as `row`, and if the caller's starting column is the same as `column`. + * + **/ + this.isStart = function(row, column) { + return this.start.row == row && this.start.column == column; + } + + /** + * Range.setStart(row, column) + * - row (Number): A row point to set + * - column (Number): A column point to set + * + * Sets the starting row and column for the range. + * + **/ + this.setStart = function(row, column) { + if (typeof row == "object") { + this.start.column = row.column; + this.start.row = row.row; + } else { + this.start.row = row; + this.start.column = column; + } + } + + /** + * Range.setEnd(row, column) + * - row (Number): A row point to set + * - column (Number): A column point to set + * + * Sets the starting row and column for the range. + * + **/ + this.setEnd = function(row, column) { + if (typeof row == "object") { + this.end.column = row.column; + this.end.row = row.row; + } else { + this.end.row = row; + this.end.column = column; + } + } + + /** related to: Range.compare + * Range.inside(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the `row` and `column` are within the given range. + * + **/ + this.inside = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column) || this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + } + + /** related to: Range.compare + * Range.insideStart(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the `row` and `column` are within the given range's starting points. + * + **/ + this.insideStart = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column)) { + return false; + } else { + return true; + } + } + return false; + } + + /** related to: Range.compare + * Range.insideEnd(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the `row` and `column` are within the given range's ending points. + * + **/ + this.insideEnd = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + } + + /** + * Range.compare(row, column) -> Number + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `0` if the two points are exactly equal
+ * * `-1` if `p.row` is less then the calling range
+ * * `1` if `p.row` is greater than the calling range
+ *
+ * If the starting row of the calling range is equal to `p.row`, and:
+ * * `p.column` is greater than or equal to the calling range's starting column, this returns `0`
+ * * Otherwise, it returns -1
+ *
+ * If the ending row of the calling range is equal to `p.row`, and:
+ * * `p.column` is less than or equal to the calling range's ending column, this returns `0`
+ * * Otherwise, it returns 1 + * + * Checks the row and column points with the row and column points of the calling range. + * + * + **/ + this.compare = function(row, column) { + if (!this.isMultiLine()) { + if (row === this.start.row) { + return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); + }; + } + + if (row < this.start.row) + return -1; + + if (row > this.end.row) + return 1; + + if (this.start.row === row) + return column >= this.start.column ? 0 : -1; + + if (this.end.row === row) + return column <= this.end.column ? 0 : 1; + + return 0; + }; + this.compareStart = function(row, column) { + if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + } + + /** + * Range.compareEnd(row, column) -> Number + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `0` if the two points are exactly equal
+ * * `-1` if `p.row` is less then the calling range
+ * * `1` if `p.row` is greater than the calling range, or if `isEnd` is `true.
+ *
+ * If the starting row of the calling range is equal to `p.row`, and:
+ * * `p.column` is greater than or equal to the calling range's starting column, this returns `0`
+ * * Otherwise, it returns -1
+ *
+ * If the ending row of the calling range is equal to `p.row`, and:
+ * * `p.column` is less than or equal to the calling range's ending column, this returns `0`
+ * * Otherwise, it returns 1 + * + * Checks the row and column points with the row and column points of the calling range. + * + * + **/ + this.compareEnd = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else { + return this.compare(row, column); + } + } + + /** + * Range.compareInside(row, column) -> Number + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `1` if the ending row of the calling range is equal to `row`, and the ending column of the calling range is equal to `column`
+ * * `-1` if the starting row of the calling range is equal to `row`, and the starting column of the calling range is equal to `column`
+ *
+ * Otherwise, it returns the value after calling [[Range.compare `compare()`]]. + * + * Checks the row and column points with the row and column points of the calling range. + * + * + * + **/ + this.compareInside = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + } + + /** + * Range.clipRows(firstRow, lastRow) -> Range + * - firstRow (Number): The starting row + * - lastRow (Number): The ending row + * + * Returns the part of the current `Range` that occurs within the boundaries of `firstRow` and `lastRow` as a new `Range` object. + * + **/ + this.clipRows = function(firstRow, lastRow) { + if (this.end.row > lastRow) { + var end = { + row: lastRow+1, + column: 0 + }; + } + + if (this.start.row > lastRow) { + var start = { + row: lastRow+1, + column: 0 + }; + } + + if (this.start.row < firstRow) { + var start = { + row: firstRow, + column: 0 + }; + } + + if (this.end.row < firstRow) { + var end = { + row: firstRow, + column: 0 + }; + } + return Range.fromPoints(start || this.start, end || this.end); + }; + this.extend = function(row, column) { + var cmp = this.compare(row, column); + + if (cmp == 0) + return this; + else if (cmp == -1) + var start = {row: row, column: column}; + else + var end = {row: row, column: column}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + + this.isEmpty = function() { + return (this.start.row == this.end.row && this.start.column == this.end.column); + }; + this.isMultiLine = function() { + return (this.start.row !== this.end.row); + }; + this.clone = function() { + return Range.fromPoints(this.start, this.end); + }; + this.collapseRows = function() { + if (this.end.column == 0) + return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) + else + return new Range(this.start.row, 0, this.end.row, 0) + }; + this.toScreenRange = function(session) { + var screenPosStart = + session.documentToScreenPosition(this.start); + var screenPosEnd = + session.documentToScreenPosition(this.end); + + return new Range( + screenPosStart.row, screenPosStart.column, + screenPosEnd.row, screenPosEnd.column + ); + }; + +}).call(Range.prototype); +Range.fromPoints = function(start, end) { + return new Range(start.row, start.column, end.row, end.column); +}; + +exports.Range = Range; +}); + +ace.define('ace/mode/text', ['require', 'exports', 'module' , 'ace/tokenizer', 'ace/mode/text_highlight_rules', 'ace/mode/behaviour', 'ace/unicode'], function(require, exports, module) { + + +var Tokenizer = require("../tokenizer").Tokenizer; +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; +var Behaviour = require("./behaviour").Behaviour; +var unicode = require("../unicode"); + +var Mode = function() { + this.$tokenizer = new Tokenizer(new TextHighlightRules().getRules()); + this.$behaviour = new Behaviour(); +}; + +(function() { + + this.tokenRe = new RegExp("^[" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\\$_]+", "g" + ); + + this.nonTokenRe = new RegExp("^(?:[^" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\\$_]|\s])+", "g" + ); + + this.getTokenizer = function() { + return this.$tokenizer; + }; + + this.toggleCommentLines = function(state, doc, startRow, endRow) { + }; + + this.getNextLineIndent = function(state, line, tab) { + return ""; + }; + + this.checkOutdent = function(state, line, input) { + return false; + }; + + this.autoOutdent = function(state, doc, row) { + }; + + this.$getIndent = function(line) { + var match = line.match(/^(\s+)/); + if (match) { + return match[1]; + } + + return ""; + }; + + this.createWorker = function(session) { + return null; + }; + + this.createModeDelegates = function (mapping) { + if (!this.$embeds) { + return; + } + this.$modes = {}; + for (var i = 0; i < this.$embeds.length; i++) { + if (mapping[this.$embeds[i]]) { + this.$modes[this.$embeds[i]] = new mapping[this.$embeds[i]](); + } + } + + var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformAction']; + + for (var i = 0; i < delegations.length; i++) { + (function(scope) { + var functionName = delegations[i]; + var defaultHandler = scope[functionName]; + scope[delegations[i]] = function() { + return this.$delegator(functionName, arguments, defaultHandler); + } + } (this)); + } + } + + this.$delegator = function(method, args, defaultHandler) { + var state = args[0]; + + for (var i = 0; i < this.$embeds.length; i++) { + if (!this.$modes[this.$embeds[i]]) continue; + + var split = state.split(this.$embeds[i]); + if (!split[0] && split[1]) { + args[0] = split[1]; + var mode = this.$modes[this.$embeds[i]]; + return mode[method].apply(mode, args); + } + } + var ret = defaultHandler.apply(this, args); + return defaultHandler ? ret : undefined; + }; + + this.transformAction = function(state, action, editor, session, param) { + if (this.$behaviour) { + var behaviours = this.$behaviour.getBehaviours(); + for (var key in behaviours) { + if (behaviours[key][action]) { + var ret = behaviours[key][action].apply(this, arguments); + if (ret) { + return ret; + } + } + } + } + } + +}).call(Mode.prototype); + +exports.Mode = Mode; +}); + +ace.define('ace/tokenizer', ['require', 'exports', 'module' ], function(require, exports, module) { + + +/** + * class Tokenizer + * + * This class takes a set of highlighting rules, and creates a tokenizer out of them. For more information, see [the wiki on extending highlighters](https://github.com/ajaxorg/ace/wiki/Creating-or-Extending-an-Edit-Mode#wiki-extendingTheHighlighter). + * + **/ + +/** + * new Tokenizer(rules, flag) + * - rules (Object): The highlighting rules + * - flag (String): Any additional regular expression flags to pass (like "i" for case insensitive) + * + * Constructs a new tokenizer based on the given rules and flags. + * + **/ +var Tokenizer = function(rules, flag) { + flag = flag ? "g" + flag : "g"; + this.rules = rules; + + this.regExps = {}; + this.matchMappings = {}; + for ( var key in this.rules) { + var rule = this.rules[key]; + var state = rule; + var ruleRegExps = []; + var matchTotal = 0; + var mapping = this.matchMappings[key] = {}; + + for ( var i = 0; i < state.length; i++) { + + if (state[i].regex instanceof RegExp) + state[i].regex = state[i].regex.toString().slice(1, -1); + + // Count number of matching groups. 2 extra groups from the full match + // And the catch-all on the end (used to force a match); + var matchcount = new RegExp("(?:(" + state[i].regex + ")|(.))").exec("a").length - 2; + + // Replace any backreferences and offset appropriately. + var adjustedregex = state[i].regex.replace(/\\([0-9]+)/g, function (match, digit) { + return "\\" + (parseInt(digit, 10) + matchTotal + 1); + }); + + if (matchcount > 1 && state[i].token.length !== matchcount-1) + throw new Error("Matching groups and length of the token array don't match in rule #" + i + " of state " + key); + + mapping[matchTotal] = { + rule: i, + len: matchcount + }; + matchTotal += matchcount; + + ruleRegExps.push(adjustedregex); + } + + this.regExps[key] = new RegExp("(?:(" + ruleRegExps.join(")|(") + ")|(.))", flag); + } +}; + +(function() { + + /** + * Tokenizer.getLineTokens() -> Object + * + * Returns an object containing two properties: `tokens`, which contains all the tokens; and `state`, the current state. + **/ + this.getLineTokens = function(line, startState) { + var currentState = startState || "start"; + var state = this.rules[currentState]; + var mapping = this.matchMappings[currentState]; + var re = this.regExps[currentState]; + re.lastIndex = 0; + + var match, tokens = []; + + var lastIndex = 0; + + var token = { + type: null, + value: "" + }; + + while (match = re.exec(line)) { + var type = "text"; + var rule = null; + var value = [match[0]]; + + for (var i = 0; i < match.length-2; i++) { + if (match[i + 1] === undefined) + continue; + + rule = state[mapping[i].rule]; + + if (mapping[i].len > 1) + value = match.slice(i+2, i+1+mapping[i].len); + + // compute token type + if (typeof rule.token == "function") + type = rule.token.apply(this, value); + else + type = rule.token; + + if (rule.next) { + currentState = rule.next; + state = this.rules[currentState]; + mapping = this.matchMappings[currentState]; + lastIndex = re.lastIndex; + + re = this.regExps[currentState]; + re.lastIndex = lastIndex; + } + break; + } + + if (value[0]) { + if (typeof type == "string") { + value = [value.join("")]; + type = [type]; + } + for (var i = 0; i < value.length; i++) { + if (!value[i]) + continue; + + if ((!rule || rule.merge || type[i] === "text") && token.type === type[i]) { + token.value += value[i]; + } else { + if (token.type) + tokens.push(token); + + token = { + type: type[i], + value: value[i] + }; + } + } + } + + if (lastIndex == line.length) + break; + + lastIndex = re.lastIndex; + } + + if (token.type) + tokens.push(token); + + return { + tokens : tokens, + state : currentState + }; + }; + +}).call(Tokenizer.prototype); + +exports.Tokenizer = Tokenizer; +}); + +ace.define('ace/mode/text_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/lang'], function(require, exports, module) { + + +var lang = require("../lib/lang"); + +var TextHighlightRules = function() { + + // regexp must not have capturing parentheses + // regexps are ordered -> the first match is used + + this.$rules = { + "start" : [{ + token : "empty_line", + regex : '^$' + }, { + token : "text", + regex : ".+" + }] + }; +}; + +(function() { + + this.addRules = function(rules, prefix) { + for (var key in rules) { + var state = rules[key]; + for (var i=0; i +Uses the Unicode 5.2 character database + +This package for the XRegExp Unicode plugin enables the following Unicode categories (aka properties): + +L - Letter (the top-level Letter category is included in the Unicode plugin base script) + Ll - Lowercase letter + Lu - Uppercase letter + Lt - Titlecase letter + Lm - Modifier letter + Lo - Letter without case +M - Mark + Mn - Non-spacing mark + Mc - Spacing combining mark + Me - Enclosing mark +N - Number + Nd - Decimal digit + Nl - Letter number + No - Other number +P - Punctuation + Pd - Dash punctuation + Ps - Open punctuation + Pe - Close punctuation + Pi - Initial punctuation + Pf - Final punctuation + Pc - Connector punctuation + Po - Other punctuation +S - Symbol + Sm - Math symbol + Sc - Currency symbol + Sk - Modifier symbol + So - Other symbol +Z - Separator + Zs - Space separator + Zl - Line separator + Zp - Paragraph separator +C - Other + Cc - Control + Cf - Format + Co - Private use + Cs - Surrogate + Cn - Unassigned + +Example usage: + + \p{N} + \p{Cn} +*/ + + +// will be populated by addUnicodePackage +exports.packages = {}; + +addUnicodePackage({ + L: "0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", + Ll: "0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A", + Lu: "0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A", + Lt: "01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC", + Lm: "02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F", + Lo: "01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", + M: "0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26", + Mn: "0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26", + Mc: "0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC", + Me: "0488048906DE20DD-20E020E2-20E4A670-A672", + N: "0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", + Nd: "0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", + Nl: "16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF", + No: "00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835", + P: "0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65", + Pd: "002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D", + Ps: "0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62", + Pe: "0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63", + Pi: "00AB2018201B201C201F20392E022E042E092E0C2E1C2E20", + Pf: "00BB2019201D203A2E032E052E0A2E0D2E1D2E21", + Pc: "005F203F20402054FE33FE34FE4D-FE4FFF3F", + Po: "0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65", + S: "0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD", + Sm: "002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC", + Sc: "002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6", + Sk: "005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3", + So: "00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD", + Z: "002000A01680180E2000-200A20282029202F205F3000", + Zs: "002000A01680180E2000-200A202F205F3000", + Zl: "2028", + Zp: "2029", + C: "0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF", + Cc: "0000-001F007F-009F", + Cf: "00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB", + Co: "E000-F8FF", + Cs: "D800-DFFF", + Cn: "03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF" +}); + +function addUnicodePackage (pack) { + var codePoint = /\w{4}/g; + for (var name in pack) + exports.packages[name] = pack[name].replace(codePoint, "\\u$&"); +}; + +}); + +ace.define('ace/document', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/range', 'ace/anchor'], function(require, exports, module) { + + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var Range = require("./range").Range; +var Anchor = require("./anchor").Anchor; + + /** + * new Document([text]) + * - text (String | Array): The starting text + * + * Creates a new `Document`. If `text` is included, the `Document` contains those strings; otherwise, it's empty. + * + **/ + +var Document = function(text) { + this.$lines = []; + + // There has to be one line at least in the document. If you pass an empty + // string to the insert function, nothing will happen. Workaround. + if (text.length == 0) { + this.$lines = [""]; + } else if (Array.isArray(text)) { + this.insertLines(0, text); + } else { + this.insert({row: 0, column:0}, text); + } +}; + +(function() { + + oop.implement(this, EventEmitter); + this.setValue = function(text) { + var len = this.getLength(); + this.remove(new Range(0, 0, len, this.getLine(len-1).length)); + this.insert({row: 0, column:0}, text); + }; + this.getValue = function() { + return this.getAllLines().join(this.getNewLineCharacter()); + }; + this.createAnchor = function(row, column) { + return new Anchor(this, row, column); + }; + + // check for IE split bug + if ("aaa".split(/a/).length == 0) + this.$split = function(text) { + return text.replace(/\r\n|\r/g, "\n").split("\n"); + } + else + this.$split = function(text) { + return text.split(/\r\n|\r|\n/); + }; + this.$detectNewLine = function(text) { + var match = text.match(/^.*?(\r\n|\r|\n)/m); + if (match) { + this.$autoNewLine = match[1]; + } else { + this.$autoNewLine = "\n"; + } + }; + this.getNewLineCharacter = function() { + switch (this.$newLineMode) { + case "windows": + return "\r\n"; + + case "unix": + return "\n"; + + case "auto": + return this.$autoNewLine; + } + }; + + this.$autoNewLine = "\n"; + this.$newLineMode = "auto"; + this.setNewLineMode = function(newLineMode) { + if (this.$newLineMode === newLineMode) + return; + + this.$newLineMode = newLineMode; + }; + this.getNewLineMode = function() { + return this.$newLineMode; + }; + this.isNewLine = function(text) { + return (text == "\r\n" || text == "\r" || text == "\n"); + }; + this.getLine = function(row) { + return this.$lines[row] || ""; + }; + this.getLines = function(firstRow, lastRow) { + return this.$lines.slice(firstRow, lastRow + 1); + }; + this.getAllLines = function() { + return this.getLines(0, this.getLength()); + }; + this.getLength = function() { + return this.$lines.length; + }; + this.getTextRange = function(range) { + if (range.start.row == range.end.row) { + return this.$lines[range.start.row].substring(range.start.column, + range.end.column); + } + else { + var lines = this.getLines(range.start.row+1, range.end.row-1); + lines.unshift((this.$lines[range.start.row] || "").substring(range.start.column)); + lines.push((this.$lines[range.end.row] || "").substring(0, range.end.column)); + return lines.join(this.getNewLineCharacter()); + } + }; + this.$clipPosition = function(position) { + var length = this.getLength(); + if (position.row >= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length-1).length; + } + return position; + }; + this.insert = function(position, text) { + if (!text || text.length === 0) + return position; + + position = this.$clipPosition(position); + + // only detect new lines if the document has no line break yet + if (this.getLength() <= 1) + this.$detectNewLine(text); + + var lines = this.$split(text); + var firstLine = lines.splice(0, 1)[0]; + var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0]; + + position = this.insertInLine(position, firstLine); + if (lastLine !== null) { + position = this.insertNewLine(position); // terminate first line + position = this.insertLines(position.row, lines); + position = this.insertInLine(position, lastLine || ""); + } + return position; + }; + /** + * Document@change(e) + * - e (Object): Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties. + * + * Fires whenever the document changes. + * + * Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available: + * + * * `"insertLines"` (emitted by [[Document.insertLines]]) + * * `range`: the [[Range]] of the change within the document + * * `lines`: the lines in the document that are changing + * * `"insertText"` (emitted by [[Document.insertNewLine]]) + * * `range`: the [[Range]] of the change within the document + * * `text`: the text that's being added + * * `"removeLines"` (emitted by [[Document.insertLines]]) + * * `range`: the [[Range]] of the change within the document + * * `lines`: the lines in the document that were removed + * * `nl`: the new line character (as defined by [[Document.getNewLineCharacter]]) + * * `"removeText"` (emitted by [[Document.removeInLine]] and [[Document.removeNewLine]]) + * * `range`: the [[Range]] of the change within the document + * * `text`: the text that's being removed + * + **/ + this.insertLines = function(row, lines) { + if (lines.length == 0) + return {row: row, column: 0}; + + // apply doesn't work for big arrays (smallest threshold is on safari 0xFFFF) + // to circumvent that we have to break huge inserts into smaller chunks here + if (lines.length > 0xFFFF) { + var end = this.insertLines(row, lines.slice(0xFFFF)); + lines = lines.slice(0, 0xFFFF); + } + + var args = [row, 0]; + args.push.apply(args, lines); + this.$lines.splice.apply(this.$lines, args); + + var range = new Range(row, 0, row + lines.length, 0); + var delta = { + action: "insertLines", + range: range, + lines: lines + }; + this._emit("change", { data: delta }); + return end || range.end; + }; + this.insertNewLine = function(position) { + position = this.$clipPosition(position); + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column); + this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length)); + + var end = { + row : position.row + 1, + column : 0 + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: this.getNewLineCharacter() + }; + this._emit("change", { data: delta }); + + return end; + }; + this.insertInLine = function(position, text) { + if (text.length == 0) + return position; + + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column) + text + + line.substring(position.column); + + var end = { + row : position.row, + column : position.column + text.length + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: text + }; + this._emit("change", { data: delta }); + + return end; + }; + this.remove = function(range) { + // clip to document + range.start = this.$clipPosition(range.start); + range.end = this.$clipPosition(range.end); + + if (range.isEmpty()) + return range.start; + + var firstRow = range.start.row; + var lastRow = range.end.row; + + if (range.isMultiLine()) { + var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1; + var lastFullRow = lastRow - 1; + + if (range.end.column > 0) + this.removeInLine(lastRow, 0, range.end.column); + + if (lastFullRow >= firstFullRow) + this.removeLines(firstFullRow, lastFullRow); + + if (firstFullRow != firstRow) { + this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length); + this.removeNewLine(range.start.row); + } + } + else { + this.removeInLine(firstRow, range.start.column, range.end.column); + } + return range.start; + }; + this.removeInLine = function(row, startColumn, endColumn) { + if (startColumn == endColumn) + return; + + var range = new Range(row, startColumn, row, endColumn); + var line = this.getLine(row); + var removed = line.substring(startColumn, endColumn); + var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length); + this.$lines.splice(row, 1, newLine); + + var delta = { + action: "removeText", + range: range, + text: removed + }; + this._emit("change", { data: delta }); + return range.start; + }; + this.removeLines = function(firstRow, lastRow) { + var range = new Range(firstRow, 0, lastRow + 1, 0); + var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1); + + var delta = { + action: "removeLines", + range: range, + nl: this.getNewLineCharacter(), + lines: removed + }; + this._emit("change", { data: delta }); + return removed; + }; + this.removeNewLine = function(row) { + var firstLine = this.getLine(row); + var secondLine = this.getLine(row+1); + + var range = new Range(row, firstLine.length, row+1, 0); + var line = firstLine + secondLine; + + this.$lines.splice(row, 2, line); + + var delta = { + action: "removeText", + range: range, + text: this.getNewLineCharacter() + }; + this._emit("change", { data: delta }); + }; + this.replace = function(range, text) { + if (text.length == 0 && range.isEmpty()) + return range.start; + + // Shortcut: If the text we want to insert is the same as it is already + // in the document, we don't have to replace anything. + if (text == this.getTextRange(range)) + return range.end; + + this.remove(range); + if (text) { + var end = this.insert(range.start, text); + } + else { + end = range.start; + } + + return end; + }; + this.applyDeltas = function(deltas) { + for (var i=0; i=0; i--) { + var delta = deltas[i]; + + var range = Range.fromPoints(delta.range.start, delta.range.end); + + if (delta.action == "insertLines") + this.removeLines(range.start.row, range.end.row - 1); + else if (delta.action == "insertText") + this.remove(range); + else if (delta.action == "removeLines") + this.insertLines(range.start.row, delta.lines); + else if (delta.action == "removeText") + this.insert(range.start, delta.text); + } + }; + +}).call(Document.prototype); + +exports.Document = Document; +}); + +ace.define('ace/anchor', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) { + + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; + +/** + * new Anchor(doc, row, column) + * - doc (Document): The document to associate with the anchor + * - row (Number): The starting row position + * - column (Number): The starting column position + * + * Creates a new `Anchor` and associates it with a document. + * + **/ + +var Anchor = exports.Anchor = function(doc, row, column) { + this.document = doc; + + if (typeof column == "undefined") + this.setPosition(row.row, row.column); + else + this.setPosition(row, column); + + this.$onChange = this.onChange.bind(this); + doc.on("change", this.$onChange); +}; + +(function() { + + oop.implement(this, EventEmitter); + + this.getPosition = function() { + return this.$clipPositionToDocument(this.row, this.column); + }; + + this.getDocument = function() { + return this.document; + }; + + this.onChange = function(e) { + var delta = e.data; + var range = delta.range; + + if (range.start.row == range.end.row && range.start.row != this.row) + return; + + if (range.start.row > this.row) + return; + + if (range.start.row == this.row && range.start.column > this.column) + return; + + var row = this.row; + var column = this.column; + + if (delta.action === "insertText") { + if (range.start.row === row && range.start.column <= column) { + if (range.start.row === range.end.row) { + column += range.end.column - range.start.column; + } + else { + column -= range.start.column; + row += range.end.row - range.start.row; + } + } + else if (range.start.row !== range.end.row && range.start.row < row) { + row += range.end.row - range.start.row; + } + } else if (delta.action === "insertLines") { + if (range.start.row <= row) { + row += range.end.row - range.start.row; + } + } + else if (delta.action == "removeText") { + if (range.start.row == row && range.start.column < column) { + if (range.end.column >= column) + column = range.start.column; + else + column = Math.max(0, column - (range.end.column - range.start.column)); + + } else if (range.start.row !== range.end.row && range.start.row < row) { + if (range.end.row == row) { + column = Math.max(0, column - range.end.column) + range.start.column; + } + row -= (range.end.row - range.start.row); + } + else if (range.end.row == row) { + row -= range.end.row - range.start.row; + column = Math.max(0, column - range.end.column) + range.start.column; + } + } else if (delta.action == "removeLines") { + if (range.start.row <= row) { + if (range.end.row <= row) + row -= range.end.row - range.start.row; + else { + row = range.start.row; + column = 0; + } + } + } + + this.setPosition(row, column, true); + }; + + this.setPosition = function(row, column, noClip) { + var pos; + if (noClip) { + pos = { + row: row, + column: column + }; + } + else { + pos = this.$clipPositionToDocument(row, column); + } + + if (this.row == pos.row && this.column == pos.column) + return; + + var old = { + row: this.row, + column: this.column + }; + + this.row = pos.row; + this.column = pos.column; + this._emit("change", { + old: old, + value: pos + }); + }; + + this.detach = function() { + this.document.removeEventListener("change", this.$onChange); + }; + + this.$clipPositionToDocument = function(row, column) { + var pos = {}; + + if (row >= this.document.getLength()) { + pos.row = Math.max(0, this.document.getLength() - 1); + pos.column = this.document.getLine(pos.row).length; + } + else if (row < 0) { + pos.row = 0; + pos.column = 0; + } + else { + pos.row = row; + pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); + } + + if (column < 0) + pos.column = 0; + + return pos; + }; + +}).call(Anchor.prototype); + +}); + +ace.define('ace/background_tokenizer', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) { + + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; + +// tokenizing lines longer than this makes editor very slow +var MAX_LINE_LENGTH = 5000; + +/** + * new BackgroundTokenizer(tokenizer, editor) + * - tokenizer (Tokenizer): The tokenizer to use + * - editor (Editor): The editor to associate with + * + * Creates a new `BackgroundTokenizer` object. + * + * + **/ + +var BackgroundTokenizer = function(tokenizer, editor) { + this.running = false; + this.lines = []; + this.states = []; + this.currentLine = 0; + this.tokenizer = tokenizer; + + var self = this; + + this.$worker = function() { + if (!self.running) { return; } + + var workerStart = new Date(); + var startLine = self.currentLine; + var doc = self.doc; + + var processedLines = 0; + + var len = doc.getLength(); + while (self.currentLine < len) { + self.$tokenizeRow(self.currentLine); + while (self.lines[self.currentLine]) + self.currentLine++; + + // only check every 5 lines + processedLines ++; + if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) { + self.fireUpdateEvent(startLine, self.currentLine-1); + self.running = setTimeout(self.$worker, 20); + return; + } + } + + self.running = false; + + self.fireUpdateEvent(startLine, len - 1); + }; +}; + +(function(){ + + oop.implement(this, EventEmitter); + this.setTokenizer = function(tokenizer) { + this.tokenizer = tokenizer; + this.lines = []; + this.states = []; + + this.start(0); + }; + this.setDocument = function(doc) { + this.doc = doc; + this.lines = []; + this.states = []; + + this.stop(); + }; + /** + * BackgroundTokenizer@update(e) + * - e (Object): An object containing two properties, `first` and `last`, which indicate the rows of the region being updated. + * + * Fires whenever the background tokeniziers between a range of rows are going to be updated. + * + **/ + this.fireUpdateEvent = function(firstRow, lastRow) { + var data = { + first: firstRow, + last: lastRow + }; + this._emit("update", {data: data}); + }; + this.start = function(startRow) { + this.currentLine = Math.min(startRow || 0, this.currentLine, this.doc.getLength()); + + // remove all cached items below this line + this.lines.splice(this.currentLine, this.lines.length); + this.states.splice(this.currentLine, this.states.length); + + this.stop(); + // pretty long delay to prevent the tokenizer from interfering with the user + this.running = setTimeout(this.$worker, 700); + }; + + this.$updateOnChange = function(delta) { + var range = delta.range; + var startRow = range.start.row; + var len = range.end.row - startRow; + + if (len === 0) { + this.lines[startRow] = null; + } else if (delta.action == "removeText" || delta.action == "removeLines") { + this.lines.splice(startRow, len + 1, null); + this.states.splice(startRow, len + 1, null); + } else { + var args = Array(len + 1); + args.unshift(startRow, 1); + this.lines.splice.apply(this.lines, args); + this.states.splice.apply(this.states, args); + } + + this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength()); + + this.stop(); + // pretty long delay to prevent the tokenizer from interfering with the user + this.running = setTimeout(this.$worker, 700); + }; + this.stop = function() { + if (this.running) + clearTimeout(this.running); + this.running = false; + }; + this.getTokens = function(row) { + return this.lines[row] || this.$tokenizeRow(row); + }; + this.getState = function(row) { + if (this.currentLine == row) + this.$tokenizeRow(row); + return this.states[row] || "start"; + }; + + this.$tokenizeRow = function(row) { + var line = this.doc.getLine(row); + var state = this.states[row - 1]; + + if (line.length > MAX_LINE_LENGTH) { + var overflow = {value: line.substr(MAX_LINE_LENGTH), type: "text"}; + line = line.slice(0, MAX_LINE_LENGTH); + } + var data = this.tokenizer.getLineTokens(line, state); + if (overflow) { + data.tokens.push(overflow); + data.state = "start"; + } + + if (this.states[row] !== data.state) { + this.states[row] = data.state; + this.lines[row + 1] = null; + if (this.currentLine > row + 1) + this.currentLine = row + 1; + } else if (this.currentLine == row) { + this.currentLine = row + 1; + } + + return this.lines[row] = data.tokens; + }; + +}).call(BackgroundTokenizer.prototype); + +exports.BackgroundTokenizer = BackgroundTokenizer; +}); + +ace.define('ace/search_highlight', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/lib/oop', 'ace/range'], function(require, exports, module) { + + +var lang = require("./lib/lang"); +var oop = require("./lib/oop"); +var Range = require("./range").Range; + +var SearchHighlight = function(regExp, clazz, type) { + this.setRegexp(regExp); + this.clazz = clazz; + this.type = type || "text"; +}; + +(function() { + this.setRegexp = function(regExp) { + if (this.regExp+"" == regExp+"") + return; + this.regExp = regExp; + this.cache = []; + }; + + this.update = function(html, markerLayer, session, config) { + if (!this.regExp) + return; + var start = config.firstRow, end = config.lastRow; + + for (var i = start; i <= end; i++) { + var ranges = this.cache[i]; + if (ranges == null) { + ranges = lang.getMatchOffsets(session.getLine(i), this.regExp); + ranges = ranges.map(function(match) { + return new Range(i, match.offset, i, match.offset + match.length); + }); + this.cache[i] = ranges.length ? ranges : ""; + } + + for (var j = ranges.length; j --; ) { + markerLayer.drawSingleLineMarker( + html, ranges[j].toScreenRange(session), this.clazz, config, + null, this.type + ); + } + } + }; + +}).call(SearchHighlight.prototype); + +exports.SearchHighlight = SearchHighlight; +}); + +ace.define('ace/edit_session/folding', ['require', 'exports', 'module' , 'ace/range', 'ace/edit_session/fold_line', 'ace/edit_session/fold', 'ace/token_iterator'], function(require, exports, module) { + + +var Range = require("../range").Range; +var FoldLine = require("./fold_line").FoldLine; +var Fold = require("./fold").Fold; +var TokenIterator = require("../token_iterator").TokenIterator; + +function Folding() { + /* + * Looks up a fold at a given row/column. Possible values for side: + * -1: ignore a fold if fold.start = row/column + * +1: ignore a fold if fold.end = row/column + */ + this.getFoldAt = function(row, column, side) { + var foldLine = this.getFoldLine(row); + if (!foldLine) + return null; + + var folds = foldLine.folds; + for (var i = 0; i < folds.length; i++) { + var fold = folds[i]; + if (fold.range.contains(row, column)) { + if (side == 1 && fold.range.isEnd(row, column)) { + continue; + } else if (side == -1 && fold.range.isStart(row, column)) { + continue; + } + return fold; + } + } + }; + this.getFoldsInRange = function(range) { + range = range.clone(); + var start = range.start; + var end = range.end; + var foldLines = this.$foldData; + var foundFolds = []; + + start.column += 1; + end.column -= 1; + + for (var i = 0; i < foldLines.length; i++) { + var cmp = foldLines[i].range.compareRange(range); + if (cmp == 2) { + // Range is before foldLine. No intersection. This means, + // there might be other foldLines that intersect. + continue; + } + else if (cmp == -2) { + // Range is after foldLine. There can't be any other foldLines then, + // so let's give up. + break; + } + + var folds = foldLines[i].folds; + for (var j = 0; j < folds.length; j++) { + var fold = folds[j]; + cmp = fold.range.compareRange(range); + if (cmp == -2) { + break; + } else if (cmp == 2) { + continue; + } else + // WTF-state: Can happen due to -1/+1 to start/end column. + if (cmp == 42) { + break; + } + foundFolds.push(fold); + } + } + return foundFolds; + }; + this.getAllFolds = function() { + var folds = []; + var foldLines = this.$foldData; + + function addFold(fold) { + folds.push(fold); + if (!fold.subFolds) + return; + + for (var i = 0; i < fold.subFolds.length; i++) + addFold(fold.subFolds[i]); + } + + for (var i = 0; i < foldLines.length; i++) + for (var j = 0; j < foldLines[i].folds.length; j++) + addFold(foldLines[i].folds[j]); + + return folds; + }; + this.getFoldStringAt = function(row, column, trim, foldLine) { + foldLine = foldLine || this.getFoldLine(row); + if (!foldLine) + return null; + + var lastFold = { + end: { column: 0 } + }; + // TODO: Refactor to use getNextFoldTo function. + var str, fold; + for (var i = 0; i < foldLine.folds.length; i++) { + fold = foldLine.folds[i]; + var cmp = fold.range.compareEnd(row, column); + if (cmp == -1) { + str = this + .getLine(fold.start.row) + .substring(lastFold.end.column, fold.start.column); + break; + } + else if (cmp === 0) { + return null; + } + lastFold = fold; + } + if (!str) + str = this.getLine(fold.start.row).substring(lastFold.end.column); + + if (trim == -1) + return str.substring(0, column - lastFold.end.column); + else if (trim == 1) + return str.substring(column - lastFold.end.column); + else + return str; + }; + + this.getFoldLine = function(docRow, startFoldLine) { + var foldData = this.$foldData; + var i = 0; + if (startFoldLine) + i = foldData.indexOf(startFoldLine); + if (i == -1) + i = 0; + for (i; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) { + return foldLine; + } else if (foldLine.end.row > docRow) { + return null; + } + } + return null; + }; + + // returns the fold which starts after or contains docRow + this.getNextFoldLine = function(docRow, startFoldLine) { + var foldData = this.$foldData; + var i = 0; + if (startFoldLine) + i = foldData.indexOf(startFoldLine); + if (i == -1) + i = 0; + for (i; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (foldLine.end.row >= docRow) { + return foldLine; + } + } + return null; + }; + + this.getFoldedRowCount = function(first, last) { + var foldData = this.$foldData, rowCount = last-first+1; + for (var i = 0; i < foldData.length; i++) { + var foldLine = foldData[i], + end = foldLine.end.row, + start = foldLine.start.row; + if (end >= last) { + if(start < last) { + if(start >= first) + rowCount -= last-start; + else + rowCount = 0;//in one fold + } + break; + } else if(end >= first){ + if (start >= first) //fold inside range + rowCount -= end-start; + else + rowCount -= end-first+1; + } + } + return rowCount; + }; + + this.$addFoldLine = function(foldLine) { + this.$foldData.push(foldLine); + this.$foldData.sort(function(a, b) { + return a.start.row - b.start.row; + }); + return foldLine; + }; + this.addFold = function(placeholder, range) { + var foldData = this.$foldData; + var added = false; + var fold; + + if (placeholder instanceof Fold) + fold = placeholder; + else + fold = new Fold(range, placeholder); + + this.$clipRangeToDocument(fold.range); + + var startRow = fold.start.row; + var startColumn = fold.start.column; + var endRow = fold.end.row; + var endColumn = fold.end.column; + + // --- Some checking --- + if (fold.placeholder.length < 2) + throw "Placeholder has to be at least 2 characters"; + + if (startRow == endRow && endColumn - startColumn < 2) + throw "The range has to be at least 2 characters width"; + + var startFold = this.getFoldAt(startRow, startColumn, 1); + var endFold = this.getFoldAt(endRow, endColumn, -1); + if (startFold && endFold == startFold) + return startFold.addSubFold(fold); + + if ( + (startFold && !startFold.range.isStart(startRow, startColumn)) + || (endFold && !endFold.range.isEnd(endRow, endColumn)) + ) { + throw "A fold can't intersect already existing fold" + fold.range + startFold.range; + } + + // Check if there are folds in the range we create the new fold for. + var folds = this.getFoldsInRange(fold.range); + if (folds.length > 0) { + // Remove the folds from fold data. + this.removeFolds(folds); + // Add the removed folds as subfolds on the new fold. + fold.subFolds = folds; + } + + for (var i = 0; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (endRow == foldLine.start.row) { + foldLine.addFold(fold); + added = true; + break; + } + else if (startRow == foldLine.end.row) { + foldLine.addFold(fold); + added = true; + if (!fold.sameRow) { + // Check if we might have to merge two FoldLines. + var foldLineNext = foldData[i + 1]; + if (foldLineNext && foldLineNext.start.row == endRow) { + // We need to merge! + foldLine.merge(foldLineNext); + break; + } + } + break; + } + else if (endRow <= foldLine.start.row) { + break; + } + } + + if (!added) + foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold)); + + if (this.$useWrapMode) + this.$updateWrapData(foldLine.start.row, foldLine.start.row); + else + this.$updateRowLengthCache(foldLine.start.row, foldLine.start.row); + + // Notify that fold data has changed. + this.$modified = true; + this._emit("changeFold", { data: fold }); + + return fold; + }; + + this.addFolds = function(folds) { + folds.forEach(function(fold) { + this.addFold(fold); + }, this); + }; + + this.removeFold = function(fold) { + var foldLine = fold.foldLine; + var startRow = foldLine.start.row; + var endRow = foldLine.end.row; + + var foldLines = this.$foldData; + var folds = foldLine.folds; + // Simple case where there is only one fold in the FoldLine such that + // the entire fold line can get removed directly. + if (folds.length == 1) { + foldLines.splice(foldLines.indexOf(foldLine), 1); + } else + // If the fold is the last fold of the foldLine, just remove it. + if (foldLine.range.isEnd(fold.end.row, fold.end.column)) { + folds.pop(); + foldLine.end.row = folds[folds.length - 1].end.row; + foldLine.end.column = folds[folds.length - 1].end.column; + } else + // If the fold is the first fold of the foldLine, just remove it. + if (foldLine.range.isStart(fold.start.row, fold.start.column)) { + folds.shift(); + foldLine.start.row = folds[0].start.row; + foldLine.start.column = folds[0].start.column; + } else + // We know there are more then 2 folds and the fold is not at the edge. + // This means, the fold is somewhere in between. + // + // If the fold is in one row, we just can remove it. + if (fold.sameRow) { + folds.splice(folds.indexOf(fold), 1); + } else + // The fold goes over more then one row. This means remvoing this fold + // will cause the fold line to get splitted up. newFoldLine is the second part + { + var newFoldLine = foldLine.split(fold.start.row, fold.start.column); + folds = newFoldLine.folds; + folds.shift(); + newFoldLine.start.row = folds[0].start.row; + newFoldLine.start.column = folds[0].start.column; + } + + if (this.$useWrapMode) + this.$updateWrapData(startRow, endRow); + else + this.$updateRowLengthCache(startRow, endRow); + + // Notify that fold data has changed. + this.$modified = true; + this._emit("changeFold", { data: fold }); + }; + + this.removeFolds = function(folds) { + // We need to clone the folds array passed in as it might be the folds + // array of a fold line and as we call this.removeFold(fold), folds + // are removed from folds and changes the current index. + var cloneFolds = []; + for (var i = 0; i < folds.length; i++) { + cloneFolds.push(folds[i]); + } + + cloneFolds.forEach(function(fold) { + this.removeFold(fold); + }, this); + this.$modified = true; + }; + + this.expandFold = function(fold) { + this.removeFold(fold); + fold.subFolds.forEach(function(fold) { + this.addFold(fold); + }, this); + fold.subFolds = []; + }; + + this.expandFolds = function(folds) { + folds.forEach(function(fold) { + this.expandFold(fold); + }, this); + }; + + this.unfold = function(location, expandInner) { + var range, folds; + if (location == null) + range = new Range(0, 0, this.getLength(), 0); + else if (typeof location == "number") + range = new Range(location, 0, location, this.getLine(location).length); + else if ("row" in location) + range = Range.fromPoints(location, location); + else + range = location; + + folds = this.getFoldsInRange(range); + if (expandInner) { + this.removeFolds(folds); + } else { + // TODO: might need to remove and add folds in one go instead of using + // expandFolds several times. + while (folds.length) { + this.expandFolds(folds); + folds = this.getFoldsInRange(range); + } + } + }; + this.isRowFolded = function(docRow, startFoldRow) { + return !!this.getFoldLine(docRow, startFoldRow); + }; + + this.getRowFoldEnd = function(docRow, startFoldRow) { + var foldLine = this.getFoldLine(docRow, startFoldRow); + return foldLine ? foldLine.end.row : docRow; + }; + + this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) { + if (startRow == null) { + startRow = foldLine.start.row; + startColumn = 0; + } + + if (endRow == null) { + endRow = foldLine.end.row; + endColumn = this.getLine(endRow).length; + } + + // Build the textline using the FoldLine walker. + var doc = this.doc; + var textLine = ""; + + foldLine.walk(function(placeholder, row, column, lastColumn) { + if (row < startRow) { + return; + } else if (row == startRow) { + if (column < startColumn) { + return; + } + lastColumn = Math.max(startColumn, lastColumn); + } + if (placeholder) { + textLine += placeholder; + } else { + textLine += doc.getLine(row).substring(lastColumn, column); + } + }.bind(this), endRow, endColumn); + return textLine; + }; + + this.getDisplayLine = function(row, endColumn, startRow, startColumn) { + var foldLine = this.getFoldLine(row); + + if (!foldLine) { + var line; + line = this.doc.getLine(row); + return line.substring(startColumn || 0, endColumn || line.length); + } else { + return this.getFoldDisplayLine( + foldLine, row, endColumn, startRow, startColumn); + } + }; + + this.$cloneFoldData = function() { + var fd = []; + fd = this.$foldData.map(function(foldLine) { + var folds = foldLine.folds.map(function(fold) { + return fold.clone(); + }); + return new FoldLine(fd, folds); + }); + + return fd; + }; + + this.toggleFold = function(tryToUnfold) { + var selection = this.selection; + var range = selection.getRange(); + var fold; + var bracketPos; + + if (range.isEmpty()) { + var cursor = range.start; + fold = this.getFoldAt(cursor.row, cursor.column); + + if (fold) { + this.expandFold(fold); + return; + } + else if (bracketPos = this.findMatchingBracket(cursor)) { + if (range.comparePoint(bracketPos) == 1) { + range.end = bracketPos; + } + else { + range.start = bracketPos; + range.start.column++; + range.end.column--; + } + } + else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) { + if (range.comparePoint(bracketPos) == 1) + range.end = bracketPos; + else + range.start = bracketPos; + + range.start.column++; + } + else { + range = this.getCommentFoldRange(cursor.row, cursor.column) || range; + } + } else { + var folds = this.getFoldsInRange(range); + if (tryToUnfold && folds.length) { + this.expandFolds(folds); + return; + } + else if (folds.length == 1 ) { + fold = folds[0]; + } + } + + if (!fold) + fold = this.getFoldAt(range.start.row, range.start.column); + + if (fold && fold.range.toString() == range.toString()) { + this.expandFold(fold); + return; + } + + var placeholder = "..."; + if (!range.isMultiLine()) { + placeholder = this.getTextRange(range); + if(placeholder.length < 4) + return; + placeholder = placeholder.trim().substring(0, 2) + ".."; + } + + this.addFold(placeholder, range); + }; + + this.getCommentFoldRange = function(row, column) { + var iterator = new TokenIterator(this, row, column); + var token = iterator.getCurrentToken(); + if (token && /^comment|string/.test(token.type)) { + var range = new Range(); + var re = new RegExp(token.type.replace(/\..*/, "\\.")); + do { + token = iterator.stepBackward(); + } while(token && re.test(token.type)); + + iterator.stepForward(); + range.start.row = iterator.getCurrentTokenRow(); + range.start.column = iterator.getCurrentTokenColumn() + 2; + + iterator = new TokenIterator(this, row, column); + + do { + token = iterator.stepForward(); + } while(token && re.test(token.type)); + + token = iterator.stepBackward(); + + range.end.row = iterator.getCurrentTokenRow(); + range.end.column = iterator.getCurrentTokenColumn() + token.value.length; + return range; + } + }; + + this.foldAll = function(startRow, endRow) { + var foldWidgets = this.foldWidgets; + endRow = endRow || this.getLength(); + for (var row = startRow || 0; row < endRow; row++) { + if (foldWidgets[row] == null) + foldWidgets[row] = this.getFoldWidget(row); + if (foldWidgets[row] != "start") + continue; + + var range = this.getFoldWidgetRange(row); + // sometimes range can be incompatible with existing fold + // wouldn't it be better for addFold to return null istead of throwing? + if (range && range.end.row < endRow) try { + this.addFold("...", range); + } catch(e) {} + } + }; + + this.$foldStyles = { + "manual": 1, + "markbegin": 1, + "markbeginend": 1 + }; + this.$foldStyle = "markbegin"; + this.setFoldStyle = function(style) { + if (!this.$foldStyles[style]) + throw new Error("invalid fold style: " + style + "[" + Object.keys(this.$foldStyles).join(", ") + "]"); + + if (this.$foldStyle == style) + return; + + this.$foldStyle = style; + + if (style == "manual") + this.unfold(); + + // reset folding + var mode = this.$foldMode; + this.$setFolding(null); + this.$setFolding(mode); + }; + + // structured folding + this.$setFolding = function(foldMode) { + if (this.$foldMode == foldMode) + return; + + this.$foldMode = foldMode; + + this.removeListener('change', this.$updateFoldWidgets); + this._emit("changeAnnotation"); + + if (!foldMode || this.$foldStyle == "manual") { + this.foldWidgets = null; + return; + } + + this.foldWidgets = []; + this.getFoldWidget = foldMode.getFoldWidget.bind(foldMode, this, this.$foldStyle); + this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle); + + this.$updateFoldWidgets = this.updateFoldWidgets.bind(this); + this.on('change', this.$updateFoldWidgets); + + }; + + this.onFoldWidgetClick = function(row, e) { + var type = this.getFoldWidget(row); + var line = this.getLine(row); + var onlySubfolds = e.shiftKey; + var addSubfolds = onlySubfolds || e.ctrlKey || e.altKey || e.metaKey; + var fold; + + if (type == "end") + fold = this.getFoldAt(row, 0, -1); + else + fold = this.getFoldAt(row, line.length, 1); + + if (fold) { + if (addSubfolds) + this.removeFold(fold); + else + this.expandFold(fold); + return; + } + + var range = this.getFoldWidgetRange(row); + if (range) { + // sometimes singleline folds can be missed by the code above + if (!range.isMultiLine()) { + fold = this.getFoldAt(range.start.row, range.start.column, 1); + if (fold && range.isEqual(fold.range)) { + this.removeFold(fold); + return; + } + } + + if (!onlySubfolds) + this.addFold("...", range); + + if (addSubfolds) + this.foldAll(range.start.row + 1, range.end.row); + } else { + if (addSubfolds) + this.foldAll(row + 1, this.getLength()); + (e.target || e.srcElement).className += " invalid" + } + }; + + this.updateFoldWidgets = function(e) { + var delta = e.data; + var range = delta.range; + var firstRow = range.start.row; + var len = range.end.row - firstRow; + + if (len === 0) { + this.foldWidgets[firstRow] = null; + } else if (delta.action == "removeText" || delta.action == "removeLines") { + this.foldWidgets.splice(firstRow, len + 1, null); + } else { + var args = Array(len + 1); + args.unshift(firstRow, 1); + this.foldWidgets.splice.apply(this.foldWidgets, args); + } + }; + +} + +exports.Folding = Folding; + +}); + +ace.define('ace/edit_session/fold_line', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) { + + +var Range = require("../range").Range; +function FoldLine(foldData, folds) { + this.foldData = foldData; + if (Array.isArray(folds)) { + this.folds = folds; + } else { + folds = this.folds = [ folds ]; + } + + var last = folds[folds.length - 1] + this.range = new Range(folds[0].start.row, folds[0].start.column, + last.end.row, last.end.column); + this.start = this.range.start; + this.end = this.range.end; + + this.folds.forEach(function(fold) { + fold.setFoldLine(this); + }, this); +} + +(function() { + /* + * Note: This doesn't update wrapData! + */ + this.shiftRow = function(shift) { + this.start.row += shift; + this.end.row += shift; + this.folds.forEach(function(fold) { + fold.start.row += shift; + fold.end.row += shift; + }); + } + + this.addFold = function(fold) { + if (fold.sameRow) { + if (fold.start.row < this.startRow || fold.endRow > this.endRow) { + throw "Can't add a fold to this FoldLine as it has no connection"; + } + this.folds.push(fold); + this.folds.sort(function(a, b) { + return -a.range.compareEnd(b.start.row, b.start.column); + }); + if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) { + this.end.row = fold.end.row; + this.end.column = fold.end.column; + } else if (this.range.compareStart(fold.end.row, fold.end.column) < 0) { + this.start.row = fold.start.row; + this.start.column = fold.start.column; + } + } else if (fold.start.row == this.end.row) { + this.folds.push(fold); + this.end.row = fold.end.row; + this.end.column = fold.end.column; + } else if (fold.end.row == this.start.row) { + this.folds.unshift(fold); + this.start.row = fold.start.row; + this.start.column = fold.start.column; + } else { + throw "Trying to add fold to FoldRow that doesn't have a matching row"; + } + fold.foldLine = this; + } + + this.containsRow = function(row) { + return row >= this.start.row && row <= this.end.row; + } + + this.walk = function(callback, endRow, endColumn) { + var lastEnd = 0, + folds = this.folds, + fold, + comp, stop, isNewRow = true; + + if (endRow == null) { + endRow = this.end.row; + endColumn = this.end.column; + } + + for (var i = 0; i < folds.length; i++) { + fold = folds[i]; + + comp = fold.range.compareStart(endRow, endColumn); + // This fold is after the endRow/Column. + if (comp == -1) { + callback(null, endRow, endColumn, lastEnd, isNewRow); + return; + } + + stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow); + stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd); + + // If the user requested to stop the walk or endRow/endColumn is + // inside of this fold (comp == 0), then end here. + if (stop || comp == 0) { + return; + } + + // Note the new lastEnd might not be on the same line. However, + // it's the callback's job to recognize this. + isNewRow = !fold.sameRow; + lastEnd = fold.end.column; + } + callback(null, endRow, endColumn, lastEnd, isNewRow); + } + + this.getNextFoldTo = function(row, column) { + var fold, cmp; + for (var i = 0; i < this.folds.length; i++) { + fold = this.folds[i]; + cmp = fold.range.compareEnd(row, column); + if (cmp == -1) { + return { + fold: fold, + kind: "after" + }; + } else if (cmp == 0) { + return { + fold: fold, + kind: "inside" + } + } + } + return null; + } + + this.addRemoveChars = function(row, column, len) { + var ret = this.getNextFoldTo(row, column), + fold, folds; + if (ret) { + fold = ret.fold; + if (ret.kind == "inside" + && fold.start.column != column + && fold.start.row != row) + { + //throwing here breaks whole editor + //@todo properly handle this + window.console && window.console.log(row, column, fold); + } else if (fold.start.row == row) { + folds = this.folds; + var i = folds.indexOf(fold); + if (i == 0) { + this.start.column += len; + } + for (i; i < folds.length; i++) { + fold = folds[i]; + fold.start.column += len; + if (!fold.sameRow) { + return; + } + fold.end.column += len; + } + this.end.column += len; + } + } + } + + this.split = function(row, column) { + var fold = this.getNextFoldTo(row, column).fold, + folds = this.folds; + var foldData = this.foldData; + + if (!fold) { + return null; + } + var i = folds.indexOf(fold); + var foldBefore = folds[i - 1]; + this.end.row = foldBefore.end.row; + this.end.column = foldBefore.end.column; + + // Remove the folds after row/column and create a new FoldLine + // containing these removed folds. + folds = folds.splice(i, folds.length - i); + + var newFoldLine = new FoldLine(foldData, folds); + foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine); + return newFoldLine; + } + + this.merge = function(foldLineNext) { + var folds = foldLineNext.folds; + for (var i = 0; i < folds.length; i++) { + this.addFold(folds[i]); + } + // Remove the foldLineNext - no longer needed, as + // it's merged now with foldLineNext. + var foldData = this.foldData; + foldData.splice(foldData.indexOf(foldLineNext), 1); + } + + this.toString = function() { + var ret = [this.range.toString() + ": [" ]; + + this.folds.forEach(function(fold) { + ret.push(" " + fold.toString()); + }); + ret.push("]") + return ret.join("\n"); + } + + this.idxToPosition = function(idx) { + var lastFoldEndColumn = 0; + var fold; + + for (var i = 0; i < this.folds.length; i++) { + var fold = this.folds[i]; + + idx -= fold.start.column - lastFoldEndColumn; + if (idx < 0) { + return { + row: fold.start.row, + column: fold.start.column + idx + }; + } + + idx -= fold.placeholder.length; + if (idx < 0) { + return fold.start; + } + + lastFoldEndColumn = fold.end.column; + } + + return { + row: this.end.row, + column: this.end.column + idx + }; + } +}).call(FoldLine.prototype); + +exports.FoldLine = FoldLine; +}); + +ace.define('ace/edit_session/fold', ['require', 'exports', 'module' ], function(require, exports, module) { + + +/* + * Simple fold-data struct. + **/ +var Fold = exports.Fold = function(range, placeholder) { + this.foldLine = null; + this.placeholder = placeholder; + this.range = range; + this.start = range.start; + this.end = range.end; + + this.sameRow = range.start.row == range.end.row; + this.subFolds = []; +}; + +(function() { + + this.toString = function() { + return '"' + this.placeholder + '" ' + this.range.toString(); + }; + + this.setFoldLine = function(foldLine) { + this.foldLine = foldLine; + this.subFolds.forEach(function(fold) { + fold.setFoldLine(foldLine); + }); + }; + + this.clone = function() { + var range = this.range.clone(); + var fold = new Fold(range, this.placeholder); + this.subFolds.forEach(function(subFold) { + fold.subFolds.push(subFold.clone()); + }); + return fold; + }; + + this.addSubFold = function(fold) { + if (this.range.isEqual(fold)) + return this; + + if (!this.range.containsRange(fold)) + throw "A fold can't intersect already existing fold" + fold.range + this.range; + + var row = fold.range.start.row, column = fold.range.start.column; + for (var i = 0, cmp = -1; i < this.subFolds.length; i++) { + cmp = this.subFolds[i].range.compare(row, column); + if (cmp != 1) + break; + } + var afterStart = this.subFolds[i]; + + if (cmp == 0) + return afterStart.addSubFold(fold); + + // cmp == -1 + var row = fold.range.end.row, column = fold.range.end.column; + for (var j = i, cmp = -1; j < this.subFolds.length; j++) { + cmp = this.subFolds[j].range.compare(row, column); + if (cmp != 1) + break; + } + var afterEnd = this.subFolds[j]; + + if (cmp == 0) + throw "A fold can't intersect already existing fold" + fold.range + this.range; + + var consumedFolds = this.subFolds.splice(i, j - i, fold); + fold.setFoldLine(this.foldLine); + + return fold; + }; + +}).call(Fold.prototype); + +}); + +ace.define('ace/token_iterator', ['require', 'exports', 'module' ], function(require, exports, module) { + + +/** + * class TokenIterator + * + * This class provides an essay way to treat the document as a stream of tokens, and provides methods to iterate over these tokens. + * + **/ + +/** + * new TokenIterator(session, initialRow, initialColumn) + * - session (EditSession): The session to associate with + * - initialRow (Number): The row to start the tokenizing at + * - initialColumn (Number): The column to start the tokenizing at + * + * Creates a new token iterator object. The inital token index is set to the provided row and column coordinates. + * + **/ +var TokenIterator = function(session, initialRow, initialColumn) { + this.$session = session; + this.$row = initialRow; + this.$rowTokens = session.getTokens(initialRow); + + var token = session.getTokenAt(initialRow, initialColumn); + this.$tokenIndex = token ? token.index : -1; +}; + +(function() { + + /** + * TokenIterator.stepBackward() -> [String] + * + (String): If the current point is not at the top of the file, this function returns `null`. Otherwise, it returns an array of the tokenized strings. + * + * Tokenizes all the items from the current point to the row prior in the document. + **/ + this.stepBackward = function() { + this.$tokenIndex -= 1; + + while (this.$tokenIndex < 0) { + this.$row -= 1; + if (this.$row < 0) { + this.$row = 0; + return null; + } + + this.$rowTokens = this.$session.getTokens(this.$row); + this.$tokenIndex = this.$rowTokens.length - 1; + } + + return this.$rowTokens[this.$tokenIndex]; + }; + this.stepForward = function() { + var rowCount = this.$session.getLength(); + this.$tokenIndex += 1; + + while (this.$tokenIndex >= this.$rowTokens.length) { + this.$row += 1; + if (this.$row >= rowCount) { + this.$row = rowCount - 1; + return null; + } + + this.$rowTokens = this.$session.getTokens(this.$row); + this.$tokenIndex = 0; + } + + return this.$rowTokens[this.$tokenIndex]; + }; + this.getCurrentToken = function () { + return this.$rowTokens[this.$tokenIndex]; + }; + this.getCurrentTokenRow = function () { + return this.$row; + }; + this.getCurrentTokenColumn = function() { + var rowTokens = this.$rowTokens; + var tokenIndex = this.$tokenIndex; + + // If a column was cached by EditSession.getTokenAt, then use it + var column = rowTokens[tokenIndex].start; + if (column !== undefined) + return column; + + column = 0; + while (tokenIndex > 0) { + tokenIndex -= 1; + column += rowTokens[tokenIndex].value.length; + } + + return column; + }; + +}).call(TokenIterator.prototype); + +exports.TokenIterator = TokenIterator; +}); + +ace.define('ace/edit_session/bracket_match', ['require', 'exports', 'module' , 'ace/token_iterator', 'ace/range'], function(require, exports, module) { + + +var TokenIterator = require("../token_iterator").TokenIterator; +var Range = require("../range").Range; + + +function BracketMatch() { + + this.findMatchingBracket = function(position) { + if (position.column == 0) return null; + + var charBeforeCursor = this.getLine(position.row).charAt(position.column-1); + if (charBeforeCursor == "") return null; + + var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/); + if (!match) + return null; + + if (match[1]) + return this.$findClosingBracket(match[1], position); + else + return this.$findOpeningBracket(match[2], position); + }; + + this.getBracketRange = function(pos) { + var line = this.getLine(pos.row); + var before = true, range; + + var chr = line.charAt(pos.column-1); + var match = chr && chr.match(/([\(\[\{])|([\)\]\}])/); + if (!match) { + chr = line.charAt(pos.column); + pos = {row: pos.row, column: pos.column + 1}; + match = chr && chr.match(/([\(\[\{])|([\)\]\}])/); + before = false; + } + if (!match) + return null; + + if (match[1]) { + var bracketPos = this.$findClosingBracket(match[1], pos); + if (!bracketPos) + return null; + range = Range.fromPoints(pos, bracketPos); + if (!before) { + range.end.column++; + range.start.column--; + } + range.cursor = range.end; + } else { + var bracketPos = this.$findOpeningBracket(match[2], pos); + if (!bracketPos) + return null; + range = Range.fromPoints(bracketPos, pos); + if (!before) { + range.start.column++; + range.end.column--; + } + range.cursor = range.start; + } + + return range; + }; + + this.$brackets = { + ")": "(", + "(": ")", + "]": "[", + "[": "]", + "{": "}", + "}": "{" + }; + + this.$findOpeningBracket = function(bracket, position, typeRe) { + var openBracket = this.$brackets[bracket]; + var depth = 1; + + var iterator = new TokenIterator(this, position.row, position.column); + var token = iterator.getCurrentToken(); + if (!token) + token = iterator.stepForward(); + if (!token) + return; + + if (!typeRe){ + typeRe = new RegExp( + "(\\.?" + + token.type.replace(".", "\\.").replace("rparen", ".paren") + + ")+" + ); + } + + // Start searching in token, just before the character at position.column + var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2; + var value = token.value; + + while (true) { + + while (valueIndex >= 0) { + var chr = value.charAt(valueIndex); + if (chr == openBracket) { + depth -= 1; + if (depth == 0) { + return {row: iterator.getCurrentTokenRow(), + column: valueIndex + iterator.getCurrentTokenColumn()}; + } + } + else if (chr == bracket) { + depth += 1; + } + valueIndex -= 1; + } + + // Scan backward through the document, looking for the next token + // whose type matches typeRe + do { + token = iterator.stepBackward(); + } while (token && !typeRe.test(token.type)); + + if (token == null) + break; + + value = token.value; + valueIndex = value.length - 1; + } + + return null; + }; + + this.$findClosingBracket = function(bracket, position, typeRe) { + var closingBracket = this.$brackets[bracket]; + var depth = 1; + + var iterator = new TokenIterator(this, position.row, position.column); + var token = iterator.getCurrentToken(); + if (!token) + token = iterator.stepForward(); + if (!token) + return; + + if (!typeRe){ + typeRe = new RegExp( + "(\\.?" + + token.type.replace(".", "\\.").replace("lparen", ".paren") + + ")+" + ); + } + + // Start searching in token, after the character at position.column + var valueIndex = position.column - iterator.getCurrentTokenColumn(); + + while (true) { + + var value = token.value; + var valueLength = value.length; + while (valueIndex < valueLength) { + var chr = value.charAt(valueIndex); + if (chr == closingBracket) { + depth -= 1; + if (depth == 0) { + return {row: iterator.getCurrentTokenRow(), + column: valueIndex + iterator.getCurrentTokenColumn()}; + } + } + else if (chr == bracket) { + depth += 1; + } + valueIndex += 1; + } + + // Scan forward through the document, looking for the next token + // whose type matches typeRe + do { + token = iterator.stepForward(); + } while (token && !typeRe.test(token.type)); + + if (token == null) + break; + + valueIndex = 0; + } + + return null; + }; +} +exports.BracketMatch = BracketMatch; + +}); + +ace.define('ace/search', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/lib/oop', 'ace/range'], function(require, exports, module) { + + +var lang = require("./lib/lang"); +var oop = require("./lib/oop"); +var Range = require("./range").Range; + +/** + * new Search() + * + * Creates a new `Search` object. The following search options are avaliable: + * + * * `needle`: The string or regular expression you're looking for + * * `backwards`: Whether to search backwards from where cursor currently is. Defaults to `false`. + * * `wrap`: Whether to wrap the search back to the beginning when it hits the end. Defaults to `false`. + * * `caseSensitive`: Whether the search ought to be case-sensitive. Defaults to `false`. + * * `wholeWord`: Whether the search matches only on whole words. Defaults to `false`. + * * `range`: The [[Range]] to search within. Set this to `null` for the whole document + * * `regExp`: Whether the search is a regular expression or not. Defaults to `false`. + * * `start`: The starting [[Range]] or cursor position to begin the search + * * `skipCurrent`: Whether or not to include the current line in the search. Default to `false`. + * +**/ + +var Search = function() { + this.$options = {}; +}; + +(function() { + /** + * Search.set(options) -> Search + * - options (Object): An object containing all the new search properties + * + * Sets the search options via the `options` parameter. + * + **/ + this.set = function(options) { + oop.mixin(this.$options, options); + return this; + }; + this.getOptions = function() { + return lang.copyObject(this.$options); + }; + + this.setOptions = function(options) { + this.$options = options; + }; + this.find = function(session) { + var iterator = this.$matchIterator(session, this.$options); + + if (!iterator) + return false; + + var firstRange = null; + iterator.forEach(function(range, row, offset) { + if (!range.start) { + var column = range.offset + (offset || 0); + firstRange = new Range(row, column, row, column+range.length); + } else + firstRange = range; + return true; + }); + + return firstRange; + }; + this.findAll = function(session) { + var options = this.$options; + if (!options.needle) + return []; + this.$assembleRegExp(options); + + var range = options.range; + var lines = range + ? session.getLines(range.start.row, range.end.row) + : session.doc.getAllLines(); + + var ranges = []; + var re = options.re; + if (options.$isMultiLine) { + var len = re.length; + var maxRow = lines.length - len; + for (var row = re.offset || 0; row <= maxRow; row++) { + for (var j = 0; j < len; j++) + if (lines[row + j].search(re[j]) == -1) + break; + + var startLine = lines[row]; + var line = lines[row + len - 1]; + var startIndex = startLine.match(re[0])[0].length; + var endIndex = line.match(re[len - 1])[0].length; + + ranges.push(new Range( + row, startLine.length - startIndex, + row + len - 1, endIndex + )); + } + } else { + for (var i = 0; i < lines.length; i++) { + var matches = lang.getMatchOffsets(lines[i], re); + for (var j = 0; j < matches.length; j++) { + var match = matches[j]; + ranges.push(new Range(i, match.offset, i, match.offset + match.length)); + } + } + } + + if (range) { + var startColumn = range.start.column; + var endColumn = range.start.column; + var i = 0, j = ranges.length - 1; + while (i < j && ranges[i].start.column < startColumn && ranges[i].start.row == range.start.row) + i++; + + while (i < j && ranges[j].end.column > endColumn && ranges[j].end.row == range.end.row) + j--; + return ranges.slice(i, j + 1); + } + + return ranges; + }; + this.replace = function(input, replacement) { + var options = this.$options; + + var re = this.$assembleRegExp(options); + if (options.$isMultiLine) + return replacement; + + if (!re) + return; + + var match = re.exec(input); + if (!match || match[0].length != input.length) + return null; + + replacement = input.replace(re, replacement); + if (options.preserveCase) { + replacement = replacement.split(""); + for (var i = Math.min(input.length, input.length); i--; ) { + var ch = input[i]; + if (ch && ch.toLowerCase() != ch) + replacement[i] = replacement[i].toUpperCase(); + else + replacement[i] = replacement[i].toLowerCase(); + } + replacement = replacement.join(""); + } + + return replacement; + }; + this.$matchIterator = function(session, options) { + var re = this.$assembleRegExp(options); + if (!re) + return false; + + var self = this, callback, backwards = options.backwards; + + if (options.$isMultiLine) { + var len = re.length; + var matchIterator = function(line, row, offset) { + var startIndex = line.search(re[0]); + if (startIndex == -1) + return; + for (var i = 1; i < len; i++) { + line = session.getLine(row + i); + if (line.search(re[i]) == -1) + return; + } + + var endIndex = line.match(re[len - 1])[0].length; + + var range = new Range(row, startIndex, row + len - 1, endIndex); + if (re.offset == 1) { + range.start.row--; + range.start.column = Number.MAX_VALUE; + } else if (offset) + range.start.column += offset; + + if (callback(range)) + return true; + }; + } else if (backwards) { + var matchIterator = function(line, row, startIndex) { + var matches = lang.getMatchOffsets(line, re); + for (var i = matches.length-1; i >= 0; i--) + if (callback(matches[i], row, startIndex)) + return true; + }; + } else { + var matchIterator = function(line, row, startIndex) { + var matches = lang.getMatchOffsets(line, re); + for (var i = 0; i < matches.length; i++) + if (callback(matches[i], row, startIndex)) + return true; + }; + } + + return { + forEach: function(_callback) { + callback = _callback; + self.$lineIterator(session, options).forEach(matchIterator); + } + }; + }; + + this.$assembleRegExp = function(options) { + if (options.needle instanceof RegExp) + return options.re = options.needle; + + var needle = options.needle; + + if (!options.needle) + return options.re = false; + + if (!options.regExp) + needle = lang.escapeRegExp(needle); + + if (options.wholeWord) + needle = "\\b" + needle + "\\b"; + + var modifier = options.caseSensitive ? "g" : "gi"; + + options.$isMultiLine = /[\n\r]/.test(needle); + if (options.$isMultiLine) + return options.re = this.$assembleMultilineRegExp(needle, modifier); + + try { + var re = new RegExp(needle, modifier); + } catch(e) { + re = false; + } + return options.re = re; + }; + + this.$assembleMultilineRegExp = function(needle, modifier) { + var parts = needle.replace(/\r\n|\r|\n/g, "$\n^").split("\n"); + var re = []; + for (var i = 0; i < parts.length; i++) try { + re.push(new RegExp(parts[i], modifier)); + } catch(e) { + return false; + } + if (parts[0] == "") { + re.shift(); + re.offset = 1; + } else { + re.offset = 0; + } + return re; + }; + + this.$lineIterator = function(session, options) { + var backwards = options.backwards == true; + var skipCurrent = options.skipCurrent != false; + + var range = options.range; + var start = options.start; + if (!start) + start = range ? range[backwards ? "end" : "start"] : session.selection.getRange(); + + if (start.start) + start = start[skipCurrent != backwards ? "end" : "start"]; + + var firstRow = range ? range.start.row : 0; + var lastRow = range ? range.end.row : session.getLength() - 1; + + var forEach = backwards ? function(callback) { + var row = start.row; + + var line = session.getLine(row).substring(0, start.column); + if (callback(line, row)) + return; + + for (row--; row >= firstRow; row--) + if (callback(session.getLine(row), row)) + return; + + if (options.wrap == false) + return; + + for (row = lastRow, firstRow = start.row; row >= firstRow; row--) + if (callback(session.getLine(row), row)) + return; + } : function(callback) { + var row = start.row; + + var line = session.getLine(row).substr(start.column); + if (callback(line, row, start.column)) + return; + + for (row = row+1; row <= lastRow; row++) + if (callback(session.getLine(row), row)) + return; + + if (options.wrap == false) + return; + + for (row = firstRow, lastRow = start.row; row <= lastRow; row++) + if (callback(session.getLine(row), row)) + return; + }; + + return {forEach: forEach}; + }; + +}).call(Search.prototype); + +exports.Search = Search; +}); +ace.define('ace/commands/command_manager', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/keyboard/hash_handler', 'ace/lib/event_emitter'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var HashHandler = require("../keyboard/hash_handler").HashHandler; +var EventEmitter = require("../lib/event_emitter").EventEmitter; + +/** + * new CommandManager(platform, commands) + * - platform (String): Identifier for the platform; must be either `'mac'` or `'win'` + * - commands (Array): A list of commands + * + * TODO + * + * + **/ + +var CommandManager = function(platform, commands) { + this.platform = platform; + this.commands = {}; + this.commmandKeyBinding = {}; + + this.addCommands(commands); + + this.setDefaultHandler("exec", function(e) { + return e.command.exec(e.editor, e.args || {}); + }); +}; + +oop.inherits(CommandManager, HashHandler); + +(function() { + + oop.implement(this, EventEmitter); + + this.exec = function(command, editor, args) { + if (typeof command === 'string') + command = this.commands[command]; + + if (!command) + return false; + + if (editor && editor.$readOnly && !command.readOnly) + return false; + + var retvalue = this._emit("exec", { + editor: editor, + command: command, + args: args + }); + + return retvalue === false ? false : true; + }; + + this.toggleRecording = function(editor) { + if (this.$inReplay) + return; + + editor && editor._emit("changeStatus"); + if (this.recording) { + this.macro.pop(); + this.removeEventListener("exec", this.$addCommandToMacro); + + if (!this.macro.length) + this.macro = this.oldMacro; + + return this.recording = false; + } + if (!this.$addCommandToMacro) { + this.$addCommandToMacro = function(e) { + this.macro.push([e.command, e.args]); + }.bind(this); + } + + this.oldMacro = this.macro; + this.macro = []; + this.on("exec", this.$addCommandToMacro); + return this.recording = true; + }; + + this.replay = function(editor) { + if (this.$inReplay || !this.macro) + return; + + if (this.recording) + return this.toggleRecording(editor); + + try { + this.$inReplay = true; + this.macro.forEach(function(x) { + if (typeof x == "string") + this.exec(x, editor); + else + this.exec(x[0], editor, x[1]); + }, this); + } finally { + this.$inReplay = false; + } + }; + + this.trimMacro = function(m) { + return m.map(function(x){ + if (typeof x[0] != "string") + x[0] = x[0].name; + if (!x[1]) + x = x[0]; + return x; + }); + }; + +}).call(CommandManager.prototype); + +exports.CommandManager = CommandManager; + +}); + +ace.define('ace/keyboard/hash_handler', ['require', 'exports', 'module' , 'ace/lib/keys'], function(require, exports, module) { + + +var keyUtil = require("../lib/keys"); + +function HashHandler(config, platform) { + this.platform = platform; + this.commands = {}; + this.commmandKeyBinding = {}; + + this.addCommands(config); +}; + +(function() { + + this.addCommand = function(command) { + if (this.commands[command.name]) + this.removeCommand(command); + + this.commands[command.name] = command; + + if (command.bindKey) + this._buildKeyHash(command); + }; + + this.removeCommand = function(command) { + var name = (typeof command === 'string' ? command : command.name); + command = this.commands[name]; + delete this.commands[name]; + + // exhaustive search is brute force but since removeCommand is + // not a performance critical operation this should be OK + var ckb = this.commmandKeyBinding; + for (var hashId in ckb) { + for (var key in ckb[hashId]) { + if (ckb[hashId][key] == command) + delete ckb[hashId][key]; + } + } + }; + + this.bindKey = function(key, command) { + if(!key) + return; + if (typeof command == "function") { + this.addCommand({exec: command, bindKey: key, name: key}); + return; + } + + var ckb = this.commmandKeyBinding; + key.split("|").forEach(function(keyPart) { + var binding = this.parseKeys(keyPart, command); + var hashId = binding.hashId; + (ckb[hashId] || (ckb[hashId] = {}))[binding.key] = command; + }, this); + }; + + this.addCommands = function(commands) { + commands && Object.keys(commands).forEach(function(name) { + var command = commands[name]; + if (typeof command === "string") + return this.bindKey(command, name); + + if (typeof command === "function") + command = { exec: command }; + + if (!command.name) + command.name = name; + + this.addCommand(command); + }, this); + }; + + this.removeCommands = function(commands) { + Object.keys(commands).forEach(function(name) { + this.removeCommand(commands[name]); + }, this); + }; + + this.bindKeys = function(keyList) { + Object.keys(keyList).forEach(function(key) { + this.bindKey(key, keyList[key]); + }, this); + }; + + this._buildKeyHash = function(command) { + var binding = command.bindKey; + if (!binding) + return; + + var key = typeof binding == "string" ? binding: binding[this.platform]; + this.bindKey(key, command); + }; + + this.parseKeys = function(keys) { + var key; + var hashId = 0; + var parts = keys.toLowerCase().trim().split(/\s*\-\s*/); + + for (var i = 0, l = parts.length; i < l; i++) { + if (keyUtil.KEY_MODS[parts[i]]) + hashId = hashId | keyUtil.KEY_MODS[parts[i]]; + else + key = parts[i] || "-"; //when empty, the splitSafe removed a '-' + } + + if (parts[0] == "text" && parts.length == 2) { + hashId = -1; + key = parts[1]; + } + + return { + key: key, + hashId: hashId + }; + }; + + this.findKeyCommand = function findKeyCommand(hashId, keyString) { + var ckbr = this.commmandKeyBinding; + return ckbr[hashId] && ckbr[hashId][keyString.toLowerCase()]; + }; + + this.handleKeyboard = function(data, hashId, keyString, keyCode) { + return { + command: this.findKeyCommand(hashId, keyString) + }; + }; + +}).call(HashHandler.prototype) + +exports.HashHandler = HashHandler; +}); + +ace.define('ace/commands/default_commands', ['require', 'exports', 'module' , 'ace/lib/lang'], function(require, exports, module) { + + +var lang = require("../lib/lang"); + +function bindKey(win, mac) { + return { + win: win, + mac: mac + }; +} + +exports.commands = [{ + name: "selectall", + bindKey: bindKey("Ctrl-A", "Command-A"), + exec: function(editor) { editor.selectAll(); }, + readOnly: true +}, { + name: "centerselection", + bindKey: bindKey(null, "Ctrl-L"), + exec: function(editor) { editor.centerSelection(); }, + readOnly: true +}, { + name: "gotoline", + bindKey: bindKey("Ctrl-L", "Command-L"), + exec: function(editor) { + var line = parseInt(prompt("Enter line number:"), 10); + if (!isNaN(line)) { + editor.gotoLine(line); + } + }, + readOnly: true +}, { + name: "fold", + bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"), + exec: function(editor) { editor.session.toggleFold(false); }, + readOnly: true +}, { + name: "unfold", + bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"), + exec: function(editor) { editor.session.toggleFold(true); }, + readOnly: true +}, { + name: "foldall", + bindKey: bindKey("Alt-0", "Command-Option-0"), + exec: function(editor) { editor.session.foldAll(); }, + readOnly: true +}, { + name: "unfoldall", + bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"), + exec: function(editor) { editor.session.unfold(); }, + readOnly: true +}, { + name: "findnext", + bindKey: bindKey("Ctrl-K", "Command-G"), + exec: function(editor) { editor.findNext(); }, + readOnly: true +}, { + name: "findprevious", + bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"), + exec: function(editor) { editor.findPrevious(); }, + readOnly: true +}, { + name: "find", + bindKey: bindKey("Ctrl-F", "Command-F"), + exec: function(editor) { + var needle = prompt("Find:", editor.getCopyText()); + editor.find(needle); + }, + readOnly: true +}, { + name: "overwrite", + bindKey: "Insert", + exec: function(editor) { editor.toggleOverwrite(); }, + readOnly: true +}, { + name: "selecttostart", + bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Up"), + exec: function(editor) { editor.getSelection().selectFileStart(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "gotostart", + bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"), + exec: function(editor) { editor.navigateFileStart(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selectup", + bindKey: bindKey("Shift-Up", "Shift-Up"), + exec: function(editor) { editor.getSelection().selectUp(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "golineup", + bindKey: bindKey("Up", "Up|Ctrl-P"), + exec: function(editor, args) { editor.navigateUp(args.times); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selecttoend", + bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-Down"), + exec: function(editor) { editor.getSelection().selectFileEnd(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "gotoend", + bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"), + exec: function(editor) { editor.navigateFileEnd(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selectdown", + bindKey: bindKey("Shift-Down", "Shift-Down"), + exec: function(editor) { editor.getSelection().selectDown(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "golinedown", + bindKey: bindKey("Down", "Down|Ctrl-N"), + exec: function(editor, args) { editor.navigateDown(args.times); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selectwordleft", + bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"), + exec: function(editor) { editor.getSelection().selectWordLeft(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "gotowordleft", + bindKey: bindKey("Ctrl-Left", "Option-Left"), + exec: function(editor) { editor.navigateWordLeft(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selecttolinestart", + bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"), + exec: function(editor) { editor.getSelection().selectLineStart(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "gotolinestart", + bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"), + exec: function(editor) { editor.navigateLineStart(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selectleft", + bindKey: bindKey("Shift-Left", "Shift-Left"), + exec: function(editor) { editor.getSelection().selectLeft(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "gotoleft", + bindKey: bindKey("Left", "Left|Ctrl-B"), + exec: function(editor, args) { editor.navigateLeft(args.times); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selectwordright", + bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"), + exec: function(editor) { editor.getSelection().selectWordRight(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "gotowordright", + bindKey: bindKey("Ctrl-Right", "Option-Right"), + exec: function(editor) { editor.navigateWordRight(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selecttolineend", + bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"), + exec: function(editor) { editor.getSelection().selectLineEnd(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "gotolineend", + bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"), + exec: function(editor) { editor.navigateLineEnd(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selectright", + bindKey: bindKey("Shift-Right", "Shift-Right"), + exec: function(editor) { editor.getSelection().selectRight(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "gotoright", + bindKey: bindKey("Right", "Right|Ctrl-F"), + exec: function(editor, args) { editor.navigateRight(args.times); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selectpagedown", + bindKey: "Shift-PageDown", + exec: function(editor) { editor.selectPageDown(); }, + readOnly: true +}, { + name: "pagedown", + bindKey: bindKey(null, "Option-PageDown"), + exec: function(editor) { editor.scrollPageDown(); }, + readOnly: true +}, { + name: "gotopagedown", + bindKey: bindKey("PageDown", "PageDown|Ctrl-V"), + exec: function(editor) { editor.gotoPageDown(); }, + readOnly: true +}, { + name: "selectpageup", + bindKey: "Shift-PageUp", + exec: function(editor) { editor.selectPageUp(); }, + readOnly: true +}, { + name: "pageup", + bindKey: bindKey(null, "Option-PageUp"), + exec: function(editor) { editor.scrollPageUp(); }, + readOnly: true +}, { + name: "gotopageup", + bindKey: "PageUp", + exec: function(editor) { editor.gotoPageUp(); }, + readOnly: true +}, { + name: "scrollup", + bindKey: bindKey("Ctrl-Up", null), + exec: function(e) { e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); }, + readOnly: true +}, { + name: "scrolldown", + bindKey: bindKey("Ctrl-Down", null), + exec: function(e) { e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); }, + readOnly: true +}, { + name: "selectlinestart", + bindKey: "Shift-Home", + exec: function(editor) { editor.getSelection().selectLineStart(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selectlineend", + bindKey: "Shift-End", + exec: function(editor) { editor.getSelection().selectLineEnd(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "togglerecording", + bindKey: bindKey("Ctrl-Alt-E", "Command-Option-E"), + exec: function(editor) { editor.commands.toggleRecording(editor); }, + readOnly: true +}, { + name: "replaymacro", + bindKey: bindKey("Ctrl-Shift-E", "Command-Shift-E"), + exec: function(editor) { editor.commands.replay(editor); }, + readOnly: true +}, { + name: "jumptomatching", + bindKey: bindKey("Ctrl-P", "Ctrl-Shift-P"), + exec: function(editor) { editor.jumpToMatching(); }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "selecttomatching", + bindKey: bindKey("Ctrl-Shift-P", null), + exec: function(editor) { editor.jumpToMatching(true); }, + readOnly: true +}, + +// commands disabled in readOnly mode +{ + name: "cut", + exec: function(editor) { + var range = editor.getSelectionRange(); + editor._emit("cut", range); + + if (!editor.selection.isEmpty()) { + editor.session.remove(range); + editor.clearSelection(); + } + }, + multiSelectAction: "forEach" +}, { + name: "removeline", + bindKey: bindKey("Ctrl-D", "Command-D"), + exec: function(editor) { editor.removeLines(); }, + multiSelectAction: "forEach" +}, { + name: "duplicateSelection", + bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"), + exec: function(editor) { editor.duplicateSelection(); }, + multiSelectAction: "forEach" +}, { + name: "togglecomment", + bindKey: bindKey("Ctrl-/", "Command-/"), + exec: function(editor) { editor.toggleCommentLines(); }, + multiSelectAction: "forEach" +}, { + name: "replace", + bindKey: bindKey("Ctrl-R", "Command-Option-F"), + exec: function(editor) { + var needle = prompt("Find:", editor.getCopyText()); + if (!needle) + return; + var replacement = prompt("Replacement:"); + if (!replacement) + return; + editor.replace(replacement, {needle: needle}); + } +}, { + name: "replaceall", + bindKey: bindKey("Ctrl-Shift-R", "Command-Shift-Option-F"), + exec: function(editor) { + var needle = prompt("Find:"); + if (!needle) + return; + var replacement = prompt("Replacement:"); + if (!replacement) + return; + editor.replaceAll(replacement, {needle: needle}); + } +}, { + name: "undo", + bindKey: bindKey("Ctrl-Z", "Command-Z"), + exec: function(editor) { editor.undo(); } +}, { + name: "redo", + bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"), + exec: function(editor) { editor.redo(); } +}, { + name: "copylinesup", + bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"), + exec: function(editor) { editor.copyLinesUp(); } +}, { + name: "movelinesup", + bindKey: bindKey("Alt-Up", "Option-Up"), + exec: function(editor) { editor.moveLinesUp(); } +}, { + name: "copylinesdown", + bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"), + exec: function(editor) { editor.copyLinesDown(); } +}, { + name: "movelinesdown", + bindKey: bindKey("Alt-Down", "Option-Down"), + exec: function(editor) { editor.moveLinesDown(); } +}, { + name: "del", + bindKey: bindKey("Delete", "Delete|Ctrl-D"), + exec: function(editor) { editor.remove("right"); }, + multiSelectAction: "forEach" +}, { + name: "backspace", + bindKey: bindKey( + "Command-Backspace|Option-Backspace|Shift-Backspace|Backspace", + "Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H" + ), + exec: function(editor) { editor.remove("left"); }, + multiSelectAction: "forEach" +}, { + name: "removetolinestart", + bindKey: bindKey("Alt-Backspace", "Command-Backspace"), + exec: function(editor) { editor.removeToLineStart(); }, + multiSelectAction: "forEach" +}, { + name: "removetolineend", + bindKey: bindKey("Alt-Delete", "Ctrl-K"), + exec: function(editor) { editor.removeToLineEnd(); }, + multiSelectAction: "forEach" +}, { + name: "removewordleft", + bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"), + exec: function(editor) { editor.removeWordLeft(); }, + multiSelectAction: "forEach" +}, { + name: "removewordright", + bindKey: bindKey("Ctrl-Delete", "Alt-Delete"), + exec: function(editor) { editor.removeWordRight(); }, + multiSelectAction: "forEach" +}, { + name: "outdent", + bindKey: bindKey("Shift-Tab", "Shift-Tab"), + exec: function(editor) { editor.blockOutdent(); }, + multiSelectAction: "forEach" +}, { + name: "indent", + bindKey: bindKey("Tab", "Tab"), + exec: function(editor) { editor.indent(); }, + multiSelectAction: "forEach" +}, { + name: "insertstring", + exec: function(editor, str) { editor.insert(str); }, + multiSelectAction: "forEach" +}, { + name: "inserttext", + exec: function(editor, args) { + editor.insert(lang.stringRepeat(args.text || "", args.times || 1)); + }, + multiSelectAction: "forEach" +}, { + name: "splitline", + bindKey: bindKey(null, "Ctrl-O"), + exec: function(editor) { editor.splitLine(); }, + multiSelectAction: "forEach" +}, { + name: "transposeletters", + bindKey: bindKey("Ctrl-T", "Ctrl-T"), + exec: function(editor) { editor.transposeLetters(); }, + multiSelectAction: function(editor) {editor.transposeSelections(1); } +}, { + name: "touppercase", + bindKey: bindKey("Ctrl-U", "Ctrl-U"), + exec: function(editor) { editor.toUpperCase(); }, + multiSelectAction: "forEach" +}, { + name: "tolowercase", + bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"), + exec: function(editor) { editor.toLowerCase(); }, + multiSelectAction: "forEach" +}]; + +}); + +ace.define('ace/undomanager', ['require', 'exports', 'module' ], function(require, exports, module) { + + +/** + * class UndoManager + * + * This object maintains the undo stack for an [[EditSession `EditSession`]]. + * + **/ + +/** + * new UndoManager() + * + * Resets the current undo state and creates a new `UndoManager`. + **/ +var UndoManager = function() { + this.reset(); +}; + +(function() { + + /** + * UndoManager.execute(options) -> Void + * - options (Object): Contains additional properties + * + * Provides a means for implementing your own undo manager. `options` has one property, `args`, an [[Array `Array`]], with two elements: + * + * * `args[0]` is an array of deltas + * * `args[1]` is the document to associate with + * + **/ + this.execute = function(options) { + var deltas = options.args[0]; + this.$doc = options.args[1]; + this.$undoStack.push(deltas); + this.$redoStack = []; + }; + this.undo = function(dontSelect) { + var deltas = this.$undoStack.pop(); + var undoSelectionRange = null; + if (deltas) { + undoSelectionRange = + this.$doc.undoChanges(deltas, dontSelect); + this.$redoStack.push(deltas); + } + return undoSelectionRange; + }; + this.redo = function(dontSelect) { + var deltas = this.$redoStack.pop(); + var redoSelectionRange = null; + if (deltas) { + redoSelectionRange = + this.$doc.redoChanges(deltas, dontSelect); + this.$undoStack.push(deltas); + } + return redoSelectionRange; + }; + this.reset = function() { + this.$undoStack = []; + this.$redoStack = []; + }; + this.hasUndo = function() { + return this.$undoStack.length > 0; + }; + this.hasRedo = function() { + return this.$redoStack.length > 0; + }; + +}).call(UndoManager.prototype); + +exports.UndoManager = UndoManager; +}); + +ace.define('ace/virtual_renderer', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/event', 'ace/lib/useragent', 'ace/config', 'ace/lib/net', 'ace/layer/gutter', 'ace/layer/marker', 'ace/layer/text', 'ace/layer/cursor', 'ace/scrollbar', 'ace/renderloop', 'ace/lib/event_emitter', 'ace/requirejs/text!ace/css/editor.css'], function(require, exports, module) { + + +var oop = require("./lib/oop"); +var dom = require("./lib/dom"); +var event = require("./lib/event"); +var useragent = require("./lib/useragent"); +var config = require("./config"); +var net = require("./lib/net"); +var GutterLayer = require("./layer/gutter").Gutter; +var MarkerLayer = require("./layer/marker").Marker; +var TextLayer = require("./layer/text").Text; +var CursorLayer = require("./layer/cursor").Cursor; +var ScrollBar = require("./scrollbar").ScrollBar; +var RenderLoop = require("./renderloop").RenderLoop; +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var editorCss = require("ace/requirejs/text!./css/editor.css"); + +dom.importCssString(editorCss, "ace_editor"); + +/** + * new VirtualRenderer(container, theme) + * - container (DOMElement): The root element of the editor + * - theme (String): The starting theme + * + * Constructs a new `VirtualRenderer` within the `container` specified, applying the given `theme`. + * + **/ + +var VirtualRenderer = function(container, theme) { + var _self = this; + + this.container = container; + + // TODO: this breaks rendering in Cloud9 with multiple ace instances +// // Imports CSS once per DOM document ('ace_editor' serves as an identifier). +// dom.importCssString(editorCss, "ace_editor", container.ownerDocument); + + // in IE <= 9 the native cursor always shines through + this.$keepTextAreaAtCursor = !useragent.isIE; + + dom.addCssClass(container, "ace_editor"); + + this.setTheme(theme); + + this.$gutter = dom.createElement("div"); + this.$gutter.className = "ace_gutter"; + this.container.appendChild(this.$gutter); + + this.scroller = dom.createElement("div"); + this.scroller.className = "ace_scroller"; + this.container.appendChild(this.scroller); + + this.content = dom.createElement("div"); + this.content.className = "ace_content"; + this.scroller.appendChild(this.content); + + this.setHighlightGutterLine(true); + this.$gutterLayer = new GutterLayer(this.$gutter); + this.$gutterLayer.on("changeGutterWidth", this.onResize.bind(this, true)); + + this.$markerBack = new MarkerLayer(this.content); + + var textLayer = this.$textLayer = new TextLayer(this.content); + this.canvas = textLayer.element; + + this.$markerFront = new MarkerLayer(this.content); + + this.characterWidth = textLayer.getCharacterWidth(); + this.lineHeight = textLayer.getLineHeight(); + + this.$cursorLayer = new CursorLayer(this.content); + this.$cursorPadding = 8; + + // Indicates whether the horizontal scrollbar is visible + this.$horizScroll = false; + this.$horizScrollAlwaysVisible = false; + + this.$animatedScroll = false; + + this.scrollBar = new ScrollBar(container); + this.scrollBar.addEventListener("scroll", function(e) { + if (!_self.$inScrollAnimation) + _self.session.setScrollTop(e.data); + }); + + this.scrollTop = 0; + this.scrollLeft = 0; + + event.addListener(this.scroller, "scroll", function() { + var scrollLeft = _self.scroller.scrollLeft; + _self.scrollLeft = scrollLeft; + _self.session.setScrollLeft(scrollLeft); + }); + + this.cursorPos = { + row : 0, + column : 0 + }; + + this.$textLayer.addEventListener("changeCharacterSize", function() { + _self.characterWidth = textLayer.getCharacterWidth(); + _self.lineHeight = textLayer.getLineHeight(); + _self.$updatePrintMargin(); + _self.onResize(true); + + _self.$loop.schedule(_self.CHANGE_FULL); + }); + + this.$size = { + width: 0, + height: 0, + scrollerHeight: 0, + scrollerWidth: 0 + }; + + this.layerConfig = { + width : 1, + padding : 0, + firstRow : 0, + firstRowScreen: 0, + lastRow : 0, + lineHeight : 1, + characterWidth : 1, + minHeight : 1, + maxHeight : 1, + offset : 0, + height : 1 + }; + + this.$loop = new RenderLoop( + this.$renderChanges.bind(this), + this.container.ownerDocument.defaultView + ); + this.$loop.schedule(this.CHANGE_FULL); + + this.setPadding(4); + this.$updatePrintMargin(); +}; + +(function() { + this.showGutter = true; + + this.CHANGE_CURSOR = 1; + this.CHANGE_MARKER = 2; + this.CHANGE_GUTTER = 4; + this.CHANGE_SCROLL = 8; + this.CHANGE_LINES = 16; + this.CHANGE_TEXT = 32; + this.CHANGE_SIZE = 64; + this.CHANGE_MARKER_BACK = 128; + this.CHANGE_MARKER_FRONT = 256; + this.CHANGE_FULL = 512; + this.CHANGE_H_SCROLL = 1024; + + oop.implement(this, EventEmitter); + this.setSession = function(session) { + this.session = session; + + this.scroller.className = "ace_scroller"; + + this.$cursorLayer.setSession(session); + this.$markerBack.setSession(session); + this.$markerFront.setSession(session); + this.$gutterLayer.setSession(session); + this.$textLayer.setSession(session); + this.$loop.schedule(this.CHANGE_FULL); + + }; + this.updateLines = function(firstRow, lastRow) { + if (lastRow === undefined) + lastRow = Infinity; + + if (!this.$changedLines) { + this.$changedLines = { + firstRow: firstRow, + lastRow: lastRow + }; + } + else { + if (this.$changedLines.firstRow > firstRow) + this.$changedLines.firstRow = firstRow; + + if (this.$changedLines.lastRow < lastRow) + this.$changedLines.lastRow = lastRow; + } + + this.$loop.schedule(this.CHANGE_LINES); + }; + + this.onChangeTabSize = function() { + this.$loop.schedule(this.CHANGE_TEXT | this.CHANGE_MARKER); + this.$textLayer.onChangeTabSize(); + }; + this.updateText = function() { + this.$loop.schedule(this.CHANGE_TEXT); + }; + this.updateFull = function(force) { + if (force){ + this.$renderChanges(this.CHANGE_FULL, true); + } + else { + this.$loop.schedule(this.CHANGE_FULL); + } + }; + this.updateFontSize = function() { + this.$textLayer.checkForSizeChanges(); + }; + this.onResize = function(force, gutterWidth, width, height) { + var changes = this.CHANGE_SIZE; + var size = this.$size; + + if (this.resizing > 2) + return; + else if (this.resizing > 1) + this.resizing++; + else + this.resizing = force ? 1 : 0; + + if (!height) + height = dom.getInnerHeight(this.container); + if (force || size.height != height) { + size.height = height; + + this.scroller.style.height = height + "px"; + size.scrollerHeight = this.scroller.clientHeight; + this.scrollBar.setHeight(size.scrollerHeight); + + if (this.session) { + this.session.setScrollTop(this.getScrollTop()); + changes = changes | this.CHANGE_FULL; + } + } + + if (!width) + width = dom.getInnerWidth(this.container); + if (force || this.resizing > 1 || size.width != width) { + size.width = width; + + var gutterWidth = this.showGutter ? this.$gutter.offsetWidth : 0; + this.scroller.style.left = gutterWidth + "px"; + size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBar.getWidth()); + this.scroller.style.right = this.scrollBar.getWidth() + "px"; + + if (this.session.getUseWrapMode() && this.adjustWrapLimit() || force) + changes = changes | this.CHANGE_FULL; + } + + if (force) + this.$renderChanges(changes, true); + else + this.$loop.schedule(changes); + + if (force) + delete this.resizing; + }; + this.adjustWrapLimit = function() { + var availableWidth = this.$size.scrollerWidth - this.$padding * 2; + var limit = Math.floor(availableWidth / this.characterWidth); + return this.session.adjustWrapLimit(limit); + }; + this.setAnimatedScroll = function(shouldAnimate){ + this.$animatedScroll = shouldAnimate; + }; + this.getAnimatedScroll = function() { + return this.$animatedScroll; + }; + this.setShowInvisibles = function(showInvisibles) { + if (this.$textLayer.setShowInvisibles(showInvisibles)) + this.$loop.schedule(this.CHANGE_TEXT); + }; + this.getShowInvisibles = function() { + return this.$textLayer.showInvisibles; + }; + + this.getDisplayIndentGuides = function() { + return this.$textLayer.displayIndentGuides; + }; + + this.setDisplayIndentGuides = function(display) { + if (this.$textLayer.setDisplayIndentGuides(display)) + this.$loop.schedule(this.CHANGE_TEXT); + }; + + this.$showPrintMargin = true; + this.setShowPrintMargin = function(showPrintMargin) { + this.$showPrintMargin = showPrintMargin; + this.$updatePrintMargin(); + }; + this.getShowPrintMargin = function() { + return this.$showPrintMargin; + }; + + this.$printMarginColumn = 80; + this.setPrintMarginColumn = function(showPrintMargin) { + this.$printMarginColumn = showPrintMargin; + this.$updatePrintMargin(); + }; + this.getPrintMarginColumn = function() { + return this.$printMarginColumn; + }; + this.getShowGutter = function(){ + return this.showGutter; + }; + this.setShowGutter = function(show){ + if(this.showGutter === show) + return; + this.$gutter.style.display = show ? "block" : "none"; + this.showGutter = show; + this.onResize(true); + }; + + this.getFadeFoldWidgets = function(){ + return dom.hasCssClass(this.$gutter, "ace_fade-fold-widgets"); + }; + + this.setFadeFoldWidgets = function(show) { + if (show) + dom.addCssClass(this.$gutter, "ace_fade-fold-widgets"); + else + dom.removeCssClass(this.$gutter, "ace_fade-fold-widgets"); + }; + + this.$highlightGutterLine = false; + this.setHighlightGutterLine = function(shouldHighlight) { + if (this.$highlightGutterLine == shouldHighlight) + return; + this.$highlightGutterLine = shouldHighlight; + + if (!this.$gutterLineHighlight) { + this.$gutterLineHighlight = dom.createElement("div"); + this.$gutterLineHighlight.className = "ace_gutter_active_line"; + this.$gutter.appendChild(this.$gutterLineHighlight); + return; + } + + this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none"; + // if cursorlayer have never been updated there's nothing on screen to update + if (this.$cursorLayer.$pixelPos) + this.$updateGutterLineHighlight(); + }; + + this.getHighlightGutterLine = function() { + return this.$highlightGutterLine; + }; + + this.$updateGutterLineHighlight = function() { + this.$gutterLineHighlight.style.top = this.$cursorLayer.$pixelPos.top - this.layerConfig.offset + "px"; + this.$gutterLineHighlight.style.height = this.layerConfig.lineHeight + "px"; + }; + + this.$updatePrintMargin = function() { + var containerEl; + + if (!this.$showPrintMargin && !this.$printMarginEl) + return; + + if (!this.$printMarginEl) { + containerEl = dom.createElement("div"); + containerEl.className = "ace_print_margin_layer"; + this.$printMarginEl = dom.createElement("div"); + this.$printMarginEl.className = "ace_print_margin"; + containerEl.appendChild(this.$printMarginEl); + this.content.insertBefore(containerEl, this.$textLayer.element); + } + + var style = this.$printMarginEl.style; + style.left = ((this.characterWidth * this.$printMarginColumn) + this.$padding) + "px"; + style.visibility = this.$showPrintMargin ? "visible" : "hidden"; + }; + this.getContainerElement = function() { + return this.container; + }; + this.getMouseEventTarget = function() { + return this.content; + }; + this.getTextAreaContainer = function() { + return this.container; + }; + + // move text input over the cursor + // this is required for iOS and IME + this.$moveTextAreaToCursor = function() { + if (!this.$keepTextAreaAtCursor) + return; + + var posTop = this.$cursorLayer.$pixelPos.top; + var posLeft = this.$cursorLayer.$pixelPos.left; + posTop -= this.layerConfig.offset; + + if (posTop < 0 || posTop > this.layerConfig.height - this.lineHeight) + return; + + var w = this.characterWidth; + if (this.$composition) + w += this.textarea.scrollWidth; + posLeft -= this.scrollLeft; + if (posLeft > this.$size.scrollerWidth - w) + posLeft = this.$size.scrollerWidth - w; + + if (this.showGutter) + posLeft += this.$gutterLayer.gutterWidth; + + this.textarea.style.height = this.lineHeight + "px"; + this.textarea.style.width = w + "px"; + this.textarea.style.left = posLeft + "px"; + this.textarea.style.top = posTop - 1 + "px"; + }; + this.getFirstVisibleRow = function() { + return this.layerConfig.firstRow; + }; + this.getFirstFullyVisibleRow = function() { + return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1); + }; + this.getLastFullyVisibleRow = function() { + var flint = Math.floor((this.layerConfig.height + this.layerConfig.offset) / this.layerConfig.lineHeight); + return this.layerConfig.firstRow - 1 + flint; + }; + this.getLastVisibleRow = function() { + return this.layerConfig.lastRow; + }; + + this.$padding = null; + this.setPadding = function(padding) { + this.$padding = padding; + this.$textLayer.setPadding(padding); + this.$cursorLayer.setPadding(padding); + this.$markerFront.setPadding(padding); + this.$markerBack.setPadding(padding); + this.$loop.schedule(this.CHANGE_FULL); + this.$updatePrintMargin(); + }; + this.getHScrollBarAlwaysVisible = function() { + return this.$horizScrollAlwaysVisible; + }; + this.setHScrollBarAlwaysVisible = function(alwaysVisible) { + if (this.$horizScrollAlwaysVisible != alwaysVisible) { + this.$horizScrollAlwaysVisible = alwaysVisible; + if (!this.$horizScrollAlwaysVisible || !this.$horizScroll) + this.$loop.schedule(this.CHANGE_SCROLL); + } + }; + + this.$updateScrollBar = function() { + this.scrollBar.setInnerHeight(this.layerConfig.maxHeight); + this.scrollBar.setScrollTop(this.scrollTop); + }; + + this.$renderChanges = function(changes, force) { + if (!force && (!changes || !this.session || !this.container.offsetWidth)) + return; + + // text, scrolling and resize changes can cause the view port size to change + if (changes & this.CHANGE_FULL || + changes & this.CHANGE_SIZE || + changes & this.CHANGE_TEXT || + changes & this.CHANGE_LINES || + changes & this.CHANGE_SCROLL + ) + this.$computeLayerConfig(); + + // horizontal scrolling + if (changes & this.CHANGE_H_SCROLL) { + this.scroller.scrollLeft = this.scrollLeft; + + // read the value after writing it since the value might get clipped + var scrollLeft = this.scroller.scrollLeft; + this.scrollLeft = scrollLeft; + this.session.setScrollLeft(scrollLeft); + + this.scroller.className = this.scrollLeft == 0 ? "ace_scroller" : "ace_scroller horscroll"; + } + + // full + if (changes & this.CHANGE_FULL) { + this.$textLayer.checkForSizeChanges(); + // update scrollbar first to not lose scroll position when gutter calls resize + this.$updateScrollBar(); + this.$textLayer.update(this.layerConfig); + if (this.showGutter) + this.$gutterLayer.update(this.layerConfig); + this.$markerBack.update(this.layerConfig); + this.$markerFront.update(this.layerConfig); + this.$cursorLayer.update(this.layerConfig); + this.$moveTextAreaToCursor(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + return; + } + + // scrolling + if (changes & this.CHANGE_SCROLL) { + this.$updateScrollBar(); + if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES) + this.$textLayer.update(this.layerConfig); + else + this.$textLayer.scrollLines(this.layerConfig); + + if (this.showGutter) + this.$gutterLayer.update(this.layerConfig); + this.$markerBack.update(this.layerConfig); + this.$markerFront.update(this.layerConfig); + this.$cursorLayer.update(this.layerConfig); + this.$moveTextAreaToCursor(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + return; + } + + if (changes & this.CHANGE_TEXT) { + this.$textLayer.update(this.layerConfig); + if (this.showGutter) + this.$gutterLayer.update(this.layerConfig); + } + else if (changes & this.CHANGE_LINES) { + if (this.$updateLines() || (changes & this.CHANGE_GUTTER) && this.showGutter) + this.$gutterLayer.update(this.layerConfig); + } + else if (changes & this.CHANGE_TEXT || changes & this.CHANGE_GUTTER) { + if (this.showGutter) + this.$gutterLayer.update(this.layerConfig); + } + + if (changes & this.CHANGE_CURSOR) { + this.$cursorLayer.update(this.layerConfig); + this.$moveTextAreaToCursor(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + } + + if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) { + this.$markerFront.update(this.layerConfig); + } + + if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) { + this.$markerBack.update(this.layerConfig); + } + + if (changes & this.CHANGE_SIZE) + this.$updateScrollBar(); + }; + + this.$computeLayerConfig = function() { + var session = this.session; + + var offset = this.scrollTop % this.lineHeight; + var minHeight = this.$size.scrollerHeight + this.lineHeight; + + var longestLine = this.$getLongestLine(); + + var horizScroll = this.$horizScrollAlwaysVisible || this.$size.scrollerWidth - longestLine < 0; + var horizScrollChanged = this.$horizScroll !== horizScroll; + this.$horizScroll = horizScroll; + if (horizScrollChanged) { + this.scroller.style.overflowX = horizScroll ? "scroll" : "hidden"; + // when we hide scrollbar scroll event isn't emited + // leaving session with wrong scrollLeft value + if (!horizScroll) + this.session.setScrollLeft(0); + } + var maxHeight = this.session.getScreenLength() * this.lineHeight; + this.session.setScrollTop(Math.max(0, Math.min(this.scrollTop, maxHeight - this.$size.scrollerHeight))); + + var lineCount = Math.ceil(minHeight / this.lineHeight) - 1; + var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight)); + var lastRow = firstRow + lineCount; + + // Map lines on the screen to lines in the document. + var firstRowScreen, firstRowHeight; + var lineHeight = this.lineHeight; + firstRow = session.screenToDocumentRow(firstRow, 0); + + // Check if firstRow is inside of a foldLine. If true, then use the first + // row of the foldLine. + var foldLine = session.getFoldLine(firstRow); + if (foldLine) { + firstRow = foldLine.start.row; + } + + firstRowScreen = session.documentToScreenRow(firstRow, 0); + firstRowHeight = session.getRowLength(firstRow) * lineHeight; + + lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1); + minHeight = this.$size.scrollerHeight + session.getRowLength(lastRow) * lineHeight + + firstRowHeight; + + offset = this.scrollTop - firstRowScreen * lineHeight; + + this.layerConfig = { + width : longestLine, + padding : this.$padding, + firstRow : firstRow, + firstRowScreen: firstRowScreen, + lastRow : lastRow, + lineHeight : lineHeight, + characterWidth : this.characterWidth, + minHeight : minHeight, + maxHeight : maxHeight, + offset : offset, + height : this.$size.scrollerHeight + }; + + // For debugging. + // console.log(JSON.stringify(this.layerConfig)); + + this.$gutterLayer.element.style.marginTop = (-offset) + "px"; + this.content.style.marginTop = (-offset) + "px"; + this.content.style.width = longestLine + 2 * this.$padding + "px"; + this.content.style.height = minHeight + "px"; + + // Horizontal scrollbar visibility may have changed, which changes + // the client height of the scroller + if (horizScrollChanged) + this.onResize(true); + }; + + this.$updateLines = function() { + var firstRow = this.$changedLines.firstRow; + var lastRow = this.$changedLines.lastRow; + this.$changedLines = null; + + var layerConfig = this.layerConfig; + + if (firstRow > layerConfig.lastRow + 1) { return; } + if (lastRow < layerConfig.firstRow) { return; } + + // if the last row is unknown -> redraw everything + if (lastRow === Infinity) { + if (this.showGutter) + this.$gutterLayer.update(layerConfig); + this.$textLayer.update(layerConfig); + return; + } + + // else update only the changed rows + this.$textLayer.updateLines(layerConfig, firstRow, lastRow); + return true; + }; + + this.$getLongestLine = function() { + var charCount = this.session.getScreenWidth(); + if (this.$textLayer.showInvisibles) + charCount += 1; + + return Math.max(this.$size.scrollerWidth - 2 * this.$padding, Math.round(charCount * this.characterWidth)); + }; + this.updateFrontMarkers = function() { + this.$markerFront.setMarkers(this.session.getMarkers(true)); + this.$loop.schedule(this.CHANGE_MARKER_FRONT); + }; + this.updateBackMarkers = function() { + this.$markerBack.setMarkers(this.session.getMarkers()); + this.$loop.schedule(this.CHANGE_MARKER_BACK); + }; + this.addGutterDecoration = function(row, className){ + this.$gutterLayer.addGutterDecoration(row, className); + }; + this.removeGutterDecoration = function(row, className){ + this.$gutterLayer.removeGutterDecoration(row, className); + }; + this.updateBreakpoints = function(rows) { + this.$loop.schedule(this.CHANGE_GUTTER); + }; + this.setAnnotations = function(annotations) { + this.$gutterLayer.setAnnotations(annotations); + this.$loop.schedule(this.CHANGE_GUTTER); + }; + this.updateCursor = function() { + this.$loop.schedule(this.CHANGE_CURSOR); + }; + this.hideCursor = function() { + this.$cursorLayer.hideCursor(); + }; + this.showCursor = function() { + this.$cursorLayer.showCursor(); + }; + + this.scrollSelectionIntoView = function(anchor, lead, offset) { + // first scroll anchor into view then scroll lead into view + this.scrollCursorIntoView(anchor, offset); + this.scrollCursorIntoView(lead, offset); + }; + this.scrollCursorIntoView = function(cursor, offset) { + // the editor is not visible + if (this.$size.scrollerHeight === 0) + return; + + var pos = this.$cursorLayer.getPixelPosition(cursor); + + var left = pos.left; + var top = pos.top; + + if (this.scrollTop > top) { + if (offset) + top -= offset * this.$size.scrollerHeight; + this.session.setScrollTop(top); + } else if (this.scrollTop + this.$size.scrollerHeight < top + this.lineHeight) { + if (offset) + top += offset * this.$size.scrollerHeight; + this.session.setScrollTop(top + this.lineHeight - this.$size.scrollerHeight); + } + + var scrollLeft = this.scrollLeft; + + if (scrollLeft > left) { + if (left < this.$padding + 2 * this.layerConfig.characterWidth) + left = 0; + this.session.setScrollLeft(left); + } else if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) { + this.session.setScrollLeft(Math.round(left + this.characterWidth - this.$size.scrollerWidth)); + } + }; + this.getScrollTop = function() { + return this.session.getScrollTop(); + }; + this.getScrollLeft = function() { + return this.session.getScrollLeft(); + }; + this.getScrollTopRow = function() { + return this.scrollTop / this.lineHeight; + }; + this.getScrollBottomRow = function() { + return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1); + }; + this.scrollToRow = function(row) { + this.session.setScrollTop(row * this.lineHeight); + }; + + this.alignCursor = function(cursor, alignment) { + if (typeof cursor == "number") + cursor = {row: cursor, column: 0}; + + var pos = this.$cursorLayer.getPixelPosition(cursor); + var offset = pos.top - this.$size.scrollerHeight * (alignment || 0); + + this.session.setScrollTop(offset); + }; + + this.STEPS = 8; + this.$calcSteps = function(fromValue, toValue){ + var i = 0; + var l = this.STEPS; + var steps = []; + + var func = function(t, x_min, dx) { + return dx * (Math.pow(t - 1, 3) + 1) + x_min; + }; + + for (i = 0; i < l; ++i) + steps.push(func(i / this.STEPS, fromValue, toValue - fromValue)); + + return steps; + }; + this.scrollToLine = function(line, center, animate, callback) { + var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0}); + var offset = pos.top; + if (center) + offset -= this.$size.scrollerHeight / 2; + + var initialScroll = this.scrollTop; + this.session.setScrollTop(offset); + if (animate !== false) + this.animateScrolling(initialScroll, callback); + }; + + this.animateScrolling = function(fromValue, callback) { + var toValue = this.scrollTop; + if (this.$animatedScroll && Math.abs(fromValue - toValue) < 100000) { + var _self = this; + var steps = _self.$calcSteps(fromValue, toValue); + this.$inScrollAnimation = true; + + clearInterval(this.$timer); + + _self.session.setScrollTop(steps.shift()); + this.$timer = setInterval(function() { + if (steps.length) { + _self.session.setScrollTop(steps.shift()); + // trick session to think it's already scrolled to not loose toValue + _self.session.$scrollTop = toValue; + } else if (toValue != null) { + _self.session.$scrollTop = -1; + _self.session.setScrollTop(toValue); + toValue = null; + } else { + // do this on separate step to not get spurious scroll event from scrollbar + _self.$timer = clearInterval(_self.$timer); + _self.$inScrollAnimation = false; + callback && callback(); + } + }, 10); + } + }; + this.scrollToY = function(scrollTop) { + // after calling scrollBar.setScrollTop + // scrollbar sends us event with same scrollTop. ignore it + if (this.scrollTop !== scrollTop) { + this.$loop.schedule(this.CHANGE_SCROLL); + this.scrollTop = scrollTop; + } + }; + this.scrollToX = function(scrollLeft) { + if (scrollLeft < 0) + scrollLeft = 0; + + if (this.scrollLeft !== scrollLeft) + this.scrollLeft = scrollLeft; + this.$loop.schedule(this.CHANGE_H_SCROLL); + }; + this.scrollBy = function(deltaX, deltaY) { + deltaY && this.session.setScrollTop(this.session.getScrollTop() + deltaY); + deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX); + }; + this.isScrollableBy = function(deltaX, deltaY) { + if (deltaY < 0 && this.session.getScrollTop() > 0) + return true; + if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight < this.layerConfig.maxHeight) + return true; + // todo: handle horizontal scrolling + }; + + this.pixelToScreenCoordinates = function(x, y) { + var canvasPos = this.scroller.getBoundingClientRect(); + + var offset = (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth; + var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight); + var col = Math.round(offset); + + return {row: row, column: col, side: offset - col > 0 ? 1 : -1}; + }; + + this.screenToTextCoordinates = function(x, y) { + var canvasPos = this.scroller.getBoundingClientRect(); + + var col = Math.round( + (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth + ); + var row = Math.floor( + (y + this.scrollTop - canvasPos.top) / this.lineHeight + ); + + return this.session.screenToDocumentPosition(row, Math.max(col, 0)); + }; + this.textToScreenCoordinates = function(row, column) { + var canvasPos = this.scroller.getBoundingClientRect(); + var pos = this.session.documentToScreenPosition(row, column); + + var x = this.$padding + Math.round(pos.column * this.characterWidth); + var y = pos.row * this.lineHeight; + + return { + pageX: canvasPos.left + x - this.scrollLeft, + pageY: canvasPos.top + y - this.scrollTop + }; + }; + this.visualizeFocus = function() { + dom.addCssClass(this.container, "ace_focus"); + }; + this.visualizeBlur = function() { + dom.removeCssClass(this.container, "ace_focus"); + }; + this.showComposition = function(position) { + if (!this.$composition) + this.$composition = { + keepTextAreaAtCursor: this.$keepTextAreaAtCursor, + cssText: this.textarea.style.cssText + }; + + this.$keepTextAreaAtCursor = true; + dom.addCssClass(this.textarea, "ace_composition"); + this.textarea.style.cssText = ""; + this.$moveTextAreaToCursor(); + }; + this.setCompositionText = function(text) { + this.$moveTextAreaToCursor(); + }; + this.hideComposition = function() { + if (!this.$composition) + return; + + dom.removeCssClass(this.textarea, "ace_composition"); + this.$keepTextAreaAtCursor = this.$composition.keepTextAreaAtCursor; + this.textarea.style.cssText = this.$composition.cssText; + this.$composition = null; + }; + + this._loadTheme = function(name, callback) { + if (!config.get("packaged")) + return callback(); + + net.loadScript(config.moduleUrl(name, "theme"), callback); + }; + this.setTheme = function(theme) { + var _self = this; + + this.$themeValue = theme; + if (!theme || typeof theme == "string") { + var moduleName = theme || "ace/theme/textmate"; + + var module; + try { + module = require(moduleName); + } catch (e) {}; + if (module) + return afterLoad(module); + + _self._loadTheme(moduleName, function() { + require([moduleName], function(module) { + if (_self.$themeValue !== theme) + return; + + afterLoad(module); + }); + }); + } else { + afterLoad(theme); + } + + function afterLoad(theme) { + dom.importCssString( + theme.cssText, + theme.cssClass, + _self.container.ownerDocument + ); + + if (_self.$theme) + dom.removeCssClass(_self.container, _self.$theme); + + _self.$theme = theme ? theme.cssClass : null; + + if (_self.$theme) + dom.addCssClass(_self.container, _self.$theme); + + if (theme && theme.isDark) + dom.addCssClass(_self.container, "ace_dark"); + else + dom.removeCssClass(_self.container, "ace_dark"); + + // force re-measure of the gutter width + if (_self.$size) { + _self.$size.width = 0; + _self.onResize(); + } + } + }; + this.getTheme = function() { + return this.$themeValue; + }; + + // Methods allows to add / remove CSS classnames to the editor element. + // This feature can be used by plug-ins to provide a visual indication of + // a certain mode that editor is in. + + /** + * VirtualRenderer.setStyle(style) + * - style (String): A class name + * + * [Adds a new class, `style`, to the editor.]{: #VirtualRenderer.setStyle} + **/ + this.setStyle = function setStyle(style) { + dom.addCssClass(this.container, style); + }; + this.unsetStyle = function unsetStyle(style) { + dom.removeCssClass(this.container, style); + }; + this.destroy = function() { + this.$textLayer.destroy(); + this.$cursorLayer.destroy(); + }; + +}).call(VirtualRenderer.prototype); + +exports.VirtualRenderer = VirtualRenderer; +}); + +ace.define('ace/layer/gutter', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) { + + +var dom = require("../lib/dom"); +var oop = require("../lib/oop"); +var EventEmitter = require("../lib/event_emitter").EventEmitter; + +var Gutter = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_gutter-layer"; + parentEl.appendChild(this.element); + this.setShowFoldWidgets(this.$showFoldWidgets); + + this.gutterWidth = 0; + + this.$annotations = []; +}; + +(function() { + + oop.implement(this, EventEmitter); + + this.setSession = function(session) { + this.session = session; + }; + + this.addGutterDecoration = function(row, className){ + if (window.console) + console.warn && console.warn("deprecated use session.addGutterDecoration"); + this.session.addGutterDecoration(row, className); + }; + + this.removeGutterDecoration = function(row, className){ + if (window.console) + console.warn && console.warn("deprecated use session.removeGutterDecoration"); + this.session.removeGutterDecoration(row, className); + }; + + this.setAnnotations = function(annotations) { + // iterate over sparse array + this.$annotations = []; + for (var row in annotations) if (annotations.hasOwnProperty(row)) { + var rowAnnotations = annotations[row]; + if (!rowAnnotations) + continue; + + var rowInfo = this.$annotations[row] = { + text: [] + }; + for (var i=0; i foldStart) { + i = fold.end.row + 1; + fold = this.session.getNextFoldLine(i, fold); + foldStart = fold ?fold.start.row :Infinity; + } + if(i > lastRow) + break; + + var annotation = this.$annotations[i] || emptyAnno; + html.push( + "
", + lastLineNumber = i + 1 + ); + + if (foldWidgets) { + var c = foldWidgets[i]; + // check if cached value is invalidated and we need to recompute + if (c == null) + c = foldWidgets[i] = this.session.getFoldWidget(i); + if (c) + html.push( + "" + ); + } + + html.push("
"); + + i++; + } + + this.element = dom.setInnerHtml(this.element, html.join("")); + this.element.style.height = config.minHeight + "px"; + + if (this.session.$useWrapMode) + lastLineNumber = this.session.getLength(); + + var gutterWidth = ("" + lastLineNumber).length * config.characterWidth; + var padding = this.$padding || this.$computePadding(); + gutterWidth += padding.left + padding.right; + if (gutterWidth !== this.gutterWidth) { + this.gutterWidth = gutterWidth; + this.element.style.width = Math.ceil(this.gutterWidth) + "px"; + this._emit("changeGutterWidth", gutterWidth); + } + }; + + this.$showFoldWidgets = true; + this.setShowFoldWidgets = function(show) { + if (show) + dom.addCssClass(this.element, "ace_folding-enabled"); + else + dom.removeCssClass(this.element, "ace_folding-enabled"); + + this.$showFoldWidgets = show; + this.$padding = null; + }; + + this.getShowFoldWidgets = function() { + return this.$showFoldWidgets; + }; + + this.$computePadding = function() { + if (!this.element.firstChild) + return {left: 0, right: 0}; + var style = dom.computedStyle(this.element.firstChild); + this.$padding = {} + this.$padding.left = parseInt(style.paddingLeft) + 1; + this.$padding.right = parseInt(style.paddingRight); + return this.$padding; + }; + + this.getRegion = function(point) { + var padding = this.$padding || this.$computePadding(); + var rect = this.element.getBoundingClientRect(); + if (point.x < padding.left + rect.left) + return "markers"; + if (this.$showFoldWidgets && point.x > rect.right - padding.right) + return "foldWidgets"; + }; + +}).call(Gutter.prototype); + +exports.Gutter = Gutter; + +}); + +ace.define('ace/layer/marker', ['require', 'exports', 'module' , 'ace/range', 'ace/lib/dom'], function(require, exports, module) { + + +var Range = require("../range").Range; +var dom = require("../lib/dom"); + +var Marker = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_marker-layer"; + parentEl.appendChild(this.element); +}; + +(function() { + + this.$padding = 0; + + this.setPadding = function(padding) { + this.$padding = padding; + }; + this.setSession = function(session) { + this.session = session; + }; + + this.setMarkers = function(markers) { + this.markers = markers; + }; + + this.update = function(config) { + var config = config || this.config; + if (!config) + return; + + this.config = config; + + + var html = []; + for (var key in this.markers) { + var marker = this.markers[key]; + + if (!marker.range) { + marker.update(html, this, this.session, config); + continue; + } + + var range = marker.range.clipRows(config.firstRow, config.lastRow); + if (range.isEmpty()) continue; + + range = range.toScreenRange(this.session); + if (marker.renderer) { + var top = this.$getTop(range.start.row, config); + var left = Math.round( + this.$padding + range.start.column * config.characterWidth + ); + marker.renderer(html, range, left, top, config); + } + else if (range.isMultiLine()) { + if (marker.type == "text") { + this.drawTextMarker(html, range, marker.clazz, config); + } else { + this.drawMultiLineMarker( + html, range, marker.clazz, config, + marker.type + ); + } + } + else { + this.drawSingleLineMarker( + html, range, marker.clazz + " start", config, + null, marker.type + ); + } + } + this.element = dom.setInnerHtml(this.element, html.join("")); + }; + + this.$getTop = function(row, layerConfig) { + return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight; + }; + + // Draws a marker, which spans a range of text on multiple lines + this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) { + // selection start + var row = range.start.row; + + var lineRange = new Range( + row, range.start.column, + row, this.session.getScreenLastRowColumn(row) + ); + this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " start", layerConfig, 1, "text"); + + // selection end + row = range.end.row; + lineRange = new Range(row, 0, row, range.end.column); + this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, "text"); + + for (row = range.start.row + 1; row < range.end.row; row++) { + lineRange.start.row = row; + lineRange.end.row = row; + lineRange.end.column = this.session.getScreenLastRowColumn(row); + this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, "text"); + } + }; + + // Draws a multi line marker, where lines span the full width + this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, type) { + var padding = type === "background" ? 0 : this.$padding; + // from selection start to the end of the line + var height = config.lineHeight; + var top = this.$getTop(range.start.row, config); + var left = Math.round(padding + range.start.column * config.characterWidth); + + stringBuilder.push( + "
" + ); + + // from start of the last line to the selection end + top = this.$getTop(range.end.row, config); + var width = Math.round(range.end.column * config.characterWidth); + + stringBuilder.push( + "
" + ); + + // all the complete lines + height = (range.end.row - range.start.row - 1) * config.lineHeight; + if (height < 0) + return; + top = this.$getTop(range.start.row + 1, config); + + stringBuilder.push( + "
" + ); + }; + + // Draws a marker which covers part or whole width of a single screen line + this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength, type) { + var padding = type === "background" ? 0 : this.$padding; + var height = layerConfig.lineHeight; + + if (type === "background") + var width = layerConfig.width; + else + width = Math.round((range.end.column + (extraLength || 0) - range.start.column) * layerConfig.characterWidth); + + var top = this.$getTop(range.start.row, layerConfig); + var left = Math.round( + padding + range.start.column * layerConfig.characterWidth + ); + + stringBuilder.push( + "
" + ); + }; + +}).call(Marker.prototype); + +exports.Marker = Marker; + +}); + +ace.define('ace/layer/text', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/lang', 'ace/lib/useragent', 'ace/lib/event_emitter'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var dom = require("../lib/dom"); +var lang = require("../lib/lang"); +var useragent = require("../lib/useragent"); +var EventEmitter = require("../lib/event_emitter").EventEmitter; + +var Text = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_text-layer"; + parentEl.appendChild(this.element); + + this.$characterSize = this.$measureSizes() || {width: 0, height: 0}; + this.$pollSizeChanges(); +}; + +(function() { + + oop.implement(this, EventEmitter); + + this.EOF_CHAR = "\xB6"; //"¶"; + this.EOL_CHAR = "\xAC"; //"¬"; + this.TAB_CHAR = "\u2192"; //"→" "\u21E5"; + this.SPACE_CHAR = "\xB7"; //"·"; + this.$padding = 0; + + this.setPadding = function(padding) { + this.$padding = padding; + this.element.style.padding = "0 " + padding + "px"; + }; + + this.getLineHeight = function() { + return this.$characterSize.height || 1; + }; + + this.getCharacterWidth = function() { + return this.$characterSize.width || 1; + }; + + this.checkForSizeChanges = function() { + var size = this.$measureSizes(); + if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) { + this.$characterSize = size; + this._emit("changeCharacterSize", {data: size}); + } + }; + + this.$pollSizeChanges = function() { + var self = this; + this.$pollSizeChangesTimer = setInterval(function() { + self.checkForSizeChanges(); + }, 500); + }; + + this.$fontStyles = { + fontFamily : 1, + fontSize : 1, + fontWeight : 1, + fontStyle : 1, + lineHeight : 1 + }; + + this.$measureSizes = useragent.isIE || useragent.isOldGecko ? function() { + var n = 1000; + if (!this.$measureNode) { + var measureNode = this.$measureNode = dom.createElement("div"); + var style = measureNode.style; + + style.width = style.height = "auto"; + style.left = style.top = (-n * 40) + "px"; + + style.visibility = "hidden"; + style.position = "fixed"; + style.overflow = "visible"; + style.whiteSpace = "nowrap"; + + // in FF 3.6 monospace fonts can have a fixed sub pixel width. + // that's why we have to measure many characters + // Note: characterWidth can be a float! + measureNode.innerHTML = lang.stringRepeat("Xy", n); + + if (this.element.ownerDocument.body) { + this.element.ownerDocument.body.appendChild(measureNode); + } else { + var container = this.element.parentNode; + while (!dom.hasCssClass(container, "ace_editor")) + container = container.parentNode; + container.appendChild(measureNode); + } + } + + // Size and width can be null if the editor is not visible or + // detached from the document + if (!this.element.offsetWidth) + return null; + + var style = this.$measureNode.style; + var computedStyle = dom.computedStyle(this.element); + for (var prop in this.$fontStyles) + style[prop] = computedStyle[prop]; + + var size = { + height: this.$measureNode.offsetHeight, + width: this.$measureNode.offsetWidth / (n * 2) + }; + + // Size and width can be null if the editor is not visible or + // detached from the document + if (size.width == 0 || size.height == 0) + return null; + + return size; + } + : function() { + if (!this.$measureNode) { + var measureNode = this.$measureNode = dom.createElement("div"); + var style = measureNode.style; + + style.width = style.height = "auto"; + style.left = style.top = -100 + "px"; + + style.visibility = "hidden"; + style.position = "fixed"; + style.overflow = "visible"; + style.whiteSpace = "nowrap"; + + measureNode.innerHTML = "X"; + + var container = this.element.parentNode; + while (container && !dom.hasCssClass(container, "ace_editor")) + container = container.parentNode; + + if (!container) + return this.$measureNode = null; + + container.appendChild(measureNode); + } + + var rect = this.$measureNode.getBoundingClientRect(); + + var size = { + height: rect.height, + width: rect.width + }; + + // Size and width can be null if the editor is not visible or + // detached from the document + if (size.width == 0 || size.height == 0) + return null; + + return size; + }; + + this.setSession = function(session) { + this.session = session; + this.$computeTabString(); + }; + + this.showInvisibles = false; + this.setShowInvisibles = function(showInvisibles) { + if (this.showInvisibles == showInvisibles) + return false; + + this.showInvisibles = showInvisibles; + this.$computeTabString(); + return true; + }; + + this.displayIndentGuides = true; + this.setDisplayIndentGuides = function(display) { + if (this.displayIndentGuides == display) + return false; + + this.displayIndentGuides = display; + this.$computeTabString(); + return true; + }; + + this.$tabStrings = []; + this.onChangeTabSize = + this.$computeTabString = function() { + var tabSize = this.session.getTabSize(); + this.tabSize = tabSize; + var tabStr = this.$tabStrings = [0]; + for (var i = 1; i < tabSize + 1; i++) { + if (this.showInvisibles) { + tabStr.push("" + + this.TAB_CHAR + + Array(i).join(" ") + + ""); + } else { + tabStr.push(new Array(i+1).join(" ")); + } + } + if (this.displayIndentGuides) { + this.$indentGuideRe = /\s\S| \t|\t |\s$/; + var className = "ace_indent-guide"; + var content = Array(this.tabSize + 1).join(" "); + var tabContent = content; + if (this.showInvisibles) { + className += " ace_invisible"; + tabContent = this.TAB_CHAR + content.substr(6); + } + + this.$tabStrings[" "] = "" + content + ""; + this.$tabStrings["\t"] = "" + tabContent + ""; + } + }; + + this.updateLines = function(config, firstRow, lastRow) { + // Due to wrap line changes there can be new lines if e.g. + // the line to updated wrapped in the meantime. + if (this.config.lastRow != config.lastRow || + this.config.firstRow != config.firstRow) { + this.scrollLines(config); + } + this.config = config; + + var first = Math.max(firstRow, config.firstRow); + var last = Math.min(lastRow, config.lastRow); + + var lineElements = this.element.childNodes; + var lineElementsIdx = 0; + + for (var row = config.firstRow; row < first; row++) { + var foldLine = this.session.getFoldLine(row); + if (foldLine) { + if (foldLine.containsRow(first)) { + first = foldLine.start.row; + break; + } else { + row = foldLine.end.row; + } + } + lineElementsIdx ++; + } + + var row = first; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row :Infinity; + } + if (row > last) + break; + + var lineElement = lineElements[lineElementsIdx++]; + if (lineElement) { + var html = []; + this.$renderLine( + html, row, !this.$useLineGroups(), row == foldStart ? foldLine : false + ); + dom.setInnerHtml(lineElement, html.join("")); + } + row++; + } + }; + + this.scrollLines = function(config) { + var oldConfig = this.config; + this.config = config; + + if (!oldConfig || oldConfig.lastRow < config.firstRow) + return this.update(config); + + if (config.lastRow < oldConfig.firstRow) + return this.update(config); + + var el = this.element; + if (oldConfig.firstRow < config.firstRow) + for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--) + el.removeChild(el.firstChild); + + if (oldConfig.lastRow > config.lastRow) + for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--) + el.removeChild(el.lastChild); + + if (config.firstRow < oldConfig.firstRow) { + var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1); + if (el.firstChild) + el.insertBefore(fragment, el.firstChild); + else + el.appendChild(fragment); + } + + if (config.lastRow > oldConfig.lastRow) { + var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow); + el.appendChild(fragment); + } + }; + + this.$renderLinesFragment = function(config, firstRow, lastRow) { + var fragment = this.element.ownerDocument.createDocumentFragment(); + var row = firstRow; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row : Infinity; + } + if (row > lastRow) + break; + + var container = dom.createElement("div"); + + var html = []; + // Get the tokens per line as there might be some lines in between + // beeing folded. + this.$renderLine(html, row, false, row == foldStart ? foldLine : false); + + // don't use setInnerHtml since we are working with an empty DIV + container.innerHTML = html.join(""); + if (this.$useLineGroups()) { + container.className = 'ace_line_group'; + fragment.appendChild(container); + } else { + var lines = container.childNodes + while(lines.length) + fragment.appendChild(lines[0]); + } + + row++; + } + return fragment; + }; + + this.update = function(config) { + this.config = config; + + var html = []; + var firstRow = config.firstRow, lastRow = config.lastRow; + + var row = firstRow; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row :Infinity; + } + if (row > lastRow) + break; + + if (this.$useLineGroups()) + html.push("
") + + this.$renderLine(html, row, false, row == foldStart ? foldLine : false); + + if (this.$useLineGroups()) + html.push("
"); // end the line group + + row++; + } + this.element = dom.setInnerHtml(this.element, html.join("")); + }; + + this.$textToken = { + "text": true, + "rparen": true, + "lparen": true + }; + + this.$renderToken = function(stringBuilder, screenColumn, token, value) { + var self = this; + var replaceReg = /\t|&|<|( +)|([\x00-\x1f\x80-\xa0\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g; + var replaceFunc = function(c, a, b, tabIdx, idx4) { + if (a) { + return new Array(c.length+1).join(" "); + } else if (c == "&") { + return "&"; + } else if (c == "<") { + return "<"; + } else if (c == "\t") { + var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx); + screenColumn += tabSize - 1; + return self.$tabStrings[tabSize]; + } else if (c == "\u3000") { + // U+3000 is both invisible AND full-width, so must be handled uniquely + var classToUse = self.showInvisibles ? "ace_cjk ace_invisible" : "ace_cjk"; + var space = self.showInvisibles ? self.SPACE_CHAR : ""; + screenColumn += 1; + return "" + space + ""; + } else if (b) { + return "" + self.SPACE_CHAR + ""; + } else { + screenColumn += 1; + return "" + c + ""; + } + }; + + var output = value.replace(replaceReg, replaceFunc); + + if (!this.$textToken[token.type]) { + var classes = "ace_" + token.type.replace(/\./g, " ace_"); + var style = ""; + if (token.type == "fold") + style = " style='width:" + (token.value.length * this.config.characterWidth) + "px;' "; + stringBuilder.push("", output, ""); + } + else { + stringBuilder.push(output); + } + return screenColumn + value.length; + }; + + this.renderIndentGuide = function(stringBuilder, value) { + var cols = value.search(this.$indentGuideRe); + if (cols <= 0) + return value; + if (value[0] == " ") { + cols -= cols % this.tabSize; + stringBuilder.push(Array(cols/this.tabSize + 1).join(this.$tabStrings[" "])); + return value.substr(cols); + } else if (value[0] == "\t") { + stringBuilder.push(Array(cols + 1).join(this.$tabStrings["\t"])); + return value.substr(cols); + } + return value; + }; + + this.$renderWrappedLine = function(stringBuilder, tokens, splits, onlyContents) { + var chars = 0; + var split = 0; + var splitChars = splits[0]; + var screenColumn = 0; + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + var value = token.value; + if (i == 0 && this.displayIndentGuides) { + chars = value.length; + value = this.renderIndentGuide(stringBuilder, value); + if (!value) + continue; + chars -= value.length; + } + + if (chars + value.length < splitChars) { + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + chars += value.length; + } else { + while (chars + value.length >= splitChars) { + screenColumn = this.$renderToken( + stringBuilder, screenColumn, + token, value.substring(0, splitChars - chars) + ); + value = value.substring(splitChars - chars); + chars = splitChars; + + if (!onlyContents) { + stringBuilder.push("", + "
" + ); + } + + split ++; + screenColumn = 0; + splitChars = splits[split] || Number.MAX_VALUE; + } + if (value.length != 0) { + chars += value.length; + screenColumn = this.$renderToken( + stringBuilder, screenColumn, token, value + ); + } + } + } + }; + + this.$renderSimpleLine = function(stringBuilder, tokens) { + var screenColumn = 0; + var token = tokens[0]; + var value = token.value; + if (this.displayIndentGuides) + value = this.renderIndentGuide(stringBuilder, value); + if (value) + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + for (var i = 1; i < tokens.length; i++) { + token = tokens[i]; + value = token.value; + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + } + }; + + // row is either first row of foldline or not in fold + this.$renderLine = function(stringBuilder, row, onlyContents, foldLine) { + if (!foldLine && foldLine != false) + foldLine = this.session.getFoldLine(row); + + if (foldLine) + var tokens = this.$getFoldLineTokens(row, foldLine); + else + var tokens = this.session.getTokens(row); + + + if (!onlyContents) { + stringBuilder.push( + "
" + ); + } + + if (tokens.length) { + var splits = this.session.getRowSplitData(row); + if (splits && splits.length) + this.$renderWrappedLine(stringBuilder, tokens, splits, onlyContents); + else + this.$renderSimpleLine(stringBuilder, tokens); + } + + if (this.showInvisibles) { + if (foldLine) + row = foldLine.end.row + + stringBuilder.push( + "", + row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR, + "" + ); + } + if (!onlyContents) + stringBuilder.push("
"); + }; + + this.$getFoldLineTokens = function(row, foldLine) { + var session = this.session; + var renderTokens = []; + + function addTokens(tokens, from, to) { + var idx = 0, col = 0; + while ((col + tokens[idx].value.length) < from) { + col += tokens[idx].value.length; + idx++; + + if (idx == tokens.length) + return; + } + if (col != from) { + var value = tokens[idx].value.substring(from - col); + // Check if the token value is longer then the from...to spacing. + if (value.length > (to - from)) + value = value.substring(0, to - from); + + renderTokens.push({ + type: tokens[idx].type, + value: value + }); + + col = from + value.length; + idx += 1; + } + + while (col < to && idx < tokens.length) { + var value = tokens[idx].value; + if (value.length + col > to) { + renderTokens.push({ + type: tokens[idx].type, + value: value.substring(0, to - col) + }); + } else + renderTokens.push(tokens[idx]); + col += value.length; + idx += 1; + } + } + + var tokens = session.getTokens(row); + foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) { + if (placeholder) { + renderTokens.push({ + type: "fold", + value: placeholder + }); + } else { + if (isNewRow) + tokens = session.getTokens(row); + + if (tokens.length) + addTokens(tokens, lastColumn, column); + } + }, foldLine.end.row, this.session.getLine(foldLine.end.row).length); + + return renderTokens; + }; + + this.$useLineGroups = function() { + // For the updateLines function to work correctly, it's important that the + // child nodes of this.element correspond on a 1-to-1 basis to rows in the + // document (as distinct from lines on the screen). For sessions that are + // wrapped, this means we need to add a layer to the node hierarchy (tagged + // with the class name ace_line_group). + return this.session.getUseWrapMode(); + }; + + this.destroy = function() { + clearInterval(this.$pollSizeChangesTimer); + if (this.$measureNode) + this.$measureNode.parentNode.removeChild(this.$measureNode); + delete this.$measureNode; + }; + +}).call(Text.prototype); + +exports.Text = Text; + +}); + +ace.define('ace/layer/cursor', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) { + + +var dom = require("../lib/dom"); + +var Cursor = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_cursor-layer"; + parentEl.appendChild(this.element); + + this.isVisible = false; + + this.cursors = []; + this.cursor = this.addCursor(); +}; + +(function() { + + this.$padding = 0; + this.setPadding = function(padding) { + this.$padding = padding; + }; + + this.setSession = function(session) { + this.session = session; + }; + + this.addCursor = function() { + var el = dom.createElement("div"); + var className = "ace_cursor"; + if (!this.isVisible) + className += " ace_hidden"; + if (this.overwrite) + className += " ace_overwrite"; + + el.className = className; + this.element.appendChild(el); + this.cursors.push(el); + return el; + }; + + this.removeCursor = function() { + if (this.cursors.length > 1) { + var el = this.cursors.pop(); + el.parentNode.removeChild(el); + return el; + } + }; + + this.hideCursor = function() { + this.isVisible = false; + for (var i = this.cursors.length; i--; ) + dom.addCssClass(this.cursors[i], "ace_hidden"); + clearInterval(this.blinkId); + }; + + this.showCursor = function() { + this.isVisible = true; + for (var i = this.cursors.length; i--; ) + dom.removeCssClass(this.cursors[i], "ace_hidden"); + + this.element.style.visibility = ""; + this.restartTimer(); + }; + + this.restartTimer = function() { + clearInterval(this.blinkId); + if (!this.isVisible) + return; + + var element = this.cursors.length == 1 ? this.cursor : this.element; + this.blinkId = setInterval(function() { + element.style.visibility = "hidden"; + setTimeout(function() { + element.style.visibility = ""; + }, 400); + }, 1000); + }; + + this.getPixelPosition = function(position, onScreen) { + if (!this.config || !this.session) { + return { + left : 0, + top : 0 + }; + } + + if (!position) + position = this.session.selection.getCursor(); + var pos = this.session.documentToScreenPosition(position); + var cursorLeft = Math.round(this.$padding + + pos.column * this.config.characterWidth); + var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) * + this.config.lineHeight; + + return { + left : cursorLeft, + top : cursorTop + }; + }; + + this.update = function(config) { + this.config = config; + + if (this.session.selectionMarkerCount > 0) { + var selections = this.session.$selectionMarkers; + var i = 0, sel, cursorIndex = 0; + + for (var i = selections.length; i--; ) { + sel = selections[i]; + var pixelPos = this.getPixelPosition(sel.cursor, true); + + var style = (this.cursors[cursorIndex++] || this.addCursor()).style; + + style.left = pixelPos.left + "px"; + style.top = pixelPos.top + "px"; + style.width = config.characterWidth + "px"; + style.height = config.lineHeight + "px"; + } + if (cursorIndex > 1) + while (this.cursors.length > cursorIndex) + this.removeCursor(); + } else { + var pixelPos = this.getPixelPosition(null, true); + var style = this.cursor.style; + style.left = pixelPos.left + "px"; + style.top = pixelPos.top + "px"; + style.width = config.characterWidth + "px"; + style.height = config.lineHeight + "px"; + + while (this.cursors.length > 1) + this.removeCursor(); + } + + var overwrite = this.session.getOverwrite(); + if (overwrite != this.overwrite) + this.$setOverite(overwrite); + + // cache for textarea and gutter highlight + this.$pixelPos = pixelPos; + + this.restartTimer(); + }; + + this.$setOverite = function(overwrite) { + this.overwrite = overwrite; + for (var i = this.cursors.length; i--; ) { + if (overwrite) + dom.addCssClass(this.cursors[i], "ace_overwrite"); + else + dom.removeCssClass(this.cursors[i], "ace_overwrite"); + } + }; + + this.destroy = function() { + clearInterval(this.blinkId); + } + +}).call(Cursor.prototype); + +exports.Cursor = Cursor; + +}); + +ace.define('ace/scrollbar', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/event', 'ace/lib/event_emitter'], function(require, exports, module) { + + +var oop = require("./lib/oop"); +var dom = require("./lib/dom"); +var event = require("./lib/event"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; + +/** + * new ScrollBar(parent) + * - parent (DOMElement): A DOM element + * + * Creates a new `ScrollBar`. `parent` is the owner of the scroll bar. + * + **/ +var ScrollBar = function(parent) { + this.element = dom.createElement("div"); + this.element.className = "ace_sb"; + + this.inner = dom.createElement("div"); + this.element.appendChild(this.inner); + + parent.appendChild(this.element); + + // in OSX lion the scrollbars appear to have no width. In this case resize + // the to show the scrollbar but still pretend that the scrollbar has a width + // of 0px + // in Firefox 6+ scrollbar is hidden if element has the same width as scrollbar + // make element a little bit wider to retain scrollbar when page is zoomed + this.width = dom.scrollbarWidth(parent.ownerDocument); + this.element.style.width = (this.width || 15) + 5 + "px"; + + event.addListener(this.element, "scroll", this.onScroll.bind(this)); +}; + +(function() { + oop.implement(this, EventEmitter); + this.onScroll = function() { + this._emit("scroll", {data: this.element.scrollTop}); + }; + this.getWidth = function() { + return this.width; + }; + this.setHeight = function(height) { + this.element.style.height = height + "px"; + }; + this.setInnerHeight = function(height) { + this.inner.style.height = height + "px"; + }; + // TODO: on chrome 17+ after for small zoom levels after this function + // this.element.scrollTop != scrollTop which makes page to scroll up. + this.setScrollTop = function(scrollTop) { + this.element.scrollTop = scrollTop; + }; + +}).call(ScrollBar.prototype); + +exports.ScrollBar = ScrollBar; +}); + +ace.define('ace/renderloop', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) { + + +var event = require("./lib/event"); + +/** internal, hide + * new RenderLoop(onRender, win) + * + * + * +**/ +var RenderLoop = function(onRender, win) { + this.onRender = onRender; + this.pending = false; + this.changes = 0; + this.window = win || window; +}; + +(function() { + + /** internal, hide + * RenderLoop.schedule(change) + * - change (Array): + * + * + **/ + this.schedule = function(change) { + //this.onRender(change); + //return; + this.changes = this.changes | change; + if (!this.pending) { + this.pending = true; + var _self = this; + event.nextTick(function() { + _self.pending = false; + var changes; + while (changes = _self.changes) { + _self.changes = 0; + _self.onRender(changes); + } + }, this.window); + } + }; + +}).call(RenderLoop.prototype); + +exports.RenderLoop = RenderLoop; +}); +ace.define("ace/requirejs/text!ace/css/editor.css", [], ".ace_editor {\n\ + position: absolute;\n\ + overflow: hidden;\n\ + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Droid Sans Mono', 'Consolas', monospace;\n\ + font-size: 12px;\n\ +}\n\ +\n\ +.ace_scroller {\n\ + position: absolute;\n\ + overflow: hidden;\n\ +}\n\ +\n\ +.ace_content {\n\ + position: absolute;\n\ + box-sizing: border-box;\n\ + -moz-box-sizing: border-box;\n\ + -webkit-box-sizing: border-box;\n\ + cursor: text;\n\ +}\n\ +\n\ +.ace_gutter {\n\ + position: absolute;\n\ + overflow : hidden;\n\ + height: 100%;\n\ + width: auto;\n\ + cursor: default;\n\ + z-index: 4;\n\ +}\n\ +\n\ +.ace_gutter_active_line {\n\ + position: absolute;\n\ + left: 0;\n\ + right: 0;\n\ +}\n\ +\n\ +.ace_scroller.horscroll {\n\ + box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;\n\ +}\n\ +\n\ +.ace_gutter-cell {\n\ + padding-left: 19px;\n\ + padding-right: 6px;\n\ + background-repeat: no-repeat;\n\ +}\n\ +\n\ +.ace_gutter-cell.ace_error {\n\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTQ4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTU4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBMjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBMzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkgXxbAAAAJbSURBVHjapFNNaBNBFH4zs5vdZLP5sQmNpT82QY209heh1ioWisaDRcSKF0WKJ0GQnrzrxasHsR6EnlrwD0TagxJabaVEpFYxLWlLSS822tr87m66ccfd2GKyVhA6MMybgfe97/vmPUQphd0sZjto9XIn9OOsvlu2nkqRzVU+6vvlzPf8W6bk8dxQ0NPbxAALgCgg2JkaQuhzQau/El0zbmUA7U0Es8v2CiYmKQJHGO1QICCLoqilMhkmurDAyapKgqItezi/USRdJqEYY4D5jCy03ht2yMkkvL91jTTX10qzyyu2hruPRN7jgbH+EOsXcMLgYiThEgAMhABW85oqy1DXdRIdvP1AHJ2acQXvDIrVHcdQNrEKNYSVMSZGMjEzIIAwDXIo+6G/FxcGnzkC3T2oMhLjre49sBB+RRcHLqdafK6sYdE/GGBwU1VpFNj0aN8pJbe+BkZyevUrvLl6Xmm0W9IuTc0DxrDNAJd5oEvI/KRsNC3bQyNjPO9yQ1YHcfj2QvfQc/5TUhJTBc2iM0U7AWDQtc1nJHvD/cfO2s7jaGkiTEfa/Ep8coLu7zmNmh8+dc5lZDuUeFAGUNA/OY6JVaypQ0vjr7XYjUvJM37vt+j1vuTK5DgVfVUoTjVe+y3/LxMxY2GgU+CSLy4cpfsYorRXuXIOi0Vt40h67uZFTdIo6nLaZcwUJWAzwNS0tBnqqKzQDnjdG/iPyZxo46HaKUpbvYkj8qYRTZsBhge+JHhZyh0x9b95JqjVJkT084kZIPwu/mPWqPgfQ5jXh2+92Ay7HedfAgwA6KDWafb4w3cAAAAASUVORK5CYII=\");\n\ + background-repeat: no-repeat;\n\ + background-position: 2px center;\n\ +}\n\ +\n\ +.ace_gutter-cell.ace_warning {\n\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTg4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTk4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBNjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBNzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pgd7PfIAAAGmSURBVHjaYvr//z8DJZiJgUIANoCRkREb9gLiSVAaQx4OQM7AAkwd7XU2/v++/rOttdYGEB9dASEvOMydGKfH8Gv/p4XTkvRBfLxeQAP+1cUhXopyvzhP7P/IoSj7g7Mw09cNKO6J1QQ0L4gICPIv/veg/8W+JdFvQNLHVsW9/nmn9zk7B+cCkDwhL7gt6knSZnx9/LuCEOcvkIAMP+cvto9nfqyZmmUAksfnBUtbM60gX/3/kgyv3/xSFOL5DZT+L8vP+Yfh5cvfPvp/xUHyQHXGyAYwgpwBjZYFT3Y1OEl/OfCH4ffv3wzc4iwMvNIsDJ+f/mH4+vIPAxsb631WW0Yln6ZpQLXdMK/DXGDflh+sIv37EivD5x//Gb7+YWT4y86sl7BCCkSD+Z++/1dkvsFRl+HnD1Rvje4F8whjMXmGj58YGf5zsDMwcnAwfPvKcml62DsQDeaDxN+/Y0qwlpEHqrdB94IRNIDUgfgfKJChGK4OikEW3gTiXUB950ASLFAF54AC94A0G9QAfOnmF9DCDzABFqS08IHYDIScdijOjQABBgC+/9awBH96jwAAAABJRU5ErkJggg==\");\n\ + background-position: 2px center;\n\ +}\n\ +\n\ +.ace_gutter-cell.ace_info {\n\ + background-image: url(\"data:image/gif;base64,R0lGODlhEAAQAMQAAAAAAEFBQVJSUl5eXmRkZGtra39/f4WFhYmJiZGRkaampry8vMPDw8zMzNXV1dzc3OTk5Orq6vDw8P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABQALAAAAAAQABAAAAUuICWOZGmeaBml5XGwFCQSBGyXRSAwtqQIiRuiwIM5BoYVbEFIyGCQoeJGrVptIQA7\");\n\ + background-position: 2px center;\n\ +}\n\ +.ace_dark .ace_gutter-cell.ace_info {\n\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRTk5MTVGREIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRTk5MTVGRUIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZFOTkxNUZCQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFOTkxNUZDQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+SIDkjAAAAJ1JREFUeNpi/P//PwMlgImBQkB7A6qrq/+DMC55FkIGKCoq4pVnpFkgTp069f/+/fv/r1u37r+tre1/kg0A+ptn9uzZYLaRkRHpLvjw4cNXWVlZhufPnzOcO3eOdAO0tbVPAjHDmzdvGA4fPsxIsgGSkpJmv379Ynj37h2DjIyMCMkG3LhxQ/T27dsMampqDHZ2dq/pH41DxwCAAAMAFdc68dUsFZgAAAAASUVORK5CYII=\");\n\ +}\n\ +\n\ +.ace_editor .ace_sb {\n\ + position: absolute;\n\ + overflow-x: hidden;\n\ + overflow-y: scroll;\n\ + right: 0;\n\ +}\n\ +\n\ +.ace_editor .ace_sb div {\n\ + position: absolute;\n\ + width: 1px;\n\ + left: 0;\n\ +}\n\ +\n\ +.ace_editor .ace_print_margin_layer {\n\ + z-index: 0;\n\ + position: absolute;\n\ + overflow: hidden;\n\ + margin: 0;\n\ + left: 0;\n\ + height: 100%;\n\ + width: 100%;\n\ +}\n\ +\n\ +.ace_editor .ace_print_margin {\n\ + position: absolute;\n\ + height: 100%;\n\ +}\n\ +\n\ +.ace_editor > textarea {\n\ + position: absolute;\n\ + z-index: 0;\n\ + width: 0.5em;\n\ + height: 1em;\n\ + opacity: 0;\n\ + background: transparent;\n\ + appearance: none;\n\ + -moz-appearance: none;\n\ + border: none;\n\ + resize: none;\n\ + outline: none;\n\ + overflow: hidden;\n\ +}\n\ +\n\ +.ace_editor > textarea.ace_composition {\n\ + background: #fff;\n\ + color: #000;\n\ + z-index: 1000;\n\ + opacity: 1;\n\ + border: solid lightgray 1px;\n\ + margin: -1px\n\ +}\n\ +\n\ +.ace_layer {\n\ + z-index: 1;\n\ + position: absolute;\n\ + overflow: hidden;\n\ + white-space: nowrap;\n\ + height: 100%;\n\ + width: 100%;\n\ + box-sizing: border-box;\n\ + -moz-box-sizing: border-box;\n\ + -webkit-box-sizing: border-box;\n\ + /* setting pointer-events: auto; on node under the mouse, which changes\n\ + during scroll, will break mouse wheel scrolling in Safari */\n\ + pointer-events: none;\n\ +}\n\ +\n\ +.ace_gutter .ace_layer {\n\ + position: relative;\n\ + width: auto;\n\ + text-align: right;\n\ + pointer-events: auto;\n\ +}\n\ +\n\ +.ace_text-layer {\n\ + color: black;\n\ + font: inherit !important;\n\ +}\n\ +\n\ +.ace_cjk {\n\ + display: inline-block;\n\ + text-align: center;\n\ +}\n\ +\n\ +.ace_cursor-layer {\n\ + z-index: 4;\n\ +}\n\ +\n\ +.ace_cursor {\n\ + z-index: 4;\n\ + position: absolute;\n\ +}\n\ +\n\ +.ace_cursor.ace_hidden {\n\ + opacity: 0.2;\n\ +}\n\ +\n\ +.ace_editor.multiselect .ace_cursor {\n\ + border-left-width: 1px;\n\ +}\n\ +\n\ +.ace_line {\n\ + white-space: nowrap;\n\ +}\n\ +\n\ +.ace_marker-layer .ace_step {\n\ + position: absolute;\n\ + z-index: 3;\n\ +}\n\ +\n\ +.ace_marker-layer .ace_selection {\n\ + position: absolute;\n\ + z-index: 5;\n\ +}\n\ +\n\ +.ace_marker-layer .ace_bracket {\n\ + position: absolute;\n\ + z-index: 6;\n\ +}\n\ +\n\ +.ace_marker-layer .ace_active_line {\n\ + position: absolute;\n\ + z-index: 2;\n\ +}\n\ +\n\ +.ace_marker-layer .ace_selected_word {\n\ + position: absolute;\n\ + z-index: 4;\n\ + box-sizing: border-box;\n\ + -moz-box-sizing: border-box;\n\ + -webkit-box-sizing: border-box;\n\ +}\n\ +\n\ +.ace_line .ace_fold {\n\ + box-sizing: border-box;\n\ + -moz-box-sizing: border-box;\n\ + -webkit-box-sizing: border-box;\n\ +\n\ + display: inline-block;\n\ + height: 11px;\n\ + margin-top: -2px;\n\ + vertical-align: middle;\n\ +\n\ + background-image:\n\ + url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),\n\ + url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%3AIDAT8%11c%FC%FF%FF%7F%18%03%1A%60%01%F2%3F%A0%891%80%04%FF%11-%F8%17%9BJ%E2%05%B1ZD%81v%26t%E7%80%F8%A3%82h%A12%1A%20%A3%01%02%0F%01%BA%25%06%00%19%C0%0D%AEF%D5%3ES%00%00%00%00IEND%AEB%60%82\");\n\ + background-repeat: no-repeat, repeat-x;\n\ + background-position: center center, top left;\n\ + color: transparent;\n\ +\n\ + border: 1px solid black;\n\ + -moz-border-radius: 2px;\n\ + -webkit-border-radius: 2px;\n\ + border-radius: 2px;\n\ +\n\ + cursor: pointer;\n\ + pointer-events: auto;\n\ +}\n\ +\n\ +.ace_dark .ace_fold {\n\ +}\n\ +\n\ +.ace_fold:hover{\n\ + background-image:\n\ + url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),\n\ + url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%003IDAT8%11c%FC%FF%FF%7F%3E%03%1A%60%01%F2%3F%A3%891%80%04%FFQ%26%F8w%C0%B43%A1%DB%0C%E2%8F%0A%A2%85%CAh%80%8C%06%08%3C%04%E8%96%18%00%A3S%0D%CD%CF%D8%C1%9D%00%00%00%00IEND%AEB%60%82\");\n\ + background-repeat: no-repeat, repeat-x;\n\ + background-position: center center, top left;\n\ +}\n\ +\n\ +.ace_dragging .ace_content {\n\ + cursor: move;\n\ +}\n\ +\n\ +.ace_gutter_tooltip {\n\ + background-color: #FFFFD5;\n\ + border: 1px solid gray;\n\ + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);\n\ + color: black;\n\ + display: inline-block;\n\ + padding: 4px;\n\ + position: absolute;\n\ + z-index: 300;\n\ + box-sizing: border-box;\n\ + -moz-box-sizing: border-box;\n\ + -webkit-box-sizing: border-box;\n\ + cursor: default;\n\ +}\n\ +\n\ +.ace_folding-enabled > .ace_gutter-cell {\n\ + padding-right: 13px;\n\ +}\n\ +\n\ +.ace_fold-widget {\n\ + box-sizing: border-box;\n\ + -moz-box-sizing: border-box;\n\ + -webkit-box-sizing: border-box;\n\ +\n\ + margin: 0 -12px 0 1px;\n\ + display: inline-block;\n\ + height: 100%;\n\ + width: 11px;\n\ + vertical-align: bottom;\n\ +\n\ + background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82\");\n\ + background-repeat: no-repeat;\n\ + background-position: center;\n\ +\n\ + border-radius: 3px;\n\ + \n\ + border: 1px solid transparent;\n\ +}\n\ +\n\ +.ace_fold-widget.end {\n\ + background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAm%C7%C1%09%000%08C%D1%8C%ECE%C8E(%8E%EC%02)%1EZJ%F1%C1'%04%07I%E1%E5%EE%CAL%F5%A2%99%99%22%E2%D6%1FU%B5%FE0%D9x%A7%26Wz5%0E%D5%00%00%00%00IEND%AEB%60%82\");\n\ +}\n\ +\n\ +.ace_fold-widget.closed {\n\ + background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%03%00%00%00%06%08%06%00%00%00%06%E5%24%0C%00%00%009IDATx%DA5%CA%C1%09%000%08%03%C0%AC*(%3E%04%C1%0D%BA%B1%23%A4Uh%E0%20%81%C0%CC%F8%82%81%AA%A2%AArGfr%88%08%11%11%1C%DD%7D%E0%EE%5B%F6%F6%CB%B8%05Q%2F%E9tai%D9%00%00%00%00IEND%AEB%60%82\");\n\ +}\n\ +\n\ +.ace_fold-widget:hover {\n\ + border: 1px solid rgba(0, 0, 0, 0.3);\n\ + background-color: rgba(255, 255, 255, 0.2);\n\ + -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n\ + -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n\ +}\n\ +\n\ +.ace_fold-widget:active {\n\ + border: 1px solid rgba(0, 0, 0, 0.4);\n\ + background-color: rgba(0, 0, 0, 0.05);\n\ + -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n\ + -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n\ +}\n\ +/**\n\ + * Dark version for fold widgets\n\ + */\n\ +.ace_dark .ace_fold-widget {\n\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");\n\ +}\n\ +.ace_dark .ace_fold-widget.end {\n\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");\n\ +}\n\ +.ace_dark .ace_fold-widget.closed {\n\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");\n\ +}\n\ +.ace_dark .ace_fold-widget:hover {\n\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\n\ + background-color: rgba(255, 255, 255, 0.1);\n\ +}\n\ +.ace_dark .ace_fold-widget:active {\n\ + -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\n\ + -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\n\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\n\ +}\n\ + \n\ + \n\ + \n\ +.ace_fold-widget.invalid {\n\ + background-color: #FFB4B4;\n\ + border-color: #DE5555;\n\ +}\n\ +\n\ +.ace_fade-fold-widgets .ace_fold-widget {\n\ + -moz-transition: opacity 0.4s ease 0.05s;\n\ + -webkit-transition: opacity 0.4s ease 0.05s;\n\ + -o-transition: opacity 0.4s ease 0.05s;\n\ + -ms-transition: opacity 0.4s ease 0.05s;\n\ + transition: opacity 0.4s ease 0.05s;\n\ + opacity: 0;\n\ +}\n\ +\n\ +.ace_fade-fold-widgets:hover .ace_fold-widget {\n\ + -moz-transition: opacity 0.05s ease 0.05s;\n\ + -webkit-transition: opacity 0.05s ease 0.05s;\n\ + -o-transition: opacity 0.05s ease 0.05s;\n\ + -ms-transition: opacity 0.05s ease 0.05s;\n\ + transition: opacity 0.05s ease 0.05s;\n\ + opacity:1;\n\ +}\n\ +"); + +ace.define('ace/multi_select', ['require', 'exports', 'module' , 'ace/range_list', 'ace/range', 'ace/selection', 'ace/mouse/multi_select_handler', 'ace/lib/event', 'ace/commands/multi_select_commands', 'ace/search', 'ace/edit_session', 'ace/editor'], function(require, exports, module) { + +var RangeList = require("./range_list").RangeList; +var Range = require("./range").Range; +var Selection = require("./selection").Selection; +var onMouseDown = require("./mouse/multi_select_handler").onMouseDown; +var event = require("./lib/event"); +var commands = require("./commands/multi_select_commands"); +exports.commands = commands.defaultCommands.concat(commands.multiSelectCommands); + +// Todo: session.find or editor.findVolatile that returns range +var Search = require("./search").Search; +var search = new Search(); + +function find(session, needle, dir) { + search.$options.wrap = true; + search.$options.needle = needle; + search.$options.backwards = dir == -1; + return search.find(session); +} + +// extend EditSession +var EditSession = require("./edit_session").EditSession; +(function() { + this.getSelectionMarkers = function() { + return this.$selectionMarkers; + }; +}).call(EditSession.prototype); + +// extend Selection +(function() { + // list of ranges in reverse addition order + this.ranges = null; + + // automatically sorted list of ranges + this.rangeList = null; + this.addRange = function(range, $blockChangeEvents) { + if (!range) + return; + + if (!this.inMultiSelectMode && this.rangeCount == 0) { + var oldRange = this.toOrientedRange(); + if (range.intersects(oldRange)) + return $blockChangeEvents || this.fromOrientedRange(range); + + this.rangeList.add(oldRange); + this.$onAddRange(oldRange); + } + + if (!range.cursor) + range.cursor = range.end; + + var removed = this.rangeList.add(range); + + this.$onAddRange(range); + + if (removed.length) + this.$onRemoveRange(removed); + + if (this.rangeCount > 1 && !this.inMultiSelectMode) { + this._emit("multiSelect"); + this.inMultiSelectMode = true; + this.session.$undoSelect = false; + this.rangeList.attach(this.session); + } + + return $blockChangeEvents || this.fromOrientedRange(range); + }; + + this.toSingleRange = function(range) { + range = range || this.ranges[0]; + var removed = this.rangeList.removeAll(); + if (removed.length) + this.$onRemoveRange(removed); + + range && this.fromOrientedRange(range); + }; + this.substractPoint = function(pos) { + var removed = this.rangeList.substractPoint(pos); + if (removed) { + this.$onRemoveRange(removed); + return removed[0]; + } + }; + this.mergeOverlappingRanges = function() { + var removed = this.rangeList.merge(); + if (removed.length) + this.$onRemoveRange(removed); + else if(this.ranges[0]) + this.fromOrientedRange(this.ranges[0]); + }; + + this.$onAddRange = function(range) { + this.rangeCount = this.rangeList.ranges.length; + this.ranges.unshift(range); + this._emit("addRange", {range: range}); + }; + + this.$onRemoveRange = function(removed) { + this.rangeCount = this.rangeList.ranges.length; + if (this.rangeCount == 1 && this.inMultiSelectMode) { + var lastRange = this.rangeList.ranges.pop(); + removed.push(lastRange); + this.rangeCount = 0; + } + + for (var i = removed.length; i--; ) { + var index = this.ranges.indexOf(removed[i]); + this.ranges.splice(index, 1); + } + + this._emit("removeRange", {ranges: removed}); + + if (this.rangeCount == 0 && this.inMultiSelectMode) { + this.inMultiSelectMode = false; + this._emit("singleSelect"); + this.session.$undoSelect = true; + this.rangeList.detach(this.session); + } + + lastRange = lastRange || this.ranges[0]; + if (lastRange && !lastRange.isEqual(this.getRange())) + this.fromOrientedRange(lastRange); + }; + + // adds multicursor support to selection + this.$initRangeList = function() { + if (this.rangeList) + return; + + this.rangeList = new RangeList(); + this.ranges = []; + this.rangeCount = 0; + }; + + this.getAllRanges = function() { + return this.rangeList.ranges.concat(); + }; + + this.splitIntoLines = function () { + if (this.rangeCount > 1) { + var ranges = this.rangeList.ranges; + var lastRange = ranges[ranges.length - 1]; + var range = Range.fromPoints(ranges[0].start, lastRange.end); + + this.toSingleRange(); + this.setSelectionRange(range, lastRange.cursor == lastRange.start); + } else { + var range = this.getRange(); + var startRow = range.start.row; + var endRow = range.end.row; + if (startRow == endRow) + return; + + var rectSel = []; + var r = this.getLineRange(startRow, true); + r.start.column = range.start.column; + rectSel.push(r); + + for (var i = startRow + 1; i < endRow; i++) + rectSel.push(this.getLineRange(i, true)); + + r = this.getLineRange(endRow, true); + r.end.column = range.end.column; + rectSel.push(r); + + rectSel.forEach(this.addRange, this); + } + }; + + this.toggleBlockSelection = function () { + if (this.rangeCount > 1) { + var ranges = this.rangeList.ranges; + var lastRange = ranges[ranges.length - 1]; + var range = Range.fromPoints(ranges[0].start, lastRange.end); + + this.toSingleRange(); + this.setSelectionRange(range, lastRange.cursor == lastRange.start); + } else { + var cursor = this.session.documentToScreenPosition(this.selectionLead); + var anchor = this.session.documentToScreenPosition(this.selectionAnchor); + + var rectSel = this.rectangularRangeBlock(cursor, anchor); + rectSel.forEach(this.addRange, this); + } + }; + this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) { + var rectSel = []; + + var xBackwards = screenCursor.column < screenAnchor.column; + if (xBackwards) { + var startColumn = screenCursor.column; + var endColumn = screenAnchor.column; + } else { + var startColumn = screenAnchor.column; + var endColumn = screenCursor.column; + } + + var yBackwards = screenCursor.row < screenAnchor.row; + if (yBackwards) { + var startRow = screenCursor.row; + var endRow = screenAnchor.row; + } else { + var startRow = screenAnchor.row; + var endRow = screenCursor.row; + } + + if (startColumn < 0) + startColumn = 0; + if (startRow < 0) + startRow = 0; + + if (startRow == endRow) + includeEmptyLines = true; + + for (var row = startRow; row <= endRow; row++) { + var range = Range.fromPoints( + this.session.screenToDocumentPosition(row, startColumn), + this.session.screenToDocumentPosition(row, endColumn) + ); + if (range.isEmpty()) { + if (docEnd && isSamePoint(range.end, docEnd)) + break; + var docEnd = range.end; + } + range.cursor = xBackwards ? range.start : range.end; + rectSel.push(range); + } + + if (yBackwards) + rectSel.reverse(); + + if (!includeEmptyLines) { + var end = rectSel.length - 1; + while (rectSel[end].isEmpty() && end > 0) + end--; + if (end > 0) { + var start = 0; + while (rectSel[start].isEmpty()) + start++; + } + for (var i = end; i >= start; i--) { + if (rectSel[i].isEmpty()) + rectSel.splice(i, 1); + } + } + + return rectSel; + }; +}).call(Selection.prototype); + +// extend Editor +var Editor = require("./editor").Editor; +(function() { + + /** extension + * Editor.updateSelectionMarkers() + * + * Updates the cursor and marker layers. + **/ + this.updateSelectionMarkers = function() { + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + this.addSelectionMarker = function(orientedRange) { + if (!orientedRange.cursor) + orientedRange.cursor = orientedRange.end; + + var style = this.getSelectionStyle(); + orientedRange.marker = this.session.addMarker(orientedRange, "ace_selection", style); + + this.session.$selectionMarkers.push(orientedRange); + this.session.selectionMarkerCount = this.session.$selectionMarkers.length; + return orientedRange; + }; + this.removeSelectionMarker = function(range) { + if (!range.marker) + return; + this.session.removeMarker(range.marker); + var index = this.session.$selectionMarkers.indexOf(range); + if (index != -1) + this.session.$selectionMarkers.splice(index, 1); + this.session.selectionMarkerCount = this.session.$selectionMarkers.length; + }; + + this.removeSelectionMarkers = function(ranges) { + var markerList = this.session.$selectionMarkers; + for (var i = ranges.length; i--; ) { + var range = ranges[i]; + if (!range.marker) + continue; + this.session.removeMarker(range.marker); + var index = markerList.indexOf(range); + if (index != -1) + markerList.splice(index, 1); + } + this.session.selectionMarkerCount = markerList.length; + }; + + this.$onAddRange = function(e) { + this.addSelectionMarker(e.range); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onRemoveRange = function(e) { + this.removeSelectionMarkers(e.ranges); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onMultiSelect = function(e) { + if (this.inMultiSelectMode) + return; + this.inMultiSelectMode = true; + + this.setStyle("multiselect"); + this.keyBinding.addKeyboardHandler(commands.keyboardHandler); + this.commands.on("exec", this.$onMultiSelectExec); + + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onSingleSelect = function(e) { + if (this.session.multiSelect.inVirtualMode) + return; + this.inMultiSelectMode = false; + + this.unsetStyle("multiselect"); + this.keyBinding.removeKeyboardHandler(commands.keyboardHandler); + + this.commands.removeEventListener("exec", this.$onMultiSelectExec); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onMultiSelectExec = function(e) { + var command = e.command; + var editor = e.editor; + if (!editor.multiSelect) + return; + if (!command.multiSelectAction) { + command.exec(editor, e.args || {}); + editor.multiSelect.addRange(editor.multiSelect.toOrientedRange()); + editor.multiSelect.mergeOverlappingRanges(); + } else if (command.multiSelectAction == "forEach") { + editor.forEachSelection(command, e.args); + } else if (command.multiSelectAction == "single") { + editor.exitMultiSelectMode(); + command.exec(editor, e.args || {}); + } else { + command.multiSelectAction(editor, e.args || {}); + } + e.preventDefault(); + }; + this.forEachSelection = function(cmd, args) { + if (this.inVirtualSelectionMode) + return; + + var session = this.session; + var selection = this.selection; + var rangeList = selection.rangeList; + + var reg = selection._eventRegistry; + selection._eventRegistry = {}; + + var tmpSel = new Selection(session); + this.inVirtualSelectionMode = true; + for (var i = rangeList.ranges.length; i--;) { + tmpSel.fromOrientedRange(rangeList.ranges[i]); + this.selection = session.selection = tmpSel; + cmd.exec(this, args || {}); + tmpSel.toOrientedRange(rangeList.ranges[i]); + } + tmpSel.detach(); + + this.selection = session.selection = selection; + this.inVirtualSelectionMode = false; + selection._eventRegistry = reg; + selection.mergeOverlappingRanges(); + + this.onCursorChange(); + this.onSelectionChange(); + }; + this.exitMultiSelectMode = function() { + if (this.inVirtualSelectionMode) + return; + this.multiSelect.toSingleRange(); + }; + + this.getCopyText = function() { + var text = ""; + if (this.inMultiSelectMode) { + var ranges = this.multiSelect.rangeList.ranges; + text = []; + for (var i = 0; i < ranges.length; i++) { + text.push(this.session.getTextRange(ranges[i])); + } + text = text.join(this.session.getDocument().getNewLineCharacter()); + } else if (!this.selection.isEmpty()) { + text = this.session.getTextRange(this.getSelectionRange()); + } + + return text; + }; + + // todo this should change when paste becomes a command + this.onPaste = function(text) { + if (this.$readOnly) + return; + + this._emit("paste", text); + if (!this.inMultiSelectMode) + return this.insert(text); + + var lines = text.split(/\r\n|\r|\n/); + var ranges = this.selection.rangeList.ranges; + + if (lines.length > ranges.length || (lines.length <= 2 || !lines[1])) + return this.commands.exec("insertstring", this, text); + + for (var i = ranges.length; i--; ) { + var range = ranges[i]; + if (!range.isEmpty()) + this.session.remove(range); + + this.session.insert(range.start, lines[i]); + } + }; + this.findAll = function(needle, options, additive) { + options = options || {}; + options.needle = needle || options.needle; + this.$search.set(options); + + var ranges = this.$search.findAll(this.session); + if (!ranges.length) + return 0; + + this.$blockScrolling += 1; + var selection = this.multiSelect; + + if (!additive) + selection.toSingleRange(ranges[0]); + + for (var i = ranges.length; i--; ) + selection.addRange(ranges[i], true); + + this.$blockScrolling -= 1; + + return ranges.length; + }; + + // commands + /** extension + * Editor.selectMoreLines(dir, skip) + * - dir (Number): The direction of lines to select: -1 for up, 1 for down + * - skip (Boolean): If `true`, removes the active selection range + * + * Adds a cursor above or below the active cursor. + **/ + this.selectMoreLines = function(dir, skip) { + var range = this.selection.toOrientedRange(); + var isBackwards = range.cursor == range.end; + + var screenLead = this.session.documentToScreenPosition(range.cursor); + if (this.selection.$desiredColumn) + screenLead.column = this.selection.$desiredColumn; + + var lead = this.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column); + + if (!range.isEmpty()) { + var screenAnchor = this.session.documentToScreenPosition(isBackwards ? range.end : range.start); + var anchor = this.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column); + } else { + var anchor = lead; + } + + if (isBackwards) { + var newRange = Range.fromPoints(lead, anchor); + newRange.cursor = newRange.start; + } else { + var newRange = Range.fromPoints(anchor, lead); + newRange.cursor = newRange.end; + } + + newRange.desiredColumn = screenLead.column; + if (!this.selection.inMultiSelectMode) { + this.selection.addRange(range); + } else { + if (skip) + var toRemove = range.cursor; + } + + this.selection.addRange(newRange); + if (toRemove) + this.selection.substractPoint(toRemove); + }; + this.transposeSelections = function(dir) { + var session = this.session; + var sel = session.multiSelect; + var all = sel.ranges; + + for (var i = all.length; i--; ) { + var range = all[i]; + if (range.isEmpty()) { + var tmp = session.getWordRange(range.start.row, range.start.column); + range.start.row = tmp.start.row; + range.start.column = tmp.start.column; + range.end.row = tmp.end.row; + range.end.column = tmp.end.column; + } + } + sel.mergeOverlappingRanges(); + + var words = []; + for (var i = all.length; i--; ) { + var range = all[i]; + words.unshift(session.getTextRange(range)); + } + + if (dir < 0) + words.unshift(words.pop()); + else + words.push(words.shift()); + + for (var i = all.length; i--; ) { + var range = all[i]; + var tmp = range.clone(); + session.replace(range, words[i]); + range.start.row = tmp.start.row; + range.start.column = tmp.start.column; + } + } + + /** extension + * Editor.selectMore(dir, skip) + * - dir (Number): The direction of lines to select: -1 for up, 1 for down + * - skip (Boolean): If `true`, removes the active selection range + * + * Finds the next occurence of text in an active selection and adds it to the selections. + **/ + this.selectMore = function (dir, skip) { + var session = this.session; + var sel = session.multiSelect; + + var range = sel.toOrientedRange(); + if (range.isEmpty()) { + var range = session.getWordRange(range.start.row, range.start.column); + range.cursor = range.end; + this.multiSelect.addRange(range); + } + var needle = session.getTextRange(range); + + var newRange = find(session, needle, dir); + if (newRange) { + newRange.cursor = dir == -1 ? newRange.start : newRange.end; + this.multiSelect.addRange(newRange); + } + if (skip) + this.multiSelect.substractPoint(range.cursor); + }; +}).call(Editor.prototype); + + +function isSamePoint(p1, p2) { + return p1.row == p2.row && p1.column == p2.column; +} + +// patch +// adds multicursor support to a session +exports.onSessionChange = function(e) { + var session = e.session; + if (!session.multiSelect) { + session.$selectionMarkers = []; + session.selection.$initRangeList(); + session.multiSelect = session.selection; + } + this.multiSelect = session.multiSelect; + + var oldSession = e.oldSession; + if (oldSession) { + // todo use events + if (oldSession.multiSelect && oldSession.multiSelect.editor == this) + oldSession.multiSelect.editor = null; + + session.multiSelect.removeEventListener("addRange", this.$onAddRange); + session.multiSelect.removeEventListener("removeRange", this.$onRemoveRange); + session.multiSelect.removeEventListener("multiSelect", this.$onMultiSelect); + session.multiSelect.removeEventListener("singleSelect", this.$onSingleSelect); + } + + session.multiSelect.on("addRange", this.$onAddRange); + session.multiSelect.on("removeRange", this.$onRemoveRange); + session.multiSelect.on("multiSelect", this.$onMultiSelect); + session.multiSelect.on("singleSelect", this.$onSingleSelect); + + // this.$onSelectionChange = this.onSelectionChange.bind(this); + + if (this.inMultiSelectMode != session.selection.inMultiSelectMode) { + if (session.selection.inMultiSelectMode) + this.$onMultiSelect(); + else + this.$onSingleSelect(); + } +}; + +// MultiSelect(editor) +// adds multiple selection support to the editor +// (note: should be called only once for each editor instance) +function MultiSelect(editor) { + editor.$onAddRange = editor.$onAddRange.bind(editor); + editor.$onRemoveRange = editor.$onRemoveRange.bind(editor); + editor.$onMultiSelect = editor.$onMultiSelect.bind(editor); + editor.$onSingleSelect = editor.$onSingleSelect.bind(editor); + + exports.onSessionChange.call(editor, editor); + editor.on("changeSession", exports.onSessionChange.bind(editor)); + + editor.on("mousedown", onMouseDown); + editor.commands.addCommands(commands.defaultCommands); + + addAltCursorListeners(editor); +} + +function addAltCursorListeners(editor){ + var el = editor.textInput.getElement(); + var altCursor = false; + var contentEl = editor.renderer.content; + event.addListener(el, "keydown", function(e) { + if (e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey)) { + if (!altCursor) { + contentEl.style.cursor = "crosshair"; + altCursor = true; + } + } else if (altCursor) { + contentEl.style.cursor = ""; + } + }); + + event.addListener(el, "keyup", reset); + event.addListener(el, "blur", reset); + function reset() { + if (altCursor) { + contentEl.style.cursor = ""; + altCursor = false; + } + } +} + +exports.MultiSelect = MultiSelect; + +}); + +ace.define('ace/range_list', ['require', 'exports', 'module' ], function(require, exports, module) { + + + +var RangeList = function() { + this.ranges = []; +}; + +(function() { + this.comparePoints = function(p1, p2) { + return p1.row - p2.row || p1.column - p2.column; + }; + + this.pointIndex = function(pos, startIndex) { + var list = this.ranges; + + for (var i = startIndex || 0; i < list.length; i++) { + var range = list[i]; + var cmp = this.comparePoints(pos, range.end); + + if (cmp > 0) + continue; + if (cmp == 0) + return i; + cmp = this.comparePoints(pos, range.start); + if (cmp >= 0) + return i; + + return -i-1; + } + return -i - 1; + }; + + this.add = function(range) { + var startIndex = this.pointIndex(range.start); + if (startIndex < 0) + startIndex = -startIndex - 1; + + var endIndex = this.pointIndex(range.end, startIndex); + + if (endIndex < 0) + endIndex = -endIndex - 1; + else + endIndex++; + + return this.ranges.splice(startIndex, endIndex - startIndex, range); + }; + + this.addList = function(list) { + var removed = []; + for (var i = list.length; i--; ) { + removed.push.call(removed, this.add(list[i])); + } + return removed; + }; + + this.substractPoint = function(pos) { + var i = this.pointIndex(pos); + + if (i >= 0) + return this.ranges.splice(i, 1); + }; + + // merge overlapping ranges + this.merge = function() { + var removed = []; + var list = this.ranges; + var next = list[0], range; + for (var i = 1; i < list.length; i++) { + range = next; + next = list[i]; + var cmp = this.comparePoints(range.end, next.start); + if (cmp < 0) + continue; + + if (cmp == 0 && !(range.isEmpty() || next.isEmpty())) + continue; + + if (this.comparePoints(range.end, next.end) < 0) { + range.end.row = next.end.row; + range.end.column = next.end.column; + } + + list.splice(i, 1); + removed.push(next); + next = range; + i--; + } + + return removed; + }; + + this.contains = function(row, column) { + return this.pointIndex({row: row, column: column}) >= 0; + }; + + this.containsPoint = function(pos) { + return this.pointIndex(pos) >= 0; + }; + + this.rangeAtPoint = function(pos) { + var i = this.pointIndex(pos); + if (i >= 0) + return this.ranges[i]; + }; + + + this.clipRows = function(startRow, endRow) { + var list = this.ranges; + if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow) + return []; + + var startIndex = this.pointIndex({row: startRow, column: 0}); + if (startIndex < 0) + startIndex = -startIndex - 1; + var endIndex = this.pointIndex({row: endRow, column: 0}, startIndex); + if (endIndex < 0) + endIndex = -endIndex - 1; + + var clipped = []; + for (var i = startIndex; i < endIndex; i++) { + clipped.push(list[i]); + } + return clipped; + }; + + this.removeAll = function() { + return this.ranges.splice(0, this.ranges.length); + }; + + this.attach = function(session) { + if (this.session) + this.detach(); + + this.session = session; + this.onChange = this.$onChange.bind(this); + + this.session.on('change', this.onChange); + }; + + this.detach = function() { + if (!this.session) + return; + this.session.removeListener('change', this.onChange); + this.session = null; + }; + + this.$onChange = function(e) { + var changeRange = e.data.range; + if (e.data.action[0] == "i"){ + var start = changeRange.start; + var end = changeRange.end; + } else { + var end = changeRange.start; + var start = changeRange.end; + } + var startRow = start.row; + var endRow = end.row; + var lineDif = endRow - startRow; + + var colDiff = -start.column + end.column; + var ranges = this.ranges; + + for (var i = 0, n = ranges.length; i < n; i++) { + var r = ranges[i]; + if (r.end.row < startRow) + continue; + if (r.start.row > startRow) + break; + + if (r.start.row == startRow && r.start.column >= start.column ) { + r.start.column += colDiff; + r.start.row += lineDif; + } + if (r.end.row == startRow && r.end.column >= start.column) { + r.end.column += colDiff; + r.end.row += lineDif; + } + } + + if (lineDif != 0 && i < n) { + for (; i < n; i++) { + var r = ranges[i]; + r.start.row += lineDif; + r.end.row += lineDif; + } + } + }; + +}).call(RangeList.prototype); + +exports.RangeList = RangeList; +}); + +ace.define('ace/mouse/multi_select_handler', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) { + +var event = require("../lib/event"); + + +// mouse +function isSamePoint(p1, p2) { + return p1.row == p2.row && p1.column == p2.column; +} + +function onMouseDown(e) { + var ev = e.domEvent; + var alt = ev.altKey; + var shift = ev.shiftKey; + var ctrl = e.getAccelKey(); + var button = e.getButton(); + + if (e.editor.inMultiSelectMode && button == 2) { + e.editor.textInput.onContextMenu(e.domEvent); + return; + } + + if (!ctrl && !alt) { + if (button == 0 && e.editor.inMultiSelectMode) + e.editor.exitMultiSelectMode(); + return; + } + + var editor = e.editor; + var selection = editor.selection; + var isMultiSelect = editor.inMultiSelectMode; + var pos = e.getDocumentPosition(); + var cursor = selection.getCursor(); + var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor)); + + + var mouseX = e.x, mouseY = e.y; + var onMouseSelection = function(e) { + mouseX = e.clientX; + mouseY = e.clientY; + }; + + var blockSelect = function() { + var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); + var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column); + + if (isSamePoint(screenCursor, newCursor) + && isSamePoint(cursor, selection.selectionLead)) + return; + screenCursor = newCursor; + + editor.selection.moveCursorToPosition(cursor); + editor.selection.clearSelection(); + editor.renderer.scrollCursorIntoView(); + + editor.removeSelectionMarkers(rectSel); + rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor); + rectSel.forEach(editor.addSelectionMarker, editor); + editor.updateSelectionMarkers(); + }; + + var session = editor.session; + var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); + var screenCursor = screenAnchor; + + + + if (ctrl && !shift && !alt && button == 0) { + if (!isMultiSelect && inSelection) + return; // dragging + + if (!isMultiSelect) { + var range = selection.toOrientedRange(); + editor.addSelectionMarker(range); + } + + var oldRange = selection.rangeList.rangeAtPoint(pos); + + event.capture(editor.container, function(){}, function() { + var tmpSel = selection.toOrientedRange(); + + if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor)) + selection.substractPoint(tmpSel.cursor); + else { + if (range) { + editor.removeSelectionMarker(range); + selection.addRange(range); + } + selection.addRange(tmpSel); + } + }); + + } else if (!shift && alt && button == 0) { + e.stop(); + + if (isMultiSelect && !ctrl) + selection.toSingleRange(); + else if (!isMultiSelect && ctrl) + selection.addRange(); + + selection.moveCursorToPosition(pos); + selection.clearSelection(); + + var rectSel = []; + + var onMouseSelectionEnd = function(e) { + clearInterval(timerId); + editor.removeSelectionMarkers(rectSel); + for (var i = 0; i < rectSel.length; i++) + selection.addRange(rectSel[i]); + }; + + var onSelectionInterval = blockSelect; + + event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); + var timerId = setInterval(function() {onSelectionInterval();}, 20); + + return e.preventDefault(); + } +} + + +exports.onMouseDown = onMouseDown; + +}); + +ace.define('ace/commands/multi_select_commands', ['require', 'exports', 'module' , 'ace/keyboard/hash_handler'], function(require, exports, module) { + +// commands to enter multiselect mode +exports.defaultCommands = [{ + name: "addCursorAbove", + exec: function(editor) { editor.selectMoreLines(-1); }, + bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"}, + readonly: true +}, { + name: "addCursorBelow", + exec: function(editor) { editor.selectMoreLines(1); }, + bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"}, + readonly: true +}, { + name: "addCursorAboveSkipCurrent", + exec: function(editor) { editor.selectMoreLines(-1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"}, + readonly: true +}, { + name: "addCursorBelowSkipCurrent", + exec: function(editor) { editor.selectMoreLines(1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"}, + readonly: true +}, { + name: "selectMoreBefore", + exec: function(editor) { editor.selectMore(-1); }, + bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"}, + readonly: true +}, { + name: "selectMoreAfter", + exec: function(editor) { editor.selectMore(1); }, + bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"}, + readonly: true +}, { + name: "selectNextBefore", + exec: function(editor) { editor.selectMore(-1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"}, + readonly: true +}, { + name: "selectNextAfter", + exec: function(editor) { editor.selectMore(1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"}, + readonly: true +}, { + name: "splitIntoLines", + exec: function(editor) { editor.multiSelect.splitIntoLines(); }, + bindKey: {win: "Ctrl-Shift-L", mac: "Ctrl-Shift-L"}, + readonly: true +}]; + +// commands active in multiselect mode +exports.multiSelectCommands = [{ + name: "singleSelection", + bindKey: "esc", + exec: function(editor) { editor.exitMultiSelectMode(); }, + readonly: true, + isAvailable: function(editor) {return editor && editor.inMultiSelectMode} +}]; + +var HashHandler = require("../keyboard/hash_handler").HashHandler; +exports.keyboardHandler = new HashHandler(exports.multiSelectCommands); + +}); + +ace.define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/config'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var EventEmitter = require("../lib/event_emitter").EventEmitter; +var config = require("../config"); + +var WorkerClient = function(topLevelNamespaces, mod, classname) { + + this.changeListener = this.changeListener.bind(this); + + if (config.get("packaged")) { + this.$worker = new Worker(config.moduleUrl(mod, "worker")); + } + else { + var workerUrl; + if (typeof require.supports !== "undefined" && require.supports.indexOf("ucjs2-pinf-0") >= 0) { + // We are running in the sourcemint loader. + workerUrl = require.nameToUrl("ace/worker/worker_sourcemint"); + } else { + // We are running in RequireJS. + // nameToUrl is renamed to toUrl in requirejs 2 + if (require.nameToUrl && !require.toUrl) + require.toUrl = require.nameToUrl; + workerUrl = this.$normalizePath(require.toUrl("ace/worker/worker", null, "_")); + } + this.$worker = new Worker(workerUrl); + + var tlns = {}; + for (var i=0; i= this.pos.column && range.start.column <= this.pos.column + this.length + 1) { + var distanceFromStart = range.start.column - this.pos.column; + this.length += lengthDiff; + if(!this.session.$fromUndo) { + if(delta.action === "insertText") { + for (var i = this.others.length - 1; i >= 0; i--) { + var otherPos = this.others[i]; + var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; + if(otherPos.row === range.start.row && range.start.column < otherPos.column) + newPos.column += lengthDiff; + this.doc.insert(newPos, delta.text); + } + } else if(delta.action === "removeText") { + for (var i = this.others.length - 1; i >= 0; i--) { + var otherPos = this.others[i]; + var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; + if(otherPos.row === range.start.row && range.start.column < otherPos.column) + newPos.column += lengthDiff; + this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff)); + } + } + // Special case: insert in beginning + if(range.start.column === this.pos.column && delta.action === "insertText") { + setTimeout(function() { + this.pos.setPosition(this.pos.row, this.pos.column - lengthDiff); + for (var i = 0; i < this.others.length; i++) { + var other = this.others[i]; + var newPos = {row: other.row, column: other.column - lengthDiff}; + if(other.row === range.start.row && range.start.column < other.column) + newPos.column += lengthDiff; + other.setPosition(newPos.row, newPos.column); + } + }.bind(this), 0); + } + else if(range.start.column === this.pos.column && delta.action === "removeText") { + setTimeout(function() { + for (var i = 0; i < this.others.length; i++) { + var other = this.others[i]; + if(other.row === range.start.row && range.start.column < other.column) { + other.setPosition(other.row, other.column - lengthDiff); + } + } + }.bind(this), 0); + } + } + this.pos._emit("change", {value: this.pos}); + for (var i = 0; i < this.others.length; i++) { + this.others[i]._emit("change", {value: this.others[i]}); + } + } + this.$updating = false; + }; + + this.onCursorChange = function(event) { + if (this.$updating) return; + var pos = this.session.selection.getCursor(); + if(pos.row === this.pos.row && pos.column >= this.pos.column && pos.column <= this.pos.column + this.length) { + this.showOtherMarkers(); + this._emit("cursorEnter", event); + } else { + this.hideOtherMarkers(); + this._emit("cursorLeave", event); + } + }; + this.detach = function() { + this.session.removeMarker(this.markerId); + this.hideOtherMarkers(); + this.doc.removeEventListener("change", this.$onUpdate); + this.session.selection.removeEventListener("changeCursor", this.$onCursorChange); + this.pos.detach(); + for (var i = 0; i < this.others.length; i++) { + this.others[i].detach(); + } + this.session.setUndoSelect(true); + }; + this.cancel = function() { + if(this.$undoStackDepth === -1) + throw Error("Canceling placeholders only supported with undo manager attached to session."); + var undoManager = this.session.getUndoManager(); + var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth; + for (var i = 0; i < undosRequired; i++) { + undoManager.undo(true); + } + }; +}).call(PlaceHolder.prototype); + + +exports.PlaceHolder = PlaceHolder; +}); + +ace.define('ace/theme/textmate', ['require', 'exports', 'module' , 'ace/requirejs/text!ace/theme/textmate.css', 'ace/lib/dom'], function(require, exports, module) { + + +exports.isDark = false; +exports.cssClass = "ace-tm"; +exports.cssText = require('ace/requirejs/text!./textmate.css'); + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); +ace.define("ace/requirejs/text!ace/theme/textmate.css", [], ".ace-tm .ace_editor {\n\ + border: 2px solid rgb(159, 159, 159);\n\ +}\n\ +\n\ +.ace-tm .ace_editor.ace_focus {\n\ + border: 2px solid #327fbd;\n\ +}\n\ +\n\ +.ace-tm .ace_gutter {\n\ + background: #f0f0f0;\n\ + color: #333;\n\ +}\n\ +\n\ +.ace-tm .ace_print_margin {\n\ + width: 1px;\n\ + background: #e8e8e8;\n\ +}\n\ +\n\ +.ace-tm .ace_fold {\n\ + background-color: #6B72E6;\n\ +}\n\ +\n\ +.ace-tm .ace_text-layer {\n\ +}\n\ +\n\ +.ace-tm .ace_cursor {\n\ + border-left: 2px solid black;\n\ +}\n\ +\n\ +.ace-tm .ace_cursor.ace_overwrite {\n\ + border-left: 0px;\n\ + border-bottom: 1px solid black;\n\ +}\n\ + \n\ +.ace-tm .ace_line .ace_invisible {\n\ + color: rgb(191, 191, 191);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_storage,\n\ +.ace-tm .ace_line .ace_keyword {\n\ + color: blue;\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_constant {\n\ + color: rgb(197, 6, 11);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_constant.ace_buildin {\n\ + color: rgb(88, 72, 246);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_constant.ace_language {\n\ + color: rgb(88, 92, 246);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_constant.ace_library {\n\ + color: rgb(6, 150, 14);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_invalid {\n\ + background-color: rgba(255, 0, 0, 0.1);\n\ + color: red;\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_support.ace_function {\n\ + color: rgb(60, 76, 114);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_support.ace_constant {\n\ + color: rgb(6, 150, 14);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_support.ace_type,\n\ +.ace-tm .ace_line .ace_support.ace_class {\n\ + color: rgb(109, 121, 222);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_keyword.ace_operator {\n\ + color: rgb(104, 118, 135);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_string {\n\ + color: rgb(3, 106, 7);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_comment {\n\ + color: rgb(76, 136, 107);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_comment.ace_doc {\n\ + color: rgb(0, 102, 255);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_comment.ace_doc.ace_tag {\n\ + color: rgb(128, 159, 191);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_constant.ace_numeric {\n\ + color: rgb(0, 0, 205);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_variable {\n\ + color: rgb(49, 132, 149);\n\ +}\n\ +\n\ +.ace-tm .ace_line .ace_xml_pe {\n\ + color: rgb(104, 104, 91);\n\ +}\n\ +\n\ +.ace-tm .ace_entity.ace_name.ace_function {\n\ + color: #0000A2;\n\ +}\n\ +\n\ +.ace-tm .ace_markup.ace_markupine {\n\ + text-decoration:underline;\n\ +}\n\ +\n\ +.ace-tm .ace_markup.ace_heading {\n\ + color: rgb(12, 7, 255);\n\ +}\n\ +\n\ +.ace-tm .ace_markup.ace_list {\n\ + color:rgb(185, 6, 144);\n\ +}\n\ +\n\ +.ace-tm .ace_marker-layer .ace_selection {\n\ + background: rgb(181, 213, 255);\n\ +}\n\ +.ace-tm.multiselect .ace_selection.start {\n\ + box-shadow: 0 0 3px 0px white;\n\ + border-radius: 2px;\n\ +}\n\ +.ace-tm .ace_marker-layer .ace_step {\n\ + background: rgb(252, 255, 0);\n\ +}\n\ +\n\ +.ace-tm .ace_marker-layer .ace_stack {\n\ + background: rgb(164, 229, 101);\n\ +}\n\ +\n\ +.ace-tm .ace_marker-layer .ace_bracket {\n\ + margin: -1px 0 0 -1px;\n\ + border: 1px solid rgb(192, 192, 192);\n\ +}\n\ +\n\ +.ace-tm .ace_marker-layer .ace_active_line {\n\ + background: rgba(0, 0, 0, 0.07);\n\ +}\n\ +\n\ +.ace-tm .ace_gutter_active_line {\n\ + background-color : #dcdcdc;\n\ +}\n\ +\n\ +.ace-tm .ace_marker-layer .ace_selected_word {\n\ + background: rgb(250, 250, 255);\n\ + border: 1px solid rgb(200, 200, 250);\n\ +}\n\ +\n\ +.ace-tm .ace_meta.ace_tag {\n\ + color:rgb(0, 22, 142);\n\ +}\n\ +\n\ +.ace-tm .ace_string.ace_regex {\n\ + color: rgb(255, 0, 0)\n\ +}\n\ +\n\ +.ace-tm .ace_indent-guide {\n\ + background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\n\ +}\n\ +"); + +; + (function() { + ace.require(["ace/ace"], function(a) { + a && a.config.init(); + if (!window.ace) + window.ace = {}; + for (var key in a) if (a.hasOwnProperty(key)) + ace[key] = a[key]; + }); + })(); + \ No newline at end of file diff --git a/lib/client/editor/ace/mode-coffee.js b/lib/client/editor/ace/mode-coffee.js new file mode 100644 index 00000000..e6dc7efd --- /dev/null +++ b/lib/client/editor/ace/mode-coffee.js @@ -0,0 +1,527 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Ajax.org Code Editor (ACE). + * + * The Initial Developer of the Original Code is + * Ajax.org B.V. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Satoshi Murakami + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +ace.define('ace/mode/coffee', ['require', 'exports', 'module' , 'ace/tokenizer', 'ace/mode/coffee_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/mode/folding/coffee', 'ace/range', 'ace/mode/text', 'ace/worker/worker_client', 'ace/lib/oop'], function(require, exports, module) { + + +var Tokenizer = require("../tokenizer").Tokenizer; +var Rules = require("./coffee_highlight_rules").CoffeeHighlightRules; +var Outdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var FoldMode = require("./folding/coffee").FoldMode; +var Range = require("../range").Range; +var TextMode = require("./text").Mode; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var oop = require("../lib/oop"); + +function Mode() { + this.$tokenizer = new Tokenizer(new Rules().getRules()); + this.$outdent = new Outdent(); + this.foldingRules = new FoldMode(); +} + +oop.inherits(Mode, TextMode); + +(function() { + + var indenter = /(?:[({[=:]|[-=]>|\b(?:else|switch|try|catch(?:\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$/; + var commentLine = /^(\s*)#/; + var hereComment = /^\s*###(?!#)/; + var indentation = /^\s*/; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + var tokens = this.$tokenizer.getLineTokens(line, state).tokens; + + if (!(tokens.length && tokens[tokens.length - 1].type === 'comment') && + state === 'start' && indenter.test(line)) + indent += tab; + return indent; + }; + + this.toggleCommentLines = function(state, doc, startRow, endRow){ + console.log("toggle"); + var range = new Range(0, 0, 0, 0); + for (var i = startRow; i <= endRow; ++i) { + var line = doc.getLine(i); + if (hereComment.test(line)) + continue; + + if (commentLine.test(line)) + line = line.replace(commentLine, '$1'); + else + line = line.replace(indentation, '$&#'); + + range.end.row = range.start.row = i; + range.end.column = line.length + 1; + doc.replace(range, line); + } + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/coffee_worker", "Worker"); + worker.attachToDocument(session.getDocument()); + + worker.on("error", function(e) { + session.setAnnotations([e.data]); + }); + + worker.on("ok", function(e) { + session.clearAnnotations(); + }); + + return worker; + }; + +}).call(Mode.prototype); + +exports.Mode = Mode; + +}); + +ace.define('ace/mode/coffee_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) { + + + var lang = require("../lib/lang"); + var oop = require("../lib/oop"); + var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + + oop.inherits(CoffeeHighlightRules, TextHighlightRules); + + function CoffeeHighlightRules() { + var identifier = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*"; + var stringfill = { + token : "string", + merge : true, + regex : ".+" + }; + + var keywords = lang.arrayToMap(( + "this|throw|then|try|typeof|super|switch|return|break|by)|continue|" + + "catch|class|in|instanceof|is|isnt|if|else|extends|for|forown|" + + "finally|function|while|when|new|no|not|delete|debugger|do|loop|of|off|" + + "or|on|unless|until|and|yes").split("|") + ); + + var langConstant = lang.arrayToMap(( + "true|false|null|undefined").split("|") + ); + + var illegal = lang.arrayToMap(( + "case|const|default|function|var|void|with|enum|export|implements|" + + "interface|let|package|private|protected|public|static|yield|" + + "__hasProp|extends|slice|bind|indexOf").split("|") + ); + + var supportClass = lang.arrayToMap(( + "Array|Boolean|Date|Function|Number|Object|RegExp|ReferenceError|" + + "RangeError|String|SyntaxError|Error|EvalError|TypeError|URIError").split("|") + ); + + var supportFunction = lang.arrayToMap(( + "Math|JSON|isNaN|isFinite|parseInt|parseFloat|encodeURI|" + + "encodeURIComponent|decodeURI|decodeURIComponent|RangeError|String|" + + "SyntaxError|Error|EvalError|TypeError|URIError").split("|") + ); + + this.$rules = { + start : [ + { + token : "identifier", + regex : "(?:(?:\\.|::)\\s*)" + identifier + }, { + token : "variable", + regex : "@(?:" + identifier + ")?" + }, { + token: function(value) { + if (keywords.hasOwnProperty(value)) + return "keyword"; + else if (langConstant.hasOwnProperty(value)) + return "constant.language"; + else if (illegal.hasOwnProperty(value)) + return "invalid.illegal"; + else if (supportClass.hasOwnProperty(value)) + return "language.support.class"; + else if (supportFunction.hasOwnProperty(value)) + return "language.support.function"; + else + return "identifier"; + }, + regex : identifier + }, { + token : "constant.numeric", + regex : "(?:0x[\\da-fA-F]+|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][+-]?\\d+)?)" + }, { + token : "string", + merge : true, + regex : "'''", + next : "qdoc" + }, { + token : "string", + merge : true, + regex : '"""', + next : "qqdoc" + }, { + token : "string", + merge : true, + regex : "'", + next : "qstring" + }, { + token : "string", + merge : true, + regex : '"', + next : "qqstring" + }, { + token : "string", + merge : true, + regex : "`", + next : "js" + }, { + token : "string.regex", + merge : true, + regex : "///", + next : "heregex" + }, { + token : "string.regex", + regex : "/(?!\\s)[^[/\\n\\\\]*(?: (?:\\\\.|\\[[^\\]\\n\\\\]*(?:\\\\.[^\\]\\n\\\\]*)*\\])[^[/\\n\\\\]*)*/[imgy]{0,4}(?!\\w)" + }, { + token : "comment", + merge : true, + regex : "###(?!#)", + next : "comment" + }, { + token : "comment", + regex : "#.*" + }, { + token : "punctuation.operator", + regex : "\\?|\\:|\\,|\\." + }, { + token : "keyword.operator", + regex : "(?:[\\-=]>|[-+*/%<>&|^!?=]=|>>>=?|\\-\\-|\\+\\+|::|&&=|\\|\\|=|<<=|>>=|\\?\\.|\\.{2,3}|[!*+-=><])" + }, { + token : "paren.lparen", + regex : "[({[]" + }, { + token : "paren.rparen", + regex : "[\\]})]" + }, { + token : "text", + regex : "\\s+" + }], + + qdoc : [{ + token : "string", + regex : ".*?'''", + next : "start" + }, stringfill], + + qqdoc : [{ + token : "string", + regex : '.*?"""', + next : "start" + }, stringfill], + + qstring : [{ + token : "string", + regex : "[^\\\\']*(?:\\\\.[^\\\\']*)*'", + merge : true, + next : "start" + }, stringfill], + + qqstring : [{ + token : "string", + regex : '[^\\\\"]*(?:\\\\.[^\\\\"]*)*"', + merge : true, + next : "start" + }, stringfill], + + js : [{ + token : "string", + merge : true, + regex : "[^\\\\`]*(?:\\\\.[^\\\\`]*)*`", + next : "start" + }, stringfill], + + heregex : [{ + token : "string.regex", + regex : '.*?///[imgy]{0,4}', + next : "start" + }, { + token : "comment.regex", + regex : "\\s+(?:#.*)?" + }, { + token : "string.regex", + merge : true, + regex : "\\S+" + }], + + comment : [{ + token : "comment", + regex : '.*?###', + next : "start" + }, { + token : "comment", + merge : true, + regex : ".+" + }] + }; + } + + exports.CoffeeHighlightRules = CoffeeHighlightRules; +}); + +ace.define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) { + + +var Range = require("../range").Range; + +var MatchingBraceOutdent = function() {}; + +(function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + var match = line.match(/^(\s+)/); + if (match) { + return match[1]; + } + + return ""; + }; + +}).call(MatchingBraceOutdent.prototype); + +exports.MatchingBraceOutdent = MatchingBraceOutdent; +}); + +ace.define('ace/mode/folding/coffee', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/folding/fold_mode', 'ace/range'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var BaseFoldMode = require("./fold_mode").FoldMode; +var Range = require("../../range").Range; + +var FoldMode = exports.FoldMode = function() {}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var range = this.indentationBlock(session, row); + if (range) + return range; + + var re = /\S/; + var line = session.getLine(row); + var startLevel = line.search(re); + if (startLevel == -1 || line[startLevel] != "#") + return; + + var startColumn = line.length; + var maxRow = session.getLength(); + var startRow = row; + var endRow = row; + + while (++row < maxRow) { + line = session.getLine(row); + var level = line.search(re); + + if (level == -1) + continue; + + if (line[level] != "#") + break; + + endRow = row; + } + + if (endRow > startRow) { + var endColumn = session.getLine(endRow).length; + return new Range(startRow, startColumn, endRow, endColumn); + } + }; + + // must return "" if there's no fold, to enable caching + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + var indent = line.search(/\S/); + var next = session.getLine(row + 1); + var prev = session.getLine(row - 1); + var prevIndent = prev.search(/\S/); + var nextIndent = next.search(/\S/); + + if (indent == -1) { + session.foldWidgets[row - 1] = prevIndent!= -1 && prevIndent < nextIndent ? "start" : ""; + return ""; + } + + // documentation comments + if (prevIndent == -1) { + if (indent == nextIndent && line[indent] == "#" && next[indent] == "#") { + session.foldWidgets[row - 1] = ""; + session.foldWidgets[row + 1] = ""; + return "start"; + } + } else if (prevIndent == indent && line[indent] == "#" && prev[indent] == "#") { + if (session.getLine(row - 2).search(/\S/) == -1) { + session.foldWidgets[row - 1] = "start"; + session.foldWidgets[row + 1] = ""; + return ""; + } + } + + if (prevIndent!= -1 && prevIndent < indent) + session.foldWidgets[row - 1] = "start"; + else + session.foldWidgets[row - 1] = ""; + + if (indent < nextIndent) + return "start"; + else + return ""; + }; + +}).call(FoldMode.prototype); + +}); + +ace.define('ace/mode/folding/fold_mode', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) { + + +var Range = require("../../range").Range; + +var FoldMode = exports.FoldMode = function() {}; + +(function() { + + this.foldingStartMarker = null; + this.foldingStopMarker = null; + + // must return "" if there's no fold, to enable caching + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + if (this.foldingStartMarker.test(line)) + return "start"; + if (foldStyle == "markbeginend" + && this.foldingStopMarker + && this.foldingStopMarker.test(line)) + return "end"; + return ""; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + return null; + }; + + this.indentationBlock = function(session, row, column) { + var re = /\S/; + var line = session.getLine(row); + var startLevel = line.search(re); + if (startLevel == -1) + return; + + var startColumn = column || line.length; + var maxRow = session.getLength(); + var startRow = row; + var endRow = row; + + while (++row < maxRow) { + var level = session.getLine(row).search(re); + + if (level == -1) + continue; + + if (level <= startLevel) + break; + + endRow = row; + } + + if (endRow > startRow) { + var endColumn = session.getLine(endRow).length; + return new Range(startRow, startColumn, endRow, endColumn); + } + }; + + this.openingBracketBlock = function(session, bracket, row, column, typeRe) { + var start = {row: row, column: column + 1}; + var end = session.$findClosingBracket(bracket, start, typeRe); + if (!end) + return; + + var fw = session.foldWidgets[end.row]; + if (fw == null) + fw = this.getFoldWidget(session, end.row); + + if (fw == "start" && end.row > start.row) { + end.row --; + end.column = session.getLine(end.row).length; + } + return Range.fromPoints(start, end); + }; + +}).call(FoldMode.prototype); + +}); diff --git a/lib/client/editor/ace/mode-javascript.js b/lib/client/editor/ace/mode-javascript.js new file mode 100644 index 00000000..996e9180 --- /dev/null +++ b/lib/client/editor/ace/mode-javascript.js @@ -0,0 +1,1069 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Ajax.org Code Editor (ACE). + * + * The Initial Developer of the Original Code is + * Ajax.org B.V. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Fabian Jakobs + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +ace.define('ace/mode/javascript', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/javascript_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/range', 'ace/worker/worker_client', 'ace/mode/behaviour/cstyle', 'ace/mode/folding/cstyle'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; +var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var Range = require("../range").Range; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.$tokenizer = new Tokenizer(new JavaScriptHighlightRules().getRules()); + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + + this.toggleCommentLines = function(state, doc, startRow, endRow) { + var outdent = true; + var re = /^(\s*)\/\//; + + for (var i=startRow; i<= endRow; i++) { + if (!re.test(doc.getLine(i))) { + outdent = false; + break; + } + } + + if (outdent) { + var deleteRange = new Range(0, 0, 0, 0); + for (var i=startRow; i<= endRow; i++) + { + var line = doc.getLine(i); + var m = line.match(re); + deleteRange.start.row = i; + deleteRange.end.row = i; + deleteRange.end.column = m[0].length; + doc.replace(deleteRange, m[1]); + } + } + else { + doc.indentRows(startRow, endRow, "//"); + } + }; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.$tokenizer.getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + var endState = tokenizedLine.state; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start" || state == "regex_allowed") { + var match = line.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/); + if (match) { + indent += tab; + } + } else if (state == "doc-start") { + if (endState == "start" || state == "regex_allowed") { + return ""; + } + var match = line.match(/^\s*(\/?)\*/); + if (match) { + if (match[1]) { + indent += " "; + } + indent += "* "; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker"); + worker.attachToDocument(session.getDocument()); + + worker.on("jslint", function(results) { + var errors = []; + for (var i=0; i the first match is used + + this.$rules = { + "start" : [ + { + token : "comment", + regex : /\/\/.*$/ + }, + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + merge : true, + regex : /\/\*/, + next : "comment" + }, { + token : "string", + regex : "'(?=.)", + next : "qstring" + }, { + token : "string", + regex : '"(?=.)', + next : "qqstring" + }, { + token : "constant.numeric", // hex + regex : /0[xX][0-9a-fA-F]+\b/ + }, { + token : "constant.numeric", // float + regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/ + }, { // match stuff like: Sound.prototype.play = function() { } + token : [ + "storage.type", + "punctuation.operator", + "support.function", + "punctuation.operator", + "entity.name.function", + "text", + "keyword.operator", + "text", + "storage.type", + "text", + "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { // match stuff like: Sound.prototype.play = myfunc + token : [ + "storage.type", + "punctuation.operator", + "support.function", + "punctuation.operator", + "entity.name.function", + "text", + "keyword.operator", + "text" + ], + regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)", + next: "function_arguments" + }, { // match stuff like: Sound.play = function() { } + token : [ + "storage.type", + "punctuation.operator", + "entity.name.function", + "text", + "keyword.operator", + "text", + "storage.type", + "text", + "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { // match stuff like: play = function() { } + token : [ + "entity.name.function", + "text", + "keyword.operator", + "text", + "storage.type", + "text", + "paren.lparen" + ], + regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { // match stuff like: Sound.play = function play() { } + token : [ + "storage.type", + "punctuation.operator", + "entity.name.function", + "text", + "keyword.operator", + "text", + "storage.type", + "text", + "entity.name.function", + "text", + "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()", + next: "function_arguments" + }, { // match regular function like: function myFunc(arg) { } + token : [ + "storage.type", + "text", + "entity.name.function", + "text", + "paren.lparen" + ], + regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()", + next: "function_arguments" + }, { // match stuff like: foobar: function() { } + token : [ + "entity.name.function", + "text", + "punctuation.operator", + "text", + "storage.type", + "text", + "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { // Attempt to match : function() { } (this is for issues with 'foo': function() { }) + token : [ + "text", + "text", + "storage.type", + "text", + "paren.lparen" + ], + regex : "(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : "constant.language.boolean", + regex : /(?:true|false)\b/ + }, { + token : "keyword", + regex : "(?:" + kwBeforeRe + ")\\b", + next : "regex_allowed" + }, { + token : ["punctuation.operator", "support.function"], + regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/ + }, { + token : ["punctuation.operator", "support.function.dom"], + regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/ + }, { + token : ["punctuation.operator", "support.constant"], + regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/ + }, { + token : ["storage.type", "punctuation.operator", "support.function.firebug"], + regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/ + }, { + token : function(value) { + if (globals.hasOwnProperty(value)) + return "variable.language"; + else if (deprecated.hasOwnProperty(value)) + return "invalid.deprecated"; + else if (definitions.hasOwnProperty(value)) + return "storage.type"; + else if (keywords.hasOwnProperty(value)) + return "keyword"; + else if (buildinConstants.hasOwnProperty(value)) + return "constant.language"; + else if (futureReserved.hasOwnProperty(value)) + return "invalid.illegal"; + else if (value == "debugger") + return "invalid.deprecated"; + else + return "identifier"; + }, + regex : identifierRe + }, { + token : "keyword.operator", + regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/, + next : "regex_allowed" + }, { + token : "punctuation.operator", + regex : /\?|\:|\,|\;|\./, + next : "regex_allowed" + }, { + token : "paren.lparen", + regex : /[\[({]/, + next : "regex_allowed" + }, { + token : "paren.rparen", + regex : /[\])}]/ + }, { + token : "keyword.operator", + regex : /\/=?/, + next : "regex_allowed" + }, { + token: "comment", + regex: /^#!.*$/ + }, { + token : "text", + regex : /\s+/ + } + ], + // regular expressions are only allowed after certain tokens. This + // makes sure we don't mix up regexps with the divison operator + "regex_allowed": [ + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + merge : true, + regex : "\\/\\*", + next : "comment_regex_allowed" + }, { + token : "comment", + regex : "\\/\\/.*$" + }, { + token: "string.regexp", + regex: "\\/", + next: "regex", + merge: true + }, { + token : "text", + regex : "\\s+" + }, { + // immediately return to the start mode without matching + // anything + token: "empty", + regex: "", + next: "start" + } + ], + "regex": [ + { + token: "regexp.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + // flag + token: "string.regexp", + regex: "/\\w*", + next: "start", + merge: true + }, { + token: "string.regexp", + regex: "[^\\\\/\\[]+", + merge: true + }, { + token: "string.regexp.charachterclass", + regex: "\\[", + next: "regex_character_class", + merge: true + }, { + token: "empty", + regex: "", + next: "start" + } + ], + "regex_character_class": [ + { + token: "regexp.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + token: "string.regexp.charachterclass", + regex: "]", + next: "regex", + merge: true + }, { + token: "string.regexp.charachterclass", + regex: "[^\\\\\\]]+", + merge: true + }, { + token: "empty", + regex: "", + next: "start" + } + ], + "function_arguments": [ + { + token: "variable.parameter", + regex: identifierRe + }, { + token: "punctuation.operator", + regex: "[, ]+", + merge: true + }, { + token: "punctuation.operator", + regex: "$", + merge: true + }, { + token: "empty", + regex: "", + next: "start" + } + ], + "comment_regex_allowed" : [ + { + token : "comment", // closing comment + regex : ".*?\\*\\/", + merge : true, + next : "regex_allowed" + }, { + token : "comment", // comment spanning whole line + merge : true, + regex : ".+" + } + ], + "comment" : [ + { + token : "comment", // closing comment + regex : ".*?\\*\\/", + merge : true, + next : "start" + }, { + token : "comment", // comment spanning whole line + merge : true, + regex : ".+" + } + ], + "qqstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : '[^"\\\\]+', + merge : true + }, { + token : "string", + regex : "\\\\$", + next : "qqstring", + merge : true + }, { + token : "string", + regex : '"|$', + next : "start", + merge : true + } + ], + "qstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : "[^'\\\\]+", + merge : true + }, { + token : "string", + regex : "\\\\$", + next : "qstring", + merge : true + }, { + token : "string", + regex : "'|$", + next : "start", + merge : true + } + ] + }; + + this.embedRules(DocCommentHighlightRules, "doc-", + [ DocCommentHighlightRules.getEndRule("start") ]); +}; + +oop.inherits(JavaScriptHighlightRules, TextHighlightRules); + +exports.JavaScriptHighlightRules = JavaScriptHighlightRules; +}); + +ace.define('ace/mode/doc_comment_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var DocCommentHighlightRules = function() { + + this.$rules = { + "start" : [ { + token : "comment.doc.tag", + regex : "@[\\w\\d_]+" // TODO: fix email addresses + }, { + token : "comment.doc", + merge : true, + regex : "\\s+" + }, { + token : "comment.doc", + merge : true, + regex : "TODO" + }, { + token : "comment.doc", + merge : true, + regex : "[^@\\*]+" + }, { + token : "comment.doc", + merge : true, + regex : "." + }] + }; +}; + +oop.inherits(DocCommentHighlightRules, TextHighlightRules); + +DocCommentHighlightRules.getStartRule = function(start) { + return { + token : "comment.doc", // doc comment + merge : true, + regex : "\\/\\*(?=\\*)", + next : start + }; +}; + +DocCommentHighlightRules.getEndRule = function (start) { + return { + token : "comment.doc", // closing comment + merge : true, + regex : "\\*\\/", + next : start + }; +}; + + +exports.DocCommentHighlightRules = DocCommentHighlightRules; + +}); + +ace.define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) { + + +var Range = require("../range").Range; + +var MatchingBraceOutdent = function() {}; + +(function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + var match = line.match(/^(\s+)/); + if (match) { + return match[1]; + } + + return ""; + }; + +}).call(MatchingBraceOutdent.prototype); + +exports.MatchingBraceOutdent = MatchingBraceOutdent; +}); + +ace.define('ace/mode/behaviour/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; + +var CstyleBehaviour = function () { + + this.add("braces", "insertion", function (state, action, editor, session, text) { + if (text == '{') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return { + text: '{' + selected + '}', + selection: false + }; + } else { + return { + text: '{}', + selection: [1, 1] + }; + } + } else if (text == '}') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null) { + return { + text: '', + selection: [1, 1] + }; + } + } + } else if (text == "\n") { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column + 1}); + if (!openBracePos) + return null; + + var indent = this.getNextLineIndent(state, line.substring(0, line.length - 1), session.getTabString()); + var next_indent = this.$getIndent(session.doc.getLine(openBracePos.row)); + + return { + text: '\n' + indent + '\n' + next_indent, + selection: [1, indent.length, 1, indent.length] + }; + } + } + }); + + this.add("braces", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar == '}') { + range.end.column++; + return range; + } + } + }); + + this.add("parens", "insertion", function (state, action, editor, session, text) { + if (text == '(') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return { + text: '(' + selected + ')', + selection: false + }; + } else { + return { + text: '()', + selection: [1, 1] + }; + } + } else if (text == ')') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ')') { + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null) { + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("parens", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ')') { + range.end.column++; + return range; + } + } + }); + + this.add("brackets", "insertion", function (state, action, editor, session, text) { + if (text == '[') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return { + text: '[' + selected + ']', + selection: false + }; + } else { + return { + text: '[]', + selection: [1, 1] + }; + } + } else if (text == ']') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ']') { + var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null) { + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("brackets", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '[') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ']') { + range.end.column++; + return range; + } + } + }); + + this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { + if (text == '"' || text == "'") { + var quote = text; + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return { + text: quote + selected + quote, + selection: false + }; + } else { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + + // We're escaped. + if (leftChar == '\\') { + return null; + } + + // Find what token we're inside. + var tokens = session.getTokens(selection.start.row); + var col = 0, token; + var quotepos = -1; // Track whether we're inside an open quote. + + for (var x = 0; x < tokens.length; x++) { + token = tokens[x]; + if (token.type == "string") { + quotepos = -1; + } else if (quotepos < 0) { + quotepos = token.value.indexOf(quote); + } + if ((token.value.length + col) > selection.start.column) { + break; + } + col += tokens[x].value.length; + } + + // Try and be smart about when we auto insert. + if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) { + return { + text: quote + quote, + selection: [1,1] + }; + } else if (token && token.type === "string") { + // Ignore input and move right one if we're typing over the closing quote. + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == quote) { + return { + text: '', + selection: [1, 1] + }; + } + } + } + } + }); + + this.add("string_dquotes", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == '"') { + range.end.column++; + return range; + } + } + }); + +}; + +oop.inherits(CstyleBehaviour, Behaviour); + +exports.CstyleBehaviour = CstyleBehaviour; +}); + +ace.define('ace/mode/folding/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/range', 'ace/mode/folding/fold_mode'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var Range = require("../../range").Range; +var BaseFoldMode = require("./fold_mode").FoldMode; + +var FoldMode = exports.FoldMode = function() {}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var line = session.getLine(row); + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + + if (match[1]) + return this.openingBracketBlock(session, match[1], row, i); + + var range = session.getCommentFoldRange(row, i + match[0].length); + range.end.column -= 2; + return range; + } + + if (foldStyle !== "markbeginend") + return; + + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + + if (match[2]) { + var range = session.getCommentFoldRange(row, i); + range.end.column -= 2; + return range; + } + + var end = {row: row, column: i}; + var start = session.$findOpeningBracket(match[1], end); + + if (!start) + return; + + start.column++; + end.column--; + + return Range.fromPoints(start, end); + } + }; + +}).call(FoldMode.prototype); + +}); + +ace.define('ace/mode/folding/fold_mode', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) { + + +var Range = require("../../range").Range; + +var FoldMode = exports.FoldMode = function() {}; + +(function() { + + this.foldingStartMarker = null; + this.foldingStopMarker = null; + + // must return "" if there's no fold, to enable caching + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + if (this.foldingStartMarker.test(line)) + return "start"; + if (foldStyle == "markbeginend" + && this.foldingStopMarker + && this.foldingStopMarker.test(line)) + return "end"; + return ""; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + return null; + }; + + this.indentationBlock = function(session, row, column) { + var re = /\S/; + var line = session.getLine(row); + var startLevel = line.search(re); + if (startLevel == -1) + return; + + var startColumn = column || line.length; + var maxRow = session.getLength(); + var startRow = row; + var endRow = row; + + while (++row < maxRow) { + var level = session.getLine(row).search(re); + + if (level == -1) + continue; + + if (level <= startLevel) + break; + + endRow = row; + } + + if (endRow > startRow) { + var endColumn = session.getLine(endRow).length; + return new Range(startRow, startColumn, endRow, endColumn); + } + }; + + this.openingBracketBlock = function(session, bracket, row, column, typeRe) { + var start = {row: row, column: column + 1}; + var end = session.$findClosingBracket(bracket, start, typeRe); + if (!end) + return; + + var fw = session.foldWidgets[end.row]; + if (fw == null) + fw = this.getFoldWidget(session, end.row); + + if (fw == "start" && end.row > start.row) { + end.row --; + end.column = session.getLine(end.row).length; + } + return Range.fromPoints(start, end); + }; + +}).call(FoldMode.prototype); + +}); diff --git a/lib/client/editor/ace/mode-json.js b/lib/client/editor/ace/mode-json.js new file mode 100644 index 00000000..89badd66 --- /dev/null +++ b/lib/client/editor/ace/mode-json.js @@ -0,0 +1,588 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Ajax.org Code Editor (ACE). + * + * The Initial Developer of the Original Code is + * Ajax.org B.V. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Fabian Jakobs + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +ace.define('ace/mode/json', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/json_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/mode/behaviour/cstyle', 'ace/mode/folding/cstyle', 'ace/worker/worker_client'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; +var HighlightRules = require("./json_highlight_rules").JsonHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; +var WorkerClient = require("../worker/worker_client").WorkerClient; + +var Mode = function() { + this.$tokenizer = new Tokenizer(new HighlightRules().getRules()); + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + if (state == "start") { + var match = line.match(/^.*[\{\(\[]\s*$/); + if (match) { + indent += tab; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/json_worker", "JsonWorker"); + worker.attachToDocument(session.getDocument()); + + worker.on("error", function(e) { + session.setAnnotations([e.data]); + }); + + worker.on("ok", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + +}).call(Mode.prototype); + +exports.Mode = Mode; +}); + +ace.define('ace/mode/json_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var JsonHighlightRules = function() { + + // regexp must not have capturing parentheses. Use (?:) instead. + // regexps are ordered -> the first match is used + this.$rules = { + "start" : [ + { + token : "variable", // single line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)' + }, { + token : "string", // single line + regex : '"', + next : "string" + }, { + token : "constant.numeric", // hex + regex : "0[xX][0-9a-fA-F]+\\b" + }, { + token : "constant.numeric", // float + regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b" + }, { + token : "constant.language.boolean", + regex : "(?:true|false)\\b" + }, { + token : "invalid.illegal", // single quoted strings are not allowed + regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" + }, { + token : "invalid.illegal", // comments are not allowed + regex : "\\/\\/.*$" + }, { + token : "paren.lparen", + regex : "[[({]" + }, { + token : "paren.rparen", + regex : "[\\])}]" + }, { + token : "text", + regex : "\\s+" + } + ], + "string" : [ + { + token : "constant.language.escape", + regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/ + }, { + token : "string", + regex : '[^"\\\\]+', + merge : true + }, { + token : "string", + regex : '"', + next : "start", + merge : true + }, { + token : "string", + regex : "", + next : "start", + merge : true + } + ] + }; + +}; + +oop.inherits(JsonHighlightRules, TextHighlightRules); + +exports.JsonHighlightRules = JsonHighlightRules; +}); + +ace.define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) { + + +var Range = require("../range").Range; + +var MatchingBraceOutdent = function() {}; + +(function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + var match = line.match(/^(\s+)/); + if (match) { + return match[1]; + } + + return ""; + }; + +}).call(MatchingBraceOutdent.prototype); + +exports.MatchingBraceOutdent = MatchingBraceOutdent; +}); + +ace.define('ace/mode/behaviour/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; + +var CstyleBehaviour = function () { + + this.add("braces", "insertion", function (state, action, editor, session, text) { + if (text == '{') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return { + text: '{' + selected + '}', + selection: false + }; + } else { + return { + text: '{}', + selection: [1, 1] + }; + } + } else if (text == '}') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null) { + return { + text: '', + selection: [1, 1] + }; + } + } + } else if (text == "\n") { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column + 1}); + if (!openBracePos) + return null; + + var indent = this.getNextLineIndent(state, line.substring(0, line.length - 1), session.getTabString()); + var next_indent = this.$getIndent(session.doc.getLine(openBracePos.row)); + + return { + text: '\n' + indent + '\n' + next_indent, + selection: [1, indent.length, 1, indent.length] + }; + } + } + }); + + this.add("braces", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar == '}') { + range.end.column++; + return range; + } + } + }); + + this.add("parens", "insertion", function (state, action, editor, session, text) { + if (text == '(') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return { + text: '(' + selected + ')', + selection: false + }; + } else { + return { + text: '()', + selection: [1, 1] + }; + } + } else if (text == ')') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ')') { + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null) { + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("parens", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ')') { + range.end.column++; + return range; + } + } + }); + + this.add("brackets", "insertion", function (state, action, editor, session, text) { + if (text == '[') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return { + text: '[' + selected + ']', + selection: false + }; + } else { + return { + text: '[]', + selection: [1, 1] + }; + } + } else if (text == ']') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ']') { + var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null) { + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("brackets", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '[') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ']') { + range.end.column++; + return range; + } + } + }); + + this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { + if (text == '"' || text == "'") { + var quote = text; + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return { + text: quote + selected + quote, + selection: false + }; + } else { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + + // We're escaped. + if (leftChar == '\\') { + return null; + } + + // Find what token we're inside. + var tokens = session.getTokens(selection.start.row); + var col = 0, token; + var quotepos = -1; // Track whether we're inside an open quote. + + for (var x = 0; x < tokens.length; x++) { + token = tokens[x]; + if (token.type == "string") { + quotepos = -1; + } else if (quotepos < 0) { + quotepos = token.value.indexOf(quote); + } + if ((token.value.length + col) > selection.start.column) { + break; + } + col += tokens[x].value.length; + } + + // Try and be smart about when we auto insert. + if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) { + return { + text: quote + quote, + selection: [1,1] + }; + } else if (token && token.type === "string") { + // Ignore input and move right one if we're typing over the closing quote. + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == quote) { + return { + text: '', + selection: [1, 1] + }; + } + } + } + } + }); + + this.add("string_dquotes", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == '"') { + range.end.column++; + return range; + } + } + }); + +}; + +oop.inherits(CstyleBehaviour, Behaviour); + +exports.CstyleBehaviour = CstyleBehaviour; +}); + +ace.define('ace/mode/folding/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/range', 'ace/mode/folding/fold_mode'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var Range = require("../../range").Range; +var BaseFoldMode = require("./fold_mode").FoldMode; + +var FoldMode = exports.FoldMode = function() {}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var line = session.getLine(row); + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + + if (match[1]) + return this.openingBracketBlock(session, match[1], row, i); + + var range = session.getCommentFoldRange(row, i + match[0].length); + range.end.column -= 2; + return range; + } + + if (foldStyle !== "markbeginend") + return; + + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + + if (match[2]) { + var range = session.getCommentFoldRange(row, i); + range.end.column -= 2; + return range; + } + + var end = {row: row, column: i}; + var start = session.$findOpeningBracket(match[1], end); + + if (!start) + return; + + start.column++; + end.column--; + + return Range.fromPoints(start, end); + } + }; + +}).call(FoldMode.prototype); + +}); + +ace.define('ace/mode/folding/fold_mode', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) { + + +var Range = require("../../range").Range; + +var FoldMode = exports.FoldMode = function() {}; + +(function() { + + this.foldingStartMarker = null; + this.foldingStopMarker = null; + + // must return "" if there's no fold, to enable caching + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + if (this.foldingStartMarker.test(line)) + return "start"; + if (foldStyle == "markbeginend" + && this.foldingStopMarker + && this.foldingStopMarker.test(line)) + return "end"; + return ""; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + return null; + }; + + this.indentationBlock = function(session, row, column) { + var re = /\S/; + var line = session.getLine(row); + var startLevel = line.search(re); + if (startLevel == -1) + return; + + var startColumn = column || line.length; + var maxRow = session.getLength(); + var startRow = row; + var endRow = row; + + while (++row < maxRow) { + var level = session.getLine(row).search(re); + + if (level == -1) + continue; + + if (level <= startLevel) + break; + + endRow = row; + } + + if (endRow > startRow) { + var endColumn = session.getLine(endRow).length; + return new Range(startRow, startColumn, endRow, endColumn); + } + }; + + this.openingBracketBlock = function(session, bracket, row, column, typeRe) { + var start = {row: row, column: column + 1}; + var end = session.$findClosingBracket(bracket, start, typeRe); + if (!end) + return; + + var fw = session.foldWidgets[end.row]; + if (fw == null) + fw = this.getFoldWidget(session, end.row); + + if (fw == "start" && end.row > start.row) { + end.row --; + end.column = session.getLine(end.row).length; + } + return Range.fromPoints(start, end); + }; + +}).call(FoldMode.prototype); + +}); diff --git a/lib/client/editor/ace/theme-monokai.js b/lib/client/editor/ace/theme-monokai.js new file mode 100644 index 00000000..c2f35a93 --- /dev/null +++ b/lib/client/editor/ace/theme-monokai.js @@ -0,0 +1,194 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Ajax.org Code Editor (ACE). + * + * The Initial Developer of the Original Code is + * Ajax.org B.V. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Fabian Jakobs + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +ace.define('ace/theme/monokai', ['require', 'exports', 'module', 'ace/lib/dom'], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-monokai"; +exports.cssText = "\ +.ace-monokai .ace_editor {\ + border: 2px solid rgb(159, 159, 159);\ +}\ +\ +.ace-monokai .ace_editor.ace_focus {\ + border: 2px solid #327fbd;\ +}\ +\ +.ace-monokai .ace_gutter {\ + background: #2f3129;\ + color: #f1f1f1;\ +}\ +\ +.ace-monokai .ace_print_margin {\ + width: 1px;\ + background: #555651;\ +}\ +\ +.ace-monokai .ace_scroller {\ + background-color: #272822;\ +}\ +\ +.ace-monokai .ace_text-layer {\ + color: #F8F8F2;\ +}\ +\ +.ace-monokai .ace_cursor {\ + border-left: 2px solid #F8F8F0;\ +}\ +\ +.ace-monokai .ace_cursor.ace_overwrite {\ + border-left: 0px;\ + border-bottom: 1px solid #F8F8F0;\ +}\ +\ +.ace-monokai .ace_marker-layer .ace_selection {\ + background: #49483E;\ +}\ +\ +.ace-monokai.multiselect .ace_selection.start {\ + box-shadow: 0 0 3px 0px #272822;\ + border-radius: 2px;\ +}\ +\ +.ace-monokai .ace_marker-layer .ace_step {\ + background: rgb(102, 82, 0);\ +}\ +\ +.ace-monokai .ace_marker-layer .ace_bracket {\ + margin: -1px 0 0 -1px;\ + border: 1px solid #49483E;\ +}\ +\ +.ace-monokai .ace_marker-layer .ace_active_line {\ + background: #49483E;\ +}\ +.ace-monokai .ace_gutter_active_line {\ + background-color: #191916;\ +}\ +\ +.ace-monokai .ace_marker-layer .ace_selected_word {\ + border: 1px solid #49483E;\ +}\ +\ +.ace-monokai .ace_invisible {\ + color: #49483E;\ +}\ +\ +.ace-monokai .ace_keyword, .ace-monokai .ace_meta {\ + color:#F92672;\ +}\ +\ +.ace-monokai .ace_constant.ace_language {\ + color:#AE81FF;\ +}\ +\ +.ace-monokai .ace_constant.ace_numeric {\ + color:#AE81FF;\ +}\ +\ +.ace-monokai .ace_constant.ace_other {\ + color:#AE81FF;\ +}\ +\ +.ace-monokai .ace_invalid {\ + color:#F8F8F0;\ +background-color:#F92672;\ +}\ +\ +.ace-monokai .ace_invalid.ace_deprecated {\ + color:#F8F8F0;\ +background-color:#AE81FF;\ +}\ +\ +.ace-monokai .ace_support.ace_constant {\ + color:#66D9EF;\ +}\ +\ +.ace-monokai .ace_fold {\ + background-color: #A6E22E;\ + border-color: #F8F8F2;\ +}\ +\ +.ace-monokai .ace_support.ace_function {\ + color:#66D9EF;\ +}\ +\ +.ace-monokai .ace_storage {\ + color:#F92672;\ +}\ +\ +.ace-monokai .ace_storage.ace_type, .ace-monokai .ace_support.ace_type{\ + font-style:italic;\ +color:#66D9EF;\ +}\ +\ +.ace-monokai .ace_variable {\ + color:#A6E22E;\ +}\ +\ +.ace-monokai .ace_variable.ace_parameter {\ + font-style:italic;\ +color:#FD971F;\ +}\ +\ +.ace-monokai .ace_string {\ + color:#E6DB74;\ +}\ +\ +.ace-monokai .ace_comment {\ + color:#75715E;\ +}\ +\ +.ace-monokai .ace_entity.ace_other.ace_attribute-name {\ + color:#A6E22E;\ +}\ +\ +.ace-monokai .ace_entity.ace_name.ace_function {\ + color:#A6E22E;\ +}\ +\ +.ace-monokai .ace_markup.ace_underline {\ + text-decoration:underline;\ +}\ +\ +.ace-monokai .ace_indent-guide {\ + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNQ11D6z7Bq1ar/ABCKBG6g04U2AAAAAElFTkSuQmCC) right repeat-y;\ +}"; + + var dom = require("../lib/dom"); + dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/lib/client/editor/ace/theme-tomorrow_night_blue.js b/lib/client/editor/ace/theme-tomorrow_night_blue.js new file mode 100644 index 00000000..bbd31be1 --- /dev/null +++ b/lib/client/editor/ace/theme-tomorrow_night_blue.js @@ -0,0 +1,213 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Ajax.org Code Editor (ACE). + * + * The Initial Developer of the Original Code is + * Ajax.org B.V. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Fabian Jakobs + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +ace.define('ace/theme/tomorrow_night_blue', ['require', 'exports', 'module', 'ace/lib/dom'], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-tomorrow-night-blue"; +exports.cssText = "\ +.ace-tomorrow-night-blue .ace_editor {\ + border: 2px solid rgb(159, 159, 159);\ +}\ +\ +.ace-tomorrow-night-blue .ace_editor.ace_focus {\ + border: 2px solid #327fbd;\ +}\ +\ +.ace-tomorrow-night-blue .ace_gutter {\ + background: #00204b;\ + color: #7388b5;\ +}\ +\ +.ace-tomorrow-night-blue .ace_print_margin {\ + width: 1px;\ + background: #00204b;\ +}\ +\ +.ace-tomorrow-night-blue .ace_scroller {\ + background-color: #002451;\ +}\ +\ +.ace-tomorrow-night-blue .ace_text-layer {\ + color: #FFFFFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_cursor {\ + border-left: 2px solid #FFFFFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_cursor.ace_overwrite {\ + border-left: 0px;\ + border-bottom: 1px solid #FFFFFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_marker-layer .ace_selection {\ + background: #003F8E;\ +}\ +\ +.ace-tomorrow-night-blue.multiselect .ace_selection.start {\ + box-shadow: 0 0 3px 0px #002451;\ + border-radius: 2px;\ +}\ +\ +.ace-tomorrow-night-blue .ace_marker-layer .ace_step {\ + background: rgb(127, 111, 19);\ +}\ +\ +.ace-tomorrow-night-blue .ace_marker-layer .ace_bracket {\ + margin: -1px 0 0 -1px;\ + border: 1px solid #404F7D;\ +}\ +\ +.ace-tomorrow-night-blue .ace_marker-layer .ace_active_line {\ + background: #00346E;\ +}\ +\ +.ace-tomorrow-night-blue .ace_gutter_active_line {\ + background-color: #022040;\ +}\ +\ +.ace-tomorrow-night-blue .ace_marker-layer .ace_selected_word {\ + border: 1px solid #003F8E;\ +}\ +\ +.ace-tomorrow-night-blue .ace_invisible {\ + color: #404F7D;\ +}\ +\ +.ace-tomorrow-night-blue .ace_keyword, .ace-tomorrow-night-blue .ace_meta {\ + color:#EBBBFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_keyword.ace_operator {\ + color:#99FFFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_constant.ace_language {\ + color:#FFC58F;\ +}\ +\ +.ace-tomorrow-night-blue .ace_constant.ace_numeric {\ + color:#FFC58F;\ +}\ +\ +.ace-tomorrow-night-blue .ace_constant.ace_other {\ + color:#FFFFFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_invalid {\ + color:#FFFFFF;\ +background-color:#F99DA5;\ +}\ +\ +.ace-tomorrow-night-blue .ace_invalid.ace_deprecated {\ + color:#FFFFFF;\ +background-color:#EBBBFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_support.ace_constant {\ + color:#FFC58F;\ +}\ +\ +.ace-tomorrow-night-blue .ace_fold {\ + background-color: #BBDAFF;\ + border-color: #FFFFFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_support.ace_function {\ + color:#BBDAFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_storage {\ + color:#EBBBFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_storage.ace_type, .ace-tomorrow-night-blue .ace_support.ace_type{\ + color:#EBBBFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_variable {\ + color:#BBDAFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_variable.ace_parameter {\ + color:#FFC58F;\ +}\ +\ +.ace-tomorrow-night-blue .ace_string {\ + color:#D1F1A9;\ +}\ +\ +.ace-tomorrow-night-blue .ace_string.ace_regexp {\ + color:#FF9DA4;\ +}\ +\ +.ace-tomorrow-night-blue .ace_comment {\ + color:#7285B7;\ +}\ +\ +.ace-tomorrow-night-blue .ace_variable {\ + color:#FF9DA4;\ +}\ +\ +.ace-tomorrow-night-blue .ace_meta.ace_tag {\ + color:#FF9DA4;\ +}\ +\ +.ace-tomorrow-night-blue .ace_entity.ace_other.ace_attribute-name {\ + color:#FF9DA4;\ +}\ +\ +.ace-tomorrow-night-blue .ace_entity.ace_name.ace_function {\ + color:#BBDAFF;\ +}\ +\ +.ace-tomorrow-night-blue .ace_markup.ace_underline {\ + text-decoration:underline;\ +}\ +\ +.ace-tomorrow-night-blue .ace_markup.ace_heading {\ + color:#D1F1A9;\ +}\ +\ +.ace-tomorrow-night-blue .ace_indent-guide {\ + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgUAn8z7Bq1ar/ABBUBHJ4/r3JAAAAAElFTkSuQmCC) right repeat-y;\ +}"; + + var dom = require("../lib/dom"); + dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/lib/client/editor/ace/worker-coffee.js b/lib/client/editor/ace/worker-coffee.js new file mode 100644 index 00000000..9aebc984 --- /dev/null +++ b/lib/client/editor/ace/worker-coffee.js @@ -0,0 +1,7187 @@ +"no use strict"; + +var console = { + log: function(msg) { + postMessage({type: "log", data: msg}); + } +}; +var window = { + console: console +}; + +var normalizeModule = function(parentId, moduleName) { + // normalize plugin requires + if (moduleName.indexOf("!") !== -1) { + var chunks = moduleName.split("!"); + return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]); + } + // normalize relative requires + if (moduleName.charAt(0) == ".") { + var base = parentId.split("/").slice(0, -1).join("/"); + var moduleName = base + "/" + moduleName; + + while(moduleName.indexOf(".") !== -1 && previous != moduleName) { + var previous = moduleName; + var moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); + } + } + + return moduleName; +}; + +var require = function(parentId, id) { + var id = normalizeModule(parentId, id); + + var module = require.modules[id]; + if (module) { + if (!module.initialized) { + module.initialized = true; + module.exports = module.factory().exports; + } + return module.exports; + } + + var chunks = id.split("/"); + chunks[0] = require.tlns[chunks[0]] || chunks[0]; + var path = chunks.join("/") + ".js"; + + require.id = id; + importScripts(path); + return require(parentId, id); +}; + +require.modules = {}; +require.tlns = {}; + +var define = function(id, deps, factory) { + if (arguments.length == 2) { + factory = deps; + if (typeof id != "string") { + deps = id; + id = require.id; + } + } else if (arguments.length == 1) { + factory = id; + id = require.id; + } + + if (id.indexOf("text!") === 0) + return; + + var req = function(deps, factory) { + return require(id, deps, factory); + }; + + require.modules[id] = { + factory: function() { + var module = { + exports: {} + }; + var returnExports = factory(req, module.exports, module); + if (returnExports) + module.exports = returnExports; + return module; + } + }; +}; + +function initBaseUrls(topLevelNamespaces) { + require.tlns = topLevelNamespaces; +} + +function initSender() { + + var EventEmitter = require(null, "ace/lib/event_emitter").EventEmitter; + var oop = require(null, "ace/lib/oop"); + + var Sender = function() {}; + + (function() { + + oop.implement(this, EventEmitter); + + this.callback = function(data, callbackId) { + postMessage({ + type: "call", + id: callbackId, + data: data + }); + }; + + this.emit = function(name, data) { + postMessage({ + type: "event", + name: name, + data: data + }); + }; + + }).call(Sender.prototype); + + return new Sender(); +} + +var main; +var sender; + +onmessage = function(e) { + var msg = e.data; + if (msg.command) { + main[msg.command].apply(main, msg.args); + } + else if (msg.init) { + initBaseUrls(msg.tlns); + require(null, "ace/lib/fixoldbrowsers"); + sender = initSender(); + var clazz = require(null, msg.module)[msg.classname]; + main = new clazz(sender); + } + else if (msg.event && sender) { + sender._emit(msg.event, msg.data); + } +}; +// vim:set ts=4 sts=4 sw=4 st: +// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License +// -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project) +// -- dantman Daniel Friesen Copyright(C) 2010 XXX No License Specified +// -- fschaefer Florian Schäfer Copyright (C) 2010 MIT License +// -- Irakli Gozalishvili Copyright (C) 2010 MIT License + +/*! + Copyright (c) 2009, 280 North Inc. http://280north.com/ + MIT License. http://github.com/280north/narwhal/blob/master/README.md +*/ + +define('ace/lib/fixoldbrowsers', ['require', 'exports', 'module' , 'ace/lib/regexp', 'ace/lib/es5-shim'], function(require, exports, module) { + + +require("./regexp"); +require("./es5-shim"); + +}); + +define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, exports, module) { + + + //--------------------------------- + // Private variables + //--------------------------------- + + var real = { + exec: RegExp.prototype.exec, + test: RegExp.prototype.test, + match: String.prototype.match, + replace: String.prototype.replace, + split: String.prototype.split + }, + compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups + compliantLastIndexIncrement = function () { + var x = /^/g; + real.test.call(x, ""); + return !x.lastIndex; + }(); + + if (compliantLastIndexIncrement && compliantExecNpcg) + return; + + //--------------------------------- + // Overriden native methods + //--------------------------------- + + // Adds named capture support (with backreferences returned as `result.name`), and fixes two + // cross-browser issues per ES3: + // - Captured values for nonparticipating capturing groups should be returned as `undefined`, + // rather than the empty string. + // - `lastIndex` should not be incremented after zero-length matches. + RegExp.prototype.exec = function (str) { + var match = real.exec.apply(this, arguments), + name, r2; + if ( typeof(str) == 'string' && match) { + // Fix browsers whose `exec` methods don't consistently return `undefined` for + // nonparticipating capturing groups + if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) { + r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", "")); + // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed + // matching due to characters outside the match + real.replace.call(str.slice(match.index), r2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) + match[i] = undefined; + } + }); + } + // Attach named capture properties + if (this._xregexp && this._xregexp.captureNames) { + for (var i = 1; i < match.length; i++) { + name = this._xregexp.captureNames[i - 1]; + if (name) + match[name] = match[i]; + } + } + // Fix browsers that increment `lastIndex` after zero-length matches + if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + } + return match; + }; + + // Don't override `test` if it won't change anything + if (!compliantLastIndexIncrement) { + // Fix browser bug in native method + RegExp.prototype.test = function (str) { + // Use the native `exec` to skip some processing overhead, even though the overriden + // `exec` would take care of the `lastIndex` fix + var match = real.exec.call(this, str); + // Fix browsers that increment `lastIndex` after zero-length matches + if (match && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + return !!match; + }; + } + + //--------------------------------- + // Private helper functions + //--------------------------------- + + function getNativeFlags (regex) { + return (regex.global ? "g" : "") + + (regex.ignoreCase ? "i" : "") + + (regex.multiline ? "m" : "") + + (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3 + (regex.sticky ? "y" : ""); + } + + function indexOf (array, item, from) { + if (Array.prototype.indexOf) // Use the native array method if available + return array.indexOf(item, from); + for (var i = from || 0; i < array.length; i++) { + if (array[i] === item) + return i; + } + return -1; + } + +}); +/*! + Copyright (c) 2009, 280 North Inc. http://280north.com/ + MIT License. http://github.com/280north/narwhal/blob/master/README.md +*/ + +define('ace/lib/es5-shim', ['require', 'exports', 'module' ], function(require, exports, module) { + +/* + * Brings an environment as close to ECMAScript 5 compliance + * as is possible with the facilities of erstwhile engines. + * + * Annotated ES5: http://es5.github.com/ (specific links below) + * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf + * + * @module + */ + +/*whatsupdoc*/ + +// +// Function +// ======== +// + +// ES-5 15.3.4.5 +// http://es5.github.com/#x15.3.4.5 + +if (!Function.prototype.bind) { + Function.prototype.bind = function bind(that) { // .length is 1 + // 1. Let Target be the this value. + var target = this; + // 2. If IsCallable(Target) is false, throw a TypeError exception. + if (typeof target != "function") + throw new TypeError(); // TODO message + // 3. Let A be a new (possibly empty) internal list of all of the + // argument values provided after thisArg (arg1, arg2 etc), in order. + // XXX slicedArgs will stand in for "A" if used + var args = slice.call(arguments, 1); // for normal call + // 4. Let F be a new native ECMAScript object. + // 11. Set the [[Prototype]] internal property of F to the standard + // built-in Function prototype object as specified in 15.3.3.1. + // 12. Set the [[Call]] internal property of F as described in + // 15.3.4.5.1. + // 13. Set the [[Construct]] internal property of F as described in + // 15.3.4.5.2. + // 14. Set the [[HasInstance]] internal property of F as described in + // 15.3.4.5.3. + var bound = function () { + + if (this instanceof bound) { + // 15.3.4.5.2 [[Construct]] + // When the [[Construct]] internal method of a function object, + // F that was created using the bind function is called with a + // list of arguments ExtraArgs, the following steps are taken: + // 1. Let target be the value of F's [[TargetFunction]] + // internal property. + // 2. If target has no [[Construct]] internal method, a + // TypeError exception is thrown. + // 3. Let boundArgs be the value of F's [[BoundArgs]] internal + // property. + // 4. Let args be a new list containing the same values as the + // list boundArgs in the same order followed by the same + // values as the list ExtraArgs in the same order. + // 5. Return the result of calling the [[Construct]] internal + // method of target providing args as the arguments. + + var F = function(){}; + F.prototype = target.prototype; + var self = new F; + + var result = target.apply( + self, + args.concat(slice.call(arguments)) + ); + if (result !== null && Object(result) === result) + return result; + return self; + + } else { + // 15.3.4.5.1 [[Call]] + // When the [[Call]] internal method of a function object, F, + // which was created using the bind function is called with a + // this value and a list of arguments ExtraArgs, the following + // steps are taken: + // 1. Let boundArgs be the value of F's [[BoundArgs]] internal + // property. + // 2. Let boundThis be the value of F's [[BoundThis]] internal + // property. + // 3. Let target be the value of F's [[TargetFunction]] internal + // property. + // 4. Let args be a new list containing the same values as the + // list boundArgs in the same order followed by the same + // values as the list ExtraArgs in the same order. + // 5. Return the result of calling the [[Call]] internal method + // of target providing boundThis as the this value and + // providing args as the arguments. + + // equiv: target.call(this, ...boundArgs, ...args) + return target.apply( + that, + args.concat(slice.call(arguments)) + ); + + } + + }; + // XXX bound.length is never writable, so don't even try + // + // 15. If the [[Class]] internal property of Target is "Function", then + // a. Let L be the length property of Target minus the length of A. + // b. Set the length own property of F to either 0 or L, whichever is + // larger. + // 16. Else set the length own property of F to 0. + // 17. Set the attributes of the length own property of F to the values + // specified in 15.3.5.1. + + // TODO + // 18. Set the [[Extensible]] internal property of F to true. + + // TODO + // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3). + // 20. Call the [[DefineOwnProperty]] internal method of F with + // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]: + // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and + // false. + // 21. Call the [[DefineOwnProperty]] internal method of F with + // arguments "arguments", PropertyDescriptor {[[Get]]: thrower, + // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false}, + // and false. + + // TODO + // NOTE Function objects created using Function.prototype.bind do not + // have a prototype property or the [[Code]], [[FormalParameters]], and + // [[Scope]] internal properties. + // XXX can't delete prototype in pure-js. + + // 22. Return F. + return bound; + }; +} + +// Shortcut to an often accessed properties, in order to avoid multiple +// dereference that costs universally. +// _Please note: Shortcuts are defined after `Function.prototype.bind` as we +// us it in defining shortcuts. +var call = Function.prototype.call; +var prototypeOfArray = Array.prototype; +var prototypeOfObject = Object.prototype; +var slice = prototypeOfArray.slice; +var toString = call.bind(prototypeOfObject.toString); +var owns = call.bind(prototypeOfObject.hasOwnProperty); + +// If JS engine supports accessors creating shortcuts. +var defineGetter; +var defineSetter; +var lookupGetter; +var lookupSetter; +var supportsAccessors; +if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) { + defineGetter = call.bind(prototypeOfObject.__defineGetter__); + defineSetter = call.bind(prototypeOfObject.__defineSetter__); + lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); + lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); +} + +// +// Array +// ===== +// + +// ES5 15.4.3.2 +// http://es5.github.com/#x15.4.3.2 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray +if (!Array.isArray) { + Array.isArray = function isArray(obj) { + return toString(obj) == "[object Array]"; + }; +} + +// The IsCallable() check in the Array functions +// has been replaced with a strict check on the +// internal class of the object to trap cases where +// the provided function was actually a regular +// expression literal, which in V8 and +// JavaScriptCore is a typeof "function". Only in +// V8 are regular expression literals permitted as +// reduce parameters, so it is desirable in the +// general case for the shim to match the more +// strict and common behavior of rejecting regular +// expressions. + +// ES5 15.4.4.18 +// http://es5.github.com/#x15.4.4.18 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach +if (!Array.prototype.forEach) { + Array.prototype.forEach = function forEach(fun /*, thisp*/) { + var self = toObject(this), + thisp = arguments[1], + i = 0, + length = self.length >>> 0; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + while (i < length) { + if (i in self) { + // Invoke the callback function with call, passing arguments: + // context, property value, property key, thisArg object context + fun.call(thisp, self[i], i, self); + } + i++; + } + }; +} + +// ES5 15.4.4.19 +// http://es5.github.com/#x15.4.4.19 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map +if (!Array.prototype.map) { + Array.prototype.map = function map(fun /*, thisp*/) { + var self = toObject(this), + length = self.length >>> 0, + result = Array(length), + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self) + result[i] = fun.call(thisp, self[i], i, self); + } + return result; + }; +} + +// ES5 15.4.4.20 +// http://es5.github.com/#x15.4.4.20 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter +if (!Array.prototype.filter) { + Array.prototype.filter = function filter(fun /*, thisp */) { + var self = toObject(this), + length = self.length >>> 0, + result = [], + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, self)) + result.push(self[i]); + } + return result; + }; +} + +// ES5 15.4.4.16 +// http://es5.github.com/#x15.4.4.16 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every +if (!Array.prototype.every) { + Array.prototype.every = function every(fun /*, thisp */) { + var self = toObject(this), + length = self.length >>> 0, + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self && !fun.call(thisp, self[i], i, self)) + return false; + } + return true; + }; +} + +// ES5 15.4.4.17 +// http://es5.github.com/#x15.4.4.17 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some +if (!Array.prototype.some) { + Array.prototype.some = function some(fun /*, thisp */) { + var self = toObject(this), + length = self.length >>> 0, + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, self)) + return true; + } + return false; + }; +} + +// ES5 15.4.4.21 +// http://es5.github.com/#x15.4.4.21 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce +if (!Array.prototype.reduce) { + Array.prototype.reduce = function reduce(fun /*, initial*/) { + var self = toObject(this), + length = self.length >>> 0; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + // no value to return if no initial value and an empty array + if (!length && arguments.length == 1) + throw new TypeError(); // TODO message + + var i = 0; + var result; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i++]; + break; + } + + // if array contains no values, no initial value to return + if (++i >= length) + throw new TypeError(); // TODO message + } while (true); + } + + for (; i < length; i++) { + if (i in self) + result = fun.call(void 0, result, self[i], i, self); + } + + return result; + }; +} + +// ES5 15.4.4.22 +// http://es5.github.com/#x15.4.4.22 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight +if (!Array.prototype.reduceRight) { + Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { + var self = toObject(this), + length = self.length >>> 0; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + // no value to return if no initial value, empty array + if (!length && arguments.length == 1) + throw new TypeError(); // TODO message + + var result, i = length - 1; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i--]; + break; + } + + // if array contains no values, no initial value to return + if (--i < 0) + throw new TypeError(); // TODO message + } while (true); + } + + do { + if (i in this) + result = fun.call(void 0, result, self[i], i, self); + } while (i--); + + return result; + }; +} + +// ES5 15.4.4.14 +// http://es5.github.com/#x15.4.4.14 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { + var self = toObject(this), + length = self.length >>> 0; + + if (!length) + return -1; + + var i = 0; + if (arguments.length > 1) + i = toInteger(arguments[1]); + + // handle negative indices + i = i >= 0 ? i : Math.max(0, length + i); + for (; i < length; i++) { + if (i in self && self[i] === sought) { + return i; + } + } + return -1; + }; +} + +// ES5 15.4.4.15 +// http://es5.github.com/#x15.4.4.15 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf +if (!Array.prototype.lastIndexOf) { + Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { + var self = toObject(this), + length = self.length >>> 0; + + if (!length) + return -1; + var i = length - 1; + if (arguments.length > 1) + i = Math.min(i, toInteger(arguments[1])); + // handle negative indices + i = i >= 0 ? i : length - Math.abs(i); + for (; i >= 0; i--) { + if (i in self && sought === self[i]) + return i; + } + return -1; + }; +} + +// +// Object +// ====== +// + +// ES5 15.2.3.2 +// http://es5.github.com/#x15.2.3.2 +if (!Object.getPrototypeOf) { + // https://github.com/kriskowal/es5-shim/issues#issue/2 + // http://ejohn.org/blog/objectgetprototypeof/ + // recommended by fschaefer on github + Object.getPrototypeOf = function getPrototypeOf(object) { + return object.__proto__ || ( + object.constructor ? + object.constructor.prototype : + prototypeOfObject + ); + }; +} + +// ES5 15.2.3.3 +// http://es5.github.com/#x15.2.3.3 +if (!Object.getOwnPropertyDescriptor) { + var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + + "non-object: "; + Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT + object); + // If object does not owns property return undefined immediately. + if (!owns(object, property)) + return; + + var descriptor, getter, setter; + + // If object has a property then it's for sure both `enumerable` and + // `configurable`. + descriptor = { enumerable: true, configurable: true }; + + // If JS engine supports accessor properties then property may be a + // getter or setter. + if (supportsAccessors) { + // Unfortunately `__lookupGetter__` will return a getter even + // if object has own non getter property along with a same named + // inherited getter. To avoid misbehavior we temporary remove + // `__proto__` so that `__lookupGetter__` will return getter only + // if it's owned by an object. + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + + var getter = lookupGetter(object, property); + var setter = lookupSetter(object, property); + + // Once we have getter and setter we can put values back. + object.__proto__ = prototype; + + if (getter || setter) { + if (getter) descriptor.get = getter; + if (setter) descriptor.set = setter; + + // If it was accessor property we're done and return here + // in order to avoid adding `value` to the descriptor. + return descriptor; + } + } + + // If we got this far we know that object has an own property that is + // not an accessor so we set it as a value and return descriptor. + descriptor.value = object[property]; + return descriptor; + }; +} + +// ES5 15.2.3.4 +// http://es5.github.com/#x15.2.3.4 +if (!Object.getOwnPropertyNames) { + Object.getOwnPropertyNames = function getOwnPropertyNames(object) { + return Object.keys(object); + }; +} + +// ES5 15.2.3.5 +// http://es5.github.com/#x15.2.3.5 +if (!Object.create) { + Object.create = function create(prototype, properties) { + var object; + if (prototype === null) { + object = { "__proto__": null }; + } else { + if (typeof prototype != "object") + throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); + var Type = function () {}; + Type.prototype = prototype; + object = new Type(); + // IE has no built-in implementation of `Object.getPrototypeOf` + // neither `__proto__`, but this manually setting `__proto__` will + // guarantee that `Object.getPrototypeOf` will work as expected with + // objects created using `Object.create` + object.__proto__ = prototype; + } + if (properties !== void 0) + Object.defineProperties(object, properties); + return object; + }; +} + +// ES5 15.2.3.6 +// http://es5.github.com/#x15.2.3.6 + +// Patch for WebKit and IE8 standard mode +// Designed by hax +// related issue: https://github.com/kriskowal/es5-shim/issues#issue/5 +// IE8 Reference: +// http://msdn.microsoft.com/en-us/library/dd282900.aspx +// http://msdn.microsoft.com/en-us/library/dd229916.aspx +// WebKit Bugs: +// https://bugs.webkit.org/show_bug.cgi?id=36423 + +function doesDefinePropertyWork(object) { + try { + Object.defineProperty(object, "sentinel", {}); + return "sentinel" in object; + } catch (exception) { + // returns falsy + } +} + +// check whether defineProperty works if it's given. Otherwise, +// shim partially. +if (Object.defineProperty) { + var definePropertyWorksOnObject = doesDefinePropertyWork({}); + var definePropertyWorksOnDom = typeof document == "undefined" || + doesDefinePropertyWork(document.createElement("div")); + if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { + var definePropertyFallback = Object.defineProperty; + } +} + +if (!Object.defineProperty || definePropertyFallback) { + var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; + var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " + var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + + "on this javascript engine"; + + Object.defineProperty = function defineProperty(object, property, descriptor) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT_TARGET + object); + if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) + throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); + + // make a valiant attempt to use the real defineProperty + // for I8's DOM elements. + if (definePropertyFallback) { + try { + return definePropertyFallback.call(Object, object, property, descriptor); + } catch (exception) { + // try the shim if the real one doesn't work + } + } + + // If it's a data property. + if (owns(descriptor, "value")) { + // fail silently if "writable", "enumerable", or "configurable" + // are requested but not supported + /* + // alternate approach: + if ( // can't implement these features; allow false but not true + !(owns(descriptor, "writable") ? descriptor.writable : true) || + !(owns(descriptor, "enumerable") ? descriptor.enumerable : true) || + !(owns(descriptor, "configurable") ? descriptor.configurable : true) + ) + throw new RangeError( + "This implementation of Object.defineProperty does not " + + "support configurable, enumerable, or writable." + ); + */ + + if (supportsAccessors && (lookupGetter(object, property) || + lookupSetter(object, property))) + { + // As accessors are supported only on engines implementing + // `__proto__` we can safely override `__proto__` while defining + // a property to make sure that we don't hit an inherited + // accessor. + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + // Deleting a property anyway since getter / setter may be + // defined on object itself. + delete object[property]; + object[property] = descriptor.value; + // Setting original `__proto__` back now. + object.__proto__ = prototype; + } else { + object[property] = descriptor.value; + } + } else { + if (!supportsAccessors) + throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); + // If we got that far then getters and setters can be defined !! + if (owns(descriptor, "get")) + defineGetter(object, property, descriptor.get); + if (owns(descriptor, "set")) + defineSetter(object, property, descriptor.set); + } + + return object; + }; +} + +// ES5 15.2.3.7 +// http://es5.github.com/#x15.2.3.7 +if (!Object.defineProperties) { + Object.defineProperties = function defineProperties(object, properties) { + for (var property in properties) { + if (owns(properties, property)) + Object.defineProperty(object, property, properties[property]); + } + return object; + }; +} + +// ES5 15.2.3.8 +// http://es5.github.com/#x15.2.3.8 +if (!Object.seal) { + Object.seal = function seal(object) { + // this is misleading and breaks feature-detection, but + // allows "securable" code to "gracefully" degrade to working + // but insecure code. + return object; + }; +} + +// ES5 15.2.3.9 +// http://es5.github.com/#x15.2.3.9 +if (!Object.freeze) { + Object.freeze = function freeze(object) { + // this is misleading and breaks feature-detection, but + // allows "securable" code to "gracefully" degrade to working + // but insecure code. + return object; + }; +} + +// detect a Rhino bug and patch it +try { + Object.freeze(function () {}); +} catch (exception) { + Object.freeze = (function freeze(freezeObject) { + return function freeze(object) { + if (typeof object == "function") { + return object; + } else { + return freezeObject(object); + } + }; + })(Object.freeze); +} + +// ES5 15.2.3.10 +// http://es5.github.com/#x15.2.3.10 +if (!Object.preventExtensions) { + Object.preventExtensions = function preventExtensions(object) { + // this is misleading and breaks feature-detection, but + // allows "securable" code to "gracefully" degrade to working + // but insecure code. + return object; + }; +} + +// ES5 15.2.3.11 +// http://es5.github.com/#x15.2.3.11 +if (!Object.isSealed) { + Object.isSealed = function isSealed(object) { + return false; + }; +} + +// ES5 15.2.3.12 +// http://es5.github.com/#x15.2.3.12 +if (!Object.isFrozen) { + Object.isFrozen = function isFrozen(object) { + return false; + }; +} + +// ES5 15.2.3.13 +// http://es5.github.com/#x15.2.3.13 +if (!Object.isExtensible) { + Object.isExtensible = function isExtensible(object) { + // 1. If Type(O) is not Object throw a TypeError exception. + if (Object(object) === object) { + throw new TypeError(); // TODO message + } + // 2. Return the Boolean value of the [[Extensible]] internal property of O. + var name = ''; + while (owns(object, name)) { + name += '?'; + } + object[name] = true; + var returnValue = owns(object, name); + delete object[name]; + return returnValue; + }; +} + +// ES5 15.2.3.14 +// http://es5.github.com/#x15.2.3.14 +if (!Object.keys) { + // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation + var hasDontEnumBug = true, + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + dontEnumsLength = dontEnums.length; + + for (var key in {"toString": null}) + hasDontEnumBug = false; + + Object.keys = function keys(object) { + + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError("Object.keys called on a non-object"); + + var keys = []; + for (var name in object) { + if (owns(object, name)) { + keys.push(name); + } + } + + if (hasDontEnumBug) { + for (var i = 0, ii = dontEnumsLength; i < ii; i++) { + var dontEnum = dontEnums[i]; + if (owns(object, dontEnum)) { + keys.push(dontEnum); + } + } + } + + return keys; + }; + +} + +// +// Date +// ==== +// + +// ES5 15.9.5.43 +// http://es5.github.com/#x15.9.5.43 +// This function returns a String value represent the instance in time +// represented by this Date object. The format of the String is the Date Time +// string format defined in 15.9.1.15. All fields are present in the String. +// The time zone is always UTC, denoted by the suffix Z. If the time value of +// this object is not a finite Number a RangeError exception is thrown. +if (!Date.prototype.toISOString || (new Date(-62198755200000).toISOString().indexOf('-000001') === -1)) { + Date.prototype.toISOString = function toISOString() { + var result, length, value, year; + if (!isFinite(this)) + throw new RangeError; + + // the date time string format is specified in 15.9.1.15. + result = [this.getUTCMonth() + 1, this.getUTCDate(), + this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()]; + year = this.getUTCFullYear(); + year = (year < 0 ? '-' : (year > 9999 ? '+' : '')) + ('00000' + Math.abs(year)).slice(0 <= year && year <= 9999 ? -4 : -6); + + length = result.length; + while (length--) { + value = result[length]; + // pad months, days, hours, minutes, and seconds to have two digits. + if (value < 10) + result[length] = "0" + value; + } + // pad milliseconds to have three digits. + return year + "-" + result.slice(0, 2).join("-") + "T" + result.slice(2).join(":") + "." + + ("000" + this.getUTCMilliseconds()).slice(-3) + "Z"; + } +} + +// ES5 15.9.4.4 +// http://es5.github.com/#x15.9.4.4 +if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; +} + +// ES5 15.9.5.44 +// http://es5.github.com/#x15.9.5.44 +// This function provides a String representation of a Date object for use by +// JSON.stringify (15.12.3). +if (!Date.prototype.toJSON) { + Date.prototype.toJSON = function toJSON(key) { + // When the toJSON method is called with argument key, the following + // steps are taken: + + // 1. Let O be the result of calling ToObject, giving it the this + // value as its argument. + // 2. Let tv be ToPrimitive(O, hint Number). + // 3. If tv is a Number and is not finite, return null. + // XXX + // 4. Let toISO be the result of calling the [[Get]] internal method of + // O with argument "toISOString". + // 5. If IsCallable(toISO) is false, throw a TypeError exception. + if (typeof this.toISOString != "function") + throw new TypeError(); // TODO message + // 6. Return the result of calling the [[Call]] internal method of + // toISO with O as the this value and an empty argument list. + return this.toISOString(); + + // NOTE 1 The argument is ignored. + + // NOTE 2 The toJSON function is intentionally generic; it does not + // require that its this value be a Date object. Therefore, it can be + // transferred to other kinds of objects for use as a method. However, + // it does require that any such object have a toISOString method. An + // object is free to use the argument key to filter its + // stringification. + }; +} + +// ES5 15.9.4.2 +// http://es5.github.com/#x15.9.4.2 +// based on work shared by Daniel Friesen (dantman) +// http://gist.github.com/303249 +if (Date.parse("+275760-09-13T00:00:00.000Z") !== 8.64e15) { + // XXX global assignment won't work in embeddings that use + // an alternate object for the context. + Date = (function(NativeDate) { + + // Date.length === 7 + var Date = function Date(Y, M, D, h, m, s, ms) { + var length = arguments.length; + if (this instanceof NativeDate) { + var date = length == 1 && String(Y) === Y ? // isString(Y) + // We explicitly pass it through parse: + new NativeDate(Date.parse(Y)) : + // We have to manually make calls depending on argument + // length here + length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) : + length >= 6 ? new NativeDate(Y, M, D, h, m, s) : + length >= 5 ? new NativeDate(Y, M, D, h, m) : + length >= 4 ? new NativeDate(Y, M, D, h) : + length >= 3 ? new NativeDate(Y, M, D) : + length >= 2 ? new NativeDate(Y, M) : + length >= 1 ? new NativeDate(Y) : + new NativeDate(); + // Prevent mixups with unfixed Date object + date.constructor = Date; + return date; + } + return NativeDate.apply(this, arguments); + }; + + // 15.9.1.15 Date Time String Format. + var isoDateExpression = new RegExp("^" + + "(\\d{4}|[\+\-]\\d{6})" + // four-digit year capture or sign + 6-digit extended year + "(?:-(\\d{2})" + // optional month capture + "(?:-(\\d{2})" + // optional day capture + "(?:" + // capture hours:minutes:seconds.milliseconds + "T(\\d{2})" + // hours capture + ":(\\d{2})" + // minutes capture + "(?:" + // optional :seconds.milliseconds + ":(\\d{2})" + // seconds capture + "(?:\\.(\\d{3}))?" + // milliseconds capture + ")?" + + "(?:" + // capture UTC offset component + "Z|" + // UTC capture + "(?:" + // offset specifier +/-hours:minutes + "([-+])" + // sign capture + "(\\d{2})" + // hours offset capture + ":(\\d{2})" + // minutes offset capture + ")" + + ")?)?)?)?" + + "$"); + + // Copy any custom methods a 3rd party library may have added + for (var key in NativeDate) + Date[key] = NativeDate[key]; + + // Copy "native" methods explicitly; they may be non-enumerable + Date.now = NativeDate.now; + Date.UTC = NativeDate.UTC; + Date.prototype = NativeDate.prototype; + Date.prototype.constructor = Date; + + // Upgrade Date.parse to handle simplified ISO 8601 strings + Date.parse = function parse(string) { + var match = isoDateExpression.exec(string); + if (match) { + match.shift(); // kill match[0], the full match + // parse months, days, hours, minutes, seconds, and milliseconds + for (var i = 1; i < 7; i++) { + // provide default values if necessary + match[i] = +(match[i] || (i < 3 ? 1 : 0)); + // match[1] is the month. Months are 0-11 in JavaScript + // `Date` objects, but 1-12 in ISO notation, so we + // decrement. + if (i == 1) + match[i]--; + } + + // parse the UTC offset component + var minuteOffset = +match.pop(), hourOffset = +match.pop(), sign = match.pop(); + + // compute the explicit time zone offset if specified + var offset = 0; + if (sign) { + // detect invalid offsets and return early + if (hourOffset > 23 || minuteOffset > 59) + return NaN; + + // express the provided time zone offset in minutes. The offset is + // negative for time zones west of UTC; positive otherwise. + offset = (hourOffset * 60 + minuteOffset) * 6e4 * (sign == "+" ? -1 : 1); + } + + // Date.UTC for years between 0 and 99 converts year to 1900 + year + // The Gregorian calendar has a 400-year cycle, so + // to Date.UTC(year + 400, .... ) - 12622780800000 == Date.UTC(year, ...), + // where 12622780800000 - number of milliseconds in Gregorian calendar 400 years + var year = +match[0]; + if (0 <= year && year <= 99) { + match[0] = year + 400; + return NativeDate.UTC.apply(this, match) + offset - 12622780800000; + } + + // compute a new UTC date value, accounting for the optional offset + return NativeDate.UTC.apply(this, match) + offset; + } + return NativeDate.parse.apply(this, arguments); + }; + + return Date; + })(Date); +} + +// +// String +// ====== +// + +// ES5 15.5.4.20 +// http://es5.github.com/#x15.5.4.20 +var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + + "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + + "\u2029\uFEFF"; +if (!String.prototype.trim || ws.trim()) { + // http://blog.stevenlevithan.com/archives/faster-trim-javascript + // http://perfectionkills.com/whitespace-deviations/ + ws = "[" + ws + "]"; + var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), + trimEndRegexp = new RegExp(ws + ws + "*$"); + String.prototype.trim = function trim() { + return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); + }; +} + +// +// Util +// ====== +// + +// ES5 9.4 +// http://es5.github.com/#x9.4 +// http://jsperf.com/to-integer +var toInteger = function (n) { + n = +n; + if (n !== n) // isNaN + n = 0; + else if (n !== 0 && n !== (1/0) && n !== -(1/0)) + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + return n; +}; + +var prepareString = "a"[0] != "a", + // ES5 9.9 + // http://es5.github.com/#x9.9 + toObject = function (o) { + if (o == null) { // this matches both null and undefined + throw new TypeError(); // TODO message + } + // If the implementation doesn't support by-index access of + // string characters (ex. IE < 7), split the string + if (prepareString && typeof o == "string" && o) { + return o.split(""); + } + return Object(o); + }; +}); + +define('ace/lib/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) { + + +var EventEmitter = {}; + +EventEmitter._emit = +EventEmitter._dispatchEvent = function(eventName, e) { + this._eventRegistry = this._eventRegistry || {}; + this._defaultHandlers = this._defaultHandlers || {}; + + var listeners = this._eventRegistry[eventName] || []; + var defaultHandler = this._defaultHandlers[eventName]; + if (!listeners.length && !defaultHandler) + return; + + e = e || {}; + if (!e.type) + e.type = eventName; + + if (!e.stopPropagation) { + e.stopPropagation = function() { + this.propagationStopped = true; + }; + } + + if (!e.preventDefault) { + e.preventDefault = function() { + this.defaultPrevented = true; + }; + } + + for (var i=0; i= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length-1).length; + } + return position; + }; + this.insert = function(position, text) { + if (!text || text.length === 0) + return position; + + position = this.$clipPosition(position); + + // only detect new lines if the document has no line break yet + if (this.getLength() <= 1) + this.$detectNewLine(text); + + var lines = this.$split(text); + var firstLine = lines.splice(0, 1)[0]; + var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0]; + + position = this.insertInLine(position, firstLine); + if (lastLine !== null) { + position = this.insertNewLine(position); // terminate first line + position = this.insertLines(position.row, lines); + position = this.insertInLine(position, lastLine || ""); + } + return position; + }; + /** + * Document@change(e) + * - e (Object): Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties. + * + * Fires whenever the document changes. + * + * Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available: + * + * * `"insertLines"` (emitted by [[Document.insertLines]]) + * * `range`: the [[Range]] of the change within the document + * * `lines`: the lines in the document that are changing + * * `"insertText"` (emitted by [[Document.insertNewLine]]) + * * `range`: the [[Range]] of the change within the document + * * `text`: the text that's being added + * * `"removeLines"` (emitted by [[Document.insertLines]]) + * * `range`: the [[Range]] of the change within the document + * * `lines`: the lines in the document that were removed + * * `nl`: the new line character (as defined by [[Document.getNewLineCharacter]]) + * * `"removeText"` (emitted by [[Document.removeInLine]] and [[Document.removeNewLine]]) + * * `range`: the [[Range]] of the change within the document + * * `text`: the text that's being removed + * + **/ + this.insertLines = function(row, lines) { + if (lines.length == 0) + return {row: row, column: 0}; + + // apply doesn't work for big arrays (smallest threshold is on safari 0xFFFF) + // to circumvent that we have to break huge inserts into smaller chunks here + if (lines.length > 0xFFFF) { + var end = this.insertLines(row, lines.slice(0xFFFF)); + lines = lines.slice(0, 0xFFFF); + } + + var args = [row, 0]; + args.push.apply(args, lines); + this.$lines.splice.apply(this.$lines, args); + + var range = new Range(row, 0, row + lines.length, 0); + var delta = { + action: "insertLines", + range: range, + lines: lines + }; + this._emit("change", { data: delta }); + return end || range.end; + }; + this.insertNewLine = function(position) { + position = this.$clipPosition(position); + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column); + this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length)); + + var end = { + row : position.row + 1, + column : 0 + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: this.getNewLineCharacter() + }; + this._emit("change", { data: delta }); + + return end; + }; + this.insertInLine = function(position, text) { + if (text.length == 0) + return position; + + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column) + text + + line.substring(position.column); + + var end = { + row : position.row, + column : position.column + text.length + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: text + }; + this._emit("change", { data: delta }); + + return end; + }; + this.remove = function(range) { + // clip to document + range.start = this.$clipPosition(range.start); + range.end = this.$clipPosition(range.end); + + if (range.isEmpty()) + return range.start; + + var firstRow = range.start.row; + var lastRow = range.end.row; + + if (range.isMultiLine()) { + var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1; + var lastFullRow = lastRow - 1; + + if (range.end.column > 0) + this.removeInLine(lastRow, 0, range.end.column); + + if (lastFullRow >= firstFullRow) + this.removeLines(firstFullRow, lastFullRow); + + if (firstFullRow != firstRow) { + this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length); + this.removeNewLine(range.start.row); + } + } + else { + this.removeInLine(firstRow, range.start.column, range.end.column); + } + return range.start; + }; + this.removeInLine = function(row, startColumn, endColumn) { + if (startColumn == endColumn) + return; + + var range = new Range(row, startColumn, row, endColumn); + var line = this.getLine(row); + var removed = line.substring(startColumn, endColumn); + var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length); + this.$lines.splice(row, 1, newLine); + + var delta = { + action: "removeText", + range: range, + text: removed + }; + this._emit("change", { data: delta }); + return range.start; + }; + this.removeLines = function(firstRow, lastRow) { + var range = new Range(firstRow, 0, lastRow + 1, 0); + var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1); + + var delta = { + action: "removeLines", + range: range, + nl: this.getNewLineCharacter(), + lines: removed + }; + this._emit("change", { data: delta }); + return removed; + }; + this.removeNewLine = function(row) { + var firstLine = this.getLine(row); + var secondLine = this.getLine(row+1); + + var range = new Range(row, firstLine.length, row+1, 0); + var line = firstLine + secondLine; + + this.$lines.splice(row, 2, line); + + var delta = { + action: "removeText", + range: range, + text: this.getNewLineCharacter() + }; + this._emit("change", { data: delta }); + }; + this.replace = function(range, text) { + if (text.length == 0 && range.isEmpty()) + return range.start; + + // Shortcut: If the text we want to insert is the same as it is already + // in the document, we don't have to replace anything. + if (text == this.getTextRange(range)) + return range.end; + + this.remove(range); + if (text) { + var end = this.insert(range.start, text); + } + else { + end = range.start; + } + + return end; + }; + this.applyDeltas = function(deltas) { + for (var i=0; i=0; i--) { + var delta = deltas[i]; + + var range = Range.fromPoints(delta.range.start, delta.range.end); + + if (delta.action == "insertLines") + this.removeLines(range.start.row, range.end.row - 1); + else if (delta.action == "insertText") + this.remove(range); + else if (delta.action == "removeLines") + this.insertLines(range.start.row, delta.lines); + else if (delta.action == "removeText") + this.insert(range.start, delta.text); + } + }; + +}).call(Document.prototype); + +exports.Document = Document; +}); + +define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) { + + +/** + * class Range + * + * This object is used in various places to indicate a region within the editor. To better visualize how this works, imagine a rectangle. Each quadrant of the rectangle is analogus to a range, as ranges contain a starting row and starting column, and an ending row, and ending column. + * + **/ + +/** + * new Range(startRow, startColumn, endRow, endColumn) + * - startRow (Number): The starting row + * - startColumn (Number): The starting column + * - endRow (Number): The ending row + * - endColumn (Number): The ending column + * + * Creates a new `Range` object with the given starting and ending row and column points. + * + **/ +var Range = function(startRow, startColumn, endRow, endColumn) { + this.start = { + row: startRow, + column: startColumn + }; + + this.end = { + row: endRow, + column: endColumn + }; +}; + +(function() { + /** + * Range.isEqual(range) -> Boolean + * - range (Range): A range to check against + * + * Returns `true` if and only if the starting row and column, and ending tow and column, are equivalent to those given by `range`. + * + **/ + this.isEqual = function(range) { + return this.start.row == range.start.row && + this.end.row == range.end.row && + this.start.column == range.start.column && + this.end.column == range.end.column + }; + this.toString = function() { + return ("Range: [" + this.start.row + "/" + this.start.column + + "] -> [" + this.end.row + "/" + this.end.column + "]"); + }; + + this.contains = function(row, column) { + return this.compare(row, column) == 0; + }; + this.compareRange = function(range) { + var cmp, + end = range.end, + start = range.start; + + cmp = this.compare(end.row, end.column); + if (cmp == 1) { + cmp = this.compare(start.row, start.column); + if (cmp == 1) { + return 2; + } else if (cmp == 0) { + return 1; + } else { + return 0; + } + } else if (cmp == -1) { + return -2; + } else { + cmp = this.compare(start.row, start.column); + if (cmp == -1) { + return -1; + } else if (cmp == 1) { + return 42; + } else { + return 0; + } + } + } + + /** related to: Range.compare + * Range.comparePoint(p) -> Number + * - p (Range): A point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `0` if the two points are exactly equal
+ * * `-1` if `p.row` is less then the calling range
+ * * `1` if `p.row` is greater than the calling range
+ *
+ * If the starting row of the calling range is equal to `p.row`, and:
+ * * `p.column` is greater than or equal to the calling range's starting column, this returns `0`
+ * * Otherwise, it returns -1
+ *
+ * If the ending row of the calling range is equal to `p.row`, and:
+ * * `p.column` is less than or equal to the calling range's ending column, this returns `0`
+ * * Otherwise, it returns 1
+ * + * Checks the row and column points of `p` with the row and column points of the calling range. + * + * + * + **/ + this.comparePoint = function(p) { + return this.compare(p.row, p.column); + } + + /** related to: Range.comparePoint + * Range.containsRange(range) -> Boolean + * - range (Range): A range to compare with + * + * Checks the start and end points of `range` and compares them to the calling range. Returns `true` if the `range` is contained within the caller's range. + * + **/ + this.containsRange = function(range) { + return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; + } + + /** + * Range.intersects(range) -> Boolean + * - range (Range): A range to compare with + * + * Returns `true` if passed in `range` intersects with the one calling this method. + * + **/ + this.intersects = function(range) { + var cmp = this.compareRange(range); + return (cmp == -1 || cmp == 0 || cmp == 1); + } + + /** + * Range.isEnd(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the caller's ending row point is the same as `row`, and if the caller's ending column is the same as `column`. + * + **/ + this.isEnd = function(row, column) { + return this.end.row == row && this.end.column == column; + } + + /** + * Range.isStart(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the caller's starting row point is the same as `row`, and if the caller's starting column is the same as `column`. + * + **/ + this.isStart = function(row, column) { + return this.start.row == row && this.start.column == column; + } + + /** + * Range.setStart(row, column) + * - row (Number): A row point to set + * - column (Number): A column point to set + * + * Sets the starting row and column for the range. + * + **/ + this.setStart = function(row, column) { + if (typeof row == "object") { + this.start.column = row.column; + this.start.row = row.row; + } else { + this.start.row = row; + this.start.column = column; + } + } + + /** + * Range.setEnd(row, column) + * - row (Number): A row point to set + * - column (Number): A column point to set + * + * Sets the starting row and column for the range. + * + **/ + this.setEnd = function(row, column) { + if (typeof row == "object") { + this.end.column = row.column; + this.end.row = row.row; + } else { + this.end.row = row; + this.end.column = column; + } + } + + /** related to: Range.compare + * Range.inside(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the `row` and `column` are within the given range. + * + **/ + this.inside = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column) || this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + } + + /** related to: Range.compare + * Range.insideStart(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the `row` and `column` are within the given range's starting points. + * + **/ + this.insideStart = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column)) { + return false; + } else { + return true; + } + } + return false; + } + + /** related to: Range.compare + * Range.insideEnd(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the `row` and `column` are within the given range's ending points. + * + **/ + this.insideEnd = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + } + + /** + * Range.compare(row, column) -> Number + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `0` if the two points are exactly equal
+ * * `-1` if `p.row` is less then the calling range
+ * * `1` if `p.row` is greater than the calling range
+ *
+ * If the starting row of the calling range is equal to `p.row`, and:
+ * * `p.column` is greater than or equal to the calling range's starting column, this returns `0`
+ * * Otherwise, it returns -1
+ *
+ * If the ending row of the calling range is equal to `p.row`, and:
+ * * `p.column` is less than or equal to the calling range's ending column, this returns `0`
+ * * Otherwise, it returns 1 + * + * Checks the row and column points with the row and column points of the calling range. + * + * + **/ + this.compare = function(row, column) { + if (!this.isMultiLine()) { + if (row === this.start.row) { + return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); + }; + } + + if (row < this.start.row) + return -1; + + if (row > this.end.row) + return 1; + + if (this.start.row === row) + return column >= this.start.column ? 0 : -1; + + if (this.end.row === row) + return column <= this.end.column ? 0 : 1; + + return 0; + }; + this.compareStart = function(row, column) { + if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + } + + /** + * Range.compareEnd(row, column) -> Number + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `0` if the two points are exactly equal
+ * * `-1` if `p.row` is less then the calling range
+ * * `1` if `p.row` is greater than the calling range, or if `isEnd` is `true.
+ *
+ * If the starting row of the calling range is equal to `p.row`, and:
+ * * `p.column` is greater than or equal to the calling range's starting column, this returns `0`
+ * * Otherwise, it returns -1
+ *
+ * If the ending row of the calling range is equal to `p.row`, and:
+ * * `p.column` is less than or equal to the calling range's ending column, this returns `0`
+ * * Otherwise, it returns 1 + * + * Checks the row and column points with the row and column points of the calling range. + * + * + **/ + this.compareEnd = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else { + return this.compare(row, column); + } + } + + /** + * Range.compareInside(row, column) -> Number + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `1` if the ending row of the calling range is equal to `row`, and the ending column of the calling range is equal to `column`
+ * * `-1` if the starting row of the calling range is equal to `row`, and the starting column of the calling range is equal to `column`
+ *
+ * Otherwise, it returns the value after calling [[Range.compare `compare()`]]. + * + * Checks the row and column points with the row and column points of the calling range. + * + * + * + **/ + this.compareInside = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + } + + /** + * Range.clipRows(firstRow, lastRow) -> Range + * - firstRow (Number): The starting row + * - lastRow (Number): The ending row + * + * Returns the part of the current `Range` that occurs within the boundaries of `firstRow` and `lastRow` as a new `Range` object. + * + **/ + this.clipRows = function(firstRow, lastRow) { + if (this.end.row > lastRow) { + var end = { + row: lastRow+1, + column: 0 + }; + } + + if (this.start.row > lastRow) { + var start = { + row: lastRow+1, + column: 0 + }; + } + + if (this.start.row < firstRow) { + var start = { + row: firstRow, + column: 0 + }; + } + + if (this.end.row < firstRow) { + var end = { + row: firstRow, + column: 0 + }; + } + return Range.fromPoints(start || this.start, end || this.end); + }; + this.extend = function(row, column) { + var cmp = this.compare(row, column); + + if (cmp == 0) + return this; + else if (cmp == -1) + var start = {row: row, column: column}; + else + var end = {row: row, column: column}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + + this.isEmpty = function() { + return (this.start.row == this.end.row && this.start.column == this.end.column); + }; + this.isMultiLine = function() { + return (this.start.row !== this.end.row); + }; + this.clone = function() { + return Range.fromPoints(this.start, this.end); + }; + this.collapseRows = function() { + if (this.end.column == 0) + return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) + else + return new Range(this.start.row, 0, this.end.row, 0) + }; + this.toScreenRange = function(session) { + var screenPosStart = + session.documentToScreenPosition(this.start); + var screenPosEnd = + session.documentToScreenPosition(this.end); + + return new Range( + screenPosStart.row, screenPosStart.column, + screenPosEnd.row, screenPosEnd.column + ); + }; + +}).call(Range.prototype); +Range.fromPoints = function(start, end) { + return new Range(start.row, start.column, end.row, end.column); +}; + +exports.Range = Range; +}); + +define('ace/anchor', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) { + + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; + +/** + * new Anchor(doc, row, column) + * - doc (Document): The document to associate with the anchor + * - row (Number): The starting row position + * - column (Number): The starting column position + * + * Creates a new `Anchor` and associates it with a document. + * + **/ + +var Anchor = exports.Anchor = function(doc, row, column) { + this.document = doc; + + if (typeof column == "undefined") + this.setPosition(row.row, row.column); + else + this.setPosition(row, column); + + this.$onChange = this.onChange.bind(this); + doc.on("change", this.$onChange); +}; + +(function() { + + oop.implement(this, EventEmitter); + + this.getPosition = function() { + return this.$clipPositionToDocument(this.row, this.column); + }; + + this.getDocument = function() { + return this.document; + }; + + this.onChange = function(e) { + var delta = e.data; + var range = delta.range; + + if (range.start.row == range.end.row && range.start.row != this.row) + return; + + if (range.start.row > this.row) + return; + + if (range.start.row == this.row && range.start.column > this.column) + return; + + var row = this.row; + var column = this.column; + + if (delta.action === "insertText") { + if (range.start.row === row && range.start.column <= column) { + if (range.start.row === range.end.row) { + column += range.end.column - range.start.column; + } + else { + column -= range.start.column; + row += range.end.row - range.start.row; + } + } + else if (range.start.row !== range.end.row && range.start.row < row) { + row += range.end.row - range.start.row; + } + } else if (delta.action === "insertLines") { + if (range.start.row <= row) { + row += range.end.row - range.start.row; + } + } + else if (delta.action == "removeText") { + if (range.start.row == row && range.start.column < column) { + if (range.end.column >= column) + column = range.start.column; + else + column = Math.max(0, column - (range.end.column - range.start.column)); + + } else if (range.start.row !== range.end.row && range.start.row < row) { + if (range.end.row == row) { + column = Math.max(0, column - range.end.column) + range.start.column; + } + row -= (range.end.row - range.start.row); + } + else if (range.end.row == row) { + row -= range.end.row - range.start.row; + column = Math.max(0, column - range.end.column) + range.start.column; + } + } else if (delta.action == "removeLines") { + if (range.start.row <= row) { + if (range.end.row <= row) + row -= range.end.row - range.start.row; + else { + row = range.start.row; + column = 0; + } + } + } + + this.setPosition(row, column, true); + }; + + this.setPosition = function(row, column, noClip) { + var pos; + if (noClip) { + pos = { + row: row, + column: column + }; + } + else { + pos = this.$clipPositionToDocument(row, column); + } + + if (this.row == pos.row && this.column == pos.column) + return; + + var old = { + row: this.row, + column: this.column + }; + + this.row = pos.row; + this.column = pos.column; + this._emit("change", { + old: old, + value: pos + }); + }; + + this.detach = function() { + this.document.removeEventListener("change", this.$onChange); + }; + + this.$clipPositionToDocument = function(row, column) { + var pos = {}; + + if (row >= this.document.getLength()) { + pos.row = Math.max(0, this.document.getLength() - 1); + pos.column = this.document.getLine(pos.row).length; + } + else if (row < 0) { + pos.row = 0; + pos.column = 0; + } + else { + pos.row = row; + pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); + } + + if (column < 0) + pos.column = 0; + + return pos; + }; + +}).call(Anchor.prototype); + +}); + +define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) { + + +exports.stringReverse = function(string) { + return string.split("").reverse().join(""); +}; + +exports.stringRepeat = function (string, count) { + return new Array(count + 1).join(string); +}; + +var trimBeginRegexp = /^\s\s*/; +var trimEndRegexp = /\s\s*$/; + +exports.stringTrimLeft = function (string) { + return string.replace(trimBeginRegexp, ''); +}; + +exports.stringTrimRight = function (string) { + return string.replace(trimEndRegexp, ''); +}; + +exports.copyObject = function(obj) { + var copy = {}; + for (var key in obj) { + copy[key] = obj[key]; + } + return copy; +}; + +exports.copyArray = function(array){ + var copy = []; + for (var i=0, l=array.length; i= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) { + tag = id.toUpperCase(); + if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) { + tag = 'LEADING_WHEN'; + } else if (tag === 'FOR') { + this.seenFor = true; + } else if (tag === 'UNLESS') { + tag = 'IF'; + } else if (__indexOf.call(UNARY, tag) >= 0) { + tag = 'UNARY'; + } else if (__indexOf.call(RELATION, tag) >= 0) { + if (tag !== 'INSTANCEOF' && this.seenFor) { + tag = 'FOR' + tag; + this.seenFor = false; + } else { + tag = 'RELATION'; + if (this.value() === '!') { + this.tokens.pop(); + id = '!' + id; + } + } + } + } + if (__indexOf.call(JS_FORBIDDEN, id) >= 0) { + if (forcedIdentifier) { + tag = 'IDENTIFIER'; + id = new String(id); + id.reserved = true; + } else if (__indexOf.call(RESERVED, id) >= 0) { + this.error("reserved word \"" + id + "\""); + } + } + if (!forcedIdentifier) { + if (__indexOf.call(COFFEE_ALIASES, id) >= 0) id = COFFEE_ALIAS_MAP[id]; + tag = (function() { + switch (id) { + case '!': + return 'UNARY'; + case '==': + case '!=': + return 'COMPARE'; + case '&&': + case '||': + return 'LOGIC'; + case 'true': + case 'false': + case 'null': + case 'undefined': + return 'BOOL'; + case 'break': + case 'continue': + return 'STATEMENT'; + default: + return tag; + } + })(); + } + this.token(tag, id); + if (colon) this.token(':', ':'); + return input.length; + }; + + Lexer.prototype.numberToken = function() { + var binaryLiteral, lexedLength, match, number, octalLiteral; + if (!(match = NUMBER.exec(this.chunk))) return 0; + number = match[0]; + if (/E/.test(number)) { + this.error("exponential notation '" + number + "' must be indicated with a lowercase 'e'"); + } else if (/[BOX]/.test(number)) { + this.error("radix prefix '" + number + "' must be lowercase"); + } else if (/^0[89]/.test(number)) { + this.error("decimal literal '" + number + "' must not be prefixed with '0'"); + } else if (/^0[0-7]/.test(number)) { + this.error("octal literal '" + number + "' must be prefixed with '0o'"); + } + lexedLength = number.length; + if (octalLiteral = /0o([0-7]+)/.exec(number)) { + number = (parseInt(octalLiteral[1], 8)).toString(); + } + if (binaryLiteral = /0b([01]+)/.exec(number)) { + number = (parseInt(binaryLiteral[1], 2)).toString(); + } + this.token('NUMBER', number); + return lexedLength; + }; + + Lexer.prototype.stringToken = function() { + var match, octalEsc, string; + switch (this.chunk.charAt(0)) { + case "'": + if (!(match = SIMPLESTR.exec(this.chunk))) return 0; + this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n')); + break; + case '"': + if (!(string = this.balancedString(this.chunk, '"'))) return 0; + if (0 < string.indexOf('#{', 1)) { + this.interpolateString(string.slice(1, -1)); + } else { + this.token('STRING', this.escapeLines(string)); + } + break; + default: + return 0; + } + if (octalEsc = /^(?:\\.|[^\\])*\\[0-7]/.test(string)) { + this.error("octal escape sequences " + string + " are not allowed"); + } + this.line += count(string, '\n'); + return string.length; + }; + + Lexer.prototype.heredocToken = function() { + var doc, heredoc, match, quote; + if (!(match = HEREDOC.exec(this.chunk))) return 0; + heredoc = match[0]; + quote = heredoc.charAt(0); + doc = this.sanitizeHeredoc(match[2], { + quote: quote, + indent: null + }); + if (quote === '"' && 0 <= doc.indexOf('#{')) { + this.interpolateString(doc, { + heredoc: true + }); + } else { + this.token('STRING', this.makeString(doc, quote, true)); + } + this.line += count(heredoc, '\n'); + return heredoc.length; + }; + + Lexer.prototype.commentToken = function() { + var comment, here, match; + if (!(match = this.chunk.match(COMMENT))) return 0; + comment = match[0], here = match[1]; + if (here) { + this.token('HERECOMMENT', this.sanitizeHeredoc(here, { + herecomment: true, + indent: Array(this.indent + 1).join(' ') + })); + } + this.line += count(comment, '\n'); + return comment.length; + }; + + Lexer.prototype.jsToken = function() { + var match, script; + if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) { + return 0; + } + this.token('JS', (script = match[0]).slice(1, -1)); + return script.length; + }; + + Lexer.prototype.regexToken = function() { + var flags, length, match, prev, regex, _ref2, _ref3; + if (this.chunk.charAt(0) !== '/') return 0; + if (match = HEREGEX.exec(this.chunk)) { + length = this.heregexToken(match); + this.line += count(match[0], '\n'); + return length; + } + prev = last(this.tokens); + if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) { + return 0; + } + if (!(match = REGEX.exec(this.chunk))) return 0; + _ref3 = match, match = _ref3[0], regex = _ref3[1], flags = _ref3[2]; + if (regex.slice(0, 2) === '/*') { + this.error('regular expressions cannot begin with `*`'); + } + if (regex === '//') regex = '/(?:)/'; + this.token('REGEX', "" + regex + flags); + return match.length; + }; + + Lexer.prototype.heregexToken = function(match) { + var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5; + heregex = match[0], body = match[1], flags = match[2]; + if (0 > body.indexOf('#{')) { + re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/'); + if (re.match(/^\*/)) { + this.error('regular expressions cannot begin with `*`'); + } + this.token('REGEX', "/" + (re || '(?:)') + "/" + flags); + return heregex.length; + } + this.token('IDENTIFIER', 'RegExp'); + this.tokens.push(['CALL_START', '(']); + tokens = []; + _ref2 = this.interpolateString(body, { + regex: true + }); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1]; + if (tag === 'TOKENS') { + tokens.push.apply(tokens, value); + } else { + if (!(value = value.replace(HEREGEX_OMIT, ''))) continue; + value = value.replace(/\\/g, '\\\\'); + tokens.push(['STRING', this.makeString(value, '"', true)]); + } + tokens.push(['+', '+']); + } + tokens.pop(); + if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') { + this.tokens.push(['STRING', '""'], ['+', '+']); + } + (_ref5 = this.tokens).push.apply(_ref5, tokens); + if (flags) this.tokens.push([',', ','], ['STRING', '"' + flags + '"']); + this.token(')', ')'); + return heregex.length; + }; + + Lexer.prototype.lineToken = function() { + var diff, indent, match, noNewlines, prev, size; + if (!(match = MULTI_DENT.exec(this.chunk))) return 0; + indent = match[0]; + this.line += count(indent, '\n'); + this.seenFor = false; + prev = last(this.tokens, 1); + size = indent.length - 1 - indent.lastIndexOf('\n'); + noNewlines = this.unfinished(); + if (size - this.indebt === this.indent) { + if (noNewlines) { + this.suppressNewlines(); + } else { + this.newlineToken(); + } + return indent.length; + } + if (size > this.indent) { + if (noNewlines) { + this.indebt = size - this.indent; + this.suppressNewlines(); + return indent.length; + } + diff = size - this.indent + this.outdebt; + this.token('INDENT', diff); + this.indents.push(diff); + this.ends.push('OUTDENT'); + this.outdebt = this.indebt = 0; + } else { + this.indebt = 0; + this.outdentToken(this.indent - size, noNewlines); + } + this.indent = size; + return indent.length; + }; + + Lexer.prototype.outdentToken = function(moveOut, noNewlines) { + var dent, len; + while (moveOut > 0) { + len = this.indents.length - 1; + if (this.indents[len] === void 0) { + moveOut = 0; + } else if (this.indents[len] === this.outdebt) { + moveOut -= this.outdebt; + this.outdebt = 0; + } else if (this.indents[len] < this.outdebt) { + this.outdebt -= this.indents[len]; + moveOut -= this.indents[len]; + } else { + dent = this.indents.pop() - this.outdebt; + moveOut -= dent; + this.outdebt = 0; + this.pair('OUTDENT'); + this.token('OUTDENT', dent); + } + } + if (dent) this.outdebt -= moveOut; + while (this.value() === ';') { + this.tokens.pop(); + } + if (!(this.tag() === 'TERMINATOR' || noNewlines)) { + this.token('TERMINATOR', '\n'); + } + return this; + }; + + Lexer.prototype.whitespaceToken = function() { + var match, nline, prev; + if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) { + return 0; + } + prev = last(this.tokens); + if (prev) prev[match ? 'spaced' : 'newLine'] = true; + if (match) { + return match[0].length; + } else { + return 0; + } + }; + + Lexer.prototype.newlineToken = function() { + while (this.value() === ';') { + this.tokens.pop(); + } + if (this.tag() !== 'TERMINATOR') this.token('TERMINATOR', '\n'); + return this; + }; + + Lexer.prototype.suppressNewlines = function() { + if (this.value() === '\\') this.tokens.pop(); + return this; + }; + + Lexer.prototype.literalToken = function() { + var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5; + if (match = OPERATOR.exec(this.chunk)) { + value = match[0]; + if (CODE.test(value)) this.tagParameters(); + } else { + value = this.chunk.charAt(0); + } + tag = value; + prev = last(this.tokens); + if (value === '=' && prev) { + if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) { + this.error("reserved word \"" + (this.value()) + "\" can't be assigned"); + } + if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') { + prev[0] = 'COMPOUND_ASSIGN'; + prev[1] += '='; + return value.length; + } + } + if (value === ';') { + this.seenFor = false; + tag = 'TERMINATOR'; + } else if (__indexOf.call(MATH, value) >= 0) { + tag = 'MATH'; + } else if (__indexOf.call(COMPARE, value) >= 0) { + tag = 'COMPARE'; + } else if (__indexOf.call(COMPOUND_ASSIGN, value) >= 0) { + tag = 'COMPOUND_ASSIGN'; + } else if (__indexOf.call(UNARY, value) >= 0) { + tag = 'UNARY'; + } else if (__indexOf.call(SHIFT, value) >= 0) { + tag = 'SHIFT'; + } else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) { + tag = 'LOGIC'; + } else if (prev && !prev.spaced) { + if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) { + if (prev[0] === '?') prev[0] = 'FUNC_EXIST'; + tag = 'CALL_START'; + } else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) { + tag = 'INDEX_START'; + switch (prev[0]) { + case '?': + prev[0] = 'INDEX_SOAK'; + } + } + } + switch (value) { + case '(': + case '{': + case '[': + this.ends.push(INVERSES[value]); + break; + case ')': + case '}': + case ']': + this.pair(value); + } + this.token(tag, value); + return value.length; + }; + + Lexer.prototype.sanitizeHeredoc = function(doc, options) { + var attempt, herecomment, indent, match, _ref2; + indent = options.indent, herecomment = options.herecomment; + if (herecomment) { + if (HEREDOC_ILLEGAL.test(doc)) { + this.error("block comment cannot contain \"*/\", starting"); + } + if (doc.indexOf('\n') <= 0) return doc; + } else { + while (match = HEREDOC_INDENT.exec(doc)) { + attempt = match[1]; + if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) { + indent = attempt; + } + } + } + if (indent) doc = doc.replace(RegExp("\\n" + indent, "g"), '\n'); + if (!herecomment) doc = doc.replace(/^\n/, ''); + return doc; + }; + + Lexer.prototype.tagParameters = function() { + var i, stack, tok, tokens; + if (this.tag() !== ')') return this; + stack = []; + tokens = this.tokens; + i = tokens.length; + tokens[--i][0] = 'PARAM_END'; + while (tok = tokens[--i]) { + switch (tok[0]) { + case ')': + stack.push(tok); + break; + case '(': + case 'CALL_START': + if (stack.length) { + stack.pop(); + } else if (tok[0] === '(') { + tok[0] = 'PARAM_START'; + return this; + } else { + return this; + } + } + } + return this; + }; + + Lexer.prototype.closeIndentation = function() { + return this.outdentToken(this.indent); + }; + + Lexer.prototype.balancedString = function(str, end) { + var continueCount, i, letter, match, prev, stack, _i, _ref2; + continueCount = 0; + stack = [end]; + for (i = _i = 1, _ref2 = str.length; 1 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 1 <= _ref2 ? ++_i : --_i) { + if (continueCount) { + --continueCount; + continue; + } + switch (letter = str.charAt(i)) { + case '\\': + ++continueCount; + continue; + case end: + stack.pop(); + if (!stack.length) return str.slice(0, i + 1 || 9e9); + end = stack[stack.length - 1]; + continue; + } + if (end === '}' && (letter === '"' || letter === "'")) { + stack.push(end = letter); + } else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) { + continueCount += match[0].length - 1; + } else if (end === '}' && letter === '{') { + stack.push(end = '}'); + } else if (end === '"' && prev === '#' && letter === '{') { + stack.push(end = '}'); + } + prev = letter; + } + return this.error("missing " + (stack.pop()) + ", starting"); + }; + + Lexer.prototype.interpolateString = function(str, options) { + var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4; + if (options == null) options = {}; + heredoc = options.heredoc, regex = options.regex; + tokens = []; + pi = 0; + i = -1; + while (letter = str.charAt(i += 1)) { + if (letter === '\\') { + i += 1; + continue; + } + if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) { + continue; + } + if (pi < i) tokens.push(['NEOSTRING', str.slice(pi, i)]); + inner = expr.slice(1, -1); + if (inner.length) { + nested = new Lexer().tokenize(inner, { + line: this.line, + rewrite: false + }); + nested.pop(); + if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') { + nested.shift(); + } + if (len = nested.length) { + if (len > 1) { + nested.unshift(['(', '(', this.line]); + nested.push([')', ')', this.line]); + } + tokens.push(['TOKENS', nested]); + } + } + i += expr.length; + pi = i + 1; + } + if ((i > pi && pi < str.length)) tokens.push(['NEOSTRING', str.slice(pi)]); + if (regex) return tokens; + if (!tokens.length) return this.token('STRING', '""'); + if (tokens[0][0] !== 'NEOSTRING') tokens.unshift(['', '']); + if (interpolated = tokens.length > 1) this.token('(', '('); + for (i = _i = 0, _len = tokens.length; _i < _len; i = ++_i) { + _ref3 = tokens[i], tag = _ref3[0], value = _ref3[1]; + if (i) this.token('+', '+'); + if (tag === 'TOKENS') { + (_ref4 = this.tokens).push.apply(_ref4, value); + } else { + this.token('STRING', this.makeString(value, '"', heredoc)); + } + } + if (interpolated) this.token(')', ')'); + return tokens; + }; + + Lexer.prototype.pair = function(tag) { + var size, wanted; + if (tag !== (wanted = last(this.ends))) { + if ('OUTDENT' !== wanted) this.error("unmatched " + tag); + this.indent -= size = last(this.indents); + this.outdentToken(size, true); + return this.pair(tag); + } + return this.ends.pop(); + }; + + Lexer.prototype.token = function(tag, value) { + return this.tokens.push([tag, value, this.line]); + }; + + Lexer.prototype.tag = function(index, tag) { + var tok; + return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]); + }; + + Lexer.prototype.value = function(index, val) { + var tok; + return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]); + }; + + Lexer.prototype.unfinished = function() { + var _ref2; + return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS'); + }; + + Lexer.prototype.escapeLines = function(str, heredoc) { + return str.replace(MULTILINER, heredoc ? '\\n' : ''); + }; + + Lexer.prototype.makeString = function(body, quote, heredoc) { + if (!body) return quote + quote; + body = body.replace(/\\([\s\S])/g, function(match, contents) { + if (contents === '\n' || contents === quote) { + return contents; + } else { + return match; + } + }); + body = body.replace(RegExp("" + quote, "g"), '\\$&'); + return quote + this.escapeLines(body, heredoc) + quote; + }; + + Lexer.prototype.error = function(message) { + throw SyntaxError("" + message + " on line " + (this.line + 1)); + }; + + return Lexer; + + })(); + + JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super']; + + COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when']; + + COFFEE_ALIAS_MAP = { + and: '&&', + or: '||', + is: '==', + isnt: '!=', + not: '!', + yes: 'true', + no: 'false', + on: 'true', + off: 'false' + }; + + COFFEE_ALIASES = (function() { + var _results; + _results = []; + for (key in COFFEE_ALIAS_MAP) { + _results.push(key); + } + return _results; + })(); + + COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES); + + RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf', 'implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static', 'yield']; + + STRICT_PROSCRIBED = ['arguments', 'eval']; + + JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED); + + exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED); + + exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED; + + IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/; + + NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i; + + HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/; + + OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/; + + WHITESPACE = /^[^\n\S]+/; + + COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/; + + CODE = /^[-=]>/; + + MULTI_DENT = /^(?:\n[^\n\S]*)+/; + + SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/; + + JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/; + + REGEX = /^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/; + + HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/; + + HEREGEX_OMIT = /\s+(?:#.*)?/g; + + MULTILINER = /\n/g; + + HEREDOC_INDENT = /\n+([^\n\S]*)/g; + + HEREDOC_ILLEGAL = /\*\//; + + LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/; + + TRAILING_SPACES = /\s+$/; + + COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|=']; + + UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO']; + + LOGIC = ['&&', '||', '&', '|', '^']; + + SHIFT = ['<<', '>>', '>>>']; + + COMPARE = ['==', '!=', '<', '>', '<=', '>=']; + + MATH = ['*', '/', '%']; + + RELATION = ['IN', 'OF', 'INSTANCEOF']; + + BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED']; + + NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']']; + + NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING'); + + CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER']; + + INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL'); + + LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']; + + +}); + +define('ace/mode/coffee/rewriter', ['require', 'exports', 'module' ], function(require, exports, module) { +// Generated by CoffeeScript 1.2.1-pre + + var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + __slice = [].slice; + + exports.Rewriter = (function() { + + Rewriter.name = 'Rewriter'; + + function Rewriter() {} + + Rewriter.prototype.rewrite = function(tokens) { + this.tokens = tokens; + this.removeLeadingNewlines(); + this.removeMidExpressionNewlines(); + this.closeOpenCalls(); + this.closeOpenIndexes(); + this.addImplicitIndentation(); + this.tagPostfixConditionals(); + this.addImplicitBraces(); + this.addImplicitParentheses(); + return this.tokens; + }; + + Rewriter.prototype.scanTokens = function(block) { + var i, token, tokens; + tokens = this.tokens; + i = 0; + while (token = tokens[i]) { + i += block.call(this, token, i, tokens); + } + return true; + }; + + Rewriter.prototype.detectEnd = function(i, condition, action) { + var levels, token, tokens, _ref, _ref1; + tokens = this.tokens; + levels = 0; + while (token = tokens[i]) { + if (levels === 0 && condition.call(this, token, i)) { + return action.call(this, token, i); + } + if (!token || levels < 0) return action.call(this, token, i - 1); + if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) { + levels += 1; + } else if (_ref1 = token[0], __indexOf.call(EXPRESSION_END, _ref1) >= 0) { + levels -= 1; + } + i += 1; + } + return i - 1; + }; + + Rewriter.prototype.removeLeadingNewlines = function() { + var i, tag, _i, _len, _ref; + _ref = this.tokens; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + tag = _ref[i][0]; + if (tag !== 'TERMINATOR') break; + } + if (i) return this.tokens.splice(0, i); + }; + + Rewriter.prototype.removeMidExpressionNewlines = function() { + return this.scanTokens(function(token, i, tokens) { + var _ref; + if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) { + return 1; + } + tokens.splice(i, 1); + return 0; + }); + }; + + Rewriter.prototype.closeOpenCalls = function() { + var action, condition; + condition = function(token, i) { + var _ref; + return ((_ref = token[0]) === ')' || _ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')'; + }; + action = function(token, i) { + return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END'; + }; + return this.scanTokens(function(token, i) { + if (token[0] === 'CALL_START') this.detectEnd(i + 1, condition, action); + return 1; + }); + }; + + Rewriter.prototype.closeOpenIndexes = function() { + var action, condition; + condition = function(token, i) { + var _ref; + return (_ref = token[0]) === ']' || _ref === 'INDEX_END'; + }; + action = function(token, i) { + return token[0] = 'INDEX_END'; + }; + return this.scanTokens(function(token, i) { + if (token[0] === 'INDEX_START') this.detectEnd(i + 1, condition, action); + return 1; + }); + }; + + Rewriter.prototype.addImplicitBraces = function() { + var action, condition, sameLine, stack, start, startIndent, startsLine; + stack = []; + start = null; + startsLine = null; + sameLine = true; + startIndent = 0; + condition = function(token, i) { + var one, tag, three, two, _ref, _ref1; + _ref = this.tokens.slice(i + 1, (i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2]; + if ('HERECOMMENT' === (one != null ? one[0] : void 0)) return false; + tag = token[0]; + if (__indexOf.call(LINEBREAKS, tag) >= 0) sameLine = false; + return (((tag === 'TERMINATOR' || tag === 'OUTDENT') || (__indexOf.call(IMPLICIT_END, tag) >= 0 && sameLine)) && ((!startsLine && this.tag(i - 1) !== ',') || !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':'))) || (tag === ',' && one && ((_ref1 = one[0]) !== 'IDENTIFIER' && _ref1 !== 'NUMBER' && _ref1 !== 'STRING' && _ref1 !== '@' && _ref1 !== 'TERMINATOR' && _ref1 !== 'OUTDENT')); + }; + action = function(token, i) { + var tok; + tok = this.generate('}', '}', token[2]); + return this.tokens.splice(i, 0, tok); + }; + return this.scanTokens(function(token, i, tokens) { + var ago, idx, prevTag, tag, tok, value, _ref, _ref1; + if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) { + stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]); + return 1; + } + if (__indexOf.call(EXPRESSION_END, tag) >= 0) { + start = stack.pop(); + return 1; + } + if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref1 = stack[stack.length - 1]) != null ? _ref1[0] : void 0) !== '{'))) { + return 1; + } + sameLine = true; + stack.push(['{']); + idx = ago === '@' ? i - 2 : i - 1; + while (this.tag(idx - 2) === 'HERECOMMENT') { + idx -= 2; + } + prevTag = this.tag(idx - 1); + startsLine = !prevTag || (__indexOf.call(LINEBREAKS, prevTag) >= 0); + value = new String('{'); + value.generated = true; + tok = this.generate('{', value, token[2]); + tokens.splice(idx, 0, tok); + this.detectEnd(i + 2, condition, action); + return 2; + }); + }; + + Rewriter.prototype.addImplicitParentheses = function() { + var action, condition, noCall, seenControl, seenSingle; + noCall = seenSingle = seenControl = false; + condition = function(token, i) { + var post, tag, _ref, _ref1; + tag = token[0]; + if (!seenSingle && token.fromThen) return true; + if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>' || tag === 'CLASS') { + seenSingle = true; + } + if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY' || tag === '=') { + seenControl = true; + } + if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') { + return true; + } + return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (((_ref = this.tag(i - 2)) !== 'CLASS' && _ref !== 'EXTENDS') && (_ref1 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref1) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{'))); + }; + action = function(token, i) { + return this.tokens.splice(i, 0, this.generate('CALL_END', ')', token[2])); + }; + return this.scanTokens(function(token, i, tokens) { + var callObject, current, next, prev, tag, _ref, _ref1, _ref2; + tag = token[0]; + if (tag === 'CLASS' || tag === 'IF' || tag === 'FOR' || tag === 'WHILE') { + noCall = true; + } + _ref = tokens.slice(i - 1, (i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2]; + callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref1 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref1) >= 0); + seenSingle = false; + seenControl = false; + if (__indexOf.call(LINEBREAKS, tag) >= 0) noCall = false; + if (prev && !prev.spaced && tag === '?') token.call = true; + if (token.fromThen) return 1; + if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) { + return 1; + } + tokens.splice(i, 0, this.generate('CALL_START', '(', token[2])); + this.detectEnd(i + 1, condition, action); + if (prev[0] === '?') prev[0] = 'FUNC_EXIST'; + return 2; + }); + }; + + Rewriter.prototype.addImplicitIndentation = function() { + var action, condition, indent, outdent, starter; + starter = indent = outdent = null; + condition = function(token, i) { + var _ref; + return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN')); + }; + action = function(token, i) { + return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent); + }; + return this.scanTokens(function(token, i, tokens) { + var tag, _ref, _ref1; + tag = token[0]; + if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') { + tokens.splice(i, 1); + return 0; + } + if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') { + tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation(token)))); + return 2; + } + if (tag === 'CATCH' && ((_ref = this.tag(i + 2)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) { + tokens.splice.apply(tokens, [i + 2, 0].concat(__slice.call(this.indentation(token)))); + return 4; + } + if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) { + starter = tag; + _ref1 = this.indentation(token, true), indent = _ref1[0], outdent = _ref1[1]; + if (starter === 'THEN') indent.fromThen = true; + tokens.splice(i + 1, 0, indent); + this.detectEnd(i + 2, condition, action); + if (tag === 'THEN') tokens.splice(i, 1); + return 1; + } + return 1; + }); + }; + + Rewriter.prototype.tagPostfixConditionals = function() { + var action, condition, original; + original = null; + condition = function(token, i) { + var _ref; + return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT'; + }; + action = function(token, i) { + if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) { + return original[0] = 'POST_' + original[0]; + } + }; + return this.scanTokens(function(token, i) { + if (token[0] !== 'IF') return 1; + original = token; + this.detectEnd(i + 1, condition, action); + return 1; + }); + }; + + Rewriter.prototype.indentation = function(token, implicit) { + var indent, outdent; + if (implicit == null) implicit = false; + indent = ['INDENT', 2, token[2]]; + outdent = ['OUTDENT', 2, token[2]]; + if (implicit) indent.generated = outdent.generated = true; + return [indent, outdent]; + }; + + Rewriter.prototype.generate = function(tag, value, line) { + var tok; + tok = [tag, value, line]; + tok.generated = true; + return tok; + }; + + Rewriter.prototype.tag = function(i) { + var _ref; + return (_ref = this.tokens[i]) != null ? _ref[0] : void 0; + }; + + return Rewriter; + + })(); + + BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']]; + + exports.INVERSES = INVERSES = {}; + + EXPRESSION_START = []; + + EXPRESSION_END = []; + + for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) { + _ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1]; + EXPRESSION_START.push(INVERSES[rite] = left); + EXPRESSION_END.push(INVERSES[left] = rite); + } + + EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END); + + IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']; + + IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++']; + + IMPLICIT_UNSPACED_CALL = ['+', '-']; + + IMPLICIT_BLOCK = ['->', '=>', '{', '[', ',']; + + IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR']; + + SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN']; + + SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN']; + + LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT']; + + +}); + +define('ace/mode/coffee/helpers', ['require', 'exports', 'module' ], function(require, exports, module) { +// Generated by CoffeeScript 1.2.1-pre + + var extend, flatten; + + exports.starts = function(string, literal, start) { + return literal === string.substr(start, literal.length); + }; + + exports.ends = function(string, literal, back) { + var len; + len = literal.length; + return literal === string.substr(string.length - len - (back || 0), len); + }; + + exports.compact = function(array) { + var item, _i, _len, _results; + _results = []; + for (_i = 0, _len = array.length; _i < _len; _i++) { + item = array[_i]; + if (item) _results.push(item); + } + return _results; + }; + + exports.count = function(string, substr) { + var num, pos; + num = pos = 0; + if (!substr.length) return 1 / 0; + while (pos = 1 + string.indexOf(substr, pos)) { + num++; + } + return num; + }; + + exports.merge = function(options, overrides) { + return extend(extend({}, options), overrides); + }; + + extend = exports.extend = function(object, properties) { + var key, val; + for (key in properties) { + val = properties[key]; + object[key] = val; + } + return object; + }; + + exports.flatten = flatten = function(array) { + var element, flattened, _i, _len; + flattened = []; + for (_i = 0, _len = array.length; _i < _len; _i++) { + element = array[_i]; + if (element instanceof Array) { + flattened = flattened.concat(flatten(element)); + } else { + flattened.push(element); + } + } + return flattened; + }; + + exports.del = function(obj, key) { + var val; + val = obj[key]; + delete obj[key]; + return val; + }; + + exports.last = function(array, back) { + return array[array.length - (back || 0) - 1]; + }; + + +}); + +define('ace/mode/coffee/parser', ['require', 'exports', 'module' ], function(require, exports, module) { +/* Jison generated parser */ + +undefined +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"Root":3,"Body":4,"Block":5,"TERMINATOR":6,"Line":7,"Expression":8,"Statement":9,"Return":10,"Comment":11,"STATEMENT":12,"Value":13,"Invocation":14,"Code":15,"Operation":16,"Assign":17,"If":18,"Try":19,"While":20,"For":21,"Switch":22,"Class":23,"Throw":24,"INDENT":25,"OUTDENT":26,"Identifier":27,"IDENTIFIER":28,"AlphaNumeric":29,"NUMBER":30,"STRING":31,"Literal":32,"JS":33,"REGEX":34,"DEBUGGER":35,"BOOL":36,"Assignable":37,"=":38,"AssignObj":39,"ObjAssignable":40,":":41,"ThisProperty":42,"RETURN":43,"HERECOMMENT":44,"PARAM_START":45,"ParamList":46,"PARAM_END":47,"FuncGlyph":48,"->":49,"=>":50,"OptComma":51,",":52,"Param":53,"ParamVar":54,"...":55,"Array":56,"Object":57,"Splat":58,"SimpleAssignable":59,"Accessor":60,"Parenthetical":61,"Range":62,"This":63,".":64,"?.":65,"::":66,"Index":67,"INDEX_START":68,"IndexValue":69,"INDEX_END":70,"INDEX_SOAK":71,"Slice":72,"{":73,"AssignList":74,"}":75,"CLASS":76,"EXTENDS":77,"OptFuncExist":78,"Arguments":79,"SUPER":80,"FUNC_EXIST":81,"CALL_START":82,"CALL_END":83,"ArgList":84,"THIS":85,"@":86,"[":87,"]":88,"RangeDots":89,"..":90,"Arg":91,"SimpleArgs":92,"TRY":93,"Catch":94,"FINALLY":95,"CATCH":96,"THROW":97,"(":98,")":99,"WhileSource":100,"WHILE":101,"WHEN":102,"UNTIL":103,"Loop":104,"LOOP":105,"ForBody":106,"FOR":107,"ForStart":108,"ForSource":109,"ForVariables":110,"OWN":111,"ForValue":112,"FORIN":113,"FOROF":114,"BY":115,"SWITCH":116,"Whens":117,"ELSE":118,"When":119,"LEADING_WHEN":120,"IfBlock":121,"IF":122,"POST_IF":123,"UNARY":124,"-":125,"+":126,"--":127,"++":128,"?":129,"MATH":130,"SHIFT":131,"COMPARE":132,"LOGIC":133,"RELATION":134,"COMPOUND_ASSIGN":135,"$accept":0,"$end":1}, +terminals_: {2:"error",6:"TERMINATOR",12:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"DEBUGGER",36:"BOOL",38:"=",41:":",43:"RETURN",44:"HERECOMMENT",45:"PARAM_START",47:"PARAM_END",49:"->",50:"=>",52:",",55:"...",64:".",65:"?.",66:"::",68:"INDEX_START",70:"INDEX_END",71:"INDEX_SOAK",73:"{",75:"}",76:"CLASS",77:"EXTENDS",80:"SUPER",81:"FUNC_EXIST",82:"CALL_START",83:"CALL_END",85:"THIS",86:"@",87:"[",88:"]",90:"..",93:"TRY",95:"FINALLY",96:"CATCH",97:"THROW",98:"(",99:")",101:"WHILE",102:"WHEN",103:"UNTIL",105:"LOOP",107:"FOR",111:"OWN",113:"FORIN",114:"FOROF",115:"BY",116:"SWITCH",118:"ELSE",120:"LEADING_WHEN",122:"IF",123:"POST_IF",124:"UNARY",125:"-",126:"+",127:"--",128:"++",129:"?",130:"MATH",131:"SHIFT",132:"COMPARE",133:"LOGIC",134:"RELATION",135:"COMPOUND_ASSIGN"}, +productions_: [0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[17,3],[17,4],[17,5],[39,1],[39,3],[39,5],[39,1],[40,1],[40,1],[40,1],[10,2],[10,1],[11,1],[15,5],[15,2],[48,1],[48,1],[51,0],[51,1],[46,0],[46,1],[46,3],[53,1],[53,2],[53,3],[54,1],[54,1],[54,1],[54,1],[58,2],[59,1],[59,2],[59,2],[59,1],[37,1],[37,1],[37,1],[13,1],[13,1],[13,1],[13,1],[13,1],[60,2],[60,2],[60,2],[60,1],[60,1],[67,3],[67,2],[69,1],[69,1],[57,4],[74,0],[74,1],[74,3],[74,4],[74,6],[23,1],[23,2],[23,3],[23,4],[23,2],[23,3],[23,4],[23,5],[14,3],[14,3],[14,1],[14,2],[78,0],[78,1],[79,2],[79,4],[63,1],[63,1],[42,2],[56,2],[56,4],[89,1],[89,1],[62,5],[72,3],[72,2],[72,2],[72,1],[84,1],[84,3],[84,4],[84,4],[84,6],[91,1],[91,1],[92,1],[92,3],[19,2],[19,3],[19,4],[19,5],[94,3],[24,2],[61,3],[61,5],[100,2],[100,4],[100,2],[100,4],[20,2],[20,2],[20,2],[20,1],[104,2],[104,2],[21,2],[21,2],[21,2],[106,2],[106,2],[108,2],[108,3],[112,1],[112,1],[112,1],[110,1],[110,3],[109,2],[109,2],[109,4],[109,4],[109,4],[109,6],[109,6],[22,5],[22,7],[22,4],[22,6],[117,1],[117,2],[119,3],[119,4],[121,3],[121,5],[18,1],[18,3],[18,3],[18,3],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,5],[16,3]], +performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + +var $0 = $$.length - 1; +switch (yystate) { +case 1:return this.$ = new yy.Block; +break; +case 2:return this.$ = $$[$0]; +break; +case 3:return this.$ = $$[$0-1]; +break; +case 4:this.$ = yy.Block.wrap([$$[$0]]); +break; +case 5:this.$ = $$[$0-2].push($$[$0]); +break; +case 6:this.$ = $$[$0-1]; +break; +case 7:this.$ = $$[$0]; +break; +case 8:this.$ = $$[$0]; +break; +case 9:this.$ = $$[$0]; +break; +case 10:this.$ = $$[$0]; +break; +case 11:this.$ = new yy.Literal($$[$0]); +break; +case 12:this.$ = $$[$0]; +break; +case 13:this.$ = $$[$0]; +break; +case 14:this.$ = $$[$0]; +break; +case 15:this.$ = $$[$0]; +break; +case 16:this.$ = $$[$0]; +break; +case 17:this.$ = $$[$0]; +break; +case 18:this.$ = $$[$0]; +break; +case 19:this.$ = $$[$0]; +break; +case 20:this.$ = $$[$0]; +break; +case 21:this.$ = $$[$0]; +break; +case 22:this.$ = $$[$0]; +break; +case 23:this.$ = $$[$0]; +break; +case 24:this.$ = new yy.Block; +break; +case 25:this.$ = $$[$0-1]; +break; +case 26:this.$ = new yy.Literal($$[$0]); +break; +case 27:this.$ = new yy.Literal($$[$0]); +break; +case 28:this.$ = new yy.Literal($$[$0]); +break; +case 29:this.$ = $$[$0]; +break; +case 30:this.$ = new yy.Literal($$[$0]); +break; +case 31:this.$ = new yy.Literal($$[$0]); +break; +case 32:this.$ = new yy.Literal($$[$0]); +break; +case 33:this.$ = (function () { + var val; + val = new yy.Literal($$[$0]); + if ($$[$0] === 'undefined') val.isUndefined = true; + return val; + }()); +break; +case 34:this.$ = new yy.Assign($$[$0-2], $$[$0]); +break; +case 35:this.$ = new yy.Assign($$[$0-3], $$[$0]); +break; +case 36:this.$ = new yy.Assign($$[$0-4], $$[$0-1]); +break; +case 37:this.$ = new yy.Value($$[$0]); +break; +case 38:this.$ = new yy.Assign(new yy.Value($$[$0-2]), $$[$0], 'object'); +break; +case 39:this.$ = new yy.Assign(new yy.Value($$[$0-4]), $$[$0-1], 'object'); +break; +case 40:this.$ = $$[$0]; +break; +case 41:this.$ = $$[$0]; +break; +case 42:this.$ = $$[$0]; +break; +case 43:this.$ = $$[$0]; +break; +case 44:this.$ = new yy.Return($$[$0]); +break; +case 45:this.$ = new yy.Return; +break; +case 46:this.$ = new yy.Comment($$[$0]); +break; +case 47:this.$ = new yy.Code($$[$0-3], $$[$0], $$[$0-1]); +break; +case 48:this.$ = new yy.Code([], $$[$0], $$[$0-1]); +break; +case 49:this.$ = 'func'; +break; +case 50:this.$ = 'boundfunc'; +break; +case 51:this.$ = $$[$0]; +break; +case 52:this.$ = $$[$0]; +break; +case 53:this.$ = []; +break; +case 54:this.$ = [$$[$0]]; +break; +case 55:this.$ = $$[$0-2].concat($$[$0]); +break; +case 56:this.$ = new yy.Param($$[$0]); +break; +case 57:this.$ = new yy.Param($$[$0-1], null, true); +break; +case 58:this.$ = new yy.Param($$[$0-2], $$[$0]); +break; +case 59:this.$ = $$[$0]; +break; +case 60:this.$ = $$[$0]; +break; +case 61:this.$ = $$[$0]; +break; +case 62:this.$ = $$[$0]; +break; +case 63:this.$ = new yy.Splat($$[$0-1]); +break; +case 64:this.$ = new yy.Value($$[$0]); +break; +case 65:this.$ = $$[$0-1].add($$[$0]); +break; +case 66:this.$ = new yy.Value($$[$0-1], [].concat($$[$0])); +break; +case 67:this.$ = $$[$0]; +break; +case 68:this.$ = $$[$0]; +break; +case 69:this.$ = new yy.Value($$[$0]); +break; +case 70:this.$ = new yy.Value($$[$0]); +break; +case 71:this.$ = $$[$0]; +break; +case 72:this.$ = new yy.Value($$[$0]); +break; +case 73:this.$ = new yy.Value($$[$0]); +break; +case 74:this.$ = new yy.Value($$[$0]); +break; +case 75:this.$ = $$[$0]; +break; +case 76:this.$ = new yy.Access($$[$0]); +break; +case 77:this.$ = new yy.Access($$[$0], 'soak'); +break; +case 78:this.$ = [new yy.Access(new yy.Literal('prototype')), new yy.Access($$[$0])]; +break; +case 79:this.$ = new yy.Access(new yy.Literal('prototype')); +break; +case 80:this.$ = $$[$0]; +break; +case 81:this.$ = $$[$0-1]; +break; +case 82:this.$ = yy.extend($$[$0], { + soak: true + }); +break; +case 83:this.$ = new yy.Index($$[$0]); +break; +case 84:this.$ = new yy.Slice($$[$0]); +break; +case 85:this.$ = new yy.Obj($$[$0-2], $$[$0-3].generated); +break; +case 86:this.$ = []; +break; +case 87:this.$ = [$$[$0]]; +break; +case 88:this.$ = $$[$0-2].concat($$[$0]); +break; +case 89:this.$ = $$[$0-3].concat($$[$0]); +break; +case 90:this.$ = $$[$0-5].concat($$[$0-2]); +break; +case 91:this.$ = new yy.Class; +break; +case 92:this.$ = new yy.Class(null, null, $$[$0]); +break; +case 93:this.$ = new yy.Class(null, $$[$0]); +break; +case 94:this.$ = new yy.Class(null, $$[$0-1], $$[$0]); +break; +case 95:this.$ = new yy.Class($$[$0]); +break; +case 96:this.$ = new yy.Class($$[$0-1], null, $$[$0]); +break; +case 97:this.$ = new yy.Class($$[$0-2], $$[$0]); +break; +case 98:this.$ = new yy.Class($$[$0-3], $$[$0-1], $$[$0]); +break; +case 99:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]); +break; +case 100:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]); +break; +case 101:this.$ = new yy.Call('super', [new yy.Splat(new yy.Literal('arguments'))]); +break; +case 102:this.$ = new yy.Call('super', $$[$0]); +break; +case 103:this.$ = false; +break; +case 104:this.$ = true; +break; +case 105:this.$ = []; +break; +case 106:this.$ = $$[$0-2]; +break; +case 107:this.$ = new yy.Value(new yy.Literal('this')); +break; +case 108:this.$ = new yy.Value(new yy.Literal('this')); +break; +case 109:this.$ = new yy.Value(new yy.Literal('this'), [new yy.Access($$[$0])], 'this'); +break; +case 110:this.$ = new yy.Arr([]); +break; +case 111:this.$ = new yy.Arr($$[$0-2]); +break; +case 112:this.$ = 'inclusive'; +break; +case 113:this.$ = 'exclusive'; +break; +case 114:this.$ = new yy.Range($$[$0-3], $$[$0-1], $$[$0-2]); +break; +case 115:this.$ = new yy.Range($$[$0-2], $$[$0], $$[$0-1]); +break; +case 116:this.$ = new yy.Range($$[$0-1], null, $$[$0]); +break; +case 117:this.$ = new yy.Range(null, $$[$0], $$[$0-1]); +break; +case 118:this.$ = new yy.Range(null, null, $$[$0]); +break; +case 119:this.$ = [$$[$0]]; +break; +case 120:this.$ = $$[$0-2].concat($$[$0]); +break; +case 121:this.$ = $$[$0-3].concat($$[$0]); +break; +case 122:this.$ = $$[$0-2]; +break; +case 123:this.$ = $$[$0-5].concat($$[$0-2]); +break; +case 124:this.$ = $$[$0]; +break; +case 125:this.$ = $$[$0]; +break; +case 126:this.$ = $$[$0]; +break; +case 127:this.$ = [].concat($$[$0-2], $$[$0]); +break; +case 128:this.$ = new yy.Try($$[$0]); +break; +case 129:this.$ = new yy.Try($$[$0-1], $$[$0][0], $$[$0][1]); +break; +case 130:this.$ = new yy.Try($$[$0-2], null, null, $$[$0]); +break; +case 131:this.$ = new yy.Try($$[$0-3], $$[$0-2][0], $$[$0-2][1], $$[$0]); +break; +case 132:this.$ = [$$[$0-1], $$[$0]]; +break; +case 133:this.$ = new yy.Throw($$[$0]); +break; +case 134:this.$ = new yy.Parens($$[$0-1]); +break; +case 135:this.$ = new yy.Parens($$[$0-2]); +break; +case 136:this.$ = new yy.While($$[$0]); +break; +case 137:this.$ = new yy.While($$[$0-2], { + guard: $$[$0] + }); +break; +case 138:this.$ = new yy.While($$[$0], { + invert: true + }); +break; +case 139:this.$ = new yy.While($$[$0-2], { + invert: true, + guard: $$[$0] + }); +break; +case 140:this.$ = $$[$0-1].addBody($$[$0]); +break; +case 141:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]])); +break; +case 142:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]])); +break; +case 143:this.$ = $$[$0]; +break; +case 144:this.$ = new yy.While(new yy.Literal('true')).addBody($$[$0]); +break; +case 145:this.$ = new yy.While(new yy.Literal('true')).addBody(yy.Block.wrap([$$[$0]])); +break; +case 146:this.$ = new yy.For($$[$0-1], $$[$0]); +break; +case 147:this.$ = new yy.For($$[$0-1], $$[$0]); +break; +case 148:this.$ = new yy.For($$[$0], $$[$0-1]); +break; +case 149:this.$ = { + source: new yy.Value($$[$0]) + }; +break; +case 150:this.$ = (function () { + $$[$0].own = $$[$0-1].own; + $$[$0].name = $$[$0-1][0]; + $$[$0].index = $$[$0-1][1]; + return $$[$0]; + }()); +break; +case 151:this.$ = $$[$0]; +break; +case 152:this.$ = (function () { + $$[$0].own = true; + return $$[$0]; + }()); +break; +case 153:this.$ = $$[$0]; +break; +case 154:this.$ = new yy.Value($$[$0]); +break; +case 155:this.$ = new yy.Value($$[$0]); +break; +case 156:this.$ = [$$[$0]]; +break; +case 157:this.$ = [$$[$0-2], $$[$0]]; +break; +case 158:this.$ = { + source: $$[$0] + }; +break; +case 159:this.$ = { + source: $$[$0], + object: true + }; +break; +case 160:this.$ = { + source: $$[$0-2], + guard: $$[$0] + }; +break; +case 161:this.$ = { + source: $$[$0-2], + guard: $$[$0], + object: true + }; +break; +case 162:this.$ = { + source: $$[$0-2], + step: $$[$0] + }; +break; +case 163:this.$ = { + source: $$[$0-4], + guard: $$[$0-2], + step: $$[$0] + }; +break; +case 164:this.$ = { + source: $$[$0-4], + step: $$[$0-2], + guard: $$[$0] + }; +break; +case 165:this.$ = new yy.Switch($$[$0-3], $$[$0-1]); +break; +case 166:this.$ = new yy.Switch($$[$0-5], $$[$0-3], $$[$0-1]); +break; +case 167:this.$ = new yy.Switch(null, $$[$0-1]); +break; +case 168:this.$ = new yy.Switch(null, $$[$0-3], $$[$0-1]); +break; +case 169:this.$ = $$[$0]; +break; +case 170:this.$ = $$[$0-1].concat($$[$0]); +break; +case 171:this.$ = [[$$[$0-1], $$[$0]]]; +break; +case 172:this.$ = [[$$[$0-2], $$[$0-1]]]; +break; +case 173:this.$ = new yy.If($$[$0-1], $$[$0], { + type: $$[$0-2] + }); +break; +case 174:this.$ = $$[$0-4].addElse(new yy.If($$[$0-1], $$[$0], { + type: $$[$0-2] + })); +break; +case 175:this.$ = $$[$0]; +break; +case 176:this.$ = $$[$0-2].addElse($$[$0]); +break; +case 177:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), { + type: $$[$0-1], + statement: true + }); +break; +case 178:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), { + type: $$[$0-1], + statement: true + }); +break; +case 179:this.$ = new yy.Op($$[$0-1], $$[$0]); +break; +case 180:this.$ = new yy.Op('-', $$[$0]); +break; +case 181:this.$ = new yy.Op('+', $$[$0]); +break; +case 182:this.$ = new yy.Op('--', $$[$0]); +break; +case 183:this.$ = new yy.Op('++', $$[$0]); +break; +case 184:this.$ = new yy.Op('--', $$[$0-1], null, true); +break; +case 185:this.$ = new yy.Op('++', $$[$0-1], null, true); +break; +case 186:this.$ = new yy.Existence($$[$0-1]); +break; +case 187:this.$ = new yy.Op('+', $$[$0-2], $$[$0]); +break; +case 188:this.$ = new yy.Op('-', $$[$0-2], $$[$0]); +break; +case 189:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 190:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 191:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 192:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 193:this.$ = (function () { + if ($$[$0-1].charAt(0) === '!') { + return new yy.Op($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert(); + } else { + return new yy.Op($$[$0-1], $$[$0-2], $$[$0]); + } + }()); +break; +case 194:this.$ = new yy.Assign($$[$0-2], $$[$0], $$[$0-1]); +break; +case 195:this.$ = new yy.Assign($$[$0-4], $$[$0-1], $$[$0-3]); +break; +case 196:this.$ = new yy.Extends($$[$0-2], $$[$0]); +break; +} +}, +table: [{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[3]},{1:[2,2],6:[1,72]},{6:[1,73]},{1:[2,4],6:[2,4],26:[2,4],99:[2,4]},{4:75,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[1,74],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,7],6:[2,7],26:[2,7],99:[2,7],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,8],6:[2,8],26:[2,8],99:[2,8],100:88,101:[1,63],103:[1,64],106:89,107:[1,66],108:67,123:[1,87]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],47:[2,12],52:[2,12],55:[2,12],60:91,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],70:[2,12],71:[1,98],75:[2,12],78:90,81:[1,92],82:[2,103],83:[2,12],88:[2,12],90:[2,12],99:[2,12],101:[2,12],102:[2,12],103:[2,12],107:[2,12],115:[2,12],123:[2,12],125:[2,12],126:[2,12],129:[2,12],130:[2,12],131:[2,12],132:[2,12],133:[2,12],134:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],47:[2,13],52:[2,13],55:[2,13],60:100,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],70:[2,13],71:[1,98],75:[2,13],78:99,81:[1,92],82:[2,103],83:[2,13],88:[2,13],90:[2,13],99:[2,13],101:[2,13],102:[2,13],103:[2,13],107:[2,13],115:[2,13],123:[2,13],125:[2,13],126:[2,13],129:[2,13],130:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],47:[2,14],52:[2,14],55:[2,14],70:[2,14],75:[2,14],83:[2,14],88:[2,14],90:[2,14],99:[2,14],101:[2,14],102:[2,14],103:[2,14],107:[2,14],115:[2,14],123:[2,14],125:[2,14],126:[2,14],129:[2,14],130:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],47:[2,15],52:[2,15],55:[2,15],70:[2,15],75:[2,15],83:[2,15],88:[2,15],90:[2,15],99:[2,15],101:[2,15],102:[2,15],103:[2,15],107:[2,15],115:[2,15],123:[2,15],125:[2,15],126:[2,15],129:[2,15],130:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],47:[2,16],52:[2,16],55:[2,16],70:[2,16],75:[2,16],83:[2,16],88:[2,16],90:[2,16],99:[2,16],101:[2,16],102:[2,16],103:[2,16],107:[2,16],115:[2,16],123:[2,16],125:[2,16],126:[2,16],129:[2,16],130:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],47:[2,17],52:[2,17],55:[2,17],70:[2,17],75:[2,17],83:[2,17],88:[2,17],90:[2,17],99:[2,17],101:[2,17],102:[2,17],103:[2,17],107:[2,17],115:[2,17],123:[2,17],125:[2,17],126:[2,17],129:[2,17],130:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],47:[2,18],52:[2,18],55:[2,18],70:[2,18],75:[2,18],83:[2,18],88:[2,18],90:[2,18],99:[2,18],101:[2,18],102:[2,18],103:[2,18],107:[2,18],115:[2,18],123:[2,18],125:[2,18],126:[2,18],129:[2,18],130:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],47:[2,19],52:[2,19],55:[2,19],70:[2,19],75:[2,19],83:[2,19],88:[2,19],90:[2,19],99:[2,19],101:[2,19],102:[2,19],103:[2,19],107:[2,19],115:[2,19],123:[2,19],125:[2,19],126:[2,19],129:[2,19],130:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],47:[2,20],52:[2,20],55:[2,20],70:[2,20],75:[2,20],83:[2,20],88:[2,20],90:[2,20],99:[2,20],101:[2,20],102:[2,20],103:[2,20],107:[2,20],115:[2,20],123:[2,20],125:[2,20],126:[2,20],129:[2,20],130:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],47:[2,21],52:[2,21],55:[2,21],70:[2,21],75:[2,21],83:[2,21],88:[2,21],90:[2,21],99:[2,21],101:[2,21],102:[2,21],103:[2,21],107:[2,21],115:[2,21],123:[2,21],125:[2,21],126:[2,21],129:[2,21],130:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],47:[2,22],52:[2,22],55:[2,22],70:[2,22],75:[2,22],83:[2,22],88:[2,22],90:[2,22],99:[2,22],101:[2,22],102:[2,22],103:[2,22],107:[2,22],115:[2,22],123:[2,22],125:[2,22],126:[2,22],129:[2,22],130:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],47:[2,23],52:[2,23],55:[2,23],70:[2,23],75:[2,23],83:[2,23],88:[2,23],90:[2,23],99:[2,23],101:[2,23],102:[2,23],103:[2,23],107:[2,23],115:[2,23],123:[2,23],125:[2,23],126:[2,23],129:[2,23],130:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23]},{1:[2,9],6:[2,9],26:[2,9],99:[2,9],101:[2,9],103:[2,9],107:[2,9],123:[2,9]},{1:[2,10],6:[2,10],26:[2,10],99:[2,10],101:[2,10],103:[2,10],107:[2,10],123:[2,10]},{1:[2,11],6:[2,11],26:[2,11],99:[2,11],101:[2,11],103:[2,11],107:[2,11],123:[2,11]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],38:[1,101],47:[2,71],52:[2,71],55:[2,71],64:[2,71],65:[2,71],66:[2,71],68:[2,71],70:[2,71],71:[2,71],75:[2,71],81:[2,71],82:[2,71],83:[2,71],88:[2,71],90:[2,71],99:[2,71],101:[2,71],102:[2,71],103:[2,71],107:[2,71],115:[2,71],123:[2,71],125:[2,71],126:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],47:[2,72],52:[2,72],55:[2,72],64:[2,72],65:[2,72],66:[2,72],68:[2,72],70:[2,72],71:[2,72],75:[2,72],81:[2,72],82:[2,72],83:[2,72],88:[2,72],90:[2,72],99:[2,72],101:[2,72],102:[2,72],103:[2,72],107:[2,72],115:[2,72],123:[2,72],125:[2,72],126:[2,72],129:[2,72],130:[2,72],131:[2,72],132:[2,72],133:[2,72],134:[2,72]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],47:[2,73],52:[2,73],55:[2,73],64:[2,73],65:[2,73],66:[2,73],68:[2,73],70:[2,73],71:[2,73],75:[2,73],81:[2,73],82:[2,73],83:[2,73],88:[2,73],90:[2,73],99:[2,73],101:[2,73],102:[2,73],103:[2,73],107:[2,73],115:[2,73],123:[2,73],125:[2,73],126:[2,73],129:[2,73],130:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],47:[2,74],52:[2,74],55:[2,74],64:[2,74],65:[2,74],66:[2,74],68:[2,74],70:[2,74],71:[2,74],75:[2,74],81:[2,74],82:[2,74],83:[2,74],88:[2,74],90:[2,74],99:[2,74],101:[2,74],102:[2,74],103:[2,74],107:[2,74],115:[2,74],123:[2,74],125:[2,74],126:[2,74],129:[2,74],130:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],47:[2,75],52:[2,75],55:[2,75],64:[2,75],65:[2,75],66:[2,75],68:[2,75],70:[2,75],71:[2,75],75:[2,75],81:[2,75],82:[2,75],83:[2,75],88:[2,75],90:[2,75],99:[2,75],101:[2,75],102:[2,75],103:[2,75],107:[2,75],115:[2,75],123:[2,75],125:[2,75],126:[2,75],129:[2,75],130:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75]},{1:[2,101],6:[2,101],25:[2,101],26:[2,101],47:[2,101],52:[2,101],55:[2,101],64:[2,101],65:[2,101],66:[2,101],68:[2,101],70:[2,101],71:[2,101],75:[2,101],79:102,81:[2,101],82:[1,103],83:[2,101],88:[2,101],90:[2,101],99:[2,101],101:[2,101],102:[2,101],103:[2,101],107:[2,101],115:[2,101],123:[2,101],125:[2,101],126:[2,101],129:[2,101],130:[2,101],131:[2,101],132:[2,101],133:[2,101],134:[2,101]},{27:107,28:[1,71],42:108,46:104,47:[2,53],52:[2,53],53:105,54:106,56:109,57:110,73:[1,68],86:[1,111],87:[1,112]},{5:113,25:[1,5]},{8:114,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:116,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:117,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{13:119,14:120,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,56:47,57:48,59:118,61:25,62:26,63:27,73:[1,68],80:[1,28],85:[1,56],86:[1,57],87:[1,55],98:[1,54]},{13:119,14:120,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,56:47,57:48,59:122,61:25,62:26,63:27,73:[1,68],80:[1,28],85:[1,56],86:[1,57],87:[1,55],98:[1,54]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],38:[2,68],47:[2,68],52:[2,68],55:[2,68],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,68],71:[2,68],75:[2,68],77:[1,126],81:[2,68],82:[2,68],83:[2,68],88:[2,68],90:[2,68],99:[2,68],101:[2,68],102:[2,68],103:[2,68],107:[2,68],115:[2,68],123:[2,68],125:[2,68],126:[2,68],127:[1,123],128:[1,124],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[1,125]},{1:[2,175],6:[2,175],25:[2,175],26:[2,175],47:[2,175],52:[2,175],55:[2,175],70:[2,175],75:[2,175],83:[2,175],88:[2,175],90:[2,175],99:[2,175],101:[2,175],102:[2,175],103:[2,175],107:[2,175],115:[2,175],118:[1,127],123:[2,175],125:[2,175],126:[2,175],129:[2,175],130:[2,175],131:[2,175],132:[2,175],133:[2,175],134:[2,175]},{5:128,25:[1,5]},{5:129,25:[1,5]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],47:[2,143],52:[2,143],55:[2,143],70:[2,143],75:[2,143],83:[2,143],88:[2,143],90:[2,143],99:[2,143],101:[2,143],102:[2,143],103:[2,143],107:[2,143],115:[2,143],123:[2,143],125:[2,143],126:[2,143],129:[2,143],130:[2,143],131:[2,143],132:[2,143],133:[2,143],134:[2,143]},{5:130,25:[1,5]},{8:131,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,132],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,91],5:133,6:[2,91],13:119,14:120,25:[1,5],26:[2,91],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,47:[2,91],52:[2,91],55:[2,91],56:47,57:48,59:135,61:25,62:26,63:27,70:[2,91],73:[1,68],75:[2,91],77:[1,134],80:[1,28],83:[2,91],85:[1,56],86:[1,57],87:[1,55],88:[2,91],90:[2,91],98:[1,54],99:[2,91],101:[2,91],102:[2,91],103:[2,91],107:[2,91],115:[2,91],123:[2,91],125:[2,91],126:[2,91],129:[2,91],130:[2,91],131:[2,91],132:[2,91],133:[2,91],134:[2,91]},{8:136,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,45],6:[2,45],8:137,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,45],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],99:[2,45],100:39,101:[2,45],103:[2,45],104:40,105:[1,65],106:41,107:[2,45],108:67,116:[1,42],121:37,122:[1,62],123:[2,45],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,46],6:[2,46],25:[2,46],26:[2,46],52:[2,46],75:[2,46],99:[2,46],101:[2,46],103:[2,46],107:[2,46],123:[2,46]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],38:[2,69],47:[2,69],52:[2,69],55:[2,69],64:[2,69],65:[2,69],66:[2,69],68:[2,69],70:[2,69],71:[2,69],75:[2,69],81:[2,69],82:[2,69],83:[2,69],88:[2,69],90:[2,69],99:[2,69],101:[2,69],102:[2,69],103:[2,69],107:[2,69],115:[2,69],123:[2,69],125:[2,69],126:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],38:[2,70],47:[2,70],52:[2,70],55:[2,70],64:[2,70],65:[2,70],66:[2,70],68:[2,70],70:[2,70],71:[2,70],75:[2,70],81:[2,70],82:[2,70],83:[2,70],88:[2,70],90:[2,70],99:[2,70],101:[2,70],102:[2,70],103:[2,70],107:[2,70],115:[2,70],123:[2,70],125:[2,70],126:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],47:[2,29],52:[2,29],55:[2,29],64:[2,29],65:[2,29],66:[2,29],68:[2,29],70:[2,29],71:[2,29],75:[2,29],81:[2,29],82:[2,29],83:[2,29],88:[2,29],90:[2,29],99:[2,29],101:[2,29],102:[2,29],103:[2,29],107:[2,29],115:[2,29],123:[2,29],125:[2,29],126:[2,29],129:[2,29],130:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],47:[2,30],52:[2,30],55:[2,30],64:[2,30],65:[2,30],66:[2,30],68:[2,30],70:[2,30],71:[2,30],75:[2,30],81:[2,30],82:[2,30],83:[2,30],88:[2,30],90:[2,30],99:[2,30],101:[2,30],102:[2,30],103:[2,30],107:[2,30],115:[2,30],123:[2,30],125:[2,30],126:[2,30],129:[2,30],130:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],47:[2,31],52:[2,31],55:[2,31],64:[2,31],65:[2,31],66:[2,31],68:[2,31],70:[2,31],71:[2,31],75:[2,31],81:[2,31],82:[2,31],83:[2,31],88:[2,31],90:[2,31],99:[2,31],101:[2,31],102:[2,31],103:[2,31],107:[2,31],115:[2,31],123:[2,31],125:[2,31],126:[2,31],129:[2,31],130:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],47:[2,32],52:[2,32],55:[2,32],64:[2,32],65:[2,32],66:[2,32],68:[2,32],70:[2,32],71:[2,32],75:[2,32],81:[2,32],82:[2,32],83:[2,32],88:[2,32],90:[2,32],99:[2,32],101:[2,32],102:[2,32],103:[2,32],107:[2,32],115:[2,32],123:[2,32],125:[2,32],126:[2,32],129:[2,32],130:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],47:[2,33],52:[2,33],55:[2,33],64:[2,33],65:[2,33],66:[2,33],68:[2,33],70:[2,33],71:[2,33],75:[2,33],81:[2,33],82:[2,33],83:[2,33],88:[2,33],90:[2,33],99:[2,33],101:[2,33],102:[2,33],103:[2,33],107:[2,33],115:[2,33],123:[2,33],125:[2,33],126:[2,33],129:[2,33],130:[2,33],131:[2,33],132:[2,33],133:[2,33],134:[2,33]},{4:138,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,139],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:140,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:142,85:[1,56],86:[1,57],87:[1,55],88:[1,141],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,107],6:[2,107],25:[2,107],26:[2,107],47:[2,107],52:[2,107],55:[2,107],64:[2,107],65:[2,107],66:[2,107],68:[2,107],70:[2,107],71:[2,107],75:[2,107],81:[2,107],82:[2,107],83:[2,107],88:[2,107],90:[2,107],99:[2,107],101:[2,107],102:[2,107],103:[2,107],107:[2,107],115:[2,107],123:[2,107],125:[2,107],126:[2,107],129:[2,107],130:[2,107],131:[2,107],132:[2,107],133:[2,107],134:[2,107]},{1:[2,108],6:[2,108],25:[2,108],26:[2,108],27:146,28:[1,71],47:[2,108],52:[2,108],55:[2,108],64:[2,108],65:[2,108],66:[2,108],68:[2,108],70:[2,108],71:[2,108],75:[2,108],81:[2,108],82:[2,108],83:[2,108],88:[2,108],90:[2,108],99:[2,108],101:[2,108],102:[2,108],103:[2,108],107:[2,108],115:[2,108],123:[2,108],125:[2,108],126:[2,108],129:[2,108],130:[2,108],131:[2,108],132:[2,108],133:[2,108],134:[2,108]},{25:[2,49]},{25:[2,50]},{1:[2,64],6:[2,64],25:[2,64],26:[2,64],38:[2,64],47:[2,64],52:[2,64],55:[2,64],64:[2,64],65:[2,64],66:[2,64],68:[2,64],70:[2,64],71:[2,64],75:[2,64],77:[2,64],81:[2,64],82:[2,64],83:[2,64],88:[2,64],90:[2,64],99:[2,64],101:[2,64],102:[2,64],103:[2,64],107:[2,64],115:[2,64],123:[2,64],125:[2,64],126:[2,64],127:[2,64],128:[2,64],129:[2,64],130:[2,64],131:[2,64],132:[2,64],133:[2,64],134:[2,64],135:[2,64]},{1:[2,67],6:[2,67],25:[2,67],26:[2,67],38:[2,67],47:[2,67],52:[2,67],55:[2,67],64:[2,67],65:[2,67],66:[2,67],68:[2,67],70:[2,67],71:[2,67],75:[2,67],77:[2,67],81:[2,67],82:[2,67],83:[2,67],88:[2,67],90:[2,67],99:[2,67],101:[2,67],102:[2,67],103:[2,67],107:[2,67],115:[2,67],123:[2,67],125:[2,67],126:[2,67],127:[2,67],128:[2,67],129:[2,67],130:[2,67],131:[2,67],132:[2,67],133:[2,67],134:[2,67],135:[2,67]},{8:147,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:148,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:149,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:150,8:151,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{27:156,28:[1,71],56:157,57:158,62:152,73:[1,68],87:[1,55],110:153,111:[1,154],112:155},{109:159,113:[1,160],114:[1,161]},{6:[2,86],11:165,25:[2,86],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:163,40:164,42:168,44:[1,46],52:[2,86],74:162,75:[2,86],86:[1,111]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],41:[2,27],47:[2,27],52:[2,27],55:[2,27],64:[2,27],65:[2,27],66:[2,27],68:[2,27],70:[2,27],71:[2,27],75:[2,27],81:[2,27],82:[2,27],83:[2,27],88:[2,27],90:[2,27],99:[2,27],101:[2,27],102:[2,27],103:[2,27],107:[2,27],115:[2,27],123:[2,27],125:[2,27],126:[2,27],129:[2,27],130:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],41:[2,28],47:[2,28],52:[2,28],55:[2,28],64:[2,28],65:[2,28],66:[2,28],68:[2,28],70:[2,28],71:[2,28],75:[2,28],81:[2,28],82:[2,28],83:[2,28],88:[2,28],90:[2,28],99:[2,28],101:[2,28],102:[2,28],103:[2,28],107:[2,28],115:[2,28],123:[2,28],125:[2,28],126:[2,28],129:[2,28],130:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],38:[2,26],41:[2,26],47:[2,26],52:[2,26],55:[2,26],64:[2,26],65:[2,26],66:[2,26],68:[2,26],70:[2,26],71:[2,26],75:[2,26],77:[2,26],81:[2,26],82:[2,26],83:[2,26],88:[2,26],90:[2,26],99:[2,26],101:[2,26],102:[2,26],103:[2,26],107:[2,26],113:[2,26],114:[2,26],115:[2,26],123:[2,26],125:[2,26],126:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26]},{1:[2,6],6:[2,6],7:169,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,6],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],99:[2,6],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],47:[2,24],52:[2,24],55:[2,24],70:[2,24],75:[2,24],83:[2,24],88:[2,24],90:[2,24],95:[2,24],96:[2,24],99:[2,24],101:[2,24],102:[2,24],103:[2,24],107:[2,24],115:[2,24],118:[2,24],120:[2,24],123:[2,24],125:[2,24],126:[2,24],129:[2,24],130:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24]},{6:[1,72],26:[1,170]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],47:[2,186],52:[2,186],55:[2,186],70:[2,186],75:[2,186],83:[2,186],88:[2,186],90:[2,186],99:[2,186],101:[2,186],102:[2,186],103:[2,186],107:[2,186],115:[2,186],123:[2,186],125:[2,186],126:[2,186],129:[2,186],130:[2,186],131:[2,186],132:[2,186],133:[2,186],134:[2,186]},{8:171,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:172,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:173,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:174,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:175,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:176,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:177,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:178,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],47:[2,142],52:[2,142],55:[2,142],70:[2,142],75:[2,142],83:[2,142],88:[2,142],90:[2,142],99:[2,142],101:[2,142],102:[2,142],103:[2,142],107:[2,142],115:[2,142],123:[2,142],125:[2,142],126:[2,142],129:[2,142],130:[2,142],131:[2,142],132:[2,142],133:[2,142],134:[2,142]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],47:[2,147],52:[2,147],55:[2,147],70:[2,147],75:[2,147],83:[2,147],88:[2,147],90:[2,147],99:[2,147],101:[2,147],102:[2,147],103:[2,147],107:[2,147],115:[2,147],123:[2,147],125:[2,147],126:[2,147],129:[2,147],130:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147]},{8:179,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],47:[2,141],52:[2,141],55:[2,141],70:[2,141],75:[2,141],83:[2,141],88:[2,141],90:[2,141],99:[2,141],101:[2,141],102:[2,141],103:[2,141],107:[2,141],115:[2,141],123:[2,141],125:[2,141],126:[2,141],129:[2,141],130:[2,141],131:[2,141],132:[2,141],133:[2,141],134:[2,141]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],47:[2,146],52:[2,146],55:[2,146],70:[2,146],75:[2,146],83:[2,146],88:[2,146],90:[2,146],99:[2,146],101:[2,146],102:[2,146],103:[2,146],107:[2,146],115:[2,146],123:[2,146],125:[2,146],126:[2,146],129:[2,146],130:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146]},{79:180,82:[1,103]},{1:[2,65],6:[2,65],25:[2,65],26:[2,65],38:[2,65],47:[2,65],52:[2,65],55:[2,65],64:[2,65],65:[2,65],66:[2,65],68:[2,65],70:[2,65],71:[2,65],75:[2,65],77:[2,65],81:[2,65],82:[2,65],83:[2,65],88:[2,65],90:[2,65],99:[2,65],101:[2,65],102:[2,65],103:[2,65],107:[2,65],115:[2,65],123:[2,65],125:[2,65],126:[2,65],127:[2,65],128:[2,65],129:[2,65],130:[2,65],131:[2,65],132:[2,65],133:[2,65],134:[2,65],135:[2,65]},{82:[2,104]},{27:181,28:[1,71]},{27:182,28:[1,71]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],27:183,28:[1,71],38:[2,79],47:[2,79],52:[2,79],55:[2,79],64:[2,79],65:[2,79],66:[2,79],68:[2,79],70:[2,79],71:[2,79],75:[2,79],77:[2,79],81:[2,79],82:[2,79],83:[2,79],88:[2,79],90:[2,79],99:[2,79],101:[2,79],102:[2,79],103:[2,79],107:[2,79],115:[2,79],123:[2,79],125:[2,79],126:[2,79],127:[2,79],128:[2,79],129:[2,79],130:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],38:[2,80],47:[2,80],52:[2,80],55:[2,80],64:[2,80],65:[2,80],66:[2,80],68:[2,80],70:[2,80],71:[2,80],75:[2,80],77:[2,80],81:[2,80],82:[2,80],83:[2,80],88:[2,80],90:[2,80],99:[2,80],101:[2,80],102:[2,80],103:[2,80],107:[2,80],115:[2,80],123:[2,80],125:[2,80],126:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80]},{8:185,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],55:[1,189],56:47,57:48,59:36,61:25,62:26,63:27,69:184,72:186,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],89:187,90:[1,188],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{67:190,68:[1,97],71:[1,98]},{79:191,82:[1,103]},{1:[2,66],6:[2,66],25:[2,66],26:[2,66],38:[2,66],47:[2,66],52:[2,66],55:[2,66],64:[2,66],65:[2,66],66:[2,66],68:[2,66],70:[2,66],71:[2,66],75:[2,66],77:[2,66],81:[2,66],82:[2,66],83:[2,66],88:[2,66],90:[2,66],99:[2,66],101:[2,66],102:[2,66],103:[2,66],107:[2,66],115:[2,66],123:[2,66],125:[2,66],126:[2,66],127:[2,66],128:[2,66],129:[2,66],130:[2,66],131:[2,66],132:[2,66],133:[2,66],134:[2,66],135:[2,66]},{6:[1,193],8:192,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,194],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,102],6:[2,102],25:[2,102],26:[2,102],47:[2,102],52:[2,102],55:[2,102],64:[2,102],65:[2,102],66:[2,102],68:[2,102],70:[2,102],71:[2,102],75:[2,102],81:[2,102],82:[2,102],83:[2,102],88:[2,102],90:[2,102],99:[2,102],101:[2,102],102:[2,102],103:[2,102],107:[2,102],115:[2,102],123:[2,102],125:[2,102],126:[2,102],129:[2,102],130:[2,102],131:[2,102],132:[2,102],133:[2,102],134:[2,102]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],83:[1,195],84:196,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{47:[1,198],52:[1,199]},{47:[2,54],52:[2,54]},{38:[1,201],47:[2,56],52:[2,56],55:[1,200]},{38:[2,59],47:[2,59],52:[2,59],55:[2,59]},{38:[2,60],47:[2,60],52:[2,60],55:[2,60]},{38:[2,61],47:[2,61],52:[2,61],55:[2,61]},{38:[2,62],47:[2,62],52:[2,62],55:[2,62]},{27:146,28:[1,71]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:142,85:[1,56],86:[1,57],87:[1,55],88:[1,141],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],47:[2,48],52:[2,48],55:[2,48],70:[2,48],75:[2,48],83:[2,48],88:[2,48],90:[2,48],99:[2,48],101:[2,48],102:[2,48],103:[2,48],107:[2,48],115:[2,48],123:[2,48],125:[2,48],126:[2,48],129:[2,48],130:[2,48],131:[2,48],132:[2,48],133:[2,48],134:[2,48]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],47:[2,179],52:[2,179],55:[2,179],70:[2,179],75:[2,179],83:[2,179],88:[2,179],90:[2,179],99:[2,179],100:85,101:[2,179],102:[2,179],103:[2,179],106:86,107:[2,179],108:67,115:[2,179],123:[2,179],125:[2,179],126:[2,179],129:[1,76],130:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179]},{100:88,101:[1,63],103:[1,64],106:89,107:[1,66],108:67,123:[1,87]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],47:[2,180],52:[2,180],55:[2,180],70:[2,180],75:[2,180],83:[2,180],88:[2,180],90:[2,180],99:[2,180],100:85,101:[2,180],102:[2,180],103:[2,180],106:86,107:[2,180],108:67,115:[2,180],123:[2,180],125:[2,180],126:[2,180],129:[1,76],130:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],47:[2,181],52:[2,181],55:[2,181],70:[2,181],75:[2,181],83:[2,181],88:[2,181],90:[2,181],99:[2,181],100:85,101:[2,181],102:[2,181],103:[2,181],106:86,107:[2,181],108:67,115:[2,181],123:[2,181],125:[2,181],126:[2,181],129:[1,76],130:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],47:[2,182],52:[2,182],55:[2,182],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,182],71:[2,68],75:[2,182],81:[2,68],82:[2,68],83:[2,182],88:[2,182],90:[2,182],99:[2,182],101:[2,182],102:[2,182],103:[2,182],107:[2,182],115:[2,182],123:[2,182],125:[2,182],126:[2,182],129:[2,182],130:[2,182],131:[2,182],132:[2,182],133:[2,182],134:[2,182]},{60:91,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],71:[1,98],78:90,81:[1,92],82:[2,103]},{60:100,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],71:[1,98],78:99,81:[1,92],82:[2,103]},{64:[2,71],65:[2,71],66:[2,71],68:[2,71],71:[2,71],81:[2,71],82:[2,71]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],47:[2,183],52:[2,183],55:[2,183],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,183],71:[2,68],75:[2,183],81:[2,68],82:[2,68],83:[2,183],88:[2,183],90:[2,183],99:[2,183],101:[2,183],102:[2,183],103:[2,183],107:[2,183],115:[2,183],123:[2,183],125:[2,183],126:[2,183],129:[2,183],130:[2,183],131:[2,183],132:[2,183],133:[2,183],134:[2,183]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],47:[2,184],52:[2,184],55:[2,184],70:[2,184],75:[2,184],83:[2,184],88:[2,184],90:[2,184],99:[2,184],101:[2,184],102:[2,184],103:[2,184],107:[2,184],115:[2,184],123:[2,184],125:[2,184],126:[2,184],129:[2,184],130:[2,184],131:[2,184],132:[2,184],133:[2,184],134:[2,184]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],47:[2,185],52:[2,185],55:[2,185],70:[2,185],75:[2,185],83:[2,185],88:[2,185],90:[2,185],99:[2,185],101:[2,185],102:[2,185],103:[2,185],107:[2,185],115:[2,185],123:[2,185],125:[2,185],126:[2,185],129:[2,185],130:[2,185],131:[2,185],132:[2,185],133:[2,185],134:[2,185]},{8:202,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,203],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:204,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:205,25:[1,5],122:[1,206]},{1:[2,128],6:[2,128],25:[2,128],26:[2,128],47:[2,128],52:[2,128],55:[2,128],70:[2,128],75:[2,128],83:[2,128],88:[2,128],90:[2,128],94:207,95:[1,208],96:[1,209],99:[2,128],101:[2,128],102:[2,128],103:[2,128],107:[2,128],115:[2,128],123:[2,128],125:[2,128],126:[2,128],129:[2,128],130:[2,128],131:[2,128],132:[2,128],133:[2,128],134:[2,128]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],47:[2,140],52:[2,140],55:[2,140],70:[2,140],75:[2,140],83:[2,140],88:[2,140],90:[2,140],99:[2,140],101:[2,140],102:[2,140],103:[2,140],107:[2,140],115:[2,140],123:[2,140],125:[2,140],126:[2,140],129:[2,140],130:[2,140],131:[2,140],132:[2,140],133:[2,140],134:[2,140]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],47:[2,148],52:[2,148],55:[2,148],70:[2,148],75:[2,148],83:[2,148],88:[2,148],90:[2,148],99:[2,148],101:[2,148],102:[2,148],103:[2,148],107:[2,148],115:[2,148],123:[2,148],125:[2,148],126:[2,148],129:[2,148],130:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148]},{25:[1,210],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{117:211,119:212,120:[1,213]},{1:[2,92],6:[2,92],25:[2,92],26:[2,92],47:[2,92],52:[2,92],55:[2,92],70:[2,92],75:[2,92],83:[2,92],88:[2,92],90:[2,92],99:[2,92],101:[2,92],102:[2,92],103:[2,92],107:[2,92],115:[2,92],123:[2,92],125:[2,92],126:[2,92],129:[2,92],130:[2,92],131:[2,92],132:[2,92],133:[2,92],134:[2,92]},{8:214,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,95],5:215,6:[2,95],25:[1,5],26:[2,95],47:[2,95],52:[2,95],55:[2,95],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,95],71:[2,68],75:[2,95],77:[1,216],81:[2,68],82:[2,68],83:[2,95],88:[2,95],90:[2,95],99:[2,95],101:[2,95],102:[2,95],103:[2,95],107:[2,95],115:[2,95],123:[2,95],125:[2,95],126:[2,95],129:[2,95],130:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],47:[2,133],52:[2,133],55:[2,133],70:[2,133],75:[2,133],83:[2,133],88:[2,133],90:[2,133],99:[2,133],100:85,101:[2,133],102:[2,133],103:[2,133],106:86,107:[2,133],108:67,115:[2,133],123:[2,133],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,44],6:[2,44],26:[2,44],99:[2,44],100:85,101:[2,44],103:[2,44],106:86,107:[2,44],108:67,123:[2,44],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,72],99:[1,217]},{4:218,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,124],25:[2,124],52:[2,124],55:[1,220],88:[2,124],89:219,90:[1,188],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],38:[2,110],47:[2,110],52:[2,110],55:[2,110],64:[2,110],65:[2,110],66:[2,110],68:[2,110],70:[2,110],71:[2,110],75:[2,110],81:[2,110],82:[2,110],83:[2,110],88:[2,110],90:[2,110],99:[2,110],101:[2,110],102:[2,110],103:[2,110],107:[2,110],113:[2,110],114:[2,110],115:[2,110],123:[2,110],125:[2,110],126:[2,110],129:[2,110],130:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110]},{6:[2,51],25:[2,51],51:221,52:[1,222],88:[2,51]},{6:[2,119],25:[2,119],26:[2,119],52:[2,119],83:[2,119],88:[2,119]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:223,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,125],25:[2,125],26:[2,125],52:[2,125],83:[2,125],88:[2,125]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],38:[2,109],41:[2,109],47:[2,109],52:[2,109],55:[2,109],64:[2,109],65:[2,109],66:[2,109],68:[2,109],70:[2,109],71:[2,109],75:[2,109],77:[2,109],81:[2,109],82:[2,109],83:[2,109],88:[2,109],90:[2,109],99:[2,109],101:[2,109],102:[2,109],103:[2,109],107:[2,109],115:[2,109],123:[2,109],125:[2,109],126:[2,109],127:[2,109],128:[2,109],129:[2,109],130:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109],135:[2,109]},{5:224,25:[1,5],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],47:[2,136],52:[2,136],55:[2,136],70:[2,136],75:[2,136],83:[2,136],88:[2,136],90:[2,136],99:[2,136],100:85,101:[1,63],102:[1,225],103:[1,64],106:86,107:[1,66],108:67,115:[2,136],123:[2,136],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],47:[2,138],52:[2,138],55:[2,138],70:[2,138],75:[2,138],83:[2,138],88:[2,138],90:[2,138],99:[2,138],100:85,101:[1,63],102:[1,226],103:[1,64],106:86,107:[1,66],108:67,115:[2,138],123:[2,138],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],47:[2,144],52:[2,144],55:[2,144],70:[2,144],75:[2,144],83:[2,144],88:[2,144],90:[2,144],99:[2,144],101:[2,144],102:[2,144],103:[2,144],107:[2,144],115:[2,144],123:[2,144],125:[2,144],126:[2,144],129:[2,144],130:[2,144],131:[2,144],132:[2,144],133:[2,144],134:[2,144]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],47:[2,145],52:[2,145],55:[2,145],70:[2,145],75:[2,145],83:[2,145],88:[2,145],90:[2,145],99:[2,145],100:85,101:[1,63],102:[2,145],103:[1,64],106:86,107:[1,66],108:67,115:[2,145],123:[2,145],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],47:[2,149],52:[2,149],55:[2,149],70:[2,149],75:[2,149],83:[2,149],88:[2,149],90:[2,149],99:[2,149],101:[2,149],102:[2,149],103:[2,149],107:[2,149],115:[2,149],123:[2,149],125:[2,149],126:[2,149],129:[2,149],130:[2,149],131:[2,149],132:[2,149],133:[2,149],134:[2,149]},{113:[2,151],114:[2,151]},{27:156,28:[1,71],56:157,57:158,73:[1,68],87:[1,112],110:227,112:155},{52:[1,228],113:[2,156],114:[2,156]},{52:[2,153],113:[2,153],114:[2,153]},{52:[2,154],113:[2,154],114:[2,154]},{52:[2,155],113:[2,155],114:[2,155]},{1:[2,150],6:[2,150],25:[2,150],26:[2,150],47:[2,150],52:[2,150],55:[2,150],70:[2,150],75:[2,150],83:[2,150],88:[2,150],90:[2,150],99:[2,150],101:[2,150],102:[2,150],103:[2,150],107:[2,150],115:[2,150],123:[2,150],125:[2,150],126:[2,150],129:[2,150],130:[2,150],131:[2,150],132:[2,150],133:[2,150],134:[2,150]},{8:229,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:230,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,51],25:[2,51],51:231,52:[1,232],75:[2,51]},{6:[2,87],25:[2,87],26:[2,87],52:[2,87],75:[2,87]},{6:[2,37],25:[2,37],26:[2,37],41:[1,233],52:[2,37],75:[2,37]},{6:[2,40],25:[2,40],26:[2,40],52:[2,40],75:[2,40]},{6:[2,41],25:[2,41],26:[2,41],41:[2,41],52:[2,41],75:[2,41]},{6:[2,42],25:[2,42],26:[2,42],41:[2,42],52:[2,42],75:[2,42]},{6:[2,43],25:[2,43],26:[2,43],41:[2,43],52:[2,43],75:[2,43]},{1:[2,5],6:[2,5],26:[2,5],99:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],47:[2,25],52:[2,25],55:[2,25],70:[2,25],75:[2,25],83:[2,25],88:[2,25],90:[2,25],95:[2,25],96:[2,25],99:[2,25],101:[2,25],102:[2,25],103:[2,25],107:[2,25],115:[2,25],118:[2,25],120:[2,25],123:[2,25],125:[2,25],126:[2,25],129:[2,25],130:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],47:[2,187],52:[2,187],55:[2,187],70:[2,187],75:[2,187],83:[2,187],88:[2,187],90:[2,187],99:[2,187],100:85,101:[2,187],102:[2,187],103:[2,187],106:86,107:[2,187],108:67,115:[2,187],123:[2,187],125:[2,187],126:[2,187],129:[1,76],130:[1,79],131:[2,187],132:[2,187],133:[2,187],134:[2,187]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],47:[2,188],52:[2,188],55:[2,188],70:[2,188],75:[2,188],83:[2,188],88:[2,188],90:[2,188],99:[2,188],100:85,101:[2,188],102:[2,188],103:[2,188],106:86,107:[2,188],108:67,115:[2,188],123:[2,188],125:[2,188],126:[2,188],129:[1,76],130:[1,79],131:[2,188],132:[2,188],133:[2,188],134:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],47:[2,189],52:[2,189],55:[2,189],70:[2,189],75:[2,189],83:[2,189],88:[2,189],90:[2,189],99:[2,189],100:85,101:[2,189],102:[2,189],103:[2,189],106:86,107:[2,189],108:67,115:[2,189],123:[2,189],125:[2,189],126:[2,189],129:[1,76],130:[2,189],131:[2,189],132:[2,189],133:[2,189],134:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],47:[2,190],52:[2,190],55:[2,190],70:[2,190],75:[2,190],83:[2,190],88:[2,190],90:[2,190],99:[2,190],100:85,101:[2,190],102:[2,190],103:[2,190],106:86,107:[2,190],108:67,115:[2,190],123:[2,190],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[2,190],132:[2,190],133:[2,190],134:[2,190]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],47:[2,191],52:[2,191],55:[2,191],70:[2,191],75:[2,191],83:[2,191],88:[2,191],90:[2,191],99:[2,191],100:85,101:[2,191],102:[2,191],103:[2,191],106:86,107:[2,191],108:67,115:[2,191],123:[2,191],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[2,191],133:[2,191],134:[1,83]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],47:[2,192],52:[2,192],55:[2,192],70:[2,192],75:[2,192],83:[2,192],88:[2,192],90:[2,192],99:[2,192],100:85,101:[2,192],102:[2,192],103:[2,192],106:86,107:[2,192],108:67,115:[2,192],123:[2,192],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[2,192],134:[1,83]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],47:[2,193],52:[2,193],55:[2,193],70:[2,193],75:[2,193],83:[2,193],88:[2,193],90:[2,193],99:[2,193],100:85,101:[2,193],102:[2,193],103:[2,193],106:86,107:[2,193],108:67,115:[2,193],123:[2,193],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[2,193],133:[2,193],134:[2,193]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],47:[2,178],52:[2,178],55:[2,178],70:[2,178],75:[2,178],83:[2,178],88:[2,178],90:[2,178],99:[2,178],100:85,101:[1,63],102:[2,178],103:[1,64],106:86,107:[1,66],108:67,115:[2,178],123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,177],6:[2,177],25:[2,177],26:[2,177],47:[2,177],52:[2,177],55:[2,177],70:[2,177],75:[2,177],83:[2,177],88:[2,177],90:[2,177],99:[2,177],100:85,101:[1,63],102:[2,177],103:[1,64],106:86,107:[1,66],108:67,115:[2,177],123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,99],6:[2,99],25:[2,99],26:[2,99],47:[2,99],52:[2,99],55:[2,99],64:[2,99],65:[2,99],66:[2,99],68:[2,99],70:[2,99],71:[2,99],75:[2,99],81:[2,99],82:[2,99],83:[2,99],88:[2,99],90:[2,99],99:[2,99],101:[2,99],102:[2,99],103:[2,99],107:[2,99],115:[2,99],123:[2,99],125:[2,99],126:[2,99],129:[2,99],130:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],38:[2,76],47:[2,76],52:[2,76],55:[2,76],64:[2,76],65:[2,76],66:[2,76],68:[2,76],70:[2,76],71:[2,76],75:[2,76],77:[2,76],81:[2,76],82:[2,76],83:[2,76],88:[2,76],90:[2,76],99:[2,76],101:[2,76],102:[2,76],103:[2,76],107:[2,76],115:[2,76],123:[2,76],125:[2,76],126:[2,76],127:[2,76],128:[2,76],129:[2,76],130:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],38:[2,77],47:[2,77],52:[2,77],55:[2,77],64:[2,77],65:[2,77],66:[2,77],68:[2,77],70:[2,77],71:[2,77],75:[2,77],77:[2,77],81:[2,77],82:[2,77],83:[2,77],88:[2,77],90:[2,77],99:[2,77],101:[2,77],102:[2,77],103:[2,77],107:[2,77],115:[2,77],123:[2,77],125:[2,77],126:[2,77],127:[2,77],128:[2,77],129:[2,77],130:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],38:[2,78],47:[2,78],52:[2,78],55:[2,78],64:[2,78],65:[2,78],66:[2,78],68:[2,78],70:[2,78],71:[2,78],75:[2,78],77:[2,78],81:[2,78],82:[2,78],83:[2,78],88:[2,78],90:[2,78],99:[2,78],101:[2,78],102:[2,78],103:[2,78],107:[2,78],115:[2,78],123:[2,78],125:[2,78],126:[2,78],127:[2,78],128:[2,78],129:[2,78],130:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78]},{70:[1,234]},{55:[1,189],70:[2,83],89:235,90:[1,188],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{70:[2,84]},{8:236,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,70:[2,118],73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{12:[2,112],28:[2,112],30:[2,112],31:[2,112],33:[2,112],34:[2,112],35:[2,112],36:[2,112],43:[2,112],44:[2,112],45:[2,112],49:[2,112],50:[2,112],70:[2,112],73:[2,112],76:[2,112],80:[2,112],85:[2,112],86:[2,112],87:[2,112],93:[2,112],97:[2,112],98:[2,112],101:[2,112],103:[2,112],105:[2,112],107:[2,112],116:[2,112],122:[2,112],124:[2,112],125:[2,112],126:[2,112],127:[2,112],128:[2,112]},{12:[2,113],28:[2,113],30:[2,113],31:[2,113],33:[2,113],34:[2,113],35:[2,113],36:[2,113],43:[2,113],44:[2,113],45:[2,113],49:[2,113],50:[2,113],70:[2,113],73:[2,113],76:[2,113],80:[2,113],85:[2,113],86:[2,113],87:[2,113],93:[2,113],97:[2,113],98:[2,113],101:[2,113],103:[2,113],105:[2,113],107:[2,113],116:[2,113],122:[2,113],124:[2,113],125:[2,113],126:[2,113],127:[2,113],128:[2,113]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],38:[2,82],47:[2,82],52:[2,82],55:[2,82],64:[2,82],65:[2,82],66:[2,82],68:[2,82],70:[2,82],71:[2,82],75:[2,82],77:[2,82],81:[2,82],82:[2,82],83:[2,82],88:[2,82],90:[2,82],99:[2,82],101:[2,82],102:[2,82],103:[2,82],107:[2,82],115:[2,82],123:[2,82],125:[2,82],126:[2,82],127:[2,82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],47:[2,100],52:[2,100],55:[2,100],64:[2,100],65:[2,100],66:[2,100],68:[2,100],70:[2,100],71:[2,100],75:[2,100],81:[2,100],82:[2,100],83:[2,100],88:[2,100],90:[2,100],99:[2,100],101:[2,100],102:[2,100],103:[2,100],107:[2,100],115:[2,100],123:[2,100],125:[2,100],126:[2,100],129:[2,100],130:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],47:[2,34],52:[2,34],55:[2,34],70:[2,34],75:[2,34],83:[2,34],88:[2,34],90:[2,34],99:[2,34],100:85,101:[2,34],102:[2,34],103:[2,34],106:86,107:[2,34],108:67,115:[2,34],123:[2,34],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:237,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:238,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],47:[2,105],52:[2,105],55:[2,105],64:[2,105],65:[2,105],66:[2,105],68:[2,105],70:[2,105],71:[2,105],75:[2,105],81:[2,105],82:[2,105],83:[2,105],88:[2,105],90:[2,105],99:[2,105],101:[2,105],102:[2,105],103:[2,105],107:[2,105],115:[2,105],123:[2,105],125:[2,105],126:[2,105],129:[2,105],130:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105]},{6:[2,51],25:[2,51],51:239,52:[1,222],83:[2,51]},{6:[2,124],25:[2,124],26:[2,124],52:[2,124],55:[1,240],83:[2,124],88:[2,124],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{48:241,49:[1,58],50:[1,59]},{27:107,28:[1,71],42:108,53:242,54:106,56:109,57:110,73:[1,68],86:[1,111],87:[1,112]},{47:[2,57],52:[2,57]},{8:243,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],47:[2,194],52:[2,194],55:[2,194],70:[2,194],75:[2,194],83:[2,194],88:[2,194],90:[2,194],99:[2,194],100:85,101:[2,194],102:[2,194],103:[2,194],106:86,107:[2,194],108:67,115:[2,194],123:[2,194],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:244,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,196],6:[2,196],25:[2,196],26:[2,196],47:[2,196],52:[2,196],55:[2,196],70:[2,196],75:[2,196],83:[2,196],88:[2,196],90:[2,196],99:[2,196],100:85,101:[2,196],102:[2,196],103:[2,196],106:86,107:[2,196],108:67,115:[2,196],123:[2,196],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,176],6:[2,176],25:[2,176],26:[2,176],47:[2,176],52:[2,176],55:[2,176],70:[2,176],75:[2,176],83:[2,176],88:[2,176],90:[2,176],99:[2,176],101:[2,176],102:[2,176],103:[2,176],107:[2,176],115:[2,176],123:[2,176],125:[2,176],126:[2,176],129:[2,176],130:[2,176],131:[2,176],132:[2,176],133:[2,176],134:[2,176]},{8:245,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,129],6:[2,129],25:[2,129],26:[2,129],47:[2,129],52:[2,129],55:[2,129],70:[2,129],75:[2,129],83:[2,129],88:[2,129],90:[2,129],95:[1,246],99:[2,129],101:[2,129],102:[2,129],103:[2,129],107:[2,129],115:[2,129],123:[2,129],125:[2,129],126:[2,129],129:[2,129],130:[2,129],131:[2,129],132:[2,129],133:[2,129],134:[2,129]},{5:247,25:[1,5]},{27:248,28:[1,71]},{117:249,119:212,120:[1,213]},{26:[1,250],118:[1,251],119:252,120:[1,213]},{26:[2,169],118:[2,169],120:[2,169]},{8:254,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],92:253,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,93],5:255,6:[2,93],25:[1,5],26:[2,93],47:[2,93],52:[2,93],55:[2,93],70:[2,93],75:[2,93],83:[2,93],88:[2,93],90:[2,93],99:[2,93],100:85,101:[1,63],102:[2,93],103:[1,64],106:86,107:[1,66],108:67,115:[2,93],123:[2,93],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,96],6:[2,96],25:[2,96],26:[2,96],47:[2,96],52:[2,96],55:[2,96],70:[2,96],75:[2,96],83:[2,96],88:[2,96],90:[2,96],99:[2,96],101:[2,96],102:[2,96],103:[2,96],107:[2,96],115:[2,96],123:[2,96],125:[2,96],126:[2,96],129:[2,96],130:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96]},{8:256,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],47:[2,134],52:[2,134],55:[2,134],64:[2,134],65:[2,134],66:[2,134],68:[2,134],70:[2,134],71:[2,134],75:[2,134],81:[2,134],82:[2,134],83:[2,134],88:[2,134],90:[2,134],99:[2,134],101:[2,134],102:[2,134],103:[2,134],107:[2,134],115:[2,134],123:[2,134],125:[2,134],126:[2,134],129:[2,134],130:[2,134],131:[2,134],132:[2,134],133:[2,134],134:[2,134]},{6:[1,72],26:[1,257]},{8:258,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,63],12:[2,113],25:[2,63],28:[2,113],30:[2,113],31:[2,113],33:[2,113],34:[2,113],35:[2,113],36:[2,113],43:[2,113],44:[2,113],45:[2,113],49:[2,113],50:[2,113],52:[2,63],73:[2,113],76:[2,113],80:[2,113],85:[2,113],86:[2,113],87:[2,113],88:[2,63],93:[2,113],97:[2,113],98:[2,113],101:[2,113],103:[2,113],105:[2,113],107:[2,113],116:[2,113],122:[2,113],124:[2,113],125:[2,113],126:[2,113],127:[2,113],128:[2,113]},{6:[1,260],25:[1,261],88:[1,259]},{6:[2,52],8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[2,52],26:[2,52],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],83:[2,52],85:[1,56],86:[1,57],87:[1,55],88:[2,52],91:262,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,51],25:[2,51],26:[2,51],51:263,52:[1,222]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],47:[2,173],52:[2,173],55:[2,173],70:[2,173],75:[2,173],83:[2,173],88:[2,173],90:[2,173],99:[2,173],101:[2,173],102:[2,173],103:[2,173],107:[2,173],115:[2,173],118:[2,173],123:[2,173],125:[2,173],126:[2,173],129:[2,173],130:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173]},{8:264,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:265,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{113:[2,152],114:[2,152]},{27:156,28:[1,71],56:157,57:158,73:[1,68],87:[1,112],112:266},{1:[2,158],6:[2,158],25:[2,158],26:[2,158],47:[2,158],52:[2,158],55:[2,158],70:[2,158],75:[2,158],83:[2,158],88:[2,158],90:[2,158],99:[2,158],100:85,101:[2,158],102:[1,267],103:[2,158],106:86,107:[2,158],108:67,115:[1,268],123:[2,158],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,159],6:[2,159],25:[2,159],26:[2,159],47:[2,159],52:[2,159],55:[2,159],70:[2,159],75:[2,159],83:[2,159],88:[2,159],90:[2,159],99:[2,159],100:85,101:[2,159],102:[1,269],103:[2,159],106:86,107:[2,159],108:67,115:[2,159],123:[2,159],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,271],25:[1,272],75:[1,270]},{6:[2,52],11:165,25:[2,52],26:[2,52],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:273,40:164,42:168,44:[1,46],75:[2,52],86:[1,111]},{8:274,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,275],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],38:[2,81],47:[2,81],52:[2,81],55:[2,81],64:[2,81],65:[2,81],66:[2,81],68:[2,81],70:[2,81],71:[2,81],75:[2,81],77:[2,81],81:[2,81],82:[2,81],83:[2,81],88:[2,81],90:[2,81],99:[2,81],101:[2,81],102:[2,81],103:[2,81],107:[2,81],115:[2,81],123:[2,81],125:[2,81],126:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81]},{8:276,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,70:[2,116],73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{70:[2,117],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],47:[2,35],52:[2,35],55:[2,35],70:[2,35],75:[2,35],83:[2,35],88:[2,35],90:[2,35],99:[2,35],100:85,101:[2,35],102:[2,35],103:[2,35],106:86,107:[2,35],108:67,115:[2,35],123:[2,35],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,277],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,260],25:[1,261],83:[1,278]},{6:[2,63],25:[2,63],26:[2,63],52:[2,63],83:[2,63],88:[2,63]},{5:279,25:[1,5]},{47:[2,55],52:[2,55]},{47:[2,58],52:[2,58],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,280],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{5:281,25:[1,5],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{5:282,25:[1,5]},{1:[2,130],6:[2,130],25:[2,130],26:[2,130],47:[2,130],52:[2,130],55:[2,130],70:[2,130],75:[2,130],83:[2,130],88:[2,130],90:[2,130],99:[2,130],101:[2,130],102:[2,130],103:[2,130],107:[2,130],115:[2,130],123:[2,130],125:[2,130],126:[2,130],129:[2,130],130:[2,130],131:[2,130],132:[2,130],133:[2,130],134:[2,130]},{5:283,25:[1,5]},{26:[1,284],118:[1,285],119:252,120:[1,213]},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],47:[2,167],52:[2,167],55:[2,167],70:[2,167],75:[2,167],83:[2,167],88:[2,167],90:[2,167],99:[2,167],101:[2,167],102:[2,167],103:[2,167],107:[2,167],115:[2,167],123:[2,167],125:[2,167],126:[2,167],129:[2,167],130:[2,167],131:[2,167],132:[2,167],133:[2,167],134:[2,167]},{5:286,25:[1,5]},{26:[2,170],118:[2,170],120:[2,170]},{5:287,25:[1,5],52:[1,288]},{25:[2,126],52:[2,126],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,94],6:[2,94],25:[2,94],26:[2,94],47:[2,94],52:[2,94],55:[2,94],70:[2,94],75:[2,94],83:[2,94],88:[2,94],90:[2,94],99:[2,94],101:[2,94],102:[2,94],103:[2,94],107:[2,94],115:[2,94],123:[2,94],125:[2,94],126:[2,94],129:[2,94],130:[2,94],131:[2,94],132:[2,94],133:[2,94],134:[2,94]},{1:[2,97],5:289,6:[2,97],25:[1,5],26:[2,97],47:[2,97],52:[2,97],55:[2,97],70:[2,97],75:[2,97],83:[2,97],88:[2,97],90:[2,97],99:[2,97],100:85,101:[1,63],102:[2,97],103:[1,64],106:86,107:[1,66],108:67,115:[2,97],123:[2,97],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{99:[1,290]},{88:[1,291],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],38:[2,111],47:[2,111],52:[2,111],55:[2,111],64:[2,111],65:[2,111],66:[2,111],68:[2,111],70:[2,111],71:[2,111],75:[2,111],81:[2,111],82:[2,111],83:[2,111],88:[2,111],90:[2,111],99:[2,111],101:[2,111],102:[2,111],103:[2,111],107:[2,111],113:[2,111],114:[2,111],115:[2,111],123:[2,111],125:[2,111],126:[2,111],129:[2,111],130:[2,111],131:[2,111],132:[2,111],133:[2,111],134:[2,111]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],91:292,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:293,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,120],25:[2,120],26:[2,120],52:[2,120],83:[2,120],88:[2,120]},{6:[1,260],25:[1,261],26:[1,294]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],47:[2,137],52:[2,137],55:[2,137],70:[2,137],75:[2,137],83:[2,137],88:[2,137],90:[2,137],99:[2,137],100:85,101:[1,63],102:[2,137],103:[1,64],106:86,107:[1,66],108:67,115:[2,137],123:[2,137],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],47:[2,139],52:[2,139],55:[2,139],70:[2,139],75:[2,139],83:[2,139],88:[2,139],90:[2,139],99:[2,139],100:85,101:[1,63],102:[2,139],103:[1,64],106:86,107:[1,66],108:67,115:[2,139],123:[2,139],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{113:[2,157],114:[2,157]},{8:295,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:296,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:297,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],38:[2,85],47:[2,85],52:[2,85],55:[2,85],64:[2,85],65:[2,85],66:[2,85],68:[2,85],70:[2,85],71:[2,85],75:[2,85],81:[2,85],82:[2,85],83:[2,85],88:[2,85],90:[2,85],99:[2,85],101:[2,85],102:[2,85],103:[2,85],107:[2,85],113:[2,85],114:[2,85],115:[2,85],123:[2,85],125:[2,85],126:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85]},{11:165,27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:298,40:164,42:168,44:[1,46],86:[1,111]},{6:[2,86],11:165,25:[2,86],26:[2,86],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:163,40:164,42:168,44:[1,46],52:[2,86],74:299,86:[1,111]},{6:[2,88],25:[2,88],26:[2,88],52:[2,88],75:[2,88]},{6:[2,38],25:[2,38],26:[2,38],52:[2,38],75:[2,38],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:300,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{70:[2,115],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],47:[2,36],52:[2,36],55:[2,36],70:[2,36],75:[2,36],83:[2,36],88:[2,36],90:[2,36],99:[2,36],101:[2,36],102:[2,36],103:[2,36],107:[2,36],115:[2,36],123:[2,36],125:[2,36],126:[2,36],129:[2,36],130:[2,36],131:[2,36],132:[2,36],133:[2,36],134:[2,36]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],47:[2,106],52:[2,106],55:[2,106],64:[2,106],65:[2,106],66:[2,106],68:[2,106],70:[2,106],71:[2,106],75:[2,106],81:[2,106],82:[2,106],83:[2,106],88:[2,106],90:[2,106],99:[2,106],101:[2,106],102:[2,106],103:[2,106],107:[2,106],115:[2,106],123:[2,106],125:[2,106],126:[2,106],129:[2,106],130:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106]},{1:[2,47],6:[2,47],25:[2,47],26:[2,47],47:[2,47],52:[2,47],55:[2,47],70:[2,47],75:[2,47],83:[2,47],88:[2,47],90:[2,47],99:[2,47],101:[2,47],102:[2,47],103:[2,47],107:[2,47],115:[2,47],123:[2,47],125:[2,47],126:[2,47],129:[2,47],130:[2,47],131:[2,47],132:[2,47],133:[2,47],134:[2,47]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],47:[2,195],52:[2,195],55:[2,195],70:[2,195],75:[2,195],83:[2,195],88:[2,195],90:[2,195],99:[2,195],101:[2,195],102:[2,195],103:[2,195],107:[2,195],115:[2,195],123:[2,195],125:[2,195],126:[2,195],129:[2,195],130:[2,195],131:[2,195],132:[2,195],133:[2,195],134:[2,195]},{1:[2,174],6:[2,174],25:[2,174],26:[2,174],47:[2,174],52:[2,174],55:[2,174],70:[2,174],75:[2,174],83:[2,174],88:[2,174],90:[2,174],99:[2,174],101:[2,174],102:[2,174],103:[2,174],107:[2,174],115:[2,174],118:[2,174],123:[2,174],125:[2,174],126:[2,174],129:[2,174],130:[2,174],131:[2,174],132:[2,174],133:[2,174],134:[2,174]},{1:[2,131],6:[2,131],25:[2,131],26:[2,131],47:[2,131],52:[2,131],55:[2,131],70:[2,131],75:[2,131],83:[2,131],88:[2,131],90:[2,131],99:[2,131],101:[2,131],102:[2,131],103:[2,131],107:[2,131],115:[2,131],123:[2,131],125:[2,131],126:[2,131],129:[2,131],130:[2,131],131:[2,131],132:[2,131],133:[2,131],134:[2,131]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],47:[2,132],52:[2,132],55:[2,132],70:[2,132],75:[2,132],83:[2,132],88:[2,132],90:[2,132],95:[2,132],99:[2,132],101:[2,132],102:[2,132],103:[2,132],107:[2,132],115:[2,132],123:[2,132],125:[2,132],126:[2,132],129:[2,132],130:[2,132],131:[2,132],132:[2,132],133:[2,132],134:[2,132]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],47:[2,165],52:[2,165],55:[2,165],70:[2,165],75:[2,165],83:[2,165],88:[2,165],90:[2,165],99:[2,165],101:[2,165],102:[2,165],103:[2,165],107:[2,165],115:[2,165],123:[2,165],125:[2,165],126:[2,165],129:[2,165],130:[2,165],131:[2,165],132:[2,165],133:[2,165],134:[2,165]},{5:301,25:[1,5]},{26:[1,302]},{6:[1,303],26:[2,171],118:[2,171],120:[2,171]},{8:304,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],47:[2,98],52:[2,98],55:[2,98],70:[2,98],75:[2,98],83:[2,98],88:[2,98],90:[2,98],99:[2,98],101:[2,98],102:[2,98],103:[2,98],107:[2,98],115:[2,98],123:[2,98],125:[2,98],126:[2,98],129:[2,98],130:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],47:[2,135],52:[2,135],55:[2,135],64:[2,135],65:[2,135],66:[2,135],68:[2,135],70:[2,135],71:[2,135],75:[2,135],81:[2,135],82:[2,135],83:[2,135],88:[2,135],90:[2,135],99:[2,135],101:[2,135],102:[2,135],103:[2,135],107:[2,135],115:[2,135],123:[2,135],125:[2,135],126:[2,135],129:[2,135],130:[2,135],131:[2,135],132:[2,135],133:[2,135],134:[2,135]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],47:[2,114],52:[2,114],55:[2,114],64:[2,114],65:[2,114],66:[2,114],68:[2,114],70:[2,114],71:[2,114],75:[2,114],81:[2,114],82:[2,114],83:[2,114],88:[2,114],90:[2,114],99:[2,114],101:[2,114],102:[2,114],103:[2,114],107:[2,114],115:[2,114],123:[2,114],125:[2,114],126:[2,114],129:[2,114],130:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114]},{6:[2,121],25:[2,121],26:[2,121],52:[2,121],83:[2,121],88:[2,121]},{6:[2,51],25:[2,51],26:[2,51],51:305,52:[1,222]},{6:[2,122],25:[2,122],26:[2,122],52:[2,122],83:[2,122],88:[2,122]},{1:[2,160],6:[2,160],25:[2,160],26:[2,160],47:[2,160],52:[2,160],55:[2,160],70:[2,160],75:[2,160],83:[2,160],88:[2,160],90:[2,160],99:[2,160],100:85,101:[2,160],102:[2,160],103:[2,160],106:86,107:[2,160],108:67,115:[1,306],123:[2,160],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,162],6:[2,162],25:[2,162],26:[2,162],47:[2,162],52:[2,162],55:[2,162],70:[2,162],75:[2,162],83:[2,162],88:[2,162],90:[2,162],99:[2,162],100:85,101:[2,162],102:[1,307],103:[2,162],106:86,107:[2,162],108:67,115:[2,162],123:[2,162],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,161],6:[2,161],25:[2,161],26:[2,161],47:[2,161],52:[2,161],55:[2,161],70:[2,161],75:[2,161],83:[2,161],88:[2,161],90:[2,161],99:[2,161],100:85,101:[2,161],102:[2,161],103:[2,161],106:86,107:[2,161],108:67,115:[2,161],123:[2,161],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[2,89],25:[2,89],26:[2,89],52:[2,89],75:[2,89]},{6:[2,51],25:[2,51],26:[2,51],51:308,52:[1,232]},{26:[1,309],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,310]},{1:[2,168],6:[2,168],25:[2,168],26:[2,168],47:[2,168],52:[2,168],55:[2,168],70:[2,168],75:[2,168],83:[2,168],88:[2,168],90:[2,168],99:[2,168],101:[2,168],102:[2,168],103:[2,168],107:[2,168],115:[2,168],123:[2,168],125:[2,168],126:[2,168],129:[2,168],130:[2,168],131:[2,168],132:[2,168],133:[2,168],134:[2,168]},{26:[2,172],118:[2,172],120:[2,172]},{25:[2,127],52:[2,127],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,260],25:[1,261],26:[1,311]},{8:312,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:313,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[1,271],25:[1,272],26:[1,314]},{6:[2,39],25:[2,39],26:[2,39],52:[2,39],75:[2,39]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],47:[2,166],52:[2,166],55:[2,166],70:[2,166],75:[2,166],83:[2,166],88:[2,166],90:[2,166],99:[2,166],101:[2,166],102:[2,166],103:[2,166],107:[2,166],115:[2,166],123:[2,166],125:[2,166],126:[2,166],129:[2,166],130:[2,166],131:[2,166],132:[2,166],133:[2,166],134:[2,166]},{6:[2,123],25:[2,123],26:[2,123],52:[2,123],83:[2,123],88:[2,123]},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],47:[2,163],52:[2,163],55:[2,163],70:[2,163],75:[2,163],83:[2,163],88:[2,163],90:[2,163],99:[2,163],100:85,101:[2,163],102:[2,163],103:[2,163],106:86,107:[2,163],108:67,115:[2,163],123:[2,163],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],47:[2,164],52:[2,164],55:[2,164],70:[2,164],75:[2,164],83:[2,164],88:[2,164],90:[2,164],99:[2,164],100:85,101:[2,164],102:[2,164],103:[2,164],106:86,107:[2,164],108:67,115:[2,164],123:[2,164],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[2,90],25:[2,90],26:[2,90],52:[2,90],75:[2,90]}], +defaultActions: {58:[2,49],59:[2,50],73:[2,3],92:[2,104],186:[2,84]}, +parseError: function parseError(str, hash) { + throw new Error(str); +}, +parse: function parse(input) { + var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + if (typeof this.lexer.yylloc == "undefined") + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + if (typeof this.yy.parseError === "function") + this.parseError = this.yy.parseError; + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + function lex() { + var token; + token = self.lexer.lex() || 1; + if (typeof token !== "number") { + token = self.symbols_[token] || token; + } + return token; + } + var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol == null) + symbol = lex(); + action = table[state] && table[state][symbol]; + } + if (typeof action === "undefined" || !action.length || !action[0]) { + if (!recovering) { + expected = []; + for (p in table[state]) + if (this.terminals_[p] && p > 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + var errStr = ""; + if (this.lexer.showPosition) { + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + this.terminals_[symbol] + "'"; + } else { + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'"); + } + this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column}; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; +} +}; + +module.exports = parser; + + +}); + +define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coffee/scope', 'ace/mode/coffee/lexer', 'ace/mode/coffee/helpers'], function(require, exports, module) { +// Generated by CoffeeScript 1.2.1-pre + + var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, unfoldSoak, utility, _ref, _ref1, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + Scope = require('./scope').Scope; + + _ref = require('./lexer'), RESERVED = _ref.RESERVED, STRICT_PROSCRIBED = _ref.STRICT_PROSCRIBED; + + _ref1 = require('./helpers'), compact = _ref1.compact, flatten = _ref1.flatten, extend = _ref1.extend, merge = _ref1.merge, del = _ref1.del, starts = _ref1.starts, ends = _ref1.ends, last = _ref1.last; + + exports.extend = extend; + + YES = function() { + return true; + }; + + NO = function() { + return false; + }; + + THIS = function() { + return this; + }; + + NEGATE = function() { + this.negated = !this.negated; + return this; + }; + + exports.Base = Base = (function() { + + Base.name = 'Base'; + + function Base() {} + + Base.prototype.compile = function(o, lvl) { + var node; + o = extend({}, o); + if (lvl) o.level = lvl; + node = this.unfoldSoak(o) || this; + node.tab = o.indent; + if (o.level === LEVEL_TOP || !node.isStatement(o)) { + return node.compileNode(o); + } else { + return node.compileClosure(o); + } + }; + + Base.prototype.compileClosure = function(o) { + if (this.jumps()) { + throw SyntaxError('cannot use a pure statement in an expression.'); + } + o.sharedScope = true; + return Closure.wrap(this).compileNode(o); + }; + + Base.prototype.cache = function(o, level, reused) { + var ref, sub; + if (!this.isComplex()) { + ref = level ? this.compile(o, level) : this; + return [ref, ref]; + } else { + ref = new Literal(reused || o.scope.freeVariable('ref')); + sub = new Assign(ref, this); + if (level) { + return [sub.compile(o, level), ref.value]; + } else { + return [sub, ref]; + } + } + }; + + Base.prototype.compileLoopReference = function(o, name) { + var src, tmp; + src = tmp = this.compile(o, LEVEL_LIST); + if (!((-Infinity < +src && +src < Infinity) || IDENTIFIER.test(src) && o.scope.check(src, true))) { + src = "" + (tmp = o.scope.freeVariable(name)) + " = " + src; + } + return [src, tmp]; + }; + + Base.prototype.makeReturn = function(res) { + var me; + me = this.unwrapAll(); + if (res) { + return new Call(new Literal("" + res + ".push"), [me]); + } else { + return new Return(me); + } + }; + + Base.prototype.contains = function(pred) { + var contains; + contains = false; + this.traverseChildren(false, function(node) { + if (pred(node)) { + contains = true; + return false; + } + }); + return contains; + }; + + Base.prototype.containsType = function(type) { + return this instanceof type || this.contains(function(node) { + return node instanceof type; + }); + }; + + Base.prototype.lastNonComment = function(list) { + var i; + i = list.length; + while (i--) { + if (!(list[i] instanceof Comment)) return list[i]; + } + return null; + }; + + Base.prototype.toString = function(idt, name) { + var tree; + if (idt == null) idt = ''; + if (name == null) name = this.constructor.name; + tree = '\n' + idt + name; + if (this.soak) tree += '?'; + this.eachChild(function(node) { + return tree += node.toString(idt + TAB); + }); + return tree; + }; + + Base.prototype.eachChild = function(func) { + var attr, child, _i, _j, _len, _len1, _ref2, _ref3; + if (!this.children) return this; + _ref2 = this.children; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + attr = _ref2[_i]; + if (this[attr]) { + _ref3 = flatten([this[attr]]); + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + child = _ref3[_j]; + if (func(child) === false) return this; + } + } + } + return this; + }; + + Base.prototype.traverseChildren = function(crossScope, func) { + return this.eachChild(function(child) { + if (func(child) === false) return false; + return child.traverseChildren(crossScope, func); + }); + }; + + Base.prototype.invert = function() { + return new Op('!', this); + }; + + Base.prototype.unwrapAll = function() { + var node; + node = this; + while (node !== (node = node.unwrap())) { + continue; + } + return node; + }; + + Base.prototype.children = []; + + Base.prototype.isStatement = NO; + + Base.prototype.jumps = NO; + + Base.prototype.isComplex = YES; + + Base.prototype.isChainable = NO; + + Base.prototype.isAssignable = NO; + + Base.prototype.unwrap = THIS; + + Base.prototype.unfoldSoak = NO; + + Base.prototype.assigns = NO; + + return Base; + + })(); + + exports.Block = Block = (function(_super) { + + __extends(Block, _super); + + Block.name = 'Block'; + + function Block(nodes) { + this.expressions = compact(flatten(nodes || [])); + } + + Block.prototype.children = ['expressions']; + + Block.prototype.push = function(node) { + this.expressions.push(node); + return this; + }; + + Block.prototype.pop = function() { + return this.expressions.pop(); + }; + + Block.prototype.unshift = function(node) { + this.expressions.unshift(node); + return this; + }; + + Block.prototype.unwrap = function() { + if (this.expressions.length === 1) { + return this.expressions[0]; + } else { + return this; + } + }; + + Block.prototype.isEmpty = function() { + return !this.expressions.length; + }; + + Block.prototype.isStatement = function(o) { + var exp, _i, _len, _ref2; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + exp = _ref2[_i]; + if (exp.isStatement(o)) return true; + } + return false; + }; + + Block.prototype.jumps = function(o) { + var exp, _i, _len, _ref2; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + exp = _ref2[_i]; + if (exp.jumps(o)) return exp; + } + }; + + Block.prototype.makeReturn = function(res) { + var expr, len; + len = this.expressions.length; + while (len--) { + expr = this.expressions[len]; + if (!(expr instanceof Comment)) { + this.expressions[len] = expr.makeReturn(res); + if (expr instanceof Return && !expr.expression) { + this.expressions.splice(len, 1); + } + break; + } + } + return this; + }; + + Block.prototype.compile = function(o, level) { + if (o == null) o = {}; + if (o.scope) { + return Block.__super__.compile.call(this, o, level); + } else { + return this.compileRoot(o); + } + }; + + Block.prototype.compileNode = function(o) { + var code, codes, node, top, _i, _len, _ref2; + this.tab = o.indent; + top = o.level === LEVEL_TOP; + codes = []; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + node = _ref2[_i]; + node = node.unwrapAll(); + node = node.unfoldSoak(o) || node; + if (node instanceof Block) { + codes.push(node.compileNode(o)); + } else if (top) { + node.front = true; + code = node.compile(o); + if (!node.isStatement(o)) { + code = "" + this.tab + code + ";"; + if (node instanceof Literal) code = "" + code + "\n"; + } + codes.push(code); + } else { + codes.push(node.compile(o, LEVEL_LIST)); + } + } + if (top) { + if (this.spaced) { + return "\n" + (codes.join('\n\n')) + "\n"; + } else { + return codes.join('\n'); + } + } + code = codes.join(', ') || 'void 0'; + if (codes.length > 1 && o.level >= LEVEL_LIST) { + return "(" + code + ")"; + } else { + return code; + } + }; + + Block.prototype.compileRoot = function(o) { + var code, exp, i, prelude, preludeExps, rest; + o.indent = o.bare ? '' : TAB; + o.scope = new Scope(null, this, null); + o.level = LEVEL_TOP; + this.spaced = true; + prelude = ""; + if (!o.bare) { + preludeExps = (function() { + var _i, _len, _ref2, _results; + _ref2 = this.expressions; + _results = []; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + exp = _ref2[i]; + if (!(exp.unwrap() instanceof Comment)) break; + _results.push(exp); + } + return _results; + }).call(this); + rest = this.expressions.slice(preludeExps.length); + this.expressions = preludeExps; + if (preludeExps.length) { + prelude = "" + (this.compileNode(merge(o, { + indent: '' + }))) + "\n"; + } + this.expressions = rest; + } + code = this.compileWithDeclarations(o); + if (o.bare) return code; + return "" + prelude + "(function() {\n" + code + "\n}).call(this);\n"; + }; + + Block.prototype.compileWithDeclarations = function(o) { + var assigns, code, declars, exp, i, post, rest, scope, spaced, _i, _len, _ref2, _ref3, _ref4; + code = post = ''; + _ref2 = this.expressions; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + exp = _ref2[i]; + exp = exp.unwrap(); + if (!(exp instanceof Comment || exp instanceof Literal)) break; + } + o = merge(o, { + level: LEVEL_TOP + }); + if (i) { + rest = this.expressions.splice(i, 9e9); + _ref3 = [this.spaced, false], spaced = _ref3[0], this.spaced = _ref3[1]; + _ref4 = [this.compileNode(o), spaced], code = _ref4[0], this.spaced = _ref4[1]; + this.expressions = rest; + } + post = this.compileNode(o); + scope = o.scope; + if (scope.expressions === this) { + declars = o.scope.hasDeclarations(); + assigns = scope.hasAssignments; + if (declars || assigns) { + if (i) code += '\n'; + code += "" + this.tab + "var "; + if (declars) code += scope.declaredVariables().join(', '); + if (assigns) { + if (declars) code += ",\n" + (this.tab + TAB); + code += scope.assignedVariables().join(",\n" + (this.tab + TAB)); + } + code += ';\n'; + } + } + return code + post; + }; + + Block.wrap = function(nodes) { + if (nodes.length === 1 && nodes[0] instanceof Block) return nodes[0]; + return new Block(nodes); + }; + + return Block; + + })(Base); + + exports.Literal = Literal = (function(_super) { + + __extends(Literal, _super); + + Literal.name = 'Literal'; + + function Literal(value) { + this.value = value; + } + + Literal.prototype.makeReturn = function() { + if (this.isStatement()) { + return this; + } else { + return Literal.__super__.makeReturn.apply(this, arguments); + } + }; + + Literal.prototype.isAssignable = function() { + return IDENTIFIER.test(this.value); + }; + + Literal.prototype.isStatement = function() { + var _ref2; + return (_ref2 = this.value) === 'break' || _ref2 === 'continue' || _ref2 === 'debugger'; + }; + + Literal.prototype.isComplex = NO; + + Literal.prototype.assigns = function(name) { + return name === this.value; + }; + + Literal.prototype.jumps = function(o) { + if (this.value === 'break' && !((o != null ? o.loop : void 0) || (o != null ? o.block : void 0))) { + return this; + } + if (this.value === 'continue' && !(o != null ? o.loop : void 0)) return this; + }; + + Literal.prototype.compileNode = function(o) { + var code, _ref2; + code = this.isUndefined ? o.level >= LEVEL_ACCESS ? '(void 0)' : 'void 0' : this.value === 'this' ? ((_ref2 = o.scope.method) != null ? _ref2.bound : void 0) ? o.scope.method.context : this.value : this.value.reserved ? "\"" + this.value + "\"" : this.value; + if (this.isStatement()) { + return "" + this.tab + code + ";"; + } else { + return code; + } + }; + + Literal.prototype.toString = function() { + return ' "' + this.value + '"'; + }; + + return Literal; + + })(Base); + + exports.Return = Return = (function(_super) { + + __extends(Return, _super); + + Return.name = 'Return'; + + function Return(expr) { + if (expr && !expr.unwrap().isUndefined) this.expression = expr; + } + + Return.prototype.children = ['expression']; + + Return.prototype.isStatement = YES; + + Return.prototype.makeReturn = THIS; + + Return.prototype.jumps = THIS; + + Return.prototype.compile = function(o, level) { + var expr, _ref2; + expr = (_ref2 = this.expression) != null ? _ref2.makeReturn() : void 0; + if (expr && !(expr instanceof Return)) { + return expr.compile(o, level); + } else { + return Return.__super__.compile.call(this, o, level); + } + }; + + Return.prototype.compileNode = function(o) { + return this.tab + ("return" + [this.expression ? " " + (this.expression.compile(o, LEVEL_PAREN)) : void 0] + ";"); + }; + + return Return; + + })(Base); + + exports.Value = Value = (function(_super) { + + __extends(Value, _super); + + Value.name = 'Value'; + + function Value(base, props, tag) { + if (!props && base instanceof Value) return base; + this.base = base; + this.properties = props || []; + if (tag) this[tag] = true; + return this; + } + + Value.prototype.children = ['base', 'properties']; + + Value.prototype.add = function(props) { + this.properties = this.properties.concat(props); + return this; + }; + + Value.prototype.hasProperties = function() { + return !!this.properties.length; + }; + + Value.prototype.isArray = function() { + return !this.properties.length && this.base instanceof Arr; + }; + + Value.prototype.isComplex = function() { + return this.hasProperties() || this.base.isComplex(); + }; + + Value.prototype.isAssignable = function() { + return this.hasProperties() || this.base.isAssignable(); + }; + + Value.prototype.isSimpleNumber = function() { + return this.base instanceof Literal && SIMPLENUM.test(this.base.value); + }; + + Value.prototype.isString = function() { + return this.base instanceof Literal && IS_STRING.test(this.base.value); + }; + + Value.prototype.isAtomic = function() { + var node, _i, _len, _ref2; + _ref2 = this.properties.concat(this.base); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + node = _ref2[_i]; + if (node.soak || node instanceof Call) return false; + } + return true; + }; + + Value.prototype.isStatement = function(o) { + return !this.properties.length && this.base.isStatement(o); + }; + + Value.prototype.assigns = function(name) { + return !this.properties.length && this.base.assigns(name); + }; + + Value.prototype.jumps = function(o) { + return !this.properties.length && this.base.jumps(o); + }; + + Value.prototype.isObject = function(onlyGenerated) { + if (this.properties.length) return false; + return (this.base instanceof Obj) && (!onlyGenerated || this.base.generated); + }; + + Value.prototype.isSplice = function() { + return last(this.properties) instanceof Slice; + }; + + Value.prototype.unwrap = function() { + if (this.properties.length) { + return this; + } else { + return this.base; + } + }; + + Value.prototype.cacheReference = function(o) { + var base, bref, name, nref; + name = last(this.properties); + if (this.properties.length < 2 && !this.base.isComplex() && !(name != null ? name.isComplex() : void 0)) { + return [this, this]; + } + base = new Value(this.base, this.properties.slice(0, -1)); + if (base.isComplex()) { + bref = new Literal(o.scope.freeVariable('base')); + base = new Value(new Parens(new Assign(bref, base))); + } + if (!name) return [base, bref]; + if (name.isComplex()) { + nref = new Literal(o.scope.freeVariable('name')); + name = new Index(new Assign(nref, name.index)); + nref = new Index(nref); + } + return [base.add(name), new Value(bref || base.base, [nref || name])]; + }; + + Value.prototype.compileNode = function(o) { + var code, prop, props, _i, _len; + this.base.front = this.front; + props = this.properties; + code = this.base.compile(o, props.length ? LEVEL_ACCESS : null); + if ((this.base instanceof Parens || props.length) && SIMPLENUM.test(code)) { + code = "" + code + "."; + } + for (_i = 0, _len = props.length; _i < _len; _i++) { + prop = props[_i]; + code += prop.compile(o); + } + return code; + }; + + Value.prototype.unfoldSoak = function(o) { + var result, + _this = this; + if (this.unfoldedSoak != null) return this.unfoldedSoak; + result = (function() { + var fst, i, ifn, prop, ref, snd, _i, _len, _ref2; + if (ifn = _this.base.unfoldSoak(o)) { + Array.prototype.push.apply(ifn.body.properties, _this.properties); + return ifn; + } + _ref2 = _this.properties; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + prop = _ref2[i]; + if (!prop.soak) continue; + prop.soak = false; + fst = new Value(_this.base, _this.properties.slice(0, i)); + snd = new Value(_this.base, _this.properties.slice(i)); + if (fst.isComplex()) { + ref = new Literal(o.scope.freeVariable('ref')); + fst = new Parens(new Assign(ref, fst)); + snd.base = ref; + } + return new If(new Existence(fst), snd, { + soak: true + }); + } + return null; + })(); + return this.unfoldedSoak = result || false; + }; + + return Value; + + })(Base); + + exports.Comment = Comment = (function(_super) { + + __extends(Comment, _super); + + Comment.name = 'Comment'; + + function Comment(comment) { + this.comment = comment; + } + + Comment.prototype.isStatement = YES; + + Comment.prototype.makeReturn = THIS; + + Comment.prototype.compileNode = function(o, level) { + var code; + code = '/*' + multident(this.comment, this.tab) + ("\n" + this.tab + "*/\n"); + if ((level || o.level) === LEVEL_TOP) code = o.indent + code; + return code; + }; + + return Comment; + + })(Base); + + exports.Call = Call = (function(_super) { + + __extends(Call, _super); + + Call.name = 'Call'; + + function Call(variable, args, soak) { + this.args = args != null ? args : []; + this.soak = soak; + this.isNew = false; + this.isSuper = variable === 'super'; + this.variable = this.isSuper ? null : variable; + } + + Call.prototype.children = ['variable', 'args']; + + Call.prototype.newInstance = function() { + var base, _ref2; + base = ((_ref2 = this.variable) != null ? _ref2.base : void 0) || this.variable; + if (base instanceof Call && !base.isNew) { + base.newInstance(); + } else { + this.isNew = true; + } + return this; + }; + + Call.prototype.superReference = function(o) { + var accesses, method, name; + method = o.scope.method; + if (!method) throw SyntaxError('cannot call super outside of a function.'); + name = method.name; + if (name == null) { + throw SyntaxError('cannot call super on an anonymous function.'); + } + if (method.klass) { + accesses = [new Access(new Literal('__super__'))]; + if (method["static"]) { + accesses.push(new Access(new Literal('constructor'))); + } + accesses.push(new Access(new Literal(name))); + return (new Value(new Literal(method.klass), accesses)).compile(o); + } else { + return "" + name + ".__super__.constructor"; + } + }; + + Call.prototype.unfoldSoak = function(o) { + var call, ifn, left, list, rite, _i, _len, _ref2, _ref3; + if (this.soak) { + if (this.variable) { + if (ifn = unfoldSoak(o, this, 'variable')) return ifn; + _ref2 = new Value(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1]; + } else { + left = new Literal(this.superReference(o)); + rite = new Value(left); + } + rite = new Call(rite, this.args); + rite.isNew = this.isNew; + left = new Literal("typeof " + (left.compile(o)) + " === \"function\""); + return new If(left, new Value(rite), { + soak: true + }); + } + call = this; + list = []; + while (true) { + if (call.variable instanceof Call) { + list.push(call); + call = call.variable; + continue; + } + if (!(call.variable instanceof Value)) break; + list.push(call); + if (!((call = call.variable.base) instanceof Call)) break; + } + _ref3 = list.reverse(); + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + call = _ref3[_i]; + if (ifn) { + if (call.variable instanceof Call) { + call.variable = ifn; + } else { + call.variable.base = ifn; + } + } + ifn = unfoldSoak(o, call, 'variable'); + } + return ifn; + }; + + Call.prototype.filterImplicitObjects = function(list) { + var node, nodes, obj, prop, properties, _i, _j, _len, _len1, _ref2; + nodes = []; + for (_i = 0, _len = list.length; _i < _len; _i++) { + node = list[_i]; + if (!((typeof node.isObject === "function" ? node.isObject() : void 0) && node.base.generated)) { + nodes.push(node); + continue; + } + obj = null; + _ref2 = node.base.properties; + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + prop = _ref2[_j]; + if (prop instanceof Assign || prop instanceof Comment) { + if (!obj) nodes.push(obj = new Obj(properties = [], true)); + properties.push(prop); + } else { + nodes.push(prop); + obj = null; + } + } + } + return nodes; + }; + + Call.prototype.compileNode = function(o) { + var arg, args, code, _ref2; + if ((_ref2 = this.variable) != null) _ref2.front = this.front; + if (code = Splat.compileSplattedArray(o, this.args, true)) { + return this.compileSplat(o, code); + } + args = this.filterImplicitObjects(this.args); + args = ((function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = args.length; _i < _len; _i++) { + arg = args[_i]; + _results.push(arg.compile(o, LEVEL_LIST)); + } + return _results; + })()).join(', '); + if (this.isSuper) { + return this.superReference(o) + (".call(this" + (args && ', ' + args) + ")"); + } else { + return (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL_ACCESS) + ("(" + args + ")"); + } + }; + + Call.prototype.compileSuper = function(args, o) { + return "" + (this.superReference(o)) + ".call(this" + (args.length ? ', ' : '') + args + ")"; + }; + + Call.prototype.compileSplat = function(o, splatArgs) { + var base, fun, idt, name, ref; + if (this.isSuper) { + return "" + (this.superReference(o)) + ".apply(this, " + splatArgs + ")"; + } + if (this.isNew) { + idt = this.tab + TAB; + return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args), t = typeof result;\n" + idt + "return t == \"object\" || t == \"function\" ? result || child : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_LIST)) + ", " + splatArgs + ", function(){})"; + } + base = new Value(this.variable); + if ((name = base.properties.pop()) && base.isComplex()) { + ref = o.scope.freeVariable('ref'); + fun = "(" + ref + " = " + (base.compile(o, LEVEL_LIST)) + ")" + (name.compile(o)); + } else { + fun = base.compile(o, LEVEL_ACCESS); + if (SIMPLENUM.test(fun)) fun = "(" + fun + ")"; + if (name) { + ref = fun; + fun += name.compile(o); + } else { + ref = 'null'; + } + } + return "" + fun + ".apply(" + ref + ", " + splatArgs + ")"; + }; + + return Call; + + })(Base); + + exports.Extends = Extends = (function(_super) { + + __extends(Extends, _super); + + Extends.name = 'Extends'; + + function Extends(child, parent) { + this.child = child; + this.parent = parent; + } + + Extends.prototype.children = ['child', 'parent']; + + Extends.prototype.compile = function(o) { + return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o); + }; + + return Extends; + + })(Base); + + exports.Access = Access = (function(_super) { + + __extends(Access, _super); + + Access.name = 'Access'; + + function Access(name, tag) { + this.name = name; + this.name.asKey = true; + this.soak = tag === 'soak'; + } + + Access.prototype.children = ['name']; + + Access.prototype.compile = function(o) { + var name; + name = this.name.compile(o); + if (IDENTIFIER.test(name)) { + return "." + name; + } else { + return "[" + name + "]"; + } + }; + + Access.prototype.isComplex = NO; + + return Access; + + })(Base); + + exports.Index = Index = (function(_super) { + + __extends(Index, _super); + + Index.name = 'Index'; + + function Index(index) { + this.index = index; + } + + Index.prototype.children = ['index']; + + Index.prototype.compile = function(o) { + return "[" + (this.index.compile(o, LEVEL_PAREN)) + "]"; + }; + + Index.prototype.isComplex = function() { + return this.index.isComplex(); + }; + + return Index; + + })(Base); + + exports.Range = Range = (function(_super) { + + __extends(Range, _super); + + Range.name = 'Range'; + + Range.prototype.children = ['from', 'to']; + + function Range(from, to, tag) { + this.from = from; + this.to = to; + this.exclusive = tag === 'exclusive'; + this.equals = this.exclusive ? '' : '='; + } + + Range.prototype.compileVariables = function(o) { + var step, _ref2, _ref3, _ref4, _ref5; + o = merge(o, { + top: true + }); + _ref2 = this.from.cache(o, LEVEL_LIST), this.fromC = _ref2[0], this.fromVar = _ref2[1]; + _ref3 = this.to.cache(o, LEVEL_LIST), this.toC = _ref3[0], this.toVar = _ref3[1]; + if (step = del(o, 'step')) { + _ref4 = step.cache(o, LEVEL_LIST), this.step = _ref4[0], this.stepVar = _ref4[1]; + } + _ref5 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref5[0], this.toNum = _ref5[1]; + if (this.stepVar) return this.stepNum = this.stepVar.match(SIMPLENUM); + }; + + Range.prototype.compileNode = function(o) { + var cond, condPart, from, gt, idx, idxName, known, lt, namedIndex, stepPart, to, varPart, _ref2, _ref3; + if (!this.fromVar) this.compileVariables(o); + if (!o.index) return this.compileArray(o); + known = this.fromNum && this.toNum; + idx = del(o, 'index'); + idxName = del(o, 'name'); + namedIndex = idxName && idxName !== idx; + varPart = "" + idx + " = " + this.fromC; + if (this.toC !== this.toVar) varPart += ", " + this.toC; + if (this.step !== this.stepVar) varPart += ", " + this.step; + _ref2 = ["" + idx + " <" + this.equals, "" + idx + " >" + this.equals], lt = _ref2[0], gt = _ref2[1]; + condPart = this.stepNum ? +this.stepNum > 0 ? "" + lt + " " + this.toVar : "" + gt + " " + this.toVar : known ? ((_ref3 = [+this.fromNum, +this.toNum], from = _ref3[0], to = _ref3[1], _ref3), from <= to ? "" + lt + " " + to : "" + gt + " " + to) : (cond = "" + this.fromVar + " <= " + this.toVar, "" + cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar); + stepPart = this.stepVar ? "" + idx + " += " + this.stepVar : known ? namedIndex ? from <= to ? "++" + idx : "--" + idx : from <= to ? "" + idx + "++" : "" + idx + "--" : namedIndex ? "" + cond + " ? ++" + idx + " : --" + idx : "" + cond + " ? " + idx + "++ : " + idx + "--"; + if (namedIndex) varPart = "" + idxName + " = " + varPart; + if (namedIndex) stepPart = "" + idxName + " = " + stepPart; + return "" + varPart + "; " + condPart + "; " + stepPart; + }; + + Range.prototype.compileArray = function(o) { + var args, body, cond, hasArgs, i, idt, post, pre, range, result, vars, _i, _ref2, _ref3, _results; + if (this.fromNum && this.toNum && Math.abs(this.fromNum - this.toNum) <= 20) { + range = (function() { + _results = []; + for (var _i = _ref2 = +this.fromNum, _ref3 = +this.toNum; _ref2 <= _ref3 ? _i <= _ref3 : _i >= _ref3; _ref2 <= _ref3 ? _i++ : _i--){ _results.push(_i); } + return _results; + }).apply(this); + if (this.exclusive) range.pop(); + return "[" + (range.join(', ')) + "]"; + } + idt = this.tab + TAB; + i = o.scope.freeVariable('i'); + result = o.scope.freeVariable('results'); + pre = "\n" + idt + result + " = [];"; + if (this.fromNum && this.toNum) { + o.index = i; + body = this.compileNode(o); + } else { + vars = ("" + i + " = " + this.fromC) + (this.toC !== this.toVar ? ", " + this.toC : ''); + cond = "" + this.fromVar + " <= " + this.toVar; + body = "var " + vars + "; " + cond + " ? " + i + " <" + this.equals + " " + this.toVar + " : " + i + " >" + this.equals + " " + this.toVar + "; " + cond + " ? " + i + "++ : " + i + "--"; + } + post = "{ " + result + ".push(" + i + "); }\n" + idt + "return " + result + ";\n" + o.indent; + hasArgs = function(node) { + return node != null ? node.contains(function(n) { + return n instanceof Literal && n.value === 'arguments' && !n.asKey; + }) : void 0; + }; + if (hasArgs(this.from) || hasArgs(this.to)) args = ', arguments'; + return "(function() {" + pre + "\n" + idt + "for (" + body + ")" + post + "}).apply(this" + (args != null ? args : '') + ")"; + }; + + return Range; + + })(Base); + + exports.Slice = Slice = (function(_super) { + + __extends(Slice, _super); + + Slice.name = 'Slice'; + + Slice.prototype.children = ['range']; + + function Slice(range) { + this.range = range; + Slice.__super__.constructor.call(this); + } + + Slice.prototype.compileNode = function(o) { + var compiled, from, fromStr, to, toStr, _ref2; + _ref2 = this.range, to = _ref2.to, from = _ref2.from; + fromStr = from && from.compile(o, LEVEL_PAREN) || '0'; + compiled = to && to.compile(o, LEVEL_PAREN); + if (to && !(!this.range.exclusive && +compiled === -1)) { + toStr = ', ' + (this.range.exclusive ? compiled : SIMPLENUM.test(compiled) ? "" + (+compiled + 1) : (compiled = to.compile(o, LEVEL_ACCESS), "" + compiled + " + 1 || 9e9")); + } + return ".slice(" + fromStr + (toStr || '') + ")"; + }; + + return Slice; + + })(Base); + + exports.Obj = Obj = (function(_super) { + + __extends(Obj, _super); + + Obj.name = 'Obj'; + + function Obj(props, generated) { + this.generated = generated != null ? generated : false; + this.objects = this.properties = props || []; + } + + Obj.prototype.children = ['properties']; + + Obj.prototype.compileNode = function(o) { + var i, idt, indent, join, lastNoncom, node, obj, prop, propName, propNames, props, _i, _j, _len, _len1, _ref2; + props = this.properties; + propNames = []; + _ref2 = this.properties; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + prop = _ref2[_i]; + if (prop.isComplex()) prop = prop.variable; + if (prop != null) { + propName = prop.unwrapAll().value.toString(); + if (__indexOf.call(propNames, propName) >= 0) { + throw SyntaxError("multiple object literal properties named \"" + propName + "\""); + } + propNames.push(propName); + } + } + if (!props.length) return (this.front ? '({})' : '{}'); + if (this.generated) { + for (_j = 0, _len1 = props.length; _j < _len1; _j++) { + node = props[_j]; + if (node instanceof Value) { + throw new Error('cannot have an implicit value in an implicit object'); + } + } + } + idt = o.indent += TAB; + lastNoncom = this.lastNonComment(this.properties); + props = (function() { + var _k, _len2, _results; + _results = []; + for (i = _k = 0, _len2 = props.length; _k < _len2; i = ++_k) { + prop = props[i]; + join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n'; + indent = prop instanceof Comment ? '' : idt; + if (prop instanceof Value && prop["this"]) { + prop = new Assign(prop.properties[0].name, prop, 'object'); + } + if (!(prop instanceof Comment)) { + if (!(prop instanceof Assign)) prop = new Assign(prop, prop, 'object'); + (prop.variable.base || prop.variable).asKey = true; + } + _results.push(indent + prop.compile(o, LEVEL_TOP) + join); + } + return _results; + })(); + props = props.join(''); + obj = "{" + (props && '\n' + props + '\n' + this.tab) + "}"; + if (this.front) { + return "(" + obj + ")"; + } else { + return obj; + } + }; + + Obj.prototype.assigns = function(name) { + var prop, _i, _len, _ref2; + _ref2 = this.properties; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + prop = _ref2[_i]; + if (prop.assigns(name)) return true; + } + return false; + }; + + return Obj; + + })(Base); + + exports.Arr = Arr = (function(_super) { + + __extends(Arr, _super); + + Arr.name = 'Arr'; + + function Arr(objs) { + this.objects = objs || []; + } + + Arr.prototype.children = ['objects']; + + Arr.prototype.filterImplicitObjects = Call.prototype.filterImplicitObjects; + + Arr.prototype.compileNode = function(o) { + var code, obj, objs; + if (!this.objects.length) return '[]'; + o.indent += TAB; + objs = this.filterImplicitObjects(this.objects); + if (code = Splat.compileSplattedArray(o, objs)) return code; + code = ((function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = objs.length; _i < _len; _i++) { + obj = objs[_i]; + _results.push(obj.compile(o, LEVEL_LIST)); + } + return _results; + })()).join(', '); + if (code.indexOf('\n') >= 0) { + return "[\n" + o.indent + code + "\n" + this.tab + "]"; + } else { + return "[" + code + "]"; + } + }; + + Arr.prototype.assigns = function(name) { + var obj, _i, _len, _ref2; + _ref2 = this.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (obj.assigns(name)) return true; + } + return false; + }; + + return Arr; + + })(Base); + + exports.Class = Class = (function(_super) { + + __extends(Class, _super); + + Class.name = 'Class'; + + function Class(variable, parent, body) { + this.variable = variable; + this.parent = parent; + this.body = body != null ? body : new Block; + this.boundFuncs = []; + this.body.classBody = true; + } + + Class.prototype.children = ['variable', 'parent', 'body']; + + Class.prototype.determineName = function() { + var decl, tail; + if (!this.variable) return null; + decl = (tail = last(this.variable.properties)) ? tail instanceof Access && tail.name.value : this.variable.base.value; + if (__indexOf.call(STRICT_PROSCRIBED, decl) >= 0) { + throw SyntaxError("variable name may not be " + decl); + } + return decl && (decl = IDENTIFIER.test(decl) && decl); + }; + + Class.prototype.setContext = function(name) { + return this.body.traverseChildren(false, function(node) { + if (node.classBody) return false; + if (node instanceof Literal && node.value === 'this') { + return node.value = name; + } else if (node instanceof Code) { + node.klass = name; + if (node.bound) return node.context = name; + } + }); + }; + + Class.prototype.addBoundFunctions = function(o) { + var bvar, lhs, _i, _len, _ref2, _results; + if (this.boundFuncs.length) { + _ref2 = this.boundFuncs; + _results = []; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + bvar = _ref2[_i]; + lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o); + _results.push(this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)"))); + } + return _results; + } + }; + + Class.prototype.addProperties = function(node, name, o) { + var assign, base, exprs, func, props; + props = node.base.properties.slice(0); + exprs = (function() { + var _results; + _results = []; + while (assign = props.shift()) { + if (assign instanceof Assign) { + base = assign.variable.base; + delete assign.context; + func = assign.value; + if (base.value === 'constructor') { + if (this.ctor) { + throw new Error('cannot define more than one constructor in a class'); + } + if (func.bound) { + throw new Error('cannot define a constructor as a bound function'); + } + if (func instanceof Code) { + assign = this.ctor = func; + } else { + this.externalCtor = o.scope.freeVariable('class'); + assign = new Assign(new Literal(this.externalCtor), func); + } + } else { + if (assign.variable["this"]) { + func["static"] = true; + if (func.bound) func.context = name; + } else { + assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]); + if (func instanceof Code && func.bound) { + this.boundFuncs.push(base); + func.bound = false; + } + } + } + } + _results.push(assign); + } + return _results; + }).call(this); + return compact(exprs); + }; + + Class.prototype.walkBody = function(name, o) { + var _this = this; + return this.traverseChildren(false, function(child) { + var exps, i, node, _i, _len, _ref2; + if (child instanceof Class) return false; + if (child instanceof Block) { + _ref2 = exps = child.expressions; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + node = _ref2[i]; + if (node instanceof Value && node.isObject(true)) { + exps[i] = _this.addProperties(node, name, o); + } + } + return child.expressions = exps = flatten(exps); + } + }); + }; + + Class.prototype.hoistDirectivePrologue = function() { + var expressions, index, node; + index = 0; + expressions = this.body.expressions; + while ((node = expressions[index]) && node instanceof Comment || node instanceof Value && node.isString()) { + ++index; + } + return this.directives = expressions.splice(0, index); + }; + + Class.prototype.ensureConstructor = function(name) { + if (!this.ctor) { + this.ctor = new Code; + if (this.parent) { + this.ctor.body.push(new Literal("" + name + ".__super__.constructor.apply(this, arguments)")); + } + if (this.externalCtor) { + this.ctor.body.push(new Literal("" + this.externalCtor + ".apply(this, arguments)")); + } + this.ctor.body.makeReturn(); + this.body.expressions.unshift(this.ctor); + } + this.ctor.ctor = this.ctor.name = name; + this.ctor.klass = null; + return this.ctor.noReturn = true; + }; + + Class.prototype.compileNode = function(o) { + var call, decl, klass, lname, name, params, _ref2; + decl = this.determineName(); + name = decl || '_Class'; + if (name.reserved) name = "_" + name; + lname = new Literal(name); + this.hoistDirectivePrologue(); + this.setContext(name); + this.walkBody(name, o); + this.ensureConstructor(name); + this.body.spaced = true; + if (!(this.ctor instanceof Code)) this.body.expressions.unshift(this.ctor); + if (decl) { + this.body.expressions.unshift(new Assign(new Value(new Literal(name), [new Access(new Literal('name'))]), new Literal("'" + name + "'"))); + } + this.body.expressions.push(lname); + (_ref2 = this.body.expressions).unshift.apply(_ref2, this.directives); + this.addBoundFunctions(o); + call = Closure.wrap(this.body); + if (this.parent) { + this.superClass = new Literal(o.scope.freeVariable('super', false)); + this.body.expressions.unshift(new Extends(lname, this.superClass)); + call.args.push(this.parent); + params = call.variable.params || call.variable.base.params; + params.push(new Param(this.superClass)); + } + klass = new Parens(call, true); + if (this.variable) klass = new Assign(this.variable, klass); + return klass.compile(o); + }; + + return Class; + + })(Base); + + exports.Assign = Assign = (function(_super) { + + __extends(Assign, _super); + + Assign.name = 'Assign'; + + function Assign(variable, value, context, options) { + var forbidden, name, _ref2; + this.variable = variable; + this.value = value; + this.context = context; + this.param = options && options.param; + this.subpattern = options && options.subpattern; + forbidden = (_ref2 = (name = this.variable.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0); + if (forbidden && this.context !== 'object') { + throw SyntaxError("variable name may not be \"" + name + "\""); + } + } + + Assign.prototype.children = ['variable', 'value']; + + Assign.prototype.isStatement = function(o) { + return (o != null ? o.level : void 0) === LEVEL_TOP && (this.context != null) && __indexOf.call(this.context, "?") >= 0; + }; + + Assign.prototype.assigns = function(name) { + return this[this.context === 'object' ? 'value' : 'variable'].assigns(name); + }; + + Assign.prototype.unfoldSoak = function(o) { + return unfoldSoak(o, this, 'variable'); + }; + + Assign.prototype.compileNode = function(o) { + var isValue, match, name, val, varBase, _ref2, _ref3, _ref4, _ref5; + if (isValue = this.variable instanceof Value) { + if (this.variable.isArray() || this.variable.isObject()) { + return this.compilePatternMatch(o); + } + if (this.variable.isSplice()) return this.compileSplice(o); + if ((_ref2 = this.context) === '||=' || _ref2 === '&&=' || _ref2 === '?=') { + return this.compileConditional(o); + } + } + name = this.variable.compile(o, LEVEL_LIST); + if (!this.context) { + if (!(varBase = this.variable.unwrapAll()).isAssignable()) { + throw SyntaxError("\"" + (this.variable.compile(o)) + "\" cannot be assigned."); + } + if (!(typeof varBase.hasProperties === "function" ? varBase.hasProperties() : void 0)) { + if (this.param) { + o.scope.add(name, 'var'); + } else { + o.scope.find(name); + } + } + } + if (this.value instanceof Code && (match = METHOD_DEF.exec(name))) { + if (match[1]) this.value.klass = match[1]; + this.value.name = (_ref3 = (_ref4 = (_ref5 = match[2]) != null ? _ref5 : match[3]) != null ? _ref4 : match[4]) != null ? _ref3 : match[5]; + } + val = this.value.compile(o, LEVEL_LIST); + if (this.context === 'object') return "" + name + ": " + val; + val = name + (" " + (this.context || '=') + " ") + val; + if (o.level <= LEVEL_LIST) { + return val; + } else { + return "(" + val + ")"; + } + }; + + Assign.prototype.compilePatternMatch = function(o) { + var acc, assigns, code, i, idx, isObject, ivar, name, obj, objects, olen, ref, rest, splat, top, val, value, vvar, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8; + top = o.level === LEVEL_TOP; + value = this.value; + objects = this.variable.base.objects; + if (!(olen = objects.length)) { + code = value.compile(o); + if (o.level >= LEVEL_OP) { + return "(" + code + ")"; + } else { + return code; + } + } + isObject = this.variable.isObject(); + if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) { + if (obj instanceof Assign) { + _ref2 = obj, (_ref3 = _ref2.variable, idx = _ref3.base), obj = _ref2.value; + } else { + if (obj.base instanceof Parens) { + _ref4 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref4[0], idx = _ref4[1]; + } else { + idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0); + } + } + acc = IDENTIFIER.test(idx.unwrap().value || 0); + value = new Value(value); + value.properties.push(new (acc ? Access : Index)(idx)); + if (_ref5 = obj.unwrap().value, __indexOf.call(RESERVED, _ref5) >= 0) { + throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (value.compile(o))); + } + return new Assign(obj, value, null, { + param: this.param + }).compile(o, LEVEL_TOP); + } + vvar = value.compile(o, LEVEL_LIST); + assigns = []; + splat = false; + if (!IDENTIFIER.test(vvar) || this.variable.assigns(vvar)) { + assigns.push("" + (ref = o.scope.freeVariable('ref')) + " = " + vvar); + vvar = ref; + } + for (i = _i = 0, _len = objects.length; _i < _len; i = ++_i) { + obj = objects[i]; + idx = i; + if (isObject) { + if (obj instanceof Assign) { + _ref6 = obj, (_ref7 = _ref6.variable, idx = _ref7.base), obj = _ref6.value; + } else { + if (obj.base instanceof Parens) { + _ref8 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref8[0], idx = _ref8[1]; + } else { + idx = obj["this"] ? obj.properties[0].name : obj; + } + } + } + if (!splat && obj instanceof Splat) { + name = obj.name.unwrap().value; + obj = obj.unwrap(); + val = "" + olen + " <= " + vvar + ".length ? " + (utility('slice')) + ".call(" + vvar + ", " + i; + if (rest = olen - i - 1) { + ivar = o.scope.freeVariable('i'); + val += ", " + ivar + " = " + vvar + ".length - " + rest + ") : (" + ivar + " = " + i + ", [])"; + } else { + val += ") : []"; + } + val = new Literal(val); + splat = "" + ivar + "++"; + } else { + name = obj.unwrap().value; + if (obj instanceof Splat) { + obj = obj.name.compile(o); + throw new SyntaxError("multiple splats are disallowed in an assignment: " + obj + "..."); + } + if (typeof idx === 'number') { + idx = new Literal(splat || idx); + acc = false; + } else { + acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0); + } + val = new Value(new Literal(vvar), [new (acc ? Access : Index)(idx)]); + } + if ((name != null) && __indexOf.call(RESERVED, name) >= 0) { + throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (val.compile(o))); + } + assigns.push(new Assign(obj, val, null, { + param: this.param, + subpattern: true + }).compile(o, LEVEL_LIST)); + } + if (!(top || this.subpattern)) assigns.push(vvar); + code = assigns.join(', '); + if (o.level < LEVEL_LIST) { + return code; + } else { + return "(" + code + ")"; + } + }; + + Assign.prototype.compileConditional = function(o) { + var left, right, _ref2; + _ref2 = this.variable.cacheReference(o), left = _ref2[0], right = _ref2[1]; + if (left.base instanceof Literal && left.base.value !== "this" && !o.scope.check(left.base.value)) { + throw new Error("the variable \"" + left.base.value + "\" can't be assigned with " + this.context + " because it has not been defined."); + } + if (__indexOf.call(this.context, "?") >= 0) o.isExistentialEquals = true; + return new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compile(o); + }; + + Assign.prototype.compileSplice = function(o) { + var code, exclusive, from, fromDecl, fromRef, name, to, valDef, valRef, _ref2, _ref3, _ref4; + _ref2 = this.variable.properties.pop().range, from = _ref2.from, to = _ref2.to, exclusive = _ref2.exclusive; + name = this.variable.compile(o); + _ref3 = (from != null ? from.cache(o, LEVEL_OP) : void 0) || ['0', '0'], fromDecl = _ref3[0], fromRef = _ref3[1]; + if (to) { + if ((from != null ? from.isSimpleNumber() : void 0) && to.isSimpleNumber()) { + to = +to.compile(o) - +fromRef; + if (!exclusive) to += 1; + } else { + to = to.compile(o, LEVEL_ACCESS) + ' - ' + fromRef; + if (!exclusive) to += ' + 1'; + } + } else { + to = "9e9"; + } + _ref4 = this.value.cache(o, LEVEL_LIST), valDef = _ref4[0], valRef = _ref4[1]; + code = "[].splice.apply(" + name + ", [" + fromDecl + ", " + to + "].concat(" + valDef + ")), " + valRef; + if (o.level > LEVEL_TOP) { + return "(" + code + ")"; + } else { + return code; + } + }; + + return Assign; + + })(Base); + + exports.Code = Code = (function(_super) { + + __extends(Code, _super); + + Code.name = 'Code'; + + function Code(params, body, tag) { + this.params = params || []; + this.body = body || new Block; + this.bound = tag === 'boundfunc'; + if (this.bound) this.context = '_this'; + } + + Code.prototype.children = ['params', 'body']; + + Code.prototype.isStatement = function() { + return !!this.ctor; + }; + + Code.prototype.jumps = NO; + + Code.prototype.compileNode = function(o) { + var code, exprs, i, idt, lit, name, p, param, params, ref, splats, uniqs, val, wasEmpty, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8; + o.scope = new Scope(o.scope, this.body, this); + o.scope.shared = del(o, 'sharedScope'); + o.indent += TAB; + delete o.bare; + delete o.isExistentialEquals; + params = []; + exprs = []; + _ref2 = this.paramNames(); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + name = _ref2[_i]; + if (!o.scope.check(name)) o.scope.parameter(name); + } + _ref3 = this.params; + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + param = _ref3[_j]; + if (!param.splat) continue; + _ref4 = this.params; + for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) { + p = _ref4[_k]; + if (p.name.value) o.scope.add(p.name.value, 'var', true); + } + splats = new Assign(new Value(new Arr((function() { + var _l, _len3, _ref5, _results; + _ref5 = this.params; + _results = []; + for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) { + p = _ref5[_l]; + _results.push(p.asReference(o)); + } + return _results; + }).call(this))), new Value(new Literal('arguments'))); + break; + } + _ref5 = this.params; + for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) { + param = _ref5[_l]; + if (param.isComplex()) { + val = ref = param.asReference(o); + if (param.value) val = new Op('?', ref, param.value); + exprs.push(new Assign(new Value(param.name), val, '=', { + param: true + })); + } else { + ref = param; + if (param.value) { + lit = new Literal(ref.name.value + ' == null'); + val = new Assign(new Value(param.name), param.value, '='); + exprs.push(new If(lit, val)); + } + } + if (!splats) params.push(ref); + } + wasEmpty = this.body.isEmpty(); + if (splats) exprs.unshift(splats); + if (exprs.length) { + (_ref6 = this.body.expressions).unshift.apply(_ref6, exprs); + } + for (i = _m = 0, _len4 = params.length; _m < _len4; i = ++_m) { + p = params[i]; + o.scope.parameter(params[i] = p.compile(o)); + } + uniqs = []; + _ref7 = this.paramNames(); + for (_n = 0, _len5 = _ref7.length; _n < _len5; _n++) { + name = _ref7[_n]; + if (__indexOf.call(uniqs, name) >= 0) { + throw SyntaxError("multiple parameters named '" + name + "'"); + } + uniqs.push(name); + } + if (!(wasEmpty || this.noReturn)) this.body.makeReturn(); + if (this.bound) { + if ((_ref8 = o.scope.parent.method) != null ? _ref8.bound : void 0) { + this.bound = this.context = o.scope.parent.method.context; + } else if (!this["static"]) { + o.scope.parent.assign('_this', 'this'); + } + } + idt = o.indent; + code = 'function'; + if (this.ctor) code += ' ' + this.name; + code += '(' + params.join(', ') + ') {'; + if (!this.body.isEmpty()) { + code += "\n" + (this.body.compileWithDeclarations(o)) + "\n" + this.tab; + } + code += '}'; + if (this.ctor) return this.tab + code; + if (this.front || (o.level >= LEVEL_ACCESS)) { + return "(" + code + ")"; + } else { + return code; + } + }; + + Code.prototype.paramNames = function() { + var names, param, _i, _len, _ref2; + names = []; + _ref2 = this.params; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + param = _ref2[_i]; + names.push.apply(names, param.names()); + } + return names; + }; + + Code.prototype.traverseChildren = function(crossScope, func) { + if (crossScope) { + return Code.__super__.traverseChildren.call(this, crossScope, func); + } + }; + + return Code; + + })(Base); + + exports.Param = Param = (function(_super) { + + __extends(Param, _super); + + Param.name = 'Param'; + + function Param(name, value, splat) { + var _ref2; + this.name = name; + this.value = value; + this.splat = splat; + if (_ref2 = (name = this.name.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) { + throw SyntaxError("parameter name \"" + name + "\" is not allowed"); + } + } + + Param.prototype.children = ['name', 'value']; + + Param.prototype.compile = function(o) { + return this.name.compile(o, LEVEL_LIST); + }; + + Param.prototype.asReference = function(o) { + var node; + if (this.reference) return this.reference; + node = this.name; + if (node["this"]) { + node = node.properties[0].name; + if (node.value.reserved) { + node = new Literal(o.scope.freeVariable(node.value)); + } + } else if (node.isComplex()) { + node = new Literal(o.scope.freeVariable('arg')); + } + node = new Value(node); + if (this.splat) node = new Splat(node); + return this.reference = node; + }; + + Param.prototype.isComplex = function() { + return this.name.isComplex(); + }; + + Param.prototype.names = function(name) { + var atParam, names, obj, _i, _len, _ref2; + if (name == null) name = this.name; + atParam = function(obj) { + var value; + value = obj.properties[0].name.value; + if (value.reserved) { + return []; + } else { + return [value]; + } + }; + if (name instanceof Literal) return [name.value]; + if (name instanceof Value) return atParam(name); + names = []; + _ref2 = name.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (obj instanceof Assign) { + names.push(obj.variable.base.value); + } else if (obj.isArray() || obj.isObject()) { + names.push.apply(names, this.names(obj.base)); + } else if (obj["this"]) { + names.push.apply(names, atParam(obj)); + } else { + names.push(obj.base.value); + } + } + return names; + }; + + return Param; + + })(Base); + + exports.Splat = Splat = (function(_super) { + + __extends(Splat, _super); + + Splat.name = 'Splat'; + + Splat.prototype.children = ['name']; + + Splat.prototype.isAssignable = YES; + + function Splat(name) { + this.name = name.compile ? name : new Literal(name); + } + + Splat.prototype.assigns = function(name) { + return this.name.assigns(name); + }; + + Splat.prototype.compile = function(o) { + if (this.index != null) { + return this.compileParam(o); + } else { + return this.name.compile(o); + } + }; + + Splat.prototype.unwrap = function() { + return this.name; + }; + + Splat.compileSplattedArray = function(o, list, apply) { + var args, base, code, i, index, node, _i, _len; + index = -1; + while ((node = list[++index]) && !(node instanceof Splat)) { + continue; + } + if (index >= list.length) return ''; + if (list.length === 1) { + code = list[0].compile(o, LEVEL_LIST); + if (apply) return code; + return "" + (utility('slice')) + ".call(" + code + ")"; + } + args = list.slice(index); + for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) { + node = args[i]; + code = node.compile(o, LEVEL_LIST); + args[i] = node instanceof Splat ? "" + (utility('slice')) + ".call(" + code + ")" : "[" + code + "]"; + } + if (index === 0) { + return args[0] + (".concat(" + (args.slice(1).join(', ')) + ")"); + } + base = (function() { + var _j, _len1, _ref2, _results; + _ref2 = list.slice(0, index); + _results = []; + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + node = _ref2[_j]; + _results.push(node.compile(o, LEVEL_LIST)); + } + return _results; + })(); + return "[" + (base.join(', ')) + "].concat(" + (args.join(', ')) + ")"; + }; + + return Splat; + + })(Base); + + exports.While = While = (function(_super) { + + __extends(While, _super); + + While.name = 'While'; + + function While(condition, options) { + this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition; + this.guard = options != null ? options.guard : void 0; + } + + While.prototype.children = ['condition', 'guard', 'body']; + + While.prototype.isStatement = YES; + + While.prototype.makeReturn = function(res) { + if (res) { + return While.__super__.makeReturn.apply(this, arguments); + } else { + this.returns = !this.jumps({ + loop: true + }); + return this; + } + }; + + While.prototype.addBody = function(body) { + this.body = body; + return this; + }; + + While.prototype.jumps = function() { + var expressions, node, _i, _len; + expressions = this.body.expressions; + if (!expressions.length) return false; + for (_i = 0, _len = expressions.length; _i < _len; _i++) { + node = expressions[_i]; + if (node.jumps({ + loop: true + })) return node; + } + return false; + }; + + While.prototype.compileNode = function(o) { + var body, code, rvar, set; + o.indent += TAB; + set = ''; + body = this.body; + if (body.isEmpty()) { + body = ''; + } else { + if (this.returns) { + body.makeReturn(rvar = o.scope.freeVariable('results')); + set = "" + this.tab + rvar + " = [];\n"; + } + if (this.guard) { + if (body.expressions.length > 1) { + body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue"))); + } else { + if (this.guard) body = Block.wrap([new If(this.guard, body)]); + } + } + body = "\n" + (body.compile(o, LEVEL_TOP)) + "\n" + this.tab; + } + code = set + this.tab + ("while (" + (this.condition.compile(o, LEVEL_PAREN)) + ") {" + body + "}"); + if (this.returns) code += "\n" + this.tab + "return " + rvar + ";"; + return code; + }; + + return While; + + })(Base); + + exports.Op = Op = (function(_super) { + var CONVERSIONS, INVERSIONS; + + __extends(Op, _super); + + Op.name = 'Op'; + + function Op(op, first, second, flip) { + if (op === 'in') return new In(first, second); + if (op === 'do') return this.generateDo(first); + if (op === 'new') { + if (first instanceof Call && !first["do"] && !first.isNew) { + return first.newInstance(); + } + if (first instanceof Code && first.bound || first["do"]) { + first = new Parens(first); + } + } + this.operator = CONVERSIONS[op] || op; + this.first = first; + this.second = second; + this.flip = !!flip; + return this; + } + + CONVERSIONS = { + '==': '===', + '!=': '!==', + 'of': 'in' + }; + + INVERSIONS = { + '!==': '===', + '===': '!==' + }; + + Op.prototype.children = ['first', 'second']; + + Op.prototype.isSimpleNumber = NO; + + Op.prototype.isUnary = function() { + return !this.second; + }; + + Op.prototype.isComplex = function() { + var _ref2; + return !(this.isUnary() && ((_ref2 = this.operator) === '+' || _ref2 === '-')) || this.first.isComplex(); + }; + + Op.prototype.isChainable = function() { + var _ref2; + return (_ref2 = this.operator) === '<' || _ref2 === '>' || _ref2 === '>=' || _ref2 === '<=' || _ref2 === '===' || _ref2 === '!=='; + }; + + Op.prototype.invert = function() { + var allInvertable, curr, fst, op, _ref2; + if (this.isChainable() && this.first.isChainable()) { + allInvertable = true; + curr = this; + while (curr && curr.operator) { + allInvertable && (allInvertable = curr.operator in INVERSIONS); + curr = curr.first; + } + if (!allInvertable) return new Parens(this).invert(); + curr = this; + while (curr && curr.operator) { + curr.invert = !curr.invert; + curr.operator = INVERSIONS[curr.operator]; + curr = curr.first; + } + return this; + } else if (op = INVERSIONS[this.operator]) { + this.operator = op; + if (this.first.unwrap() instanceof Op) this.first.invert(); + return this; + } else if (this.second) { + return new Parens(this).invert(); + } else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref2 = fst.operator) === '!' || _ref2 === 'in' || _ref2 === 'instanceof')) { + return fst; + } else { + return new Op('!', this); + } + }; + + Op.prototype.unfoldSoak = function(o) { + var _ref2; + return ((_ref2 = this.operator) === '++' || _ref2 === '--' || _ref2 === 'delete') && unfoldSoak(o, this, 'first'); + }; + + Op.prototype.generateDo = function(exp) { + var call, func, param, passedParams, ref, _i, _len, _ref2; + passedParams = []; + func = exp instanceof Assign && (ref = exp.value.unwrap()) instanceof Code ? ref : exp; + _ref2 = func.params || []; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + param = _ref2[_i]; + if (param.value) { + passedParams.push(param.value); + delete param.value; + } else { + passedParams.push(param); + } + } + call = new Call(exp, passedParams); + call["do"] = true; + return call; + }; + + Op.prototype.compileNode = function(o) { + var code, isChain, _ref2, _ref3; + isChain = this.isChainable() && this.first.isChainable(); + if (!isChain) this.first.front = this.front; + if (this.operator === 'delete' && o.scope.check(this.first.unwrapAll().value)) { + throw SyntaxError('delete operand may not be argument or var'); + } + if (((_ref2 = this.operator) === '--' || _ref2 === '++') && (_ref3 = this.first.unwrapAll().value, __indexOf.call(STRICT_PROSCRIBED, _ref3) >= 0)) { + throw SyntaxError('prefix increment/decrement may not have eval or arguments operand'); + } + if (this.isUnary()) return this.compileUnary(o); + if (isChain) return this.compileChain(o); + if (this.operator === '?') return this.compileExistence(o); + code = this.first.compile(o, LEVEL_OP) + ' ' + this.operator + ' ' + this.second.compile(o, LEVEL_OP); + if (o.level <= LEVEL_OP) { + return code; + } else { + return "(" + code + ")"; + } + }; + + Op.prototype.compileChain = function(o) { + var code, fst, shared, _ref2; + _ref2 = this.first.second.cache(o), this.first.second = _ref2[0], shared = _ref2[1]; + fst = this.first.compile(o, LEVEL_OP); + code = "" + fst + " " + (this.invert ? '&&' : '||') + " " + (shared.compile(o)) + " " + this.operator + " " + (this.second.compile(o, LEVEL_OP)); + return "(" + code + ")"; + }; + + Op.prototype.compileExistence = function(o) { + var fst, ref; + if (this.first.isComplex() && o.level > LEVEL_TOP) { + ref = new Literal(o.scope.freeVariable('ref')); + fst = new Parens(new Assign(ref, this.first)); + } else { + fst = this.first; + ref = fst; + } + return new If(new Existence(fst), ref, { + type: 'if' + }).addElse(this.second).compile(o); + }; + + Op.prototype.compileUnary = function(o) { + var op, parts, plusMinus; + if (o.level >= LEVEL_ACCESS) return (new Parens(this)).compile(o); + parts = [op = this.operator]; + plusMinus = op === '+' || op === '-'; + if ((op === 'new' || op === 'typeof' || op === 'delete') || plusMinus && this.first instanceof Op && this.first.operator === op) { + parts.push(' '); + } + if ((plusMinus && this.first instanceof Op) || (op === 'new' && this.first.isStatement(o))) { + this.first = new Parens(this.first); + } + parts.push(this.first.compile(o, LEVEL_OP)); + if (this.flip) parts.reverse(); + return parts.join(''); + }; + + Op.prototype.toString = function(idt) { + return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator); + }; + + return Op; + + })(Base); + + exports.In = In = (function(_super) { + + __extends(In, _super); + + In.name = 'In'; + + function In(object, array) { + this.object = object; + this.array = array; + } + + In.prototype.children = ['object', 'array']; + + In.prototype.invert = NEGATE; + + In.prototype.compileNode = function(o) { + var hasSplat, obj, _i, _len, _ref2; + if (this.array instanceof Value && this.array.isArray()) { + _ref2 = this.array.base.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (!(obj instanceof Splat)) continue; + hasSplat = true; + break; + } + if (!hasSplat) return this.compileOrTest(o); + } + return this.compileLoopTest(o); + }; + + In.prototype.compileOrTest = function(o) { + var cmp, cnj, i, item, ref, sub, tests, _ref2, _ref3; + if (this.array.base.objects.length === 0) return "" + (!!this.negated); + _ref2 = this.object.cache(o, LEVEL_OP), sub = _ref2[0], ref = _ref2[1]; + _ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1]; + tests = (function() { + var _i, _len, _ref4, _results; + _ref4 = this.array.base.objects; + _results = []; + for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) { + item = _ref4[i]; + _results.push((i ? ref : sub) + cmp + item.compile(o, LEVEL_ACCESS)); + } + return _results; + }).call(this); + tests = tests.join(cnj); + if (o.level < LEVEL_OP) { + return tests; + } else { + return "(" + tests + ")"; + } + }; + + In.prototype.compileLoopTest = function(o) { + var code, ref, sub, _ref2; + _ref2 = this.object.cache(o, LEVEL_LIST), sub = _ref2[0], ref = _ref2[1]; + code = utility('indexOf') + (".call(" + (this.array.compile(o, LEVEL_LIST)) + ", " + ref + ") ") + (this.negated ? '< 0' : '>= 0'); + if (sub === ref) return code; + code = sub + ', ' + code; + if (o.level < LEVEL_LIST) { + return code; + } else { + return "(" + code + ")"; + } + }; + + In.prototype.toString = function(idt) { + return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : '')); + }; + + return In; + + })(Base); + + exports.Try = Try = (function(_super) { + + __extends(Try, _super); + + Try.name = 'Try'; + + function Try(attempt, error, recovery, ensure) { + this.attempt = attempt; + this.error = error; + this.recovery = recovery; + this.ensure = ensure; + } + + Try.prototype.children = ['attempt', 'recovery', 'ensure']; + + Try.prototype.isStatement = YES; + + Try.prototype.jumps = function(o) { + var _ref2; + return this.attempt.jumps(o) || ((_ref2 = this.recovery) != null ? _ref2.jumps(o) : void 0); + }; + + Try.prototype.makeReturn = function(res) { + if (this.attempt) this.attempt = this.attempt.makeReturn(res); + if (this.recovery) this.recovery = this.recovery.makeReturn(res); + return this; + }; + + Try.prototype.compileNode = function(o) { + var catchPart, ensurePart, errorPart, tryPart; + o.indent += TAB; + errorPart = this.error ? " (" + (this.error.compile(o)) + ") " : ' '; + tryPart = this.attempt.compile(o, LEVEL_TOP); + catchPart = (function() { + var _ref2; + if (this.recovery) { + if (_ref2 = this.error.value, __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) { + throw SyntaxError("catch variable may not be \"" + this.error.value + "\""); + } + if (!o.scope.check(this.error.value)) { + o.scope.add(this.error.value, 'param'); + } + return " catch" + errorPart + "{\n" + (this.recovery.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}"; + } else if (!(this.ensure || this.recovery)) { + return ' catch (_error) {}'; + } + }).call(this); + ensurePart = this.ensure ? " finally {\n" + (this.ensure.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}" : ''; + return "" + this.tab + "try {\n" + tryPart + "\n" + this.tab + "}" + (catchPart || '') + ensurePart; + }; + + return Try; + + })(Base); + + exports.Throw = Throw = (function(_super) { + + __extends(Throw, _super); + + Throw.name = 'Throw'; + + function Throw(expression) { + this.expression = expression; + } + + Throw.prototype.children = ['expression']; + + Throw.prototype.isStatement = YES; + + Throw.prototype.jumps = NO; + + Throw.prototype.makeReturn = THIS; + + Throw.prototype.compileNode = function(o) { + return this.tab + ("throw " + (this.expression.compile(o)) + ";"); + }; + + return Throw; + + })(Base); + + exports.Existence = Existence = (function(_super) { + + __extends(Existence, _super); + + Existence.name = 'Existence'; + + function Existence(expression) { + this.expression = expression; + } + + Existence.prototype.children = ['expression']; + + Existence.prototype.invert = NEGATE; + + Existence.prototype.compileNode = function(o) { + var cmp, cnj, code, _ref2; + this.expression.front = this.front; + code = this.expression.compile(o, LEVEL_OP); + if (IDENTIFIER.test(code) && !o.scope.check(code)) { + _ref2 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref2[0], cnj = _ref2[1]; + code = "typeof " + code + " " + cmp + " \"undefined\" " + cnj + " " + code + " " + cmp + " null"; + } else { + code = "" + code + " " + (this.negated ? '==' : '!=') + " null"; + } + if (o.level <= LEVEL_COND) { + return code; + } else { + return "(" + code + ")"; + } + }; + + return Existence; + + })(Base); + + exports.Parens = Parens = (function(_super) { + + __extends(Parens, _super); + + Parens.name = 'Parens'; + + function Parens(body) { + this.body = body; + } + + Parens.prototype.children = ['body']; + + Parens.prototype.unwrap = function() { + return this.body; + }; + + Parens.prototype.isComplex = function() { + return this.body.isComplex(); + }; + + Parens.prototype.compileNode = function(o) { + var bare, code, expr; + expr = this.body.unwrap(); + if (expr instanceof Value && expr.isAtomic()) { + expr.front = this.front; + return expr.compile(o); + } + code = expr.compile(o, LEVEL_PAREN); + bare = o.level < LEVEL_OP && (expr instanceof Op || expr instanceof Call || (expr instanceof For && expr.returns)); + if (bare) { + return code; + } else { + return "(" + code + ")"; + } + }; + + return Parens; + + })(Base); + + exports.For = For = (function(_super) { + + __extends(For, _super); + + For.name = 'For'; + + function For(body, source) { + var _ref2; + this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index; + this.body = Block.wrap([body]); + this.own = !!source.own; + this.object = !!source.object; + if (this.object) { + _ref2 = [this.index, this.name], this.name = _ref2[0], this.index = _ref2[1]; + } + if (this.index instanceof Value) { + throw SyntaxError('index cannot be a pattern matching expression'); + } + this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length; + this.pattern = this.name instanceof Value; + if (this.range && this.index) { + throw SyntaxError('indexes do not apply to range loops'); + } + if (this.range && this.pattern) { + throw SyntaxError('cannot pattern match over range loops'); + } + this.returns = false; + } + + For.prototype.children = ['body', 'source', 'guard', 'step']; + + For.prototype.compileNode = function(o) { + var body, defPart, forPart, forVarPart, guardPart, idt1, index, ivar, kvar, kvarAssign, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, stepPart, stepvar, svar, varPart, _ref2; + body = Block.wrap([this.body]); + lastJumps = (_ref2 = last(body.expressions)) != null ? _ref2.jumps() : void 0; + if (lastJumps && lastJumps instanceof Return) this.returns = false; + source = this.range ? this.source.base : this.source; + scope = o.scope; + name = this.name && this.name.compile(o, LEVEL_LIST); + index = this.index && this.index.compile(o, LEVEL_LIST); + if (name && !this.pattern) { + scope.find(name, { + immediate: true + }); + } + if (index) { + scope.find(index, { + immediate: true + }); + } + if (this.returns) rvar = scope.freeVariable('results'); + ivar = (this.object && index) || scope.freeVariable('i'); + kvar = (this.range && name) || index || ivar; + kvarAssign = kvar !== ivar ? "" + kvar + " = " : ""; + if (this.step && !this.range) stepvar = scope.freeVariable("step"); + if (this.pattern) name = ivar; + varPart = ''; + guardPart = ''; + defPart = ''; + idt1 = this.tab + TAB; + if (this.range) { + forPart = source.compile(merge(o, { + index: ivar, + name: name, + step: this.step + })); + } else { + svar = this.source.compile(o, LEVEL_LIST); + if ((name || this.own) && !IDENTIFIER.test(svar)) { + defPart = "" + this.tab + (ref = scope.freeVariable('ref')) + " = " + svar + ";\n"; + svar = ref; + } + if (name && !this.pattern) { + namePart = "" + name + " = " + svar + "[" + kvar + "]"; + } + if (!this.object) { + lvar = scope.freeVariable('len'); + forVarPart = "" + kvarAssign + ivar + " = 0, " + lvar + " = " + svar + ".length"; + if (this.step) { + forVarPart += ", " + stepvar + " = " + (this.step.compile(o, LEVEL_OP)); + } + stepPart = "" + kvarAssign + (this.step ? "" + ivar + " += " + stepvar : (kvar !== ivar ? "++" + ivar : "" + ivar + "++")); + forPart = "" + forVarPart + "; " + ivar + " < " + lvar + "; " + stepPart; + } + } + if (this.returns) { + resultPart = "" + this.tab + rvar + " = [];\n"; + returnResult = "\n" + this.tab + "return " + rvar + ";"; + body.makeReturn(rvar); + } + if (this.guard) { + if (body.expressions.length > 1) { + body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue"))); + } else { + if (this.guard) body = Block.wrap([new If(this.guard, body)]); + } + } + if (this.pattern) { + body.expressions.unshift(new Assign(this.name, new Literal("" + svar + "[" + kvar + "]"))); + } + defPart += this.pluckDirectCall(o, body); + if (namePart) varPart = "\n" + idt1 + namePart + ";"; + if (this.object) { + forPart = "" + kvar + " in " + svar; + if (this.own) { + guardPart = "\n" + idt1 + "if (!" + (utility('hasProp')) + ".call(" + svar + ", " + kvar + ")) continue;"; + } + } + body = body.compile(merge(o, { + indent: idt1 + }), LEVEL_TOP); + if (body) body = '\n' + body + '\n'; + return "" + defPart + (resultPart || '') + this.tab + "for (" + forPart + ") {" + guardPart + varPart + body + this.tab + "}" + (returnResult || ''); + }; + + For.prototype.pluckDirectCall = function(o, body) { + var base, defs, expr, fn, idx, ref, val, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; + defs = ''; + _ref2 = body.expressions; + for (idx = _i = 0, _len = _ref2.length; _i < _len; idx = ++_i) { + expr = _ref2[idx]; + expr = expr.unwrapAll(); + if (!(expr instanceof Call)) continue; + val = expr.variable.unwrapAll(); + if (!((val instanceof Code) || (val instanceof Value && ((_ref3 = val.base) != null ? _ref3.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((_ref4 = (_ref5 = val.properties[0].name) != null ? _ref5.value : void 0) === 'call' || _ref4 === 'apply')))) { + continue; + } + fn = ((_ref6 = val.base) != null ? _ref6.unwrapAll() : void 0) || val; + ref = new Literal(o.scope.freeVariable('fn')); + base = new Value(ref); + if (val.base) _ref7 = [base, val], val.base = _ref7[0], base = _ref7[1]; + body.expressions[idx] = new Call(base, expr.args); + defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n'; + } + return defs; + }; + + return For; + + })(While); + + exports.Switch = Switch = (function(_super) { + + __extends(Switch, _super); + + Switch.name = 'Switch'; + + function Switch(subject, cases, otherwise) { + this.subject = subject; + this.cases = cases; + this.otherwise = otherwise; + } + + Switch.prototype.children = ['subject', 'cases', 'otherwise']; + + Switch.prototype.isStatement = YES; + + Switch.prototype.jumps = function(o) { + var block, conds, _i, _len, _ref2, _ref3, _ref4; + if (o == null) { + o = { + block: true + }; + } + _ref2 = this.cases; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _ref3 = _ref2[_i], conds = _ref3[0], block = _ref3[1]; + if (block.jumps(o)) return block; + } + return (_ref4 = this.otherwise) != null ? _ref4.jumps(o) : void 0; + }; + + Switch.prototype.makeReturn = function(res) { + var pair, _i, _len, _ref2, _ref3; + _ref2 = this.cases; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + pair = _ref2[_i]; + pair[1].makeReturn(res); + } + if (res) { + this.otherwise || (this.otherwise = new Block([new Literal('void 0')])); + } + if ((_ref3 = this.otherwise) != null) _ref3.makeReturn(res); + return this; + }; + + Switch.prototype.compileNode = function(o) { + var block, body, code, cond, conditions, expr, i, idt1, idt2, _i, _j, _len, _len1, _ref2, _ref3, _ref4, _ref5; + idt1 = o.indent + TAB; + idt2 = o.indent = idt1 + TAB; + code = this.tab + ("switch (" + (((_ref2 = this.subject) != null ? _ref2.compile(o, LEVEL_PAREN) : void 0) || false) + ") {\n"); + _ref3 = this.cases; + for (i = _i = 0, _len = _ref3.length; _i < _len; i = ++_i) { + _ref4 = _ref3[i], conditions = _ref4[0], block = _ref4[1]; + _ref5 = flatten([conditions]); + for (_j = 0, _len1 = _ref5.length; _j < _len1; _j++) { + cond = _ref5[_j]; + if (!this.subject) cond = cond.invert(); + code += idt1 + ("case " + (cond.compile(o, LEVEL_PAREN)) + ":\n"); + } + if (body = block.compile(o, LEVEL_TOP)) code += body + '\n'; + if (i === this.cases.length - 1 && !this.otherwise) break; + expr = this.lastNonComment(block.expressions); + if (expr instanceof Return || (expr instanceof Literal && expr.jumps() && expr.value !== 'debugger')) { + continue; + } + code += idt2 + 'break;\n'; + } + if (this.otherwise && this.otherwise.expressions.length) { + code += idt1 + ("default:\n" + (this.otherwise.compile(o, LEVEL_TOP)) + "\n"); + } + return code + this.tab + '}'; + }; + + return Switch; + + })(Base); + + exports.If = If = (function(_super) { + + __extends(If, _super); + + If.name = 'If'; + + function If(condition, body, options) { + this.body = body; + if (options == null) options = {}; + this.condition = options.type === 'unless' ? condition.invert() : condition; + this.elseBody = null; + this.isChain = false; + this.soak = options.soak; + } + + If.prototype.children = ['condition', 'body', 'elseBody']; + + If.prototype.bodyNode = function() { + var _ref2; + return (_ref2 = this.body) != null ? _ref2.unwrap() : void 0; + }; + + If.prototype.elseBodyNode = function() { + var _ref2; + return (_ref2 = this.elseBody) != null ? _ref2.unwrap() : void 0; + }; + + If.prototype.addElse = function(elseBody) { + if (this.isChain) { + this.elseBodyNode().addElse(elseBody); + } else { + this.isChain = elseBody instanceof If; + this.elseBody = this.ensureBlock(elseBody); + } + return this; + }; + + If.prototype.isStatement = function(o) { + var _ref2; + return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : void 0); + }; + + If.prototype.jumps = function(o) { + var _ref2; + return this.body.jumps(o) || ((_ref2 = this.elseBody) != null ? _ref2.jumps(o) : void 0); + }; + + If.prototype.compileNode = function(o) { + if (this.isStatement(o)) { + return this.compileStatement(o); + } else { + return this.compileExpression(o); + } + }; + + If.prototype.makeReturn = function(res) { + if (res) { + this.elseBody || (this.elseBody = new Block([new Literal('void 0')])); + } + this.body && (this.body = new Block([this.body.makeReturn(res)])); + this.elseBody && (this.elseBody = new Block([this.elseBody.makeReturn(res)])); + return this; + }; + + If.prototype.ensureBlock = function(node) { + if (node instanceof Block) { + return node; + } else { + return new Block([node]); + } + }; + + If.prototype.compileStatement = function(o) { + var body, bodyc, child, cond, exeq, ifPart, _ref2; + child = del(o, 'chainChild'); + exeq = del(o, 'isExistentialEquals'); + if (exeq) { + return new If(this.condition.invert(), this.elseBodyNode(), { + type: 'if' + }).compile(o); + } + cond = this.condition.compile(o, LEVEL_PAREN); + o.indent += TAB; + body = this.ensureBlock(this.body); + bodyc = body.compile(o); + if (1 === ((_ref2 = body.expressions) != null ? _ref2.length : void 0) && !this.elseBody && !child && bodyc && cond && -1 === (bodyc.indexOf('\n')) && 80 > cond.length + bodyc.length) { + return "" + this.tab + "if (" + cond + ") " + (bodyc.replace(/^\s+/, '')); + } + if (bodyc) bodyc = "\n" + bodyc + "\n" + this.tab; + ifPart = "if (" + cond + ") {" + bodyc + "}"; + if (!child) ifPart = this.tab + ifPart; + if (!this.elseBody) return ifPart; + return ifPart + ' else ' + (this.isChain ? (o.indent = this.tab, o.chainChild = true, this.elseBody.unwrap().compile(o, LEVEL_TOP)) : "{\n" + (this.elseBody.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}"); + }; + + If.prototype.compileExpression = function(o) { + var alt, body, code, cond; + cond = this.condition.compile(o, LEVEL_COND); + body = this.bodyNode().compile(o, LEVEL_LIST); + alt = this.elseBodyNode() ? this.elseBodyNode().compile(o, LEVEL_LIST) : 'void 0'; + code = "" + cond + " ? " + body + " : " + alt; + if (o.level >= LEVEL_COND) { + return "(" + code + ")"; + } else { + return code; + } + }; + + If.prototype.unfoldSoak = function() { + return this.soak && this; + }; + + return If; + + })(Base); + + Closure = { + wrap: function(expressions, statement, noReturn) { + var args, call, func, mentionsArgs, meth; + if (expressions.jumps()) return expressions; + func = new Code([], Block.wrap([expressions])); + args = []; + if ((mentionsArgs = expressions.contains(this.literalArgs)) || expressions.contains(this.literalThis)) { + meth = new Literal(mentionsArgs ? 'apply' : 'call'); + args = [new Literal('this')]; + if (mentionsArgs) args.push(new Literal('arguments')); + func = new Value(func, [new Access(meth)]); + } + func.noReturn = noReturn; + call = new Call(func, args); + if (statement) { + return Block.wrap([call]); + } else { + return call; + } + }, + literalArgs: function(node) { + return node instanceof Literal && node.value === 'arguments' && !node.asKey; + }, + literalThis: function(node) { + return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound); + } + }; + + unfoldSoak = function(o, parent, name) { + var ifn; + if (!(ifn = parent[name].unfoldSoak(o))) return; + parent[name] = ifn.body; + ifn.body = new Value(parent); + return ifn; + }; + + UTILITIES = { + "extends": function() { + return "function(child, parent) { for (var key in parent) { if (" + (utility('hasProp')) + ".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }"; + }, + bind: function() { + return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }'; + }, + indexOf: function() { + return "[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"; + }, + hasProp: function() { + return '{}.hasOwnProperty'; + }, + slice: function() { + return '[].slice'; + } + }; + + LEVEL_TOP = 1; + + LEVEL_PAREN = 2; + + LEVEL_LIST = 3; + + LEVEL_COND = 4; + + LEVEL_OP = 5; + + LEVEL_ACCESS = 6; + + TAB = ' '; + + IDENTIFIER_STR = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*"; + + IDENTIFIER = RegExp("^" + IDENTIFIER_STR + "$"); + + SIMPLENUM = /^[+-]?\d+$/; + + METHOD_DEF = RegExp("^(?:(" + IDENTIFIER_STR + ")\\.prototype(?:\\.(" + IDENTIFIER_STR + ")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|(" + IDENTIFIER_STR + ")$"); + + IS_STRING = /^['"]/; + + utility = function(name) { + var ref; + ref = "__" + name; + Scope.root.assign(ref, UTILITIES[name]()); + return ref; + }; + + multident = function(code, tab) { + code = code.replace(/\n/g, '$&' + tab); + return code.replace(/\s+$/, ''); + }; + + +}); + +define('ace/mode/coffee/scope', ['require', 'exports', 'module' , 'ace/mode/coffee/helpers'], function(require, exports, module) { +// Generated by CoffeeScript 1.2.1-pre + + var Scope, extend, last, _ref; + + _ref = require('./helpers'), extend = _ref.extend, last = _ref.last; + + exports.Scope = Scope = (function() { + + Scope.name = 'Scope'; + + Scope.root = null; + + function Scope(parent, expressions, method) { + this.parent = parent; + this.expressions = expressions; + this.method = method; + this.variables = [ + { + name: 'arguments', + type: 'arguments' + } + ]; + this.positions = {}; + if (!this.parent) Scope.root = this; + } + + Scope.prototype.add = function(name, type, immediate) { + if (this.shared && !immediate) return this.parent.add(name, type, immediate); + if (Object.prototype.hasOwnProperty.call(this.positions, name)) { + return this.variables[this.positions[name]].type = type; + } else { + return this.positions[name] = this.variables.push({ + name: name, + type: type + }) - 1; + } + }; + + Scope.prototype.find = function(name, options) { + if (this.check(name, options)) return true; + this.add(name, 'var'); + return false; + }; + + Scope.prototype.parameter = function(name) { + if (this.shared && this.parent.check(name, true)) return; + return this.add(name, 'param'); + }; + + Scope.prototype.check = function(name, immediate) { + var found, _ref1; + found = !!this.type(name); + if (found || immediate) return found; + return !!((_ref1 = this.parent) != null ? _ref1.check(name) : void 0); + }; + + Scope.prototype.temporary = function(name, index) { + if (name.length > 1) { + return '_' + name + (index > 1 ? index - 1 : ''); + } else { + return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a'); + } + }; + + Scope.prototype.type = function(name) { + var v, _i, _len, _ref1; + _ref1 = this.variables; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.name === name) return v.type; + } + return null; + }; + + Scope.prototype.freeVariable = function(name, reserve) { + var index, temp; + if (reserve == null) reserve = true; + index = 0; + while (this.check((temp = this.temporary(name, index)))) { + index++; + } + if (reserve) this.add(temp, 'var', true); + return temp; + }; + + Scope.prototype.assign = function(name, value) { + this.add(name, { + value: value, + assigned: true + }, true); + return this.hasAssignments = true; + }; + + Scope.prototype.hasDeclarations = function() { + return !!this.declaredVariables().length; + }; + + Scope.prototype.declaredVariables = function() { + var realVars, tempVars, v, _i, _len, _ref1; + realVars = []; + tempVars = []; + _ref1 = this.variables; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.type === 'var') { + (v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name); + } + } + return realVars.sort().concat(tempVars.sort()); + }; + + Scope.prototype.assignedVariables = function() { + var v, _i, _len, _ref1, _results; + _ref1 = this.variables; + _results = []; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.type.assigned) _results.push("" + v.name + " = " + v.type.value); + } + return _results; + }; + + return Scope; + + })(); + + +}); diff --git a/lib/client/editor/ace/worker-javascript.js b/lib/client/editor/ace/worker-javascript.js new file mode 100644 index 00000000..874873da --- /dev/null +++ b/lib/client/editor/ace/worker-javascript.js @@ -0,0 +1,10417 @@ +"no use strict"; + +var console = { + log: function(msg) { + postMessage({type: "log", data: msg}); + } +}; +var window = { + console: console +}; + +var normalizeModule = function(parentId, moduleName) { + // normalize plugin requires + if (moduleName.indexOf("!") !== -1) { + var chunks = moduleName.split("!"); + return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]); + } + // normalize relative requires + if (moduleName.charAt(0) == ".") { + var base = parentId.split("/").slice(0, -1).join("/"); + var moduleName = base + "/" + moduleName; + + while(moduleName.indexOf(".") !== -1 && previous != moduleName) { + var previous = moduleName; + var moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); + } + } + + return moduleName; +}; + +var require = function(parentId, id) { + var id = normalizeModule(parentId, id); + + var module = require.modules[id]; + if (module) { + if (!module.initialized) { + module.initialized = true; + module.exports = module.factory().exports; + } + return module.exports; + } + + var chunks = id.split("/"); + chunks[0] = require.tlns[chunks[0]] || chunks[0]; + var path = chunks.join("/") + ".js"; + + require.id = id; + importScripts(path); + return require(parentId, id); +}; + +require.modules = {}; +require.tlns = {}; + +var define = function(id, deps, factory) { + if (arguments.length == 2) { + factory = deps; + if (typeof id != "string") { + deps = id; + id = require.id; + } + } else if (arguments.length == 1) { + factory = id; + id = require.id; + } + + if (id.indexOf("text!") === 0) + return; + + var req = function(deps, factory) { + return require(id, deps, factory); + }; + + require.modules[id] = { + factory: function() { + var module = { + exports: {} + }; + var returnExports = factory(req, module.exports, module); + if (returnExports) + module.exports = returnExports; + return module; + } + }; +}; + +function initBaseUrls(topLevelNamespaces) { + require.tlns = topLevelNamespaces; +} + +function initSender() { + + var EventEmitter = require(null, "ace/lib/event_emitter").EventEmitter; + var oop = require(null, "ace/lib/oop"); + + var Sender = function() {}; + + (function() { + + oop.implement(this, EventEmitter); + + this.callback = function(data, callbackId) { + postMessage({ + type: "call", + id: callbackId, + data: data + }); + }; + + this.emit = function(name, data) { + postMessage({ + type: "event", + name: name, + data: data + }); + }; + + }).call(Sender.prototype); + + return new Sender(); +} + +var main; +var sender; + +onmessage = function(e) { + var msg = e.data; + if (msg.command) { + main[msg.command].apply(main, msg.args); + } + else if (msg.init) { + initBaseUrls(msg.tlns); + require(null, "ace/lib/fixoldbrowsers"); + sender = initSender(); + var clazz = require(null, msg.module)[msg.classname]; + main = new clazz(sender); + } + else if (msg.event && sender) { + sender._emit(msg.event, msg.data); + } +}; +// vim:set ts=4 sts=4 sw=4 st: +// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License +// -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project) +// -- dantman Daniel Friesen Copyright(C) 2010 XXX No License Specified +// -- fschaefer Florian Schäfer Copyright (C) 2010 MIT License +// -- Irakli Gozalishvili Copyright (C) 2010 MIT License + +/*! + Copyright (c) 2009, 280 North Inc. http://280north.com/ + MIT License. http://github.com/280north/narwhal/blob/master/README.md +*/ + +define('ace/lib/fixoldbrowsers', ['require', 'exports', 'module' , 'ace/lib/regexp', 'ace/lib/es5-shim'], function(require, exports, module) { + + +require("./regexp"); +require("./es5-shim"); + +}); + +define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, exports, module) { + + + //--------------------------------- + // Private variables + //--------------------------------- + + var real = { + exec: RegExp.prototype.exec, + test: RegExp.prototype.test, + match: String.prototype.match, + replace: String.prototype.replace, + split: String.prototype.split + }, + compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups + compliantLastIndexIncrement = function () { + var x = /^/g; + real.test.call(x, ""); + return !x.lastIndex; + }(); + + if (compliantLastIndexIncrement && compliantExecNpcg) + return; + + //--------------------------------- + // Overriden native methods + //--------------------------------- + + // Adds named capture support (with backreferences returned as `result.name`), and fixes two + // cross-browser issues per ES3: + // - Captured values for nonparticipating capturing groups should be returned as `undefined`, + // rather than the empty string. + // - `lastIndex` should not be incremented after zero-length matches. + RegExp.prototype.exec = function (str) { + var match = real.exec.apply(this, arguments), + name, r2; + if ( typeof(str) == 'string' && match) { + // Fix browsers whose `exec` methods don't consistently return `undefined` for + // nonparticipating capturing groups + if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) { + r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", "")); + // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed + // matching due to characters outside the match + real.replace.call(str.slice(match.index), r2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) + match[i] = undefined; + } + }); + } + // Attach named capture properties + if (this._xregexp && this._xregexp.captureNames) { + for (var i = 1; i < match.length; i++) { + name = this._xregexp.captureNames[i - 1]; + if (name) + match[name] = match[i]; + } + } + // Fix browsers that increment `lastIndex` after zero-length matches + if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + } + return match; + }; + + // Don't override `test` if it won't change anything + if (!compliantLastIndexIncrement) { + // Fix browser bug in native method + RegExp.prototype.test = function (str) { + // Use the native `exec` to skip some processing overhead, even though the overriden + // `exec` would take care of the `lastIndex` fix + var match = real.exec.call(this, str); + // Fix browsers that increment `lastIndex` after zero-length matches + if (match && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + return !!match; + }; + } + + //--------------------------------- + // Private helper functions + //--------------------------------- + + function getNativeFlags (regex) { + return (regex.global ? "g" : "") + + (regex.ignoreCase ? "i" : "") + + (regex.multiline ? "m" : "") + + (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3 + (regex.sticky ? "y" : ""); + } + + function indexOf (array, item, from) { + if (Array.prototype.indexOf) // Use the native array method if available + return array.indexOf(item, from); + for (var i = from || 0; i < array.length; i++) { + if (array[i] === item) + return i; + } + return -1; + } + +}); +/*! + Copyright (c) 2009, 280 North Inc. http://280north.com/ + MIT License. http://github.com/280north/narwhal/blob/master/README.md +*/ + +define('ace/lib/es5-shim', ['require', 'exports', 'module' ], function(require, exports, module) { + +/* + * Brings an environment as close to ECMAScript 5 compliance + * as is possible with the facilities of erstwhile engines. + * + * Annotated ES5: http://es5.github.com/ (specific links below) + * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf + * + * @module + */ + +/*whatsupdoc*/ + +// +// Function +// ======== +// + +// ES-5 15.3.4.5 +// http://es5.github.com/#x15.3.4.5 + +if (!Function.prototype.bind) { + Function.prototype.bind = function bind(that) { // .length is 1 + // 1. Let Target be the this value. + var target = this; + // 2. If IsCallable(Target) is false, throw a TypeError exception. + if (typeof target != "function") + throw new TypeError(); // TODO message + // 3. Let A be a new (possibly empty) internal list of all of the + // argument values provided after thisArg (arg1, arg2 etc), in order. + // XXX slicedArgs will stand in for "A" if used + var args = slice.call(arguments, 1); // for normal call + // 4. Let F be a new native ECMAScript object. + // 11. Set the [[Prototype]] internal property of F to the standard + // built-in Function prototype object as specified in 15.3.3.1. + // 12. Set the [[Call]] internal property of F as described in + // 15.3.4.5.1. + // 13. Set the [[Construct]] internal property of F as described in + // 15.3.4.5.2. + // 14. Set the [[HasInstance]] internal property of F as described in + // 15.3.4.5.3. + var bound = function () { + + if (this instanceof bound) { + // 15.3.4.5.2 [[Construct]] + // When the [[Construct]] internal method of a function object, + // F that was created using the bind function is called with a + // list of arguments ExtraArgs, the following steps are taken: + // 1. Let target be the value of F's [[TargetFunction]] + // internal property. + // 2. If target has no [[Construct]] internal method, a + // TypeError exception is thrown. + // 3. Let boundArgs be the value of F's [[BoundArgs]] internal + // property. + // 4. Let args be a new list containing the same values as the + // list boundArgs in the same order followed by the same + // values as the list ExtraArgs in the same order. + // 5. Return the result of calling the [[Construct]] internal + // method of target providing args as the arguments. + + var F = function(){}; + F.prototype = target.prototype; + var self = new F; + + var result = target.apply( + self, + args.concat(slice.call(arguments)) + ); + if (result !== null && Object(result) === result) + return result; + return self; + + } else { + // 15.3.4.5.1 [[Call]] + // When the [[Call]] internal method of a function object, F, + // which was created using the bind function is called with a + // this value and a list of arguments ExtraArgs, the following + // steps are taken: + // 1. Let boundArgs be the value of F's [[BoundArgs]] internal + // property. + // 2. Let boundThis be the value of F's [[BoundThis]] internal + // property. + // 3. Let target be the value of F's [[TargetFunction]] internal + // property. + // 4. Let args be a new list containing the same values as the + // list boundArgs in the same order followed by the same + // values as the list ExtraArgs in the same order. + // 5. Return the result of calling the [[Call]] internal method + // of target providing boundThis as the this value and + // providing args as the arguments. + + // equiv: target.call(this, ...boundArgs, ...args) + return target.apply( + that, + args.concat(slice.call(arguments)) + ); + + } + + }; + // XXX bound.length is never writable, so don't even try + // + // 15. If the [[Class]] internal property of Target is "Function", then + // a. Let L be the length property of Target minus the length of A. + // b. Set the length own property of F to either 0 or L, whichever is + // larger. + // 16. Else set the length own property of F to 0. + // 17. Set the attributes of the length own property of F to the values + // specified in 15.3.5.1. + + // TODO + // 18. Set the [[Extensible]] internal property of F to true. + + // TODO + // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3). + // 20. Call the [[DefineOwnProperty]] internal method of F with + // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]: + // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and + // false. + // 21. Call the [[DefineOwnProperty]] internal method of F with + // arguments "arguments", PropertyDescriptor {[[Get]]: thrower, + // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false}, + // and false. + + // TODO + // NOTE Function objects created using Function.prototype.bind do not + // have a prototype property or the [[Code]], [[FormalParameters]], and + // [[Scope]] internal properties. + // XXX can't delete prototype in pure-js. + + // 22. Return F. + return bound; + }; +} + +// Shortcut to an often accessed properties, in order to avoid multiple +// dereference that costs universally. +// _Please note: Shortcuts are defined after `Function.prototype.bind` as we +// us it in defining shortcuts. +var call = Function.prototype.call; +var prototypeOfArray = Array.prototype; +var prototypeOfObject = Object.prototype; +var slice = prototypeOfArray.slice; +var toString = call.bind(prototypeOfObject.toString); +var owns = call.bind(prototypeOfObject.hasOwnProperty); + +// If JS engine supports accessors creating shortcuts. +var defineGetter; +var defineSetter; +var lookupGetter; +var lookupSetter; +var supportsAccessors; +if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) { + defineGetter = call.bind(prototypeOfObject.__defineGetter__); + defineSetter = call.bind(prototypeOfObject.__defineSetter__); + lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); + lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); +} + +// +// Array +// ===== +// + +// ES5 15.4.3.2 +// http://es5.github.com/#x15.4.3.2 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray +if (!Array.isArray) { + Array.isArray = function isArray(obj) { + return toString(obj) == "[object Array]"; + }; +} + +// The IsCallable() check in the Array functions +// has been replaced with a strict check on the +// internal class of the object to trap cases where +// the provided function was actually a regular +// expression literal, which in V8 and +// JavaScriptCore is a typeof "function". Only in +// V8 are regular expression literals permitted as +// reduce parameters, so it is desirable in the +// general case for the shim to match the more +// strict and common behavior of rejecting regular +// expressions. + +// ES5 15.4.4.18 +// http://es5.github.com/#x15.4.4.18 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach +if (!Array.prototype.forEach) { + Array.prototype.forEach = function forEach(fun /*, thisp*/) { + var self = toObject(this), + thisp = arguments[1], + i = 0, + length = self.length >>> 0; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + while (i < length) { + if (i in self) { + // Invoke the callback function with call, passing arguments: + // context, property value, property key, thisArg object context + fun.call(thisp, self[i], i, self); + } + i++; + } + }; +} + +// ES5 15.4.4.19 +// http://es5.github.com/#x15.4.4.19 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map +if (!Array.prototype.map) { + Array.prototype.map = function map(fun /*, thisp*/) { + var self = toObject(this), + length = self.length >>> 0, + result = Array(length), + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self) + result[i] = fun.call(thisp, self[i], i, self); + } + return result; + }; +} + +// ES5 15.4.4.20 +// http://es5.github.com/#x15.4.4.20 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter +if (!Array.prototype.filter) { + Array.prototype.filter = function filter(fun /*, thisp */) { + var self = toObject(this), + length = self.length >>> 0, + result = [], + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, self)) + result.push(self[i]); + } + return result; + }; +} + +// ES5 15.4.4.16 +// http://es5.github.com/#x15.4.4.16 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every +if (!Array.prototype.every) { + Array.prototype.every = function every(fun /*, thisp */) { + var self = toObject(this), + length = self.length >>> 0, + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self && !fun.call(thisp, self[i], i, self)) + return false; + } + return true; + }; +} + +// ES5 15.4.4.17 +// http://es5.github.com/#x15.4.4.17 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some +if (!Array.prototype.some) { + Array.prototype.some = function some(fun /*, thisp */) { + var self = toObject(this), + length = self.length >>> 0, + thisp = arguments[1]; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, self)) + return true; + } + return false; + }; +} + +// ES5 15.4.4.21 +// http://es5.github.com/#x15.4.4.21 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce +if (!Array.prototype.reduce) { + Array.prototype.reduce = function reduce(fun /*, initial*/) { + var self = toObject(this), + length = self.length >>> 0; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + // no value to return if no initial value and an empty array + if (!length && arguments.length == 1) + throw new TypeError(); // TODO message + + var i = 0; + var result; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i++]; + break; + } + + // if array contains no values, no initial value to return + if (++i >= length) + throw new TypeError(); // TODO message + } while (true); + } + + for (; i < length; i++) { + if (i in self) + result = fun.call(void 0, result, self[i], i, self); + } + + return result; + }; +} + +// ES5 15.4.4.22 +// http://es5.github.com/#x15.4.4.22 +// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight +if (!Array.prototype.reduceRight) { + Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { + var self = toObject(this), + length = self.length >>> 0; + + // If no callback function or if callback is not a callable function + if (toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + // no value to return if no initial value, empty array + if (!length && arguments.length == 1) + throw new TypeError(); // TODO message + + var result, i = length - 1; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i--]; + break; + } + + // if array contains no values, no initial value to return + if (--i < 0) + throw new TypeError(); // TODO message + } while (true); + } + + do { + if (i in this) + result = fun.call(void 0, result, self[i], i, self); + } while (i--); + + return result; + }; +} + +// ES5 15.4.4.14 +// http://es5.github.com/#x15.4.4.14 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { + var self = toObject(this), + length = self.length >>> 0; + + if (!length) + return -1; + + var i = 0; + if (arguments.length > 1) + i = toInteger(arguments[1]); + + // handle negative indices + i = i >= 0 ? i : Math.max(0, length + i); + for (; i < length; i++) { + if (i in self && self[i] === sought) { + return i; + } + } + return -1; + }; +} + +// ES5 15.4.4.15 +// http://es5.github.com/#x15.4.4.15 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf +if (!Array.prototype.lastIndexOf) { + Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { + var self = toObject(this), + length = self.length >>> 0; + + if (!length) + return -1; + var i = length - 1; + if (arguments.length > 1) + i = Math.min(i, toInteger(arguments[1])); + // handle negative indices + i = i >= 0 ? i : length - Math.abs(i); + for (; i >= 0; i--) { + if (i in self && sought === self[i]) + return i; + } + return -1; + }; +} + +// +// Object +// ====== +// + +// ES5 15.2.3.2 +// http://es5.github.com/#x15.2.3.2 +if (!Object.getPrototypeOf) { + // https://github.com/kriskowal/es5-shim/issues#issue/2 + // http://ejohn.org/blog/objectgetprototypeof/ + // recommended by fschaefer on github + Object.getPrototypeOf = function getPrototypeOf(object) { + return object.__proto__ || ( + object.constructor ? + object.constructor.prototype : + prototypeOfObject + ); + }; +} + +// ES5 15.2.3.3 +// http://es5.github.com/#x15.2.3.3 +if (!Object.getOwnPropertyDescriptor) { + var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + + "non-object: "; + Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT + object); + // If object does not owns property return undefined immediately. + if (!owns(object, property)) + return; + + var descriptor, getter, setter; + + // If object has a property then it's for sure both `enumerable` and + // `configurable`. + descriptor = { enumerable: true, configurable: true }; + + // If JS engine supports accessor properties then property may be a + // getter or setter. + if (supportsAccessors) { + // Unfortunately `__lookupGetter__` will return a getter even + // if object has own non getter property along with a same named + // inherited getter. To avoid misbehavior we temporary remove + // `__proto__` so that `__lookupGetter__` will return getter only + // if it's owned by an object. + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + + var getter = lookupGetter(object, property); + var setter = lookupSetter(object, property); + + // Once we have getter and setter we can put values back. + object.__proto__ = prototype; + + if (getter || setter) { + if (getter) descriptor.get = getter; + if (setter) descriptor.set = setter; + + // If it was accessor property we're done and return here + // in order to avoid adding `value` to the descriptor. + return descriptor; + } + } + + // If we got this far we know that object has an own property that is + // not an accessor so we set it as a value and return descriptor. + descriptor.value = object[property]; + return descriptor; + }; +} + +// ES5 15.2.3.4 +// http://es5.github.com/#x15.2.3.4 +if (!Object.getOwnPropertyNames) { + Object.getOwnPropertyNames = function getOwnPropertyNames(object) { + return Object.keys(object); + }; +} + +// ES5 15.2.3.5 +// http://es5.github.com/#x15.2.3.5 +if (!Object.create) { + Object.create = function create(prototype, properties) { + var object; + if (prototype === null) { + object = { "__proto__": null }; + } else { + if (typeof prototype != "object") + throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); + var Type = function () {}; + Type.prototype = prototype; + object = new Type(); + // IE has no built-in implementation of `Object.getPrototypeOf` + // neither `__proto__`, but this manually setting `__proto__` will + // guarantee that `Object.getPrototypeOf` will work as expected with + // objects created using `Object.create` + object.__proto__ = prototype; + } + if (properties !== void 0) + Object.defineProperties(object, properties); + return object; + }; +} + +// ES5 15.2.3.6 +// http://es5.github.com/#x15.2.3.6 + +// Patch for WebKit and IE8 standard mode +// Designed by hax +// related issue: https://github.com/kriskowal/es5-shim/issues#issue/5 +// IE8 Reference: +// http://msdn.microsoft.com/en-us/library/dd282900.aspx +// http://msdn.microsoft.com/en-us/library/dd229916.aspx +// WebKit Bugs: +// https://bugs.webkit.org/show_bug.cgi?id=36423 + +function doesDefinePropertyWork(object) { + try { + Object.defineProperty(object, "sentinel", {}); + return "sentinel" in object; + } catch (exception) { + // returns falsy + } +} + +// check whether defineProperty works if it's given. Otherwise, +// shim partially. +if (Object.defineProperty) { + var definePropertyWorksOnObject = doesDefinePropertyWork({}); + var definePropertyWorksOnDom = typeof document == "undefined" || + doesDefinePropertyWork(document.createElement("div")); + if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { + var definePropertyFallback = Object.defineProperty; + } +} + +if (!Object.defineProperty || definePropertyFallback) { + var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; + var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " + var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + + "on this javascript engine"; + + Object.defineProperty = function defineProperty(object, property, descriptor) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT_TARGET + object); + if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) + throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); + + // make a valiant attempt to use the real defineProperty + // for I8's DOM elements. + if (definePropertyFallback) { + try { + return definePropertyFallback.call(Object, object, property, descriptor); + } catch (exception) { + // try the shim if the real one doesn't work + } + } + + // If it's a data property. + if (owns(descriptor, "value")) { + // fail silently if "writable", "enumerable", or "configurable" + // are requested but not supported + /* + // alternate approach: + if ( // can't implement these features; allow false but not true + !(owns(descriptor, "writable") ? descriptor.writable : true) || + !(owns(descriptor, "enumerable") ? descriptor.enumerable : true) || + !(owns(descriptor, "configurable") ? descriptor.configurable : true) + ) + throw new RangeError( + "This implementation of Object.defineProperty does not " + + "support configurable, enumerable, or writable." + ); + */ + + if (supportsAccessors && (lookupGetter(object, property) || + lookupSetter(object, property))) + { + // As accessors are supported only on engines implementing + // `__proto__` we can safely override `__proto__` while defining + // a property to make sure that we don't hit an inherited + // accessor. + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + // Deleting a property anyway since getter / setter may be + // defined on object itself. + delete object[property]; + object[property] = descriptor.value; + // Setting original `__proto__` back now. + object.__proto__ = prototype; + } else { + object[property] = descriptor.value; + } + } else { + if (!supportsAccessors) + throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); + // If we got that far then getters and setters can be defined !! + if (owns(descriptor, "get")) + defineGetter(object, property, descriptor.get); + if (owns(descriptor, "set")) + defineSetter(object, property, descriptor.set); + } + + return object; + }; +} + +// ES5 15.2.3.7 +// http://es5.github.com/#x15.2.3.7 +if (!Object.defineProperties) { + Object.defineProperties = function defineProperties(object, properties) { + for (var property in properties) { + if (owns(properties, property)) + Object.defineProperty(object, property, properties[property]); + } + return object; + }; +} + +// ES5 15.2.3.8 +// http://es5.github.com/#x15.2.3.8 +if (!Object.seal) { + Object.seal = function seal(object) { + // this is misleading and breaks feature-detection, but + // allows "securable" code to "gracefully" degrade to working + // but insecure code. + return object; + }; +} + +// ES5 15.2.3.9 +// http://es5.github.com/#x15.2.3.9 +if (!Object.freeze) { + Object.freeze = function freeze(object) { + // this is misleading and breaks feature-detection, but + // allows "securable" code to "gracefully" degrade to working + // but insecure code. + return object; + }; +} + +// detect a Rhino bug and patch it +try { + Object.freeze(function () {}); +} catch (exception) { + Object.freeze = (function freeze(freezeObject) { + return function freeze(object) { + if (typeof object == "function") { + return object; + } else { + return freezeObject(object); + } + }; + })(Object.freeze); +} + +// ES5 15.2.3.10 +// http://es5.github.com/#x15.2.3.10 +if (!Object.preventExtensions) { + Object.preventExtensions = function preventExtensions(object) { + // this is misleading and breaks feature-detection, but + // allows "securable" code to "gracefully" degrade to working + // but insecure code. + return object; + }; +} + +// ES5 15.2.3.11 +// http://es5.github.com/#x15.2.3.11 +if (!Object.isSealed) { + Object.isSealed = function isSealed(object) { + return false; + }; +} + +// ES5 15.2.3.12 +// http://es5.github.com/#x15.2.3.12 +if (!Object.isFrozen) { + Object.isFrozen = function isFrozen(object) { + return false; + }; +} + +// ES5 15.2.3.13 +// http://es5.github.com/#x15.2.3.13 +if (!Object.isExtensible) { + Object.isExtensible = function isExtensible(object) { + // 1. If Type(O) is not Object throw a TypeError exception. + if (Object(object) === object) { + throw new TypeError(); // TODO message + } + // 2. Return the Boolean value of the [[Extensible]] internal property of O. + var name = ''; + while (owns(object, name)) { + name += '?'; + } + object[name] = true; + var returnValue = owns(object, name); + delete object[name]; + return returnValue; + }; +} + +// ES5 15.2.3.14 +// http://es5.github.com/#x15.2.3.14 +if (!Object.keys) { + // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation + var hasDontEnumBug = true, + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + dontEnumsLength = dontEnums.length; + + for (var key in {"toString": null}) + hasDontEnumBug = false; + + Object.keys = function keys(object) { + + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError("Object.keys called on a non-object"); + + var keys = []; + for (var name in object) { + if (owns(object, name)) { + keys.push(name); + } + } + + if (hasDontEnumBug) { + for (var i = 0, ii = dontEnumsLength; i < ii; i++) { + var dontEnum = dontEnums[i]; + if (owns(object, dontEnum)) { + keys.push(dontEnum); + } + } + } + + return keys; + }; + +} + +// +// Date +// ==== +// + +// ES5 15.9.5.43 +// http://es5.github.com/#x15.9.5.43 +// This function returns a String value represent the instance in time +// represented by this Date object. The format of the String is the Date Time +// string format defined in 15.9.1.15. All fields are present in the String. +// The time zone is always UTC, denoted by the suffix Z. If the time value of +// this object is not a finite Number a RangeError exception is thrown. +if (!Date.prototype.toISOString || (new Date(-62198755200000).toISOString().indexOf('-000001') === -1)) { + Date.prototype.toISOString = function toISOString() { + var result, length, value, year; + if (!isFinite(this)) + throw new RangeError; + + // the date time string format is specified in 15.9.1.15. + result = [this.getUTCMonth() + 1, this.getUTCDate(), + this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()]; + year = this.getUTCFullYear(); + year = (year < 0 ? '-' : (year > 9999 ? '+' : '')) + ('00000' + Math.abs(year)).slice(0 <= year && year <= 9999 ? -4 : -6); + + length = result.length; + while (length--) { + value = result[length]; + // pad months, days, hours, minutes, and seconds to have two digits. + if (value < 10) + result[length] = "0" + value; + } + // pad milliseconds to have three digits. + return year + "-" + result.slice(0, 2).join("-") + "T" + result.slice(2).join(":") + "." + + ("000" + this.getUTCMilliseconds()).slice(-3) + "Z"; + } +} + +// ES5 15.9.4.4 +// http://es5.github.com/#x15.9.4.4 +if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; +} + +// ES5 15.9.5.44 +// http://es5.github.com/#x15.9.5.44 +// This function provides a String representation of a Date object for use by +// JSON.stringify (15.12.3). +if (!Date.prototype.toJSON) { + Date.prototype.toJSON = function toJSON(key) { + // When the toJSON method is called with argument key, the following + // steps are taken: + + // 1. Let O be the result of calling ToObject, giving it the this + // value as its argument. + // 2. Let tv be ToPrimitive(O, hint Number). + // 3. If tv is a Number and is not finite, return null. + // XXX + // 4. Let toISO be the result of calling the [[Get]] internal method of + // O with argument "toISOString". + // 5. If IsCallable(toISO) is false, throw a TypeError exception. + if (typeof this.toISOString != "function") + throw new TypeError(); // TODO message + // 6. Return the result of calling the [[Call]] internal method of + // toISO with O as the this value and an empty argument list. + return this.toISOString(); + + // NOTE 1 The argument is ignored. + + // NOTE 2 The toJSON function is intentionally generic; it does not + // require that its this value be a Date object. Therefore, it can be + // transferred to other kinds of objects for use as a method. However, + // it does require that any such object have a toISOString method. An + // object is free to use the argument key to filter its + // stringification. + }; +} + +// ES5 15.9.4.2 +// http://es5.github.com/#x15.9.4.2 +// based on work shared by Daniel Friesen (dantman) +// http://gist.github.com/303249 +if (Date.parse("+275760-09-13T00:00:00.000Z") !== 8.64e15) { + // XXX global assignment won't work in embeddings that use + // an alternate object for the context. + Date = (function(NativeDate) { + + // Date.length === 7 + var Date = function Date(Y, M, D, h, m, s, ms) { + var length = arguments.length; + if (this instanceof NativeDate) { + var date = length == 1 && String(Y) === Y ? // isString(Y) + // We explicitly pass it through parse: + new NativeDate(Date.parse(Y)) : + // We have to manually make calls depending on argument + // length here + length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) : + length >= 6 ? new NativeDate(Y, M, D, h, m, s) : + length >= 5 ? new NativeDate(Y, M, D, h, m) : + length >= 4 ? new NativeDate(Y, M, D, h) : + length >= 3 ? new NativeDate(Y, M, D) : + length >= 2 ? new NativeDate(Y, M) : + length >= 1 ? new NativeDate(Y) : + new NativeDate(); + // Prevent mixups with unfixed Date object + date.constructor = Date; + return date; + } + return NativeDate.apply(this, arguments); + }; + + // 15.9.1.15 Date Time String Format. + var isoDateExpression = new RegExp("^" + + "(\\d{4}|[\+\-]\\d{6})" + // four-digit year capture or sign + 6-digit extended year + "(?:-(\\d{2})" + // optional month capture + "(?:-(\\d{2})" + // optional day capture + "(?:" + // capture hours:minutes:seconds.milliseconds + "T(\\d{2})" + // hours capture + ":(\\d{2})" + // minutes capture + "(?:" + // optional :seconds.milliseconds + ":(\\d{2})" + // seconds capture + "(?:\\.(\\d{3}))?" + // milliseconds capture + ")?" + + "(?:" + // capture UTC offset component + "Z|" + // UTC capture + "(?:" + // offset specifier +/-hours:minutes + "([-+])" + // sign capture + "(\\d{2})" + // hours offset capture + ":(\\d{2})" + // minutes offset capture + ")" + + ")?)?)?)?" + + "$"); + + // Copy any custom methods a 3rd party library may have added + for (var key in NativeDate) + Date[key] = NativeDate[key]; + + // Copy "native" methods explicitly; they may be non-enumerable + Date.now = NativeDate.now; + Date.UTC = NativeDate.UTC; + Date.prototype = NativeDate.prototype; + Date.prototype.constructor = Date; + + // Upgrade Date.parse to handle simplified ISO 8601 strings + Date.parse = function parse(string) { + var match = isoDateExpression.exec(string); + if (match) { + match.shift(); // kill match[0], the full match + // parse months, days, hours, minutes, seconds, and milliseconds + for (var i = 1; i < 7; i++) { + // provide default values if necessary + match[i] = +(match[i] || (i < 3 ? 1 : 0)); + // match[1] is the month. Months are 0-11 in JavaScript + // `Date` objects, but 1-12 in ISO notation, so we + // decrement. + if (i == 1) + match[i]--; + } + + // parse the UTC offset component + var minuteOffset = +match.pop(), hourOffset = +match.pop(), sign = match.pop(); + + // compute the explicit time zone offset if specified + var offset = 0; + if (sign) { + // detect invalid offsets and return early + if (hourOffset > 23 || minuteOffset > 59) + return NaN; + + // express the provided time zone offset in minutes. The offset is + // negative for time zones west of UTC; positive otherwise. + offset = (hourOffset * 60 + minuteOffset) * 6e4 * (sign == "+" ? -1 : 1); + } + + // Date.UTC for years between 0 and 99 converts year to 1900 + year + // The Gregorian calendar has a 400-year cycle, so + // to Date.UTC(year + 400, .... ) - 12622780800000 == Date.UTC(year, ...), + // where 12622780800000 - number of milliseconds in Gregorian calendar 400 years + var year = +match[0]; + if (0 <= year && year <= 99) { + match[0] = year + 400; + return NativeDate.UTC.apply(this, match) + offset - 12622780800000; + } + + // compute a new UTC date value, accounting for the optional offset + return NativeDate.UTC.apply(this, match) + offset; + } + return NativeDate.parse.apply(this, arguments); + }; + + return Date; + })(Date); +} + +// +// String +// ====== +// + +// ES5 15.5.4.20 +// http://es5.github.com/#x15.5.4.20 +var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + + "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + + "\u2029\uFEFF"; +if (!String.prototype.trim || ws.trim()) { + // http://blog.stevenlevithan.com/archives/faster-trim-javascript + // http://perfectionkills.com/whitespace-deviations/ + ws = "[" + ws + "]"; + var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), + trimEndRegexp = new RegExp(ws + ws + "*$"); + String.prototype.trim = function trim() { + return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); + }; +} + +// +// Util +// ====== +// + +// ES5 9.4 +// http://es5.github.com/#x9.4 +// http://jsperf.com/to-integer +var toInteger = function (n) { + n = +n; + if (n !== n) // isNaN + n = 0; + else if (n !== 0 && n !== (1/0) && n !== -(1/0)) + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + return n; +}; + +var prepareString = "a"[0] != "a", + // ES5 9.9 + // http://es5.github.com/#x9.9 + toObject = function (o) { + if (o == null) { // this matches both null and undefined + throw new TypeError(); // TODO message + } + // If the implementation doesn't support by-index access of + // string characters (ex. IE < 7), split the string + if (prepareString && typeof o == "string" && o) { + return o.split(""); + } + return Object(o); + }; +}); + +define('ace/lib/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) { + + +var EventEmitter = {}; + +EventEmitter._emit = +EventEmitter._dispatchEvent = function(eventName, e) { + this._eventRegistry = this._eventRegistry || {}; + this._defaultHandlers = this._defaultHandlers || {}; + + var listeners = this._eventRegistry[eventName] || []; + var defaultHandler = this._defaultHandlers[eventName]; + if (!listeners.length && !defaultHandler) + return; + + e = e || {}; + if (!e.type) + e.type = eventName; + + if (!e.stopPropagation) { + e.stopPropagation = function() { + this.propagationStopped = true; + }; + } + + if (!e.preventDefault) { + e.preventDefault = function() { + this.defaultPrevented = true; + }; + } + + for (var i=0; i= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length-1).length; + } + return position; + }; + this.insert = function(position, text) { + if (!text || text.length === 0) + return position; + + position = this.$clipPosition(position); + + // only detect new lines if the document has no line break yet + if (this.getLength() <= 1) + this.$detectNewLine(text); + + var lines = this.$split(text); + var firstLine = lines.splice(0, 1)[0]; + var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0]; + + position = this.insertInLine(position, firstLine); + if (lastLine !== null) { + position = this.insertNewLine(position); // terminate first line + position = this.insertLines(position.row, lines); + position = this.insertInLine(position, lastLine || ""); + } + return position; + }; + /** + * Document@change(e) + * - e (Object): Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties. + * + * Fires whenever the document changes. + * + * Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available: + * + * * `"insertLines"` (emitted by [[Document.insertLines]]) + * * `range`: the [[Range]] of the change within the document + * * `lines`: the lines in the document that are changing + * * `"insertText"` (emitted by [[Document.insertNewLine]]) + * * `range`: the [[Range]] of the change within the document + * * `text`: the text that's being added + * * `"removeLines"` (emitted by [[Document.insertLines]]) + * * `range`: the [[Range]] of the change within the document + * * `lines`: the lines in the document that were removed + * * `nl`: the new line character (as defined by [[Document.getNewLineCharacter]]) + * * `"removeText"` (emitted by [[Document.removeInLine]] and [[Document.removeNewLine]]) + * * `range`: the [[Range]] of the change within the document + * * `text`: the text that's being removed + * + **/ + this.insertLines = function(row, lines) { + if (lines.length == 0) + return {row: row, column: 0}; + + // apply doesn't work for big arrays (smallest threshold is on safari 0xFFFF) + // to circumvent that we have to break huge inserts into smaller chunks here + if (lines.length > 0xFFFF) { + var end = this.insertLines(row, lines.slice(0xFFFF)); + lines = lines.slice(0, 0xFFFF); + } + + var args = [row, 0]; + args.push.apply(args, lines); + this.$lines.splice.apply(this.$lines, args); + + var range = new Range(row, 0, row + lines.length, 0); + var delta = { + action: "insertLines", + range: range, + lines: lines + }; + this._emit("change", { data: delta }); + return end || range.end; + }; + this.insertNewLine = function(position) { + position = this.$clipPosition(position); + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column); + this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length)); + + var end = { + row : position.row + 1, + column : 0 + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: this.getNewLineCharacter() + }; + this._emit("change", { data: delta }); + + return end; + }; + this.insertInLine = function(position, text) { + if (text.length == 0) + return position; + + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column) + text + + line.substring(position.column); + + var end = { + row : position.row, + column : position.column + text.length + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: text + }; + this._emit("change", { data: delta }); + + return end; + }; + this.remove = function(range) { + // clip to document + range.start = this.$clipPosition(range.start); + range.end = this.$clipPosition(range.end); + + if (range.isEmpty()) + return range.start; + + var firstRow = range.start.row; + var lastRow = range.end.row; + + if (range.isMultiLine()) { + var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1; + var lastFullRow = lastRow - 1; + + if (range.end.column > 0) + this.removeInLine(lastRow, 0, range.end.column); + + if (lastFullRow >= firstFullRow) + this.removeLines(firstFullRow, lastFullRow); + + if (firstFullRow != firstRow) { + this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length); + this.removeNewLine(range.start.row); + } + } + else { + this.removeInLine(firstRow, range.start.column, range.end.column); + } + return range.start; + }; + this.removeInLine = function(row, startColumn, endColumn) { + if (startColumn == endColumn) + return; + + var range = new Range(row, startColumn, row, endColumn); + var line = this.getLine(row); + var removed = line.substring(startColumn, endColumn); + var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length); + this.$lines.splice(row, 1, newLine); + + var delta = { + action: "removeText", + range: range, + text: removed + }; + this._emit("change", { data: delta }); + return range.start; + }; + this.removeLines = function(firstRow, lastRow) { + var range = new Range(firstRow, 0, lastRow + 1, 0); + var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1); + + var delta = { + action: "removeLines", + range: range, + nl: this.getNewLineCharacter(), + lines: removed + }; + this._emit("change", { data: delta }); + return removed; + }; + this.removeNewLine = function(row) { + var firstLine = this.getLine(row); + var secondLine = this.getLine(row+1); + + var range = new Range(row, firstLine.length, row+1, 0); + var line = firstLine + secondLine; + + this.$lines.splice(row, 2, line); + + var delta = { + action: "removeText", + range: range, + text: this.getNewLineCharacter() + }; + this._emit("change", { data: delta }); + }; + this.replace = function(range, text) { + if (text.length == 0 && range.isEmpty()) + return range.start; + + // Shortcut: If the text we want to insert is the same as it is already + // in the document, we don't have to replace anything. + if (text == this.getTextRange(range)) + return range.end; + + this.remove(range); + if (text) { + var end = this.insert(range.start, text); + } + else { + end = range.start; + } + + return end; + }; + this.applyDeltas = function(deltas) { + for (var i=0; i=0; i--) { + var delta = deltas[i]; + + var range = Range.fromPoints(delta.range.start, delta.range.end); + + if (delta.action == "insertLines") + this.removeLines(range.start.row, range.end.row - 1); + else if (delta.action == "insertText") + this.remove(range); + else if (delta.action == "removeLines") + this.insertLines(range.start.row, delta.lines); + else if (delta.action == "removeText") + this.insert(range.start, delta.text); + } + }; + +}).call(Document.prototype); + +exports.Document = Document; +}); + +define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) { + + +/** + * class Range + * + * This object is used in various places to indicate a region within the editor. To better visualize how this works, imagine a rectangle. Each quadrant of the rectangle is analogus to a range, as ranges contain a starting row and starting column, and an ending row, and ending column. + * + **/ + +/** + * new Range(startRow, startColumn, endRow, endColumn) + * - startRow (Number): The starting row + * - startColumn (Number): The starting column + * - endRow (Number): The ending row + * - endColumn (Number): The ending column + * + * Creates a new `Range` object with the given starting and ending row and column points. + * + **/ +var Range = function(startRow, startColumn, endRow, endColumn) { + this.start = { + row: startRow, + column: startColumn + }; + + this.end = { + row: endRow, + column: endColumn + }; +}; + +(function() { + /** + * Range.isEqual(range) -> Boolean + * - range (Range): A range to check against + * + * Returns `true` if and only if the starting row and column, and ending tow and column, are equivalent to those given by `range`. + * + **/ + this.isEqual = function(range) { + return this.start.row == range.start.row && + this.end.row == range.end.row && + this.start.column == range.start.column && + this.end.column == range.end.column + }; + this.toString = function() { + return ("Range: [" + this.start.row + "/" + this.start.column + + "] -> [" + this.end.row + "/" + this.end.column + "]"); + }; + + this.contains = function(row, column) { + return this.compare(row, column) == 0; + }; + this.compareRange = function(range) { + var cmp, + end = range.end, + start = range.start; + + cmp = this.compare(end.row, end.column); + if (cmp == 1) { + cmp = this.compare(start.row, start.column); + if (cmp == 1) { + return 2; + } else if (cmp == 0) { + return 1; + } else { + return 0; + } + } else if (cmp == -1) { + return -2; + } else { + cmp = this.compare(start.row, start.column); + if (cmp == -1) { + return -1; + } else if (cmp == 1) { + return 42; + } else { + return 0; + } + } + } + + /** related to: Range.compare + * Range.comparePoint(p) -> Number + * - p (Range): A point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `0` if the two points are exactly equal
+ * * `-1` if `p.row` is less then the calling range
+ * * `1` if `p.row` is greater than the calling range
+ *
+ * If the starting row of the calling range is equal to `p.row`, and:
+ * * `p.column` is greater than or equal to the calling range's starting column, this returns `0`
+ * * Otherwise, it returns -1
+ *
+ * If the ending row of the calling range is equal to `p.row`, and:
+ * * `p.column` is less than or equal to the calling range's ending column, this returns `0`
+ * * Otherwise, it returns 1
+ * + * Checks the row and column points of `p` with the row and column points of the calling range. + * + * + * + **/ + this.comparePoint = function(p) { + return this.compare(p.row, p.column); + } + + /** related to: Range.comparePoint + * Range.containsRange(range) -> Boolean + * - range (Range): A range to compare with + * + * Checks the start and end points of `range` and compares them to the calling range. Returns `true` if the `range` is contained within the caller's range. + * + **/ + this.containsRange = function(range) { + return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; + } + + /** + * Range.intersects(range) -> Boolean + * - range (Range): A range to compare with + * + * Returns `true` if passed in `range` intersects with the one calling this method. + * + **/ + this.intersects = function(range) { + var cmp = this.compareRange(range); + return (cmp == -1 || cmp == 0 || cmp == 1); + } + + /** + * Range.isEnd(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the caller's ending row point is the same as `row`, and if the caller's ending column is the same as `column`. + * + **/ + this.isEnd = function(row, column) { + return this.end.row == row && this.end.column == column; + } + + /** + * Range.isStart(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the caller's starting row point is the same as `row`, and if the caller's starting column is the same as `column`. + * + **/ + this.isStart = function(row, column) { + return this.start.row == row && this.start.column == column; + } + + /** + * Range.setStart(row, column) + * - row (Number): A row point to set + * - column (Number): A column point to set + * + * Sets the starting row and column for the range. + * + **/ + this.setStart = function(row, column) { + if (typeof row == "object") { + this.start.column = row.column; + this.start.row = row.row; + } else { + this.start.row = row; + this.start.column = column; + } + } + + /** + * Range.setEnd(row, column) + * - row (Number): A row point to set + * - column (Number): A column point to set + * + * Sets the starting row and column for the range. + * + **/ + this.setEnd = function(row, column) { + if (typeof row == "object") { + this.end.column = row.column; + this.end.row = row.row; + } else { + this.end.row = row; + this.end.column = column; + } + } + + /** related to: Range.compare + * Range.inside(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the `row` and `column` are within the given range. + * + **/ + this.inside = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column) || this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + } + + /** related to: Range.compare + * Range.insideStart(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the `row` and `column` are within the given range's starting points. + * + **/ + this.insideStart = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column)) { + return false; + } else { + return true; + } + } + return false; + } + + /** related to: Range.compare + * Range.insideEnd(row, column) -> Boolean + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + * Returns `true` if the `row` and `column` are within the given range's ending points. + * + **/ + this.insideEnd = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + } + + /** + * Range.compare(row, column) -> Number + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `0` if the two points are exactly equal
+ * * `-1` if `p.row` is less then the calling range
+ * * `1` if `p.row` is greater than the calling range
+ *
+ * If the starting row of the calling range is equal to `p.row`, and:
+ * * `p.column` is greater than or equal to the calling range's starting column, this returns `0`
+ * * Otherwise, it returns -1
+ *
+ * If the ending row of the calling range is equal to `p.row`, and:
+ * * `p.column` is less than or equal to the calling range's ending column, this returns `0`
+ * * Otherwise, it returns 1 + * + * Checks the row and column points with the row and column points of the calling range. + * + * + **/ + this.compare = function(row, column) { + if (!this.isMultiLine()) { + if (row === this.start.row) { + return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); + }; + } + + if (row < this.start.row) + return -1; + + if (row > this.end.row) + return 1; + + if (this.start.row === row) + return column >= this.start.column ? 0 : -1; + + if (this.end.row === row) + return column <= this.end.column ? 0 : 1; + + return 0; + }; + this.compareStart = function(row, column) { + if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + } + + /** + * Range.compareEnd(row, column) -> Number + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `0` if the two points are exactly equal
+ * * `-1` if `p.row` is less then the calling range
+ * * `1` if `p.row` is greater than the calling range, or if `isEnd` is `true.
+ *
+ * If the starting row of the calling range is equal to `p.row`, and:
+ * * `p.column` is greater than or equal to the calling range's starting column, this returns `0`
+ * * Otherwise, it returns -1
+ *
+ * If the ending row of the calling range is equal to `p.row`, and:
+ * * `p.column` is less than or equal to the calling range's ending column, this returns `0`
+ * * Otherwise, it returns 1 + * + * Checks the row and column points with the row and column points of the calling range. + * + * + **/ + this.compareEnd = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else { + return this.compare(row, column); + } + } + + /** + * Range.compareInside(row, column) -> Number + * - row (Number): A row point to compare with + * - column (Number): A column point to compare with + * + (Number): This method returns one of the following numbers:
+ * * `1` if the ending row of the calling range is equal to `row`, and the ending column of the calling range is equal to `column`
+ * * `-1` if the starting row of the calling range is equal to `row`, and the starting column of the calling range is equal to `column`
+ *
+ * Otherwise, it returns the value after calling [[Range.compare `compare()`]]. + * + * Checks the row and column points with the row and column points of the calling range. + * + * + * + **/ + this.compareInside = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + } + + /** + * Range.clipRows(firstRow, lastRow) -> Range + * - firstRow (Number): The starting row + * - lastRow (Number): The ending row + * + * Returns the part of the current `Range` that occurs within the boundaries of `firstRow` and `lastRow` as a new `Range` object. + * + **/ + this.clipRows = function(firstRow, lastRow) { + if (this.end.row > lastRow) { + var end = { + row: lastRow+1, + column: 0 + }; + } + + if (this.start.row > lastRow) { + var start = { + row: lastRow+1, + column: 0 + }; + } + + if (this.start.row < firstRow) { + var start = { + row: firstRow, + column: 0 + }; + } + + if (this.end.row < firstRow) { + var end = { + row: firstRow, + column: 0 + }; + } + return Range.fromPoints(start || this.start, end || this.end); + }; + this.extend = function(row, column) { + var cmp = this.compare(row, column); + + if (cmp == 0) + return this; + else if (cmp == -1) + var start = {row: row, column: column}; + else + var end = {row: row, column: column}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + + this.isEmpty = function() { + return (this.start.row == this.end.row && this.start.column == this.end.column); + }; + this.isMultiLine = function() { + return (this.start.row !== this.end.row); + }; + this.clone = function() { + return Range.fromPoints(this.start, this.end); + }; + this.collapseRows = function() { + if (this.end.column == 0) + return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) + else + return new Range(this.start.row, 0, this.end.row, 0) + }; + this.toScreenRange = function(session) { + var screenPosStart = + session.documentToScreenPosition(this.start); + var screenPosEnd = + session.documentToScreenPosition(this.end); + + return new Range( + screenPosStart.row, screenPosStart.column, + screenPosEnd.row, screenPosEnd.column + ); + }; + +}).call(Range.prototype); +Range.fromPoints = function(start, end) { + return new Range(start.row, start.column, end.row, end.column); +}; + +exports.Range = Range; +}); + +define('ace/anchor', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) { + + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; + +/** + * new Anchor(doc, row, column) + * - doc (Document): The document to associate with the anchor + * - row (Number): The starting row position + * - column (Number): The starting column position + * + * Creates a new `Anchor` and associates it with a document. + * + **/ + +var Anchor = exports.Anchor = function(doc, row, column) { + this.document = doc; + + if (typeof column == "undefined") + this.setPosition(row.row, row.column); + else + this.setPosition(row, column); + + this.$onChange = this.onChange.bind(this); + doc.on("change", this.$onChange); +}; + +(function() { + + oop.implement(this, EventEmitter); + + this.getPosition = function() { + return this.$clipPositionToDocument(this.row, this.column); + }; + + this.getDocument = function() { + return this.document; + }; + + this.onChange = function(e) { + var delta = e.data; + var range = delta.range; + + if (range.start.row == range.end.row && range.start.row != this.row) + return; + + if (range.start.row > this.row) + return; + + if (range.start.row == this.row && range.start.column > this.column) + return; + + var row = this.row; + var column = this.column; + + if (delta.action === "insertText") { + if (range.start.row === row && range.start.column <= column) { + if (range.start.row === range.end.row) { + column += range.end.column - range.start.column; + } + else { + column -= range.start.column; + row += range.end.row - range.start.row; + } + } + else if (range.start.row !== range.end.row && range.start.row < row) { + row += range.end.row - range.start.row; + } + } else if (delta.action === "insertLines") { + if (range.start.row <= row) { + row += range.end.row - range.start.row; + } + } + else if (delta.action == "removeText") { + if (range.start.row == row && range.start.column < column) { + if (range.end.column >= column) + column = range.start.column; + else + column = Math.max(0, column - (range.end.column - range.start.column)); + + } else if (range.start.row !== range.end.row && range.start.row < row) { + if (range.end.row == row) { + column = Math.max(0, column - range.end.column) + range.start.column; + } + row -= (range.end.row - range.start.row); + } + else if (range.end.row == row) { + row -= range.end.row - range.start.row; + column = Math.max(0, column - range.end.column) + range.start.column; + } + } else if (delta.action == "removeLines") { + if (range.start.row <= row) { + if (range.end.row <= row) + row -= range.end.row - range.start.row; + else { + row = range.start.row; + column = 0; + } + } + } + + this.setPosition(row, column, true); + }; + + this.setPosition = function(row, column, noClip) { + var pos; + if (noClip) { + pos = { + row: row, + column: column + }; + } + else { + pos = this.$clipPositionToDocument(row, column); + } + + if (this.row == pos.row && this.column == pos.column) + return; + + var old = { + row: this.row, + column: this.column + }; + + this.row = pos.row; + this.column = pos.column; + this._emit("change", { + old: old, + value: pos + }); + }; + + this.detach = function() { + this.document.removeEventListener("change", this.$onChange); + }; + + this.$clipPositionToDocument = function(row, column) { + var pos = {}; + + if (row >= this.document.getLength()) { + pos.row = Math.max(0, this.document.getLength() - 1); + pos.column = this.document.getLine(pos.row).length; + } + else if (row < 0) { + pos.row = 0; + pos.column = 0; + } + else { + pos.row = row; + pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); + } + + if (column < 0) + pos.column = 0; + + return pos; + }; + +}).call(Anchor.prototype); + +}); + +define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) { + + +exports.stringReverse = function(string) { + return string.split("").reverse().join(""); +}; + +exports.stringRepeat = function (string, count) { + return new Array(count + 1).join(string); +}; + +var trimBeginRegexp = /^\s\s*/; +var trimEndRegexp = /\s\s*$/; + +exports.stringTrimLeft = function (string) { + return string.replace(trimBeginRegexp, ''); +}; + +exports.stringTrimRight = function (string) { + return string.replace(trimEndRegexp, ''); +}; + +exports.copyObject = function(obj) { + var copy = {}; + for (var key in obj) { + copy[key] = obj[key]; + } + return copy; +}; + +exports.copyArray = function(array){ + var copy = []; + for (var i=0, l=array.length; i. + + var myReport = JSHINT.report(limited); + + If limited is true, then the report will be limited to only errors. + + You can request a data structure which contains JSHint's results. + + var myData = JSHINT.data(); + + It returns a structure with this form: + + { + errors: [ + { + line: NUMBER, + character: NUMBER, + reason: STRING, + evidence: STRING + } + ], + functions: [ + name: STRING, + line: NUMBER, + last: NUMBER, + param: [ + STRING + ], + closure: [ + STRING + ], + var: [ + STRING + ], + exception: [ + STRING + ], + outer: [ + STRING + ], + unused: [ + STRING + ], + global: [ + STRING + ], + label: [ + STRING + ] + ], + globals: [ + STRING + ], + member: { + STRING: NUMBER + }, + unused: [ + { + name: STRING, + line: NUMBER + } + ], + implieds: [ + { + name: STRING, + line: NUMBER + } + ], + urls: [ + STRING + ], + json: BOOLEAN + } + + Empty arrays will not be included. + +*/ + +/*jshint + evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true, + undef: true, maxlen: 100, indent:4 +*/ + +/*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)", + "(breakage)", "(context)", "(error)", "(global)", "(identifier)", "(last)", + "(line)", "(loopage)", "(name)", "(onevar)", "(params)", "(scope)", + "(statement)", "(verb)", "*", "+", "++", "-", "--", "\/", "<", "<=", "==", + "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax, + __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio, + Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas, + CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date, + Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, DOMParser, Drag, + E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event, + Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form, + FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey, + HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement, + HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement, + HTMLDivElement, HTMLDListElement, HTMLFieldSetElement, + HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement, + HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement, + HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement, + HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement, + HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement, + HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement, + HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement, + HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement, + HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement, + HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement, + HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement, + Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array, + Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E, + MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MessageChannel, MessageEvent, MessagePort, + MoveAnimation, MooTools, Native, NEGATIVE_INFINITY, Number, Object, ObjectRange, Option, + Options, OverText, PI, POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, + RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, + SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion, + ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller, + Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables, + SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template, + Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL, + VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XMLSerializer, + XPathEvaluator, XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, + "\\", a, addEventListener, address, alert, apply, applicationCache, arguments, arity, asi, atob, + b, basic, basicToken, bitwise, block, blur, boolOptions, boss, browser, btoa, c, call, callee, + caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout, + close, closed, closure, comment, condition, confirm, console, constructor, + content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI, + decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document, + dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent, + entityify, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil, + ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, + forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions, + g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict, + hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include, + indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray, + isDigit, isFinite, isNaN, iterator, java, join, jshint, + JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, laxcomma, + latedef, lbp, led, left, length, line, load, loadClass, localStorage, location, + log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy, + moveTo, mootools, multistr, name, navigator, new, newcap, noarg, node, noempty, nomen, + nonew, nonstandard, nud, onbeforeunload, onblur, onerror, onevar, onecase, onfocus, + onload, onresize, onunload, open, openDatabase, openURL, opener, opera, options, outer, param, + parent, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt, + proto, prototype, prototypejs, provides, push, quit, range, raw, reach, reason, regexp, + readFile, readUrl, regexdash, removeEventListener, replace, report, require, + reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right, + runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal, + send, serialize, sessionStorage, setInterval, setTimeout, setter, setterToken, shift, slice, + smarttabs, sort, spawn, split, stack, status, start, strict, sub, substr, supernew, shadow, + supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing, + type, typeOf, Uint16Array, Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis, + value, valueOf, var, version, WebSocket, withstmt, white, window, Worker, wsh*/ + +/*global exports: false */ + +// We build the application inside a function so that we produce only a single +// global variable. That function will be invoked immediately, and its return +// value is the JSHINT function itself. + +var JSHINT = (function () { + + + var anonname, // The guessed name for anonymous functions. + +// These are operators that should not be used with the ! operator. + + bang = { + '<' : true, + '<=' : true, + '==' : true, + '===': true, + '!==': true, + '!=' : true, + '>' : true, + '>=' : true, + '+' : true, + '-' : true, + '*' : true, + '/' : true, + '%' : true + }, + + // These are the JSHint boolean options. + boolOptions = { + asi : true, // if automatic semicolon insertion should be tolerated + bitwise : true, // if bitwise operators should not be allowed + boss : true, // if advanced usage of assignments should be allowed + browser : true, // if the standard browser globals should be predefined + couch : true, // if CouchDB globals should be predefined + curly : true, // if curly braces around all blocks should be required + debug : true, // if debugger statements should be allowed + devel : true, // if logging globals should be predefined (console, + // alert, etc.) + dojo : true, // if Dojo Toolkit globals should be predefined + eqeqeq : true, // if === should be required + eqnull : true, // if == null comparisons should be tolerated + es5 : true, // if ES5 syntax should be allowed + esnext : true, // if es.next specific syntax should be allowed + evil : true, // if eval should be allowed + expr : true, // if ExpressionStatement should be allowed as Programs + forin : true, // if for in statements must filter + funcscope : true, // if only function scope should be used for scope tests + globalstrict: true, // if global should be allowed (also + // enables 'strict') + immed : true, // if immediate invocations must be wrapped in parens + iterator : true, // if the `__iterator__` property should be allowed + jquery : true, // if jQuery globals should be predefined + lastsemic : true, // if semicolons may be ommitted for the trailing + // statements inside of a one-line blocks. + latedef : true, // if the use before definition should not be tolerated + laxbreak : true, // if line breaks should not be checked + laxcomma : true, // if line breaks should not be checked around commas + loopfunc : true, // if functions should be allowed to be defined within + // loops + mootools : true, // if MooTools globals should be predefined + multistr : true, // allow multiline strings + newcap : true, // if constructor names must be capitalized + noarg : true, // if arguments.caller and arguments.callee should be + // disallowed + node : true, // if the Node.js environment globals should be + // predefined + noempty : true, // if empty blocks should be disallowed + nonew : true, // if using `new` for side-effects should be disallowed + nonstandard : true, // if non-standard (but widely adopted) globals should + // be predefined + nomen : true, // if names should be checked + onevar : true, // if only one var statement per function should be + // allowed + onecase : true, // if one case switch statements should be allowed + passfail : true, // if the scan should stop on first error + plusplus : true, // if increment/decrement should not be allowed + proto : true, // if the `__proto__` property should be allowed + prototypejs : true, // if Prototype and Scriptaculous globals should be + // predefined + regexdash : true, // if unescaped first/last dash (-) inside brackets + // should be tolerated + regexp : true, // if the . should not be allowed in regexp literals + rhino : true, // if the Rhino environment globals should be predefined + undef : true, // if variables should be declared before used + scripturl : true, // if script-targeted URLs should be tolerated + shadow : true, // if variable shadowing should be tolerated + smarttabs : true, // if smarttabs should be tolerated + // (http://www.emacswiki.org/emacs/SmartTabs) + strict : true, // require the pragma + sub : true, // if all forms of subscript notation are tolerated + supernew : true, // if `new function () { ... };` and `new Object;` + // should be tolerated + trailing : true, // if trailing whitespace rules apply + validthis : true, // if 'this' inside a non-constructor function is valid. + // This is a function scoped option only. + withstmt : true, // if with statements should be allowed + white : true, // if strict whitespace rules apply + wsh : true // if the Windows Scripting Host environment globals + // should be predefined + }, + + // These are the JSHint options that can take any value + // (we use this object to detect invalid options) + valOptions = { + maxlen: false, + indent: false, + maxerr: false, + predef: false + }, + + + // browser contains a set of global names which are commonly provided by a + // web browser environment. + browser = { + ArrayBuffer : false, + ArrayBufferView : false, + Audio : false, + addEventListener : false, + applicationCache : false, + atob : false, + blur : false, + btoa : false, + clearInterval : false, + clearTimeout : false, + close : false, + closed : false, + DataView : false, + DOMParser : false, + defaultStatus : false, + document : false, + event : false, + FileReader : false, + Float32Array : false, + Float64Array : false, + FormData : false, + focus : false, + frames : false, + getComputedStyle : false, + HTMLElement : false, + HTMLAnchorElement : false, + HTMLBaseElement : false, + HTMLBlockquoteElement : false, + HTMLBodyElement : false, + HTMLBRElement : false, + HTMLButtonElement : false, + HTMLCanvasElement : false, + HTMLDirectoryElement : false, + HTMLDivElement : false, + HTMLDListElement : false, + HTMLFieldSetElement : false, + HTMLFontElement : false, + HTMLFormElement : false, + HTMLFrameElement : false, + HTMLFrameSetElement : false, + HTMLHeadElement : false, + HTMLHeadingElement : false, + HTMLHRElement : false, + HTMLHtmlElement : false, + HTMLIFrameElement : false, + HTMLImageElement : false, + HTMLInputElement : false, + HTMLIsIndexElement : false, + HTMLLabelElement : false, + HTMLLayerElement : false, + HTMLLegendElement : false, + HTMLLIElement : false, + HTMLLinkElement : false, + HTMLMapElement : false, + HTMLMenuElement : false, + HTMLMetaElement : false, + HTMLModElement : false, + HTMLObjectElement : false, + HTMLOListElement : false, + HTMLOptGroupElement : false, + HTMLOptionElement : false, + HTMLParagraphElement : false, + HTMLParamElement : false, + HTMLPreElement : false, + HTMLQuoteElement : false, + HTMLScriptElement : false, + HTMLSelectElement : false, + HTMLStyleElement : false, + HTMLTableCaptionElement : false, + HTMLTableCellElement : false, + HTMLTableColElement : false, + HTMLTableElement : false, + HTMLTableRowElement : false, + HTMLTableSectionElement : false, + HTMLTextAreaElement : false, + HTMLTitleElement : false, + HTMLUListElement : false, + HTMLVideoElement : false, + history : false, + Int16Array : false, + Int32Array : false, + Int8Array : false, + Image : false, + length : false, + localStorage : false, + location : false, + MessageChannel : false, + MessageEvent : false, + MessagePort : false, + moveBy : false, + moveTo : false, + name : false, + navigator : false, + onbeforeunload : true, + onblur : true, + onerror : true, + onfocus : true, + onload : true, + onresize : true, + onunload : true, + open : false, + openDatabase : false, + opener : false, + Option : false, + parent : false, + print : false, + removeEventListener : false, + resizeBy : false, + resizeTo : false, + screen : false, + scroll : false, + scrollBy : false, + scrollTo : false, + sessionStorage : false, + setInterval : false, + setTimeout : false, + SharedWorker : false, + status : false, + top : false, + Uint16Array : false, + Uint32Array : false, + Uint8Array : false, + WebSocket : false, + window : false, + Worker : false, + XMLHttpRequest : false, + XMLSerializer : false, + XPathEvaluator : false, + XPathException : false, + XPathExpression : false, + XPathNamespace : false, + XPathNSResolver : false, + XPathResult : false + }, + + couch = { + "require" : false, + respond : false, + getRow : false, + emit : false, + send : false, + start : false, + sum : false, + log : false, + exports : false, + module : false, + provides : false + }, + + devel = { + alert : false, + confirm : false, + console : false, + Debug : false, + opera : false, + prompt : false + }, + + dojo = { + dojo : false, + dijit : false, + dojox : false, + define : false, + "require" : false + }, + + escapes = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '/' : '\\/', + '\\': '\\\\' + }, + + funct, // The current function + + functionicity = [ + 'closure', 'exception', 'global', 'label', + 'outer', 'unused', 'var' + ], + + functions, // All of the functions + + global, // The global scope + implied, // Implied globals + inblock, + indent, + jsonmode, + + jquery = { + '$' : false, + jQuery : false + }, + + lines, + lookahead, + member, + membersOnly, + + mootools = { + '$' : false, + '$$' : false, + Assets : false, + Browser : false, + Chain : false, + Class : false, + Color : false, + Cookie : false, + Core : false, + Document : false, + DomReady : false, + DOMReady : false, + Drag : false, + Element : false, + Elements : false, + Event : false, + Events : false, + Fx : false, + Group : false, + Hash : false, + HtmlTable : false, + Iframe : false, + IframeShim : false, + InputValidator : false, + instanceOf : false, + Keyboard : false, + Locale : false, + Mask : false, + MooTools : false, + Native : false, + Options : false, + OverText : false, + Request : false, + Scroller : false, + Slick : false, + Slider : false, + Sortables : false, + Spinner : false, + Swiff : false, + Tips : false, + Type : false, + typeOf : false, + URI : false, + Window : false + }, + + nexttoken, + + node = { + __filename : false, + __dirname : false, + Buffer : false, + console : false, + exports : false, + GLOBAL : false, + global : false, + module : false, + process : false, + require : false, + setTimeout : false, + clearTimeout : false, + setInterval : false, + clearInterval : false + }, + + noreach, + option, + predefined, // Global variables defined by option + prereg, + prevtoken, + + prototypejs = { + '$' : false, + '$$' : false, + '$A' : false, + '$F' : false, + '$H' : false, + '$R' : false, + '$break' : false, + '$continue' : false, + '$w' : false, + Abstract : false, + Ajax : false, + Class : false, + Enumerable : false, + Element : false, + Event : false, + Field : false, + Form : false, + Hash : false, + Insertion : false, + ObjectRange : false, + PeriodicalExecuter: false, + Position : false, + Prototype : false, + Selector : false, + Template : false, + Toggle : false, + Try : false, + Autocompleter : false, + Builder : false, + Control : false, + Draggable : false, + Draggables : false, + Droppables : false, + Effect : false, + Sortable : false, + SortableObserver : false, + Sound : false, + Scriptaculous : false + }, + + rhino = { + defineClass : false, + deserialize : false, + gc : false, + help : false, + importPackage: false, + "java" : false, + load : false, + loadClass : false, + print : false, + quit : false, + readFile : false, + readUrl : false, + runCommand : false, + seal : false, + serialize : false, + spawn : false, + sync : false, + toint32 : false, + version : false + }, + + scope, // The current scope + stack, + + // standard contains the global names that are provided by the + // ECMAScript standard. + standard = { + Array : false, + Boolean : false, + Date : false, + decodeURI : false, + decodeURIComponent : false, + encodeURI : false, + encodeURIComponent : false, + Error : false, + 'eval' : false, + EvalError : false, + Function : false, + hasOwnProperty : false, + isFinite : false, + isNaN : false, + JSON : false, + Math : false, + Number : false, + Object : false, + parseInt : false, + parseFloat : false, + RangeError : false, + ReferenceError : false, + RegExp : false, + String : false, + SyntaxError : false, + TypeError : false, + URIError : false + }, + + // widely adopted global names that are not part of ECMAScript standard + nonstandard = { + escape : false, + unescape : false + }, + + standard_member = { + E : true, + LN2 : true, + LN10 : true, + LOG2E : true, + LOG10E : true, + MAX_VALUE : true, + MIN_VALUE : true, + NEGATIVE_INFINITY : true, + PI : true, + POSITIVE_INFINITY : true, + SQRT1_2 : true, + SQRT2 : true + }, + + directive, + syntax = {}, + tab, + token, + urls, + useESNextSyntax, + warnings, + + wsh = { + ActiveXObject : true, + Enumerator : true, + GetObject : true, + ScriptEngine : true, + ScriptEngineBuildVersion : true, + ScriptEngineMajorVersion : true, + ScriptEngineMinorVersion : true, + VBArray : true, + WSH : true, + WScript : true, + XDomainRequest : true + }; + + // Regular expressions. Some of these are stupidly long. + var ax, cx, tx, nx, nxg, lx, ix, jx, ft; + (function () { + /*jshint maxlen:300 */ + + // unsafe comment or string + ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i; + + // unsafe characters that are silently deleted by one or more browsers + cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + + // token + tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/; + + // characters in strings that need escapement + nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + + // star slash + lx = /\*\/|\/\*/; + + // identifier + ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/; + + // javascript url + jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i; + + // catches /* falls through */ comments + ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/; + }()); + + function F() {} // Used by Object.create + + function is_own(object, name) { + +// The object.hasOwnProperty method fails when the property under consideration +// is named 'hasOwnProperty'. So we have to use this more convoluted form. + + return Object.prototype.hasOwnProperty.call(object, name); + } + + function checkOption(name, t) { + if (valOptions[name] === undefined && boolOptions[name] === undefined) { + warning("Bad option: '" + name + "'.", t); + } + } + +// Provide critical ES5 functions to ES3. + + if (typeof Array.isArray !== 'function') { + Array.isArray = function (o) { + return Object.prototype.toString.apply(o) === '[object Array]'; + }; + } + + if (typeof Object.create !== 'function') { + Object.create = function (o) { + F.prototype = o; + return new F(); + }; + } + + if (typeof Object.keys !== 'function') { + Object.keys = function (o) { + var a = [], k; + for (k in o) { + if (is_own(o, k)) { + a.push(k); + } + } + return a; + }; + } + +// Non standard methods + + if (typeof String.prototype.entityify !== 'function') { + String.prototype.entityify = function () { + return this + .replace(/&/g, '&') + .replace(//g, '>'); + }; + } + + if (typeof String.prototype.isAlpha !== 'function') { + String.prototype.isAlpha = function () { + return (this >= 'a' && this <= 'z\uffff') || + (this >= 'A' && this <= 'Z\uffff'); + }; + } + + if (typeof String.prototype.isDigit !== 'function') { + String.prototype.isDigit = function () { + return (this >= '0' && this <= '9'); + }; + } + + if (typeof String.prototype.supplant !== 'function') { + String.prototype.supplant = function (o) { + return this.replace(/\{([^{}]*)\}/g, function (a, b) { + var r = o[b]; + return typeof r === 'string' || typeof r === 'number' ? r : a; + }); + }; + } + + if (typeof String.prototype.name !== 'function') { + String.prototype.name = function () { + +// If the string looks like an identifier, then we can return it as is. +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can simply slap some quotes around it. +// Otherwise we must also replace the offending characters with safe +// sequences. + + if (ix.test(this)) { + return this; + } + if (nx.test(this)) { + return '"' + this.replace(nxg, function (a) { + var c = escapes[a]; + if (c) { + return c; + } + return '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4); + }) + '"'; + } + return '"' + this + '"'; + }; + } + + + function combine(t, o) { + var n; + for (n in o) { + if (is_own(o, n)) { + t[n] = o[n]; + } + } + } + + function assume() { + if (option.couch) { + combine(predefined, couch); + } + + if (option.rhino) { + combine(predefined, rhino); + } + + if (option.prototypejs) { + combine(predefined, prototypejs); + } + + if (option.node) { + combine(predefined, node); + option.globalstrict = true; + } + + if (option.devel) { + combine(predefined, devel); + } + + if (option.dojo) { + combine(predefined, dojo); + } + + if (option.browser) { + combine(predefined, browser); + } + + if (option.nonstandard) { + combine(predefined, nonstandard); + } + + if (option.jquery) { + combine(predefined, jquery); + } + + if (option.mootools) { + combine(predefined, mootools); + } + + if (option.wsh) { + combine(predefined, wsh); + } + + if (option.esnext) { + useESNextSyntax(); + } + + if (option.globalstrict && option.strict !== false) { + option.strict = true; + } + } + + + // Produce an error warning. + function quit(message, line, chr) { + var percentage = Math.floor((line / lines.length) * 100); + + throw { + name: 'JSHintError', + line: line, + character: chr, + message: message + " (" + percentage + "% scanned).", + raw: message + }; + } + + function isundef(scope, m, t, a) { + return JSHINT.undefs.push([scope, m, t, a]); + } + + function warning(m, t, a, b, c, d) { + var ch, l, w; + t = t || nexttoken; + if (t.id === '(end)') { // `~ + t = token; + } + l = t.line || 0; + ch = t.from || 0; + w = { + id: '(error)', + raw: m, + evidence: lines[l - 1] || '', + line: l, + character: ch, + a: a, + b: b, + c: c, + d: d + }; + w.reason = m.supplant(w); + JSHINT.errors.push(w); + if (option.passfail) { + quit('Stopping. ', l, ch); + } + warnings += 1; + if (warnings >= option.maxerr) { + quit("Too many errors.", l, ch); + } + return w; + } + + function warningAt(m, l, ch, a, b, c, d) { + return warning(m, { + line: l, + from: ch + }, a, b, c, d); + } + + function error(m, t, a, b, c, d) { + var w = warning(m, t, a, b, c, d); + } + + function errorAt(m, l, ch, a, b, c, d) { + return error(m, { + line: l, + from: ch + }, a, b, c, d); + } + + + +// lexical analysis and token construction + + var lex = (function lex() { + var character, from, line, s; + +// Private lex methods + + function nextLine() { + var at, + tw; // trailing whitespace check + + if (line >= lines.length) + return false; + + character = 1; + s = lines[line]; + line += 1; + + // If smarttabs option is used check for spaces followed by tabs only. + // Otherwise check for any occurence of mixed tabs and spaces. + if (option.smarttabs) + at = s.search(/ \t/); + else + at = s.search(/ \t|\t /); + + if (at >= 0) + warningAt("Mixed spaces and tabs.", line, at + 1); + + s = s.replace(/\t/g, tab); + at = s.search(cx); + + if (at >= 0) + warningAt("Unsafe character.", line, at); + + if (option.maxlen && option.maxlen < s.length) + warningAt("Line too long.", line, s.length); + + // Check for trailing whitespaces + tw = option.trailing && s.match(/^(.*?)\s+$/); + if (tw && !/^\s+$/.test(s)) { + warningAt("Trailing whitespace.", line, tw[1].length + 1); + } + return true; + } + +// Produce a token object. The token inherits from a syntax symbol. + + function it(type, value) { + var i, t; + if (type === '(color)' || type === '(range)') { + t = {type: type}; + } else if (type === '(punctuator)' || + (type === '(identifier)' && is_own(syntax, value))) { + t = syntax[value] || syntax['(error)']; + } else { + t = syntax[type]; + } + t = Object.create(t); + if (type === '(string)' || type === '(range)') { + if (!option.scripturl && jx.test(value)) { + warningAt("Script URL.", line, from); + } + } + if (type === '(identifier)') { + t.identifier = true; + if (value === '__proto__' && !option.proto) { + warningAt("The '{a}' property is deprecated.", + line, from, value); + } else if (value === '__iterator__' && !option.iterator) { + warningAt("'{a}' is only available in JavaScript 1.7.", + line, from, value); + } else if (option.nomen && (value.charAt(0) === '_' || + value.charAt(value.length - 1) === '_')) { + if (!option.node || token.id === '.' || + (value !== '__dirname' && value !== '__filename')) { + warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", value); + } + } + } + t.value = value; + t.line = line; + t.character = character; + t.from = from; + i = t.id; + if (i !== '(endline)') { + prereg = i && + (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) || + i === 'return' || + i === 'case'); + } + return t; + } + + // Public lex methods + return { + init: function (source) { + if (typeof source === 'string') { + lines = source + .replace(/\r\n/g, '\n') + .replace(/\r/g, '\n') + .split('\n'); + } else { + lines = source; + } + + // If the first line is a shebang (#!), make it a blank and move on. + // Shebangs are used by Node scripts. + if (lines[0] && lines[0].substr(0, 2) === '#!') + lines[0] = ''; + + line = 0; + nextLine(); + from = 1; + }, + + range: function (begin, end) { + var c, value = ''; + from = character; + if (s.charAt(0) !== begin) { + errorAt("Expected '{a}' and instead saw '{b}'.", + line, character, begin, s.charAt(0)); + } + for (;;) { + s = s.slice(1); + character += 1; + c = s.charAt(0); + switch (c) { + case '': + errorAt("Missing '{a}'.", line, character, c); + break; + case end: + s = s.slice(1); + character += 1; + return it('(range)', value); + case '\\': + warningAt("Unexpected '{a}'.", line, character, c); + } + value += c; + } + + }, + + + // token -- this is called by advance to get the next token + token: function () { + var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n; + + function match(x) { + var r = x.exec(s), r1; + if (r) { + l = r[0].length; + r1 = r[1]; + c = r1.charAt(0); + s = s.substr(l); + from = character + l - r1.length; + character += l; + return r1; + } + } + + function string(x) { + var c, j, r = '', allowNewLine = false; + + if (jsonmode && x !== '"') { + warningAt("Strings must use doublequote.", + line, character); + } + + function esc(n) { + var i = parseInt(s.substr(j + 1, n), 16); + j += n; + if (i >= 32 && i <= 126 && + i !== 34 && i !== 92 && i !== 39) { + warningAt("Unnecessary escapement.", line, character); + } + character += n; + c = String.fromCharCode(i); + } + j = 0; +unclosedString: for (;;) { + while (j >= s.length) { + j = 0; + + var cl = line, cf = from; + if (!nextLine()) { + errorAt("Unclosed string.", cl, cf); + break unclosedString; + } + + if (allowNewLine) { + allowNewLine = false; + } else { + warningAt("Unclosed string.", cl, cf); + } + } + c = s.charAt(j); + if (c === x) { + character += 1; + s = s.substr(j + 1); + return it('(string)', r, x); + } + if (c < ' ') { + if (c === '\n' || c === '\r') { + break; + } + warningAt("Control character in string: {a}.", + line, character + j, s.slice(0, j)); + } else if (c === '\\') { + j += 1; + character += 1; + c = s.charAt(j); + n = s.charAt(j + 1); + switch (c) { + case '\\': + case '"': + case '/': + break; + case '\'': + if (jsonmode) { + warningAt("Avoid \\'.", line, character); + } + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case '0': + c = '\0'; + // Octal literals fail in strict mode + // check if the number is between 00 and 07 + // where 'n' is the token next to 'c' + if (n >= 0 && n <= 7 && directive["use strict"]) { + warningAt( + "Octal literals are not allowed in strict mode.", + line, character); + } + break; + case 'u': + esc(4); + break; + case 'v': + if (jsonmode) { + warningAt("Avoid \\v.", line, character); + } + c = '\v'; + break; + case 'x': + if (jsonmode) { + warningAt("Avoid \\x-.", line, character); + } + esc(2); + break; + case '': + // last character is escape character + // always allow new line if escaped, but show + // warning if option is not set + allowNewLine = true; + if (option.multistr) { + if (jsonmode) { + warningAt("Avoid EOL escapement.", line, character); + } + c = ''; + character -= 1; + break; + } + warningAt("Bad escapement of EOL. Use option multistr if needed.", + line, character); + break; + default: + warningAt("Bad escapement.", line, character); + } + } + r += c; + character += 1; + j += 1; + } + } + + for (;;) { + if (!s) { + return it(nextLine() ? '(endline)' : '(end)', ''); + } + t = match(tx); + if (!t) { + t = ''; + c = ''; + while (s && s < '!') { + s = s.substr(1); + } + if (s) { + errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1)); + s = ''; + } + } else { + + // identifier + + if (c.isAlpha() || c === '_' || c === '$') { + return it('(identifier)', t); + } + + // number + + if (c.isDigit()) { + if (!isFinite(Number(t))) { + warningAt("Bad number '{a}'.", + line, character, t); + } + if (s.substr(0, 1).isAlpha()) { + warningAt("Missing space after '{a}'.", + line, character, t); + } + if (c === '0') { + d = t.substr(1, 1); + if (d.isDigit()) { + if (token.id !== '.') { + warningAt("Don't use extra leading zeros '{a}'.", + line, character, t); + } + } else if (jsonmode && (d === 'x' || d === 'X')) { + warningAt("Avoid 0x-. '{a}'.", + line, character, t); + } + } + if (t.substr(t.length - 1) === '.') { + warningAt( +"A trailing decimal point can be confused with a dot '{a}'.", line, character, t); + } + return it('(number)', t); + } + switch (t) { + + // string + + case '"': + case "'": + return string(t); + + // // comment + + case '//': + s = ''; + token.comment = true; + break; + + // /* comment + + case '/*': + for (;;) { + i = s.search(lx); + if (i >= 0) { + break; + } + if (!nextLine()) { + errorAt("Unclosed comment.", line, character); + } + } + character += i + 2; + if (s.substr(i, 1) === '/') { + errorAt("Nested comment.", line, character); + } + s = s.substr(i + 2); + token.comment = true; + break; + + // /*members /*jshint /*global + + case '/*members': + case '/*member': + case '/*jshint': + case '/*jslint': + case '/*global': + case '*/': + return { + value: t, + type: 'special', + line: line, + character: character, + from: from + }; + + case '': + break; + // / + case '/': + if (token.id === '/=') { + errorAt("A regular expression literal can be confused with '/='.", + line, from); + } + if (prereg) { + depth = 0; + captures = 0; + l = 0; + for (;;) { + b = true; + c = s.charAt(l); + l += 1; + switch (c) { + case '': + errorAt("Unclosed regular expression.", line, from); + return quit('Stopping.', line, from); + case '/': + if (depth > 0) { + warningAt("{a} unterminated regular expression " + + "group(s).", line, from + l, depth); + } + c = s.substr(0, l - 1); + q = { + g: true, + i: true, + m: true + }; + while (q[s.charAt(l)] === true) { + q[s.charAt(l)] = false; + l += 1; + } + character += l; + s = s.substr(l); + q = s.charAt(0); + if (q === '/' || q === '*') { + errorAt("Confusing regular expression.", + line, from); + } + return it('(regexp)', c); + case '\\': + c = s.charAt(l); + if (c < ' ') { + warningAt( +"Unexpected control character in regular expression.", line, from + l); + } else if (c === '<') { + warningAt( +"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); + } + l += 1; + break; + case '(': + depth += 1; + b = false; + if (s.charAt(l) === '?') { + l += 1; + switch (s.charAt(l)) { + case ':': + case '=': + case '!': + l += 1; + break; + default: + warningAt( +"Expected '{a}' and instead saw '{b}'.", line, from + l, ':', s.charAt(l)); + } + } else { + captures += 1; + } + break; + case '|': + b = false; + break; + case ')': + if (depth === 0) { + warningAt("Unescaped '{a}'.", + line, from + l, ')'); + } else { + depth -= 1; + } + break; + case ' ': + q = 1; + while (s.charAt(l) === ' ') { + l += 1; + q += 1; + } + if (q > 1) { + warningAt( +"Spaces are hard to count. Use {{a}}.", line, from + l, q); + } + break; + case '[': + c = s.charAt(l); + if (c === '^') { + l += 1; + if (option.regexp) { + warningAt("Insecure '{a}'.", + line, from + l, c); + } else if (s.charAt(l) === ']') { + errorAt("Unescaped '{a}'.", + line, from + l, '^'); + } + } + if (c === ']') { + warningAt("Empty class.", line, + from + l - 1); + } + isLiteral = false; + isInRange = false; +klass: do { + c = s.charAt(l); + l += 1; + switch (c) { + case '[': + case '^': + warningAt("Unescaped '{a}'.", + line, from + l, c); + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case '-': + if (isLiteral && !isInRange) { + isLiteral = false; + isInRange = true; + } else if (isInRange) { + isInRange = false; + } else if (s.charAt(l) === ']') { + isInRange = true; + } else { + if (option.regexdash !== (l === 2 || (l === 3 && + s.charAt(1) === '^'))) { + warningAt("Unescaped '{a}'.", + line, from + l - 1, '-'); + } + isLiteral = true; + } + break; + case ']': + if (isInRange && !option.regexdash) { + warningAt("Unescaped '{a}'.", + line, from + l - 1, '-'); + } + break klass; + case '\\': + c = s.charAt(l); + if (c < ' ') { + warningAt( +"Unexpected control character in regular expression.", line, from + l); + } else if (c === '<') { + warningAt( +"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); + } + l += 1; + + // \w, \s and \d are never part of a character range + if (/[wsd]/i.test(c)) { + if (isInRange) { + warningAt("Unescaped '{a}'.", + line, from + l, '-'); + isInRange = false; + } + isLiteral = false; + } else if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case '/': + warningAt("Unescaped '{a}'.", + line, from + l - 1, '/'); + + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case '<': + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + default: + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + } + } while (c); + break; + case '.': + if (option.regexp) { + warningAt("Insecure '{a}'.", line, + from + l, c); + } + break; + case ']': + case '?': + case '{': + case '}': + case '+': + case '*': + warningAt("Unescaped '{a}'.", line, + from + l, c); + } + if (b) { + switch (s.charAt(l)) { + case '?': + case '+': + case '*': + l += 1; + if (s.charAt(l) === '?') { + l += 1; + } + break; + case '{': + l += 1; + c = s.charAt(l); + if (c < '0' || c > '9') { + warningAt( +"Expected a number and instead saw '{a}'.", line, from + l, c); + } + l += 1; + low = +c; + for (;;) { + c = s.charAt(l); + if (c < '0' || c > '9') { + break; + } + l += 1; + low = +c + (low * 10); + } + high = low; + if (c === ',') { + l += 1; + high = Infinity; + c = s.charAt(l); + if (c >= '0' && c <= '9') { + l += 1; + high = +c; + for (;;) { + c = s.charAt(l); + if (c < '0' || c > '9') { + break; + } + l += 1; + high = +c + (high * 10); + } + } + } + if (s.charAt(l) !== '}') { + warningAt( +"Expected '{a}' and instead saw '{b}'.", line, from + l, '}', c); + } else { + l += 1; + } + if (s.charAt(l) === '?') { + l += 1; + } + if (low > high) { + warningAt( +"'{a}' should not be greater than '{b}'.", line, from + l, low, high); + } + } + } + } + c = s.substr(0, l - 1); + character += l; + s = s.substr(l); + return it('(regexp)', c); + } + return it('(punctuator)', t); + + // punctuator + + case '#': + return it('(punctuator)', t); + default: + return it('(punctuator)', t); + } + } + } + } + }; + }()); + + + function addlabel(t, type) { + + if (t === 'hasOwnProperty') { + warning("'hasOwnProperty' is a really bad name."); + } + +// Define t in the current function in the current scope. + if (is_own(funct, t) && !funct['(global)']) { + if (funct[t] === true) { + if (option.latedef) + warning("'{a}' was used before it was defined.", nexttoken, t); + } else { + if (!option.shadow && type !== "exception") + warning("'{a}' is already defined.", nexttoken, t); + } + } + + funct[t] = type; + if (funct['(global)']) { + global[t] = funct; + if (is_own(implied, t)) { + if (option.latedef) + warning("'{a}' was used before it was defined.", nexttoken, t); + delete implied[t]; + } + } else { + scope[t] = funct; + } + } + + + function doOption() { + var b, obj, filter, o = nexttoken.value, t, v; + + switch (o) { + case '*/': + error("Unbegun comment."); + break; + case '/*members': + case '/*member': + o = '/*members'; + if (!membersOnly) { + membersOnly = {}; + } + obj = membersOnly; + break; + case '/*jshint': + case '/*jslint': + obj = option; + filter = boolOptions; + break; + case '/*global': + obj = predefined; + break; + default: + error("What?"); + } + + t = lex.token(); +loop: for (;;) { + for (;;) { + if (t.type === 'special' && t.value === '*/') { + break loop; + } + if (t.id !== '(endline)' && t.id !== ',') { + break; + } + t = lex.token(); + } + if (t.type !== '(string)' && t.type !== '(identifier)' && + o !== '/*members') { + error("Bad option.", t); + } + + v = lex.token(); + if (v.id === ':') { + v = lex.token(); + + if (obj === membersOnly) { + error("Expected '{a}' and instead saw '{b}'.", + t, '*/', ':'); + } + + if (o === '/*jshint') { + checkOption(t.value, t); + } + + if (t.value === 'indent' && (o === '/*jshint' || o === '/*jslint')) { + b = +v.value; + if (typeof b !== 'number' || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.white = true; + obj.indent = b; + } else if (t.value === 'maxerr' && (o === '/*jshint' || o === '/*jslint')) { + b = +v.value; + if (typeof b !== 'number' || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.maxerr = b; + } else if (t.value === 'maxlen' && (o === '/*jshint' || o === '/*jslint')) { + b = +v.value; + if (typeof b !== 'number' || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.maxlen = b; + } else if (t.value === 'validthis') { + if (funct['(global)']) { + error("Option 'validthis' can't be used in a global scope."); + } else { + if (v.value === 'true' || v.value === 'false') + obj[t.value] = v.value === 'true'; + else + error("Bad option value.", v); + } + } else if (v.value === 'true') { + obj[t.value] = true; + } else if (v.value === 'false') { + obj[t.value] = false; + } else { + error("Bad option value.", v); + } + t = lex.token(); + } else { + if (o === '/*jshint' || o === '/*jslint') { + error("Missing option value.", t); + } + obj[t.value] = false; + t = v; + } + } + if (filter) { + assume(); + } + } + + +// We need a peek function. If it has an argument, it peeks that much farther +// ahead. It is used to distinguish +// for ( var i in ... +// from +// for ( var i = ... + + function peek(p) { + var i = p || 0, j = 0, t; + + while (j <= i) { + t = lookahead[j]; + if (!t) { + t = lookahead[j] = lex.token(); + } + j += 1; + } + return t; + } + + + +// Produce the next token. It looks for programming errors. + + function advance(id, t) { + switch (token.id) { + case '(number)': + if (nexttoken.id === '.') { + warning("A dot following a number can be confused with a decimal point.", token); + } + break; + case '-': + if (nexttoken.id === '-' || nexttoken.id === '--') { + warning("Confusing minusses."); + } + break; + case '+': + if (nexttoken.id === '+' || nexttoken.id === '++') { + warning("Confusing plusses."); + } + break; + } + + if (token.type === '(string)' || token.identifier) { + anonname = token.value; + } + + if (id && nexttoken.id !== id) { + if (t) { + if (nexttoken.id === '(end)') { + warning("Unmatched '{a}'.", t, t.id); + } else { + warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.", + nexttoken, id, t.id, t.line, nexttoken.value); + } + } else if (nexttoken.type !== '(identifier)' || + nexttoken.value !== id) { + warning("Expected '{a}' and instead saw '{b}'.", + nexttoken, id, nexttoken.value); + } + } + + prevtoken = token; + token = nexttoken; + for (;;) { + nexttoken = lookahead.shift() || lex.token(); + if (nexttoken.id === '(end)' || nexttoken.id === '(error)') { + return; + } + if (nexttoken.type === 'special') { + doOption(); + } else { + if (nexttoken.id !== '(endline)') { + break; + } + } + } + } + + +// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it +// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is +// like .nud except that it is only used on the first token of a statement. +// Having .fud makes it much easier to define statement-oriented languages like +// JavaScript. I retained Pratt's nomenclature. + +// .nud Null denotation +// .fud First null denotation +// .led Left denotation +// lbp Left binding power +// rbp Right binding power + +// They are elements of the parsing method called Top Down Operator Precedence. + + function expression(rbp, initial) { + var left, isArray = false, isObject = false; + + if (nexttoken.id === '(end)') + error("Unexpected early end of program.", token); + + advance(); + if (initial) { + anonname = 'anonymous'; + funct['(verb)'] = token.value; + } + if (initial === true && token.fud) { + left = token.fud(); + } else { + if (token.nud) { + left = token.nud(); + } else { + if (nexttoken.type === '(number)' && token.id === '.') { + warning("A leading decimal point can be confused with a dot: '.{a}'.", + token, nexttoken.value); + advance(); + return token; + } else { + error("Expected an identifier and instead saw '{a}'.", + token, token.id); + } + } + while (rbp < nexttoken.lbp) { + isArray = token.value === 'Array'; + isObject = token.value === 'Object'; + advance(); + if (isArray && token.id === '(' && nexttoken.id === ')') + warning("Use the array literal notation [].", token); + if (isObject && token.id === '(' && nexttoken.id === ')') + warning("Use the object literal notation {}.", token); + if (token.led) { + left = token.led(left); + } else { + error("Expected an operator and instead saw '{a}'.", + token, token.id); + } + } + } + return left; + } + + +// Functions for conformance of style. + + function adjacent(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white) { + if (left.character !== right.from && left.line === right.line) { + left.from += (left.character - left.from); + warning("Unexpected space after '{a}'.", left, left.value); + } + } + } + + function nobreak(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white && (left.character !== right.from || left.line !== right.line)) { + warning("Unexpected space before '{a}'.", right, right.value); + } + } + + function nospace(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white && !left.comment) { + if (left.line === right.line) { + adjacent(left, right); + } + } + } + + function nonadjacent(left, right) { + if (option.white) { + left = left || token; + right = right || nexttoken; + if (left.line === right.line && left.character === right.from) { + left.from += (left.character - left.from); + warning("Missing space after '{a}'.", + left, left.value); + } + } + } + + function nobreaknonadjacent(left, right) { + left = left || token; + right = right || nexttoken; + if (!option.laxbreak && left.line !== right.line) { + warning("Bad line breaking before '{a}'.", right, right.id); + } else if (option.white) { + left = left || token; + right = right || nexttoken; + if (left.character === right.from) { + left.from += (left.character - left.from); + warning("Missing space after '{a}'.", + left, left.value); + } + } + } + + function indentation(bias) { + var i; + if (option.white && nexttoken.id !== '(end)') { + i = indent + (bias || 0); + if (nexttoken.from !== i) { + warning( +"Expected '{a}' to have an indentation at {b} instead at {c}.", + nexttoken, nexttoken.value, i, nexttoken.from); + } + } + } + + function nolinebreak(t) { + t = t || token; + if (t.line !== nexttoken.line) { + warning("Line breaking error '{a}'.", t, t.value); + } + } + + + function comma() { + if (token.line !== nexttoken.line) { + if (!option.laxcomma) { + if (comma.first) { + warning("Comma warnings can be turned off with 'laxcomma'"); + comma.first = false; + } + warning("Bad line breaking before '{a}'.", token, nexttoken.id); + } + } else if (!token.comment && token.character !== nexttoken.from && option.white) { + token.from += (token.character - token.from); + warning("Unexpected space after '{a}'.", token, token.value); + } + advance(','); + nonadjacent(token, nexttoken); + } + + +// Functional constructors for making the symbols that will be inherited by +// tokens. + + function symbol(s, p) { + var x = syntax[s]; + if (!x || typeof x !== 'object') { + syntax[s] = x = { + id: s, + lbp: p, + value: s + }; + } + return x; + } + + + function delim(s) { + return symbol(s, 0); + } + + + function stmt(s, f) { + var x = delim(s); + x.identifier = x.reserved = true; + x.fud = f; + return x; + } + + + function blockstmt(s, f) { + var x = stmt(s, f); + x.block = true; + return x; + } + + + function reserveName(x) { + var c = x.id.charAt(0); + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + x.identifier = x.reserved = true; + } + return x; + } + + + function prefix(s, f) { + var x = symbol(s, 150); + reserveName(x); + x.nud = (typeof f === 'function') ? f : function () { + this.right = expression(150); + this.arity = 'unary'; + if (this.id === '++' || this.id === '--') { + if (option.plusplus) { + warning("Unexpected use of '{a}'.", this, this.id); + } else if ((!this.right.identifier || this.right.reserved) && + this.right.id !== '.' && this.right.id !== '[') { + warning("Bad operand.", this); + } + } + return this; + }; + return x; + } + + + function type(s, f) { + var x = delim(s); + x.type = s; + x.nud = f; + return x; + } + + + function reserve(s, f) { + var x = type(s, f); + x.identifier = x.reserved = true; + return x; + } + + + function reservevar(s, v) { + return reserve(s, function () { + if (typeof v === 'function') { + v(this); + } + return this; + }); + } + + + function infix(s, f, p, w) { + var x = symbol(s, p); + reserveName(x); + x.led = function (left) { + if (!w) { + nobreaknonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + } + if (s === "in" && left.id === "!") { + warning("Confusing use of '{a}'.", left, '!'); + } + if (typeof f === 'function') { + return f(left, this); + } else { + this.left = left; + this.right = expression(p); + return this; + } + }; + return x; + } + + + function relation(s, f) { + var x = symbol(s, 100); + x.led = function (left) { + nobreaknonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + var right = expression(100); + if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) { + warning("Use the isNaN function to compare with NaN.", this); + } else if (f) { + f.apply(this, [left, right]); + } + if (left.id === '!') { + warning("Confusing use of '{a}'.", left, '!'); + } + if (right.id === '!') { + warning("Confusing use of '{a}'.", right, '!'); + } + this.left = left; + this.right = right; + return this; + }; + return x; + } + + + function isPoorRelation(node) { + return node && + ((node.type === '(number)' && +node.value === 0) || + (node.type === '(string)' && node.value === '') || + (node.type === 'null' && !option.eqnull) || + node.type === 'true' || + node.type === 'false' || + node.type === 'undefined'); + } + + + function assignop(s, f) { + symbol(s, 20).exps = true; + return infix(s, function (left, that) { + var l; + that.left = left; + if (predefined[left.value] === false && + scope[left.value]['(global)'] === true) { + warning("Read only.", left); + } else if (left['function']) { + warning("'{a}' is a function.", left, left.value); + } + if (left) { + if (option.esnext && funct[left.value] === 'const') { + warning("Attempting to override '{a}' which is a constant", left, left.value); + } + if (left.id === '.' || left.id === '[') { + if (!left.left || left.left.value === 'arguments') { + warning('Bad assignment.', that); + } + that.right = expression(19); + return that; + } else if (left.identifier && !left.reserved) { + if (funct[left.value] === 'exception') { + warning("Do not assign to the exception parameter.", left); + } + that.right = expression(19); + return that; + } + if (left === syntax['function']) { + warning( +"Expected an identifier in an assignment and instead saw a function invocation.", + token); + } + } + error("Bad assignment.", that); + }, 20); + } + + + function bitwise(s, f, p) { + var x = symbol(s, p); + reserveName(x); + x.led = (typeof f === 'function') ? f : function (left) { + if (option.bitwise) { + warning("Unexpected use of '{a}'.", this, this.id); + } + this.left = left; + this.right = expression(p); + return this; + }; + return x; + } + + + function bitwiseassignop(s) { + symbol(s, 20).exps = true; + return infix(s, function (left, that) { + if (option.bitwise) { + warning("Unexpected use of '{a}'.", that, that.id); + } + nonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + if (left) { + if (left.id === '.' || left.id === '[' || + (left.identifier && !left.reserved)) { + expression(19); + return that; + } + if (left === syntax['function']) { + warning( +"Expected an identifier in an assignment, and instead saw a function invocation.", + token); + } + return that; + } + error("Bad assignment.", that); + }, 20); + } + + + function suffix(s, f) { + var x = symbol(s, 150); + x.led = function (left) { + if (option.plusplus) { + warning("Unexpected use of '{a}'.", this, this.id); + } else if ((!left.identifier || left.reserved) && + left.id !== '.' && left.id !== '[') { + warning("Bad operand.", this); + } + this.left = left; + return this; + }; + return x; + } + + + // fnparam means that this identifier is being defined as a function + // argument (see identifier()) + function optionalidentifier(fnparam) { + if (nexttoken.identifier) { + advance(); + if (token.reserved && !option.es5) { + // `undefined` as a function param is a common pattern to protect + // against the case when somebody does `undefined = true` and + // help with minification. More info: https://gist.github.com/315916 + if (!fnparam || token.value !== 'undefined') { + warning("Expected an identifier and instead saw '{a}' (a reserved word).", + token, token.id); + } + } + return token.value; + } + } + + // fnparam means that this identifier is being defined as a function + // argument + function identifier(fnparam) { + var i = optionalidentifier(fnparam); + if (i) { + return i; + } + if (token.id === 'function' && nexttoken.id === '(') { + warning("Missing name in function declaration."); + } else { + error("Expected an identifier and instead saw '{a}'.", + nexttoken, nexttoken.value); + } + } + + + function reachable(s) { + var i = 0, t; + if (nexttoken.id !== ';' || noreach) { + return; + } + for (;;) { + t = peek(i); + if (t.reach) { + return; + } + if (t.id !== '(endline)') { + if (t.id === 'function') { + if (!option.latedef) { + break; + } + warning( +"Inner functions should be listed at the top of the outer function.", t); + break; + } + warning("Unreachable '{a}' after '{b}'.", t, t.value, s); + break; + } + i += 1; + } + } + + + function statement(noindent) { + var i = indent, r, s = scope, t = nexttoken; + + if (t.id === ";") { + advance(";"); + return; + } + +// Is this a labelled statement? + + if (t.identifier && !t.reserved && peek().id === ':') { + advance(); + advance(':'); + scope = Object.create(s); + addlabel(t.value, 'label'); + if (!nexttoken.labelled) { + warning("Label '{a}' on {b} statement.", + nexttoken, t.value, nexttoken.value); + } + if (jx.test(t.value + ':')) { + warning("Label '{a}' looks like a javascript url.", + t, t.value); + } + nexttoken.label = t.value; + t = nexttoken; + } + +// Parse the statement. + + if (!noindent) { + indentation(); + } + r = expression(0, true); + + // Look for the final semicolon. + if (!t.block) { + if (!option.expr && (!r || !r.exps)) { + warning("Expected an assignment or function call and instead saw an expression.", + token); + } else if (option.nonew && r.id === '(' && r.left.id === 'new') { + warning("Do not use 'new' for side effects."); + } + + if (nexttoken.id === ',') { + return comma(); + } + + if (nexttoken.id !== ';') { + if (!option.asi) { + // If this is the last statement in a block that ends on + // the same line *and* option lastsemic is on, ignore the warning. + // Otherwise, complain about missing semicolon. + if (!option.lastsemic || nexttoken.id !== '}' || + nexttoken.line !== token.line) { + warningAt("Missing semicolon.", token.line, token.character); + } + } + } else { + adjacent(token, nexttoken); + advance(';'); + nonadjacent(token, nexttoken); + } + } + +// Restore the indentation. + + indent = i; + scope = s; + return r; + } + + + function statements(startLine) { + var a = [], f, p; + + while (!nexttoken.reach && nexttoken.id !== '(end)') { + if (nexttoken.id === ';') { + p = peek(); + if (!p || p.id !== "(") { + warning("Unnecessary semicolon."); + } + advance(';'); + } else { + a.push(statement(startLine === nexttoken.line)); + } + } + return a; + } + + + /* + * read all directives + * recognizes a simple form of asi, but always + * warns, if it is used + */ + function directives() { + var i, p, pn; + + for (;;) { + if (nexttoken.id === "(string)") { + p = peek(0); + if (p.id === "(endline)") { + i = 1; + do { + pn = peek(i); + i = i + 1; + } while (pn.id === "(endline)"); + + if (pn.id !== ";") { + if (pn.id !== "(string)" && pn.id !== "(number)" && + pn.id !== "(regexp)" && pn.identifier !== true && + pn.id !== "}") { + break; + } + warning("Missing semicolon.", nexttoken); + } else { + p = pn; + } + } else if (p.id === "}") { + // directive with no other statements, warn about missing semicolon + warning("Missing semicolon.", p); + } else if (p.id !== ";") { + break; + } + + indentation(); + advance(); + if (directive[token.value]) { + warning("Unnecessary directive \"{a}\".", token, token.value); + } + + if (token.value === "use strict") { + option.newcap = true; + option.undef = true; + } + + // there's no directive negation, so always set to true + directive[token.value] = true; + + if (p.id === ";") { + advance(";"); + } + continue; + } + break; + } + } + + + /* + * Parses a single block. A block is a sequence of statements wrapped in + * braces. + * + * ordinary - true for everything but function bodies and try blocks. + * stmt - true if block can be a single statement (e.g. in if/for/while). + * isfunc - true if block is a function body + */ + function block(ordinary, stmt, isfunc) { + var a, + b = inblock, + old_indent = indent, + m, + s = scope, + t, + line, + d; + + inblock = ordinary; + if (!ordinary || !option.funcscope) scope = Object.create(scope); + nonadjacent(token, nexttoken); + t = nexttoken; + + if (nexttoken.id === '{') { + advance('{'); + line = token.line; + if (nexttoken.id !== '}') { + indent += option.indent; + while (!ordinary && nexttoken.from > indent) { + indent += option.indent; + } + + if (isfunc) { + m = {}; + for (d in directive) { + if (is_own(directive, d)) { + m[d] = directive[d]; + } + } + directives(); + + if (option.strict && funct['(context)']['(global)']) { + if (!m["use strict"] && !directive["use strict"]) { + warning("Missing \"use strict\" statement."); + } + } + } + + a = statements(line); + + if (isfunc) { + directive = m; + } + + indent -= option.indent; + if (line !== nexttoken.line) { + indentation(); + } + } else if (line !== nexttoken.line) { + indentation(); + } + advance('}', t); + indent = old_indent; + } else if (!ordinary) { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, '{', nexttoken.value); + } else { + if (!stmt || option.curly) + warning("Expected '{a}' and instead saw '{b}'.", + nexttoken, '{', nexttoken.value); + + noreach = true; + indent += option.indent; + // test indentation only if statement is in new line + a = [statement(nexttoken.line === token.line)]; + indent -= option.indent; + noreach = false; + } + funct['(verb)'] = null; + if (!ordinary || !option.funcscope) scope = s; + inblock = b; + if (ordinary && option.noempty && (!a || a.length === 0)) { + warning("Empty block."); + } + return a; + } + + + function countMember(m) { + if (membersOnly && typeof membersOnly[m] !== 'boolean') { + warning("Unexpected /*member '{a}'.", token, m); + } + if (typeof member[m] === 'number') { + member[m] += 1; + } else { + member[m] = 1; + } + } + + + function note_implied(token) { + var name = token.value, line = token.line, a = implied[name]; + if (typeof a === 'function') { + a = false; + } + + if (!a) { + a = [line]; + implied[name] = a; + } else if (a[a.length - 1] !== line) { + a.push(line); + } + } + + + // Build the syntax table by declaring the syntactic elements of the language. + + type('(number)', function () { + return this; + }); + + type('(string)', function () { + return this; + }); + + syntax['(identifier)'] = { + type: '(identifier)', + lbp: 0, + identifier: true, + nud: function () { + var v = this.value, + s = scope[v], + f; + + if (typeof s === 'function') { + // Protection against accidental inheritance. + s = undefined; + } else if (typeof s === 'boolean') { + f = funct; + funct = functions[0]; + addlabel(v, 'var'); + s = funct; + funct = f; + } + + // The name is in scope and defined in the current function. + if (funct === s) { + // Change 'unused' to 'var', and reject labels. + switch (funct[v]) { + case 'unused': + funct[v] = 'var'; + break; + case 'unction': + funct[v] = 'function'; + this['function'] = true; + break; + case 'function': + this['function'] = true; + break; + case 'label': + warning("'{a}' is a statement label.", token, v); + break; + } + } else if (funct['(global)']) { + // The name is not defined in the function. If we are in the global + // scope, then we have an undefined variable. + // + // Operators typeof and delete do not raise runtime errors even if + // the base object of a reference is null so no need to display warning + // if we're inside of typeof or delete. + + if (option.undef && typeof predefined[v] !== 'boolean') { + // Attempting to subscript a null reference will throw an + // error, even within the typeof and delete operators + if (!(anonname === 'typeof' || anonname === 'delete') || + (nexttoken && (nexttoken.value === '.' || nexttoken.value === '['))) { + + isundef(funct, "'{a}' is not defined.", token, v); + } + } + note_implied(token); + } else { + // If the name is already defined in the current + // function, but not as outer, then there is a scope error. + + switch (funct[v]) { + case 'closure': + case 'function': + case 'var': + case 'unused': + warning("'{a}' used out of scope.", token, v); + break; + case 'label': + warning("'{a}' is a statement label.", token, v); + break; + case 'outer': + case 'global': + break; + default: + // If the name is defined in an outer function, make an outer entry, + // and if it was unused, make it var. + if (s === true) { + funct[v] = true; + } else if (s === null) { + warning("'{a}' is not allowed.", token, v); + note_implied(token); + } else if (typeof s !== 'object') { + // Operators typeof and delete do not raise runtime errors even + // if the base object of a reference is null so no need to + // display warning if we're inside of typeof or delete. + if (option.undef) { + // Attempting to subscript a null reference will throw an + // error, even within the typeof and delete operators + if (!(anonname === 'typeof' || anonname === 'delete') || + (nexttoken && + (nexttoken.value === '.' || nexttoken.value === '['))) { + + isundef(funct, "'{a}' is not defined.", token, v); + } + } + funct[v] = true; + note_implied(token); + } else { + switch (s[v]) { + case 'function': + case 'unction': + this['function'] = true; + s[v] = 'closure'; + funct[v] = s['(global)'] ? 'global' : 'outer'; + break; + case 'var': + case 'unused': + s[v] = 'closure'; + funct[v] = s['(global)'] ? 'global' : 'outer'; + break; + case 'closure': + case 'parameter': + funct[v] = s['(global)'] ? 'global' : 'outer'; + break; + case 'label': + warning("'{a}' is a statement label.", token, v); + } + } + } + } + return this; + }, + led: function () { + error("Expected an operator and instead saw '{a}'.", + nexttoken, nexttoken.value); + } + }; + + type('(regexp)', function () { + return this; + }); + + +// ECMAScript parser + + delim('(endline)'); + delim('(begin)'); + delim('(end)').reach = true; + delim(''); + delim('(error)').reach = true; + delim('}').reach = true; + delim(')'); + delim(']'); + delim('"').reach = true; + delim("'").reach = true; + delim(';'); + delim(':').reach = true; + delim(','); + delim('#'); + delim('@'); + reserve('else'); + reserve('case').reach = true; + reserve('catch'); + reserve('default').reach = true; + reserve('finally'); + reservevar('arguments', function (x) { + if (directive['use strict'] && funct['(global)']) { + warning("Strict violation.", x); + } + }); + reservevar('eval'); + reservevar('false'); + reservevar('Infinity'); + reservevar('NaN'); + reservevar('null'); + reservevar('this', function (x) { + if (directive['use strict'] && !option.validthis && ((funct['(statement)'] && + funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) { + warning("Possible strict violation.", x); + } + }); + reservevar('true'); + reservevar('undefined'); + assignop('=', 'assign', 20); + assignop('+=', 'assignadd', 20); + assignop('-=', 'assignsub', 20); + assignop('*=', 'assignmult', 20); + assignop('/=', 'assigndiv', 20).nud = function () { + error("A regular expression literal can be confused with '/='."); + }; + assignop('%=', 'assignmod', 20); + bitwiseassignop('&=', 'assignbitand', 20); + bitwiseassignop('|=', 'assignbitor', 20); + bitwiseassignop('^=', 'assignbitxor', 20); + bitwiseassignop('<<=', 'assignshiftleft', 20); + bitwiseassignop('>>=', 'assignshiftright', 20); + bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20); + infix('?', function (left, that) { + that.left = left; + that.right = expression(10); + advance(':'); + that['else'] = expression(10); + return that; + }, 30); + + infix('||', 'or', 40); + infix('&&', 'and', 50); + bitwise('|', 'bitor', 70); + bitwise('^', 'bitxor', 80); + bitwise('&', 'bitand', 90); + relation('==', function (left, right) { + var eqnull = option.eqnull && (left.value === 'null' || right.value === 'null'); + + if (!eqnull && option.eqeqeq) + warning("Expected '{a}' and instead saw '{b}'.", this, '===', '=='); + else if (isPoorRelation(left)) + warning("Use '{a}' to compare with '{b}'.", this, '===', left.value); + else if (isPoorRelation(right)) + warning("Use '{a}' to compare with '{b}'.", this, '===', right.value); + + return this; + }); + relation('==='); + relation('!=', function (left, right) { + var eqnull = option.eqnull && + (left.value === 'null' || right.value === 'null'); + + if (!eqnull && option.eqeqeq) { + warning("Expected '{a}' and instead saw '{b}'.", + this, '!==', '!='); + } else if (isPoorRelation(left)) { + warning("Use '{a}' to compare with '{b}'.", + this, '!==', left.value); + } else if (isPoorRelation(right)) { + warning("Use '{a}' to compare with '{b}'.", + this, '!==', right.value); + } + return this; + }); + relation('!=='); + relation('<'); + relation('>'); + relation('<='); + relation('>='); + bitwise('<<', 'shiftleft', 120); + bitwise('>>', 'shiftright', 120); + bitwise('>>>', 'shiftrightunsigned', 120); + infix('in', 'in', 120); + infix('instanceof', 'instanceof', 120); + infix('+', function (left, that) { + var right = expression(130); + if (left && right && left.id === '(string)' && right.id === '(string)') { + left.value += right.value; + left.character = right.character; + if (!option.scripturl && jx.test(left.value)) { + warning("JavaScript URL.", left); + } + return left; + } + that.left = left; + that.right = right; + return that; + }, 130); + prefix('+', 'num'); + prefix('+++', function () { + warning("Confusing pluses."); + this.right = expression(150); + this.arity = 'unary'; + return this; + }); + infix('+++', function (left) { + warning("Confusing pluses."); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix('-', 'sub', 130); + prefix('-', 'neg'); + prefix('---', function () { + warning("Confusing minuses."); + this.right = expression(150); + this.arity = 'unary'; + return this; + }); + infix('---', function (left) { + warning("Confusing minuses."); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix('*', 'mult', 140); + infix('/', 'div', 140); + infix('%', 'mod', 140); + + suffix('++', 'postinc'); + prefix('++', 'preinc'); + syntax['++'].exps = true; + + suffix('--', 'postdec'); + prefix('--', 'predec'); + syntax['--'].exps = true; + prefix('delete', function () { + var p = expression(0); + if (!p || (p.id !== '.' && p.id !== '[')) { + warning("Variables should not be deleted."); + } + this.first = p; + return this; + }).exps = true; + + prefix('~', function () { + if (option.bitwise) { + warning("Unexpected '{a}'.", this, '~'); + } + expression(150); + return this; + }); + + prefix('!', function () { + this.right = expression(150); + this.arity = 'unary'; + if (bang[this.right.id] === true) { + warning("Confusing use of '{a}'.", this, '!'); + } + return this; + }); + prefix('typeof', 'typeof'); + prefix('new', function () { + var c = expression(155), i; + if (c && c.id !== 'function') { + if (c.identifier) { + c['new'] = true; + switch (c.value) { + case 'Number': + case 'String': + case 'Boolean': + case 'Math': + case 'JSON': + warning("Do not use {a} as a constructor.", token, c.value); + break; + case 'Function': + if (!option.evil) { + warning("The Function constructor is eval."); + } + break; + case 'Date': + case 'RegExp': + break; + default: + if (c.id !== 'function') { + i = c.value.substr(0, 1); + if (option.newcap && (i < 'A' || i > 'Z')) { + warning("A constructor name should start with an uppercase letter.", + token); + } + } + } + } else { + if (c.id !== '.' && c.id !== '[' && c.id !== '(') { + warning("Bad constructor.", token); + } + } + } else { + if (!option.supernew) + warning("Weird construction. Delete 'new'.", this); + } + adjacent(token, nexttoken); + if (nexttoken.id !== '(' && !option.supernew) { + warning("Missing '()' invoking a constructor."); + } + this.first = c; + return this; + }); + syntax['new'].exps = true; + + prefix('void').exps = true; + + infix('.', function (left, that) { + adjacent(prevtoken, token); + nobreak(); + var m = identifier(); + if (typeof m === 'string') { + countMember(m); + } + that.left = left; + that.right = m; + if (left && left.value === 'arguments' && (m === 'callee' || m === 'caller')) { + if (option.noarg) + warning("Avoid arguments.{a}.", left, m); + else if (directive['use strict']) + error('Strict violation.'); + } else if (!option.evil && left && left.value === 'document' && + (m === 'write' || m === 'writeln')) { + warning("document.write can be a form of eval.", left); + } + if (!option.evil && (m === 'eval' || m === 'execScript')) { + warning('eval is evil.'); + } + return that; + }, 160, true); + + infix('(', function (left, that) { + if (prevtoken.id !== '}' && prevtoken.id !== ')') { + nobreak(prevtoken, token); + } + nospace(); + if (option.immed && !left.immed && left.id === 'function') { + warning("Wrap an immediate function invocation in parentheses " + + "to assist the reader in understanding that the expression " + + "is the result of a function, and not the function itself."); + } + var n = 0, + p = []; + if (left) { + if (left.type === '(identifier)') { + if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) { + if (left.value !== 'Number' && left.value !== 'String' && + left.value !== 'Boolean' && + left.value !== 'Date') { + if (left.value === 'Math') { + warning("Math is not a function.", left); + } else if (option.newcap) { + warning( +"Missing 'new' prefix when invoking a constructor.", left); + } + } + } + } + } + if (nexttoken.id !== ')') { + for (;;) { + p[p.length] = expression(10); + n += 1; + if (nexttoken.id !== ',') { + break; + } + comma(); + } + } + advance(')'); + nospace(prevtoken, token); + if (typeof left === 'object') { + if (left.value === 'parseInt' && n === 1) { + warning("Missing radix parameter.", left); + } + if (!option.evil) { + if (left.value === 'eval' || left.value === 'Function' || + left.value === 'execScript') { + warning("eval is evil.", left); + } else if (p[0] && p[0].id === '(string)' && + (left.value === 'setTimeout' || + left.value === 'setInterval')) { + warning( + "Implied eval is evil. Pass a function instead of a string.", left); + } + } + if (!left.identifier && left.id !== '.' && left.id !== '[' && + left.id !== '(' && left.id !== '&&' && left.id !== '||' && + left.id !== '?') { + warning("Bad invocation.", left); + } + } + that.left = left; + return that; + }, 155, true).exps = true; + + prefix('(', function () { + nospace(); + if (nexttoken.id === 'function') { + nexttoken.immed = true; + } + var v = expression(0); + advance(')', this); + nospace(prevtoken, token); + if (option.immed && v.id === 'function') { + if (nexttoken.id === '(' || + (nexttoken.id === '.' && (peek().value === 'call' || peek().value === 'apply'))) { + warning( +"Move the invocation into the parens that contain the function.", nexttoken); + } else { + warning( +"Do not wrap function literals in parens unless they are to be immediately invoked.", + this); + } + } + return v; + }); + + infix('[', function (left, that) { + nobreak(prevtoken, token); + nospace(); + var e = expression(0), s; + if (e && e.type === '(string)') { + if (!option.evil && (e.value === 'eval' || e.value === 'execScript')) { + warning("eval is evil.", that); + } + countMember(e.value); + if (!option.sub && ix.test(e.value)) { + s = syntax[e.value]; + if (!s || !s.reserved) { + warning("['{a}'] is better written in dot notation.", + e, e.value); + } + } + } + advance(']', that); + nospace(prevtoken, token); + that.left = left; + that.right = e; + return that; + }, 160, true); + + prefix('[', function () { + var b = token.line !== nexttoken.line; + this.first = []; + if (b) { + indent += option.indent; + if (nexttoken.from === indent + option.indent) { + indent += option.indent; + } + } + while (nexttoken.id !== '(end)') { + while (nexttoken.id === ',') { + warning("Extra comma."); + advance(','); + } + if (nexttoken.id === ']') { + break; + } + if (b && token.line !== nexttoken.line) { + indentation(); + } + this.first.push(expression(10)); + if (nexttoken.id === ',') { + comma(); + if (nexttoken.id === ']' && !option.es5) { + warning("Extra comma.", token); + break; + } + } else { + break; + } + } + if (b) { + indent -= option.indent; + indentation(); + } + advance(']', this); + return this; + }, 160); + + + function property_name() { + var id = optionalidentifier(true); + if (!id) { + if (nexttoken.id === '(string)') { + id = nexttoken.value; + advance(); + } else if (nexttoken.id === '(number)') { + id = nexttoken.value.toString(); + advance(); + } + } + return id; + } + + + function functionparams() { + var i, t = nexttoken, p = []; + advance('('); + nospace(); + if (nexttoken.id === ')') { + advance(')'); + return; + } + for (;;) { + i = identifier(true); + p.push(i); + addlabel(i, 'parameter'); + if (nexttoken.id === ',') { + comma(); + } else { + advance(')', t); + nospace(prevtoken, token); + return p; + } + } + } + + + function doFunction(i, statement) { + var f, + oldOption = option, + oldScope = scope; + + option = Object.create(option); + scope = Object.create(scope); + + funct = { + '(name)' : i || '"' + anonname + '"', + '(line)' : nexttoken.line, + '(context)' : funct, + '(breakage)' : 0, + '(loopage)' : 0, + '(scope)' : scope, + '(statement)': statement + }; + f = funct; + token.funct = funct; + functions.push(funct); + if (i) { + addlabel(i, 'function'); + } + funct['(params)'] = functionparams(); + + block(false, false, true); + scope = oldScope; + option = oldOption; + funct['(last)'] = token.line; + funct = funct['(context)']; + return f; + } + + + (function (x) { + x.nud = function () { + var b, f, i, j, p, t; + var props = {}; // All properties, including accessors + + function saveProperty(name, token) { + if (props[name] && is_own(props, name)) + warning("Duplicate member '{a}'.", nexttoken, i); + else + props[name] = {}; + + props[name].basic = true; + props[name].basicToken = token; + } + + function saveSetter(name, token) { + if (props[name] && is_own(props, name)) { + if (props[name].basic || props[name].setter) + warning("Duplicate member '{a}'.", nexttoken, i); + } else { + props[name] = {}; + } + + props[name].setter = true; + props[name].setterToken = token; + } + + function saveGetter(name) { + if (props[name] && is_own(props, name)) { + if (props[name].basic || props[name].getter) + warning("Duplicate member '{a}'.", nexttoken, i); + } else { + props[name] = {}; + } + + props[name].getter = true; + props[name].getterToken = token; + } + + b = token.line !== nexttoken.line; + if (b) { + indent += option.indent; + if (nexttoken.from === indent + option.indent) { + indent += option.indent; + } + } + for (;;) { + if (nexttoken.id === '}') { + break; + } + if (b) { + indentation(); + } + if (nexttoken.value === 'get' && peek().id !== ':') { + advance('get'); + if (!option.es5) { + error("get/set are ES5 features."); + } + i = property_name(); + if (!i) { + error("Missing property name."); + } + saveGetter(i); + t = nexttoken; + adjacent(token, nexttoken); + f = doFunction(); + p = f['(params)']; + if (p) { + warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i); + } + adjacent(token, nexttoken); + } else if (nexttoken.value === 'set' && peek().id !== ':') { + advance('set'); + if (!option.es5) { + error("get/set are ES5 features."); + } + i = property_name(); + if (!i) { + error("Missing property name."); + } + saveSetter(i, nexttoken); + t = nexttoken; + adjacent(token, nexttoken); + f = doFunction(); + p = f['(params)']; + if (!p || p.length !== 1) { + warning("Expected a single parameter in set {a} function.", t, i); + } + } else { + i = property_name(); + saveProperty(i, nexttoken); + if (typeof i !== 'string') { + break; + } + advance(':'); + nonadjacent(token, nexttoken); + expression(10); + } + + countMember(i); + if (nexttoken.id === ',') { + comma(); + if (nexttoken.id === ',') { + warning("Extra comma.", token); + } else if (nexttoken.id === '}' && !option.es5) { + warning("Extra comma.", token); + } + } else { + break; + } + } + if (b) { + indent -= option.indent; + indentation(); + } + advance('}', this); + + // Check for lonely setters if in the ES5 mode. + if (option.es5) { + for (var name in props) { + if (is_own(props, name) && props[name].setter && !props[name].getter) { + warning("Setter is defined without getter.", props[name].setterToken); + } + } + } + return this; + }; + x.fud = function () { + error("Expected to see a statement and instead saw a block.", token); + }; + }(delim('{'))); + +// This Function is called when esnext option is set to true +// it adds the `const` statement to JSHINT + + useESNextSyntax = function () { + var conststatement = stmt('const', function (prefix) { + var id, name, value; + + this.first = []; + for (;;) { + nonadjacent(token, nexttoken); + id = identifier(); + if (funct[id] === "const") { + warning("const '" + id + "' has already been declared"); + } + if (funct['(global)'] && predefined[id] === false) { + warning("Redefinition of '{a}'.", token, id); + } + addlabel(id, 'const'); + if (prefix) { + break; + } + name = token; + this.first.push(token); + + if (nexttoken.id !== "=") { + warning("const " + + "'{a}' is initialized to 'undefined'.", token, id); + } + + if (nexttoken.id === '=') { + nonadjacent(token, nexttoken); + advance('='); + nonadjacent(token, nexttoken); + if (nexttoken.id === 'undefined') { + warning("It is not necessary to initialize " + + "'{a}' to 'undefined'.", token, id); + } + if (peek(0).id === '=' && nexttoken.identifier) { + error("Constant {a} was not declared correctly.", + nexttoken, nexttoken.value); + } + value = expression(0); + name.first = value; + } + + if (nexttoken.id !== ',') { + break; + } + comma(); + } + return this; + }); + conststatement.exps = true; + }; + + var varstatement = stmt('var', function (prefix) { + // JavaScript does not have block scope. It only has function scope. So, + // declaring a variable in a block can have unexpected consequences. + var id, name, value; + + if (funct['(onevar)'] && option.onevar) { + warning("Too many var statements."); + } else if (!funct['(global)']) { + funct['(onevar)'] = true; + } + this.first = []; + for (;;) { + nonadjacent(token, nexttoken); + id = identifier(); + if (option.esnext && funct[id] === "const") { + warning("const '" + id + "' has already been declared"); + } + if (funct['(global)'] && predefined[id] === false) { + warning("Redefinition of '{a}'.", token, id); + } + addlabel(id, 'unused'); + if (prefix) { + break; + } + name = token; + this.first.push(token); + if (nexttoken.id === '=') { + nonadjacent(token, nexttoken); + advance('='); + nonadjacent(token, nexttoken); + if (nexttoken.id === 'undefined') { + warning("It is not necessary to initialize '{a}' to 'undefined'.", token, id); + } + if (peek(0).id === '=' && nexttoken.identifier) { + error("Variable {a} was not declared correctly.", + nexttoken, nexttoken.value); + } + value = expression(0); + name.first = value; + } + if (nexttoken.id !== ',') { + break; + } + comma(); + } + return this; + }); + varstatement.exps = true; + + blockstmt('function', function () { + if (inblock) { + warning("Function declarations should not be placed in blocks. " + + "Use a function expression or move the statement to the top of " + + "the outer function.", token); + + } + var i = identifier(); + if (option.esnext && funct[i] === "const") { + warning("const '" + i + "' has already been declared"); + } + adjacent(token, nexttoken); + addlabel(i, 'unction'); + doFunction(i, true); + if (nexttoken.id === '(' && nexttoken.line === token.line) { + error( +"Function declarations are not invocable. Wrap the whole function invocation in parens."); + } + return this; + }); + + prefix('function', function () { + var i = optionalidentifier(); + if (i) { + adjacent(token, nexttoken); + } else { + nonadjacent(token, nexttoken); + } + doFunction(i); + if (!option.loopfunc && funct['(loopage)']) { + warning("Don't make functions within a loop."); + } + return this; + }); + + blockstmt('if', function () { + var t = nexttoken; + advance('('); + nonadjacent(this, t); + nospace(); + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + advance(')', t); + nospace(prevtoken, token); + block(true, true); + if (nexttoken.id === 'else') { + nonadjacent(token, nexttoken); + advance('else'); + if (nexttoken.id === 'if' || nexttoken.id === 'switch') { + statement(true); + } else { + block(true, true); + } + } + return this; + }); + + blockstmt('try', function () { + var b, e, s; + + block(false); + if (nexttoken.id === 'catch') { + advance('catch'); + nonadjacent(token, nexttoken); + advance('('); + s = scope; + scope = Object.create(s); + e = nexttoken.value; + if (nexttoken.type !== '(identifier)') { + warning("Expected an identifier and instead saw '{a}'.", + nexttoken, e); + } else { + addlabel(e, 'exception'); + } + advance(); + advance(')'); + block(false); + b = true; + scope = s; + } + if (nexttoken.id === 'finally') { + advance('finally'); + block(false); + return; + } else if (!b) { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, 'catch', nexttoken.value); + } + return this; + }); + + blockstmt('while', function () { + var t = nexttoken; + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + advance('('); + nonadjacent(this, t); + nospace(); + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + advance(')', t); + nospace(prevtoken, token); + block(true, true); + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + }).labelled = true; + + blockstmt('with', function () { + var t = nexttoken; + if (directive['use strict']) { + error("'with' is not allowed in strict mode.", token); + } else if (!option.withstmt) { + warning("Don't use 'with'.", token); + } + + advance('('); + nonadjacent(this, t); + nospace(); + expression(0); + advance(')', t); + nospace(prevtoken, token); + block(true, true); + + return this; + }); + + blockstmt('switch', function () { + var t = nexttoken, + g = false; + funct['(breakage)'] += 1; + advance('('); + nonadjacent(this, t); + nospace(); + this.condition = expression(20); + advance(')', t); + nospace(prevtoken, token); + nonadjacent(token, nexttoken); + t = nexttoken; + advance('{'); + nonadjacent(token, nexttoken); + indent += option.indent; + this.cases = []; + for (;;) { + switch (nexttoken.id) { + case 'case': + switch (funct['(verb)']) { + case 'break': + case 'case': + case 'continue': + case 'return': + case 'switch': + case 'throw': + break; + default: + // You can tell JSHint that you don't use break intentionally by + // adding a comment /* falls through */ on a line just before + // the next `case`. + if (!ft.test(lines[nexttoken.line - 2])) { + warning( + "Expected a 'break' statement before 'case'.", + token); + } + } + indentation(-option.indent); + advance('case'); + this.cases.push(expression(20)); + g = true; + advance(':'); + funct['(verb)'] = 'case'; + break; + case 'default': + switch (funct['(verb)']) { + case 'break': + case 'continue': + case 'return': + case 'throw': + break; + default: + if (!ft.test(lines[nexttoken.line - 2])) { + warning( + "Expected a 'break' statement before 'default'.", + token); + } + } + indentation(-option.indent); + advance('default'); + g = true; + advance(':'); + break; + case '}': + indent -= option.indent; + indentation(); + advance('}', t); + if (this.cases.length === 1 || this.condition.id === 'true' || + this.condition.id === 'false') { + if (!option.onecase) + warning("This 'switch' should be an 'if'.", this); + } + funct['(breakage)'] -= 1; + funct['(verb)'] = undefined; + return; + case '(end)': + error("Missing '{a}'.", nexttoken, '}'); + return; + default: + if (g) { + switch (token.id) { + case ',': + error("Each value should have its own case label."); + return; + case ':': + g = false; + statements(); + break; + default: + error("Missing ':' on a case clause.", token); + return; + } + } else { + if (token.id === ':') { + advance(':'); + error("Unexpected '{a}'.", token, ':'); + statements(); + } else { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, 'case', nexttoken.value); + return; + } + } + } + } + }).labelled = true; + + stmt('debugger', function () { + if (!option.debug) { + warning("All 'debugger' statements should be removed."); + } + return this; + }).exps = true; + + (function () { + var x = stmt('do', function () { + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + this.first = block(true); + advance('while'); + var t = nexttoken; + nonadjacent(token, t); + advance('('); + nospace(); + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + advance(')', t); + nospace(prevtoken, token); + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + }); + x.labelled = true; + x.exps = true; + }()); + + blockstmt('for', function () { + var s, t = nexttoken; + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + advance('('); + nonadjacent(this, t); + nospace(); + if (peek(nexttoken.id === 'var' ? 1 : 0).id === 'in') { + if (nexttoken.id === 'var') { + advance('var'); + varstatement.fud.call(varstatement, true); + } else { + switch (funct[nexttoken.value]) { + case 'unused': + funct[nexttoken.value] = 'var'; + break; + case 'var': + break; + default: + warning("Bad for in variable '{a}'.", + nexttoken, nexttoken.value); + } + advance(); + } + advance('in'); + expression(20); + advance(')', t); + s = block(true, true); + if (option.forin && s && (s.length > 1 || typeof s[0] !== 'object' || + s[0].value !== 'if')) { + warning("The body of a for in should be wrapped in an if statement to filter " + + "unwanted properties from the prototype.", this); + } + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + } else { + if (nexttoken.id !== ';') { + if (nexttoken.id === 'var') { + advance('var'); + varstatement.fud.call(varstatement); + } else { + for (;;) { + expression(0, 'for'); + if (nexttoken.id !== ',') { + break; + } + comma(); + } + } + } + nolinebreak(token); + advance(';'); + if (nexttoken.id !== ';') { + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + } + nolinebreak(token); + advance(';'); + if (nexttoken.id === ';') { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, ')', ';'); + } + if (nexttoken.id !== ')') { + for (;;) { + expression(0, 'for'); + if (nexttoken.id !== ',') { + break; + } + comma(); + } + } + advance(')', t); + nospace(prevtoken, token); + block(true, true); + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + } + }).labelled = true; + + + stmt('break', function () { + var v = nexttoken.value; + + if (funct['(breakage)'] === 0) + warning("Unexpected '{a}'.", nexttoken, this.value); + + if (!option.asi) + nolinebreak(this); + + if (nexttoken.id !== ';') { + if (token.line === nexttoken.line) { + if (funct[v] !== 'label') { + warning("'{a}' is not a statement label.", nexttoken, v); + } else if (scope[v] !== funct) { + warning("'{a}' is out of scope.", nexttoken, v); + } + this.first = nexttoken; + advance(); + } + } + reachable('break'); + return this; + }).exps = true; + + + stmt('continue', function () { + var v = nexttoken.value; + + if (funct['(breakage)'] === 0) + warning("Unexpected '{a}'.", nexttoken, this.value); + + if (!option.asi) + nolinebreak(this); + + if (nexttoken.id !== ';') { + if (token.line === nexttoken.line) { + if (funct[v] !== 'label') { + warning("'{a}' is not a statement label.", nexttoken, v); + } else if (scope[v] !== funct) { + warning("'{a}' is out of scope.", nexttoken, v); + } + this.first = nexttoken; + advance(); + } + } else if (!funct['(loopage)']) { + warning("Unexpected '{a}'.", nexttoken, this.value); + } + reachable('continue'); + return this; + }).exps = true; + + + stmt('return', function () { + if (this.line === nexttoken.line) { + if (nexttoken.id === '(regexp)') + warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator."); + + if (nexttoken.id !== ';' && !nexttoken.reach) { + nonadjacent(token, nexttoken); + if (peek().value === "=" && !option.boss) { + warningAt("Did you mean to return a conditional instead of an assignment?", + token.line, token.character + 1); + } + this.first = expression(0); + } + } else if (!option.asi) { + nolinebreak(this); // always warn (Line breaking error) + } + reachable('return'); + return this; + }).exps = true; + + + stmt('throw', function () { + nolinebreak(this); + nonadjacent(token, nexttoken); + this.first = expression(20); + reachable('throw'); + return this; + }).exps = true; + +// Superfluous reserved words + + reserve('class'); + reserve('const'); + reserve('enum'); + reserve('export'); + reserve('extends'); + reserve('import'); + reserve('super'); + + reserve('let'); + reserve('yield'); + reserve('implements'); + reserve('interface'); + reserve('package'); + reserve('private'); + reserve('protected'); + reserve('public'); + reserve('static'); + + +// Parse JSON + + function jsonValue() { + + function jsonObject() { + var o = {}, t = nexttoken; + advance('{'); + if (nexttoken.id !== '}') { + for (;;) { + if (nexttoken.id === '(end)') { + error("Missing '}' to match '{' from line {a}.", + nexttoken, t.line); + } else if (nexttoken.id === '}') { + warning("Unexpected comma.", token); + break; + } else if (nexttoken.id === ',') { + error("Unexpected comma.", nexttoken); + } else if (nexttoken.id !== '(string)') { + warning("Expected a string and instead saw {a}.", + nexttoken, nexttoken.value); + } + if (o[nexttoken.value] === true) { + warning("Duplicate key '{a}'.", + nexttoken, nexttoken.value); + } else if ((nexttoken.value === '__proto__' && + !option.proto) || (nexttoken.value === '__iterator__' && + !option.iterator)) { + warning("The '{a}' key may produce unexpected results.", + nexttoken, nexttoken.value); + } else { + o[nexttoken.value] = true; + } + advance(); + advance(':'); + jsonValue(); + if (nexttoken.id !== ',') { + break; + } + advance(','); + } + } + advance('}'); + } + + function jsonArray() { + var t = nexttoken; + advance('['); + if (nexttoken.id !== ']') { + for (;;) { + if (nexttoken.id === '(end)') { + error("Missing ']' to match '[' from line {a}.", + nexttoken, t.line); + } else if (nexttoken.id === ']') { + warning("Unexpected comma.", token); + break; + } else if (nexttoken.id === ',') { + error("Unexpected comma.", nexttoken); + } + jsonValue(); + if (nexttoken.id !== ',') { + break; + } + advance(','); + } + } + advance(']'); + } + + switch (nexttoken.id) { + case '{': + jsonObject(); + break; + case '[': + jsonArray(); + break; + case 'true': + case 'false': + case 'null': + case '(number)': + case '(string)': + advance(); + break; + case '-': + advance('-'); + if (token.character !== nexttoken.from) { + warning("Unexpected space after '-'.", token); + } + adjacent(token, nexttoken); + advance('(number)'); + break; + default: + error("Expected a JSON value.", nexttoken); + } + } + + +// The actual JSHINT function itself. + + var itself = function (s, o, g) { + var a, i, k; + JSHINT.errors = []; + JSHINT.undefs = []; + predefined = Object.create(standard); + combine(predefined, g || {}); + if (o) { + a = o.predef; + if (a) { + if (Array.isArray(a)) { + for (i = 0; i < a.length; i += 1) { + predefined[a[i]] = true; + } + } else if (typeof a === 'object') { + k = Object.keys(a); + for (i = 0; i < k.length; i += 1) { + predefined[k[i]] = !!a[k[i]]; + } + } + } + option = o; + } else { + option = {}; + } + option.indent = option.indent || 4; + option.maxerr = option.maxerr || 50; + + tab = ''; + for (i = 0; i < option.indent; i += 1) { + tab += ' '; + } + indent = 1; + global = Object.create(predefined); + scope = global; + funct = { + '(global)': true, + '(name)': '(global)', + '(scope)': scope, + '(breakage)': 0, + '(loopage)': 0 + }; + functions = [funct]; + urls = []; + stack = null; + member = {}; + membersOnly = null; + implied = {}; + inblock = false; + lookahead = []; + jsonmode = false; + warnings = 0; + lex.init(s); + prereg = true; + directive = {}; + + prevtoken = token = nexttoken = syntax['(begin)']; + + // Check options + for (var name in o) { + if (is_own(o, name)) { + checkOption(name, token); + } + } + + assume(); + + // combine the passed globals after we've assumed all our options + combine(predefined, g || {}); + + //reset values + comma.first = true; + + try { + advance(); + switch (nexttoken.id) { + case '{': + case '[': + option.laxbreak = true; + jsonmode = true; + jsonValue(); + break; + default: + directives(); + if (directive["use strict"] && !option.globalstrict) { + warning("Use the function form of \"use strict\".", prevtoken); + } + + statements(); + } + advance('(end)'); + + var markDefined = function (name, context) { + do { + if (typeof context[name] === 'string') { + // JSHINT marks unused variables as 'unused' and + // unused function declaration as 'unction'. This + // code changes such instances back 'var' and + // 'closure' so that the code in JSHINT.data() + // doesn't think they're unused. + + if (context[name] === 'unused') + context[name] = 'var'; + else if (context[name] === 'unction') + context[name] = 'closure'; + + return true; + } + + context = context['(context)']; + } while (context); + + return false; + }; + + var clearImplied = function (name, line) { + if (!implied[name]) + return; + + var newImplied = []; + for (var i = 0; i < implied[name].length; i += 1) { + if (implied[name][i] !== line) + newImplied.push(implied[name][i]); + } + + if (newImplied.length === 0) + delete implied[name]; + else + implied[name] = newImplied; + }; + + // Check queued 'x is not defined' instances to see if they're still undefined. + for (i = 0; i < JSHINT.undefs.length; i += 1) { + k = JSHINT.undefs[i].slice(0); + + if (markDefined(k[2].value, k[0])) { + clearImplied(k[2].value, k[2].line); + } else { + warning.apply(warning, k.slice(1)); + } + } + } catch (e) { + if (e) { + var nt = nexttoken || {}; + JSHINT.errors.push({ + raw : e.raw, + reason : e.message, + line : e.line || nt.line, + character : e.character || nt.from + }, null); + } + } + + return JSHINT.errors.length === 0; + }; + + // Data summary. + itself.data = function () { + + var data = { functions: [], options: option }, fu, globals, implieds = [], f, i, j, + members = [], n, unused = [], v; + if (itself.errors.length) { + data.errors = itself.errors; + } + + if (jsonmode) { + data.json = true; + } + + for (n in implied) { + if (is_own(implied, n)) { + implieds.push({ + name: n, + line: implied[n] + }); + } + } + if (implieds.length > 0) { + data.implieds = implieds; + } + + if (urls.length > 0) { + data.urls = urls; + } + + globals = Object.keys(scope); + if (globals.length > 0) { + data.globals = globals; + } + for (i = 1; i < functions.length; i += 1) { + f = functions[i]; + fu = {}; + for (j = 0; j < functionicity.length; j += 1) { + fu[functionicity[j]] = []; + } + for (n in f) { + if (is_own(f, n) && n.charAt(0) !== '(') { + v = f[n]; + if (v === 'unction') { + v = 'unused'; + } + if (Array.isArray(fu[v])) { + fu[v].push(n); + if (v === 'unused') { + unused.push({ + name: n, + line: f['(line)'], + 'function': f['(name)'] + }); + } + } + } + } + for (j = 0; j < functionicity.length; j += 1) { + if (fu[functionicity[j]].length === 0) { + delete fu[functionicity[j]]; + } + } + fu.name = f['(name)']; + fu.param = f['(params)']; + fu.line = f['(line)']; + fu.last = f['(last)']; + data.functions.push(fu); + } + + if (unused.length > 0) { + data.unused = unused; + } + + members = []; + for (n in member) { + if (typeof member[n] === 'number') { + data.member = member; + break; + } + } + + return data; + }; + + itself.report = function (option) { + var data = itself.data(); + + var a = [], c, e, err, f, i, k, l, m = '', n, o = [], s; + + function detail(h, array) { + var b, i, singularity; + if (array) { + o.push('
' + h + ' '); + array = array.sort(); + for (i = 0; i < array.length; i += 1) { + if (array[i] !== singularity) { + singularity = array[i]; + o.push((b ? ', ' : '') + singularity); + b = true; + } + } + o.push('
'); + } + } + + + if (data.errors || data.implieds || data.unused) { + err = true; + o.push('
Error:'); + if (data.errors) { + for (i = 0; i < data.errors.length; i += 1) { + c = data.errors[i]; + if (c) { + e = c.evidence || ''; + o.push('

Problem' + (isFinite(c.line) ? ' at line ' + + c.line + ' character ' + c.character : '') + + ': ' + c.reason.entityify() + + '

' + + (e && (e.length > 80 ? e.slice(0, 77) + '...' : + e).entityify()) + '

'); + } + } + } + + if (data.implieds) { + s = []; + for (i = 0; i < data.implieds.length; i += 1) { + s[i] = '' + data.implieds[i].name + ' ' + + data.implieds[i].line + ''; + } + o.push('

Implied global: ' + s.join(', ') + '

'); + } + + if (data.unused) { + s = []; + for (i = 0; i < data.unused.length; i += 1) { + s[i] = '' + data.unused[i].name + ' ' + + data.unused[i].line + ' ' + + data.unused[i]['function'] + ''; + } + o.push('

Unused variable: ' + s.join(', ') + '

'); + } + if (data.json) { + o.push('

JSON: bad.

'); + } + o.push('
'); + } + + if (!option) { + + o.push('
'); + + if (data.urls) { + detail("URLs
", data.urls, '
'); + } + + if (data.json && !err) { + o.push('

JSON: good.

'); + } else if (data.globals) { + o.push('
Global ' + + data.globals.sort().join(', ') + '
'); + } else { + o.push('
No new global variables introduced.
'); + } + + for (i = 0; i < data.functions.length; i += 1) { + f = data.functions[i]; + + o.push('
' + f.line + '-' + + f.last + ' ' + (f.name || '') + '(' + + (f.param ? f.param.join(', ') : '') + ')
'); + detail('Unused', f.unused); + detail('Closure', f.closure); + detail('Variable', f['var']); + detail('Exception', f.exception); + detail('Outer', f.outer); + detail('Global', f.global); + detail('Label', f.label); + } + + if (data.member) { + a = Object.keys(data.member); + if (a.length) { + a = a.sort(); + m = '
/*members ';
+                    l = 10;
+                    for (i = 0; i < a.length; i += 1) {
+                        k = a[i];
+                        n = k.name();
+                        if (l + n.length > 72) {
+                            o.push(m + '
'); + m = ' '; + l = 1; + } + l += n.length + 2; + if (data.member[k] === 1) { + n = '' + n + ''; + } + if (i < a.length - 1) { + n += ', '; + } + m += n; + } + o.push(m + '
*/
'); + } + o.push('
'); + } + } + return o.join(''); + }; + + itself.jshint = itself; + + return itself; +}()); + +// Make JSHINT a Node module, if possible. +if (typeof exports === 'object' && exports) + exports.JSHINT = JSHINT; + +}); + +/* + * Narcissus - JS implemented in JS. + * + * Parser. + */ + +define('ace/narcissus/parser', ['require', 'exports', 'module' , 'ace/narcissus/lexer', 'ace/narcissus/definitions', 'ace/narcissus/options'], function(require, exports, module) { + +var lexer = require('./lexer'); +var definitions = require('./definitions'); +var options = require('./options'); +var Tokenizer = lexer.Tokenizer; + +var Dict = definitions.Dict; +var Stack = definitions.Stack; + +// Set constants in the local scope. +eval(definitions.consts); +function pushDestructuringVarDecls(n, s) { + for (var i in n) { + var sub = n[i]; + if (sub.type === IDENTIFIER) { + s.varDecls.push(sub); + } else { + pushDestructuringVarDecls(sub, s); + } + } +} + +function Parser(tokenizer) { + tokenizer.parser = this; + this.t = tokenizer; + this.x = null; + this.unexpectedEOF = false; + options.mozillaMode && (this.mozillaMode = true); + options.parenFreeMode && (this.parenFreeMode = true); +} + +function StaticContext(parentScript, parentBlock, inModule, inFunction, strictMode) { + this.parentScript = parentScript; + this.parentBlock = parentBlock || parentScript; + this.inModule = inModule || false; + this.inFunction = inFunction || false; + this.inForLoopInit = false; + this.topLevel = true; + this.allLabels = new Stack(); + this.currentLabels = new Stack(); + this.labeledTargets = new Stack(); + this.defaultLoopTarget = null; + this.defaultTarget = null; + this.strictMode = strictMode; +} + +StaticContext.prototype = { + // non-destructive update via prototype extension + update: function(ext) { + var desc = {}; + for (var key in ext) { + desc[key] = { + value: ext[key], + writable: true, + enumerable: true, + configurable: true + } + } + return Object.create(this, desc); + }, + pushLabel: function(label) { + return this.update({ currentLabels: this.currentLabels.push(label), + allLabels: this.allLabels.push(label) }); + }, + pushTarget: function(target) { + var isDefaultLoopTarget = target.isLoop; + var isDefaultTarget = isDefaultLoopTarget || target.type === SWITCH; + + if (this.currentLabels.isEmpty()) { + if (isDefaultLoopTarget) this.update({ defaultLoopTarget: target }); + if (isDefaultTarget) this.update({ defaultTarget: target }); + return this; + } + + target.labels = new Dict(); + this.currentLabels.forEach(function(label) { + target.labels.set(label, true); + }); + return this.update({ currentLabels: new Stack(), + labeledTargets: this.labeledTargets.push(target), + defaultLoopTarget: isDefaultLoopTarget + ? target + : this.defaultLoopTarget, + defaultTarget: isDefaultTarget + ? target + : this.defaultTarget }); + }, + nest: function() { + return this.topLevel ? this.update({ topLevel: false }) : this; + }, + canImport: function() { + return this.topLevel && !this.inFunction; + }, + canExport: function() { + return this.inModule && this.topLevel && !this.inFunction; + }, + banWith: function() { + return this.strictMode || this.inModule; + }, + modulesAllowed: function() { + return this.topLevel && !this.inFunction; + } +}; + +var Pp = Parser.prototype; + +Pp.mozillaMode = false; + +Pp.parenFreeMode = false; + +Pp.withContext = function(x, f) { + var x0 = this.x; + this.x = x; + var result = f.call(this); + // NB: we don't bother with finally, since exceptions trash the parser + this.x = x0; + return result; +}; + +Pp.newNode = function newNode(opts) { + return new Node(this.t, opts); +}; + +Pp.fail = function fail(msg) { + throw this.t.newSyntaxError(msg); +}; + +Pp.match = function match(tt, scanOperand, keywordIsName) { + return this.t.match(tt, scanOperand, keywordIsName); +}; + +Pp.mustMatch = function mustMatch(tt, keywordIsName) { + return this.t.mustMatch(tt, keywordIsName); +}; + +Pp.peek = function peek(scanOperand) { + return this.t.peek(scanOperand); +}; + +Pp.peekOnSameLine = function peekOnSameLine(scanOperand) { + return this.t.peekOnSameLine(scanOperand); +}; + +Pp.done = function done() { + return this.t.done; +}; +Pp.Script = function Script(inModule, inFunction, expectEnd) { + var node = this.newNode(scriptInit()); + var x2 = new StaticContext(node, node, inModule, inFunction); + this.withContext(x2, function() { + this.Statements(node, true); + }); + if (expectEnd && !this.done()) + this.fail("expected end of input"); + return node; +}; +function Pragma(n) { + if (n.type === SEMICOLON) { + var e = n.expression; + if (e.type === STRING && e.value === "use strict") { + n.pragma = "strict"; + return true; + } + } + return false; +} + +/* + * Node :: (tokenizer, optional init object) -> node + */ +function Node(t, init) { + var token = t.token; + if (token) { + // If init.type exists it will override token.type. + this.type = token.type; + this.value = token.value; + this.lineno = token.lineno; + + // Start and end are file positions for error handling. + this.start = token.start; + this.end = token.end; + } else { + this.lineno = t.lineno; + } + + this.filename = t.filename; + this.children = []; + + for (var prop in init) + this[prop] = init[prop]; +} + +/* + * SyntheticNode :: (optional init object) -> node + */ +function SyntheticNode(init) { + this.children = []; + for (var prop in init) + this[prop] = init[prop]; + this.synthetic = true; +} + +var Np = Node.prototype = SyntheticNode.prototype = {}; +Np.constructor = Node; + +var TO_SOURCE_SKIP = { + type: true, + value: true, + lineno: true, + start: true, + end: true, + tokenizer: true, + assignOp: true +}; +function unevalableConst(code) { + var token = definitions.tokens[code]; + var constName = definitions.opTypeNames.hasOwnProperty(token) + ? definitions.opTypeNames[token] + : token in definitions.keywords + ? token.toUpperCase() + : token; + return { toSource: function() { return constName } }; +} +Np.toSource = function toSource() { + var mock = {}; + var self = this; + mock.type = unevalableConst(this.type); + // avoid infinite recursion in case of back-links + if (this.generatingSource) + return mock.toSource(); + this.generatingSource = true; + if ("value" in this) + mock.value = this.value; + if ("lineno" in this) + mock.lineno = this.lineno; + if ("start" in this) + mock.start = this.start; + if ("end" in this) + mock.end = this.end; + if (this.assignOp) + mock.assignOp = unevalableConst(this.assignOp); + for (var key in this) { + if (this.hasOwnProperty(key) && !(key in TO_SOURCE_SKIP)) + mock[key] = this[key]; + } + try { + return mock.toSource(); + } finally { + delete this.generatingSource; + } +}; + +// Always use push to add operands to an expression, to update start and end. +Np.push = function (kid) { + // kid can be null e.g. [1, , 2]. + if (kid !== null) { + if (kid.start < this.start) + this.start = kid.start; + if (this.end < kid.end) + this.end = kid.end; + } + return this.children.push(kid); +} + +Node.indentLevel = 0; + +function tokenString(tt) { + var t = definitions.tokens[tt]; + return /^\W/.test(t) ? definitions.opTypeNames[t] : t.toUpperCase(); +} + +Np.toString = function () { + var a = []; + for (var i in this) { + if (this.hasOwnProperty(i) && i !== 'type' && i !== 'target') + a.push({id: i, value: this[i]}); + } + a.sort(function (a,b) { return (a.id < b.id) ? -1 : 1; }); + var INDENTATION = " "; + var n = ++Node.indentLevel; + var s = "{\n" + INDENTATION.repeat(n) + "type: " + tokenString(this.type); + for (i = 0; i < a.length; i++) + s += ",\n" + INDENTATION.repeat(n) + a[i].id + ": " + a[i].value; + n = --Node.indentLevel; + s += "\n" + INDENTATION.repeat(n) + "}"; + return s; +} + +Np.synth = function(init) { + var node = new SyntheticNode(init); + node.filename = this.filename; + node.lineno = this.lineno; + node.start = this.start; + node.end = this.end; + return node; +}; + +var LOOP_INIT = { isLoop: true }; + +function blockInit() { + return { type: BLOCK, varDecls: [] }; +} + +function scriptInit() { + return { type: SCRIPT, + funDecls: [], + varDecls: [], + modDefns: new Dict(), + modAssns: new Dict(), + modDecls: new Dict(), + modLoads: new Dict(), + impDecls: [], + expDecls: [], + exports: new Dict(), + hasEmptyReturn: false, + hasReturnWithValue: false, + hasYield: false }; +} + +definitions.defineGetter(Np, "length", + function() { + throw new Error("Node.prototype.length is gone; " + + "use n.children.length instead"); + }); + +definitions.defineProperty(String.prototype, "repeat", + function(n) { + var s = "", t = this + s; + while (--n >= 0) + s += t; + return s; + }, false, false, true); + +Pp.MaybeLeftParen = function MaybeLeftParen() { + if (this.parenFreeMode) + return this.match(LEFT_PAREN) ? LEFT_PAREN : END; + return this.mustMatch(LEFT_PAREN).type; +}; + +Pp.MaybeRightParen = function MaybeRightParen(p) { + if (p === LEFT_PAREN) + this.mustMatch(RIGHT_PAREN); +} + +/* + * Statements :: (node[, boolean]) -> void + * + * Parses a sequence of Statements. + */ +Pp.Statements = function Statements(n, topLevel) { + var prologue = !!topLevel; + try { + while (!this.done() && this.peek(true) !== RIGHT_CURLY) { + var n2 = this.Statement(); + n.push(n2); + if (prologue && Pragma(n2)) { + this.x.strictMode = true; + n.strict = true; + } else { + prologue = false; + } + } + } catch (e) { + try { + if (this.done()) + this.unexpectedEOF = true; + } catch(e) {} + throw e; + } +} + +Pp.Block = function Block() { + this.mustMatch(LEFT_CURLY); + var n = this.newNode(blockInit()); + var x2 = this.x.update({ parentBlock: n }).pushTarget(n); + this.withContext(x2, function() { + this.Statements(n); + }); + this.mustMatch(RIGHT_CURLY); + return n; +} + +var DECLARED_FORM = 0, EXPRESSED_FORM = 1, STATEMENT_FORM = 2; +function Export(node, isDefinition) { + this.node = node; // the AST node declaring this individual export + this.isDefinition = isDefinition; // is the node an 'export'-annotated definition? + this.resolved = null; // resolved pointer to the target of this export +} + +/* + * registerExport :: (Dict, EXPORT node) -> void + */ +function registerExport(exports, decl) { + function register(name, exp) { + if (exports.has(name)) + throw new SyntaxError("multiple exports of " + name); + exports.set(name, exp); + } + + switch (decl.type) { + case MODULE: + case FUNCTION: + register(decl.name, new Export(decl, true)); + break; + + case VAR: + for (var i = 0; i < decl.children.length; i++) + register(decl.children[i].name, new Export(decl.children[i], true)); + break; + + case LET: + case CONST: + throw new Error("NYI: " + definitions.tokens[decl.type]); + + case EXPORT: + for (var i = 0; i < decl.pathList.length; i++) { + var path = decl.pathList[i]; + switch (path.type) { + case OBJECT_INIT: + for (var j = 0; j < path.children.length; j++) { + // init :: IDENTIFIER | PROPERTY_INIT + var init = path.children[j]; + if (init.type === IDENTIFIER) + register(init.value, new Export(init, false)); + else + register(init.children[0].value, new Export(init.children[1], false)); + } + break; + + case DOT: + register(path.children[1].value, new Export(path, false)); + break; + + case IDENTIFIER: + register(path.value, new Export(path, false)); + break; + + default: + throw new Error("unexpected export path: " + definitions.tokens[path.type]); + } + } + break; + + default: + throw new Error("unexpected export decl: " + definitions.tokens[exp.type]); + } +} + +/* + * Module :: (node) -> Module + * + * Static semantic representation of a module. + */ +function Module(node) { + var exports = node.body.exports; + var modDefns = node.body.modDefns; + + var exportedModules = new Dict(); + + exports.forEach(function(name, exp) { + var node = exp.node; + if (node.type === MODULE) { + exportedModules.set(name, node); + } else if (!exp.isDefinition && node.type === IDENTIFIER && modDefns.has(node.value)) { + var mod = modDefns.get(node.value); + exportedModules.set(name, mod); + } + }); + + this.node = node; + this.exports = exports; + this.exportedModules = exportedModules; +} + +/* + * Statement :: () -> node + * + * Parses a Statement. + */ +Pp.Statement = function Statement() { + var i, label, n, n2, p, c, ss, tt = this.t.get(true), tt2, x0, x2, x3; + + var comments = this.t.blockComments; + + // Cases for statements ending in a right curly return early, avoiding the + // common semicolon insertion magic after this switch. + switch (tt) { + case IMPORT: + if (!this.x.canImport()) + this.fail("illegal context for import statement"); + n = this.newNode(); + n.pathList = this.ImportPathList(); + this.x.parentScript.impDecls.push(n); + break; + + case EXPORT: + if (!this.x.canExport()) + this.fail("export statement not in module top level"); + switch (this.peek()) { + case MODULE: + case FUNCTION: + case LET: + case VAR: + case CONST: + n = this.Statement(); + n.blockComments = comments; + n.exported = true; + this.x.parentScript.expDecls.push(n); + registerExport(this.x.parentScript.exports, n); + return n; + } + n = this.newNode(); + n.pathList = this.ExportPathList(); + this.x.parentScript.expDecls.push(n); + registerExport(this.x.parentScript.exports, n); + break; + + case FUNCTION: + // DECLARED_FORM extends funDecls of x, STATEMENT_FORM doesn't. + return this.FunctionDefinition(true, this.x.topLevel ? DECLARED_FORM : STATEMENT_FORM, comments); + + case LEFT_CURLY: + n = this.newNode(blockInit()); + x2 = this.x.update({ parentBlock: n }).pushTarget(n).nest(); + this.withContext(x2, function() { + this.Statements(n); + }); + this.mustMatch(RIGHT_CURLY); + return n; + + case IF: + n = this.newNode(); + n.condition = this.HeadExpression(); + x2 = this.x.pushTarget(n).nest(); + this.withContext(x2, function() { + n.thenPart = this.Statement(); + n.elsePart = this.match(ELSE, true) ? this.Statement() : null; + }); + return n; + + case SWITCH: + // This allows CASEs after a DEFAULT, which is in the standard. + n = this.newNode({ cases: [], defaultIndex: -1 }); + n.discriminant = this.HeadExpression(); + x2 = this.x.pushTarget(n).nest(); + this.withContext(x2, function() { + this.mustMatch(LEFT_CURLY); + while ((tt = this.t.get()) !== RIGHT_CURLY) { + switch (tt) { + case DEFAULT: + if (n.defaultIndex >= 0) + this.fail("More than one switch default"); + // FALL THROUGH + case CASE: + n2 = this.newNode(); + if (tt === DEFAULT) + n.defaultIndex = n.cases.length; + else + n2.caseLabel = this.Expression(COLON); + break; + + default: + this.fail("Invalid switch case"); + } + this.mustMatch(COLON); + n2.statements = this.newNode(blockInit()); + while ((tt=this.peek(true)) !== CASE && tt !== DEFAULT && + tt !== RIGHT_CURLY) + n2.statements.push(this.Statement()); + n.cases.push(n2); + } + }); + return n; + + case FOR: + n = this.newNode(LOOP_INIT); + n.blockComments = comments; + if (this.match(IDENTIFIER)) { + if (this.t.token.value === "each") + n.isEach = true; + else + this.t.unget(); + } + if (!this.parenFreeMode) + this.mustMatch(LEFT_PAREN); + x2 = this.x.pushTarget(n).nest(); + x3 = this.x.update({ inForLoopInit: true }); + n2 = null; + if ((tt = this.peek(true)) !== SEMICOLON) { + this.withContext(x3, function() { + if (tt === VAR || tt === CONST) { + this.t.get(); + n2 = this.Variables(); + } else if (tt === LET) { + this.t.get(); + if (this.peek() === LEFT_PAREN) { + n2 = this.LetBlock(false); + } else { + // Let in for head, we need to add an implicit block + // around the rest of the for. + this.x.parentBlock = n; + n.varDecls = []; + n2 = this.Variables(); + } + } else { + n2 = this.Expression(); + } + }); + } + if (n2 && this.match(IN)) { + n.type = FOR_IN; + this.withContext(x3, function() { + n.object = this.Expression(); + if (n2.type === VAR || n2.type === LET) { + c = n2.children; + + // Destructuring turns one decl into multiples, so either + // there must be only one destructuring or only one + // decl. + if (c.length !== 1 && n2.destructurings.length !== 1) { + // FIXME: this.fail ? + throw new SyntaxError("Invalid for..in left-hand side", + this.filename, n2.lineno); + } + if (n2.destructurings.length > 0) { + n.iterator = n2.destructurings[0]; + } else { + n.iterator = c[0]; + } + n.varDecl = n2; + } else { + if (n2.type === ARRAY_INIT || n2.type === OBJECT_INIT) { + n2.destructuredNames = this.checkDestructuring(n2); + } + n.iterator = n2; + } + }); + } else { + x3.inForLoopInit = false; + n.setup = n2; + this.mustMatch(SEMICOLON); + if (n.isEach) + this.fail("Invalid for each..in loop"); + this.withContext(x3, function() { + n.condition = (this.peek(true) === SEMICOLON) + ? null + : this.Expression(); + this.mustMatch(SEMICOLON); + tt2 = this.peek(true); + n.update = (this.parenFreeMode + ? tt2 === LEFT_CURLY || definitions.isStatementStartCode[tt2] + : tt2 === RIGHT_PAREN) + ? null + : this.Expression(); + }); + } + if (!this.parenFreeMode) + this.mustMatch(RIGHT_PAREN); + this.withContext(x2, function() { + n.body = this.Statement(); + }); + return n; + + case WHILE: + n = this.newNode({ isLoop: true }); + n.blockComments = comments; + n.condition = this.HeadExpression(); + x2 = this.x.pushTarget(n).nest(); + this.withContext(x2, function() { + n.body = this.Statement(); + }); + return n; + + case DO: + n = this.newNode({ isLoop: true }); + n.blockComments = comments; + x2 = this.x.pushTarget(n).next(); + this.withContext(x2, function() { + n.body = this.Statement(); + }); + this.mustMatch(WHILE); + n.condition = this.HeadExpression(); + //