*
* 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
@@ -1158,303 +1822,409 @@ exports.shutdown = function(data, reason) {
*
* ***** END LICENSE BLOCK ***** */
-define('pilot/types/basic', ['require', 'exports', 'module' , 'pilot/types'], function(require, exports, module) {
-
-var types = require("pilot/types");
-var Type = types.Type;
-var Conversion = types.Conversion;
-var Status = types.Status;
+define('ace/lib/event', ['require', 'exports', 'module' , 'ace/lib/keys', 'ace/lib/useragent', 'ace/lib/dom'], function(require, exports, module) {
+"use strict";
-/**
- * These are the basic types that we accept. They are vaguely based on the
- * Jetpack settings system (https://wiki.mozilla.org/Labs/Jetpack/JEP/24)
- * although clearly more restricted.
- *
- * In addition to these types, Jetpack also accepts range, member, password
- * that we are thinking of adding.
- *
- *
This module probably should not be accessed directly, but instead used
- * through types.js
- */
-
-/**
- * 'text' is the default if no type is given.
- */
-var text = new Type();
-
-text.stringify = function(value) {
- return value;
-};
+var keys = require("./keys");
+var useragent = require("./useragent");
+var dom = require("./dom");
-text.parse = function(value) {
- if (typeof value != 'string') {
- throw new Error('non-string passed to text.parse()');
+exports.addListener = function(elem, type, callback) {
+ if (elem.addEventListener) {
+ return elem.addEventListener(type, callback, false);
}
- return new Conversion(value);
-};
-
-text.name = 'text';
-
-/**
- * We don't currently plan to distinguish between integers and floats
- */
-var number = new Type();
-
-number.stringify = function(value) {
- if (!value) {
- return null;
+ if (elem.attachEvent) {
+ var wrapper = function() {
+ callback(window.event);
+ };
+ callback._wrapper = wrapper;
+ elem.attachEvent("on" + type, wrapper);
}
- return '' + value;
};
-number.parse = function(value) {
- if (typeof value != 'string') {
- throw new Error('non-string passed to number.parse()');
- }
-
- if (value.replace(/\s/g, '').length === 0) {
- return new Conversion(null, Status.INCOMPLETE, '');
+exports.removeListener = function(elem, type, callback) {
+ if (elem.removeEventListener) {
+ return elem.removeEventListener(type, callback, false);
}
-
- var reply = new Conversion(parseInt(value, 10));
- if (isNaN(reply.value)) {
- reply.status = Status.INVALID;
- reply.message = 'Can\'t convert "' + value + '" to a number.';
+ if (elem.detachEvent) {
+ elem.detachEvent("on" + type, callback._wrapper || callback);
}
-
- return reply;
};
-number.decrement = function(value) {
- return value - 1;
+/*
+* Prevents propagation and clobbers the default action of the passed event
+*/
+exports.stopEvent = function(e) {
+ exports.stopPropagation(e);
+ exports.preventDefault(e);
+ return false;
};
-number.increment = function(value) {
- return value + 1;
+exports.stopPropagation = function(e) {
+ if (e.stopPropagation)
+ e.stopPropagation();
+ else
+ e.cancelBubble = true;
};
-number.name = 'number';
-
-/**
- * One of a known set of options
+exports.preventDefault = function(e) {
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+};
+
+/*
+ * @return {Number} 0 for left button, 1 for middle button, 2 for right button
*/
-function SelectionType(typeSpec) {
- if (!Array.isArray(typeSpec.data) && typeof typeSpec.data !== 'function') {
- throw new Error('instances of SelectionType need typeSpec.data to be an array or function that returns an array:' + JSON.stringify(typeSpec));
+exports.getButton = function(e) {
+ if (e.type == "dblclick")
+ return 0;
+ else if (e.type == "contextmenu")
+ return 2;
+
+ // DOM Event
+ if (e.preventDefault) {
+ return e.button;
+ }
+ // old IE
+ else {
+ return {1:0, 2:2, 4:1}[e.button];
}
- Object.keys(typeSpec).forEach(function(key) {
- this[key] = typeSpec[key];
- }, this);
};
-SelectionType.prototype = new Type();
+if (document.documentElement.setCapture) {
+ exports.capture = function(el, eventHandler, releaseCaptureHandler) {
+ function onMouseMove(e) {
+ eventHandler(e);
+ return exports.stopPropagation(e);
+ }
-SelectionType.prototype.stringify = function(value) {
- return value;
-};
+ var called = false;
+ function onReleaseCapture(e) {
+ eventHandler(e);
-SelectionType.prototype.parse = function(str) {
- if (typeof str != 'string') {
- throw new Error('non-string passed to parse()');
- }
- if (!this.data) {
- throw new Error('Missing data on selection type extension.');
- }
- var data = (typeof(this.data) === 'function') ? this.data() : this.data;
+ if (!called) {
+ called = true;
+ releaseCaptureHandler(e);
+ }
+
+ exports.removeListener(el, "mousemove", eventHandler);
+ exports.removeListener(el, "mouseup", onReleaseCapture);
+ exports.removeListener(el, "losecapture", onReleaseCapture);
- // The matchedValue could be the boolean value false
- var hasMatched = false;
- var matchedValue;
- var completions = [];
- data.forEach(function(option) {
- if (str == option) {
- matchedValue = this.fromString(option);
- hasMatched = true;
+ el.releaseCapture();
}
- else if (option.indexOf(str) === 0) {
- completions.push(this.fromString(option));
+
+ 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 onMouseMove(e) {
+ eventHandler(e);
+ e.stopPropagation();
}
- }, this);
- if (hasMatched) {
- return new Conversion(matchedValue);
- }
- else {
- // This is something of a hack it basically allows us to tell the
- // setting type to forget its last setting hack.
- if (this.noMatch) {
- this.noMatch();
+ function onMouseUp(e) {
+ eventHandler && eventHandler(e);
+ releaseCaptureHandler && releaseCaptureHandler(e);
+
+ document.removeEventListener("mousemove", onMouseMove, true);
+ document.removeEventListener("mouseup", onMouseUp, true);
+
+ e.stopPropagation();
}
- if (completions.length > 0) {
- var msg = 'Possibilities' +
- (str.length === 0 ? '' : ' for \'' + str + '\'');
- return new Conversion(null, Status.INCOMPLETE, msg, completions);
+ document.addEventListener("mousemove", onMouseMove, 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 {
- var msg = 'Can\'t use \'' + str + '\'.';
- return new Conversion(null, Status.INVALID, msg, completions);
+ 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);
};
-SelectionType.prototype.fromString = function(str) {
- return str;
-};
+exports.addMultiMouseDownListener = function(el, button, count, timeout, callback) {
+ var clicks = 0;
+ var startX, startY;
-SelectionType.prototype.decrement = function(value) {
- var data = (typeof this.data === 'function') ? this.data() : this.data;
- var index;
- if (value == null) {
- index = data.length - 1;
- }
- else {
- var name = this.stringify(value);
- var index = data.indexOf(name);
- index = (index === 0 ? data.length - 1 : index - 1);
- }
- return this.fromString(data[index]);
+ var listener = function(e) {
+ clicks += 1;
+ if (clicks == 1) {
+ startX = e.clientX;
+ startY = e.clientY;
+
+ setTimeout(function() {
+ clicks = 0;
+ }, timeout || 600);
+ }
+
+ var isButton = exports.getButton(e) == button;
+ if (!isButton || Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5)
+ clicks = 0;
+
+ if (clicks == count) {
+ clicks = 0;
+ callback(e);
+ }
+
+ if (isButton)
+ return exports.preventDefault(e);
+ };
+
+ exports.addListener(el, "mousedown", listener);
+ useragent.isOldIE && exports.addListener(el, "dblclick", listener);
};
-SelectionType.prototype.increment = function(value) {
- var data = (typeof this.data === 'function') ? this.data() : this.data;
- var index;
- if (value == null) {
- index = 0;
- }
- else {
- var name = this.stringify(value);
- var index = data.indexOf(name);
- index = (index === data.length - 1 ? 0 : index + 1);
+function normalizeCommandKeys(callback, e, keyCode) {
+ var hashId = 0;
+ if (useragent.isOpera && 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);
}
- return this.fromString(data[index]);
-};
-SelectionType.prototype.name = 'selection';
+ 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;
+ }
-/**
- * SelectionType is a base class for other types
- */
-exports.SelectionType = SelectionType;
+ if (hashId & 8 && (keyCode == 91 || keyCode == 93)) {
+ keyCode = 0;
+ }
-/**
- * true/false values
- */
-var bool = new SelectionType({
- name: 'bool',
- data: [ 'true', 'false' ],
- stringify: function(value) {
- return '' + value;
- },
- fromString: function(str) {
- return str === 'true' ? true : false;
+ // 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) {
+ // 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;
-/**
- * A we don't know right now, but hope to soon.
- */
-function DeferredType(typeSpec) {
- if (typeof typeSpec.defer !== 'function') {
- throw new Error('Instances of DeferredType need typeSpec.defer to be a function that returns a type');
+ addListener(el, "keydown", function(e) {
+ lastDown = e.keyIdentifier || e.keyCode;
+ return normalizeCommandKeys(callback, e, e.keyCode);
+ });
}
- Object.keys(typeSpec).forEach(function(key) {
- this[key] = typeSpec[key];
- }, this);
};
-DeferredType.prototype = new Type();
-
-DeferredType.prototype.stringify = function(value) {
- return this.defer().stringify(value);
-};
+if (window.postMessage) {
+ 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);
+ };
+}
-DeferredType.prototype.parse = function(value) {
- return this.defer().parse(value);
-};
+});
+/*! @license
+==========================================================================
+SproutCore -- JavaScript Application Framework
+copyright 2006-2009, Sprout Systems Inc., Apple Inc. and contributors.
-DeferredType.prototype.decrement = function(value) {
- var deferred = this.defer();
- return (deferred.decrement ? deferred.decrement(value) : undefined);
-};
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
-DeferredType.prototype.increment = function(value) {
- var deferred = this.defer();
- return (deferred.increment ? deferred.increment(value) : undefined);
-};
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
-DeferredType.prototype.name = 'deferred';
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
-/**
- * DeferredType is a base class for other types
- */
-exports.DeferredType = DeferredType;
+SproutCore and the SproutCore logo are trademarks of Sprout Systems, Inc.
+For more information about SproutCore, visit http://www.sproutcore.com
-/**
- * A set of objects of the same type
- */
-function ArrayType(typeSpec) {
- if (typeSpec instanceof Type) {
- this.subtype = typeSpec;
- }
- else if (typeof typeSpec === 'string') {
- this.subtype = types.getType(typeSpec);
- if (this.subtype == null) {
- throw new Error('Unknown array subtype: ' + typeSpec);
- }
- }
- else {
- throw new Error('Can\' handle array subtype');
- }
-};
-ArrayType.prototype = new Type();
+==========================================================================
+@license */
-ArrayType.prototype.stringify = function(values) {
- // TODO: Check for strings with spaces and add quotes
- return values.join(' ');
-};
+// Most of the following code is taken from SproutCore with a few changes.
-ArrayType.prototype.parse = function(value) {
- return this.defer().parse(value);
-};
+define('ace/lib/keys', ['require', 'exports', 'module' , 'ace/lib/oop'], function(require, exports, module) {
+"use strict";
-ArrayType.prototype.name = 'array';
+var oop = require("./oop");
-/**
- * Registration and de-registration.
+/*
+ * Helper functions and hashes for key handling.
*/
-var isStarted = false;
-exports.startup = function() {
- if (isStarted) {
- return;
- }
- isStarted = true;
- types.registerType(text);
- types.registerType(number);
- types.registerType(bool);
- types.registerType(SelectionType);
- types.registerType(DeferredType);
- types.registerType(ArrayType);
-};
-
-exports.shutdown = function() {
- isStarted = false;
- types.unregisterType(text);
- types.unregisterType(number);
- types.unregisterType(bool);
- types.unregisterType(SelectionType);
- types.unregisterType(DeferredType);
- types.unregisterType(ArrayType);
-};
+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
+ },
-});
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
+ 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();
+}
+
+});
+/* ***** 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
@@ -1465,15 +2235,15 @@ exports.shutdown = function() {
* for the specific language governing rights and limitations under the
* License.
*
- * The Original Code is Skywriter.
+ * The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Joe Walker (jwalker@mozilla.com)
+ * 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
@@ -1489,250 +2259,29 @@ exports.shutdown = function() {
*
* ***** END LICENSE BLOCK ***** */
-define('pilot/types', ['require', 'exports', 'module' ], function(require, exports, module) {
-
-/**
- * Some types can detect validity, that is to say they can distinguish between
- * valid and invalid values.
- * TODO: Change these constants to be numbers for more performance?
- */
-var Status = {
- /**
- * The conversion process worked without any problem, and the value is
- * valid. There are a number of failure states, so the best way to check
- * for failure is (x !== Status.VALID)
- */
- VALID: {
- toString: function() { return 'VALID'; },
- valueOf: function() { return 0; }
- },
-
- /**
- * A conversion process failed, however it was noted that the string
- * provided to 'parse()' could be VALID by the addition of more characters,
- * so the typing may not be actually incorrect yet, just unfinished.
- * @see Status.INVALID
- */
- INCOMPLETE: {
- toString: function() { return 'INCOMPLETE'; },
- valueOf: function() { return 1; }
- },
-
- /**
- * The conversion process did not work, the value should be null and a
- * reason for failure should have been provided. In addition some completion
- * values may be available.
- * @see Status.INCOMPLETE
- */
- INVALID: {
- toString: function() { return 'INVALID'; },
- valueOf: function() { return 2; }
- },
-
- /**
- * A combined status is the worser of the provided statuses
- */
- combine: function(statuses) {
- var combined = Status.VALID;
- for (var i = 0; i < statuses.length; i++) {
- if (statuses[i].valueOf() > combined.valueOf()) {
- combined = statuses[i];
- }
- }
- return combined;
- }
-};
-exports.Status = Status;
-
-/**
- * The type.parse() method returns a Conversion to inform the user about not
- * only the result of a Conversion but also about what went wrong.
- * We could use an exception, and throw if the conversion failed, but that
- * seems to violate the idea that exceptions should be exceptional. Typos are
- * not. Also in order to store both a status and a message we'd still need
- * some sort of exception type...
- */
-function Conversion(value, status, message, predictions) {
- /**
- * The result of the conversion process. Will be null if status != VALID
- */
- this.value = value;
-
- /**
- * The status of the conversion.
- * @see Status
- */
- this.status = status || Status.VALID;
-
- /**
- * A message to go with the conversion. This could be present for any status
- * including VALID in the case where we want to note a warning for example.
- * I18N: On the one hand this nasty and un-internationalized, however with
- * a command line it is hard to know where to start.
- */
- this.message = message;
-
- /**
- * A array of strings which are the systems best guess at better inputs than
- * the one presented.
- * We generally expect there to be about 7 predictions (to match human list
- * comprehension ability) however it is valid to provide up to about 20,
- * or less. It is the job of the predictor to decide a smart cut-off.
- * For example if there are 4 very good matches and 4 very poor ones,
- * probably only the 4 very good matches should be presented.
- */
- this.predictions = predictions || [];
-}
-exports.Conversion = Conversion;
-
-/**
- * Most of our types are 'static' e.g. there is only one type of 'text', however
- * some types like 'selection' and 'deferred' are customizable. The basic
- * Type type isn't useful, but does provide documentation about what types do.
- */
-function Type() {
-};
-Type.prototype = {
- /**
- * Convert the given value to a string representation.
- * Where possible, there should be round-tripping between values and their
- * string representations.
- */
- stringify: function(value) { throw new Error("not implemented"); },
-
- /**
- * Convert the given str to an instance of this type.
- * Where possible, there should be round-tripping between values and their
- * string representations.
- * @return Conversion
- */
- parse: function(str) { throw new Error("not implemented"); },
-
- /**
- * The plug-in system, and other things need to know what this type is
- * called. The name alone is not enough to fully specify a type. Types like
- * 'selection' and 'deferred' need extra data, however this function returns
- * only the name, not the extra data.
- * In old bespin, equality was based on the name. This may turn out to be
- * important in Ace too.
- */
- name: undefined,
-
- /**
- * If there is some concept of a higher value, return it,
- * otherwise return undefined.
- */
- increment: function(value) {
- return undefined;
- },
-
- /**
- * If there is some concept of a lower value, return it,
- * otherwise return undefined.
- */
- decrement: function(value) {
- return undefined;
- },
-
- /**
- * There is interesting information (like predictions) in a conversion of
- * nothing, the output of this can sometimes be customized.
- * @return Conversion
- */
- getDefault: function() {
- return this.parse('');
- }
-};
-exports.Type = Type;
+define('ace/lib/oop', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
-/**
- * Private registry of types
- * Invariant: types[name] = type.name
- */
-var types = {};
+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;
+ };
+}());
-/**
- * Add a new type to the list available to the system.
- * You can pass 2 things to this function - either an instance of Type, in
- * which case we return this instance when #getType() is called with a 'name'
- * that matches type.name.
- * Also you can pass in a constructor (i.e. function) in which case when
- * #getType() is called with a 'name' that matches Type.prototype.name we will
- * pass the typeSpec into this constructor. See #reconstituteType().
- */
-exports.registerType = function(type) {
- if (typeof type === 'object') {
- if (type instanceof Type) {
- if (!type.name) {
- throw new Error('All registered types must have a name');
- }
- types[type.name] = type;
- }
- else {
- throw new Error('Can\'t registerType using: ' + type);
- }
- }
- else if (typeof type === 'function') {
- if (!type.prototype.name) {
- throw new Error('All registered types must have a name');
- }
- types[type.prototype.name] = type;
- }
- else {
- throw new Error('Unknown type: ' + type);
+exports.mixin = function(obj, mixin) {
+ for (var key in mixin) {
+ obj[key] = mixin[key];
}
};
-exports.registerTypes = function registerTypes(types) {
- Object.keys(types).forEach(function (name) {
- var type = types[name];
- type.name = name;
- exports.registerType(type);
- });
-};
-
-/**
- * Remove a type from the list available to the system
- */
-exports.deregisterType = function(type) {
- delete types[type.name];
-};
-
-/**
- * See description of #exports.registerType()
- */
-function reconstituteType(name, typeSpec) {
- if (name.substr(-2) === '[]') { // i.e. endsWith('[]')
- var subtypeName = name.slice(0, -2);
- return new types['array'](subtypeName);
- }
-
- var type = types[name];
- if (typeof type === 'function') {
- type = new type(typeSpec);
- }
- return type;
-}
-
-/**
- * Find a type, previously registered using #registerType()
- */
-exports.getType = function(typeSpec) {
- if (typeof typeSpec === 'string') {
- return reconstituteType(typeSpec);
- }
-
- if (typeof typeSpec === 'object') {
- if (!typeSpec.name) {
- throw new Error('Missing \'name\' member to typeSpec');
- }
- return reconstituteType(typeSpec.name, typeSpec);
- }
-
- throw new Error('Can\'t extract type from ' + typeSpec);
+exports.implement = function(proto, mixin) {
+ exports.mixin(proto, mixin);
};
-
});
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -1747,16 +2296,15 @@ exports.getType = function(typeSpec) {
* for the specific language governing rights and limitations under the
* License.
*
- * The Original Code is Mozilla Skywriter.
+ * The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Joe Walker (jwalker@mozilla.com)
- * Kevin Dangoor (kdangoor@mozilla.com)
+ * 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
@@ -1772,44 +2320,76 @@ exports.getType = function(typeSpec) {
*
* ***** END LICENSE BLOCK ***** */
-define('pilot/types/command', ['require', 'exports', 'module' , 'pilot/canon', 'pilot/types/basic', 'pilot/types'], function(require, exports, module) {
+define('ace/lib/useragent', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
-var canon = require("pilot/canon");
-var SelectionType = require("pilot/types/basic").SelectionType;
-var types = require("pilot/types");
+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");
-/**
- * Select from the available commands
- */
-var command = new SelectionType({
- name: 'command',
- data: function() {
- return canon.getCommandNames();
- },
- stringify: function(command) {
- return command.name;
- },
- fromString: function(str) {
- return canon.getCommand(str);
- }
-});
+// 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");
-/**
- * Registration and de-registration.
+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;
+
+/*
+ * I hate doing this, but we need some way to determine if the user is on a Mac
+ * The reason is that users have different expectations of their key combinations.
+ *
+ * Take copy as an example, Mac people expect to use CMD or APPLE + C
+ * Windows folks expect to use CTRL + C
*/
-exports.startup = function() {
- types.registerType(command);
+exports.OS = {
+ LINUX: "LINUX",
+ MAC: "MAC",
+ WINDOWS: "WINDOWS"
};
-exports.shutdown = function() {
- types.unregisterType(command);
+/*
+ * Return an exports.OS constant
+ */
+exports.getOS = function() {
+ if (exports.isMac) {
+ return exports.OS.MAC;
+ } else if (exports.isLinux) {
+ return exports.OS.LINUX;
+ } else {
+ return exports.OS.WINDOWS;
+ }
};
-
});
-/* ***** BEGIN LICENSE BLOCK *****
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
@@ -1822,15 +2402,17 @@ exports.shutdown = function() {
* for the specific language governing rights and limitations under the
* License.
*
- * The Original Code is Mozilla Skywriter.
+ * The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Joe Walker (jwalker@mozilla.com)
+ * Fabian Jakobs
+ * Irakli Gozalishvili (http://jeditoolkit.com)
+ * Julian Viereck
*
* 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
@@ -1846,2170 +2428,2010 @@ exports.shutdown = function() {
*
* ***** END LICENSE BLOCK ***** */
-define('pilot/canon', ['require', 'exports', 'module' , 'pilot/console', 'pilot/stacktrace', 'pilot/oop', 'pilot/useragent', 'pilot/keys', 'pilot/event_emitter', 'pilot/typecheck', 'pilot/catalog', 'pilot/types', 'pilot/lang'], function(require, exports, module) {
+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) {
+"use strict";
+
+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;
-var console = require('pilot/console');
-var Trace = require('pilot/stacktrace').Trace;
-var oop = require('pilot/oop');
-var useragent = require('pilot/useragent');
-var keyUtil = require('pilot/keys');
-var EventEmitter = require('pilot/event_emitter').EventEmitter;
-var typecheck = require('pilot/typecheck');
-var catalog = require('pilot/catalog');
-var Status = require('pilot/types').Status;
-var types = require('pilot/types');
-var lang = require('pilot/lang');
-
-/*
-// TODO: this doesn't belong here - or maybe anywhere?
-var dimensionsChangedExtensionSpec = {
- name: 'dimensionsChanged',
- description: 'A dimensionsChanged is a way to be notified of ' +
- 'changes to the dimension of Skywriter'
-};
-exports.startup = function(data, reason) {
- catalog.addExtensionSpec(commandExtensionSpec);
-};
-exports.shutdown = function(data, reason) {
- catalog.removeExtensionSpec(commandExtensionSpec);
-};
-*/
-
-var commandExtensionSpec = {
- name: 'command',
- description: 'A command is a bit of functionality with optional ' +
- 'typed arguments which can do something small like moving ' +
- 'the cursor around the screen, or large like cloning a ' +
- 'project from VCS.',
- indexOn: 'name'
-};
-
-exports.startup = function(data, reason) {
- // TODO: this is probably all kinds of evil, but we need something working
- catalog.addExtensionSpec(commandExtensionSpec);
-};
-
-exports.shutdown = function(data, reason) {
- catalog.removeExtensionSpec(commandExtensionSpec);
-};
+/**
+ * class Editor
+ *
+ * The main entry point into the Ace functionality. The `Editor` manages the `EditSession` (which manages `Document`s), as well as the `VirtualRenderer`, which draws everything to the screen. Event sessions dealing with the mouse and keyboard are bubbled up from `Document` to the `Editor`, which decides what to do with them.
+ *
+ **/
/**
- * Manage a list of commands in the current canon
- */
+ * 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;
-/**
- * A Command is a discrete action optionally with a set of ways to customize
- * how it happens. This is here for documentation purposes.
- * TODO: Document better
- */
-var thingCommand = {
- name: 'thing',
- description: 'thing is an example command',
- params: [{
- name: 'param1',
- description: 'an example parameter',
- type: 'text',
- defaultValue: null
- }],
- exec: function(env, args, request) {
- thing();
+ 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);
}
-};
-/**
- * A lookup hash of our registered commands
- */
-var commands = {};
+ this.$blockScrolling = 0;
+ this.$search = new Search().set({
+ wrap: true
+ });
-/**
- * A lookup has for command key bindings that use a string as sender.
- */
-var commmandKeyBinding = {};
+ this.setSession(session || new EditSession(""));
+};
-/**
- * Array with command key bindings that use a function to determ the sender.
- */
-var commandKeyBindingFunc = { };
+(function(){
-function splitSafe(s, separator, limit, bLowerCase) {
- return (bLowerCase && s.toLowerCase() || s)
- .replace(/(?:^\s+|\n|\s+$)/g, "")
- .split(new RegExp("[\\s ]*" + separator + "[\\s ]*", "g"), limit || 999);
-}
+ oop.implement(this, EventEmitter);
-function parseKeys(keys, val, ret) {
- var key,
- hashId = 0,
- parts = splitSafe(keys, "\\-", null, true),
- i = 0,
- l = parts.length;
+ /**
+ * Editor.setKeyboardHandler(keyboardHandler)
+ *
+ * Sets a new keyboard handler.
+ **/
+ this.setKeyboardHandler = function(keyboardHandler) {
+ this.keyBinding.setKeyboardHandler(keyboardHandler);
+ };
- for (; 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 '-'
- }
+ /** related to: KeyBinding
+ * Editor.getKeyboardHandler() -> String
+ *
+ * Returns the keyboard handler.
+ **/
+ this.getKeyboardHandler = function() {
+ return this.keyBinding.getKeyboardHandler();
+ };
- if (ret == null) {
- return {
- key: key,
- hashId: hashId
- }
- } else {
- (ret[hashId] || (ret[hashId] = {}))[key] = val;
- }
-}
+ /**
+ * Editor.setSession(session)
+ * - session (EditSession): The new session to use
+ *
+ * Sets a new editsession to use. This method also emits the `'changeSession'` event.
+ **/
+ this.setSession = function(session) {
+ if (this.session == session)
+ return;
-var platform = useragent.isMac ? "mac" : "win";
-function buildKeyHash(command) {
- var binding = command.bindKey,
- key = binding[platform],
- ckb = commmandKeyBinding,
- ckbf = commandKeyBindingFunc
+ 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);
- if (!binding.sender) {
- throw new Error('All key bindings must have a sender');
- }
- if (!binding.mac && binding.mac !== null) {
- throw new Error('All key bindings must have a mac key binding');
- }
- if (!binding.win && binding.win !== null) {
- throw new Error('All key bindings must have a windows key binding');
- }
- if(!binding[platform]) {
- // No keymapping for this platform.
- return;
- }
- if (typeof binding.sender == 'string') {
- var targets = splitSafe(binding.sender, "\\|", null, true);
- targets.forEach(function(target) {
- if (!ckb[target]) {
- ckb[target] = { };
- }
- key.split("|").forEach(function(keyPart) {
- parseKeys(keyPart, command, ckb[target]);
- });
- });
- } else if (typecheck.isFunction(binding.sender)) {
- var val = {
- command: command,
- sender: binding.sender
- };
-
- keyData = parseKeys(key);
- if (!ckbf[keyData.hashId]) {
- ckbf[keyData.hashId] = { };
- }
- if (!ckbf[keyData.hashId][keyData.key]) {
- ckbf[keyData.hashId][keyData.key] = [ val ];
- } else {
- ckbf[keyData.hashId][keyData.key].push(val);
+ var selection = this.session.getSelection();
+ selection.removeEventListener("changeCursor", this.$onCursorChange);
+ selection.removeEventListener("changeSelection", this.$onSelectionChange);
}
- } else {
- throw new Error('Key binding must have a sender that is a string or function');
- }
-}
-function findKeyCommand(env, sender, hashId, textOrKey) {
- // Convert keyCode to the string representation.
- if (typecheck.isNumber(textOrKey)) {
- textOrKey = keyUtil.keyCodeToString(textOrKey);
- }
-
- // Check bindings with functions as sender first.
- var bindFuncs = (commandKeyBindingFunc[hashId] || {})[textOrKey] || [];
- for (var i = 0; i < bindFuncs.length; i++) {
- if (bindFuncs[i].sender(env, sender, hashId, textOrKey)) {
- return bindFuncs[i].command;
- }
- }
-
- var ckbr = commmandKeyBinding[sender];
- return ckbr && ckbr[hashId] && ckbr[hashId][textOrKey];
-}
+ this.session = session;
-function execKeyCommand(env, sender, hashId, textOrKey) {
- var command = findKeyCommand(env, sender, hashId, textOrKey);
- if (command) {
- return exec(command, env, sender, { });
- } else {
- return false;
- }
-}
+ this.$onDocumentChange = this.onDocumentChange.bind(this);
+ session.addEventListener("change", this.$onDocumentChange);
+ this.renderer.setSession(session);
-/**
- * A sorted list of command names, we regularly want them in order, so pre-sort
- */
-var commandNames = [];
+ this.$onChangeMode = this.onChangeMode.bind(this);
+ session.addEventListener("changeMode", this.$onChangeMode);
-/**
- * This registration method isn't like other Ace registration methods because
- * it doesn't return a decorated command because there is no functional
- * decoration to be done.
- * TODO: Are we sure that in the future there will be no such decoration?
- */
-function addCommand(command) {
- if (!command.name) {
- throw new Error('All registered commands must have a name');
- }
- if (command.params == null) {
- command.params = [];
- }
- if (!Array.isArray(command.params)) {
- throw new Error('command.params must be an array in ' + command.name);
- }
- // Replace the type
- command.params.forEach(function(param) {
- if (!param.name) {
- throw new Error('In ' + command.name + ': all params must have a name');
- }
- upgradeType(command.name, param);
- }, this);
- commands[command.name] = command;
+ this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this);
+ session.addEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
- if (command.bindKey) {
- buildKeyHash(command);
- }
+ this.$onChangeTabSize = this.renderer.updateText.bind(this.renderer);
+ session.addEventListener("changeTabSize", this.$onChangeTabSize);
- commandNames.push(command.name);
- commandNames.sort();
-};
+ this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this);
+ session.addEventListener("changeWrapLimit", this.$onChangeWrapLimit);
-function upgradeType(name, param) {
- var lookup = param.type;
- param.type = types.getType(lookup);
- if (param.type == null) {
- throw new Error('In ' + name + '/' + param.name +
- ': can\'t find type for: ' + JSON.stringify(lookup));
- }
-}
+ this.$onChangeWrapMode = this.onChangeWrapMode.bind(this);
+ session.addEventListener("changeWrapMode", this.$onChangeWrapMode);
-function removeCommand(command) {
- var name = (typeof command === 'string' ? command : command.name);
- command = commands[name];
- delete commands[name];
- lang.arrayRemove(commandNames, name);
-
- // exaustive search is a little bit brute force but since removeCommand is
- // not a performance critical operation this should be OK
- var ckb = commmandKeyBinding;
- for (var k1 in ckb) {
- for (var k2 in ckb[k1]) {
- for (var k3 in ckb[k1][k2]) {
- if (ckb[k1][k2][k3] == command)
- delete ckb[k1][k2][k3];
- }
- }
- }
-
- var ckbf = commandKeyBindingFunc;
- for (var k1 in ckbf) {
- for (var k2 in ckbf[k1]) {
- ckbf[k1][k2].forEach(function(cmd, i) {
- if (cmd.command == command) {
- ckbf[k1][k2].splice(i, 1);
- }
- })
- }
- }
-};
+ this.$onChangeFold = this.onChangeFold.bind(this);
+ session.addEventListener("changeFold", this.$onChangeFold);
-function getCommand(name) {
- return commands[name];
-};
+ this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);
+ this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker);
-function getCommandNames() {
- return commandNames;
-};
+ this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);
+ this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker);
-/**
- * Default ArgumentProvider that is used if no ArgumentProvider is provided
- * by the command's sender.
- */
-function defaultArgsProvider(request, callback) {
- var args = request.args,
- params = request.command.params;
+ this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);
+ this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint);
- for (var i = 0; i < params.length; i++) {
- var param = params[i];
+ this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);
+ this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation);
- // If the parameter is already valid, then don't ask for it anymore.
- if (request.getParamStatus(param) != Status.VALID ||
- // Ask for optional parameters as well.
- param.defaultValue === null)
- {
- var paramPrompt = param.description;
- if (param.defaultValue === null) {
- paramPrompt += " (optional)";
- }
- var value = prompt(paramPrompt, param.defaultValue || "");
- // No value but required -> nope.
- if (!value) {
- callback();
- return;
- } else {
- args[param.name] = value;
- }
- }
- }
- callback();
-}
+ this.$onCursorChange = this.onCursorChange.bind(this);
+ this.session.addEventListener("changeOverwrite", this.$onCursorChange);
-/**
- * Entry point for keyboard accelerators or anything else that wants to execute
- * a command. A new request object is created and a check performed, if the
- * passed in arguments are VALID/INVALID or INCOMPLETE. If they are INCOMPLETE
- * the ArgumentProvider on the sender is called or otherwise the default
- * ArgumentProvider to get the still required arguments.
- * If they are valid (or valid after the ArgumentProvider is done), the command
- * is executed.
- *
- * @param command Either a command, or the name of one
- * @param env Current environment to execute the command in
- * @param sender String that should be the same as the senderObject stored on
- * the environment in env[sender]
- * @param args Arguments for the command
- * @param typed (Optional)
- */
-function exec(command, env, sender, args, typed) {
- if (typeof command === 'string') {
- command = commands[command];
- }
- if (!command) {
- // TODO: Should we complain more than returning false?
- return false;
- }
+ this.$onScrollTopChange = this.onScrollTopChange.bind(this);
+ this.session.addEventListener("changeScrollTop", this.$onScrollTopChange);
- var request = new Request({
- sender: sender,
- command: command,
- args: args || {},
- typed: typed
- });
-
- /**
- * Executes the command and ensures request.done is called on the request in
- * case it's not marked to be done already or async.
- */
- function execute() {
- command.exec(env, request.args, request);
-
- // If the request isn't asnync and isn't done, then make it done.
- if (!request.isAsync && !request.isDone) {
- request.done();
- }
- }
-
-
- if (request.getStatus() == Status.INVALID) {
- console.error("Canon.exec: Invalid parameter(s) passed to " +
- command.name);
- return false;
- }
- // If the request isn't complete yet, try to complete it.
- else if (request.getStatus() == Status.INCOMPLETE) {
- // Check if the sender has a ArgsProvider, otherwise use the default
- // build in one.
- var argsProvider;
- var senderObj = env[sender];
- if (!senderObj || !senderObj.getArgsProvider ||
- !(argsProvider = senderObj.getArgsProvider()))
- {
- argsProvider = defaultArgsProvider;
- }
+ this.$onScrollLeftChange = this.onScrollLeftChange.bind(this);
+ this.session.addEventListener("changeScrollLeft", this.$onScrollLeftChange);
- // Ask the paramProvider to complete the request.
- argsProvider(request, function() {
- if (request.getStatus() == Status.VALID) {
- execute();
- }
- });
- return true;
- } else {
- execute();
- return true;
- }
-};
+ this.selection = session.getSelection();
+ this.selection.addEventListener("changeCursor", this.$onCursorChange);
-exports.removeCommand = removeCommand;
-exports.addCommand = addCommand;
-exports.getCommand = getCommand;
-exports.getCommandNames = getCommandNames;
-exports.findKeyCommand = findKeyCommand;
-exports.exec = exec;
-exports.execKeyCommand = execKeyCommand;
-exports.upgradeType = upgradeType;
+ this.$onSelectionChange = this.onSelectionChange.bind(this);
+ this.selection.addEventListener("changeSelection", this.$onSelectionChange);
+ this.onChangeMode();
-/**
- * We publish a 'output' event whenever new command begins output
- * TODO: make this more obvious
- */
-oop.implement(exports, EventEmitter);
+ 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();
-/**
- * Current requirements are around displaying the command line, and provision
- * of a 'history' command and cursor up|down navigation of history.
- * Future requirements could include:
- *
- * - Multiple command lines
- *
- The ability to recall key presses (i.e. requests with no output) which
- * will likely be needed for macro recording or similar
- *
- The ability to store the command history either on the server or in the
- * browser local storage.
- *
- * The execute() command doesn't really live here, except as part of that
- * last future requirement, and because it doesn't really have anywhere else to
- * live.
- */
+ this._emit("changeSession", {
+ session: session,
+ oldSession: oldSession
+ });
+ };
-/**
- * The array of requests that wish to announce their presence
- */
-var requests = [];
+ /**
+ * Editor.getSession() -> EditSession
+ *
+ * Returns the current session being used.
+ **/
+ this.getSession = function() {
+ return this.session;
+ };
-/**
- * How many requests do we store?
- */
-var maxRequestLength = 100;
+ /**
+ * Editor.getSelection() -> String
+ *
+ * Returns the currently highlighted selection.
+ **/
+ this.getSelection = function() {
+ return this.selection;
+ };
-/**
- * To create an invocation, you need to do something like this (all the ctor
- * args are optional):
- *
- * var request = new Request({
- * command: command,
- * args: args,
- * typed: typed
- * });
- *
- * @constructor
- */
-function Request(options) {
- options = options || {};
+ /** related to: VirtualRenderer.onResize
+ * Editor.resize()
+ *
+ * {:VirtualRenderer.onResize}
+ **/
+ this.resize = function() {
+ this.renderer.onResize();
+ };
- // Will be used in the keyboard case and the cli case
- this.command = options.command;
+ /**
+ * Editor.setTheme(theme)
+ *
+ * {:VirtualRenderer.setTheme}
+ **/
+ this.setTheme = function(theme) {
+ this.renderer.setTheme(theme);
+ };
- // Will be used only in the cli case
- this.args = options.args;
- this.typed = options.typed;
+ /** related to: VirtualRenderer.getTheme
+ * Editor.getTheme() -> String
+ *
+ * {:VirtualRenderer.getTheme}
+ **/
+ this.getTheme = function() {
+ return this.renderer.getTheme();
+ };
- // Have we been initialized?
- this._begunOutput = false;
+ /** related to: VirtualRenderer.setStyle
+ * Editor.setStyle(style)
+ *
+ * {:VirtualRenderer.setStyle}
+ **/
+ this.setStyle = function(style) {
+ this.renderer.setStyle(style);
+ };
- this.start = new Date();
- this.end = null;
- this.completed = false;
- this.error = false;
-};
+ /** related to: VirtualRenderer.unsetStyle
+ * Editor.unsetStyle(style)
+ *
+ * {:VirtualRenderer.unsetStyle}
+ **/
+ this.unsetStyle = function(style) {
+ this.renderer.unsetStyle(style);
+ };
-oop.implement(Request.prototype, EventEmitter);
+ /**
+ * Editor.setFontSize(size)
+ * - size (Number): A font size
+ *
+ * Set a new font size (in pixels) for the editor text.
+ **/
+ this.setFontSize = function(size) {
+ this.container.style.fontSize = size;
+ this.renderer.updateFontSize();
+ };
-/**
- * Return the status of a parameter on the request object.
- */
-Request.prototype.getParamStatus = function(param) {
- var args = this.args || {};
-
- // Check if there is already a value for this parameter.
- if (param.name in args) {
- // If there is no value set and then the value is VALID if it's not
- // required or INCOMPLETE if not set yet.
- if (args[param.name] == null) {
- if (param.defaultValue === null) {
- return Status.VALID;
- } else {
- return Status.INCOMPLETE;
- }
- }
-
- // Check if the parameter value is valid.
- var reply,
- // The passed in value when parsing a type is a string.
- argsValue = args[param.name].toString();
-
- // Type.parse can throw errors.
- try {
- reply = param.type.parse(argsValue);
- } catch (e) {
- return Status.INVALID;
- }
-
- if (reply.status != Status.VALID) {
- return reply.status;
+ /** internal, hide
+ * Editor.$highlightBrackets()
+ *
+ **/
+ this.$highlightBrackets = function() {
+ if (this.session.$bracketHighlight) {
+ this.session.removeMarker(this.session.$bracketHighlight);
+ this.session.$bracketHighlight = null;
}
- }
- // Check if the param is marked as required.
- else if (param.defaultValue === undefined) {
- // The parameter is not set on the args object but it's required,
- // which means, things are invalid.
- return Status.INCOMPLETE;
- }
-
- return Status.VALID;
-}
-/**
- * Return the status of a parameter name on the request object.
- */
-Request.prototype.getParamNameStatus = function(paramName) {
- var params = this.command.params || [];
-
- for (var i = 0; i < params.length; i++) {
- if (params[i].name == paramName) {
- return this.getParamStatus(params[i]);
+ if (this.$highlightPending) {
+ return;
}
- }
-
- throw "Parameter '" + paramName +
- "' not defined on command '" + this.command.name + "'";
-}
-/**
- * Checks if all required arguments are set on the request such that it can
- * get executed.
- */
-Request.prototype.getStatus = function() {
- var args = this.args || {},
- params = this.command.params;
+ // perform highlight async to not block the browser during navigation
+ var self = this;
+ this.$highlightPending = true;
+ setTimeout(function() {
+ self.$highlightPending = false;
- // If there are not parameters, then it's valid.
- if (!params || params.length == 0) {
- return Status.VALID;
- }
+ 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);
+ };
- var status = [];
- for (var i = 0; i < params.length; i++) {
- status.push(this.getParamStatus(params[i]));
- }
+ /**
+ * Editor.focus()
+ *
+ * Brings the current `textInput` into focus.
+ **/
+ 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();
+ };
- return Status.combine(status);
-}
+ /**
+ * Editor.isFocused() -> Boolean
+ *
+ * Returns true if the current `textInput` is in focus.
+ **/
+ this.isFocused = function() {
+ return this.textInput.isFocused();
+ };
-/**
- * Lazy init to register with the history should only be done on output.
- * init() is expensive, and won't be used in the majority of cases
- */
-Request.prototype._beginOutput = function() {
- this._begunOutput = true;
- this.outputs = [];
-
- requests.push(this);
- // This could probably be optimized with some maths, but 99.99% of the
- // time we will only be off by one, and I'm feeling lazy.
- while (requests.length > maxRequestLength) {
- requests.shiftObject();
- }
+ /**
+ * Editor.blur()
+ *
+ * Blurs the current `textInput`.
+ **/
+ this.blur = function() {
+ this.textInput.blur();
+ };
- exports._dispatchEvent('output', { requests: requests, request: this });
-};
+ /**
+ * Editor@onFocus()
+ *
+ * Emitted once the editor comes into focus.
+ **/
+ this.onFocus = function() {
+ this.renderer.showCursor();
+ this.renderer.visualizeFocus();
+ this._emit("focus");
+ };
-/**
- * Sugar for:
- * request.error = true; request.done(output);
- */
-Request.prototype.doneWithError = function(content) {
- this.error = true;
- this.done(content);
-};
+ /**
+ * Editor@onBlur()
+ *
+ * Emitted once the editor has been blurred.
+ **/
+ this.onBlur = function() {
+ this.renderer.hideCursor();
+ this.renderer.visualizeBlur();
+ this._emit("blur");
+ };
-/**
- * Declares that this function will not be automatically done when
- * the command exits
- */
-Request.prototype.async = function() {
- this.isAsync = true;
- if (!this._begunOutput) {
- this._beginOutput();
- }
-};
+ this.$cursorChange = function() {
+ this.renderer.updateCursor();
+ };
-/**
- * Complete the currently executing command with successful output.
- * @param output Either DOM node, an SproutCore element or something that
- * can be used in the content of a DIV to create a DOM node.
- */
-Request.prototype.output = function(content) {
- if (!this._begunOutput) {
- this._beginOutput();
- }
+ /**
+ * Editor@onDocumentChange(e)
+ * - e (Object): Contains a single property, `data`, which has the delta of changes
+ *
+ * Emitted whenever the document is changed.
+ *
+ **/
+ this.onDocumentChange = function(e) {
+ var delta = e.data;
+ var range = delta.range;
+ var lastRow;
- if (typeof content !== 'string' && !(content instanceof Node)) {
- content = content.toString();
- }
+ 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.outputs.push(content);
- this.isDone = true;
- this._dispatchEvent('output', {});
+ this._emit("change", e);
- return this;
-};
+ // update cursor because tab characters can influence the cursor position
+ this.$cursorChange();
+ };
-/**
- * All commands that do output must call this to indicate that the command
- * has finished execution.
- */
-Request.prototype.done = function(content) {
- this.completed = true;
- this.end = new Date();
- this.duration = this.end.getTime() - this.start.getTime();
+ /**
+ * Editor@onTokenizerUpdate(e)
+ * - e (Object): Contains a single property, `data`, which indicates the changed rows
+ *
+ * Emitted when the a tokenizer is updated.
+ **/
+ this.onTokenizerUpdate = function(e) {
+ var rows = e.data;
+ this.renderer.updateLines(rows.first, rows.last);
+ };
- if (content) {
- this.output(content);
- }
-
- // Ensure to finish the request only once.
- if (!this.isDone) {
- this.isDone = true;
- this._dispatchEvent('output', {});
- }
-};
-exports.Request = Request;
+ /**
+ * Editor@onScrollTopChange()
+ *
+ * Emitted when the scroll top changes.
+ **/
+ this.onScrollTopChange = function() {
+ this.renderer.scrollToY(this.session.getScrollTop());
+ };
+ /**
+ * Editor@onScrollLeftChange()
+ *
+ * Emitted when the scroll left changes.
+ **/
+ this.onScrollLeftChange = function() {
+ this.renderer.scrollToX(this.session.getScrollLeft());
+ };
-});
-/* ***** 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 Mozilla Skywriter.
- *
- * The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Joe Walker (jwalker@mozilla.com)
- * Patrick Walton (pwalton@mozilla.com)
- * Julian Viereck (jviereck@mozilla.com)
- *
- * 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('pilot/console', ['require', 'exports', 'module' ], function(require, exports, module) {
-
-/**
- * This object represents a "safe console" object that forwards debugging
- * messages appropriately without creating a dependency on Firebug in Firefox.
- */
+ /**
+ * Editor@onCursorChange()
+ *
+ * Emitted when the cursor changes.
+ **/
+ this.onCursorChange = function() {
+ this.$cursorChange();
-var noop = function() {};
-
-// These are the functions that are available in Chrome 4/5, Safari 4
-// and Firefox 3.6. Don't add to this list without checking browser support
-var NAMES = [
- "assert", "count", "debug", "dir", "dirxml", "error", "group", "groupEnd",
- "info", "log", "profile", "profileEnd", "time", "timeEnd", "trace", "warn"
-];
-
-if (typeof(window) === 'undefined') {
- // We're in a web worker. Forward to the main thread so the messages
- // will show up.
- NAMES.forEach(function(name) {
- exports[name] = function() {
- var args = Array.prototype.slice.call(arguments);
- var msg = { op: 'log', method: name, args: args };
- postMessage(JSON.stringify(msg));
- };
- });
-} else {
- // For each of the console functions, copy them if they exist, stub if not
- NAMES.forEach(function(name) {
- if (window.console && window.console[name]) {
- exports[name] = Function.prototype.bind.call(window.console[name], window.console);
- } else {
- exports[name] = noop;
+ if (!this.$blockScrolling) {
+ this.renderer.scrollCursorIntoView();
}
- });
-}
-});
-define('pilot/stacktrace', ['require', 'exports', 'module' , 'pilot/useragent', 'pilot/console'], function(require, exports, module) {
-
-var ua = require("pilot/useragent");
-var console = require('pilot/console');
-
-// Changed to suit the specific needs of running within Skywriter
-
-// Domain Public by Eric Wendelin http://eriwen.com/ (2008)
-// Luke Smith http://lucassmith.name/ (2008)
-// Loic Dachary (2008)
-// Johan Euphrosine (2008)
-// Øyvind Sean Kinsey http://kinsey.no/blog
-//
-// Information and discussions
-// http://jspoker.pokersource.info/skin/test-printstacktrace.html
-// http://eriwen.com/javascript/js-stack-trace/
-// http://eriwen.com/javascript/stacktrace-update/
-// http://pastie.org/253058
-// http://browsershots.org/http://jspoker.pokersource.info/skin/test-printstacktrace.html
-//
-
-//
-// guessFunctionNameFromLines comes from firebug
-//
-// Software License Agreement (BSD License)
-//
-// Copyright (c) 2007, Parakey Inc.
-// All rights reserved.
-//
-// Redistribution and use of this software in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above
-// copyright notice, this list of conditions and the
-// following disclaimer.
-//
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the
-// following disclaimer in the documentation and/or other
-// materials provided with the distribution.
-//
-// * Neither the name of Parakey Inc. nor the names of its
-// contributors may be used to endorse or promote products
-// derived from this software without specific prior
-// written permission of Parakey Inc.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
-// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
-// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ this.$highlightBrackets();
+ this.$updateHighlightActiveLine();
+ };
+ /** internal, hide
+ * Editor.$updateHighlightActiveLine()
+ *
+ *
+ **/
+ this.$updateHighlightActiveLine = function() {
+ var session = this.getSession();
+ if (session.$highlightLineMarker)
+ session.removeMarker(session.$highlightLineMarker);
-/**
- * Different browsers create stack traces in different ways.
- * Feature Browser detection baby ;).
- */
-var mode = (function() {
-
- // We use SC's browser detection here to avoid the "break on error"
- // functionality provided by Firebug. Firebug tries to do the right
- // thing here and break, but it happens every time you load the page.
- // bug 554105
- if (ua.isGecko) {
- return 'firefox';
- } else if (ua.isOpera) {
- return 'opera';
- } else {
- return 'other';
- }
+ session.$highlightLineMarker = null;
- // SC doesn't do any detection of Chrome at this time.
+ if (this.$highlightActiveLine) {
+ var cursor = this.getCursorPosition();
+ var foldLine = this.session.getFoldLine(cursor.row);
- // this is the original feature detection code that is used as a
- // fallback.
- try {
- (0)();
- } catch (e) {
- if (e.arguments) {
- return 'chrome';
- }
- if (e.stack) {
- return 'firefox';
- }
- if (window.opera && !('stacktrace' in e)) { //Opera 9-
- return 'opera';
+ 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");
+ }
}
- }
- return 'other';
-})();
+ };
-/**
- *
- */
-function stringifyArguments(args) {
- for (var i = 0; i < args.length; ++i) {
- var argument = args[i];
- if (typeof argument == 'object') {
- args[i] = '#object';
- } else if (typeof argument == 'function') {
- args[i] = '#function';
- } else if (typeof argument == 'string') {
- args[i] = '"' + argument + '"';
- }
- }
- return args.join(',');
-}
-/**
- * Extract a stack trace from the format emitted by each browser.
- */
-var decoders = {
- chrome: function(e) {
- var stack = e.stack;
- if (!stack) {
- console.log(e);
- return [];
- }
- return stack.replace(/^.*?\n/, '').
- replace(/^.*?\n/, '').
- replace(/^.*?\n/, '').
- replace(/^[^\(]+?[\n$]/gm, '').
- replace(/^\s+at\s+/gm, '').
- replace(/^Object.\s*\(/gm, '{anonymous}()@').
- split('\n');
- },
+ /**
+ * Editor@onSelectionChange(e)
+ * - e (Object): Contains a single property, `data`, which has the delta of changes
+ *
+ * Emitted when a selection has changed.
+ **/
+ this.onSelectionChange = function(e) {
+ var session = this.getSession();
- firefox: function(e) {
- var stack = e.stack;
- if (!stack) {
- console.log(e);
- return [];
+ if (session.$selectionMarker) {
+ session.removeMarker(session.$selectionMarker);
}
- // stack = stack.replace(/^.*?\n/, '');
- stack = stack.replace(/(?:\n@:0)?\s+$/m, '');
- stack = stack.replace(/^\(/gm, '{anonymous}(');
- return stack.split('\n');
- },
-
- // Opera 7.x and 8.x only!
- opera: function(e) {
- var lines = e.message.split('\n'), ANON = '{anonymous}',
- lineRE = /Line\s+(\d+).*?script\s+(http\S+)(?:.*?in\s+function\s+(\S+))?/i, i, j, len;
+ session.$selectionMarker = null;
- for (i = 4, j = 0, len = lines.length; i < len; i += 2) {
- if (lineRE.test(lines[i])) {
- lines[j++] = (RegExp.$3 ? RegExp.$3 + '()@' + RegExp.$2 + RegExp.$1 : ANON + '()@' + RegExp.$2 + ':' + RegExp.$1) +
- ' -- ' +
- lines[i + 1].replace(/^\s+/, '');
- }
+ if (!this.selection.isEmpty()) {
+ var range = this.selection.getRange();
+ var style = this.getSelectionStyle();
+ session.$selectionMarker = session.addMarker(range, "ace_selection", style);
+ } else {
+ this.$updateHighlightActiveLine();
}
- lines.splice(j, lines.length - j);
- return lines;
- },
+ if (this.$highlightSelectedWord)
+ this.session.getMode().highlightSelection(this);
+ };
- // Safari, Opera 9+, IE, and others
- other: function(curr) {
- var ANON = '{anonymous}', fnRE = /function\s*([\w\-$]+)?\s*\(/i, stack = [], j = 0, fn, args;
+ /**
+ * Editor@onChangeFrontMarker()
+ *
+ * Emitted when a front marker changes.
+ **/
+ this.onChangeFrontMarker = function() {
+ this.renderer.updateFrontMarkers();
+ };
- var maxStackSize = 10;
- while (curr && stack.length < maxStackSize) {
- fn = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON;
- args = Array.prototype.slice.call(curr['arguments']);
- stack[j++] = fn + '(' + stringifyArguments(args) + ')';
+ /**
+ * Editor@onChangeBackMarker()
+ *
+ * Emitted when a back marker changes.
+ **/
+ this.onChangeBackMarker = function() {
+ this.renderer.updateBackMarkers();
+ };
- //Opera bug: if curr.caller does not exist, Opera returns curr (WTF)
- if (curr === curr.caller && window.opera) {
- //TODO: check for same arguments if possible
- break;
- }
- curr = curr.caller;
- }
- return stack;
- }
-};
+ /**
+ * Editor@onChangeBreakpoint()
+ *
+ * Emitted when a breakpoint changes.
+ **/
+ this.onChangeBreakpoint = function() {
+ this.renderer.setBreakpoints(this.session.getBreakpoints());
+ };
-/**
- *
- */
-function NameGuesser() {
-}
+ /**
+ * Editor@onChangeAnnotation()
+ *
+ * Emitted when an annotation changes.
+ **/
+ this.onChangeAnnotation = function() {
+ this.renderer.setAnnotations(this.session.getAnnotations());
+ };
-NameGuesser.prototype = {
+ /**
+ * Editor@onChangeMode()
+ *
+ * Emitted when the mode changes.
+ **/
+ this.onChangeMode = function() {
+ this.renderer.updateText();
+ };
- sourceCache: {},
+ /**
+ * Editor@onChangeWrapLimit()
+ *
+ * Emitted when the wrap limit changes.
+ **/
+ this.onChangeWrapLimit = function() {
+ this.renderer.updateFull();
+ };
- ajax: function(url) {
- var req = this.createXMLHTTPObject();
- if (!req) {
- return;
- }
- req.open('GET', url, false);
- req.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
- req.send('');
- return req.responseText;
- },
+ /**
+ * Editor@onChangeWrapMode()
+ *
+ * Emitted when the wrap mode changes.
+ **/
+ this.onChangeWrapMode = function() {
+ this.renderer.onResize(true);
+ };
- createXMLHTTPObject: function() {
- // Try XHR methods in order and store XHR factory
- var xmlhttp, XMLHttpFactories = [
- function() {
- return new XMLHttpRequest();
- }, function() {
- return new ActiveXObject('Msxml2.XMLHTTP');
- }, function() {
- return new ActiveXObject('Msxml3.XMLHTTP');
- }, function() {
- return new ActiveXObject('Microsoft.XMLHTTP');
- }
- ];
- for (var i = 0; i < XMLHttpFactories.length; i++) {
- try {
- xmlhttp = XMLHttpFactories[i]();
- // Use memoization to cache the factory
- this.createXMLHTTPObject = XMLHttpFactories[i];
- return xmlhttp;
- } catch (e) {}
- }
- },
+ /**
+ * Editor@onChangeFold()
+ *
+ * Emitted when the code folds change.
+ **/
+ 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();
+ };
- getSource: function(url) {
- if (!(url in this.sourceCache)) {
- this.sourceCache[url] = this.ajax(url).split('\n');
- }
- return this.sourceCache[url];
- },
+ /**
+ * Editor.getCopyText() -> String
+ *
+ * Returns the string of text currently highlighted.
+ **/
+ this.getCopyText = function() {
+ var text = "";
+ if (!this.selection.isEmpty())
+ text = this.session.getTextRange(this.getSelectionRange());
- guessFunctions: function(stack) {
- for (var i = 0; i < stack.length; ++i) {
- var reStack = /{anonymous}\(.*\)@(\w+:\/\/([-\w\.]+)+(:\d+)?[^:]+):(\d+):?(\d+)?/;
- var frame = stack[i], m = reStack.exec(frame);
- if (m) {
- var file = m[1], lineno = m[4]; //m[7] is character position in Chrome
- if (file && lineno) {
- var functionName = this.guessFunctionName(file, lineno);
- stack[i] = frame.replace('{anonymous}', functionName);
- }
- }
- }
- return stack;
- },
+ this._emit("copy", text);
+ return text;
+ };
- guessFunctionName: function(url, lineNo) {
- try {
- return this.guessFunctionNameFromLines(lineNo, this.getSource(url));
- } catch (e) {
- return 'getSource failed with url: ' + url + ', exception: ' + e.toString();
- }
- },
+ /**
+ * Editor.onCopy()
+ *
+ * Called whenever a text "copy" happens.
+ **/
+ this.onCopy = function() {
+ this.commands.exec("copy", this);
+ };
- guessFunctionNameFromLines: function(lineNo, source) {
- var reFunctionArgNames = /function ([^(]*)\(([^)]*)\)/;
- var reGuessFunction = /['"]?([0-9A-Za-z_]+)['"]?\s*[:=]\s*(function|eval|new Function)/;
- // Walk backwards from the first line in the function until we find the line which
- // matches the pattern above, which is the function definition
- var line = '', maxLines = 10;
- for (var i = 0; i < maxLines; ++i) {
- line = source[lineNo - i] + line;
- if (line !== undefined) {
- var m = reGuessFunction.exec(line);
- if (m) {
- return m[1];
- }
- else {
- m = reFunctionArgNames.exec(line);
- }
- if (m && m[1]) {
- return m[1];
- }
- }
- }
- return '(?)';
- }
-};
+ /**
+ * Editor.onCut()
+ *
+ * called whenever a text "cut" happens.
+ **/
+ this.onCut = function() {
+ this.commands.exec("cut", this);
+ };
-var guesser = new NameGuesser();
+ /**
+ * Editor.onPaste()
+ *
+ * called whenever a text "paste" happens.
+ **/
+ this.onPaste = function(text) {
+ this._emit("paste", text);
+ this.insert(text);
+ };
-var frameIgnorePatterns = [
- /http:\/\/localhost:4020\/sproutcore.js:/
-];
+ /**
+ * Editor.insert(text)
+ * - text (String): The new text to add
+ *
+ * Inserts `text` into wherever the cursor is pointing.
+ **/
+ this.insert = function(text) {
+ var session = this.session;
+ var mode = session.getMode();
-exports.ignoreFramesMatching = function(regex) {
- frameIgnorePatterns.push(regex);
-};
+ var cursor = this.getCursorPosition();
-/**
- * Create a stack trace from an exception
- * @param ex {Error} The error to create a stacktrace from (optional)
- * @param guess {Boolean} If we should try to resolve the names of anonymous functions
- */
-exports.Trace = function Trace(ex, guess) {
- this._ex = ex;
- this._stack = decoders[mode](ex);
+ 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;
+ }
- if (guess) {
- this._stack = guesser.guessFunctions(this._stack);
- }
-};
+ text = text.replace("\t", this.session.getTabString());
-/**
- * Log to the console a number of lines (default all of them)
- * @param lines {number} Maximum number of lines to wrote to console
- */
-exports.Trace.prototype.log = function(lines) {
- if (lines <= 0) {
- // You aren't going to have more lines in your stack trace than this
- // and it still fits in a 32bit integer
- lines = 999999999;
- }
+ // 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);
+ }
- var printed = 0;
- for (var i = 0; i < this._stack.length && printed < lines; i++) {
- var frame = this._stack[i];
- var display = true;
- frameIgnorePatterns.forEach(function(regex) {
- if (regex.test(frame)) {
- display = false;
+ 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]));
}
- });
- if (display) {
- console.debug(frame);
- printed++;
}
- }
-};
-});
-/* ***** 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 ***** */
+ var lineState = session.getState(cursor.row);
-define('pilot/useragent', ['require', 'exports', 'module' ], function(require, exports, module) {
+ // 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 os = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase();
-var ua = navigator.userAgent;
-var av = navigator.appVersion;
+ var size = session.getTabSize();
+ var minIndent = Number.MAX_VALUE;
-/** Is the user using a browser that identifies itself as Windows */
-exports.isWin = (os == "win");
+ for (var row = cursor.row + 1; row <= end.row; ++row) {
+ var indent = 0;
-/** Is the user using a browser that identifies itself as Mac OS */
-exports.isMac = (os == "mac");
+ 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);
+ }
-/** Is the user using a browser that identifies itself as Linux */
-exports.isLinux = (os == "linux");
+ for (var row = cursor.row + 1; row <= end.row; ++row) {
+ var outdent = minIndent;
-exports.isIE = ! + "\v1";
+ 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);
+ };
-/** Is this Firefox or related? */
-exports.isGecko = exports.isMozilla = window.controllers && window.navigator.product === "Gecko";
+ /**
+ * Editor@onTextInput(text, pasted)
+ * - text (String): The text entered
+ * - pasted (Boolean): Identifies whether the text was pasted (`true`) or not
+ *
+ * Emitted when text is entered.
+ **/
+ this.onTextInput = function(text) {
+ this.keyBinding.onTextInput(text);
+ };
-/** oldGecko == rev < 2.0 **/
-exports.isOldGecko = exports.isGecko && /rv\:1/.test(navigator.userAgent);
+ /**
+ * Editor@onCommandKey(e, hashId, keyCode)
+ *
+ * Emitted when the command-key is pressed.
+ **/
+ this.onCommandKey = function(e, hashId, keyCode) {
+ this.keyBinding.onCommandKey(e, hashId, keyCode);
+ };
-/** Is this Opera */
-exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]";
+ /** related to: EditSession.setOverwrite
+ * Editor.setOverwrite(overwrite)
+ * - overwrite (Boolean): Defines wheter or not to set overwrites
+ *
+ * Pass in `true` to enable overwrites in your session, or `false` to disable. If overwrites is enabled, any text you enter will type over any text after it. If the value of `overwrite` changes, this function also emites the `changeOverwrite` event.
+ *
+ **/
+ this.setOverwrite = function(overwrite) {
+ this.session.setOverwrite(overwrite);
+ };
-/** Is the user using a browser that identifies itself as WebKit */
-exports.isWebKit = parseFloat(ua.split("WebKit/")[1]) || undefined;
+ /** related to: EditSession.getOverwrite
+ * Editor.getOverwrite() -> Boolean
+ *
+ * Returns `true` if overwrites are enabled; `false` otherwise.
+ **/
+ this.getOverwrite = function() {
+ return this.session.getOverwrite();
+ };
-exports.isChrome = parseFloat(ua.split(" Chrome/")[1]) || undefined;
+ /** related to: EditSession.toggleOverwrite
+ * Editor.toggleOverwrite()
+ *
+ * Sets the value of overwrite to the opposite of whatever it currently is.
+ **/
+ this.toggleOverwrite = function() {
+ this.session.toggleOverwrite();
+ };
-exports.isAIR = ua.indexOf("AdobeAIR") >= 0;
+ /**
+ * Editor.setScrollSpeed(speed)
+ * - speed (Number): A value indicating the new speed
+ *
+ * Sets how fast the mouse scrolling should do.
+ *
+ **/
+ this.setScrollSpeed = function(speed) {
+ this.$mouseHandler.setScrollSpeed(speed);
+ };
-exports.isIPad = ua.indexOf("iPad") >= 0;
+ /**
+ * Editor.getScrollSpeed() -> Number
+ *
+ * Returns the value indicating how fast the mouse scroll speed is.
+ **/
+ this.getScrollSpeed = function() {
+ return this.$mouseHandler.getScrollSpeed();
+ };
-/**
- * I hate doing this, but we need some way to determine if the user is on a Mac
- * The reason is that users have different expectations of their key combinations.
- *
- * Take copy as an example, Mac people expect to use CMD or APPLE + C
- * Windows folks expect to use CTRL + C
- */
-exports.OS = {
- LINUX: 'LINUX',
- MAC: 'MAC',
- WINDOWS: 'WINDOWS'
-};
+ /**
+ * Editor.setDragDelay(dragDelay)
+ * - dragDelay (Number): A value indicating the new delay
+ *
+ * Sets the delay (in milliseconds) of the mouse drag.
+ *
+ **/
+ this.setDragDelay = function(dragDelay) {
+ this.$mouseHandler.setDragDelay(dragDelay);
+ };
-/**
- * Return an exports.OS constant
- */
-exports.getOS = function() {
- if (exports.isMac) {
- return exports.OS['MAC'];
- } else if (exports.isLinux) {
- return exports.OS['LINUX'];
- } else {
- return exports.OS['WINDOWS'];
- }
-};
+ /**
+ * Editor.getDragDelay() -> Number
+ *
+ * Returns the current mouse drag delay.
+ **/
+ this.getDragDelay = function() {
+ return this.$mouseHandler.getDragDelay();
+ };
-});
-/* ***** 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 ***** */
+ this.$selectionStyle = "line";
+ /**
+ * Editor.setSelectionStyle(style)
+ * - style (String): The new selection style
+ *
+ * Indicates how selections should occur. By default, selections are set to "line". This function also emits the `'changeSelectionStyle'` event.
+ *
+ **/
+ this.setSelectionStyle = function(style) {
+ if (this.$selectionStyle == style) return;
-define('pilot/oop', ['require', 'exports', 'module' ], function(require, exports, module) {
+ this.$selectionStyle = style;
+ this.onSelectionChange();
+ this._emit("changeSelectionStyle", {data: style});
+ };
-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;
- }
-}());
+ /**
+ * Editor.getSelectionStyle() -> String
+ *
+ * Returns the current selection style.
+ **/
+ this.getSelectionStyle = function() {
+ return this.$selectionStyle;
+ };
-exports.mixin = function(obj, mixin) {
- for (var key in mixin) {
- obj[key] = mixin[key];
- }
-};
+ this.$highlightActiveLine = true;
-exports.implement = function(proto, mixin) {
- exports.mixin(proto, mixin);
-};
+ /**
+ * Editor.setHighlightActiveLine(shouldHighlight)
+ * - shouldHighlight (Boolean): Set to `true` to highlight the current line
+ *
+ * Determines whether or not the current line should be highlighted.
+ *
+ **/
+ this.setHighlightActiveLine = function(shouldHighlight) {
+ if (this.$highlightActiveLine == shouldHighlight)
+ return;
-});
-/*! @license
-==========================================================================
-SproutCore -- JavaScript Application Framework
-copyright 2006-2009, Sprout Systems Inc., Apple Inc. and contributors.
+ this.$highlightActiveLine = shouldHighlight;
+ this.$updateHighlightActiveLine();
+ };
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
+ /**
+ * Editor.getHighlightActiveLine() -> Boolean
+ *
+ * Returns `true` if current lines are always highlighted.
+ **/
+ this.getHighlightActiveLine = function() {
+ return this.$highlightActiveLine;
+ };
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
+ this.$highlightGutterLine = true;
+ this.setHighlightGutterLine = function(shouldHighlight) {
+ if (this.$highlightGutterLine == shouldHighlight)
+ return;
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
+ this.renderer.setHighlightGutterLine(shouldHighlight);
+ };
-SproutCore and the SproutCore logo are trademarks of Sprout Systems, Inc.
+ this.getHighlightGutterLine = function() {
+ return this.$highlightGutterLine;
+ };
-For more information about SproutCore, visit http://www.sproutcore.com
+ this.$highlightSelectedWord = true;
+ /**
+ * Editor.setHighlightSelectedWord(shouldHighlight)
+ * - shouldHighlight (Boolean): Set to `true` to highlight the currently selected word
+ *
+ * Determines if the currently selected word should be highlighted.
+ **/
+ this.setHighlightSelectedWord = function(shouldHighlight) {
+ if (this.$highlightSelectedWord == shouldHighlight)
+ return;
+ this.$highlightSelectedWord = shouldHighlight;
+ if (shouldHighlight)
+ this.session.getMode().highlightSelection(this);
+ else
+ this.session.getMode().clearSelectionHighlight(this);
+ };
-==========================================================================
-@license */
+ /**
+ * Editor.getHighlightSelectedWord() -> Boolean
+ *
+ * Returns `true` if currently highlighted words are to be highlighted.
+ **/
+ this.getHighlightSelectedWord = function() {
+ return this.$highlightSelectedWord;
+ };
-// Most of the following code is taken from SproutCore with a few changes.
+ this.setAnimatedScroll = function(shouldAnimate){
+ this.renderer.setAnimatedScroll(shouldAnimate);
+ };
-define('pilot/keys', ['require', 'exports', 'module' , 'pilot/oop'], function(require, exports, module) {
+ this.getAnimatedScroll = function(){
+ return this.renderer.getAnimatedScroll();
+ };
-var oop = require("pilot/oop");
+ /**
+ * Editor.setShowInvisibles(showInvisibles)
+ * - showInvisibles (Boolean): Specifies whether or not to show invisible characters
+ *
+ * If `showInvisibiles` is set to `true`, invisible characters—like spaces or new lines—are show in the editor.
+ **/
+ this.setShowInvisibles = function(showInvisibles) {
+ if (this.getShowInvisibles() == showInvisibles)
+ return;
-/**
- * Helper functions and hashes for key handling.
- */
-var Keys = (function() {
- var ret = {
- MODIFIER_KEYS: {
- 16: 'Shift', 17: 'Ctrl', 18: 'Alt', 224: 'Meta'
- },
+ this.renderer.setShowInvisibles(showInvisibles);
+ };
- KEY_MODS: {
- "ctrl": 1, "alt": 2, "option" : 2,
- "shift": 4, "meta": 8, "command": 8
- },
+ /**
+ * Editor.getShowInvisibles() -> Boolean
+ *
+ * Returns `true` if invisible characters are being shown.
+ **/
+ this.getShowInvisibles = function() {
+ return this.renderer.getShowInvisibles();
+ };
- 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",
- 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"
- },
+ /**
+ * Editor.setShowPrintMargin(showPrintMargin)
+ * - showPrintMargin (Boolean): Specifies whether or not to show the print margin
+ *
+ * If `showPrintMargin` is set to `true`, the print margin is shown in the editor.
+ **/
+ this.setShowPrintMargin = function(showPrintMargin) {
+ this.renderer.setShowPrintMargin(showPrintMargin);
+ };
- 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: '\"'
- }
+ /**
+ * Editor.getShowPrintMargin() -> Boolean
+ *
+ * Returns `true` if the print margin is being shown.
+ **/
+ this.getShowPrintMargin = function() {
+ return this.renderer.getShowPrintMargin();
};
- // A reverse map of FUNCTION_KEYS
- for (i in ret.FUNCTION_KEYS) {
- var name = ret.FUNCTION_KEYS[i].toUpperCase();
- ret[name] = parseInt(i, 10);
- }
+ /**
+ * Editor.setPrintMarginColumn(showPrintMargin)
+ * - showPrintMargin (Number): Specifies the new print margin
+ *
+ * Sets the column defining where the print margin should be.
+ *
+ **/
+ this.setPrintMarginColumn = function(showPrintMargin) {
+ this.renderer.setPrintMarginColumn(showPrintMargin);
+ };
- // 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);
+ /**
+ * Editor.getPrintMarginColumn() -> Number
+ *
+ * Returns the column number of where the print margin is.
+ **/
+ this.getPrintMarginColumn = function() {
+ return this.renderer.getPrintMarginColumn();
+ };
- return ret;
-})();
-oop.mixin(exports, Keys);
+ this.$readOnly = false;
+ /**
+ * Editor.setReadOnly(readOnly)
+ * - readOnly (Boolean): Specifies whether the editor can be modified or not
+ *
+ * If `readOnly` is true, then the editor is set to read-only mode, and none of the content can change.
+ **/
+ this.setReadOnly = function(readOnly) {
+ this.$readOnly = readOnly;
+ };
-exports.keyCodeToString = function(keyCode) {
- return (Keys[keyCode] || String.fromCharCode(keyCode)).toLowerCase();
-}
-
-});
-/* vim:ts=4:sts=4:sw=4:
- * ***** 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
- * Irakli Gozalishvili (http://jeditoolkit.com)
- *
- * 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 ***** */
+ /**
+ * Editor.getReadOnly() -> Boolean
+ *
+ * Returns `true` if the editor is set to read-only mode.
+ **/
+ this.getReadOnly = function() {
+ return this.$readOnly;
+ };
-define('pilot/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) {
+ this.$modeBehaviours = true;
-var EventEmitter = {};
+ /**
+ * Editor.setBehavioursEnabled()
+ * - enabled (Boolean): Enables or disables behaviors
+ *
+ * Specifies whether to use behaviors or not. ["Behaviors" in this case is the auto-pairing of special characters, like quotation marks, parenthesis, or brackets.]{: #BehaviorsDef}
+ **/
+ this.setBehavioursEnabled = function (enabled) {
+ this.$modeBehaviours = enabled;
+ };
-EventEmitter._emit =
-EventEmitter._dispatchEvent = function(eventName, e) {
- this._eventRegistry = this._eventRegistry || {};
+ /**
+ * Editor.getBehavioursEnabled() -> Boolean
+ *
+ * Returns `true` if the behaviors are currently enabled. {:BehaviorsDef}
+ **/
+ this.getBehavioursEnabled = function () {
+ return this.$modeBehaviours;
+ };
- var listeners = this._eventRegistry[eventName];
- if (!listeners || !listeners.length) return;
+ /**
+ * Editor.setShowFoldWidgets(show)
+ * - show (Boolean): Specifies whether the fold widgets are shown
+ *
+ * Indicates whether the fold widgets are shown or not.
+ **/
+ this.setShowFoldWidgets = function(show) {
+ var gutter = this.renderer.$gutterLayer;
+ if (gutter.getShowFoldWidgets() == show)
+ return;
- var e = e || {};
- e.type = eventName;
+ this.renderer.$gutterLayer.setShowFoldWidgets(show);
+ this.$showFoldWidgets = show;
+ this.renderer.updateFull();
+ };
- for (var i=0; i Boolean
+ *
+ * Returns `true` if the fold widgets are shown.
+ **/
+ this.getShowFoldWidgets = function() {
+ return this.renderer.$gutterLayer.getShowFoldWidgets();
+ };
-EventEmitter.on =
-EventEmitter.addEventListener = function(eventName, callback) {
- this._eventRegistry = this._eventRegistry || {};
+ this.setFadeFoldWidgets = function(show) {
+ this.renderer.setFadeFoldWidgets(show);
+ };
- var listeners = this._eventRegistry[eventName];
- if (!listeners) {
- var listeners = this._eventRegistry[eventName] = [];
- }
- if (listeners.indexOf(callback) == -1) {
- listeners.push(callback);
- }
-};
+ this.getFadeFoldWidgets = function() {
+ return this.renderer.getFadeFoldWidgets();
+ };
-EventEmitter.removeListener =
-EventEmitter.removeEventListener = function(eventName, callback) {
- this._eventRegistry = this._eventRegistry || {};
+ /**
+ * Editor.remove(dir)
+ * - dir (String): The direction of the deletion to occur, either "left" or "right"
+ *
+ * Removes words of text from the editor. A "word" is defined as a string of characters bookended by whitespace.
+ *
+ **/
+ this.remove = function(dir) {
+ if (this.selection.isEmpty()){
+ if (dir == "left")
+ this.selection.selectLeft();
+ else
+ this.selection.selectRight();
+ }
- var listeners = this._eventRegistry[eventName];
- if (!listeners) {
- return;
- }
- var index = listeners.indexOf(callback);
- if (index !== -1) {
- listeners.splice(index, 1);
- }
-};
+ 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;
+ }
-EventEmitter.removeAllListeners = function(eventName) {
- if (this._eventRegistry) this._eventRegistry[eventName] = [];
-}
+ this.session.remove(range);
+ this.clearSelection();
+ };
-exports.EventEmitter = EventEmitter;
+ /**
+ * Editor.removeWordRight()
+ *
+ * Removes the word directly to the right of the current selection.
+ **/
+ this.removeWordRight = function() {
+ if (this.selection.isEmpty())
+ this.selection.selectWordRight();
-});
-/* ***** 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 Skywriter.
- *
- * The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Joe Walker (jwalker@mozilla.com)
- *
- * 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 ***** */
+ this.session.remove(this.getSelectionRange());
+ this.clearSelection();
+ };
-define('pilot/typecheck', ['require', 'exports', 'module' ], function(require, exports, module) {
+ /**
+ * Editor.removeWordLeft()
+ *
+ * Removes the word directly to the left of the current selection.
+ **/
+ this.removeWordLeft = function() {
+ if (this.selection.isEmpty())
+ this.selection.selectWordLeft();
-var objectToString = Object.prototype.toString;
+ this.session.remove(this.getSelectionRange());
+ this.clearSelection();
+ };
-/**
- * Return true if it is a String
- */
-exports.isString = function(it) {
- return it && objectToString.call(it) === "[object String]";
-};
+ /**
+ * Editor.removeToLineStart()
+ *
+ * Removes all the words to the left of the current selection, until the start of the line.
+ **/
+ this.removeToLineStart = function() {
+ if (this.selection.isEmpty())
+ this.selection.selectLineStart();
-/**
- * Returns true if it is a Boolean.
- */
-exports.isBoolean = function(it) {
- return it && objectToString.call(it) === "[object Boolean]";
-};
+ this.session.remove(this.getSelectionRange());
+ this.clearSelection();
+ };
-/**
- * Returns true if it is a Number.
- */
-exports.isNumber = function(it) {
- return it && objectToString.call(it) === "[object Number]" && isFinite(it);
-};
+ /**
+ * Editor.removeToLineEnd()
+ *
+ * Removes all the words to the right of the current selection, until the end of the line.
+ **/
+ this.removeToLineEnd = function() {
+ if (this.selection.isEmpty())
+ this.selection.selectLineEnd();
-/**
- * Hack copied from dojo.
- */
-exports.isObject = function(it) {
- return it !== undefined &&
- (it === null || typeof it == "object" ||
- Array.isArray(it) || exports.isFunction(it));
-};
+ var range = this.getSelectionRange();
+ if (range.start.column == range.end.column && range.start.row == range.end.row) {
+ range.end.column = 0;
+ range.end.row++;
+ }
-/**
- * Is the passed object a function?
- * From dojo.isFunction()
- */
-exports.isFunction = function(it) {
- return it && objectToString.call(it) === "[object Function]";
-};
+ this.session.remove(range);
+ this.clearSelection();
+ };
-});/* ***** 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 Mozilla Skywriter.
- *
- * The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Julian Viereck (jviereck@mozilla.com)
- *
- * 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 ***** */
+ /**
+ * Editor.splitLine()
+ *
+ * Splits the line at the current selection (by inserting an `'\n'`).
+ **/
+ this.splitLine = function() {
+ if (!this.selection.isEmpty()) {
+ this.session.remove(this.getSelectionRange());
+ this.clearSelection();
+ }
-define('pilot/catalog', ['require', 'exports', 'module' ], function(require, exports, module) {
+ var cursor = this.getCursorPosition();
+ this.insert("\n");
+ this.moveCursorToPosition(cursor);
+ };
+ /**
+ * Editor.transposeLetters()
+ *
+ * Transposes current line.
+ **/
+ this.transposeLetters = function() {
+ if (!this.selection.isEmpty()) {
+ return;
+ }
-var extensionSpecs = {};
+ var cursor = this.getCursorPosition();
+ var column = cursor.column;
+ if (column === 0)
+ return;
-exports.addExtensionSpec = function(extensionSpec) {
- extensionSpecs[extensionSpec.name] = extensionSpec;
-};
+ 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);
+ };
-exports.removeExtensionSpec = function(extensionSpec) {
- if (typeof extensionSpec === "string") {
- delete extensionSpecs[extensionSpec];
- }
- else {
- delete extensionSpecs[extensionSpec.name];
- }
-};
+ /**
+ * Editor.toLowerCase()
+ *
+ * Converts the current selection entirely into lowercase.
+ **/
+ this.toLowerCase = function() {
+ var originalRange = this.getSelectionRange();
+ if (this.selection.isEmpty()) {
+ this.selection.selectWord();
+ }
-exports.getExtensionSpec = function(name) {
- return extensionSpecs[name];
-};
+ var range = this.getSelectionRange();
+ var text = this.session.getTextRange(range);
+ this.session.replace(range, text.toLowerCase());
+ this.selection.setSelectionRange(originalRange);
+ };
-exports.getExtensionSpecs = function() {
- return Object.keys(extensionSpecs);
-};
+ /**
+ * Editor.toUpperCase()
+ *
+ * Converts the current selection entirely into uppercase.
+ **/
+ 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);
+ };
-});
-/* ***** 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 ***** */
+ /** related to: EditSession.indentRows
+ * Editor.indent()
+ *
+ * Indents the current line.
+ **/
+ this.indent = function() {
+ var session = this.session;
+ var range = this.getSelectionRange();
-define('pilot/lang', ['require', 'exports', 'module' ], function(require, exports, module) {
+ 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;
-exports.stringReverse = function(string) {
- return string.split("").reverse().join("");
-};
+ if (this.session.getUseSoftTabs()) {
+ var size = session.getTabSize(),
+ position = this.getCursorPosition(),
+ column = session.documentToScreenColumn(position.row, position.column),
+ count = (size - column % size);
-exports.stringRepeat = function (string, count) {
- return new Array(count + 1).join(string);
-};
+ indentString = lang.stringRepeat(" ", count);
+ } else
+ indentString = "\t";
+ return this.insert(indentString);
+ }
+ };
-var trimBeginRegexp = /^\s\s*/;
-var trimEndRegexp = /\s\s*$/;
+ /** related to: EditSession.outdentRows
+ * Editor.blockOutdent()
+ *
+ * Outdents the current line.
+ **/
+ this.blockOutdent = function() {
+ var selection = this.session.getSelection();
+ this.session.outdentRows(selection.getRange());
+ };
-exports.stringTrimLeft = function (string) {
- return string.replace(trimBeginRegexp, '')
-};
+ /**
+ * Editor.toggleCommentLines()
+ *
+ * Given the currently selected range, this function either comments all lines or uncomments all lines (depending on whether it's commented or not).
+ **/
+ 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);
+ };
-exports.stringTrimRight = function (string) {
- return string.replace(trimEndRegexp, '');
-};
+ /** related to: EditSession.remove
+ * Editor.removeLines()
+ *
+ * Removes all the lines in the current selection
+ **/
+ 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();
+ };
-exports.copyObject = function(obj) {
- var copy = {};
- for (var key in obj) {
- copy[key] = obj[key];
- }
- return copy;
-};
+ /** related to: EditSession.moveLinesDown
+ * Editor.moveLinesDown() -> Number
+ * + (Number): On success, it returns -1.
+ *
+ * Shifts all the selected lines down one row.
+ *
+ *
+ *
+ **/
+ this.moveLinesDown = function() {
+ this.$moveLines(function(firstRow, lastRow) {
+ return this.session.moveLinesDown(firstRow, lastRow);
+ });
+ };
-exports.copyArray = function(array){
- var copy = [];
- for (i=0, l=array.length; i Number
+ * + (Number): On success, it returns -1.
+ *
+ * Shifts all the selected lines up one row.
+ *
+ *
+ **/
+ this.moveLinesUp = function() {
+ this.$moveLines(function(firstRow, lastRow) {
+ return this.session.moveLinesUp(firstRow, lastRow);
+ });
+ };
-exports.deepCopy = function (obj) {
- if (typeof obj != "object") {
- return obj;
- }
-
- var copy = obj.constructor();
- for (var key in obj) {
- if (typeof obj[key] == "object") {
- copy[key] = this.deepCopy(obj[key]);
- } else {
- copy[key] = obj[key];
- }
- }
- return copy;
-}
+ /** related to: EditSession.moveText
+ * Editor.moveText(fromRange, toPosition) -> Range
+ * - fromRange (Range): The range of text you want moved within the document
+ * - toPosition (Object): The location (row and column) where you want to move the text to
+ * + (Range): The new range where the text was moved to.
+ *
+ * Moves a range of text from the given range to the given position. `toPosition` is an object that looks like this:
+ *
+ * { row: newRowLocation, column: newColumnLocation }
+ *
+ *
+ **/
+ this.moveText = function(range, toPosition) {
+ if (this.$readOnly)
+ return null;
-exports.arrayToMap = function(arr) {
- var map = {};
- for (var i=0; i Number
+ * + (Number): On success, returns 0.
+ *
+ * Copies all the selected lines up one row.
+ *
+ *
+ **/
+ this.copyLinesUp = function() {
+ this.$moveLines(function(firstRow, lastRow) {
+ this.session.duplicateLines(firstRow, lastRow);
+ return 0;
+ });
+ };
-/**
- * splice out of 'array' anything that === 'value'
- */
-exports.arrayRemove = function(array, value) {
- for (var i = 0; i <= array.length; i++) {
- if (value === array[i]) {
- array.splice(i, 1);
- }
- }
-};
+ /** related to: EditSession.duplicateLines
+ * Editor.copyLinesDown() -> Number
+ * + (Number): On success, returns the number of new rows added; in other words, `lastRow - firstRow + 1`.
+ *
+ * Copies all the selected lines down one row.
+ *
+ *
+ *
+ **/
+ this.copyLinesDown = function() {
+ this.$moveLines(function(firstRow, lastRow) {
+ return this.session.duplicateLines(firstRow, lastRow);
+ });
+ };
-exports.escapeRegExp = function(str) {
- return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
-};
-exports.deferredCall = function(fcn) {
+ /**
+ * Editor.$moveLines(mover)
+ * - mover (Function): A method to call on each selected row
+ *
+ * Executes a specific function, which can be anything that manipulates selected lines, such as copying them, duplicating them, or shifting them.
+ *
+ **/
+ this.$moveLines = function(mover) {
+ var rows = this.$getSelectedRows();
+ var selection = this.selection;
+ if (!selection.isMultiLine()) {
+ var range = selection.getRange();
+ var reverse = selection.isBackwards();
+ }
- var timer = null;
- var callback = function() {
- timer = null;
- fcn();
- };
+ var linesMoved = mover.call(this, rows.first, rows.last);
- var deferred = function(timeout) {
- if (!timer) {
- timer = setTimeout(callback, timeout || 0);
+ if (range) {
+ range.start.row += linesMoved;
+ range.end.row += linesMoved;
+ selection.setSelectionRange(range, reverse);
}
- return deferred;
- }
+ else {
+ selection.setSelectionAnchor(rows.last+linesMoved+1, 0);
+ selection.$moveSelection(function() {
+ selection.moveCursorTo(rows.first+linesMoved, 0);
+ });
+ }
+ };
- deferred.schedule = deferred;
+ /**
+ * Editor.$getSelectedRows() -> Object
+ *
+ * Returns an object indicating the currently selected rows. The object looks like this:
+ *
+ * { first: range.start.row, last: range.end.row }
+ *
+ **/
+ this.$getSelectedRows = function() {
+ var range = this.getSelectionRange().collapseRows();
- deferred.call = function() {
- this.cancel();
- fcn();
- return deferred;
+ return {
+ first: range.start.row,
+ last: range.end.row
+ };
};
- deferred.cancel = function() {
- clearTimeout(timer);
- timer = null;
- return deferred;
+ /** internal, hide
+ * Editor@onCompositionStart(text)
+ * - text (String): The text being written
+ *
+ *
+ **/
+ this.onCompositionStart = function(text) {
+ this.renderer.showComposition(this.getCursorPosition());
};
- return deferred;
-};
-
-});
-/* ***** 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 Mozilla Skywriter.
- *
- * The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Joe Walker (jwalker@mozilla.com)
- * Kevin Dangoor (kdangoor@mozilla.com)
- *
- * 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 ***** */
+ /** internal, hide
+ * Editor@onCompositionUpdate(text)
+ * - text (String): The text being written
+ *
+ *
+ **/
+ this.onCompositionUpdate = function(text) {
+ this.renderer.setCompositionText(text);
+ };
-define('pilot/types/settings', ['require', 'exports', 'module' , 'pilot/types/basic', 'pilot/types', 'pilot/settings'], function(require, exports, module) {
+ /** internal, hide
+ * Editor@onCompositionEnd()
+ *
+ *
+ **/
+ this.onCompositionEnd = function() {
+ this.renderer.hideComposition();
+ };
-var SelectionType = require('pilot/types/basic').SelectionType;
-var DeferredType = require('pilot/types/basic').DeferredType;
-var types = require('pilot/types');
-var settings = require('pilot/settings').settings;
+ /** related to: VirtualRenderer.getFirstVisibleRow
+ * Editor.getFirstVisibleRow() -> Number
+ *
+ * {:VirtualRenderer.getFirstVisibleRow}
+ **/
+ this.getFirstVisibleRow = function() {
+ return this.renderer.getFirstVisibleRow();
+ };
+ /** related to: VirtualRenderer.getLastVisibleRow
+ * Editor.getLastVisibleRow() -> Number
+ *
+ * {:VirtualRenderer.getLastVisibleRow}
+ **/
+ this.getLastVisibleRow = function() {
+ return this.renderer.getLastVisibleRow();
+ };
-/**
- * EVIL: This relies on us using settingValue in the same event as setting
- * The alternative is to have some central place where we store the current
- * command line, but this might be a lesser evil for now.
- */
-var lastSetting;
+ /**
+ * Editor.isRowVisible(row) -> Boolean
+ * - row (Number): The row to check
+ *
+ * Indicates if the row is currently visible on the screen.
+ **/
+ this.isRowVisible = function(row) {
+ return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow());
+ };
-/**
- * Select from the available settings
- */
-var setting = new SelectionType({
- name: 'setting',
- data: function() {
- return env.settings.getSettingNames();
- },
- stringify: function(setting) {
- lastSetting = setting;
- return setting.name;
- },
- fromString: function(str) {
- lastSetting = settings.getSetting(str);
- return lastSetting;
- },
- noMatch: function() {
- lastSetting = null;
- }
-});
+ /**
+ * Editor.isRowFullyVisible(row) -> Boolean
+ * - row (Number): The row to check
+ *
+ * Indicates if the entire row is currently visible on the screen.
+ **/
+ this.isRowFullyVisible = function(row) {
+ return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow());
+ };
-/**
- * Something of a hack to allow the set command to give a clearer definition
- * of the type to the command line.
- */
-var settingValue = new DeferredType({
- name: 'settingValue',
- defer: function() {
- if (lastSetting) {
- return lastSetting.type;
- }
- else {
- return types.getType('text');
- }
- },
/**
- * Promote the current value in any list of predictions, and add it if
- * there are none.
- */
- getDefault: function() {
- var conversion = this.parse('');
- if (lastSetting) {
- var current = lastSetting.get();
- if (conversion.predictions.length === 0) {
- conversion.predictions.push(current);
- }
- else {
- // Remove current from predictions
- var removed = false;
- while (true) {
- var index = conversion.predictions.indexOf(current);
- if (index === -1) {
- break;
- }
- conversion.predictions.splice(index, 1);
- removed = true;
- }
- // If the current value wasn't something we would predict, leave it
- if (removed) {
- conversion.predictions.push(current);
- }
- }
+ * Editor.$getVisibleRowCount() -> Number
+ *
+ * Returns the number of currently visibile rows.
+ **/
+ 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();
}
- return conversion;
- }
-});
+ this.$blockScrolling--;
-var env;
+ var scrollTop = renderer.scrollTop;
-/**
- * Registration and de-registration.
- */
-exports.startup = function(data, reason) {
- // TODO: this is probably all kinds of evil, but we need something working
- env = data.env;
- types.registerType(setting);
- types.registerType(settingValue);
-};
+ renderer.scrollBy(0, rows * config.lineHeight);
+ if (select != null)
+ renderer.scrollCursorIntoView(null, 0.5);
-exports.shutdown = function(data, reason) {
- types.unregisterType(setting);
- types.unregisterType(settingValue);
-};
+ renderer.animateScrolling(scrollTop);
+ };
+ /**
+ * Editor.selectPageDown()
+ *
+ * Selects the text from the current position of the document until where a "page down" finishes.
+ **/
+ this.selectPageDown = function() {
+ this.$moveByPage(1, true);
+ };
-});
-/* vim:ts=4:sts=4:sw=4:
- * ***** 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 Mozilla Skywriter.
- *
- * The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Joe Walker (jwalker@mozilla.com)
- * Julian Viereck (jviereck@mozilla.com)
- * Kevin Dangoor (kdangoor@mozilla.com)
- * Irakli Gozalishvili (http://jeditoolkit.com)
- *
- * 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 ***** */
+ /**
+ * Editor.selectPageUp()
+ *
+ * Selects the text from the current position of the document until where a "page up" finishes.
+ **/
+ this.selectPageUp = function() {
+ this.$moveByPage(-1, true);
+ };
-define('pilot/settings', ['require', 'exports', 'module' , 'pilot/console', 'pilot/oop', 'pilot/types', 'pilot/event_emitter', 'pilot/catalog'], function(require, exports, module) {
+ /**
+ * Editor.gotoPageDown()
+ *
+ * Shifts the document to wherever "page down" is, as well as moving the cursor position.
+ **/
+ this.gotoPageDown = function() {
+ this.$moveByPage(1, false);
+ };
-/**
- * This plug-in manages settings.
- */
+ /**
+ * Editor.gotoPageUp()
+ *
+ * Shifts the document to wherever "page up" is, as well as moving the cursor position.
+ **/
+ this.gotoPageUp = function() {
+ this.$moveByPage(-1, false);
+ };
-var console = require('pilot/console');
-var oop = require('pilot/oop');
-var types = require('pilot/types');
-var EventEmitter = require('pilot/event_emitter').EventEmitter;
-var catalog = require('pilot/catalog');
-
-var settingExtensionSpec = {
- name: 'setting',
- description: 'A setting is something that the application offers as a ' +
- 'way to customize how it works',
- register: 'env.settings.addSetting',
- indexOn: 'name'
-};
+ /**
+ * Editor.scrollPageDown()
+ *
+ * Scrolls the document to wherever "page down" is, without changing the cursor position.
+ **/
+ this.scrollPageDown = function() {
+ this.$moveByPage(1);
+ };
-exports.startup = function(data, reason) {
- catalog.addExtensionSpec(settingExtensionSpec);
-};
+ /**
+ * Editor.scrollPageUp()
+ *
+ * Scrolls the document to wherever "page up" is, without changing the cursor position.
+ **/
+ this.scrollPageUp = function() {
+ this.$moveByPage(-1);
+ };
-exports.shutdown = function(data, reason) {
- catalog.removeExtensionSpec(settingExtensionSpec);
-};
+ /** related to: VirtualRenderer.scrollToRow
+ * Editor.scrollToRow(row)
+ * - row (Number): The row to move to
+ *
+ * Moves the editor to the specified row.
+ *
+ **/
+ this.scrollToRow = function(row) {
+ this.renderer.scrollToRow(row);
+ };
+ /** related to: VirtualRenderer.scrollToLine
+ * Editor.scrollToLine(line, center)
+ * - line (Number): The line to scroll to
+ * - center (Boolean): If `true`
+ * - animate (Boolean): If `true` animates scrolling
+ * - callback (Function): Function to be called when the animation has finished
+ *
+ * TODO scrolls a to line, if center == true, puts line in middle of screen or attempts to)
+ **/
+ this.scrollToLine = function(line, center, animate, callback) {
+ this.renderer.scrollToLine(line, center, animate, callback);
+ };
-/**
- * Create a new setting.
- * @param settingSpec An object literal that looks like this:
- * {
- * name: 'thing',
- * description: 'Thing is an example setting',
- * type: 'string',
- * defaultValue: 'something'
- * }
- */
-function Setting(settingSpec, settings) {
- this._settings = settings;
+ /**
+ * Editor.centerSelection()
+ *
+ * Attempts to center the current selection on the screen.
+ **/
+ this.centerSelection = function() {
+ var range = this.getSelectionRange();
+ var line = Math.floor(range.start.row + (range.end.row - range.start.row) / 2);
+ this.renderer.scrollToLine(line, true);
+ };
- Object.keys(settingSpec).forEach(function(key) {
- this[key] = settingSpec[key];
- }, this);
+ /** related to: Selection.getCursor
+ * Editor.getCursorPosition() -> Object
+ * + (Object): This returns an object that looks something like this:
+ * ```{ row: currRow, column: currCol }```
+ *
+ * Gets the current position of the cursor.
+ *
+ *
+ *
+ **/
+ this.getCursorPosition = function() {
+ return this.selection.getCursor();
+ };
- this.type = types.getType(this.type);
- if (this.type == null) {
- throw new Error('In ' + this.name +
- ': can\'t find type for: ' + JSON.stringify(settingSpec.type));
- }
+ /** related to: EditSession.documentToScreenPosition
+ * Editor.getCursorPositionScreen() -> Number
+ *
+ * Returns the screen position of the cursor.
+ **/
+ this.getCursorPositionScreen = function() {
+ return this.session.documentToScreenPosition(this.getCursorPosition());
+ };
- if (!this.name) {
- throw new Error('Setting.name == undefined. Ignoring.', this);
- }
+ /** related to: Selection.getRange
+ * Editor.getSelectionRange() -> Range
+ *
+ * {:Selection.getRange}
+ **/
+ this.getSelectionRange = function() {
+ return this.selection.getRange();
+ };
- if (!this.defaultValue === undefined) {
- throw new Error('Setting.defaultValue == undefined', this);
- }
- if (this.onChange) {
- this.on('change', this.onChange.bind(this))
- }
+ /** related to: Selection.selectAll
+ * Editor.selectAll()
+ *
+ * Selects all the text in editor.
+ **/
+ this.selectAll = function() {
+ this.$blockScrolling += 1;
+ this.selection.selectAll();
+ this.$blockScrolling -= 1;
+ };
- this.set(this.defaultValue);
-}
-Setting.prototype = {
- get: function() {
- return this.value;
- },
+ /** related to: Selection.clearSelection
+ * Editor.clearSelection()
+ *
+ * {:Selection.clearSelection}
+ **/
+ this.clearSelection = function() {
+ this.selection.clearSelection();
+ };
- set: function(value) {
- if (this.value === value) {
- return;
- }
+ /** related to: Selection.moveCursorTo
+ * Editor.moveCursorTo(row, column)
+ * - row (Number): The new row number
+ * - column (Number): The new column number
+ *
+ * Moves the cursor to the specified row and column. Note that this does not de-select the current selection.
+ *
+ **/
+ this.moveCursorTo = function(row, column) {
+ this.selection.moveCursorTo(row, column);
+ };
+
+ /** related to: Selection.moveCursorToPosition
+ * Editor.moveCursorToPosition(pos)
+ * - pos (Object): An object with two properties, row and column
+ *
+ * Moves the cursor to the position indicated by `pos.row` and `pos.column`.
+ *
+ **/
+ this.moveCursorToPosition = function(pos) {
+ this.selection.moveCursorToPosition(pos);
+ };
- this.value = value;
- if (this._settings.persister) {
- this._settings.persister.persistValue(this._settings, this.name, value);
+ /**
+ * Editor.jumpToMatching()
+ *
+ * Moves the cursor's row and column to the next matching bracket.
+ *
+ **/
+ this.jumpToMatching = function() {
+ var cursor = this.getCursorPosition();
+ var pos = this.session.findMatchingBracket(cursor);
+ if (!pos) {
+ cursor.column += 1;
+ pos = this.session.findMatchingBracket(cursor);
+ }
+ if (!pos) {
+ cursor.column -= 2;
+ pos = this.session.findMatchingBracket(cursor);
}
- this._dispatchEvent('change', { setting: this, value: value });
- },
+ if (pos) {
+ this.clearSelection();
+ this.moveCursorTo(pos.row, pos.column);
+ }
+ };
/**
- * Reset the value of the key setting to it's default
- */
- resetValue: function() {
- this.set(this.defaultValue);
- },
- toString: function () {
- return this.name;
- }
-};
-oop.implement(Setting.prototype, EventEmitter);
+ * Editor.gotoLine(lineNumber, column)
+ * - lineNumber (Number): The line number to go to
+ * - column (Number): A column number to go to
+ * - animate (Boolean): If `true` animates scolling
+ *
+ * Moves the cursor to the specified line number, and also into the indiciated 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;
-/**
- * A base class for all the various methods of storing settings.
- * Usage:
- *
- * // Create manually, or require 'settings' from the container.
- * // This is the manual version:
- * var settings = plugins.catalog.getObject('settings');
- * // Add a new setting
- * settings.addSetting({ name:'foo', ... });
- * // Display the default value
- * alert(settings.get('foo'));
- * // Alter the value, which also publishes the change etc.
- * settings.set('foo', 'bar');
- * // Reset the value to the default
- * settings.resetValue('foo');
- *
- * @constructor
- */
-function Settings(persister) {
- // Storage for deactivated values
- this._deactivated = {};
+ if (!this.isRowFullyVisible(lineNumber - 1))
+ this.scrollToLine(lineNumber - 1, true, animate);
+ };
- // Storage for the active settings
- this._settings = {};
- // We often want sorted setting names. Cache
- this._settingNames = [];
+ /** related to: Editor.moveCursorTo
+ * Editor.navigateTo(row, column)
+ * - row (Number): The new row number
+ * - column (Number): The new column number
+ *
+ * Moves the cursor to the specified row and column. Note that this does de-select the current selection.
+ *
+ **/
+ this.navigateTo = function(row, column) {
+ this.clearSelection();
+ this.moveCursorTo(row, column);
+ };
- if (persister) {
- this.setPersister(persister);
- }
-};
+ /**
+ * Editor.navigateUp(times)
+ * - times (Number): The number of times to change navigation
+ *
+ * Moves the cursor up in the document the specified number of times. Note that this does de-select the current selection.
+ **/
+ this.navigateUp = function(times) {
+ this.selection.clearSelection();
+ times = times || 1;
+ this.selection.moveCursorBy(-times, 0);
+ };
-Settings.prototype = {
- /**
- * Function to add to the list of available settings.
- * Example usage:
- *
- * var settings = plugins.catalog.getObject('settings');
- * settings.addSetting({
- * name: 'tabsize', // For use in settings.get('X')
- * type: 'number', // To allow value checking.
- * defaultValue: 4 // Default value for use when none is directly set
- * });
- *
- * @param {object} settingSpec Object containing name/type/defaultValue members.
- */
- addSetting: function(settingSpec) {
- var setting = new Setting(settingSpec, this);
- this._settings[setting.name] = setting;
- this._settingNames.push(setting.name);
- this._settingNames.sort();
- },
+ /**
+ * Editor.navigateDown(times)
+ * - times (Number): The number of times to change navigation
+ *
+ * Moves the cursor down in the document the specified number of times. Note that this does de-select the current selection.
+ **/
+ this.navigateDown = function(times) {
+ this.selection.clearSelection();
+ times = times || 1;
+ this.selection.moveCursorBy(times, 0);
+ };
- addSettings: function addSettings(settings) {
- Object.keys(settings).forEach(function (name) {
- var setting = settings[name];
- if (!('name' in setting)) setting.name = name;
- this.addSetting(setting);
- }, this);
- },
+ /**
+ * Editor.navigateLeft(times)
+ * - times (Number): The number of times to change navigation
+ *
+ * Moves the cursor left in the document the specified number of times. Note that this does de-select the current selection.
+ **/
+ 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();
+ };
- removeSetting: function(setting) {
- var name = (typeof setting === 'string' ? setting : setting.name);
- setting = this._settings[name];
- delete this._settings[name];
- util.arrayRemove(this._settingNames, name);
- settings.removeAllListeners('change');
- },
+ /**
+ * Editor.navigateRight(times)
+ * - times (Number): The number of times to change navigation
+ *
+ * Moves the cursor right in the document the specified number of times. Note that this does de-select the current selection.
+ **/
+ 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();
+ };
- removeSettings: function removeSettings(settings) {
- Object.keys(settings).forEach(function(name) {
- var setting = settings[name];
- if (!('name' in setting)) setting.name = name;
- this.removeSettings(setting);
- }, this);
- },
+ /**
+ * Editor.navigateLineStart()
+ *
+ * Moves the cursor to the start of the current line. Note that this does de-select the current selection.
+ **/
+ this.navigateLineStart = function() {
+ this.selection.moveCursorLineStart();
+ this.clearSelection();
+ };
- getSettingNames: function() {
- return this._settingNames;
- },
+ /**
+ * Editor.navigateLineEnd()
+ *
+ * Moves the cursor to the end of the current line. Note that this does de-select the current selection.
+ **/
+ this.navigateLineEnd = function() {
+ this.selection.moveCursorLineEnd();
+ this.clearSelection();
+ };
- getSetting: function(name) {
- return this._settings[name];
- },
+ /**
+ * Editor.navigateFileEnd()
+ *
+ * Moves the cursor to the end of the current file. Note that this does de-select the current selection.
+ **/
+ this.navigateFileEnd = function() {
+ var scrollTop = this.renderer.scrollTop;
+ this.selection.moveCursorFileEnd();
+ this.clearSelection();
+ this.renderer.animateScrolling(scrollTop);
+ };
/**
- * A Persister is able to store settings. It is an object that defines
- * two functions:
- * loadInitialValues(settings) and persistValue(settings, key, value).
- */
- setPersister: function(persister) {
- this._persister = persister;
- if (persister) {
- persister.loadInitialValues(this);
- }
- },
+ * Editor.navigateFileStart()
+ *
+ * Moves the cursor to the start of the current file. Note that this does de-select the current selection.
+ **/
+ this.navigateFileStart = function() {
+ var scrollTop = this.renderer.scrollTop;
+ this.selection.moveCursorFileStart();
+ this.clearSelection();
+ this.renderer.animateScrolling(scrollTop);
+ };
- resetAll: function() {
- this.getSettingNames().forEach(function(key) {
- this.resetValue(key);
- }, this);
- },
+ /**
+ * Editor.navigateWordRight()
+ *
+ * Moves the cursor to the word immediately to the right of the current position. Note that this does de-select the current selection.
+ **/
+ this.navigateWordRight = function() {
+ this.selection.moveCursorWordRight();
+ this.clearSelection();
+ };
/**
- * Retrieve a list of the known settings and their values
- */
- _list: function() {
- var reply = [];
- this.getSettingNames().forEach(function(setting) {
- reply.push({
- 'key': setting,
- 'value': this.getSetting(setting).get()
- });
- }, this);
- return reply;
- },
+ * Editor.navigateWordLeft()
+ *
+ * Moves the cursor to the word immediately to the left of the current position. Note that this does de-select the current selection.
+ **/
+ this.navigateWordLeft = function() {
+ this.selection.moveCursorWordLeft();
+ this.clearSelection();
+ };
/**
- * Prime the local cache with the defaults.
- */
- _loadDefaultValues: function() {
- this._loadFromObject(this._getDefaultValues());
- },
+ * Editor.replace(replacement, options)
+ * - replacement (String): The text to replace with
+ * - options (Object): The [[Search `Search`]] options to use
+ *
+ * Replaces the first occurance of `options.needle` with the value in `replacement`.
+ **/
+ 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;
+ };
/**
- * Utility to load settings from an object
- */
- _loadFromObject: function(data) {
- // We iterate over data rather than keys so we don't forget values
- // which don't have a setting yet.
- for (var key in data) {
- if (data.hasOwnProperty(key)) {
- var setting = this._settings[key];
- if (setting) {
- var value = setting.type.parse(data[key]);
- this.set(key, value);
- } else {
- this.set(key, data[key]);
- }
+ * Editor.replaceAll(replacement, options)
+ * - replacement (String): The text to replace with
+ * - options (Object): The [[Search `Search`]] options to use
+ *
+ * Replaces all occurances of `options.needle` with the value in `replacement`.
+ **/
+ 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++;
}
}
- },
- /**
- * Utility to grab all the settings and export them into an object
- */
- _saveToObject: function() {
- return this.getSettingNames().map(function(key) {
- return this._settings[key].type.stringify(this.get(key));
- }.bind(this));
- },
+ this.selection.setSelectionRange(selection);
+ this.$blockScrolling -= 1;
- /**
- * The default initial settings
- */
- _getDefaultValues: function() {
- return this.getSettingNames().map(function(key) {
- return this._settings[key].spec.defaultValue;
- }.bind(this));
- }
-};
-exports.settings = new Settings();
+ return replaced;
+ };
-/**
- * Save the settings in a cookie
- * This code has not been tested since reboot
- * @constructor
- */
-function CookiePersister() {
-};
+ 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;
+ }
+ };
-CookiePersister.prototype = {
- loadInitialValues: function(settings) {
- settings._loadDefaultValues();
- var data = cookie.get('settings');
- settings._loadFromObject(JSON.parse(data));
- },
+ /** related to: Search.getOptions
+ * Editor.getLastSearchOptions() -> Object
+ *
+ * {:Search.getOptions} For more information on `options`, see [[Search `Search`]].
+ **/
+ this.getLastSearchOptions = function() {
+ return this.$search.getOptions();
+ };
- persistValue: function(settings, key, value) {
- try {
- var stringData = JSON.stringify(settings._saveToObject());
- cookie.set('settings', stringData);
- } catch (ex) {
- console.error('Unable to JSONify the settings! ' + ex);
- return;
+ /** related to: Search.find
+ * Editor.find(needle, options)
+ * - needle (String): The text to search for
+ * - options (Object): An object defining various search properties
+ * - animate (Boolean): If `true` animate scrolling
+ *
+ * Attempts to find `needle` within the document. For more information on `options`, see [[Search `Search`]].
+ **/
+ this.find = function(needle, options, animate) {
+ this.clearSelection();
+ options = options || {};
+ options.needle = needle;
+ this.$search.set(options);
+ this.$find(false, animate);
+ };
+
+ /** related to: Editor.find
+ * Editor.findNext(options)
+ * - options (Object): search options
+ * - animate (Boolean): If `true` animate scrolling
+ *
+ * Performs another search for `needle` in the document. For more information on `options`, see [[Search `Search`]].
+ **/
+ this.findNext = function(options, animate) {
+ options = options || {};
+ this.$search.set(options);
+ this.$find(false, animate);
+ };
+
+ /** related to: Editor.find
+ * Editor.findPrevious(options)
+ * - options (Object): search options
+ * - animate (Boolean): If `true` animate scrolling
+ *
+ * Performs a search for `needle` backwards. For more information on `options`, see [[Search `Search`]].
+ **/
+ this.findPrevious = function(options, animate) {
+ options = options || {};
+ this.$search.set(options);
+ this.$find(true, animate);
+ };
+
+ this.$find = function(backwards, animate) {
+ if (!this.selection.isEmpty())
+ this.$search.set({needle: this.session.getTextRange(this.getSelectionRange())});
+
+ if (typeof backwards != "undefined")
+ this.$search.set({backwards: backwards});
+
+ var range = this.$search.find(this.session);
+ if (range) {
+ 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);
+ this.renderer.animateScrolling(scrollTop);
}
- }
-};
+ };
-exports.CookiePersister = CookiePersister;
+ /** related to: UndoManager.undo
+ * Editor.undo()
+ *
+ * {:UndoManager.undo}
+ **/
+ this.undo = function() {
+ this.$blockScrolling++;
+ this.session.getUndoManager().undo();
+ this.$blockScrolling--;
+ this.renderer.scrollCursorIntoView(null, 0.5);
+ };
+
+ /** related to: UndoManager.redo
+ * Editor.redo()
+ *
+ * {:UndoManager.redo}
+ **/
+ this.redo = function() {
+ this.$blockScrolling++;
+ this.session.getUndoManager().redo();
+ this.$blockScrolling--;
+ this.renderer.scrollCursorIntoView(null, 0.5);
+ };
+
+ /**
+ * Editor.destroy()
+ *
+ * Cleans up the entire editor.
+ **/
+ this.destroy = function() {
+ this.renderer.destroy();
+ };
+
+}).call(Editor.prototype);
+
+exports.Editor = Editor;
});
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -4024,15 +4446,15 @@ exports.CookiePersister = CookiePersister;
* for the specific language governing rights and limitations under the
* License.
*
- * The Original Code is Skywriter.
+ * The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Skywriter Team (skywriter@mozilla.com)
+ * 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
@@ -4048,317 +4470,121 @@ exports.CookiePersister = CookiePersister;
*
* ***** END LICENSE BLOCK ***** */
-define('pilot/commands/settings', ['require', 'exports', 'module' , 'pilot/canon'], function(require, exports, module) {
+define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+exports.stringReverse = function(string) {
+ return string.split("").reverse().join("");
+};
-var setCommandSpec = {
- name: 'set',
- params: [
- {
- name: 'setting',
- type: 'setting',
- description: 'The name of the setting to display or alter',
- defaultValue: null
- },
- {
- name: 'value',
- type: 'settingValue',
- description: 'The new value for the chosen setting',
- defaultValue: null
- }
- ],
- description: 'define and show settings',
- exec: function(env, args, request) {
- var html;
- if (!args.setting) {
- // 'set' by itself lists all the settings
- var names = env.settings.getSettingNames();
- html = '';
- // first sort the settingsList based on the name
- names.sort(function(name1, name2) {
- return name1.localeCompare(name2);
- });
-
- names.forEach(function(name) {
- var setting = env.settings.getSetting(name);
- var url = 'https://wiki.mozilla.org/Labs/Skywriter/Settings#' +
- setting.name;
- html += '' +
- setting.name +
- ' = ' +
- setting.value +
- '
';
- });
- } else {
- // set with only a setting, shows the value for that setting
- if (args.value === undefined) {
- html = '' + setting.name + ' = ' +
- setting.get();
- } else {
- // Actually change the setting
- args.setting.set(args.value);
- html = 'Setting: ' + args.setting.name + ' = ' +
- args.setting.get();
- }
- }
- request.done(html);
- }
+exports.stringRepeat = function (string, count) {
+ return new Array(count + 1).join(string);
};
-var unsetCommandSpec = {
- name: 'unset',
- params: [
- {
- name: 'setting',
- type: 'setting',
- description: 'The name of the setting to return to defaults'
- }
- ],
- description: 'unset a setting entirely',
- exec: function(env, args, request) {
- var setting = env.settings.get(args.setting);
- if (!setting) {
- request.doneWithError('No setting with the name ' +
- args.setting + '.');
- return;
- }
+var trimBeginRegexp = /^\s\s*/;
+var trimEndRegexp = /\s\s*$/;
- setting.reset();
- request.done('Reset ' + setting.name + ' to default: ' +
- env.settings.get(args.setting));
- }
+exports.stringTrimLeft = function (string) {
+ return string.replace(trimBeginRegexp, '');
};
-var canon = require('pilot/canon');
-
-exports.startup = function(data, reason) {
- canon.addCommand(setCommandSpec);
- canon.addCommand(unsetCommandSpec);
+exports.stringTrimRight = function (string) {
+ return string.replace(trimEndRegexp, '');
};
-exports.shutdown = function(data, reason) {
- canon.removeCommand(setCommandSpec);
- canon.removeCommand(unsetCommandSpec);
+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; iSub-Commands of ' + command.name + '');
- output.push('' + command.description + '
');
- }
- else if (args.search) {
- if (args.search == 'hidden') { // sneaky, sneaky.
- args.search = '';
- showHidden = true;
- }
- output.push('Commands starting with \'' + args.search + '\':
');
- }
- else {
- output.push('Available Commands:
');
- }
-
- var commandNames = canon.getCommandNames();
- commandNames.sort();
-
- output.push('');
- for (var i = 0; i < commandNames.length; i++) {
- command = canon.getCommand(commandNames[i]);
- if (!showHidden && command.hidden) {
- continue;
- }
- if (command.description === undefined) {
- // Ignore editor actions
- continue;
- }
- if (args.search && command.name.indexOf(args.search) !== 0) {
- // Filtered out by the user
- continue;
- }
- if (!args.search && command.name.indexOf(' ') != -1) {
- // sub command
- continue;
- }
- if (command && command.name == args.search) {
- // sub command, and we've already given that help
- continue;
- }
-
- // todo add back a column with parameter information, perhaps?
-
- output.push('');
- output.push('| ' + command.name + ' | ');
- output.push('' + command.description + ' | ');
- output.push('
');
- }
- output.push('
');
+ copy[key] = obj[key];
}
-
- request.done(output.join(''));
}
+ return copy;
};
-/**
- * 'eval' command
- */
-var evalCommandSpec = {
- name: 'eval',
- params: [
- {
- name: 'javascript',
- type: 'text',
- description: 'The JavaScript to evaluate'
- }
- ],
- description: 'evals given js code and show the result',
- hidden: true,
- exec: function(env, args, request) {
- var result;
- var javascript = args.javascript;
- try {
- result = eval(javascript);
- } catch (e) {
- result = 'Error: ' + e.message + '';
- }
-
- var msg = '';
- var type = '';
- var x;
-
- if (checks.isFunction(result)) {
- // converts the function to a well formated string
- msg = (result + '').replace(/\n/g, '
').replace(/ /g, ' ');
- type = 'function';
- } else if (checks.isObject(result)) {
- if (Array.isArray(result)) {
- type = 'array';
- } else {
- type = 'object';
- }
+exports.arrayToMap = function(arr) {
+ var map = {};
+ for (var i=0; i' + items[x].name + ': ' + items[x].value + '
';
- }
+ var timer = null;
+ var callback = function() {
+ timer = null;
+ fcn();
+ };
- } else {
- msg = result;
- type = typeof result;
- }
+ var deferred = function(timeout) {
+ deferred.cancel();
+ timer = setTimeout(callback, timeout || 0);
+ return deferred;
+ };
- request.done('Result for eval \'' + javascript + '\'' +
- ' (type: '+ type+'):
'+ msg);
- }
-};
+ deferred.schedule = deferred;
-var canon = require('pilot/canon');
+ deferred.call = function() {
+ this.cancel();
+ fcn();
+ return deferred;
+ };
-exports.startup = function(data, reason) {
- canon.addCommand(helpCommandSpec);
- canon.addCommand(evalCommandSpec);
-};
+ deferred.cancel = function() {
+ clearTimeout(timer);
+ timer = null;
+ return deferred;
+ };
-exports.shutdown = function(data, reason) {
- canon.removeCommand(helpCommandSpec);
- canon.removeCommand(evalCommandSpec);
+ return deferred;
};
-
});
-/* ***** BEGIN LICENSE BLOCK *****
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
@@ -4371,15 +4597,16 @@ exports.shutdown = function(data, reason) {
* for the specific language governing rights and limitations under the
* License.
*
- * The Original Code is Mozilla Skywriter.
+ * The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Joe Walker (jwalker@mozilla.com)
+ * Fabian Jakobs
+ * Mihai Sucan
*
* 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
@@ -4395,186 +4622,255 @@ exports.shutdown = function(data, reason) {
*
* ***** END LICENSE BLOCK ***** */
-define('pilot/settings/canon', ['require', 'exports', 'module' ], function(require, exports, module) {
+define('ace/keyboard/textinput', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/lib/useragent', 'ace/lib/dom'], function(require, exports, module) {
+"use strict";
+var event = require("../lib/event");
+var useragent = require("../lib/useragent");
+var dom = require("../lib/dom");
-var historyLengthSetting = {
- name: "historyLength",
- description: "How many typed commands do we recall for reference?",
- type: "number",
- defaultValue: 50
-};
+var TextInput = function(parentNode, host) {
-exports.startup = function(data, reason) {
- data.env.settings.addSetting(historyLengthSetting);
-};
+ var text = dom.createElement("textarea");
+ if (useragent.isTouchPad)
+ text.setAttribute("x-palm-disable-auto-cap", true);
-exports.shutdown = function(data, reason) {
- data.env.settings.removeSetting(historyLengthSetting);
-};
+ text.setAttribute("wrap", "off");
+ text.style.left = "-10000px";
+ text.style.position = "fixed";
+ parentNode.insertBefore(text, parentNode.firstChild);
-});
-/* ***** 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 Skywriter.
- *
- * The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Kevin Dangoor (kdangoor@mozilla.com)
- *
- * 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 ***** */
+ var PLACEHOLDER = String.fromCharCode(0);
+ sendText();
-define('pilot/plugin_manager', ['require', 'exports', 'module' , 'pilot/promise'], function(require, exports, module) {
+ var inCompostion = false;
+ var copied = false;
+ var pasted = false;
+ var tempStyle = '';
-var Promise = require("pilot/promise").Promise;
+ function select() {
+ try {
+ text.select();
+ } catch (e) {}
+ }
-exports.REASONS = {
- APP_STARTUP: 1,
- APP_SHUTDOWN: 2,
- PLUGIN_ENABLE: 3,
- PLUGIN_DISABLE: 4,
- PLUGIN_INSTALL: 5,
- PLUGIN_UNINSTALL: 6,
- PLUGIN_UPGRADE: 7,
- PLUGIN_DOWNGRADE: 8
-};
+ function sendText(valueToSend) {
+ if (!copied) {
+ var value = valueToSend || text.value;
+ if (value) {
+ if (value.length > 1) {
+ if (value.charAt(0) == PLACEHOLDER)
+ value = value.substr(1);
+ else if (value.charAt(value.length - 1) == PLACEHOLDER)
+ value = value.slice(0, -1);
+ }
-exports.Plugin = function(name) {
- this.name = name;
- this.status = this.INSTALLED;
-};
+ if (value && value != PLACEHOLDER) {
+ if (pasted)
+ host.onPaste(value);
+ else
+ host.onTextInput(value);
+ }
-exports.Plugin.prototype = {
- /**
- * constants for the state
- */
- NEW: 0,
- INSTALLED: 1,
- REGISTERED: 2,
- STARTED: 3,
- UNREGISTERED: 4,
- SHUTDOWN: 5,
-
- install: function(data, reason) {
- var pr = new Promise();
- if (this.status > this.NEW) {
- pr.resolve(this);
- return pr;
- }
- require([this.name], function(pluginModule) {
- if (pluginModule.install) {
- pluginModule.install(data, reason);
+ // If editor is no longer focused we quit immediately, since
+ // it means that something else is in charge now.
+ if (!isFocused())
+ return false;
}
- this.status = this.INSTALLED;
- pr.resolve(this);
- }.bind(this));
- return pr;
- },
-
- register: function(data, reason) {
- var pr = new Promise();
- if (this.status != this.INSTALLED) {
- pr.resolve(this);
- return pr;
}
- require([this.name], function(pluginModule) {
- if (pluginModule.register) {
- pluginModule.register(data, reason);
- }
- this.status = this.REGISTERED;
- pr.resolve(this);
- }.bind(this));
- return pr;
- },
- startup: function(data, reason) {
- reason = reason || exports.REASONS.APP_STARTUP;
- var pr = new Promise();
- if (this.status != this.REGISTERED) {
- pr.resolve(this);
- return pr;
- }
- require([this.name], function(pluginModule) {
- if (pluginModule.startup) {
- pluginModule.startup(data, reason);
- }
- this.status = this.STARTED;
- pr.resolve(this);
- }.bind(this));
- return pr;
- },
+ copied = false;
+ pasted = false;
- shutdown: function(data, reason) {
- if (this.status != this.STARTED) {
- return;
- }
- pluginModule = require(this.name);
- if (pluginModule.shutdown) {
- pluginModule.shutdown(data, reason);
- }
+ // Safari doesn't fire copy events if no text is selected
+ text.value = PLACEHOLDER;
+ select();
}
-};
-
-exports.PluginCatalog = function() {
- this.plugins = {};
-};
-exports.PluginCatalog.prototype = {
- registerPlugins: function(pluginList, data, reason) {
- var registrationPromises = [];
- pluginList.forEach(function(pluginName) {
- var plugin = this.plugins[pluginName];
- if (plugin === undefined) {
- plugin = new exports.Plugin(pluginName);
- this.plugins[pluginName] = plugin;
- registrationPromises.push(plugin.register(data, reason));
- }
- }.bind(this));
- return Promise.group(registrationPromises);
- },
+ var onTextInput = function(e) {
+ setTimeout(function () {
+ if (!inCompostion)
+ sendText(e.data);
+ }, 0);
+ };
+
+ var onPropertyChange = function(e) {
+ if (useragent.isOldIE && text.value.charCodeAt(0) > 128) return;
+ setTimeout(function() {
+ if (!inCompostion)
+ sendText();
+ }, 0);
+ };
- startupPlugins: function(data, reason) {
- var startupPromises = [];
- for (var pluginName in this.plugins) {
- var plugin = this.plugins[pluginName];
- startupPromises.push(plugin.startup(data, reason));
- }
- return Promise.group(startupPromises);
- }
-};
+ var onCompositionStart = function(e) {
+ inCompostion = true;
+ host.onCompositionStart();
+ if (!useragent.isGecko) setTimeout(onCompositionUpdate, 0);
+ };
-exports.catalog = new exports.PluginCatalog();
+ 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();
+ select();
+ setTimeout(function () {
+ sendText();
+ }, 0);
+ };
+
+ var onCut = function(e) {
+ copied = true;
+ var copyText = host.getCopyText();
+ if(copyText) {
+ text.value = copyText;
+ host.onCut();
+ } else
+ e.preventDefault();
+ select();
+ setTimeout(function () {
+ sendText();
+ }, 0);
+ };
+
+ event.addCommandKeyListener(text, host.onCommandKey.bind(host));
+
+ 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();
+ });
+ }
+
+ if ("onpropertychange" in text && !("oninput" in text))
+ event.addListener(text, "propertychange", onPropertyChange);
+ else
+ event.addListener(text, "input", onTextInput);
+
+ 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) {
+ 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);
+ }
+ });
+ }
+ 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();
+ select();
+ });
+
+ this.focus = function() {
+ host.onFocus();
+ select();
+ text.focus();
+ };
+
+ this.blur = function() {
+ text.blur();
+ };
+
+ function isFocused() {
+ return document.activeElement === text;
+ }
+ this.isFocused = isFocused;
+
+ this.getElement = function() {
+ return text;
+ };
+
+ this.onContextMenu = function(mousePos, isEmpty){
+ if (mousePos) {
+ if (!tempStyle)
+ tempStyle = text.style.cssText;
+
+ text.style.cssText =
+ 'position:fixed; z-index:1000;' +
+ 'left:' + (mousePos.x - 2) + 'px; top:' + (mousePos.y - 2) + 'px;';
+
+ }
+ if (isEmpty)
+ text.value='';
+ };
+
+ this.onContextMenuClose = function(){
+ setTimeout(function () {
+ if (tempStyle) {
+ text.style.cssText = tempStyle;
+ tempStyle = '';
+ }
+ sendText();
+ }, 0);
+ };
+};
+
+exports.TextInput = TextInput;
});
-/* ***** BEGIN LICENSE BLOCK *****
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
@@ -4587,15 +4883,16 @@ exports.catalog = new exports.PluginCatalog();
* for the specific language governing rights and limitations under the
* License.
*
- * The Original Code is Mozilla Skywriter.
+ * The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Joe Walker (jwalker@mozilla.com)
+ * Fabian Jakobs
+ * Mihai Sucan
*
* 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
@@ -4611,232 +4908,127 @@ exports.catalog = new exports.PluginCatalog();
*
* ***** END LICENSE BLOCK ***** */
-define('pilot/promise', ['require', 'exports', 'module' , 'pilot/console', 'pilot/stacktrace'], function(require, exports, module) {
-
-var console = require("pilot/console");
-var Trace = require('pilot/stacktrace').Trace;
-
-/**
- * A promise can be in one of 2 states.
- * The ERROR and SUCCESS states are terminal, the PENDING state is the only
- * start state.
- */
-var ERROR = -1;
-var PENDING = 0;
-var SUCCESS = 1;
-
-/**
- * We give promises and ID so we can track which are outstanding
- */
-var _nextId = 0;
-
-/**
- * Debugging help if 2 things try to complete the same promise.
- * This can be slow (especially on chrome due to the stack trace unwinding) so
- * we should leave this turned off in normal use.
- */
-var _traceCompletion = false;
+define('ace/mouse/mouse_handler', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/mouse/default_handlers', 'ace/mouse/default_gutter_handler', 'ace/mouse/mouse_event'], function(require, exports, module) {
+"use strict";
-/**
- * Outstanding promises. Handy list for debugging only.
- */
-var _outstanding = [];
+var event = require("../lib/event");
+var DefaultHandlers = require("./default_handlers").DefaultHandlers;
+var DefaultGutterHandler = require("./default_gutter_handler").GutterHandler;
+var MouseEvent = require("./mouse_event").MouseEvent;
-/**
- * Recently resolved promises. Also for debugging only.
- */
-var _recent = [];
+var MouseHandler = function(editor) {
+ this.editor = editor;
-/**
- * Create an unfulfilled promise
- */
-Promise = function () {
- this._status = PENDING;
- this._value = undefined;
- this._onSuccessHandlers = [];
- this._onErrorHandlers = [];
-
- // Debugging help
- this._id = _nextId++;
- //this._createTrace = new Trace(new Error());
- _outstanding[this._id] = this;
-};
+ new DefaultHandlers(this);
+ new DefaultGutterHandler(this);
-/**
- * Yeay for RTTI.
- */
-Promise.prototype.isPromise = true;
+ event.addListener(editor.container, "mousedown", function(e) {
+ editor.focus();
+ return event.preventDefault(e);
+ });
+ event.addListener(editor.container, "selectstart", function(e) {
+ return event.preventDefault(e);
+ });
-/**
- * Have we either been resolve()ed or reject()ed?
- */
-Promise.prototype.isComplete = function() {
- return this._status != PENDING;
+ var mouseTarget = editor.renderer.getMouseEventTarget();
+ event.addListener(mouseTarget, "mousedown", this.onMouseEvent.bind(this, "mousedown"));
+ event.addListener(mouseTarget, "click", this.onMouseEvent.bind(this, "click"));
+ event.addListener(mouseTarget, "mousemove", this.onMouseMove.bind(this, "mousemove"));
+ event.addMultiMouseDownListener(mouseTarget, 0, 2, 500, this.onMouseEvent.bind(this, "dblclick"));
+ event.addMultiMouseDownListener(mouseTarget, 0, 3, 600, this.onMouseEvent.bind(this, "tripleclick"));
+ event.addMultiMouseDownListener(mouseTarget, 0, 4, 600, this.onMouseEvent.bind(this, "quadclick"));
+ 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.onMouseMove.bind(this, "gutter"));
};
-/**
- * Have we resolve()ed?
- */
-Promise.prototype.isResolved = function() {
- return this._status == SUCCESS;
-};
+(function() {
-/**
- * Have we reject()ed?
- */
-Promise.prototype.isRejected = function() {
- return this._status == ERROR;
-};
+ this.$scrollSpeed = 1;
+ this.setScrollSpeed = function(speed) {
+ this.$scrollSpeed = speed;
+ };
-/**
- * Take the specified action of fulfillment of a promise, and (optionally)
- * a different action on promise rejection.
- */
-Promise.prototype.then = function(onSuccess, onError) {
- if (typeof onSuccess === 'function') {
- if (this._status === SUCCESS) {
- onSuccess.call(null, this._value);
- } else if (this._status === PENDING) {
- this._onSuccessHandlers.push(onSuccess);
- }
- }
+ this.getScrollSpeed = function() {
+ return this.$scrollSpeed;
+ };
- if (typeof onError === 'function') {
- if (this._status === ERROR) {
- onError.call(null, this._value);
- } else if (this._status === PENDING) {
- this._onErrorHandlers.push(onError);
- }
- }
+ this.onMouseEvent = function(name, e) {
+ this.editor._emit(name, new MouseEvent(e, this.editor));
+ };
- return this;
-};
+ this.$dragDelay = 250;
+ this.setDragDelay = function(dragDelay) {
+ this.$dragDelay = dragDelay;
+ };
-/**
- * Like then() except that rather than returning this we return
- * a promise which
- */
-Promise.prototype.chainPromise = function(onSuccess) {
- var chain = new Promise();
- chain._chainedFrom = this;
- this.then(function(data) {
- try {
- chain.resolve(onSuccess(data));
- } catch (ex) {
- chain.reject(ex);
- }
- }, function(ex) {
- chain.reject(ex);
- });
- return chain;
-};
+ this.getDragDelay = function() {
+ return this.$dragDelay;
+ };
-/**
- * Supply the fulfillment of a promise
- */
-Promise.prototype.resolve = function(data) {
- return this._complete(this._onSuccessHandlers, SUCCESS, data, 'resolve');
-};
+ 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;
-/**
- * Renege on a promise
- */
-Promise.prototype.reject = function(data) {
- return this._complete(this._onErrorHandlers, ERROR, data, 'reject');
-};
+ this.editor._emit(name, new MouseEvent(e, this.editor));
+ };
-/**
- * Internal method to be called on resolve() or reject().
- * @private
- */
-Promise.prototype._complete = function(list, status, data, name) {
- // Complain if we've already been completed
- if (this._status != PENDING) {
- console.group('Promise already closed');
- console.error('Attempted ' + name + '() with ', data);
- console.error('Previous status = ', this._status,
- ', previous value = ', this._value);
- console.trace();
-
- if (this._completeTrace) {
- console.error('Trace of previous completion:');
- this._completeTrace.log(5);
- }
- console.groupEnd();
- return this;
- }
+ 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;
- if (_traceCompletion) {
- this._completeTrace = new Trace(new Error());
- }
+ this.editor._emit(name, mouseEvent);
+ };
- this._status = status;
- this._value = data;
+ this.setState = function(state) {
+ this.state = state;
+ };
- // Call all the handlers, and then delete them
- list.forEach(function(handler) {
- handler.call(null, this._value);
- }, this);
- this._onSuccessHandlers.length = 0;
- this._onErrorHandlers.length = 0;
-
- // Remove the given {promise} from the _outstanding list, and add it to the
- // _recent list, pruning more than 20 recent promises from that list.
- delete _outstanding[this._id];
- _recent.push(this);
- while (_recent.length > 20) {
- _recent.shift();
- }
+ this.captureMouse = function(ev, state) {
+ if (state)
+ this.setState(state);
- return this;
-};
+ this.x = ev.x;
+ this.y = ev.y;
-/**
- * Takes an array of promises and returns a promise that that is fulfilled once
- * all the promises in the array are fulfilled
- * @param group The array of promises
- * @return the promise that is fulfilled when all the array is fulfilled
- */
-Promise.group = function(promiseList) {
- if (!(promiseList instanceof Array)) {
- promiseList = Array.prototype.slice.call(arguments);
- }
+ // do not move textarea during selection
+ var kt = this.editor.renderer.$keepTextAreaAtCursor;
+ this.editor.renderer.$keepTextAreaAtCursor = false;
- // If the original array has nothing in it, return now to avoid waiting
- if (promiseList.length === 0) {
- return new Promise().resolve([]);
- }
+ var self = this;
+ var onMouseSelection = function(e) {
+ self.x = e.clientX;
+ self.y = e.clientY;
+ };
- var groupPromise = new Promise();
- var results = [];
- var fulfilled = 0;
-
- var onSuccessFactory = function(index) {
- return function(data) {
- results[index] = data;
- fulfilled++;
- // If the group has already failed, silently drop extra results
- if (groupPromise._status !== ERROR) {
- if (fulfilled === promiseList.length) {
- groupPromise.resolve(results);
- }
- }
+ var onMouseSelectionEnd = function(e) {
+ clearInterval(timerId);
+ self[self.state + "End"] && self[self.state + "End"](e);
+ self.$clickSelection = null;
+ self.editor.renderer.$keepTextAreaAtCursor = kt;
+ self.editor.renderer.$moveTextAreaToCursor();
};
- };
- promiseList.forEach(function(promise, index) {
- var onSuccess = onSuccessFactory(index);
- var onError = groupPromise.reject.bind(groupPromise);
- promise.then(onSuccess, onError);
- });
+ var onSelectionInterval = function() {
+ self[self.state] && self[self.state]();
+ }
- return groupPromise;
-};
+ event.capture(this.editor.container, onMouseSelection, onMouseSelectionEnd);
+ var timerId = setInterval(onSelectionInterval, 20);
-exports.Promise = Promise;
-exports._outstanding = _outstanding;
-exports._recent = _recent;
+ ev.preventDefault();
+ };
+}).call(MouseHandler.prototype);
+exports.MouseHandler = MouseHandler;
});
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
@@ -4861,7 +5053,8 @@ exports._recent = _recent;
*
* Contributor(s):
* Fabian Jakobs
- * Mihai Sucan
+ * Mike de Boer
+ * Harutyun Amirjanyan
*
* 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
@@ -4877,264 +5070,301 @@ exports._recent = _recent;
*
* ***** END LICENSE BLOCK ***** */
-define('pilot/dom', ['require', 'exports', 'module' ], function(require, exports, module) {
+define('ace/mouse/default_handlers', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/browser_focus'], function(require, exports, module) {
+"use strict";
-var XHTML_NS = "http://www.w3.org/1999/xhtml";
+var dom = require("../lib/dom");
+var BrowserFocus = require("../lib/browser_focus").BrowserFocus;
-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;
- }
-};
+var DRAG_OFFSET = 5; // pixels
-if (!document.documentElement.classList) {
- exports.hasCssClass = function(el, name) {
- var classes = el.className.split(/\s+/g);
- return classes.indexOf(name) !== -1;
- };
- /**
- * Add a CSS class to the list of classes on the given node
- */
- exports.addCssClass = function(el, name) {
- if (!exports.hasCssClass(el, name)) {
- el.className += " " + name;
- }
- };
- /**
- * Remove a CSS class from the list of classes on the given node
- */
- exports.removeCssClass = function(el, name) {
- var classes = el.className.split(/\s+/g);
- while (true) {
- var index = classes.indexOf(name);
- if (index == -1) {
- break;
+function DefaultHandlers(mouseHandler) {
+ mouseHandler.$clickSelection = null;
+ mouseHandler.browserFocus = new BrowserFocus();
+
+ 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"];
+
+ exports.forEach(function(x) {
+ mouseHandler[x] = this[x];
+ }, this);
+
+ mouseHandler.selectByLines = this.extendSelectionBy.bind(mouseHandler, "getLineRange");
+ mouseHandler.selectByWords = this.extendSelectionBy.bind(mouseHandler, "getWordRange");
+}
+
+(function() {
+
+ this.onMouseDown = function(ev) {
+ this.mousedownEvent = ev;
+ var inSelection = ev.inSelection();
+ var pos = ev.getDocumentPosition();
+ var editor = this.editor;
+ var _self = this;
+
+ this.ev = ev
+ var selectionRange = editor.getSelectionRange();
+ var selectionEmpty = selectionRange.isEmpty();
+
+ var button = ev.getButton();
+ if (button !== 0) {
+ if (selectionEmpty) {
+ editor.moveCursorToPosition(pos);
+ editor.selection.clearSelection();
}
- classes.splice(index, 1);
+ // 2: contextmenu, 1: linux paste
+ this.moveTextarea = function() {
+ editor.textInput.onContextMenu({x: _self.x, y: _self.y});
+ };
+ this.moveTextareaEnd = editor.textInput.onContextMenuClose;
+
+ editor.textInput.onContextMenu({x: this.x, y: this.y}, selectionEmpty);
+ this.captureMouse(ev, "moveTextarea");
+
+ return;
}
- 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;
+ // if this click caused the editor to be focused should not clear the
+ // selection
+ if (inSelection && !editor.isFocused()) {
+ editor.focus();
+ return;
+ }
+
+ 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) {
+ var e = ev.domEvent;
+ if ((e.ctrlKey || e.altKey)) {
+ this.startDrag();
+ } else {
+ this.mousedownEvent.time = (new Date()).getTime();
+ this.setState("dragWait");
}
- add = false;
- classes.splice(index, 1);
}
- if(add)
- classes.push(name);
- el.className = classes.join(" ");
- return add;
- };
-} else {
- exports.hasCssClass = function(el, name) {
- return el.classList.contains(name);
+ this.captureMouse(ev)
};
- exports.addCssClass = function(el, name) {
- el.classList.add(name);
- };
+ 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");
+ }
- exports.removeCssClass = function(el, name) {
- el.classList.remove(name);
- };
+ this.select = function() {
+ var anchor, editor = this.editor;
+ var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y);
- exports.toggleCssClass = function(el, name) {
- return el.classList.toggle(name);
- };
-}
+ if (this.$clickSelection) {
+ var cmp = this.$clickSelection.comparePoint(cursor);
-/**
- * Add or remove a CSS class from the list of classes on the given node
- * depending on the value of include
- */
-exports.setCssClass = function(node, className, include) {
- if (include) {
- exports.addCssClass(node, className);
- } else {
- exports.removeCssClass(node, className);
- }
-};
+ if (cmp == -1) {
+ anchor = this.$clickSelection.end;
+ } else if (cmp == 1) {
+ anchor = this.$clickSelection.start;
+ } else {
+ cursor = this.$clickSelection.end;
+ anchor = this.$clickSelection.start;
+ }
+ editor.selection.setSelectionAnchor(anchor.row, anchor.column);
+ }
+ editor.selection.selectToPosition(cursor);
-exports.importCssString = function(cssText, doc){
- doc = doc || document;
+ editor.renderer.scrollCursorIntoView();
+ };
- if (doc.createStyleSheet) {
- var sheet = doc.createStyleSheet();
- sheet.cssText = cssText;
- }
- else {
- var style = doc.createElementNS ?
- doc.createElementNS(XHTML_NS, "style") :
- doc.createElement("style");
+ 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);
- style.appendChild(doc.createTextNode(cssText));
+ if (this.$clickSelection) {
+ var cmpStart = this.$clickSelection.comparePoint(range.start);
+ var cmpEnd = this.$clickSelection.comparePoint(range.end);
- var head = doc.getElementsByTagName("head")[0] || doc.documentElement;
- head.appendChild(style);
- }
-};
+ if (cmpStart == -1 && cmpEnd <= 0) {
+ anchor = this.$clickSelection.end;
+ cursor = range.start;
+ } else if (cmpEnd == 1 && cmpStart >= 0) {
+ anchor = this.$clickSelection.start;
+ cursor = range.end;
+ } else if (cmpStart == -1 && cmpEnd == 1) {
+ cursor = range.end;
+ anchor = range.start;
+ } else {
+ cursor = this.$clickSelection.end;
+ anchor = this.$clickSelection.start;
+ }
+ editor.selection.setSelectionAnchor(anchor.row, anchor.column);
+ }
+ editor.selection.selectToPosition(cursor);
-exports.getInnerWidth = function(element) {
- return (parseInt(exports.computedStyle(element, "paddingLeft"))
- + parseInt(exports.computedStyle(element, "paddingRight")) + element.clientWidth);
-};
+ editor.renderer.scrollCursorIntoView();
+ };
-exports.getInnerHeight = function(element) {
- return (parseInt(exports.computedStyle(element, "paddingTop"))
- + parseInt(exports.computedStyle(element, "paddingBottom")) + element.clientHeight);
-};
+ 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();
+ }
+ }
+ }
+ }
-if (window.pageYOffset !== undefined) {
- exports.getPageScrollTop = function() {
- return window.pageYOffset;
+ editor.keyBinding.addKeyboardHandler(this.$dragKeybinding);
};
- exports.getPageScrollLeft = function() {
- return window.pageXOffset;
- };
-}
-else {
- exports.getPageScrollTop = function() {
- return document.body.scrollTop;
- };
+ this.dragWait = function() {
+ var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);
+ var time = (new Date()).getTime();
+ var editor = this.editor;
- exports.getPageScrollLeft = function() {
- return document.body.scrollLeft;
+ if (distance > DRAG_OFFSET) {
+ this.startSelect();
+ } else if ((time - this.mousedownEvent.time) > editor.getDragDelay()) {
+ this.startDrag()
+ }
};
-}
-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
+ this.dragWaitEnd = function(e) {
+ this.mousedownEvent.domEvent = e;
+ this.startSelect();
};
-exports.scrollbarWidth = function() {
+ this.drag = function() {
+ var editor = this.editor;
+ this.dragCursor = editor.renderer.screenToTextCoordinates(this.x, this.y);
+ editor.moveCursorToPosition(this.dragCursor);
+ editor.renderer.scrollCursorIntoView();
+ };
- var inner = exports.createElement("p");
- inner.style.width = "100%";
- inner.style.minWidth = "0px";
- inner.style.height = "200px";
+ 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);
- var outer = exports.createElement("div");
- var style = outer.style;
+ if (!dragCursor)
+ return;
- style.position = "absolute";
- style.left = "-10000px";
- style.overflow = "hidden";
- style.width = "200px";
- style.minWidth = "0px";
- style.height = "150px";
+ 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);
+ }
- outer.appendChild(inner);
+ if (!newRange)
+ return;
- var body = document.body || document.documentElement;
- body.appendChild(outer);
+ editor.selection.setSelectionRange(newRange);
+ };
- var noScrollbar = inner.offsetWidth;
+ this.onDoubleClick = function(ev) {
+ var pos = ev.getDocumentPosition();
+ var editor = this.editor;
- style.overflow = "scroll";
- var withScrollbar = inner.offsetWidth;
+ this.setState("selectByWords");
- if (noScrollbar == withScrollbar) {
- withScrollbar = outer.clientWidth;
- }
+ editor.moveCursorToPosition(pos);
+ editor.selection.selectWord();
+ this.$clickSelection = editor.getSelectionRange();
+ };
- body.removeChild(outer);
+ this.onTripleClick = function(ev) {
+ var pos = ev.getDocumentPosition();
+ var editor = this.editor;
- return noScrollbar-withScrollbar;
-};
+ this.setState("selectByLines");
-/**
- * Optimized set innerHTML. This is faster than plain innerHTML if the element
- * already contains a lot of child elements.
- *
- * See http://blog.stevenlevithan.com/archives/faster-than-innerhtml for details
- */
-exports.setInnerHtml = function(el, innerHtml) {
- var element = el.cloneNode(false);//document.createElement("div");
- element.innerHTML = innerHtml;
- el.parentNode.replaceChild(element, el);
- return element;
-};
+ editor.moveCursorToPosition(pos);
+ editor.selection.selectLine();
+ this.$clickSelection = editor.getSelectionRange();
+ };
-exports.setInnerText = function(el, innerText) {
- if (document.body && "textContent" in document.body)
- el.textContent = innerText;
- else
- el.innerText = innerText;
+ this.onQuadClick = function(ev) {
+ var editor = this.editor;
-};
+ editor.selectAll();
+ this.$clickSelection = editor.getSelectionRange();
+ this.setState("select");
+ };
-exports.getInnerText = function(el) {
- if (document.body && "textContent" in document.body)
- return el.textContent;
- else
- return el.innerText || el.textContent || "";
-};
+ 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;
-exports.getParentWindow = function(document) {
- return document.defaultView || document.parentWindow;
-};
+ if (!this.$scrollStopTimeout) {
+ var self = this;
+ this.$scrollStopTimeout = setTimeout(function() {
+ self.$passScrollEvent = true;
+ self.$scrollStopTimeout = null;
+ }, 200);
+ }
+ }
-exports.getSelectionStart = function(textarea) {
- // TODO IE
- var start;
- try {
- start = textarea.selectionStart || 0;
- } catch (e) {
- start = 0;
- }
- return start;
-};
+ editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);
+ return ev.preventDefault();
+ };
-exports.setSelectionStart = function(textarea, start) {
- // TODO IE
- return textarea.selectionStart = start;
-};
+}).call(DefaultHandlers.prototype);
-exports.getSelectionEnd = function(textarea) {
- // TODO IE
- var end;
- try {
- end = textarea.selectionEnd || 0;
- } catch (e) {
- end = 0;
- }
- return end;
-};
+exports.DefaultHandlers = DefaultHandlers;
-exports.setSelectionEnd = function(textarea, end) {
- // TODO IE
- return textarea.selectionEnd = end;
-};
+function calcDistance(ax, ay, bx, by) {
+ return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));
+}
});
-/* ***** BEGIN LICENSE BLOCK *****
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
@@ -5156,6 +5386,8 @@ exports.setSelectionEnd = function(textarea, end) {
*
* Contributor(s):
* Fabian Jakobs
+ * Irakli Gozalishvili (http://jeditoolkit.com)
+ * Julian Viereck
*
* 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
@@ -5171,276 +5403,70 @@ exports.setSelectionEnd = function(textarea, end) {
*
* ***** END LICENSE BLOCK ***** */
-define('pilot/event', ['require', 'exports', 'module' , 'pilot/keys', 'pilot/useragent', 'pilot/dom'], function(require, exports, module) {
+define('ace/lib/browser_focus', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event', 'ace/lib/event_emitter'], function(require, exports, module) {
+"use strict";
-var keys = require("pilot/keys");
-var useragent = require("pilot/useragent");
-var dom = require("pilot/dom");
+var oop = require("./oop");
+var event = require("./event");
+var EventEmitter = require("./event_emitter").EventEmitter;
-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);
- }
-};
+/*
+ * This class keeps track of the focus state of the given window.
+ * Focus changes for example when the user switches a browser tab,
+ * goes to the location bar or switches to another application.
+ */
+var BrowserFocus = function(win) {
+ win = win || window;
+
+ this.lastFocus = new Date().getTime();
+ this._isFocused = true;
+
+ var _self = this;
-exports.removeListener = function(elem, type, callback) {
- if (elem.removeEventListener) {
- return elem.removeEventListener(type, callback, false);
+ // IE < 9 supports focusin and focusout events
+ if ("onfocusin" in win.document) {
+ event.addListener(win.document, "focusin", function(e) {
+ _self._setFocused(true);
+ });
+
+ event.addListener(win.document, "focusout", function(e) {
+ _self._setFocused(!!e.toElement);
+ });
}
- if (elem.detachEvent) {
- elem.detachEvent("on" + type, callback._wrapper || callback);
+ else {
+ event.addListener(win, "blur", function(e) {
+ _self._setFocused(false);
+ });
+
+ event.addListener(win, "focus", function(e) {
+ _self._setFocused(true);
+ });
}
};
-/**
-* Prevents propagation and clobbers the default action of the passed event
-*/
-exports.stopEvent = function(e) {
- exports.stopPropagation(e);
- exports.preventDefault(e);
- return false;
-};
+(function(){
-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.getDocumentX = function(e) {
- if (e.clientX) {
- return e.clientX + dom.getPageScrollLeft();
- } else {
- return e.pageX;
- }
-};
-
-exports.getDocumentY = function(e) {
- if (e.clientY) {
- return e.clientY + dom.getPageScrollTop();
- } else {
- return e.pageY;
- }
-};
-
-/**
- * @return {Number} 0 for left button, 1 for middle button, 2 for right button
- */
-exports.getButton = function(e) {
- if (e.type == "dblclick")
- return 0;
- else if (e.type == "contextmenu")
- 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) {
- function onMouseMove(e) {
- eventHandler(e);
- return exports.stopPropagation(e);
- }
-
- function onReleaseCapture(e) {
- eventHandler && eventHandler(e);
- releaseCaptureHandler && releaseCaptureHandler();
-
- 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 onMouseMove(e) {
- eventHandler(e);
- e.stopPropagation();
- }
-
- function onMouseUp(e) {
- eventHandler && eventHandler(e);
- releaseCaptureHandler && releaseCaptureHandler();
-
- document.removeEventListener("mousemove", onMouseMove, true);
- document.removeEventListener("mouseup", onMouseUp, true);
-
- e.stopPropagation();
- }
-
- document.addEventListener("mousemove", onMouseMove, true);
- document.addEventListener("mouseup", onMouseUp, true);
- };
-}
-
-exports.addMouseWheelListener = function(el, callback) {
- var listener = function(e) {
- if (e.wheelDelta !== undefined) {
- if (e.wheelDeltaX !== undefined) {
- e.wheelX = -e.wheelDeltaX / 8;
- e.wheelY = -e.wheelDeltaY / 8;
- } else {
- e.wheelX = 0;
- e.wheelY = -e.wheelDelta / 8;
- }
- }
- 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);
+ oop.implement(this, EventEmitter);
+
+ this.isFocused = function() {
+ return this._isFocused;
};
- exports.addListener(el, "DOMMouseScroll", listener);
- exports.addListener(el, "mousewheel", listener);
-};
-
-exports.addMultiMouseDownListener = function(el, button, count, timeout, callback) {
- var clicks = 0;
- var startX, startY;
-
- var listener = function(e) {
- clicks += 1;
- if (clicks == 1) {
- startX = e.clientX;
- startY = e.clientY;
-
- setTimeout(function() {
- clicks = 0;
- }, timeout || 600);
- }
-
- var isButton = exports.getButton(e) == button;
- if (!isButton || Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5)
- clicks = 0;
-
- if (clicks == count) {
- clicks = 0;
- callback(e);
- }
-
- if (isButton)
- return exports.preventDefault(e);
+
+ this._setFocused = function(isFocused) {
+ if (this._isFocused == isFocused)
+ return;
+
+ if (isFocused)
+ this.lastFocus = new Date().getTime();
+
+ this._isFocused = isFocused;
+ this._emit("changeFocus");
};
- exports.addListener(el, "mousedown", listener);
- useragent.isIE && exports.addListener(el, "dblclick", listener);
-};
-
-function normalizeCommandKeys(callback, e, keyCode) {
- var hashId = 0;
- if (useragent.isOpera && 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 == 0 && !(keyCode in keys.FUNCTION_KEYS)) {
- return false;
- }
-
- return callback(e, hashId, keyCode);
-}
-
-exports.addCommandKeyListener = function(el, callback) {
- var addListener = exports.addListener;
- if (useragent.isOldGecko) {
- // 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);
- });
+}).call(BrowserFocus.prototype);
- // repeated keys are fired as keypress and not keydown events
- if (useragent.isMac && useragent.isOpera) {
- addListener(el, "keypress", function(e) {
- var keyId = e.keyIdentifier || e.keyCode;
- if (lastDown !== keyId) {
- return normalizeCommandKeys(callback, e, e.keyCode);
- } else {
- lastDown = null;
- }
- });
- }
- }
-};
+exports.BrowserFocus = BrowserFocus;
});
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
@@ -5466,7 +5492,7 @@ exports.addCommandKeyListener = function(el, callback) {
* Contributor(s):
* Fabian Jakobs
* Irakli Gozalishvili (http://jeditoolkit.com)
- * Julian Viereck
+ * Mike de Boer
*
* 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
@@ -5482,1191 +5508,3309 @@ exports.addCommandKeyListener = function(el, callback) {
*
* ***** END LICENSE BLOCK ***** */
-define('ace/editor', ['require', 'exports', 'module' , 'pilot/fixoldbrowsers', 'pilot/oop', 'pilot/event', 'pilot/lang', 'pilot/useragent', 'ace/keyboard/textinput', 'ace/mouse_handler', 'ace/keyboard/keybinding', 'ace/edit_session', 'ace/search', 'ace/range', 'pilot/event_emitter'], function(require, exports, module) {
+define('ace/lib/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
-require("pilot/fixoldbrowsers");
-
-var oop = require("pilot/oop");
-var event = require("pilot/event");
-var lang = require("pilot/lang");
-var useragent = require("pilot/useragent");
-var TextInput = require("ace/keyboard/textinput").TextInput;
-var MouseHandler = require("ace/mouse_handler").MouseHandler;
-//var TouchHandler = require("ace/touch_handler").TouchHandler;
-var KeyBinding = require("ace/keyboard/keybinding").KeyBinding;
-var EditSession = require("ace/edit_session").EditSession;
-var Search = require("ace/search").Search;
-var Range = require("ace/range").Range;
-var EventEmitter = require("pilot/event_emitter").EventEmitter;
+var EventEmitter = {};
-var Editor =function(renderer, session) {
- var container = renderer.getContainerElement();
- this.container = container;
- this.renderer = renderer;
+EventEmitter._emit =
+EventEmitter._dispatchEvent = function(eventName, e) {
+ this._eventRegistry = this._eventRegistry || {};
+ this._defaultHandlers = this._defaultHandlers || {};
- this.textInput = new TextInput(renderer.getTextAreaContainer(), this);
- this.keyBinding = new KeyBinding(this);
+ var listeners = this._eventRegistry[eventName] || [];
+ var defaultHandler = this._defaultHandlers[eventName];
+ if (!listeners.length && !defaultHandler)
+ return;
- // TODO detect touch event support
- if (useragent.isIPad) {
- //this.$mouseHandler = new TouchHandler(this);
- } else {
- this.$mouseHandler = new MouseHandler(this);
+ e = e || {};
+ e.type = eventName;
+
+ if (!e.stopPropagation) {
+ e.stopPropagation = function() {
+ this.propagationStopped = true;
+ };
+ }
+
+ if (!e.preventDefault) {
+ e.preventDefault = function() {
+ this.defaultPrevented = true;
+ };
}
- this.$blockScrolling = 0;
- this.$search = new Search().set({
- wrap: true
- });
+ for (var i=0; i
+ *
+ * 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 ***** */
- this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);
- this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker);
+define('ace/mouse/default_gutter_handler', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
- this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);
- this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker);
+function GutterHandler(mouseHandler) {
+ var editor = mouseHandler.editor;
- this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);
- this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint);
+ mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) {
+ if (e.domEvent.target.className.indexOf("ace_gutter-cell") == -1)
+ return;
- this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);
- this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation);
+ if (!editor.isFocused())
+ return;
- this.$onCursorChange = this.onCursorChange.bind(this);
- this.session.addEventListener("changeOverwrite", this.$onCursorChange);
+ var row = e.getDocumentPosition().row;
+ var selection = editor.session.selection;
- this.selection = session.getSelection();
- this.selection.addEventListener("changeCursor", this.$onCursorChange);
+ selection.moveCursorTo(row, 0);
+ selection.selectLine();
- this.$onSelectionChange = this.onSelectionChange.bind(this);
- this.selection.addEventListener("changeSelection", this.$onSelectionChange);
+ mouseHandler.$clickSelection = selection.getRange();
+ mouseHandler.captureMouse(e, "selectByLines");
+ });
+}
- this.onChangeMode();
+exports.GutterHandler = GutterHandler;
- this.onCursorChange();
- this.onSelectionChange();
- this.onChangeFrontMarker();
- this.onChangeBackMarker();
- this.onChangeBreakpoint();
- this.onChangeAnnotation();
- this.session.getUseWrapMode() && this.renderer.adjustWrapLimit();
- this.renderer.scrollToRow(session.getScrollTopRow());
- this.renderer.updateFull();
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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 ***** */
- this._dispatchEvent("changeSession", {
- session: session,
- oldSession: oldSession
- });
- };
+define('ace/mouse/mouse_event', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) {
+"use strict";
- this.getSession = function() {
- return this.session;
- };
+var event = require("../lib/event");
- this.getSelection = function() {
- return this.selection;
- };
+/*
+ * Custom Ace mouse event
+ */
+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.resize = function() {
- this.renderer.onResize();
- };
+ this.$pos = null;
+ this.$inSelection = null;
+
+ this.propagationStopped = false;
+ this.defaultPrevented = false;
+};
- this.setTheme = function(theme) {
- this.renderer.setTheme(theme);
+(function() {
+
+ this.stopPropagation = function() {
+ event.stopPropagation(this.domEvent);
+ this.propagationStopped = true;
};
-
- this.getTheme = function() {
- return this.renderer.getTheme();
+
+ this.preventDefault = function() {
+ event.preventDefault(this.domEvent);
+ this.defaultPrevented = true;
};
-
- this.setStyle = function(style) {
- this.renderer.setStyle(style);
+
+ this.stop = function() {
+ this.stopPropagation();
+ this.preventDefault();
};
- this.unsetStyle = function(style) {
- this.renderer.unsetStyle(style);
+ /*
+ * Get the document position below the mouse cursor
+ *
+ * @return {Object} 'row' and 'column' of the document position
+ */
+ this.getDocumentPosition = function() {
+ if (this.$pos)
+ return this.$pos;
+
+ this.$pos = this.editor.renderer.screenToTextCoordinates(this.clientX, this.clientY);
+ return this.$pos;
};
- this.setFontSize = function(size) {
- this.container.style.fontSize = size;
- };
-
- this.$highlightBrackets = function() {
- if (this.session.$bracketHighlight) {
- this.session.removeMarker(this.session.$bracketHighlight);
- this.session.$bracketHighlight = null;
- }
-
- if (this.$highlightPending) {
- return;
+ /*
+ * Check if the mouse cursor is inside of the text selection
+ *
+ * @return {Boolean} whether the mouse cursor is inside of the selection
+ */
+ this.inSelection = function() {
+ if (this.$inSelection !== null)
+ return this.$inSelection;
+
+ var editor = this.editor;
+
+ if (editor.getReadOnly()) {
+ this.$inSelection = false;
}
-
- // 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");
+ else {
+ var selectionRange = editor.getSelectionRange();
+ if (selectionRange.isEmpty())
+ this.$inSelection = false;
+ else {
+ var pos = this.getDocumentPosition();
+ this.$inSelection = selectionRange.contains(pos.row, pos.column);
}
- }, 10);
- };
-
- this.focus = function() {
- // Safari needs the timeout
- // iOS and Firefox need it called immediately
- // to be on the save side we do both
- // except for IE
- var _self = this;
- if (!useragent.isIE) {
- setTimeout(function() {
- _self.textInput.focus();
- });
}
- this.textInput.focus();
+ return this.$inSelection;
};
- this.isFocused = function() {
- return this.textInput.isFocused();
+ /*
+ * Get the clicked mouse button
+ *
+ * @return {Number} 0 for left button, 1 for middle button, 2 for right button
+ */
+ this.getButton = function() {
+ return event.getButton(this.domEvent);
};
-
- this.blur = function() {
- this.textInput.blur();
+
+ /*
+ * @return {Boolean} whether the shift key was pressed when the event was emitted
+ */
+ this.getShiftKey = function() {
+ return this.domEvent.shiftKey;
};
-
- this.onFocus = function() {
- this.renderer.showCursor();
- this.renderer.visualizeFocus();
- this._dispatchEvent("focus");
+
+ this.getAccelKey = function() {
+ return this.domEvent.ctrlKey || this.domEvent.metaKey ;
};
+
+}).call(MouseEvent.prototype);
- this.onBlur = function() {
- this.renderer.hideCursor();
- this.renderer.visualizeBlur();
- this._dispatchEvent("blur");
- };
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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 ***** */
- this.onDocumentChange = function(e) {
- var delta = e.data;
- var range = delta.range;
+define('ace/mouse/fold_handler', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
- if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines")
- var lastRow = range.end.row;
- else
- lastRow = Infinity;
- this.renderer.updateLines(range.start.row, lastRow);
+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) {
+ if (e.domEvent.target.className.indexOf("ace_fold-widget") != -1) {
+ var row = e.getDocumentPosition().row;
+ editor.session.onFoldWidgetClick(row, e.domEvent);
+ e.stop();
+ }
+ });
+}
- // update cursor because tab characters can influence the cursor position
- this.renderer.updateCursor();
- };
+exports.FoldHandler = FoldHandler;
- this.onTokenizerUpdate = function(e) {
- var rows = e.data;
- this.renderer.updateLines(rows.first, rows.last);
- };
+});
+/* ***** 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
+ * Julian Viereck
+ * Harutyun Amirjanyan
+ *
+ * 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 ***** */
- this.onCursorChange = function(e) {
- this.renderer.updateCursor();
+define('ace/keyboard/keybinding', ['require', 'exports', 'module' , 'ace/lib/keys', 'ace/lib/event', 'ace/commands/default_commands'], function(require, exports, module) {
+"use strict";
- if (!this.$blockScrolling) {
- this.renderer.scrollCursorIntoView();
- }
+var keyUtil = require("../lib/keys");
+var event = require("../lib/event");
+require("../commands/default_commands");
- // move text input over the cursor
- // this is required for iOS and IME
- this.renderer.moveTextAreaToCursor(this.textInput.getElement());
+var KeyBinding = function(editor) {
+ this.$editor = editor;
+ this.$data = { };
+ this.$handlers = [];
+ this.setDefaultHandler(editor.commands);
+};
- this.$highlightBrackets();
- this.$updateHighlightActiveLine();
+(function() {
+ this.setDefaultHandler = function(keyboardHandler) {
+ this.removeKeyboardHandler(this.$defaultHandler);
+ this.$defaultHandler = keyboardHandler;
+ if (keyboardHandler)
+ this.$handlers.unshift(keyboardHandler);
+ this.$data = { };
};
- this.$updateHighlightActiveLine = function() {
- var session = this.getSession();
-
- if (session.$highlightLineMarker) {
- session.removeMarker(session.$highlightLineMarker);
- }
- session.$highlightLineMarker = null;
+ this.setKeyboardHandler = function(keyboardHandler) {
+ if (this.$handlers[this.$handlers.length - 1] == keyboardHandler)
+ return;
+ this.$data = { };
+ this.$handlers = [];
+ this.setDefaultHandler(this.$defaultHandler);
+ if (keyboardHandler)
+ this.$handlers.push(keyboardHandler);
+ };
- if (this.getHighlightActiveLine() && (this.getSelectionStyle() != "line" || !this.selection.isMultiLine())) {
- var cursor = this.getCursorPosition(),
- foldLine = this.session.getFoldLine(cursor.row);
- 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.addKeyboardHandler = function(keyboardHandler) {
+ this.removeKeyboardHandler(keyboardHandler);
+ this.$handlers.push(keyboardHandler);
};
- this.onSelectionChange = function(e) {
- var session = this.getSession();
+ this.removeKeyboardHandler = function(keyboardHandler) {
+ var i = this.$handlers.indexOf(keyboardHandler);
+ if (i == -1)
+ return false;
+ this.$handlers.splice(i, 1);
+ return true;
+ };
- if (session.$selectionMarker) {
- session.removeMarker(session.$selectionMarker);
- }
- session.$selectionMarker = null;
+ this.getKeyboardHandler = function() {
+ return this.$handlers[this.$handlers.length - 1];
+ };
- if (!this.selection.isEmpty()) {
- var range = this.selection.getRange();
- var style = this.getSelectionStyle();
- session.$selectionMarker = session.addMarker(range, "ace_selection", style);
- } else {
- this.$updateHighlightActiveLine();
+ 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 (this.$highlightSelectedWord)
- this.session.getMode().highlightSelection(this);
- };
+ if (!toExecute || !toExecute.command)
+ return false;
- this.onChangeFrontMarker = function() {
- this.renderer.updateFrontMarkers();
- };
+ var success = false;
+ var commands = this.$editor.commands;
- this.onChangeBackMarker = function() {
- this.renderer.updateBackMarkers();
- };
+ // allow keyboardHandler to consume keys
+ if (toExecute.command != "null")
+ success = commands.exec(toExecute.command, this.$editor, toExecute.args, e);
+ else
+ success = true;
- this.onChangeBreakpoint = function() {
- this.renderer.setBreakpoints(this.session.getBreakpoints());
- };
+ if (success && e)
+ event.stopEvent(e);
- this.onChangeAnnotation = function() {
- this.renderer.setAnnotations(this.session.getAnnotations());
+ return success;
};
- this.onChangeMode = function() {
- this.renderer.updateText()
+ this.onCommandKey = function(e, hashId, keyCode) {
+ var keyString = keyUtil.keyCodeToString(keyCode);
+ this.$callKeyboardHandlers(hashId, keyString, keyCode, e);
};
- this.onChangeWrapLimit = function() {
- this.renderer.updateFull();
+ this.onTextInput = function(text) {
+ var success = false;
+ if (text.length == 1)
+ success = this.$callKeyboardHandlers(0, text);
+ if (!success)
+ this.$editor.commands.exec("insertstring", this.$editor, text);
};
- this.onChangeWrapMode = function() {
- this.renderer.onResize(true);
- };
+}).call(KeyBinding.prototype);
- 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();
- };
+exports.KeyBinding = KeyBinding;
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
+ * Julian Viereck
+ * Mihai Sucan
+ *
+ * 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 ***** */
- this.getCopyText = function() {
- if (!this.selection.isEmpty()) {
- return this.session.getTextRange(this.getSelectionRange());
- }
- else {
- return "";
- }
- };
+define('ace/commands/default_commands', ['require', 'exports', 'module' , 'ace/lib/lang'], function(require, exports, module) {
+"use strict";
- this.onCut = function() {
- if (this.$readOnly)
- return;
+var lang = require("../lib/lang");
- if (!this.selection.isEmpty()) {
- this.session.remove(this.getSelectionRange())
- this.clearSelection();
- }
+function bindKey(win, mac) {
+ return {
+ win: win,
+ mac: mac
};
+}
- this.insert = function(text) {
- if (this.$readOnly)
+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", "Alt-L"),
+ exec: function(editor) { editor.session.toggleFold(false); },
+ readOnly: true
+}, {
+ name: "unfold",
+ bindKey: bindKey("Alt-Shift-L", "Alt-Shift-L"),
+ exec: function(editor) { editor.session.toggleFold(true); },
+ readOnly: true
+}, {
+ name: "foldall",
+ bindKey: bindKey("Alt-0", "Alt-0"),
+ exec: function(editor) { editor.session.foldAll(); },
+ readOnly: true
+}, {
+ name: "unfoldall",
+ bindKey: bindKey("Alt-Shift-0", "Alt-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: bindKey("Insert", "Insert"),
+ exec: function(editor) { editor.toggleOverwrite(); },
+ readOnly: true
+}, {
+ name: "selecttostart",
+ bindKey: bindKey("Ctrl-Shift-Home|Alt-Shift-Up", "Command-Shift-Up"),
+ exec: function(editor) { editor.getSelection().selectFileStart(); },
+ readOnly: true
+}, {
+ name: "gotostart",
+ bindKey: bindKey("Ctrl-Home|Ctrl-Up", "Command-Home|Command-Up"),
+ exec: function(editor) { editor.navigateFileStart(); },
+ 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|Alt-Shift-Down", "Command-Shift-Down"),
+ exec: function(editor) { editor.getSelection().selectFileEnd(); },
+ multiSelectAction: "forEach",
+ readOnly: true
+}, {
+ name: "gotoend",
+ bindKey: bindKey("Ctrl-End|Ctrl-Down", "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: bindKey("Shift-PageDown", "Shift-PageDown"),
+ exec: function(editor) { editor.selectPageDown(); },
+ readOnly: true
+}, {
+ name: "pagedown",
+ bindKey: bindKey(null, "PageDown"),
+ exec: function(editor) { editor.scrollPageDown(); },
+ readOnly: true
+}, {
+ name: "gotopagedown",
+ bindKey: bindKey("PageDown", "Option-PageDown|Ctrl-V"),
+ exec: function(editor) { editor.gotoPageDown(); },
+ readOnly: true
+}, {
+ name: "selectpageup",
+ bindKey: bindKey("Shift-PageUp", "Shift-PageUp"),
+ exec: function(editor) { editor.selectPageUp(); },
+ readOnly: true
+}, {
+ name: "pageup",
+ bindKey: bindKey(null, "PageUp"),
+ exec: function(editor) { editor.scrollPageUp(); },
+ readOnly: true
+}, {
+ name: "gotopageup",
+ bindKey: bindKey("PageUp", "Option-PageUp"),
+ exec: function(editor) { editor.gotoPageUp(); },
+ readOnly: true
+}, {
+ name: "selectlinestart",
+ bindKey: bindKey("Shift-Home", "Shift-Home"),
+ exec: function(editor) { editor.getSelection().selectLineStart(); },
+ multiSelectAction: "forEach",
+ readOnly: true
+}, {
+ name: "selectlineend",
+ bindKey: bindKey("Shift-End", "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(); },
+ 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-Shift-P", "Ctrl-Shift-P"),
+ exec: function(editor) { editor.jumpToMatching(); },
+ multiSelectAction: "forEach",
+ 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: "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("Ctrl-Alt-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("Ctrl-Alt-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"
+}];
+
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
+ * Mihai Sucan
+ * Julian Viereck
+ *
+ * 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('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/edit_session/folding', 'ace/edit_session/bracket_match'], function(require, exports, module) {
+"use strict";
+
+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;
+
+/**
+ * class EditSession
+ *
+ * Stores various states related to a [[Document `Document`]]. A single `EditSession` can be in charge of several `Document`s.
+ *
+ **/
+
+/**
+ * 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.$frontMarkers = {};
+ this.$backMarkers = {};
+ this.$markerId = 1;
+ this.$rowCache = [];
+ this.$wrapData = [];
+ this.$foldData = [];
+ this.$undoSelect = true;
+ this.$foldData.toString = function() {
+ var str = "";
+ this.forEach(function(foldLine) {
+ str += "\n" + foldLine.toString();
+ });
+ return str;
+ }
+
+ if (text instanceof Document) {
+ this.setDocument(text);
+ } else {
+ this.setDocument(new Document(text));
+ }
+
+ this.selection = new Selection(this);
+ this.setMode(mode);
+};
+
+
+(function() {
+
+ oop.implement(this, EventEmitter);
+
+ /**
+ * EditSession.setDocument(doc)
+ * - doc (Document): The new `Document` to use
+ *
+ * Sets the `EditSession` to point to a new `Document`. If a `BackgroundTokenizer` exists, it also points to `doc`.
+ *
+ **/
+ 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);
+ }
+ };
+
+ /**
+ * EditSession.getDocument() -> Document
+ *
+ * Returns the `Document` associated with this session.
+ *
+ **/
+ this.getDocument = function() {
+ return this.doc;
+ };
+
+ /** internal, hide
+ * EditSession.$resetRowCache(row)
+ * - row (Number): The row to work with
+ *
+ *
+ *
+ **/
+ this.$resetRowCache = function(row) {
+ if (row == 0) {
+ this.$rowCache = [];
+ return;
+ }
+ var rowCache = this.$rowCache;
+ for (var i = 0; i < rowCache.length; i++) {
+ if (rowCache[i].docRow >= row) {
+ rowCache.splice(i, rowCache.length);
+ return;
+ }
+ }
+ };
+
+ /**
+ * EditSession@onChangeFold(e)
+ *
+ * Emitted when a code fold changes its state.
+ *
+ **/
+ this.onChangeFold = function(e) {
+ var fold = e.data;
+ this.$resetRowCache(fold.start.row);
+ };
+
+ /**
+ * EditSession@onChange(e)
+ *
+ * Emitted when the document changes.
+ **/
+ 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.start(delta.range.start.row);
+ this._emit("change", e);
+ };
+
+ /**
+ * EditSession.setValue(text)
+ * - text (String): The new text to place
+ *
+ * Sets the session text.
+ *
+ **/
+ 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.toString
+ * EditSession.getValue() -> String
+ *
+ * Returns the current [[Document `Document`]] as a string.
+ *
+ **/
+ /** alias of: EditSession.getValue
+ * EditSession.toString() -> String
+ *
+ * Returns the current [[Document `Document`]] as a string.
+ *
+ **/
+ this.getValue =
+ this.toString = function() {
+ return this.doc.getValue();
+ };
+
+ /**
+ * EditSession.getSelection() -> String
+ *
+ * Returns the string of the current selection.
+ **/
+ this.getSelection = function() {
+ return this.selection;
+ };
+
+ /** related to: BackgroundTokenizer.getState
+ * EditSession.getState(row) -> Array
+ * - row (Number): The row to start at
+ *
+ * {:BackgroundTokenizer.getState}
+ *
+ **/
+ this.getState = function(row) {
+ return this.bgTokenizer.getState(row);
+ };
+
+ /** related to: BackgroundTokenizer.getTokens
+ * EditSession.getTokens(firstRow, lastRow) -> Array
+ * - firstRow (Number): The row to start at
+ * - lastRow (Number): The row to finish at
+ *
+ * Starts tokenizing at the row indicated. Returns a list of objects of the tokenized rows.
+ *
+ **/
+ this.getTokens = function(firstRow, lastRow) {
+ return this.bgTokenizer.getTokens(firstRow, lastRow);
+ };
+
+ /**
+ * EditSession.getTokenAt(row, column) -> Array
+ * - row (Number): The row number to retrieve from
+ * - column (Number): The column number to retrieve from
+ *
+ * Returns an array of tokens at the indicated row and column.
+ **/
+ this.getTokenAt = function(row, column) {
+ var tokens = this.bgTokenizer.getTokens(row, row)[0].tokens;
+ 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;
+ };
+
+ /**
+ * EditSession.setUndoManager(undoManager)
+ * - undoManager (UndoManager): The new undo manager
+ *
+ * Sets the undo manager.
+ **/
+ this.setUndoManager = function(undoManager) {
+ this.$undoManager = undoManager;
+ this.$resetRowCache(0);
+ this.$deltas = [];
+ this.$deltasDoc = [];
+ this.$deltasFold = [];
+
+ if (this.$informUndoManager)
+ this.$informUndoManager.cancel();
+
+ if (undoManager) {
+ var self = this;
+ /** internal, hide
+ * EditSession.$syncInformUndoManager()
+ *
+ *
+ **/
+ 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() {}
+ };
+
+ /**
+ * EditSession.getUndoManager() -> UndoManager
+ *
+ * Returns the current undo manager.
+ **/
+ 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;
+ /**
+ * EditSession.setUseSoftTabs(useSoftTabs)
+ * - useSoftTabs (Boolean): Value indicating whether or not to use soft tabs
+ *
+ * Pass `true` to enable the use of soft tabs. Soft tabs means you're using spaces instead of the tab character (`'\t'`).
+ *
+ **/
+ this.setUseSoftTabs = function(useSoftTabs) {
+ if (this.$useSoftTabs === useSoftTabs) return;
+
+ this.$useSoftTabs = useSoftTabs;
+ };
+
+ /**
+ * EditSession.getUseSoftTabs() -> Boolean
+ *
+ * Returns `true` if soft tabs are being used, `false` otherwise.
+ *
+ **/
+ this.getUseSoftTabs = function() {
+ return this.$useSoftTabs;
+ };
+
+ this.$tabSize = 4;
+ /**
+ * EditSession.setTabSize(tabSize)
+ * - tabSize (Number): The new tab size
+ *
+ * Set the number of spaces that define a soft tab; for example, passing in `4` transforms the soft tabs to be equivalent to four spaces. This function also emits the `changeTabSize` event.
+ **/
+ this.setTabSize = function(tabSize) {
+ if (isNaN(tabSize) || this.$tabSize === tabSize) return;
+
+ this.$modified = true;
+ this.$tabSize = tabSize;
+ this._emit("changeTabSize");
+ };
+
+ /**
+ * EditSession.getTabSize() -> Number
+ *
+ * Returns the current tab size.
+ **/
+ this.getTabSize = function() {
+ return this.$tabSize;
+ };
+
+ /**
+ * EditSession.isTabStop(position) -> Boolean
+ * - position (Object): The position to check
+ *
+ * Returns `true` if the character at the position is a soft tab.
+ **/
+ this.isTabStop = function(position) {
+ return this.$useSoftTabs && (position.column % this.$tabSize == 0);
+ };
+
+ this.$overwrite = false;
+ /**
+ * EditSession.setOverwrite(overwrite)
+ * - overwrite (Boolean): Defines wheter or not to set overwrites
+ *
+ * Pass in `true` to enable overwrites in your session, or `false` to disable. If overwrites is enabled, any text you enter will type over any text after it. If the value of `overwrite` changes, this function also emites the `changeOverwrite` event.
+ *
+ **/
+ this.setOverwrite = function(overwrite) {
+ if (this.$overwrite == overwrite) return;
+
+ this.$overwrite = overwrite;
+ this._emit("changeOverwrite");
+ };
+
+ /**
+ * EditSession.getOverwrite() -> Boolean
+ *
+ * Returns `true` if overwrites are enabled; `false` otherwise.
+ **/
+ this.getOverwrite = function() {
+ return this.$overwrite;
+ };
+
+ /**
+ * EditSession.toggleOverwrite()
+ *
+ * Sets the value of overwrite to the opposite of whatever it currently is.
+ **/
+ this.toggleOverwrite = function() {
+ this.setOverwrite(!this.$overwrite);
+ };
+
+ /**
+ * EditSession.getBreakpoints() -> Array
+ *
+ * Returns an array of numbers, indicating which rows have breakpoints.
+ **/
+ this.getBreakpoints = function() {
+ return this.$breakpoints;
+ };
+
+ /**
+ * EditSession.setBreakpoints(rows)
+ * - rows (Array): An array of row indicies
+ *
+ * Sets a breakpoint on every row number given by `rows`. This function also emites the `'changeBreakpoint'` event.
+ *
+ **/
+ this.setBreakpoints = function(rows) {
+ this.$breakpoints = [];
+ for (var i=0; i Number
+ * - range (Range): Define the range of the marker
+ * - clazz (String): Set the CSS class for the marker
+ * - type (Function | String): Identify the type of the marker
+ * - inFront (Boolean): Set to `true` to establish a front marker
+ *
+ * Adds a new marker to the given `Range`. If `inFront` is `true`, a front marker is defined, and the `'changeFrontMarker'` event fires; otherwise, the `'changeBackMarker'` event fires.
+ *
+ **/
+ this.addMarker = function(range, clazz, type, inFront) {
+ var id = this.$markerId++;
+
+ var marker = {
+ range : range,
+ type : type || "line",
+ renderer: typeof type == "function" ? type : null,
+ clazz : clazz,
+ inFront: !!inFront
+ }
+
+ if (inFront) {
+ this.$frontMarkers[id] = marker;
+ this._emit("changeFrontMarker")
+ } else {
+ this.$backMarkers[id] = marker;
+ this._emit("changeBackMarker")
+ }
+
+ return id;
+ };
+
+ /**
+ * EditSession.removeMarker(markerId)
+ * - markerId (Number): A number representing a marker
+ *
+ * Removes the marker with the specified ID. If this marker was in front, the `'changeFrontMarker'` event is emitted. If the marker was in the back, the `'changeBackMarker'` event is emitted.
+ *
+ **/
+ this.removeMarker = function(markerId) {
+ var marker = this.$frontMarkers[markerId] || this.$backMarkers[markerId];
+ if (!marker)
+ return;
+
+ var markers = marker.inFront ? this.$frontMarkers : this.$backMarkers;
+ if (marker) {
+ delete (markers[markerId]);
+ this._emit(marker.inFront ? "changeFrontMarker" : "changeBackMarker");
+ }
+ };
+
+ /**
+ * EditSession.getMarkers(inFront) -> Array
+ * - inFront (Boolean): If `true`, indicates you only want front markers; `false` indicates only back markers
+ *
+ * Returns an array containing the IDs of all the markers, either front or back.
+ *
+ **/
+ this.getMarkers = function(inFront) {
+ return inFront ? this.$frontMarkers : this.$backMarkers;
+ };
+
+ /*
+ * Error:
+ * {
+ * row: 12,
+ * column: 2, //can be undefined
+ * text: "Missing argument",
+ * type: "error" // or "warning" or "info"
+ * }
+ */
+ /**
+ * EditSession.setAnnotations(annotations)
+ * - annotations (Array): A list of annotations
+ *
+ * Sets annotations for the `EditSession`. This functions emits the `'changeAnnotation'` event.
+ **/
+ this.setAnnotations = function(annotations) {
+ this.$annotations = {};
+ for (var i=0; i Object
+ *
+ * Returns the annotations for the `EditSession`.
+ **/
+ this.getAnnotations = function() {
+ return this.$annotations || {};
+ };
+
+ /**
+ * EditSession.clearAnnotations()
+ *
+ * Clears all the annotations for this session. This function also triggers the `'changeAnnotation'` event.
+ **/
+ this.clearAnnotations = function() {
+ this.$annotations = {};
+ this._emit("changeAnnotation", {});
+ };
+
+ /** internal, hide
+ * EditSession.$detectNewLine(text)
+ * - text (String): A block of text
+ *
+ * If `text` contains either the newline (`\n`) or carriage-return ('\r') characters, `$autoNewLine` stores that value.
+ *
+ **/
+ this.$detectNewLine = function(text) {
+ var match = text.match(/^.*?(\r?\n)/m);
+ if (match) {
+ this.$autoNewLine = match[1];
+ } else {
+ this.$autoNewLine = "\n";
+ }
+ };
+
+ /**
+ * EditSession.getWordRange(row, column) -> Range
+ * - row (Number): The row to start at
+ * - column (Number): The column to start at
+ *
+ * Given a starting row and column, this method returns the `Range` of the first word boundary it finds.
+ *
+ **/
+ this.getWordRange = function(row, column) {
+ var line = this.getLine(row);
+
+ var inToken = false;
+ if (column > 0) {
+ inToken = !!line.charAt(column - 1).match(this.tokenRe);
+ }
+
+ if (!inToken) {
+ inToken = !!line.charAt(column).match(this.tokenRe);
+ }
+
+ var re = inToken ? this.tokenRe : 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);
+ };
+
+ /**
+ * EditSession.getAWordRange(row, column) -> Range
+ * - row (Number): The row number to start from
+ * - column (Number): The column number to start from
+ *
+ * Gets the range of a word, including its right whitespace.
+ **/
+ 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;
+ };
+
+ /** related to: Document.setNewLineMode
+ * EditSession.setNewLineMode(newLineMode)
+ * - newLineMode (String): {:Document.setNewLineMode.param}
+ *
+ * {:Document.setNewLineMode.desc}
+ **/
+ this.setNewLineMode = function(newLineMode) {
+ this.doc.setNewLineMode(newLineMode);
+ };
+
+ /** related to: Document.getNewLineMode
+ * EditSession.getNewLineMode() -> String
+ *
+ * Returns the current new line mode.
+ **/
+ this.getNewLineMode = function() {
+ return this.doc.getNewLineMode();
+ };
+
+ this.$useWorker = true;
+
+ /**
+ * EditSession.setUseWorker(useWorker)
+ * - useWorker (Boolean): Set to `true` to use a worker
+ *
+ * Identifies if you want to use a worker for the `EditSession`.
+ *
+ **/
+ this.setUseWorker = function(useWorker) {
+ if (this.$useWorker == useWorker)
return;
- var session = this.session;
- var mode = session.getMode();
+ this.$useWorker = useWorker;
- var cursor = this.getCursorPosition();
+ this.$stopWorker();
+ if (useWorker)
+ this.$startWorker();
+ };
- 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;
- }
+ /**
+ * EditSession.getUseWorker() -> Boolean
+ *
+ * Returns `true` if workers are being used.
+ **/
+ this.getUseWorker = function() {
+ return this.$useWorker;
+ };
- text = text.replace("\t", this.session.getTabString());
+ /**
+ * EditSession@onReloadTokenizer(e)
+ *
+ * Reloads all the tokens on the current session. This function calls [[BackgroundTokenizer.start `BackgroundTokenizer.start ()`]] to all the rows; it also emits the `'tokenizerUpdate'` event.
+ **/
+ this.onReloadTokenizer = function(e) {
+ var rows = e.data;
+ this.bgTokenizer.start(rows.first);
+ this._emit("tokenizerUpdate", e);
+ };
- // remove selected text
- if (!this.selection.isEmpty()) {
- var cursor = this.session.remove(this.getSelectionRange());
- this.clearSelection();
+ this.$modes = {};
+ this._loadMode = function(mode, callback) {
+ if (this.$modes[mode])
+ return callback(this.$modes[mode]);
+
+ var _self = this;
+ var module;
+ try {
+ module = require(mode);
+ } catch (e) {};
+ if (module)
+ return done(module);
+
+ fetch(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]);
}
- else if (this.session.getOverwrite()) {
- var range = new Range.fromPoints(cursor, cursor);
- range.end.column += text.length;
- this.session.remove(range);
+
+ function fetch(callback) {
+ if (!config.get("packaged"))
+ return callback();
+
+ var base = mode.split("/").pop();
+ var filename = config.get("modePath") + "/mode-" + base + config.get("suffix");
+ net.loadScript(filename, callback);
}
+ };
- this.clearSelection();
+ /**
+ * EditSession.setMode(mode)
+ * - mode (TextMode): Set a new text mode
+ *
+ * Sets a new text mode for the `EditSession`. This method also emits the `'changeMode'` event. If a [[BackgroundTokenizer `BackgroundTokenizer`]] is set, the `'tokenizerUpdate'` event is also emitted.
+ *
+ **/
+ this.$mode = null;
+ this.$modeId = null;
+ this.setMode = function(mode) {
+ // load on demand
+ if (typeof mode === "string") {
+ if (this.$modeId == mode)
+ return;
- 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);
+ this.$modeId = mode;
+ var _self = this;
+ this._loadMode(mode, function(module) {
+ if (_self.$modeId !== mode)
+ return;
- 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]));
- }
+ _self.setMode(module);
+ });
+ return;
+ } else if (mode == null) {
+ mode = "ace/mode/text"
+ this.$modeId = mode;
+ this.$modes[mode] = this.$modes[mode] || (new TextMode());
+ this.setMode(this.$modes[mode]);
+ return;
}
- 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);
+ if (this.$mode === mode) return;
+ this.$mode = mode;
+ this.$modeId = mode.$id;
- var size = session.getTabSize();
- var minIndent = Number.MAX_VALUE;
+ this.$stopWorker();
- for (var row = cursor.row + 1; row <= end.row; ++row) {
- var indent = 0;
+ if (this.$useWorker)
+ this.$startWorker();
- 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);
- }
+ var tokenizer = mode.getTokenizer();
- for (var row = cursor.row + 1; row <= end.row; ++row) {
- var outdent = minIndent;
+ if(tokenizer.addEventListener !== undefined) {
+ var onReloadTokenizer = this.onReloadTokenizer.bind(this);
+ tokenizer.addEventListener("update", onReloadTokenizer);
+ }
- 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 (!this.bgTokenizer) {
+ this.bgTokenizer = new BackgroundTokenizer(tokenizer);
+ var _self = this;
+ this.bgTokenizer.addEventListener("update", function(e) {
+ _self._emit("tokenizerUpdate", e);
+ });
} else {
- if (shouldOutdent) {
- mode.autoOutdent(lineState, session, cursor.row);
- }
+ 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");
+ };
+
+ /** internal, hide
+ * EditSession.stopWorker()
+ *
+ *
+ **/
+ this.$stopWorker = function() {
+ if (this.$worker)
+ this.$worker.terminate();
+
+ this.$worker = null;
};
- this.onTextInput = function(text, notPasted) {
- // In case the text was not pasted and we got only one character, then
- // handel it as a command key stroke.
- if (notPasted && text.length == 1) {
- // Note: The `null` as `keyCode` is important here, as there are
- // some checks in the code for `keyCode == 0` meaning the text comes
- // from the keyBinding.onTextInput code path.
- var handled = this.keyBinding.onCommandKey({}, 0, null, text);
-
- // Check if the text was handled. If not, then handled it as "normal"
- // text and insert it to the editor directly. This shouldn't be done
- // using the this.keyBinding.onTextInput(text) function, as it would
- // make the `text` get sent to the keyboardHandler twice, which might
- // turn out to be a bad thing in case there is a custome keyboard
- // handler like the StateHandler.
- if (!handled) {
- this.insert(text);
+ /** internal, hide
+ * EditSession.$startWorker()
+ *
+ *
+ **/
+ 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.keyBinding.onTextInput(text);
}
+ else
+ this.$worker = null;
};
- this.onCommandKey = function(e, hashId, keyCode) {
- this.keyBinding.onCommandKey(e, hashId, keyCode);
+ /**
+ * EditSession.getMode() -> TextMode
+ *
+ * Returns the current text mode.
+ **/
+ this.getMode = function() {
+ return this.$mode;
};
- this.setOverwrite = function(overwrite) {
- this.session.setOverwrite(overwrite);
+ this.$scrollTop = 0;
+ /**
+ * EditSession.setScrollTop(scrollTop)
+ * - scrollTop (Number): The new scroll top value
+ *
+ * This function sets the scroll top value. It also emits the `'changeScrollTop'` event.
+ **/
+ this.setScrollTop = function(scrollTop) {
+ scrollTop = Math.round(Math.max(0, scrollTop));
+ if (this.$scrollTop === scrollTop)
+ return;
+
+ this.$scrollTop = scrollTop;
+ this._emit("changeScrollTop", scrollTop);
};
- this.getOverwrite = function() {
- return this.session.getOverwrite();
+ /**
+ * EditSession.getScrollTop() -> Number
+ *
+ * [Returns the value of the distance between the top of the editor and the topmost part of the visible content.]{: #EditSession.getScrollTop}
+ **/
+ this.getScrollTop = function() {
+ return this.$scrollTop;
};
- this.toggleOverwrite = function() {
- this.session.toggleOverwrite();
+ this.$scrollLeft = 0;
+ /**
+ * EditSession.setScrollLeft(scrollLeft)
+ *
+ * [Sets the value of the distance between the left of the editor and the leftmost part of the visible content.]{: #EditSession.setScrollLeft}
+ **/
+ this.setScrollLeft = function(scrollLeft) {
+ scrollLeft = Math.round(Math.max(0, scrollLeft));
+ if (this.$scrollLeft === scrollLeft)
+ return;
+
+ this.$scrollLeft = scrollLeft;
+ this._emit("changeScrollLeft", scrollLeft);
};
- this.setScrollSpeed = function(speed) {
- this.$mouseHandler.setScrollSpeed(speed);
+ /**
+ * EditSession.getScrollLeft() -> Number
+ *
+ * [Returns the value of the distance between the left of the editor and the leftmost part of the visible content.]{: #EditSession.getScrollLeft}
+ **/
+ this.getScrollLeft = function() {
+ return this.$scrollLeft;
};
- this.getScrollSpeed = function() {
- return this.$mouseHandler.getScrollSpeed()
+ /**
+ * EditSession.getWidth() -> Number
+ *
+ * Returns the width of the document.
+ **/
+ this.getWidth = function() {
+ this.$computeWidth();
+ return this.width;
};
- this.$selectionStyle = "line";
- this.setSelectionStyle = function(style) {
- if (this.$selectionStyle == style) return;
+ /**
+ * EditSession.getScreenWidth() -> Number
+ *
+ * Returns the width of the screen.
+ **/
+ this.getScreenWidth = function() {
+ this.$computeWidth();
+ return this.screenWidth;
+ };
- this.$selectionStyle = style;
- this.onSelectionChange();
- this._dispatchEvent("changeSelectionStyle", {data: style});
+ this.$computeWidth = function(force) {
+ if (this.$modified || force) {
+ this.$modified = false;
+
+ var lines = this.doc.getAllLines();
+ var longestLine = 0;
+ var longestScreenLine = 0;
+
+ for ( var i = 0; i < lines.length; i++) {
+ var foldLine = this.getFoldLine(i),
+ line, len;
+
+ line = lines[i];
+ if (foldLine) {
+ var end = foldLine.range.end;
+ line = this.getFoldDisplayLine(foldLine);
+ // Continue after the foldLine.end.row. All the lines in
+ // between are folded.
+ i = end.row;
+ }
+ len = line.length;
+ longestLine = Math.max(longestLine, len);
+ if (!this.$useWrapMode) {
+ longestScreenLine = Math.max(
+ longestScreenLine,
+ this.$getStringScreenWidth(line)[0]
+ );
+ }
+ }
+ this.width = longestLine;
+
+ if (this.$useWrapMode) {
+ this.screenWidth = this.$wrapLimit;
+ } else {
+ this.screenWidth = longestScreenLine;
+ }
+ }
};
- this.getSelectionStyle = function() {
- return this.$selectionStyle;
+ /** related to: Document.getLine
+ * EditSession.getLine(row) -> String
+ * - row (Number): The row to retrieve from
+ *
+ * Returns a verbatim copy of the given line as it is in the document
+ *
+ **/
+ this.getLine = function(row) {
+ return this.doc.getLine(row);
};
- this.$highlightActiveLine = true;
- this.setHighlightActiveLine = function(shouldHighlight) {
- if (this.$highlightActiveLine == shouldHighlight) return;
-
- this.$highlightActiveLine = shouldHighlight;
- this.$updateHighlightActiveLine();
+ /** related to: Document.getLines
+ * EditSession.getLines(firstRow, lastRow) -> Array
+ * - firstRow (Number): The first row index to retrieve
+ * - lastRow (Number): The final row index to retrieve
+ *
+ * Returns an array of strings of the rows between `firstRow` and `lastRow`. This function is inclusive of `lastRow`.
+ *
+ **/
+ this.getLines = function(firstRow, lastRow) {
+ return this.doc.getLines(firstRow, lastRow);
};
- this.getHighlightActiveLine = function() {
- return this.$highlightActiveLine;
+ /** related to: Document.getLength
+ * EditSession.getLength()-> Number
+ *
+ * Returns the number of rows in the document.
+ **/
+ this.getLength = function() {
+ return this.doc.getLength();
};
- this.$highlightSelectedWord = true;
- this.setHighlightSelectedWord = function(shouldHighlight) {
- if (this.$highlightSelectedWord == shouldHighlight)
- return;
+ /** related to: Document.getTextRange
+ * EditSession.getTextRange(range) -> Array
+ * - range (String): The range to work with
+ *
+ * {:Document.getTextRange.desc}
+ **/
+ this.getTextRange = function(range) {
+ return this.doc.getTextRange(range);
+ };
- this.$highlightSelectedWord = shouldHighlight;
- if (shouldHighlight)
- this.session.getMode().highlightSelection(this);
- else
- this.session.getMode().clearSelectionHighlight(this);
+ /** related to: Document.insert
+ * EditSession.insert(position, text) -> Number
+ * - position (Number): The position to start inserting at
+ * - text (String): A chunk of text to insert
+ * + (Number): The position of the last line of `text`. If the length of `text` is 0, this function simply returns `position`.
+ *
+ * Inserts a block of `text` and the indicated `position`.
+ *
+ *
+ **/
+ this.insert = function(position, text) {
+ return this.doc.insert(position, text);
};
- this.getHighlightSelectedWord = function() {
- return this.$highlightSelectedWord;
+ /** related to: Document.remove
+ * EditSession.remove(range) -> Object
+ * - range (Range): A specified Range to remove
+ * + (Object): The new `start` property of the range, which contains `startRow` and `startColumn`. If `range` is empty, this function returns the unmodified value of `range.start`.
+ *
+ * Removes the `range` from the document.
+ *
+ *
+ **/
+ this.remove = function(range) {
+ return this.doc.remove(range);
};
- this.setShowInvisibles = function(showInvisibles) {
- if (this.getShowInvisibles() == showInvisibles)
+ /**
+ * EditSession.undoChanges(deltas, dontSelect) -> Range
+ * - deltas (Array): An array of previous changes
+ * - dontSelect (Boolean): [If `true`, doesn't select the range of where the change occured]{: #dontSelect}
+ *
+ * Reverts previous changes to your document.
+ **/
+ this.undoChanges = function(deltas, dontSelect) {
+ if (!deltas.length)
return;
- this.renderer.setShowInvisibles(showInvisibles);
+ 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.getShowInvisibles = function() {
- return this.renderer.getShowInvisibles();
- };
+ /**
+ * EditSession.redoChanges(deltas, dontSelect) -> Range
+ * - deltas (Array): An array of previous changes
+ * - dontSelect (Boolean): {:dontSelect}
+ *
+ * Re-implements a previously undone change to your document.
+ **/
+ this.redoChanges = function(deltas, dontSelect) {
+ if (!deltas.length)
+ return;
- this.setShowPrintMargin = function(showPrintMargin) {
- this.renderer.setShowPrintMargin(showPrintMargin);
+ 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;
};
+
+ /**
+ * EditSession.setUndoSelect(enable)
+ * - enable (Boolean): If `true`, selects the range of the reinserted change
+ *
+ * ENables or disables highlighting of the range where an undo occured.
+ **/
+ this.setUndoSelect = function(enable) {
+ this.$undoSelect = enable;
+ };
+
+ /** internal, hide
+ * EditSession.$getUndoSelection(deltas, isUndo, lastUndoRange) -> Range
+ *
+ *
+ **/
+ this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {
+ function isInsert(delta) {
+ var insert =
+ delta.action == "insertText" || delta.action == "insertLines";
+ return isUndo ? !insert : insert;
+ }
- this.getShowPrintMargin = function() {
- return this.renderer.getShowPrintMargin();
- };
+ 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;
+ }
- this.setPrintMarginColumn = function(showPrintMargin) {
- this.renderer.setPrintMarginColumn(showPrintMargin);
- };
+ 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;
+ }
+ }
- this.getPrintMarginColumn = function() {
- return this.renderer.getPrintMarginColumn();
- };
+ // 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);
+ }
+ }
- this.$readOnly = false;
- this.setReadOnly = function(readOnly) {
- this.$readOnly = readOnly;
- };
+ return range;
+ },
- this.getReadOnly = function() {
- return this.$readOnly;
+ /** 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.$modeBehaviours = true;
- this.setBehavioursEnabled = function (enabled) {
- this.$modeBehaviours = enabled;
- }
+ /**
+ * EditSession.moveText(fromRange, toPosition) -> Range
+ * - fromRange (Range): The range of text you want moved within the document
+ * - toPosition (Object): The location (row and column) where you want to move the text to
+ * + (Range): The new range where the text was moved to.
+ * Moves a range of text from the given range to the given position. `toPosition` is an object that looks like this:
+ *
+ * { row: newRowLocation, column: newColumnLocation }
+ *
+ *
+ *
+ **/
+ this.moveText = function(fromRange, toPosition) {
+ var text = this.getTextRange(fromRange);
+ this.remove(fromRange);
- this.getBehavioursEnabled = function () {
- return this.$modeBehaviours;
- }
+ var toRow = toPosition.row;
+ var toColumn = toPosition.column;
- this.removeRight = function() {
- if (this.$readOnly)
- return;
+ // 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 (this.selection.isEmpty()) {
- this.selection.selectRight();
+ if (fromRange.isMultiLine() && fromRange.end.row < toRow) {
+ var lines = this.doc.$split(text);
+ toRow -= lines.length - 1;
}
- this.session.remove(this.getSelectionRange())
- this.clearSelection();
- };
- this.removeLeft = function() {
- if (this.$readOnly)
- return;
+ var endRow = toRow + fromRange.end.row - fromRange.start.row;
+ var endColumn = fromRange.isMultiLine() ?
+ fromRange.end.column :
+ toColumn + fromRange.end.column - fromRange.start.column;
- if (this.selection.isEmpty())
- this.selection.selectLeft();
+ var toRange = new Range(toRow, toColumn, endRow, endColumn);
- 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 !== false) {
- range = new_range;
- }
- }
+ this.insert(toRange.start, text);
- this.session.remove(range);
- this.clearSelection();
+ return toRange;
};
- this.removeWordRight = function() {
- if (this.$readOnly)
- return;
-
- if (this.selection.isEmpty())
- this.selection.selectWordRight();
-
- this.session.remove(this.getSelectionRange());
- this.clearSelection();
+ /**
+ * EditSession.indentRows(startRow, endRow, indentString)
+ * - startRow (Number): Starting row
+ * - endRow (Number): Ending row
+ * - indentString (String): The indent token
+ *
+ * Indents all the rows, from `startRow` to `endRow` (inclusive), by prefixing each row with the token in `indentString`.
+ *
+ * If `indentString` contains the `'\t'` character, it's replaced by whatever is defined by [[EditSession.getTabString `getTabString()`]].
+ *
+ **/
+ 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.removeWordLeft = function() {
- if (this.$readOnly)
- return;
+ /**
+ * EditSession.outdentRows(range)
+ * - range (Range): A range of rows
+ *
+ * Outdents all the rows defined by the `start` and `end` properties of `range`.
+ *
+ **/
+ this.outdentRows = function (range) {
+ var rowRange = range.collapseRows();
+ var deleteRange = new Range(0, 0, 0, 0);
+ var size = this.getTabSize();
- if (this.selection.isEmpty())
- this.selection.selectWordLeft();
+ for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) {
+ var line = this.getLine(i);
- this.session.remove(this.getSelectionRange());
- this.clearSelection();
+ 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.removeToLineStart = function() {
- if (this.$readOnly)
- return;
-
- if (this.selection.isEmpty())
- this.selection.selectLineStart();
+ /** related to: Document.insertLines
+ * EditSession.moveLinesUp(firstRow, lastRow) -> Number
+ * - firstRow (Number): The starting row to move up
+ * - lastRow (Number): The final row to move up
+ * + (Number): If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
+ *
+ * Shifts all the lines in the document up one, starting from `firstRow` and ending at `lastRow`.
+ *
+ *
+ **/
+ this.moveLinesUp = function(firstRow, lastRow) {
+ if (firstRow <= 0) return 0;
- this.session.remove(this.getSelectionRange());
- this.clearSelection();
+ var removed = this.doc.removeLines(firstRow, lastRow);
+ this.doc.insertLines(firstRow - 1, removed);
+ return -1;
};
- this.removeToLineEnd = function() {
- if (this.$readOnly)
- return;
+ /** related to: Document.insertLines
+ * EditSession.moveLinesDown(firstRow, lastRow) -> Number
+ * - firstRow (Number): The starting row to move down
+ * - lastRow (Number): The final row to move down
+ * + (Number): If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -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;
+ };
- if (this.selection.isEmpty())
- this.selection.selectLineEnd();
+ /**
+ * EditSession.duplicateLines(firstRow, lastRow) -> Number
+ * - firstRow (Number): The starting row to duplicate
+ * - lastRow (Number): The final row to duplicate
+ * + (Number): Returns the number of new rows added; in other words, `lastRow - firstRow + 1`.
+ *
+ * Duplicates all the text between `firstRow` and `lastRow`.
+ *
+ *
+ *
+ **/
+ this.duplicateLines = function(firstRow, lastRow) {
+ var firstRow = this.$clipRowToDocument(firstRow);
+ var lastRow = this.$clipRowToDocument(lastRow);
- var range = this.getSelectionRange();
- if (range.start.column == range.end.column && range.start.row == range.end.row) {
- range.end.column = 0;
- range.end.row++;
- }
+ var lines = this.getLines(firstRow, lastRow);
+ this.doc.insertLines(firstRow, lines);
- this.session.remove(range);
- this.clearSelection();
+ var addedRows = lastRow - firstRow + 1;
+ return addedRows;
};
- this.splitLine = function() {
- if (this.$readOnly)
- return;
- if (!this.selection.isEmpty()) {
- this.session.remove(this.getSelectionRange());
- this.clearSelection();
- }
+ this.$clipRowToDocument = function(row) {
+ return Math.max(0, Math.min(row, this.doc.getLength()-1));
+ };
- var cursor = this.getCursorPosition();
- this.insert("\n");
- this.moveCursorToPosition(cursor);
+ this.$clipColumnToRow = function(row, column) {
+ if (column < 0)
+ return 0;
+ return Math.min(this.doc.getLine(row).length, column);
};
- this.transposeLetters = function() {
- if (this.$readOnly)
- return;
- if (!this.selection.isEmpty()) {
- return;
+ 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);
+ }
}
- var cursor = this.getCursorPosition();
- var column = cursor.column;
- if (column == 0)
- return;
+ return {
+ row: row,
+ column: column
+ };
+ };
- var line = this.session.getLine(cursor.row);
- if (column < line.length) {
- var swap = line.charAt(column) + line.charAt(column-1);
- var range = new Range(cursor.row, column-1, cursor.row, column+1)
+ 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
+ );
}
- else {
- var swap = line.charAt(column-1) + line.charAt(column-2);
- var range = new Range(cursor.row, column-2, cursor.row, 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
+ );
}
- this.session.replace(range, swap);
+ return range;
};
- this.indent = function() {
- if (this.$readOnly)
- return;
-
- var session = this.session;
- var range = this.getSelectionRange();
+ // WRAPMODE
+ this.$wrapLimit = 80;
+ this.$useWrapMode = false;
+ this.$wrapLimitRange = {
+ min : null,
+ max : null
+ };
- 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;
+ /**
+ * EditSession.setUseWrapMode(useWrapMode)
+ * - useWrapMode (Boolean): Enable (or disable) wrap mode
+ *
+ * Sets whether or not line wrapping is enabled. If `useWrapMode` is different than the current value, the `'changeWrapMode'` event is emitted.
+ **/
+ this.setUseWrapMode = function(useWrapMode) {
+ if (useWrapMode != this.$useWrapMode) {
+ this.$useWrapMode = useWrapMode;
+ this.$modified = true;
+ this.$resetRowCache(0);
- if (this.session.getUseSoftTabs()) {
- var size = session.getTabSize(),
- position = this.getCursorPosition(),
- column = session.documentToScreenColumn(position.row, position.column),
- count = (size - column % size);
+ // 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);
+ }
- indentString = lang.stringRepeat(" ", count);
- } else
- indentString = "\t";
- return this.onTextInput(indentString);
+ this._emit("changeWrapMode");
}
};
- this.blockOutdent = function() {
- if (this.$readOnly)
- return;
-
- var selection = this.session.getSelection();
- this.session.outdentRows(selection.getRange());
+ /**
+ * EditSession.getUseWrapMode() -> Boolean
+ *
+ * Returns `true` if wrap mode is being used; `false` otherwise.
+ **/
+ this.getUseWrapMode = function() {
+ return this.$useWrapMode;
};
- this.toggleCommentLines = function() {
- if (this.$readOnly)
- return;
-
- var state = this.session.getState(this.getCursorPosition().row);
- var rows = this.$getSelectedRows()
- this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last);
+ // 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.removeLines = function() {
- if (this.$readOnly)
- return;
-
- var rows = this.$getSelectedRows();
- if (rows.last == 0 || rows.last+1 < this.session.getLength())
- var range = new Range(rows.first, 0, rows.last+1, 0)
- else
- var range = new Range(
- rows.first-1, this.session.getLine(rows.first).length,
- rows.last, this.session.getLine(rows.last).length
- );
- this.session.remove(range);
- this.clearSelection();
+ /** internal, hide
+ * EditSession.adjustWrapLimit(desiredLimit) -> Boolean
+ * - desiredLimit (Number): The new wrap limit
+ *
+ * This should generally only be called by the renderer when a resize is detected.
+ **/
+ 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.moveLinesDown = function() {
- if (this.$readOnly)
- return;
+ /** internal, hide
+ * EditSession.$constrainWrapLimit(wrapLimit)
+ *
+ *
+ **/
+ this.$constrainWrapLimit = function(wrapLimit) {
+ var min = this.$wrapLimitRange.min;
+ if (min)
+ wrapLimit = Math.max(min, wrapLimit);
- this.$moveLines(function(firstRow, lastRow) {
- return this.session.moveLinesDown(firstRow, lastRow);
- });
+ 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.moveLinesUp = function() {
- if (this.$readOnly)
- return;
+ /**
+ * EditSession.getWrapLimit() -> Number
+ *
+ * Returns the value of wrap limit.
+ **/
+ this.getWrapLimit = function() {
+ return this.$wrapLimit;
+ };
- this.$moveLines(function(firstRow, lastRow) {
- return this.session.moveLinesUp(firstRow, lastRow);
- });
+ /**
+ * EditSession.getWrapLimitRange() -> Object
+ *
+ * Returns an object that defines the minimum and maximum of the wrap limit; it looks something like this:
+ *
+ * { min: wrapLimitRange_min, max: wrapLimitRange_max }
+ *
+ **/
+ this.getWrapLimitRange = function() {
+ // Avoid unexpected mutation by returning a copy
+ return {
+ min : this.$wrapLimitRange.min,
+ max : this.$wrapLimitRange.max
+ };
};
- this.moveText = function(range, toPosition) {
- if (this.$readOnly)
- return null;
+ /** internal, hide
+ * EditSession.$updateInternalDataOnChange()
+ *
+ *
+ **/
+ 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;
- return this.session.moveText(range, toPosition);
- };
+ 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;
+ }
- this.copyLinesUp = function() {
- if (this.$readOnly)
- return;
+ if (len != 0) {
+ if (action.indexOf("remove") != -1) {
+ useWrapMode && this.$wrapData.splice(firstRow, len);
- this.$moveLines(function(firstRow, lastRow) {
- this.session.duplicateLines(firstRow, lastRow);
- return 0;
- });
- };
+ var foldLines = this.$foldData;
+ removedFolds = this.getFoldsInRange(e.data.range);
+ this.removeFolds(removedFolds);
- this.copyLinesDown = function() {
- if (this.$readOnly)
- return;
+ var foldLine = this.getFoldLine(end.row);
+ var idx = 0;
+ if (foldLine) {
+ foldLine.addRemoveChars(end.row, end.column, start.column - end.column);
+ foldLine.shiftRow(-len);
- this.$moveLines(function(firstRow, lastRow) {
- return this.session.duplicateLines(firstRow, lastRow);
- });
- };
+ 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);
+ }
+ }
- this.$moveLines = function(mover) {
- var rows = this.$getSelectedRows();
+ 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);
+ }
- var linesMoved = mover.call(this, rows.first, rows.last);
+ // 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;
+ }
- var selection = this.selection;
- selection.setSelectionAnchor(rows.last+linesMoved+1, 0);
- selection.$moveSelection(function() {
- selection.moveCursorTo(rows.first+linesMoved, 0);
- });
- };
+ 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);
- this.$getSelectedRows = function() {
- var range = this.getSelectionRange().collapseRows();
+ len = -len;
+ }
+ var foldLine = this.getFoldLine(firstRow);
+ if (foldLine) {
+ foldLine.addRemoveChars(firstRow, start.column, len);
+ }
+ }
- return {
- first: range.start.row,
- last: range.end.row
- };
- };
+ if (useWrapMode && this.$wrapData.length != this.doc.getLength()) {
+ console.error("doc.getLength() and $wrapData.length have to be the same!");
+ }
- this.onCompositionStart = function(text) {
- this.renderer.showComposition(this.getCursorPosition());
- };
+ useWrapMode && this.$updateWrapData(firstRow, lastRow);
- this.onCompositionUpdate = function(text) {
- this.renderer.setCompositionText(text);
+ return removedFolds;
};
- this.onCompositionEnd = function() {
- this.renderer.hideComposition();
- };
+ /** internal, hide
+ * EditSession.$updateWrapData(firstRow, lastRow)
+ *
+ *
+ **/
+ 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();
- this.getFirstVisibleRow = function() {
- return this.renderer.getFirstVisibleRow();
+ wrapData[foldLine.start.row]
+ = this.$computeWrapSplits(tokens, wrapLimit, tabSize);
+ row = foldLine.end.row + 1;
+ }
+ }
};
- this.getLastVisibleRow = function() {
- return this.renderer.getLastVisibleRow();
- };
+ // "Tokens"
+ var CHAR = 1,
+ CHAR_EXT = 2,
+ PLACEHOLDER_START = 3,
+ PLACEHOLDER_BODY = 4,
+ PUNCTUATION = 9,
+ SPACE = 10,
+ TAB = 11,
+ TAB_SPACE = 12;
- this.isRowVisible = function(row) {
- return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow());
- };
+ /** internal, hide
+ * EditSession.$computeWrapSplits(tokens, wrapLimit) -> Array
+ *
+ *
+ **/
+ this.$computeWrapSplits = function(tokens, wrapLimit) {
+ if (tokens.length == 0) {
+ return [];
+ }
- this.$getVisibleRowCount = function() {
- return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1;
- };
+ var splits = [];
+ var displayLength = tokens.length;
+ var lastSplit = 0, lastDocSplit = 0;
- this.$getPageDownRow = function() {
- return this.renderer.getScrollBottomRow();
- };
+ function addSplit(screenPos) {
+ var displayed = tokens.slice(lastSplit, screenPos);
- this.$getPageUpRow = function() {
- var firstRow = this.renderer.getScrollTopRow();
- var lastRow = this.renderer.getScrollBottomRow();
+ // 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;
+ });
- return firstRow - (lastRow - firstRow);
- };
+ lastDocSplit += len;
+ splits.push(lastDocSplit);
+ lastSplit = screenPos;
+ }
- this.selectPageDown = function() {
- var row = this.$getPageDownRow() + Math.floor(this.$getVisibleRowCount() / 2);
+ while (displayLength - lastSplit > wrapLimit) {
+ // This is, where the split should be.
+ var split = lastSplit + wrapLimit;
- this.scrollPageDown();
+ // 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;
+ }
- var selection = this.getSelection();
- var leadScreenPos = this.session.documentToScreenPosition(selection.getSelectionLead());
- var dest = this.session.screenToDocumentPosition(row, leadScreenPos.column);
- selection.selectTo(dest.row, dest.column);
- };
+ // === 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;
+ }
+ }
- this.selectPageUp = function() {
- var visibleRows = this.renderer.getScrollTopRow() - this.renderer.getScrollBottomRow();
- var row = this.$getPageUpRow() + Math.round(visibleRows / 2);
+ // If the PLACEHOLDER_START is not the index of the
+ // last split, then we can do the split
+ if (split > lastSplit) {
+ addSplit(split);
+ continue;
+ }
- this.scrollPageUp();
+ // 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;
+ }
+ }
- var selection = this.getSelection();
- var leadScreenPos = this.session.documentToScreenPosition(selection.getSelectionLead());
- var dest = this.session.screenToDocumentPosition(row, leadScreenPos.column);
- selection.selectTo(dest.row, dest.column);
- };
+ // 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.
+ }
- this.gotoPageDown = function() {
- var row = this.$getPageDownRow();
- var column = this.getCursorPositionScreen().column;
+ // Finally, add the split...
+ addSplit(split);
+ continue;
+ }
- this.scrollToRow(row);
- this.getSelection().moveCursorToScreen(row, column);
- };
+ // === 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;
+ }
- this.gotoPageUp = function() {
- var row = this.$getPageUpRow();
- var column = this.getCursorPositionScreen().column;
+ // === 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.scrollToRow(row);
- this.getSelection().moveCursorToScreen(row, column);
- };
+ /** internal, hide
+ * EditSession.$getDisplayTokens(str, offset) -> Array
+ * - str (String): The string to check
+ * - offset (Number): The value to start at
+ *
+ * Given a string, returns an array of the display characters, including tabs and spaces.
+ **/
+ this.$getDisplayTokens = function(str, offset) {
+ var arr = [];
+ var tabSize;
+ offset = offset || 0;
- this.scrollPageDown = function() {
- this.scrollToRow(this.$getPageDownRow());
- };
+ 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.scrollPageUp = function() {
- this.renderer.scrollToRow(this.$getPageUpRow());
- };
+ /** internal, hide
+ * EditSession.$getStringScreenWidth(str, maxScreenColumn, screenColumn) -> [Number]
+ * - str (String): The string to calculate the screen width of
+ * - maxScreenColumn (Number):
+ * - screenColumn (Number):
+ * + ([Number]): Returns an `int[]` array with two elements:
+ * The first position indicates the number of columns for `str` on screen.
+ * The second value contains the position of the document column that this function read until.
+ *
+ * Calculates the width of the string `str` on the screen while assuming that the string starts at the first column on the screen.
+ *
+ *
+ **/
+ this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {
+ if (maxScreenColumn == 0) {
+ return [0, 0];
+ }
+ if (maxScreenColumn == null) {
+ maxScreenColumn = screenColumn +
+ str.length * Math.max(this.getTabSize(), 2);
+ }
+ screenColumn = screenColumn || 0;
- this.scrollToRow = function(row) {
- this.renderer.scrollToRow(row);
- };
+ 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
+ }
+ }
- this.scrollToLine = function(line, center) {
- this.renderer.scrollToLine(line, center);
- };
+ return [screenColumn, column];
+ }
- this.centerSelection = function() {
- var range = this.getSelectionRange();
- var line = Math.floor(range.start.row + (range.end.row - range.start.row) / 2);
- this.renderer.scrollToLine(line, true);
- };
+ /**
+ * EditSession.getRowLength(row) -> Number
+ * - row (Number): The row number to check
+ *
+ *
+ * Returns the length of the indicated row.
+ **/
+ this.getRowLength = function(row) {
+ if (!this.$useWrapMode || !this.$wrapData[row]) {
+ return 1;
+ } else {
+ return this.$wrapData[row].length + 1;
+ }
+ }
- this.getCursorPosition = function() {
- return this.selection.getCursor();
- };
+ /**
+ * EditSession.getRowHeight(config, row) -> Number
+ * - config (Object): An object containing a parameter indicating the `lineHeight`.
+ * - row (Number): The row number to check
+ *
+ * Returns the height of the indicated row. This is mostly relevant for situations where wrapping occurs, and a single line spans across multiple rows.
+ *
+ **/
+ this.getRowHeight = function(config, row) {
+ return this.getRowLength(row) * config.lineHeight;
+ }
- this.getCursorPositionScreen = function() {
- return this.session.documentToScreenPosition(this.getCursorPosition());
+ /** internal, hide, related to: EditSession.documentToScreenColumn
+ * EditSession.getScreenLastRowColumn(screenRow) -> Number
+ * - screenRow (Number): The screen row to check
+ *
+ * Returns the column position (on screen) for the last character in the provided row.
+ **/
+ this.getScreenLastRowColumn = function(screenRow) {
+ var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE)
+ return this.documentToScreenColumn(pos.row, pos.column);
};
- this.getSelectionRange = function() {
- return this.selection.getRange();
+ /** internal, hide
+ * EditSession.getDocumentLastRowColumn(docRow, docColumn) -> Number
+ * - docRow (Number):
+ * - docColumn (Number):
+ *
+ **/
+ this.getDocumentLastRowColumn = function(docRow, docColumn) {
+ var screenRow = this.documentToScreenRow(docRow, docColumn);
+ return this.getScreenLastRowColumn(screenRow);
};
-
- this.selectAll = function() {
- this.$blockScrolling += 1;
- this.selection.selectAll();
- this.$blockScrolling -= 1;
+ /** internal, hide
+ * EditSession.getDocumentLastRowColumnPosition(docRow, docColumn) -> Number
+ *
+ **/
+ this.getDocumentLastRowColumnPosition = function(docRow, docColumn) {
+ var screenRow = this.documentToScreenRow(docRow, docColumn);
+ return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10);
};
- this.clearSelection = function() {
- this.selection.clearSelection();
+ /** internal, hide
+ * EditSession.getRowSplitData(row) -> undefined | String
+ *
+ **/
+ this.getRowSplitData = function(row) {
+ if (!this.$useWrapMode) {
+ return undefined;
+ } else {
+ return this.$wrapData[row];
+ }
};
- this.moveCursorTo = function(row, column) {
- this.selection.moveCursorTo(row, column);
+ /**
+ * EditSession.getScreenTabSize(screenColumn) -> Number
+ * - screenColumn (Number): The screen column to check
+ *
+ * The distance to the next tab stop at the specified screen column.
+ **/
+ this.getScreenTabSize = function(screenColumn) {
+ return this.$tabSize - screenColumn % this.$tabSize;
};
- this.moveCursorToPosition = function(pos) {
- this.selection.moveCursorToPosition(pos);
+ /** internal, hide
+ * EditSession.screenToDocumentRow(screenRow, screenColumn) -> Number
+ *
+ *
+ **/
+ this.screenToDocumentRow = function(screenRow, screenColumn) {
+ return this.screenToDocumentPosition(screenRow, screenColumn).row;
};
+ /** internal, hide
+ * EditSession.screenToDocumentColumn(screenRow, screenColumn) -> Number
+ *
+ *
+ **/
+ this.screenToDocumentColumn = function(screenRow, screenColumn) {
+ return this.screenToDocumentPosition(screenRow, screenColumn).column;
+ };
- this.gotoLine = function(lineNumber, column) {
- this.selection.clearSelection();
-
- this.$blockScrolling += 1;
- this.moveCursorTo(lineNumber-1, column || 0);
- this.$blockScrolling -= 1;
-
- if (!this.isRowVisible(this.getCursorPosition().row)) {
- this.scrollToLine(lineNumber, true);
+ /** related to: EditSession.documentToScreenPosition
+ * EditSession.screenToDocumentPosition(screenRow, screenColumn) -> Object
+ * - screenRow (Number): The screen row to check
+ * - screenColumn (Number): The screen column to check
+ * + (Object): The object returned has two properties: `row` and `column`.
+ *
+ * Converts characters coordinates on the screen to characters coordinates within the document. [This takes into account code folding, word wrap, tab size, and any other visual modifications.]{: #conversionConsiderations}
+ *
+ *
+ **/
+ this.screenToDocumentPosition = function(screenRow, screenColumn) {
+ if (screenRow < 0) {
+ return {
+ row: 0,
+ column: 0
+ }
}
- },
- this.navigateTo = function(row, column) {
- this.clearSelection();
- this.moveCursorTo(row, column);
- };
+ var line;
+ var docRow = 0;
+ var docColumn = 0;
+ var column;
+ var row = 0;
+ var rowLength = 0;
- this.navigateUp = function(times) {
- this.selection.clearSelection();
- times = times || 1;
- this.selection.moveCursorBy(-times, 0);
- };
+ var rowCache = this.$rowCache;
+ for (var i = 0; i < rowCache.length; i++) {
+ if (rowCache[i].screenRow < screenRow) {
+ row = rowCache[i].screenRow;
+ docRow = rowCache[i].docRow;
+ }
+ else {
+ break;
+ }
+ }
+ var doCache = !rowCache.length || i == rowCache.length;
- this.navigateDown = function(times) {
- this.selection.clearSelection();
- times = times || 1;
- this.selection.moveCursorBy(times, 0);
- };
+ var maxRow = this.getLength() - 1;
+ var foldLine = this.getNextFoldLine(docRow);
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
- 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();
+ 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) {
+ rowCache.push({
+ docRow: docRow,
+ screenRow: row
+ });
}
}
- this.clearSelection();
- };
- this.navigateRight = function(times) {
- if (!this.selection.isEmpty()) {
- var selectionEnd = this.getSelectionRange().end;
- this.moveCursorToPosition(selectionEnd);
+ 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;
}
- else {
- times = times || 1;
- while (times--) {
- this.selection.moveCursorRight();
+
+ 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);
+ }
}
}
- this.clearSelection();
- };
- this.navigateLineStart = function() {
- this.selection.moveCursorLineStart();
- this.clearSelection();
- };
+ docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
- this.navigateLineEnd = function() {
- this.selection.moveCursorLineEnd();
- this.clearSelection();
- };
+ // 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;
+ }
- this.navigateFileEnd = function() {
- this.selection.moveCursorFileEnd();
- this.clearSelection();
- };
+ if (foldLine) {
+ return foldLine.idxToPosition(docColumn);
+ }
- this.navigateFileStart = function() {
- this.selection.moveCursorFileStart();
- this.clearSelection();
+ return {
+ row: docRow,
+ column: docColumn
+ }
};
- this.navigateWordRight = function() {
- this.selection.moveCursorWordRight();
- this.clearSelection();
- };
+ /** related to: EditSession.screenToDocumentPosition
+ * EditSession.documentToScreenPosition(docRow, docColumn) -> Object
+ * - docRow (Number): The document row to check
+ * - docColumn (Number): The document column to check
+ * + (Object): The object returned by this method has two properties: `row` and `column`.
+ *
+ * Converts document coordinates to screen coordinates. {:conversionConsiderations}
+ *
+ *
+ *
+ **/
+ 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);
- this.navigateWordLeft = function() {
- this.selection.moveCursorWordLeft();
- this.clearSelection();
- };
+ docRow = pos.row;
+ docColumn = pos.column;
- this.replace = function(replacement, options) {
- if (options)
- this.$search.set(options);
+ var wrapData;
+ // Special case in wrapMode if the doc is at the end of the document.
+ if (this.$useWrapMode) {
+ wrapData = this.$wrapData;
+ if (docRow > wrapData.length - 1) {
+ return {
+ row: this.getScreenLength(),
+ column: wrapData.length == 0
+ ? 0
+ : (wrapData[wrapData.length - 1].length - 1)
+ };
+ }
+ }
- var range = this.$search.find(this.session);
- if (!range)
- return;
+ var screenRow = 0;
+ var foldStartRow = null;
+ var fold = null;
- this.$tryReplace(range, replacement);
- if (range !== null)
- this.selection.setSelectionRange(range);
- },
+ // 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;
+ }
- this.replaceAll = function(replacement, options) {
- if (options) {
- this.$search.set(options);
+ var rowEnd, row = 0;
+ var rowCache = this.$rowCache;
+
+ for (var i = 0; i < rowCache.length; i++) {
+ if (rowCache[i].docRow < docRow) {
+ screenRow = rowCache[i].screenRow;
+ row = rowCache[i].docRow;
+ } else {
+ break;
+ }
}
+ var doCache = !rowCache.length || i == rowCache.length;
- var ranges = this.$search.findAll(this.session);
- if (!ranges.length)
- return;
+ var foldLine = this.getNextFoldLine(row);
+ var foldStart = foldLine ?foldLine.start.row :Infinity;
- var selection = this.getSelectionRange();
- this.clearSelection();
- this.selection.moveCursorTo(0, 0);
+ 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;
+ }
- this.$blockScrolling += 1;
- for (var i = ranges.length - 1; i >= 0; --i)
- this.$tryReplace(ranges[i], replacement);
+ screenRow += this.getRowLength(row);
+ row = rowEnd;
- this.selection.setSelectionRange(selection);
- this.$blockScrolling -= 1;
- },
+ if (doCache) {
+ rowCache.push({
+ docRow: row,
+ screenRow: screenRow
+ });
+ }
+ }
- this.$tryReplace = function(range, replacement) {
- var input = this.session.getTextRange(range);
- var replacement = this.$search.replace(input, replacement);
- if (replacement !== null) {
- range.end = this.session.replace(range, replacement);
- return range;
+ // 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 {
- return null;
+ textLine = this.getLine(docRow).substring(0, docColumn);
+ foldStartRow = docRow;
+ }
+ // Clamp textLine if in wrapMode.
+ if (this.$useWrapMode) {
+ var wrapRow = wrapData[foldStartRow];
+ var screenRowOffset = 0;
+ while (textLine.length >= wrapRow[screenRowOffset]) {
+ screenRow ++;
+ screenRowOffset++;
+ }
+ textLine = textLine.substring(
+ wrapRow[screenRowOffset - 1] || 0, textLine.length
+ );
}
- };
- this.getLastSearchOptions = function() {
- return this.$search.getOptions();
+ return {
+ row: screenRow,
+ column: this.$getStringScreenWidth(textLine)[0]
+ };
};
- this.find = function(needle, options) {
- this.clearSelection();
- options = options || {};
- options.needle = needle;
- this.$search.set(options);
- this.$find();
- },
-
- this.findNext = function(options) {
- options = options || {};
- if (typeof options.backwards == "undefined")
- options.backwards = false;
- this.$search.set(options);
- this.$find();
+ /** internal, hide
+ * EditSession.documentToScreenColumn(row, docColumn) -> Number
+ *
+ *
+ **/
+ this.documentToScreenColumn = function(row, docColumn) {
+ return this.documentToScreenPosition(row, docColumn).column;
};
- this.findPrevious = function(options) {
- options = options || {};
- if (typeof options.backwards == "undefined")
- options.backwards = true;
- this.$search.set(options);
- this.$find();
+ /** internal, hide
+ * EditSession.documentToScreenRow(docRow, docColumn) -> Number
+ *
+ *
+ **/
+ this.documentToScreenRow = function(docRow, docColumn) {
+ return this.documentToScreenPosition(docRow, docColumn).row;
};
- this.$find = function(backwards) {
- if (!this.selection.isEmpty()) {
- this.$search.set({needle: this.session.getTextRange(this.getSelectionRange())});
- }
-
- if (typeof backwards != "undefined")
- this.$search.set({backwards: backwards});
+ /**
+ * EditSession.getScreenLength() -> Number
+ *
+ * Returns the length of the screen.
+ **/
+ this.getScreenLength = function() {
+ var screenRows = 0;
+ var fold = null;
+ if (!this.$useWrapMode) {
+ screenRows = this.getLength();
- var range = this.$search.find(this.session);
- if (range) {
- this.gotoLine(range.end.row+1, range.end.column);
- this.selection.setSelectionRange(range);
+ // 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;
+ }
+ }
}
- };
- this.undo = function() {
- this.session.getUndoManager().undo();
- };
+ return screenRows;
+ }
- this.redo = function() {
- this.session.getUndoManager().redo();
+ // 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;
};
- this.destroy = function() {
- this.renderer.destroy();
- }
-
-}).call(Editor.prototype);
+}).call(EditSession.prototype);
+require("./edit_session/folding").Folding.call(EditSession.prototype);
+require("./edit_session/bracket_match").BracketMatch.call(EditSession.prototype);
-exports.Editor = Editor;
+exports.EditSession = EditSession;
});
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
@@ -6691,7 +8835,6 @@ exports.Editor = Editor;
*
* Contributor(s):
* Fabian Jakobs
- * Mihai Sucan
*
* 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
@@ -6707,245 +8850,159 @@ exports.Editor = Editor;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/keyboard/textinput', ['require', 'exports', 'module' , 'pilot/event', 'pilot/useragent', 'pilot/dom'], function(require, exports, module) {
-
-var event = require("pilot/event");
-var useragent = require("pilot/useragent");
-var dom = require("pilot/dom");
-
-var TextInput = function(parentNode, host) {
-
- var text = dom.createElement("textarea");
- text.style.left = "-10000px";
- parentNode.appendChild(text);
-
- var PLACEHOLDER = String.fromCharCode(0);
- sendText();
-
- var inCompostion = false;
- var copied = false;
- var pasted = false;
- var tempStyle = '';
-
- function sendText(valueToSend) {
- if (!copied) {
- var value = valueToSend || text.value;
- if (value) {
- if (value.charCodeAt(value.length-1) == PLACEHOLDER.charCodeAt(0)) {
- value = value.slice(0, -1);
- if (value)
- host.onTextInput(value, !pasted);
- }
- else {
- host.onTextInput(value, !pasted);
- }
-
- // If editor is no longer focused we quit immediately, since
- // it means that something else is in charge now.
- if (!isFocused())
- return false;
- }
- }
-
- copied = false;
- pasted = false;
-
- // Safari doesn't fire copy events if no text is selected
- text.value = PLACEHOLDER;
- text.select();
- }
-
- var onTextInput = function(e) {
- setTimeout(function () {
- if (!inCompostion)
- sendText(e.data);
- }, 0);
- };
-
- var onKeyPress = function(e) {
- if (useragent.isIE && text.value.charCodeAt(0) > 128) return;
- setTimeout(function() {
- if (!inCompostion)
- sendText();
- }, 0);
- };
-
- var onCompositionStart = function(e) {
- inCompostion = true;
- host.onCompositionStart();
- if (!useragent.isGecko) setTimeout(onCompositionUpdate, 0);
- };
-
- var onCompositionUpdate = function() {
- if (!inCompostion) return;
- host.onCompositionUpdate(text.value);
- };
+define('ace/config', ['require', 'exports', 'module' , 'ace/lib/lang'], function(require, exports, module) {
+"no use strict";
- var onCompositionEnd = function(e) {
- inCompostion = false;
- host.onCompositionEnd();
- };
+var lang = require("./lib/lang");
- var onCopy = function(e) {
- copied = true;
- var copyText = host.getCopyText();
- if(copyText)
- text.value = copyText;
- else
- e.preventDefault();
- text.select();
- setTimeout(function () {
- sendText();
- }, 0);
- };
+var global = (function() {
+ return this;
+})();
- var onCut = function(e) {
- copied = true;
- var copyText = host.getCopyText();
- if(copyText) {
- text.value = copyText;
- host.onCut();
- } else
- e.preventDefault();
- text.select();
- setTimeout(function () {
- sendText();
- }, 0);
- };
+var options = {
+ packaged: false,
+ workerPath: "",
+ modePath: "",
+ themePath: "",
+ suffix: ".js"
+};
- event.addCommandKeyListener(text, host.onCommandKey.bind(host));
- if (useragent.isIE) {
- 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();
- });
- };
+exports.get = function(key) {
+ if (!options.hasOwnProperty(key))
+ throw new Error("Unknown confik key: " + key);
+
+ return options[key];
+};
- if (text.attachEvent) {
- // Old IE + Opera
- event.addListener(text, "propertychange", onKeyPress);
- }
- else {
- if (useragent.isChrome || useragent.isSafari)
- event.addListener(text, "textInput", onTextInput);
- else if (useragent.isIE)
- // IE9
- event.addListener(text, "textinput", onTextInput);
- else
- // All browsers except old IE
- event.addListener(text, "input", onTextInput);
- }
-
+exports.set = function(key, value) {
+ if (!options.hasOwnProperty(key))
+ throw new Error("Unknown confik key: " + key);
+
+ options[key] = value;
+};
+
+exports.all = function() {
+ return lang.copyObject(options);
+};
+
+exports.init = function() {
+ options.packaged = require.packaged || module.packaged || (global.define && define.packaged);
+
+ if (!global.document)
+ return "";
+
+ var scriptOptions = {};
+ var scriptUrl = "";
+ var suffix;
- 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.
- onKeyPress();
- }
- });
+ var scripts = document.getElementsByTagName("script");
+ for (var i=0; i
- * Mihai Sucan
+ * Julian Viereck
*
* 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
@@ -6983,858 +9040,842 @@ exports.TextInput = TextInput;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/mouse_handler', ['require', 'exports', 'module' , 'pilot/event', 'pilot/dom', 'pilot/browser_focus'], function(require, exports, module) {
+define('ace/selection', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/lib/event_emitter', 'ace/range'], function(require, exports, module) {
+"use strict";
+
+var oop = require("./lib/oop");
+var lang = require("./lib/lang");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+var Range = require("./range").Range;
+
+/**
+ * class Selection
+ *
+ * Contains the cursor position and the text selection of an edit session.
+ *
+ * The row/columns used in the selection are in document coordinates representing ths coordinates as thez appear in the document before applying soft wrap and folding.
+ **/
+
+/**
+ * new Selection(session)
+ * - session (EditSession): The session to use
+ *
+ * Creates a new `Selection` object.
+ *
+**/
+var Selection = function(session) {
+ this.session = session;
+ this.doc = session.getDocument();
+
+ this.clearSelection();
+ this.lead = this.selectionLead = this.doc.createAnchor(0, 0);
+ this.anchor = this.selectionAnchor = this.doc.createAnchor(0, 0);
+
+ var self = this;
+ this.lead.on("change", function(e) {
+ self._emit("changeCursor");
+ if (!self.$isEmpty)
+ self._emit("changeSelection");
+ if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column)
+ self.$desiredColumn = null;
+ });
+
+ this.selectionAnchor.on("change", function() {
+ if (!self.$isEmpty)
+ self._emit("changeSelection");
+ });
+};
+
+(function() {
+
+ oop.implement(this, EventEmitter);
+
+ /**
+ * Selection.isEmpty() -> Boolean
+ *
+ * Returns `true` if the selection is empty.
+ **/
+ this.isEmpty = function() {
+ return (this.$isEmpty || (
+ this.anchor.row == this.lead.row &&
+ this.anchor.column == this.lead.column
+ ));
+ };
+
+ /**
+ * Selection.isMultiLine() -> Boolean
+ *
+ * Returns `true` if the selection is a multi-line.
+ **/
+ this.isMultiLine = function() {
+ if (this.isEmpty()) {
+ return false;
+ }
+
+ return this.getRange().isMultiLine();
+ };
+
+ /**
+ * Selection.getCursor() -> Number
+ *
+ * Gets the current position of the cursor.
+ **/
+ this.getCursor = function() {
+ return this.lead.getPosition();
+ };
+
+ /**
+ * Selection.setSelectionAnchor(row, column)
+ * - row (Number): The new row
+ * - column (Number): The new column
+ *
+ * Sets the row and column position of the anchor. This function also emits the `'changeSelection'` event.
+ **/
+ this.setSelectionAnchor = function(row, column) {
+ this.anchor.setPosition(row, column);
+
+ if (this.$isEmpty) {
+ this.$isEmpty = false;
+ this._emit("changeSelection");
+ }
+ };
+
+ /** related to: Anchor.getPosition
+ * Selection.getSelectionAnchor() -> Object
+ *
+ * Returns an object containing the `row` and `column` of the calling selection anchor.
+ *
+ **/
+ this.getSelectionAnchor = function() {
+ if (this.$isEmpty)
+ return this.getSelectionLead()
+ else
+ return this.anchor.getPosition();
+ };
+
+ /**
+ * Selection.getSelectionLead() -> Object
+ *
+ * Returns an object containing the `row` and `column` of the calling selection lead.
+ **/
+ this.getSelectionLead = function() {
+ return this.lead.getPosition();
+ };
+
+ /**
+ * Selection.shiftSelection(columns)
+ * - columns (Number): The number of columns to shift by
+ *
+ * Shifts the selection up (or down, if [[Selection.isBackwards `isBackwards()`]] is true) the given number of columns.
+ *
+ **/
+ this.shiftSelection = function(columns) {
+ if (this.$isEmpty) {
+ this.moveCursorTo(this.lead.row, this.lead.column + columns);
+ return;
+ };
+
+ var anchor = this.getSelectionAnchor();
+ var lead = this.getSelectionLead();
+
+ var isBackwards = this.isBackwards();
+
+ if (!isBackwards || anchor.column !== 0)
+ this.setSelectionAnchor(anchor.row, anchor.column + columns);
+
+ if (isBackwards || lead.column !== 0) {
+ this.$moveSelection(function() {
+ this.moveCursorTo(lead.row, lead.column + columns);
+ });
+ }
+ };
+
+ /**
+ * Selection.isBackwards() -> Boolean
+ *
+ * Returns `true` if the selection is going backwards in the document.
+ **/
+ this.isBackwards = function() {
+ var anchor = this.anchor;
+ var lead = this.lead;
+ return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));
+ };
+
+ /**
+ * Selection.getRange() -> Range
+ *
+ * [Returns the [[Range `Range`]] for the selected text.]{: #Selection.getRange}
+ **/
+ 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);
+ }
+ };
+
+ /**
+ * Selection.clearSelection()
+ *
+ * [Empties the selection (by de-selecting it). This function also emits the `'changeSelection'` event.]{: #Selection.clearSelection}
+ **/
+ this.clearSelection = function() {
+ if (!this.$isEmpty) {
+ this.$isEmpty = true;
+ this._emit("changeSelection");
+ }
+ };
+
+ /**
+ * Selection.selectAll()
+ *
+ * Selects all the text in the document.
+ **/
+ this.selectAll = function() {
+ var lastRow = this.doc.getLength() - 1;
+ this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length);
+ this.moveCursorTo(0, 0);
+ };
+
+ /**
+ * Selection.setSelectionRange(range, reverse)
+ * - range (Range): The range of text to select
+ * - reverse (Boolean): Indicates if the range should go backwards (`true`) or not
+ *
+ * Sets the selection to the provided range.
+ *
+ **/
+ this.setSelectionRange = function(range, reverse) {
+ if (range.isEmpty()) {
+ this.lead.setPosition(range.start.row, range.start.column);
+ this.clearSelection();
+ } else if (reverse) {
+ this.$isEmpty = false;
+ this.anchor.setPosition(range.end.row, range.end.column);
+ this.lead.setPosition(range.start.row, range.start.column);
+ } else {
+ this.$isEmpty = false;
+ this.anchor.setPosition(range.start.row, range.start.column);
+ this.lead.setPosition(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);
-var event = require("pilot/event");
-var dom = require("pilot/dom");
-var BrowserFocus = require("pilot/browser_focus").BrowserFocus;
+ mover.call(this);
+ };
-var STATE_UNKNOWN = 0;
-var STATE_SELECT = 1;
-var STATE_DRAG = 2;
+ /**
+ * Selection.selectTo(row, column)
+ * - row (Number): The row to select to
+ * - column (Number): The column to select to
+ *
+ * Moves the selection cursor to the indicated row and column.
+ *
+ **/
+ this.selectTo = function(row, column) {
+ this.$moveSelection(function() {
+ this.moveCursorTo(row, column);
+ });
+ };
-var DRAG_TIMER = 250; // milliseconds
-var DRAG_OFFSET = 5; // pixels
+ /**
+ * Selection.selectToPosition(pos)
+ * - pos (Object): An object containing the row and column
+ *
+ * Moves the selection cursor to the row and column indicated by `pos`.
+ *
+ **/
+ this.selectToPosition = function(pos) {
+ this.$moveSelection(function() {
+ this.moveCursorToPosition(pos);
+ });
+ };
-var MouseHandler = function(editor) {
- this.editor = editor;
-
- this.browserFocus = new BrowserFocus();
- event.addListener(editor.container, "mousedown", function(e) {
- editor.focus();
- return event.preventDefault(e);
- });
- event.addListener(editor.container, "selectstart", function(e) {
- return event.preventDefault(e);
- });
+ /**
+ * Selection.selectUp()
+ *
+ * Moves the selection up one row.
+ **/
+ this.selectUp = function() {
+ this.$moveSelection(this.moveCursorUp);
+ };
- var mouseTarget = editor.renderer.getMouseEventTarget();
- event.addListener(mouseTarget, "mousedown", this.onMouseDown.bind(this));
- event.addMultiMouseDownListener(mouseTarget, 0, 2, 500, this.onMouseDoubleClick.bind(this));
- event.addMultiMouseDownListener(mouseTarget, 0, 3, 600, this.onMouseTripleClick.bind(this));
- event.addMultiMouseDownListener(mouseTarget, 0, 4, 600, this.onMouseQuadClick.bind(this));
- event.addMouseWheelListener(mouseTarget, this.onMouseWheel.bind(this));
-};
+ /**
+ * Selection.selectDown()
+ *
+ * Moves the selection down one row.
+ **/
+ this.selectDown = function() {
+ this.$moveSelection(this.moveCursorDown);
+ };
-(function() {
+ /**
+ * Selection.selectRight()
+ *
+ * Moves the selection right one column.
+ **/
+ this.selectRight = function() {
+ this.$moveSelection(this.moveCursorRight);
+ };
- this.$scrollSpeed = 1;
- this.setScrollSpeed = function(speed) {
- this.$scrollSpeed = speed;
+ /**
+ * Selection.selectLeft()
+ *
+ * Moves the selection left one column.
+ **/
+ this.selectLeft = function() {
+ this.$moveSelection(this.moveCursorLeft);
};
- this.getScrollSpeed = function() {
- return this.$scrollSpeed;
+ /**
+ * Selection.selectLineStart()
+ *
+ * Moves the selection to the beginning of the current line.
+ **/
+ this.selectLineStart = function() {
+ this.$moveSelection(this.moveCursorLineStart);
};
- this.$getEventPosition = function(e) {
- var pageX = event.getDocumentX(e);
- var pageY = event.getDocumentY(e);
- var pos = this.editor.renderer.screenToTextCoordinates(pageX, pageY);
- pos.row = Math.max(0, Math.min(pos.row, this.editor.session.getLength()-1));
- return pos;
+ /**
+ * Selection.selectLineEnd()
+ *
+ * Moves the selection to the end of the current line.
+ **/
+ this.selectLineEnd = function() {
+ this.$moveSelection(this.moveCursorLineEnd);
};
- this.$distance = function(ax, ay, bx, by) {
- return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));
+ /**
+ * Selection.selectFileEnd()
+ *
+ * Moves the selection to the end of the file.
+ **/
+ this.selectFileEnd = function() {
+ this.$moveSelection(this.moveCursorFileEnd);
};
- this.onMouseDown = function(e) {
- // if this click caused the editor to be focused ignore the click
- // for selection and cursor placement
- if (
- !this.browserFocus.isFocused()
- || new Date().getTime() - this.browserFocus.lastFocus < 20
- || !this.editor.isFocused()
- )
- return;
-
- var pageX = event.getDocumentX(e);
- var pageY = event.getDocumentY(e);
- var pos = this.$getEventPosition(e);
- var editor = this.editor;
- var self = this;
- var selectionRange = editor.getSelectionRange();
- var selectionEmpty = selectionRange.isEmpty();
- var state = STATE_UNKNOWN;
- var inSelection = false;
+ /**
+ * Selection.selectFileStart()
+ *
+ * Moves the selection to the start of the file.
+ **/
+ this.selectFileStart = function() {
+ this.$moveSelection(this.moveCursorFileStart);
+ };
- var button = event.getButton(e);
- if (button !== 0) {
- if (selectionEmpty) {
- editor.moveCursorToPosition(pos);
- }
- if(button == 2) {
- editor.textInput.onContextMenu({x: pageX, y: pageY}, selectionEmpty);
- event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose);
- }
- return;
- } else {
- // Select the fold as the user clicks it.
- var fold = editor.session.getFoldAt(pos.row, pos.column, 1);
- if (fold) {
- editor.selection.setSelectionRange(fold.range);
- return;
- }
+ /**
+ * Selection.selectWordRight()
+ *
+ * Moves the selection to the first word on the right.
+ **/
+ this.selectWordRight = function() {
+ this.$moveSelection(this.moveCursorWordRight);
+ };
- inSelection = !editor.getReadOnly()
- && !selectionEmpty
- && selectionRange.contains(pos.row, pos.column);
- }
+ /**
+ * Selection.selectWordLeft()
+ *
+ * Moves the selection to the first word on the left.
+ **/
+ this.selectWordLeft = function() {
+ this.$moveSelection(this.moveCursorWordLeft);
+ };
- if (!inSelection) {
- // Directly pick STATE_SELECT, since the user is not clicking inside
- // a selection.
- onStartSelect(pos);
+ /** related to: EditSession.getWordRange
+ * Selection.selectWord()
+ *
+ * Moves the selection to highlight the entire word.
+ **/
+ 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);
+ };
- var mousePageX, mousePageY;
- var overwrite = editor.getOverwrite();
- var mousedownTime = (new Date()).getTime();
- var dragCursor, dragRange;
+ this.selectWord = function() {
+ this.setSelectionRange(this.getWordRange());
+ };
- var onMouseSelection = function(e) {
- mousePageX = event.getDocumentX(e);
- mousePageY = event.getDocumentY(e);
- };
+ /** related to: EditSession.getAWordRange
+ * Selection.selectAWord()
+ *
+ * Selects a word, including its right whitespace.
+ **/
+ this.selectAWord = function() {
+ var cursor = this.getCursor();
+ var range = this.session.getAWordRange(cursor.row, cursor.column);
+ this.setSelectionRange(range);
+ };
- var onMouseSelectionEnd = function() {
- clearInterval(timerId);
- if (state == STATE_UNKNOWN)
- onStartSelect(pos);
- else if (state == STATE_DRAG)
- onMouseDragSelectionEnd();
+ this.getLineRange = function(row, excludeLastChar) {
+ var rowStart = typeof row == "number" ? row : this.lead.row;
+ var rowEnd;
- self.$clickSelection = null;
- state = STATE_UNKNOWN;
- };
+ 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);
+ };
- var onMouseDragSelectionEnd = function() {
- dom.removeCssClass(editor.container, "ace_dragging");
- editor.session.removeMarker(dragSelectionMarker);
+ /**
+ * Selection.selectLine()
+ *
+ * Selects the entire line.
+ **/
+ this.selectLine = function() {
+ this.setSelectionRange(this.getLineRange());
+ };
- if (!self.$clickSelection) {
- if (!dragCursor) {
- editor.moveCursorToPosition(pos);
- editor.selection.clearSelection(pos.row, pos.column);
- }
- }
+ /**
+ * Selection.moveCursorUp()
+ *
+ * Moves the cursor up one row.
+ **/
+ this.moveCursorUp = function() {
+ this.moveCursorBy(-1, 0);
+ };
- if (!dragCursor)
- return;
+ /**
+ * Selection.moveCursorDown()
+ *
+ * Moves the cursor down one row.
+ **/
+ this.moveCursorDown = function() {
+ this.moveCursorBy(1, 0);
+ };
- if (dragRange.contains(dragCursor.row, dragCursor.column)) {
- dragCursor = null;
- return;
- }
+ /**
+ * Selection.moveCursorLeft()
+ *
+ * Moves the cursor left one column.
+ **/
+ this.moveCursorLeft = function() {
+ var cursor = this.lead.getPosition(),
+ fold;
- editor.clearSelection();
- var newRange = editor.moveText(dragRange, dragCursor);
- if (!newRange) {
- dragCursor = null;
- return;
+ 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);
+ }
+ };
- editor.selection.setSelectionRange(newRange);
- };
-
- var onSelectionInterval = function() {
- if (mousePageX === undefined || mousePageY === undefined)
- return;
+ /**
+ * Selection.moveCursorRight()
+ *
+ * Moves the cursor right one column.
+ **/
+ 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);
+ }
+ };
- if (state == STATE_UNKNOWN) {
- var distance = self.$distance(pageX, pageY, mousePageX, mousePageY);
- var time = (new Date()).getTime();
-
-
- if (distance > DRAG_OFFSET) {
- state = STATE_SELECT;
- var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
- cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1));
- onStartSelect(cursor);
- } else if ((time - mousedownTime) > DRAG_TIMER) {
- state = STATE_DRAG;
- dragRange = editor.getSelectionRange();
- var style = editor.getSelectionStyle();
- dragSelectionMarker = editor.session.addMarker(dragRange, "ace_selection", style);
- editor.clearSelection();
- dom.addCssClass(editor.container, "ace_dragging");
- }
+ /**
+ * Selection.moveCursorLineStart()
+ *
+ * Moves the cursor to the start of the line.
+ **/
+ 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);
- if (state == STATE_DRAG)
- onDragSelectionInterval();
- else if (state == STATE_SELECT)
- onUpdateSelectionInterval();
- };
+ // Determ the line
+ var beforeCursor = this.session.getDisplayLine(
+ row, null,
+ firstColumnPosition.row, firstColumnPosition.column
+ );
- function onStartSelect(pos) {
- if (e.shiftKey)
- editor.selection.selectToPosition(pos)
- else {
- if (!self.$clickSelection) {
- editor.moveCursorToPosition(pos);
- editor.selection.clearSelection(pos.row, pos.column);
- }
- }
- state = STATE_SELECT;
+ 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
+ );
}
+ };
- var onUpdateSelectionInterval = function() {
- var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
- cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1));
+ /**
+ * Selection.moveCursorLineEnd()
+ *
+ * Moves the cursor to the end of the line.
+ **/
+ this.moveCursorLineEnd = function() {
+ var lead = this.lead;
+ var lastRowColumnPosition =
+ this.session.getDocumentLastRowColumnPosition(lead.row, lead.column);
+ this.moveCursorTo(
+ lastRowColumnPosition.row,
+ lastRowColumnPosition.column
+ );
+ };
- if (self.$clickSelection) {
- if (self.$clickSelection.contains(cursor.row, cursor.column)) {
- editor.selection.setSelectionRange(self.$clickSelection);
- } else {
- if (self.$clickSelection.compare(cursor.row, cursor.column) == -1) {
- var anchor = self.$clickSelection.end;
- } else {
- var anchor = self.$clickSelection.start;
- }
- editor.selection.setSelectionAnchor(anchor.row, anchor.column);
- editor.selection.selectToPosition(cursor);
- }
- }
- else {
- editor.selection.selectToPosition(cursor);
- }
+ /**
+ * Selection.moveCursorFileEnd()
+ *
+ * Moves the cursor to the end of the file.
+ **/
+ this.moveCursorFileEnd = function() {
+ var row = this.doc.getLength() - 1;
+ var column = this.doc.getLine(row).length;
+ this.moveCursorTo(row, column);
+ };
- editor.renderer.scrollCursorIntoView();
- };
+ /**
+ * Selection.moveCursorFileStart()
+ *
+ * Moves the cursor to the start of the file.
+ **/
+ this.moveCursorFileStart = function() {
+ this.moveCursorTo(0, 0);
+ };
- var onDragSelectionInterval = function() {
- dragCursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
- dragCursor.row = Math.max(0, Math.min(dragCursor.row,
- editor.session.getLength() - 1));
+ /**
+ * Selection.moveCursorLongWordRight()
+ *
+ * Moves the cursor to the word on the right.
+ **/
+ this.moveCursorLongWordRight = function() {
+ var row = this.lead.row;
+ var column = this.lead.column;
+ var line = this.doc.getLine(row);
+ var rightOfCursor = line.substring(column);
- editor.moveCursorToPosition(dragCursor);
- };
+ var match;
+ this.session.nonTokenRe.lastIndex = 0;
+ this.session.tokenRe.lastIndex = 0;
- event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
- var timerId = setInterval(onSelectionInterval, 20);
+ // 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;
+ }
- return event.preventDefault(e);
+ this.moveCursorTo(row, column);
};
- this.onMouseDoubleClick = function(e) {
- var editor = this.editor;
- var pos = this.$getEventPosition(e);
-
- // If the user dclicked on a fold, then expand it.
- var fold = editor.session.getFoldAt(pos.row, pos.column, 1);
- if (fold) {
- editor.session.expandFold(fold);
- } else {
- editor.moveCursorToPosition(pos);
- editor.selection.selectWord();
- this.$clickSelection = editor.getSelectionRange();
+ /**
+ * Selection.moveCursorLongWordLeft()
+ *
+ * Moves the cursor to the word on the left.
+ **/
+ 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;
}
- };
-
- this.onMouseTripleClick = function(e) {
- var pos = this.$getEventPosition(e);
- this.editor.moveCursorToPosition(pos);
- this.editor.selection.selectLine();
- this.$clickSelection = this.editor.getSelectionRange();
- };
- this.onMouseQuadClick = function(e) {
- this.editor.selectAll();
- this.$clickSelection = this.editor.getSelectionRange();
- };
+ 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;
+ }
- this.onMouseWheel = function(e) {
- var speed = this.$scrollSpeed * 2;
+ // 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.editor.renderer.scrollBy(e.wheelX * speed, e.wheelY * speed);
- return event.preventDefault(e);
+ this.moveCursorTo(row, column);
};
+ this.$shortWordEndIndex = function(rightOfCursor) {
+ var match, index = 0, ch;
+ var whitespaceRe = /\s/;
+ var tokenRe = this.session.tokenRe;
-}).call(MouseHandler.prototype);
-
-exports.MouseHandler = MouseHandler;
-});
-/* vim:ts=4:sts=4:sw=4:
- * ***** 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
- * Irakli Gozalishvili (http://jeditoolkit.com)
- * Julian Viereck
- *
- * 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 ***** */
+ 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;
-define('pilot/browser_focus', ['require', 'exports', 'module' , 'pilot/oop', 'pilot/event', 'pilot/event_emitter'], function(require, exports, module) {
+ return index;
+ };
-var oop = require("pilot/oop");
-var event = require("pilot/event");
-var EventEmitter = require("pilot/event_emitter").EventEmitter;
+ this.moveCursorShortWordRight = function() {
+ var row = this.lead.row;
+ var column = this.lead.column;
+ var line = this.doc.getLine(row);
+ var rightOfCursor = line.substring(column);
-/**
- * This class keeps track of the focus state of the given window.
- * Focus changes for example when the user switches a browser tab,
- * goes to the location bar or switches to another application.
- */
-var BrowserFocus = function(win) {
- win = win || window;
-
- this.lastFocus = new Date().getTime();
- this._isFocused = true;
-
- var _self = this;
- event.addListener(win, "blur", function(e) {
- _self._setFocused(false);
- });
+ var fold = this.session.getFoldAt(row, column, 1);
+ if (fold)
+ return this.moveCursorTo(fold.end.row, fold.end.column);
- event.addListener(win, "focus", function(e) {
- _self._setFocused(true);
- });
-};
+ if (column == line.length)
+ return this.moveCursorRight();
-(function(){
+ var index = this.$shortWordEndIndex(rightOfCursor);
- oop.implement(this, EventEmitter);
-
- this.isFocused = function() {
- return this._isFocused;
- };
-
- this._setFocused = function(isFocused) {
- if (this._isFocused == isFocused)
- return;
-
- if (isFocused)
- this.lastFocus = new Date().getTime();
-
- this._isFocused = isFocused;
- this._emit("changeFocus");
+ this.moveCursorTo(row, column + index);
};
-}).call(BrowserFocus.prototype);
-
+ this.moveCursorShortWordLeft = function() {
+ var row = this.lead.row;
+ var column = this.lead.column;
-exports.BrowserFocus = BrowserFocus;
-});
-/* ***** 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
- * Julian Viereck
- *
- * 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 ***** */
+ var fold;
+ if (fold = this.session.getFoldAt(row, column, -1))
+ return this.moveCursorTo(fold.start.row, fold.start.column);
-define('ace/keyboard/keybinding', ['require', 'exports', 'module' , 'pilot/useragent', 'pilot/keys', 'pilot/event', 'pilot/settings', 'pilot/canon', 'ace/commands/default_commands'], function(require, exports, module) {
+ if (column == 0)
+ return this.moveCursorLeft();
-var useragent = require("pilot/useragent");
-var keyUtil = require("pilot/keys");
-var event = require("pilot/event");
-var settings = require("pilot/settings").settings;
-var canon = require("pilot/canon");
-require("ace/commands/default_commands");
+ var str = this.session.getLine(row).substring(0, column);
+ var leftOfCursor = lang.stringReverse(str);
+ var index = this.$shortWordEndIndex(leftOfCursor);
-var KeyBinding = function(editor) {
- this.$editor = editor;
- this.$data = { };
- this.$keyboardHandler = null;
-};
+ return this.moveCursorTo(row, column - index);
+ };
-(function() {
- this.setKeyboardHandler = function(keyboardHandler) {
- if (this.$keyboardHandler != keyboardHandler) {
- this.$data = { };
- this.$keyboardHandler = keyboardHandler;
- }
+ this.moveCursorWordRight = function() {
+ if (this.session.$selectLongWords)
+ this.moveCursorLongWordRight();
+ else
+ this.moveCursorShortWordRight();
};
- this.getKeyboardHandler = function() {
- return this.$keyboardHandler;
+ this.moveCursorWordLeft = function() {
+ if (this.session.$selectLongWords)
+ this.moveCursorLongWordLeft();
+ else
+ this.moveCursorShortWordLeft();
};
- this.$callKeyboardHandler = function (e, hashId, keyOrText, keyCode) {
- var env = {editor: this.$editor},
- toExecute;
+ /** related to: EditSession.documentToScreenPosition
+ * Selection.moveCursorBy(rows, chars)
+ * - rows (Number): The number of rows to move by
+ * - chars (Number): The number of characters to move by
+ *
+ * Moves the cursor to position indicated by the parameters. Negative numbers move the cursor backwards in the document.
+ **/
+ this.moveCursorBy = function(rows, chars) {
+ var screenPos = this.session.documentToScreenPosition(
+ this.lead.row,
+ this.lead.column
+ );
- if (this.$keyboardHandler) {
- toExecute =
- this.$keyboardHandler.handleKeyboard(this.$data, hashId, keyOrText, keyCode, e);
+ if (chars === 0) {
+ if (this.$desiredColumn)
+ screenPos.column = this.$desiredColumn;
+ else
+ this.$desiredColumn = screenPos.column;
}
- // If there is nothing to execute yet, then use the default keymapping.
- if (!toExecute || !toExecute.command) {
- if (hashId != 0 || keyCode != 0) {
- toExecute = {
- command: canon.findKeyCommand(env, "editor", hashId, keyOrText)
- }
- } else {
- toExecute = {
- command: "inserttext",
- args: {
- text: keyOrText
- }
- }
- }
- }
+ var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column);
- var success = false;
- if (toExecute) {
- success = canon.exec(toExecute.command,
- env, "editor", toExecute.args);
- if (success) {
- event.stopEvent(e);
- }
- }
- return success;
+ // move the cursor and update the desired column
+ this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0);
};
- this.onCommandKey = function(e, hashId, keyCode, keyString) {
- // In case there is no keyString, try to interprete the keyCode.
- if (!keyString) {
- keyString = keyUtil.keyCodeToString(keyCode);
- }
- return this.$callKeyboardHandler(e, hashId, keyString, keyCode);
+ /**
+ * Selection.moveCursorToPosition(position)
+ * - position (Object): The position to move to
+ *
+ * Moves the selection to the position indicated by its `row` and `column`.
+ **/
+ this.moveCursorToPosition = function(position) {
+ this.moveCursorTo(position.row, position.column);
};
- this.onTextInput = function(text) {
- return this.$callKeyboardHandler({}, 0, text, 0);
- }
-
-}).call(KeyBinding.prototype);
-
-exports.KeyBinding = KeyBinding;
-});
-/* vim:ts=4:sts=4:sw=4:
- * ***** 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
- * Julian Viereck
- * Mihai Sucan
- *
- * 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('ace/commands/default_commands', ['require', 'exports', 'module' , 'pilot/lang', 'pilot/canon'], function(require, exports, module) {
+ /**
+ * Selection.moveCursorTo(row, column, keepDesiredColumn)
+ * - row (Number): The row to move to
+ * - column (Number): The column to move to
+ * - keepDesiredColumn (Boolean): [If `true`, the cursor move does not respect the previous column]{: #preventUpdateBool}
+ *
+ * Moves the cursor to the row and column provided. [If `preventUpdateDesiredColumn` is `true`, then the cursor stays in the same column position as its original point.]{: #preventUpdateBoolDesc}
+ **/
+ 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;
+ }
-var lang = require("pilot/lang");
-var canon = require("pilot/canon");
+ this.$keepDesiredColumnOnChange = true;
+ this.lead.setPosition(row, column);
+ this.$keepDesiredColumnOnChange = false;
-function bindKey(win, mac) {
- return {
- win: win,
- mac: mac,
- sender: "editor"
+ if (!keepDesiredColumn)
+ this.$desiredColumn = null;
};
-}
-canon.addCommand({
- name: "null",
- exec: function(env, args, request) { }
-});
+ /**
+ * Selection.moveCursorToScreen(row, column, keepDesiredColumn)
+ * - row (Number): The row to move to
+ * - column (Number): The column to move to
+ * - keepDesiredColumn (Boolean): {:preventUpdateBool}
+ *
+ * Moves the cursor to the screen position indicated by row and column. {:preventUpdateBoolDesc}
+ **/
+ this.moveCursorToScreen = function(row, column, keepDesiredColumn) {
+ var pos = this.session.screenToDocumentPosition(row, column);
+ this.moveCursorTo(pos.row, pos.column, keepDesiredColumn);
+ };
-canon.addCommand({
- name: "selectall",
- bindKey: bindKey("Ctrl-A", "Command-A"),
- exec: function(env, args, request) { env.editor.selectAll(); }
-});
-canon.addCommand({
- name: "removeline",
- bindKey: bindKey("Ctrl-D", "Command-D"),
- exec: function(env, args, request) { env.editor.removeLines(); }
-});
-canon.addCommand({
- name: "gotoline",
- bindKey: bindKey("Ctrl-L", "Command-L"),
- exec: function(env, args, request) {
- var line = parseInt(prompt("Enter line number:"));
- if (!isNaN(line)) {
- env.editor.gotoLine(line);
- }
- }
-});
-canon.addCommand({
- name: "togglecomment",
- bindKey: bindKey("Ctrl-7", "Command-7"),
- exec: function(env, args, request) { env.editor.toggleCommentLines(); }
-});
-canon.addCommand({
- name: "findnext",
- bindKey: bindKey("Ctrl-K", "Command-G"),
- exec: function(env, args, request) { env.editor.findNext(); }
-});
-canon.addCommand({
- name: "findprevious",
- bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"),
- exec: function(env, args, request) { env.editor.findPrevious(); }
-});
-canon.addCommand({
- name: "find",
- bindKey: bindKey("Ctrl-F", "Command-F"),
- exec: function(env, args, request) {
- var needle = prompt("Find:");
- env.editor.find(needle);
- }
-});
-canon.addCommand({
- name: "replace",
- bindKey: bindKey("Ctrl-R", "Command-Option-F"),
- exec: function(env, args, request) {
- var needle = prompt("Find:");
- if (!needle)
- return;
- var replacement = prompt("Replacement:");
- if (!replacement)
- return;
- env.editor.replace(replacement, {needle: needle});
+ // remove listeners from document
+ this.detach = function() {
+ this.lead.detach();
+ this.anchor.detach();
+ this.session = this.doc = null;
}
-});
-canon.addCommand({
- name: "replaceall",
- bindKey: bindKey("Ctrl-Shift-R", "Command-Shift-Option-F"),
- exec: function(env, args, request) {
- var needle = prompt("Find:");
- if (!needle)
- return;
- var replacement = prompt("Replacement:");
- if (!replacement)
- return;
- env.editor.replaceAll(replacement, {needle: needle});
+
+ this.fromOrientedRange = function(range) {
+ this.setSelectionRange(range, range.cursor == range.start);
+ this.$desiredColumn = range.desiredColumn || this.$desiredColumn;
}
-});
-canon.addCommand({
- name: "undo",
- bindKey: bindKey("Ctrl-Z", "Command-Z"),
- exec: function(env, args, request) { env.editor.undo(); }
-});
-canon.addCommand({
- name: "redo",
- bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"),
- exec: function(env, args, request) { env.editor.redo(); }
-});
-canon.addCommand({
- name: "overwrite",
- bindKey: bindKey("Insert", "Insert"),
- exec: function(env, args, request) { env.editor.toggleOverwrite(); }
-});
-canon.addCommand({
- name: "copylinesup",
- bindKey: bindKey("Ctrl-Alt-Up", "Command-Option-Up"),
- exec: function(env, args, request) { env.editor.copyLinesUp(); }
-});
-canon.addCommand({
- name: "movelinesup",
- bindKey: bindKey("Alt-Up", "Option-Up"),
- exec: function(env, args, request) { env.editor.moveLinesUp(); }
-});
-canon.addCommand({
- name: "selecttostart",
- bindKey: bindKey("Ctrl-Shift-Home|Alt-Shift-Up", "Command-Shift-Up"),
- exec: function(env, args, request) { env.editor.getSelection().selectFileStart(); }
-});
-canon.addCommand({
- name: "gotostart",
- bindKey: bindKey("Ctrl-Home|Ctrl-Up", "Command-Home|Command-Up"),
- exec: function(env, args, request) { env.editor.navigateFileStart(); }
-});
-canon.addCommand({
- name: "selectup",
- bindKey: bindKey("Shift-Up", "Shift-Up"),
- exec: function(env, args, request) { env.editor.getSelection().selectUp(); }
-});
-canon.addCommand({
- name: "golineup",
- bindKey: bindKey("Up", "Up|Ctrl-P"),
- exec: function(env, args, request) { env.editor.navigateUp(args.times); }
-});
-canon.addCommand({
- name: "copylinesdown",
- bindKey: bindKey("Ctrl-Alt-Down", "Command-Option-Down"),
- exec: function(env, args, request) { env.editor.copyLinesDown(); }
-});
-canon.addCommand({
- name: "movelinesdown",
- bindKey: bindKey("Alt-Down", "Option-Down"),
- exec: function(env, args, request) { env.editor.moveLinesDown(); }
-});
-canon.addCommand({
- name: "selecttoend",
- bindKey: bindKey("Ctrl-Shift-End|Alt-Shift-Down", "Command-Shift-Down"),
- exec: function(env, args, request) { env.editor.getSelection().selectFileEnd(); }
-});
-canon.addCommand({
- name: "gotoend",
- bindKey: bindKey("Ctrl-End|Ctrl-Down", "Command-End|Command-Down"),
- exec: function(env, args, request) { env.editor.navigateFileEnd(); }
-});
-canon.addCommand({
- name: "selectdown",
- bindKey: bindKey("Shift-Down", "Shift-Down"),
- exec: function(env, args, request) { env.editor.getSelection().selectDown(); }
-});
-canon.addCommand({
- name: "golinedown",
- bindKey: bindKey("Down", "Down|Ctrl-N"),
- exec: function(env, args, request) { env.editor.navigateDown(args.times); }
-});
-canon.addCommand({
- name: "selectwordleft",
- bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"),
- exec: function(env, args, request) { env.editor.getSelection().selectWordLeft(); }
-});
-canon.addCommand({
- name: "gotowordleft",
- bindKey: bindKey("Ctrl-Left", "Option-Left"),
- exec: function(env, args, request) { env.editor.navigateWordLeft(); }
-});
-canon.addCommand({
- name: "selecttolinestart",
- bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"),
- exec: function(env, args, request) { env.editor.getSelection().selectLineStart(); }
-});
-canon.addCommand({
- name: "gotolinestart",
- bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"),
- exec: function(env, args, request) { env.editor.navigateLineStart(); }
-});
-canon.addCommand({
- name: "selectleft",
- bindKey: bindKey("Shift-Left", "Shift-Left"),
- exec: function(env, args, request) { env.editor.getSelection().selectLeft(); }
-});
-canon.addCommand({
- name: "gotoleft",
- bindKey: bindKey("Left", "Left|Ctrl-B"),
- exec: function(env, args, request) { env.editor.navigateLeft(args.times); }
-});
-canon.addCommand({
- name: "selectwordright",
- bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"),
- exec: function(env, args, request) { env.editor.getSelection().selectWordRight(); }
-});
-canon.addCommand({
- name: "gotowordright",
- bindKey: bindKey("Ctrl-Right", "Option-Right"),
- exec: function(env, args, request) { env.editor.navigateWordRight(); }
-});
-canon.addCommand({
- name: "selecttolineend",
- bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"),
- exec: function(env, args, request) { env.editor.getSelection().selectLineEnd(); }
-});
-canon.addCommand({
- name: "gotolineend",
- bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"),
- exec: function(env, args, request) { env.editor.navigateLineEnd(); }
-});
-canon.addCommand({
- name: "selectright",
- bindKey: bindKey("Shift-Right", "Shift-Right"),
- exec: function(env, args, request) { env.editor.getSelection().selectRight(); }
-});
-canon.addCommand({
- name: "gotoright",
- bindKey: bindKey("Right", "Right|Ctrl-F"),
- exec: function(env, args, request) { env.editor.navigateRight(args.times); }
-});
-canon.addCommand({
- name: "selectpagedown",
- bindKey: bindKey("Shift-PageDown", "Shift-PageDown"),
- exec: function(env, args, request) { env.editor.selectPageDown(); }
-});
-canon.addCommand({
- name: "pagedown",
- bindKey: bindKey(null, "PageDown"),
- exec: function(env, args, request) { env.editor.scrollPageDown(); }
-});
-canon.addCommand({
- name: "gotopagedown",
- bindKey: bindKey("PageDown", "Option-PageDown|Ctrl-V"),
- exec: function(env, args, request) { env.editor.gotoPageDown(); }
-});
-canon.addCommand({
- name: "selectpageup",
- bindKey: bindKey("Shift-PageUp", "Shift-PageUp"),
- exec: function(env, args, request) { env.editor.selectPageUp(); }
-});
-canon.addCommand({
- name: "pageup",
- bindKey: bindKey(null, "PageUp"),
- exec: function(env, args, request) { env.editor.scrollPageUp(); }
-});
-canon.addCommand({
- name: "gotopageup",
- bindKey: bindKey("PageUp", "Option-PageUp"),
- exec: function(env, args, request) { env.editor.gotoPageUp(); }
-});
-canon.addCommand({
- name: "selectlinestart",
- bindKey: bindKey("Shift-Home", "Shift-Home"),
- exec: function(env, args, request) { env.editor.getSelection().selectLineStart(); }
-});
-canon.addCommand({
- name: "selectlineend",
- bindKey: bindKey("Shift-End", "Shift-End"),
- exec: function(env, args, request) { env.editor.getSelection().selectLineEnd(); }
-});
-canon.addCommand({
- name: "del",
- bindKey: bindKey("Delete", "Delete|Ctrl-D"),
- exec: function(env, args, request) { env.editor.removeRight(); }
-});
-canon.addCommand({
- name: "backspace",
- bindKey: bindKey(
- "Ctrl-Backspace|Command-Backspace|Option-Backspace|Shift-Backspace|Backspace",
- "Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"
- ),
- exec: function(env, args, request) { env.editor.removeLeft(); }
-});
-canon.addCommand({
- name: "removetolinestart",
- bindKey: bindKey(null, "Option-Backspace"),
- exec: function(env, args, request) { env.editor.removeToLineStart(); }
-});
-canon.addCommand({
- name: "removetolineend",
- bindKey: bindKey(null, "Ctrl-K"),
- exec: function(env, args, request) { env.editor.removeToLineEnd(); }
-});
-canon.addCommand({
- name: "removewordleft",
- bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"),
- exec: function(env, args, request) { env.editor.removeWordLeft(); }
-});
-canon.addCommand({
- name: "removewordright",
- bindKey: bindKey(null, "Alt-Delete"),
- exec: function(env, args, request) { env.editor.removeWordRight(); }
-});
-canon.addCommand({
- name: "outdent",
- bindKey: bindKey("Shift-Tab", "Shift-Tab"),
- exec: function(env, args, request) { env.editor.blockOutdent(); }
-});
-canon.addCommand({
- name: "indent",
- bindKey: bindKey("Tab", "Tab"),
- exec: function(env, args, request) { env.editor.indent(); }
-});
-canon.addCommand({
- name: "inserttext",
- exec: function(env, args, request) {
- env.editor.insert(lang.stringRepeat(args.text || "", args.times || 1));
+
+ 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;
}
-});
-canon.addCommand({
- name: "centerselection",
- bindKey: bindKey(null, "Ctrl-L"),
- exec: function(env, args, request) { env.editor.centerSelection(); }
-});
-canon.addCommand({
- name: "splitline",
- bindKey: bindKey(null, "Ctrl-O"),
- exec: function(env, args, request) { env.editor.splitLine(); }
-});
-canon.addCommand({
- name: "transposeletters",
- bindKey: bindKey("Ctrl-T", "Ctrl-T"),
- exec: function(env, args, request) { env.editor.transposeLetters(); }
-});
-});/* vim:ts=4:sts=4:sw=4:
- * ***** BEGIN LICENSE BLOCK *****
+}).call(Selection.prototype);
+
+exports.Selection = Selection;
+});
+/* ***** 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
@@ -7856,8 +9897,6 @@ canon.addCommand({
*
* Contributor(s):
* Fabian Jakobs
- * Mihai Sucan
- * Julian Viereck
*
* 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
@@ -7873,1677 +9912,2145 @@ canon.addCommand({
*
* ***** END LICENSE BLOCK ***** */
-define('ace/edit_session', ['require', 'exports', 'module' , 'pilot/oop', 'pilot/lang', 'pilot/event_emitter', 'ace/selection', 'ace/mode/text', 'ace/range', 'ace/document', 'ace/background_tokenizer', 'ace/edit_session/folding'], function(require, exports, module) {
-
-var oop = require("pilot/oop");
-var lang = require("pilot/lang");
-var EventEmitter = require("pilot/event_emitter").EventEmitter;
-var Selection = require("ace/selection").Selection;
-var TextMode = require("ace/mode/text").Mode;
-var Range = require("ace/range").Range;
-var Document = require("ace/document").Document;
-var BackgroundTokenizer = require("ace/background_tokenizer").BackgroundTokenizer;
-
-var EditSession = function(text, mode) {
- this.$modified = true;
- this.$breakpoints = [];
- this.$frontMarkers = {};
- this.$backMarkers = {};
- this.$markerId = 1;
- this.$rowCache = [];
- this.$wrapData = [];
- this.$foldData = [];
- this.$foldData.toString = function() {
- var str = "";
- this.forEach(function(foldLine) {
- str += "\n" + foldLine.toString();
- });
- return str;
- }
-
- if (text instanceof Document) {
- this.setDocument(text);
- } else {
- this.setDocument(new Document(text));
- }
-
- this.selection = new Selection(this);
- if (mode)
- this.setMode(mode);
- else
- this.setMode(new TextMode());
-};
-
-
-(function() {
+define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
- oop.implement(this, EventEmitter);
+/**
+ * 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.
+ *
+ **/
- this.setDocument = function(doc) {
- if (this.doc)
- throw new Error("Document is already set");
+/**
+ * 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.doc = doc;
- doc.on("change", this.onChange.bind(this));
- this.on("changeFold", this.onChangeFold.bind(this));
+ this.end = {
+ row: endRow,
+ column: endColumn
};
+};
- this.getDocument = function() {
- return this.doc;
+(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.$resetRowCache = function(row) {
- if (row == 0) {
- this.$rowCache = [];
- return;
- }
- var rowCache = this.$rowCache;
- for (var i = 0; i < rowCache.length; i++) {
- if (rowCache[i].docRow >= row) {
- rowCache.splice(i, rowCache.length);
- return;
- }
- }
- };
+ /**
+ * Range.toString() -> String
+ *
+ * Returns a string containing the range's row and column information, given like this:
+ *
+ * [start.row/start.column] -> [end.row/end.column]
+ *
+ **/
- this.onChangeFold = function(e) {
- var fold = e.data;
- this.$resetRowCache(fold.start.row);
+ this.toString = function() {
+ return ("Range: [" + this.start.row + "/" + this.start.column +
+ "] -> [" + this.end.row + "/" + this.end.column + "]");
};
- this.onChange = function(e) {
- var delta = e.data;
- this.$modified = true;
+ /** related to: Range.compare
+ * Range.contains(row, column) -> Boolean
+ * - row (Number): A row to check for
+ * - column (Number): A column to check for
+ *
+ * Returns `true` if the `row` and `column` provided are within the given range. This can better be expressed as returning `true` if:
+ *
+ * this.start.row <= row <= this.end.row &&
+ * this.start.column <= column <= this.end.column
+ *
+ **/
- this.$resetRowCache(delta.range.start.row);
+ this.contains = function(row, column) {
+ return this.compare(row, column) == 0;
+ };
- 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
- });
+ /** related to: Range.compare
+ * Range.compareRange(range) -> Number
+ * - range (Range): A range to compare with
+ * + (Number): This method returns one of the following numbers:
+ *
+ * * `-2`: (B) is in front of (A), and doesn't intersect with (A)
+ * * `-1`: (B) begins before (A) but ends inside of (A)
+ * * `0`: (B) is completely inside of (A) OR (A) is completely inside of (B)
+ * * `+1`: (B) begins inside of (A) but ends outside of (A)
+ * * `+2`: (B) is after (A) and doesn't intersect with (A)
+ * * `42`: FTW state: (B) ends in (A) but starts outside of (A)
+ *
+ * Compares `this` range (A) with another range (B).
+ *
+ **/
+ 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;
}
-
- this.$informUndoManager.schedule();
}
+ }
- this.bgTokenizer.start(delta.range.start.row);
- this._dispatchEvent("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();
- };
+ /** 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);
+ }
- this.getValue =
- this.toString = function() {
- return this.doc.getValue();
- };
+ /** 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;
+ }
- this.getSelection = function() {
- return this.selection;
- };
+ /**
+ * 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);
+ }
- this.getState = function(row) {
- return this.bgTokenizer.getState(row);
- };
+ /**
+ * 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;
+ }
- this.getTokens = function(firstRow, lastRow) {
- return this.bgTokenizer.getTokens(firstRow, lastRow);
- };
+ /**
+ * 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;
+ }
- this.setUndoManager = function(undoManager) {
- this.$undoManager = undoManager;
- this.$resetRowCache(0);
- this.$deltas = [];
- this.$deltasDoc = [];
- this.$deltasFold = [];
+ /**
+ * 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;
+ }
+ }
- if (this.$informUndoManager)
- this.$informUndoManager.cancel();
+ /**
+ * 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;
+ }
+ }
- 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 = [];
+ /** 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;
}
- this.$informUndoManager =
- lang.deferredCall(this.$syncInformUndoManager);
}
- };
-
- this.$defaultUndoManager = {
- undo: function() {},
- redo: function() {},
- reset: function() {}
- };
+ return false;
+ }
- this.getUndoManager = function() {
- return this.$undoManager || this.$defaultUndoManager;
- },
+ /** 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;
+ }
- this.getTabString = function() {
- if (this.getUseSoftTabs()) {
- return lang.stringRepeat(" ", this.getTabSize());
- } else {
- return "\t";
+ /** 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;
+ }
- this.$useSoftTabs = true;
- this.setUseSoftTabs = function(useSoftTabs) {
- if (this.$useSoftTabs === useSoftTabs) return;
+ /**
+ * 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);
+ };
+ }
- this.$useSoftTabs = useSoftTabs;
- };
+ if (row < this.start.row)
+ return -1;
- this.getUseSoftTabs = function() {
- return this.$useSoftTabs;
- };
+ if (row > this.end.row)
+ return 1;
- this.$tabSize = 4;
- this.setTabSize = function(tabSize) {
- if (isNaN(tabSize) || this.$tabSize === tabSize) return;
+ if (this.start.row === row)
+ return column >= this.start.column ? 0 : -1;
- this.$modified = true;
- this.$tabSize = tabSize;
- this._dispatchEvent("changeTabSize");
- };
+ if (this.end.row === row)
+ return column <= this.end.column ? 0 : 1;
- this.getTabSize = function() {
- return this.$tabSize;
+ return 0;
};
- this.isTabStop = function(position) {
- return this.$useSoftTabs && (position.column % this.$tabSize == 0);
- };
+ /**
+ * Range.compareStart(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 `isStart` 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.compareStart = function(row, column) {
+ if (this.start.row == row && this.start.column == column) {
+ return -1;
+ } else {
+ return this.compare(row, column);
+ }
+ }
- this.$overwrite = false;
- this.setOverwrite = function(overwrite) {
- if (this.$overwrite == overwrite) return;
+ /**
+ * 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);
+ }
+ }
- this.$overwrite = overwrite;
- this._dispatchEvent("changeOverwrite");
- };
+ /**
+ * 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);
+ }
+ }
- this.getOverwrite = function() {
- return this.$overwrite;
- };
+ /**
+ * 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
+ };
+ }
- this.toggleOverwrite = function() {
- this.setOverwrite(!this.$overwrite);
- };
+ if (this.start.row > lastRow) {
+ var start = {
+ row: lastRow+1,
+ column: 0
+ };
+ }
- this.getBreakpoints = function() {
- return this.$breakpoints;
- };
+ if (this.start.row < firstRow) {
+ var start = {
+ row: firstRow,
+ column: 0
+ };
+ }
- this.setBreakpoints = function(rows) {
- this.$breakpoints = [];
- for (var i=0; i Range
+ * - row (Number): A new row to extend to
+ * - column (Number): A new column to extend to
+ *
+ * Changes the row and column points for the calling range for both the starting and ending points. This method returns that range with a new row.
+ *
+ **/
+ this.extend = function(row, column) {
+ var cmp = this.compare(row, column);
- this.setBreakpoint = function(row) {
- this.$breakpoints[row] = true;
- this._dispatchEvent("changeBreakpoint", {});
- };
+ if (cmp == 0)
+ return this;
+ else if (cmp == -1)
+ var start = {row: row, column: column};
+ else
+ var end = {row: row, column: column};
- this.clearBreakpoint = function(row) {
- delete this.$breakpoints[row];
- this._dispatchEvent("changeBreakpoint", {});
+ return Range.fromPoints(start || this.start, end || this.end);
};
- this.getBreakpoints = function() {
- return this.$breakpoints;
+ this.isEmpty = function() {
+ return (this.start.row == this.end.row && this.start.column == this.end.column);
};
- this.addMarker = function(range, clazz, type, inFront) {
- var id = this.$markerId++;
-
- var marker = {
- range : range,
- type : type || "line",
- renderer: typeof type == "function" ? type : null,
- clazz : clazz,
- inFront: !!inFront
- }
-
- if (inFront) {
- this.$frontMarkers[id] = marker;
- this._dispatchEvent("changeFrontMarker")
- } else {
- this.$backMarkers[id] = marker;
- this._dispatchEvent("changeBackMarker")
- }
-
- return id;
+ /**
+ * Range.isMultiLine() -> Boolean
+ *
+ * Returns true if the range spans across multiple lines.
+ *
+ **/
+ this.isMultiLine = function() {
+ return (this.start.row !== this.end.row);
};
- this.removeMarker = function(markerId) {
- var marker = this.$frontMarkers[markerId] || this.$backMarkers[markerId];
- if (!marker)
- return;
-
- var markers = marker.inFront ? this.$frontMarkers : this.$backMarkers;
- if (marker) {
- delete (markers[markerId]);
- this._dispatchEvent(marker.inFront ? "changeFrontMarker" : "changeBackMarker");
- }
+ /**
+ * Range.clone() -> Range
+ *
+ * Returns a duplicate of the calling range.
+ *
+ **/
+ this.clone = function() {
+ return Range.fromPoints(this.start, this.end);
};
- this.getMarkers = function(inFront) {
- return inFront ? this.$frontMarkers : this.$backMarkers;
+ /**
+ * Range.collapseRows() -> Range
+ *
+ * Returns a range containing the starting and ending rows of the original range, but with a column value of `0`.
+ *
+ **/
+ 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)
};
- /**
- * Error:
- * {
- * row: 12,
- * column: 2, //can be undefined
- * text: "Missing argument",
- * type: "error" // or "warning" or "info"
- * }
- */
- this.setAnnotations = function(annotations) {
- this.$annotations = {};
- for (var i=0; i Range
+ * - session (EditSession): The `EditSession` to retrieve coordinates from
+ *
+ * Given the current `Range`, this function converts those starting and ending points into screen positions, and then returns a new `Range` object.
+ **/
+ this.toScreenRange = function(session) {
+ var screenPosStart =
+ session.documentToScreenPosition(this.start);
+ var screenPosEnd =
+ session.documentToScreenPosition(this.end);
- this.getAnnotations = function() {
- return this.$annotations;
+ return new Range(
+ screenPosStart.row, screenPosStart.column,
+ screenPosEnd.row, screenPosEnd.column
+ );
};
- this.clearAnnotations = function() {
- this.$annotations = {};
- this._dispatchEvent("changeAnnotation", {});
- };
+}).call(Range.prototype);
- this.$detectNewLine = function(text) {
- var match = text.match(/^.*?(\r?\n)/m);
- if (match) {
- this.$autoNewLine = match[1];
- } else {
- this.$autoNewLine = "\n";
- }
- };
+/**
+ * Range.fromPoints(start, end) -> Range
+ * - start (Range): A starting point to use
+ * - end (Range): An ending point to use
+ *
+ * Creates and returns a new `Range` based on the row and column of the given parameters.
+ *
+**/
+Range.fromPoints = function(start, end) {
+ return new Range(start.row, start.column, end.row, end.column);
+};
- this.getWordRange = function(row, column) {
- var line = this.getLine(row);
+exports.Range = Range;
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
+ * Mihai Sucan
+ * Chris Spencer
+ *
+ * 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 ***** */
- var inToken = false;
- if (column > 0) {
- inToken = !!line.charAt(column - 1).match(this.tokenRe);
- }
+define('ace/mode/text', ['require', 'exports', 'module' , 'ace/tokenizer', 'ace/mode/text_highlight_rules', 'ace/mode/behaviour', 'ace/unicode'], function(require, exports, module) {
+"use strict";
- if (!inToken) {
- inToken = !!line.charAt(column).match(this.tokenRe);
- }
+var Tokenizer = require("../tokenizer").Tokenizer;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+var Behaviour = require("./behaviour").Behaviour;
+var unicode = require("../unicode");
- var re = inToken ? this.tokenRe : this.nonTokenRe;
+var Mode = function() {
+ this.$tokenizer = new Tokenizer(new TextHighlightRules().getRules());
+ this.$behaviour = new Behaviour();
+};
- var start = column;
- if (start > 0) {
- do {
- start--;
- }
- while (start >= 0 && line.charAt(start).match(re));
- start++;
- }
+(function() {
- var end = column;
- while (end < line.length && line.charAt(end).match(re)) {
- end++;
- }
+ 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"
+ );
- return new Range(row, start, row, end);
+ this.getTokenizer = function() {
+ return this.$tokenizer;
};
- this.setNewLineMode = function(newLineMode) {
- this.doc.setNewLineMode(newLineMode);
+ this.toggleCommentLines = function(state, doc, startRow, endRow) {
};
- this.getNewLineMode = function() {
- return this.doc.getNewLineMode();
+ this.getNextLineIndent = function(state, line, tab) {
+ return "";
};
- this.$useWorker = true;
- this.setUseWorker = function(useWorker) {
- if (this.$useWorker == useWorker)
- return;
-
- this.$useWorker = useWorker;
-
- this.$stopWorker();
- if (useWorker)
- this.$startWorker();
+ this.checkOutdent = function(state, line, input) {
+ return false;
};
- this.getUseWorker = function() {
- return this.$useWorker;
+ this.autoOutdent = function(state, doc, row) {
};
- this.onReloadTokenizer = function(e) {
- var rows = e.data;
- this.bgTokenizer.start(rows.first);
- this._dispatchEvent("tokenizerUpdate", e);
- };
+ this.$getIndent = function(line) {
+ var match = line.match(/^(\s+)/);
+ if (match) {
+ return match[1];
+ }
- this.$mode = null;
- this.setMode = function(mode) {
- if (this.$mode === mode) return;
- this.$mode = mode;
+ return "";
+ };
+
+ this.createWorker = function(session) {
+ return null;
+ };
- this.$stopWorker();
+ this.highlightSelection = function(editor) {
+ var session = editor.session;
+ if (!session.$selectionOccurrences)
+ session.$selectionOccurrences = [];
- if (this.$useWorker)
- this.$startWorker();
+ if (session.$selectionOccurrences.length)
+ this.clearSelectionHighlight(editor);
- var tokenizer = mode.getTokenizer();
+ var selection = editor.getSelectionRange();
+ if (selection.isEmpty() || selection.isMultiLine())
+ return;
- if(tokenizer.addEventListener !== undefined) {
- var onReloadTokenizer = this.onReloadTokenizer.bind(this);
- tokenizer.addEventListener("update", onReloadTokenizer);
- }
+ 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));
- if (!this.bgTokenizer) {
- this.bgTokenizer = new BackgroundTokenizer(tokenizer);
- var _self = this;
- this.bgTokenizer.addEventListener("update", function(e) {
- _self._dispatchEvent("tokenizerUpdate", e);
- });
- } else {
- this.bgTokenizer.setTokenizer(tokenizer);
- }
+ // 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;
- this.bgTokenizer.setDocument(this.getDocument());
- this.bgTokenizer.start(0);
-
- this.tokenRe = mode.tokenRe;
- this.nonTokenRe = mode.nonTokenRe;
+ needle = line.substring(selection.start.column, selection.end.column);
+ if (!/^[\w\d]+$/.test(needle))
+ return;
- this._dispatchEvent("changeMode");
- };
+ var cursor = editor.getCursorPosition();
- this.$stopWorker = function() {
- if (this.$worker)
- this.$worker.terminate();
+ var newOptions = {
+ wrap: true,
+ wholeWord: true,
+ caseSensitive: true,
+ needle: needle
+ };
- this.$worker = null;
- };
+ var currentOptions = editor.$search.getOptions();
+ editor.$search.set(newOptions);
- 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;
+ var ranges = editor.$search.findAll(session);
+ ranges.forEach(function(range) {
+ if (!range.contains(cursor.row, cursor.column)) {
+ var marker = session.addMarker(range, "ace_selected_word", "text");
+ session.$selectionOccurrences.push(marker);
}
- }
- else
- this.$worker = null;
- };
-
- this.getMode = function() {
- return this.$mode;
- };
-
- this.$scrollTop = 0;
- this.setScrollTopRow = function(scrollTopRow) {
- if (this.$scrollTop === scrollTopRow) return;
+ });
- this.$scrollTop = scrollTopRow;
- this._dispatchEvent("changeScrollTop");
+ editor.$search.set(currentOptions);
};
- this.getScrollTopRow = function() {
- return this.$scrollTop;
- };
+ this.clearSelectionHighlight = function(editor) {
+ if (!editor.session.$selectionOccurrences)
+ return;
- this.getWidth = function() {
- this.$computeWidth();
- return this.width;
- };
+ editor.session.$selectionOccurrences.forEach(function(marker) {
+ editor.session.removeMarker(marker);
+ });
- this.getScreenWidth = function() {
- this.$computeWidth();
- return this.screenWidth;
+ editor.session.$selectionOccurrences = [];
};
-
- this.$computeWidth = function(force) {
- if (this.$modified || force) {
- this.$modified = false;
-
- var lines = this.doc.getAllLines();
- var longestLine = 0;
- var longestScreenLine = 0;
-
- for ( var i = 0; i < lines.length; i++) {
- var foldLine = this.getFoldLine(i),
- line, len;
-
- line = lines[i];
- if (foldLine) {
- var end = foldLine.range.end;
- line = this.getFoldDisplayLine(foldLine);
- // Continue after the foldLine.end.row. All the lines in
- // between are folded.
- i = end.row;
- }
- len = line.length;
- longestLine = Math.max(longestLine, len);
- if (!this.$useWrapMode) {
- longestScreenLine = Math.max(
- longestScreenLine,
- this.$getStringScreenWidth(line)[0]
- );
- }
+
+ 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]]();
}
- this.width = longestLine;
+ }
+
+ var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformAction'];
- if (this.$useWrapMode) {
- this.screenWidth = this.$wrapLimit;
- } else {
- this.screenWidth = longestScreenLine;
+ 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);
- /**
- * Get a verbatim copy of the given line as it is in the document
- */
- 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();
- };
+exports.Mode = Mode;
+});
+/* ***** 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 ***** */
- this.getTextRange = function(range) {
- return this.doc.getTextRange(range);
- };
+define('ace/tokenizer', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
- this.findMatchingBracket = function(position) {
- if (position.column == 0) return null;
+/**
+ * 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).
+ *
+ **/
- var charBeforeCursor = this.getLine(position.row).charAt(position.column-1);
- if (charBeforeCursor == "") return null;
+/**
+ * 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;
- var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/);
- if (!match) {
- return null;
- }
+ 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] = {};
- if (match[1]) {
- return this.$findClosingBracket(match[1], position);
- } else {
- return this.$findOpeningBracket(match[2], position);
- }
- };
+ for ( var i = 0; i < state.length; i++) {
- this.$brackets = {
- ")": "(",
- "(": ")",
- "]": "[",
- "[": "]",
- "{": "}",
- "}": "{"
- };
+ if (state[i].regex instanceof RegExp)
+ state[i].regex = state[i].regex.toString().slice(1, -1);
- this.$findOpeningBracket = function(bracket, position) {
- var openBracket = this.$brackets[bracket];
+ // 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;
- var column = position.column - 2;
- var row = position.row;
- var depth = 1;
+ // Replace any backreferences and offset appropriately.
+ var adjustedregex = state[i].regex.replace(/\\([0-9]+)/g, function (match, digit) {
+ return "\\" + (parseInt(digit, 10) + matchTotal + 1);
+ });
- var line = this.getLine(row);
+ 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);
- while (true) {
- while(column >= 0) {
- var ch = line.charAt(column);
- if (ch == openBracket) {
- depth -= 1;
- if (depth == 0) {
- return {row: row, column: column};
- }
- }
- else if (ch == bracket) {
- depth +=1;
- }
- column -= 1;
- }
- row -=1;
- if (row < 0) break;
+ mapping[matchTotal] = {
+ rule: i,
+ len: matchcount
+ };
+ matchTotal += matchcount;
- var line = this.getLine(row);
- var column = line.length-1;
+ ruleRegExps.push(adjustedregex);
}
- return null;
- };
-
- this.$findClosingBracket = function(bracket, position) {
- var closingBracket = this.$brackets[bracket];
-
- var column = position.column;
- var row = position.row;
- var depth = 1;
-
- var line = this.getLine(row);
- var lineCount = this.getLength();
- while (true) {
- while(column < line.length) {
- var ch = line.charAt(column);
- if (ch == closingBracket) {
- depth -= 1;
- if (depth == 0) {
- return {row: row, column: column};
- }
- }
- else if (ch == bracket) {
- depth +=1;
- }
- column += 1;
- }
- row +=1;
- if (row >= lineCount) break;
+ this.regExps[key] = new RegExp("(?:(" + ruleRegExps.join(")|(") + ")|(.))", flag);
+ }
+};
- var line = this.getLine(row);
- var column = 0;
- }
- return null;
- };
+(function() {
- this.insert = function(position, text) {
- return this.doc.insert(position, text);
- };
+ /**
+ * 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;
+ var state = this.rules[currentState];
+ var mapping = this.matchMappings[currentState];
+ var re = this.regExps[currentState];
+ re.lastIndex = 0;
- this.remove = function(range) {
- return this.doc.remove(range);
- };
+ var match, tokens = [];
- this.undoChanges = function(deltas, dontSelect) {
- if (!deltas.length)
- return;
+ var lastIndex = 0;
- this.$fromUndo = true;
- var lastUndoRange = null;
- for (var i = deltas.length - 1; i != -1; i--) {
- 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 &&
- !dontSelect &&
- this.selection.setSelectionRange(lastUndoRange);
- return lastUndoRange;
- },
+ var token = {
+ type: null,
+ value: ""
+ };
- this.redoChanges = function(deltas, dontSelect) {
- if (!deltas.length)
- return;
+ while (match = re.exec(line)) {
+ var type = "text";
+ var rule = null;
+ var value = [match[0]];
- this.$fromUndo = true;
- var lastUndoRange = null;
- for (var i = 0; i < deltas.length; i++) {
- delta = deltas[i];
- if (delta.group == "doc") {
- this.doc.applyDeltas(delta.deltas);
- lastUndoRange =
- this.$getUndoSelection(delta.deltas, false, lastUndoRange);
- }
- }
- this.$fromUndo = false;
- lastUndoRange &&
- !dontSelect &&
- this.selection.setSelectionRange(lastUndoRange);
- return lastUndoRange;
- },
+ for (var i = 0; i < match.length-2; i++) {
+ if (match[i + 1] === undefined)
+ continue;
- this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {
- function isInsert(delta) {
- var insert =
- delta.action == "insertText" || delta.action == "insertLines";
- return isUndo ? !insert : insert;
- }
+ rule = state[mapping[i].rule];
- 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;
- }
+ if (mapping[i].len > 1)
+ value = match.slice(i+2, i+1+mapping[i].len);
- 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);
+ // 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;
}
- point = delta.range.end;
- if (range.compare(point.row, point.column) == 1) {
- range.setEnd(delta.range.end);
+ break;
+ }
+
+ if (value[0]) {
+ if (typeof type == "string") {
+ value = [value.join("")];
+ type = [type];
}
- lastDeltaIsInsert = true;
- } else {
- point = delta.range.start;
- if (range.compare(point.row, point.column) == -1) {
- range =
- Range.fromPoints(delta.range.start, delta.range.start);
+ 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]
+ };
+ }
}
- 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);
- }
+ if (lastIndex == line.length)
+ break;
+
+ lastIndex = re.lastIndex;
}
- return range;
- },
+ if (token.type)
+ tokens.push(token);
- this.replace = function(range, text) {
- return this.doc.replace(range, text);
+ return {
+ tokens : tokens,
+ state : currentState
+ };
};
- /**
- * Move a range of text from the given range to the given position.
- *
- * @param fromRange {Range} The range of text you want moved within the
- * document.
- * @param toPosition {Object} The location (row and column) where you want
- * to move the text to.
- * @return {Range} The new range where the text was moved to.
- */
- this.moveText = function(fromRange, toPosition) {
- var text = this.getTextRange(fromRange);
- this.remove(fromRange);
-
- var toRow = toPosition.row;
- var toColumn = toPosition.column;
+}).call(Tokenizer.prototype);
- // 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;
+exports.Tokenizer = Tokenizer;
+});
+/* ***** 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 ***** */
- if (fromRange.isMultiLine() && fromRange.end.row < toRow) {
- var lines = this.doc.$split(text);
- toRow -= lines.length - 1;
- }
+define('ace/mode/text_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/lang'], function(require, exports, module) {
+"use strict";
- var endRow = toRow + fromRange.end.row - fromRange.start.row;
- var endColumn = fromRange.isMultiLine() ?
- fromRange.end.column :
- toColumn + fromRange.end.column - fromRange.start.column;
+var lang = require("../lib/lang");
- var toRange = new Range(toRow, toColumn, endRow, endColumn);
+var TextHighlightRules = function() {
- this.insert(toRange.start, text);
+ // regexp must not have capturing parentheses
+ // regexps are ordered -> the first match is used
- return toRange;
+ this.$rules = {
+ "start" : [{
+ token : "empty_line",
+ regex : '^$'
+ }, {
+ token : "text",
+ regex : ".+"
+ }]
};
+};
- 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);
+(function() {
+
+ this.addRules = function(rules, prefix) {
+ for (var key in rules) {
+ var state = rules[key];
+ for (var i=0; i
+ *
+ * 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('ace/mode/behaviour', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+
+var Behaviour = function() {
+ this.$behaviours = {};
+};
+
+(function () {
+
+ this.add = function (name, action, callback) {
+ switch (undefined) {
+ case this.$behaviours:
+ this.$behaviours = {};
+ case this.$behaviours[name]:
+ this.$behaviours[name] = {};
+ }
+ this.$behaviours[name][action] = callback;
+ }
+
+ this.addBehaviours = function (behaviours) {
+ for (var key in behaviours) {
+ for (var action in behaviours[key]) {
+ this.add(key, action, behaviours[key][action]);
}
- this.remove(deleteRange);
}
- };
+ }
+
+ this.remove = function (name) {
+ if (this.$behaviours && this.$behaviours[name]) {
+ delete this.$behaviours[name];
+ }
+ }
+
+ this.inherit = function (mode, filter) {
+ if (typeof mode === "function") {
+ var behaviours = new mode().getBehaviours(filter);
+ } else {
+ var behaviours = mode.getBehaviours(filter);
+ }
+ this.addBehaviours(behaviours);
+ }
+
+ this.getBehaviours = function (filter) {
+ if (!filter) {
+ return this.$behaviours;
+ } else {
+ var ret = {}
+ for (var i = 0; i < filter.length; i++) {
+ if (this.$behaviours[filter[i]]) {
+ ret[filter[i]] = this.$behaviours[filter[i]];
+ }
+ }
+ return ret;
+ }
+ }
- this.moveLinesUp = function(firstRow, lastRow) {
- if (firstRow <= 0) return 0;
+}).call(Behaviour.prototype);
- var removed = this.doc.removeLines(firstRow, lastRow);
- this.doc.insertLines(firstRow - 1, removed);
- return -1;
- };
+exports.Behaviour = Behaviour;
+});
+define('ace/unicode', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
- this.moveLinesDown = function(firstRow, lastRow) {
- if (lastRow >= this.doc.getLength()-1) return 0;
+/*
+XRegExp Unicode plugin pack: Categories 1.0
+(c) 2010 Steven Levithan
+MIT License
+
+Uses the Unicode 5.2 character database
- var removed = this.doc.removeLines(firstRow, lastRow);
- this.doc.insertLines(firstRow+1, removed);
- return 1;
- };
+This package for the XRegExp Unicode plugin enables the following Unicode categories (aka properties):
- this.duplicateLines = function(firstRow, lastRow) {
- var firstRow = this.$clipRowToDocument(firstRow);
- var lastRow = this.$clipRowToDocument(lastRow);
+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
- var lines = this.getLines(firstRow, lastRow);
- this.doc.insertLines(firstRow, lines);
+Example usage:
- var addedRows = lastRow - firstRow + 1;
- return addedRows;
- };
+ \p{N}
+ \p{Cn}
+*/
- this.$clipRowToDocument = function(row) {
- return Math.max(0, Math.min(row, this.doc.getLength()-1));
- };
-
- 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
- };
- };
+// will be populated by addUnicodePackage
+exports.packages = {};
- // WRAPMODE
- this.$wrapLimit = 80;
- this.$useWrapMode = false;
- this.$wrapLimitRange = {
- min : null,
- max : null
- };
+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"
+});
- this.setUseWrapMode = function(useWrapMode) {
- if (useWrapMode != this.$useWrapMode) {
- this.$useWrapMode = useWrapMode;
- this.$modified = true;
- this.$resetRowCache(0);
+function addUnicodePackage (pack) {
+ var codePoint = /\w{4}/g;
+ for (var name in pack)
+ exports.packages[name] = pack[name].replace(codePoint, "\\u$&");
+};
- // If wrapMode is activaed, the wrapData array has to be initialized.
- if (useWrapMode) {
- var len = this.getLength();
- this.$wrapData = [];
- for (i = 0; i < len; i++) {
- this.$wrapData.push([]);
- }
- this.$updateWrapData(0, len - 1);
- }
+});
+/* ***** 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 ***** */
- this._dispatchEvent("changeWrapMode");
- }
- };
+define('ace/document', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/range', 'ace/anchor'], function(require, exports, module) {
+"use strict";
- this.getUseWrapMode = function() {
- return this.$useWrapMode;
- };
+var oop = require("./lib/oop");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+var Range = require("./range").Range;
+var Anchor = require("./anchor").Anchor;
- // 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.
- 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._dispatchEvent("changeWrapMode");
- }
- };
+/**
+ * class Document
+ *
+ * Contains the text of the document. Documents are controlled by a single [[EditSession `EditSession`]]. At its core, `Document`s are just an array of strings, with each row in the document matching up to the array index.
+ *
+ *
+ **/
+
+ /**
+ * 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 = [];
- // This should generally only be called by the renderer when a resize
- // is detected.
- 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._dispatchEvent("changeWrapLimit");
- }
- return true;
- }
- return false;
- };
+ if (Array.isArray(text)) {
+ this.insertLines(0, text);
+ }
+ // 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.
+ else if (text.length == 0) {
+ this.$lines = [""];
+ } else {
+ this.insert({row: 0, column:0}, text);
+ }
+};
- this.$constrainWrapLimit = function(wrapLimit) {
- var min = this.$wrapLimitRange.min;
- if (min)
- wrapLimit = Math.max(min, wrapLimit);
+(function() {
- var max = this.$wrapLimitRange.max;
- if (max)
- wrapLimit = Math.min(max, wrapLimit);
+ oop.implement(this, EventEmitter);
- // What would a limit of 0 even mean?
- return Math.max(1, wrapLimit);
+ /**
+ * Document.setValue(text) -> Void
+ * - text (String): The text to use
+ *
+ * Replaces all the lines in the current `Document` with the value of `text`.
+ **/
+ 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.getWrapLimit = function() {
- return this.$wrapLimit;
+ /**
+ * Document.getValue() -> String
+ *
+ * Returns all the lines in the document as a single string, split by the new line character.
+ **/
+ this.getValue = function() {
+ return this.getAllLines().join(this.getNewLineCharacter());
};
- this.getWrapLimitRange = function() {
- // Avoid unexpected mutation by returning a copy
- return {
- min : this.$wrapLimitRange.min,
- max : this.$wrapLimitRange.max
- };
+ /**
+ * Document.createAnchor(row, column) -> Anchor
+ * - row (Number): The row number to use
+ * - column (Number): The column number to use
+ *
+ * Creates a new `Anchor` to define a floating point in the document.
+ **/
+ this.createAnchor = function(row, column) {
+ return new Anchor(this, row, column);
};
- this.$updateInternalDataOnChange = function(e) {
- var useWrapMode = this.$useWrapMode;
- var len;
- var action = e.data.action;
- var firstRow = e.data.range.start.row,
- lastRow = e.data.range.end.row,
- start = e.data.range.start,
- end = e.data.range.end;
- var removedFolds = null;
+ /** internal, hide
+ * Document.$split(text) -> [String]
+ * - text (String): The text to work with
+ * + ([String]): A String array, with each index containing a piece of the original `text` string.
+ *
+ * Splits a string of text on any newline (`\n`) or carriage-return ('\r') characters.
+ *
+ *
+ **/
- if (action.indexOf("Lines") != -1) {
- if (action == "insertLines") {
- lastRow = firstRow + (e.data.lines.length);
- } else {
- lastRow = firstRow;
- }
- len = e.data.lines.length;
- } else {
- len = lastRow - firstRow;
+ // 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/);
+ };
- if (len != 0) {
- if (action.indexOf("remove") != -1) {
- useWrapMode && this.$wrapData.splice(firstRow, len);
- var foldLines = this.$foldData;
- removedFolds = this.getFoldsInRange(e.data.range);
- this.removeFolds(removedFolds);
+ /** internal, hide
+ * Document.$detectNewLine(text) -> Void
+ *
+ *
+ **/
+ this.$detectNewLine = function(text) {
+ var match = text.match(/^.*?(\r\n|\r|\n)/m);
+ if (match) {
+ this.$autoNewLine = match[1];
+ } else {
+ this.$autoNewLine = "\n";
+ }
+ };
- var foldLine = this.getFoldLine(end.row);
- var idx = 0;
- if (foldLine) {
- foldLine.addRemoveChars(end.row, end.column, start.column - end.column);
- foldLine.shiftRow(-len);
+ /**
+ * Document.getNewLineCharacter() -> String
+ * + (String): If `newLineMode == windows`, `\r\n` is returned.
+ * If `newLineMode == unix`, `\n` is returned.
+ * If `newLineMode == auto`, the value of `autoNewLine` is returned.
+ *
+ * Returns the newline character that's being used, depending on the value of `newLineMode`.
+ *
+ *
+ *
+ **/
+ this.getNewLineCharacter = function() {
+ switch (this.$newLineMode) {
+ case "windows":
+ return "\r\n";
- var foldLineBefore = this.getFoldLine(firstRow);
- if (foldLineBefore && foldLineBefore !== foldLine) {
- foldLineBefore.merge(foldLine);
- foldLine = foldLineBefore;
- }
- idx = foldLines.indexOf(foldLine) + 1;
- }
+ case "unix":
+ return "\n";
- for (idx; idx < foldLines.length; idx++) {
- var foldLine = foldLines[idx];
- if (foldLine.start.row >= end.row) {
- foldLine.shiftRow(-len);
- }
- }
+ case "auto":
+ return this.$autoNewLine;
+ }
+ };
- 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);
- }
+ this.$autoNewLine = "\n";
+ this.$newLineMode = "auto";
+ /**
+ * Document.setNewLineMode(newLineMode) -> Void
+ * - newLineMode(String): [The newline mode to use; can be either `windows`, `unix`, or `auto`]{: #Document.setNewLineMode.param}
+ *
+ * [Sets the new line mode.]{: #Document.setNewLineMode.desc}
+ **/
+ this.setNewLineMode = function(newLineMode) {
+ if (this.$newLineMode === newLineMode)
+ return;
- // 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;
- }
+ this.$newLineMode = newLineMode;
+ };
- 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.
- var column;
- 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);
+ /**
+ * Document.getNewLineMode() -> String
+ *
+ * [Returns the type of newlines being used; either `windows`, `unix`, or `auto`]{: #Document.getNewLineMode}
+ *
+ **/
+ this.getNewLineMode = function() {
+ return this.$newLineMode;
+ };
- len = -len;
- }
- var foldLine = this.getFoldLine(firstRow);
- if (foldLine) {
- foldLine.addRemoveChars(firstRow, start.column, len);
- }
- }
+ /**
+ * Document.isNewLine(text) -> Boolean
+ * - text (String): The text to check
+ *
+ * Returns `true` if `text` is a newline character (either `\r\n`, `\r`, or `\n`).
+ *
+ **/
+ this.isNewLine = function(text) {
+ return (text == "\r\n" || text == "\r" || text == "\n");
+ };
- if (useWrapMode && this.$wrapData.length != this.doc.getLength()) {
- console.error("doc.getLength() and $wrapData.length have to be the same!");
- }
+ /**
+ * Document.getLine(row) -> String
+ * - row (Number): The row index to retrieve
+ *
+ * Returns a verbatim copy of the given line as it is in the document
+ *
+ **/
+ this.getLine = function(row) {
+ return this.$lines[row] || "";
+ };
- useWrapMode && this.$updateWrapData(firstRow, lastRow);
+ /**
+ * Document.getLines(firstRow, lastRow) -> [String]
+ * - firstRow (Number): The first row index to retrieve
+ * - lastRow (Number): The final row index to retrieve
+ *
+ * Returns an array of strings of the rows between `firstRow` and `lastRow`. This function is inclusive of `lastRow`.
+ *
+ **/
+ this.getLines = function(firstRow, lastRow) {
+ return this.$lines.slice(firstRow, lastRow + 1);
+ };
- return removedFolds;
+ /**
+ * Document.getAllLines() -> [String]
+ *
+ * Returns all lines in the document as string array. Warning: The caller should not modify this array!
+ **/
+ this.getAllLines = function() {
+ return this.getLines(0, this.getLength());
};
- 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;
+ /**
+ * Document.getLength() -> Number
+ *
+ * Returns the number of rows in the document.
+ **/
+ this.getLength = function() {
+ return this.$lines.length;
+ };
- var row = firstRow;
- lastRow = Math.min(lastRow, lines.length - 1);
- while (row <= lastRow) {
- foldLine = this.getFoldLine(row);
- if (!foldLine) {
- tokens = this.$getDisplayTokens(lang.stringTrimRight(lines[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[row] =
- this.$computeWrapSplits(tokens, wrapLimit, tabSize);
+ /**
+ * Document.getTextRange(range) -> String
+ * - range (Range): The range to work with
+ *
+ * [Given a range within the document, this function returns all the text within that range as a single string.]{: #Document.getTextRange.desc}
+ **/
+ 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());
+ }
+ };
- row = this.getRowFoldEnd(row) + 1;
+ /** internal, hide
+ * Document.$clipPosition(position) -> Number
+ *
+ *
+ **/
+ 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;
};
- // "Tokens"
- var CHAR = 1,
- CHAR_EXT = 2,
- PLACEHOLDER_START = 3,
- PLACEHOLDER_BODY = 4,
- SPACE = 10,
- TAB = 11,
- TAB_SPACE = 12;
+ /**
+ * Document.insert(position, text) -> Number
+ * - position (Number): The position to start inserting at
+ * - text (String): A chunk of text to insert
+ * + (Number): The position of the last line of `text`. If the length of `text` is 0, this function simply returns `position`.
+ * Inserts a block of `text` and the indicated `position`.
+ *
+ *
+ **/
+ this.insert = function(position, text) {
+ if (!text || text.length === 0)
+ return position;
- this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) {
- if (tokens.length == 0) {
- return [];
+ 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;
+ };
- var tabSize = this.getTabSize();
- var splits = [];
- var displayLength = tokens.length;
- var lastSplit = 0, lastDocSplit = 0;
+ /**
+ * Document.insertLines(row, lines) -> Object
+ * - row (Number): The index of the row to insert at
+ * - lines (Array): An array of strings
+ * + (Object): Returns an object containing the final row and column, like this:
+ * ```{row: endRow, column: 0}```
+ * If `lines` is empty, this function returns an object containing the current row, and column, like this:
+ * ```{row: row, column: 0}```
+ *
+ * Inserts the elements in `lines` into the document, starting at the row index given by `row`. This method also triggers the `'change'` event.
+ *
+ *
+ **/
+ this.insertLines = function(row, lines) {
+ if (lines.length == 0)
+ return {row: row, column: 0};
- function addSplit(screenPos) {
- var displayed = tokens.slice(lastSplit, screenPos);
+ var args = [row, 0];
+ args.push.apply(args, lines);
+ this.$lines.splice.apply(this.$lines, args);
- // 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(m) {
- len -= 1;
- }).
- // Get all the CHAR_EXT/multipleWidth characters.
- replace(/2/g, function(m) {
- len -= 1;
- });
+ var range = new Range(row, 0, row + lines.length, 0);
+ var delta = {
+ action: "insertLines",
+ range: range,
+ lines: lines
+ };
+ this._emit("change", { data: delta });
+ return range.end;
+ };
- lastDocSplit += len;
- splits.push(lastDocSplit);
- lastSplit = screenPos;
- }
+ /**
+ * Document.insertNewLine(position) -> Object
+ * - position (String): The position to insert at
+ * + (Object): Returns an object containing the final row and column, like this:
+ * ```{row: endRow, column: 0}```
+ *
+ * Inserts a new line into the document at the current row's `position`. This method also triggers the `'change'` event.
+ *
+ *
+ *
+ **/
+ this.insertNewLine = function(position) {
+ position = this.$clipPosition(position);
+ var line = this.$lines[position.row] || "";
- while (displayLength - lastSplit > wrapLimit) {
- // This is, where the split should be.
- var split = lastSplit + wrapLimit;
+ this.$lines[position.row] = line.substring(0, position.column);
+ this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
- // 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;
- }
+ var end = {
+ row : position.row + 1,
+ column : 0
+ };
- // === 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;
- }
- }
+ var delta = {
+ action: "insertText",
+ range: Range.fromPoints(position, end),
+ text: this.getNewLineCharacter()
+ };
+ this._emit("change", { data: delta });
- // If the PLACEHOLDER_START is not the index of the
- // last split, then we can do the split
- if (split > lastSplit) {
- addSplit(split);
- continue;
- }
+ return end;
+ };
- // 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;
- }
- }
+ /**
+ * Document.insertInLine(position, text) -> Object | Number
+ * - position (Number): The position to insert at
+ * - text (String): A chunk of text
+ * + (Object): Returns an object containing the final row and column, like this:
+ * ```{row: endRow, column: 0}```
+ * + (Number): If `text` is empty, this function returns the value of `position`
+ *
+ * Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event.
+ *
+ *
+ *
+ **/
+ this.insertInLine = function(position, text) {
+ if (text.length == 0)
+ return position;
- // 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.
- }
+ var line = this.$lines[position.row] || "";
- // Finally, add the split...
- addSplit(split);
- continue;
- }
+ this.$lines[position.row] = line.substring(0, position.column) + text
+ + line.substring(position.column);
- // === ELSE ===
- // Search for the first non space/tab/placeholder token backwards.
- for (split; split != lastSplit - 1; split--) {
- if (tokens[split] >= PLACEHOLDER_START) {
- split++;
- break;
- }
- }
- // If we found one, then add the split.
- if (split > lastSplit) {
- addSplit(split);
- continue;
- }
+ var end = {
+ row : position.row,
+ column : position.column + text.length
+ };
- // === ELSE ===
- split = lastSplit + wrapLimit;
- // The split is inside of a CHAR or CHAR_EXT token and no space
- // around -> force a split.
- addSplit(lastSplit + wrapLimit);
- }
- return splits;
- }
+ var delta = {
+ action: "insertText",
+ range: Range.fromPoints(position, end),
+ text: text
+ };
+ this._emit("change", { data: delta });
+
+ return end;
+ };
/**
- * @param
- * offset: The offset in screenColumn at which position str starts.
- * Important for calculating the realTabSize.
- */
- this.$getDisplayTokens = function(str, offset) {
- var arr = [];
- var tabSize;
- offset = offset || 0;
+ * Document.remove(range) -> Object
+ * - range (Range): A specified Range to remove
+ * + (Object): Returns the new `start` property of the range, which contains `startRow` and `startColumn`. If `range` is empty, this function returns the unmodified value of `range.start`.
+ *
+ * Removes the `range` from the document.
+ *
+ *
+ **/
+ this.remove = function(range) {
+ // clip to document
+ range.start = this.$clipPosition(range.start);
+ range.end = this.$clipPosition(range.end);
- 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);
- }
- // full width characters
- else if (isFullWidth(c)) {
- arr.push(CHAR, CHAR_EXT);
- } else {
- arr.push(CHAR);
- }
- }
- return arr;
- }
+ if (range.isEmpty())
+ return range.start;
- /**
- * Calculates the width of the a string on the screen while assuming that
- * the string starts at the first column on the screen.
- *
- * @param string str String to calculate the screen width of
- * @return array
- * [0]: number of columns for str on screen.
- * [1]: docColumn position that was read until (useful with screenColumn)
- */
- this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {
- if (maxScreenColumn == 0) {
- return [0, 0];
- }
- if (maxScreenColumn == null) {
- maxScreenColumn = screenColumn +
- str.length * Math.max(this.getTabSize(), 2);
- }
- screenColumn = screenColumn || 0;
+ var firstRow = range.start.row;
+ var lastRow = range.end.row;
- 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 (isFullWidth(c)) {
- screenColumn += 2;
- } else {
- screenColumn += 1;
- }
- if (screenColumn > maxScreenColumn) {
- break
- }
- }
+ if (range.isMultiLine()) {
+ var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
+ var lastFullRow = lastRow - 1;
- return [screenColumn, column];
- }
+ if (range.end.column > 0)
+ this.removeInLine(lastRow, 0, range.end.column);
- /**
- * Returns the number of rows required to render this row on the screen
- */
- this.getRowLength = function(row) {
- if (!this.$useWrapMode || !this.$wrapData[row]) {
- return 1;
- } else {
- return this.$wrapData[row].length + 1;
+ 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;
+ };
/**
- * Returns the height in pixels required to render this row on the screen
- **/
- this.getRowHeight = function(config, row) {
- return this.getRowLength(row) * config.lineHeight;
- }
+ * Document.removeInLine(row, startColumn, endColumn) -> Object
+ * - row (Number): The row to remove from
+ * - startColumn (Number): The column to start removing at
+ * - endColumn (Number): The column to stop removing at
+ * + (Object): Returns an object containing `startRow` and `startColumn`, indicating the new row and column values.
If `startColumn` is equal to `endColumn`, this function returns nothing.
+ *
+ * Removes the specified columns from the `row`. This method also triggers the `'change'` event.
+ *
+ *
+ **/
+ this.removeInLine = function(row, startColumn, endColumn) {
+ if (startColumn == endColumn)
+ return;
- this.getScreenLastRowColumn = function(screenRow) {
- //return this.screenToDocumentColumn(screenRow, Number.MAX_VALUE / 10)
- return this.documentToScreenColumn(screenRow, this.doc.getLine(screenRow).length);
- };
+ 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);
- this.getDocumentLastRowColumn = function(docRow, docColumn) {
- var screenRow = this.documentToScreenRow(docRow, docColumn);
- return this.getScreenLastRowColumn(screenRow);
+ var delta = {
+ action: "removeText",
+ range: range,
+ text: removed
+ };
+ this._emit("change", { data: delta });
+ return range.start;
};
- this.getDocumentLastRowColumnPosition = function(docRow, docColumn) {
- var screenRow = this.documentToScreenRow(docRow, docColumn);
- return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10);
- };
+ /**
+ * Document.removeLines(firstRow, lastRow) -> [String]
+ * - firstRow (Number): The first row to be removed
+ * - lastRow (Number): The last row to be removed
+ * + ([String]): Returns all the removed lines.
+ *
+ * Removes a range of full lines. This method also triggers the `'change'` event.
+ *
+ *
+ **/
+ this.removeLines = function(firstRow, lastRow) {
+ var range = new Range(firstRow, 0, lastRow + 1, 0);
+ var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
- this.getRowSplitData = function(row) {
- if (!this.$useWrapMode) {
- return undefined;
- } else {
- return this.$wrapData[row];
- }
+ var delta = {
+ action: "removeLines",
+ range: range,
+ nl: this.getNewLineCharacter(),
+ lines: removed
+ };
+ this._emit("change", { data: delta });
+ return removed;
};
/**
- * Returns the width of a tab character at screenColumn.
- */
- this.getScreenTabSize = function(screenColumn) {
- return this.$tabSize - screenColumn % this.$tabSize;
- };
+ * Document.removeNewLine(row) -> Void
+ * - row (Number): The row to check
+ *
+ * Removes the new line between `row` and the row immediately following it. This method also triggers the `'change'` event.
+ *
+ **/
+ this.removeNewLine = function(row) {
+ var firstLine = this.getLine(row);
+ var secondLine = this.getLine(row+1);
- this.screenToDocumentRow = function(screenRow, screenColumn) {
- return this.screenToDocumentPosition(screenRow, screenColumn).row;
- };
+ var range = new Range(row, firstLine.length, row+1, 0);
+ var line = firstLine + secondLine;
- this.screenToDocumentColumn = function(screenRow, screenColumn) {
- return this.screenToDocumentPosition(screenRow, screenColumn).column;
- };
+ this.$lines.splice(row, 2, line);
- this.screenToDocumentPosition = function(screenRow, screenColumn) {
- if (screenRow < 0) {
- return {
- row: 0,
- column: 0
- }
- }
-
- var line;
- var docRow = 0;
- var docColumn = 0;
- var column;
- var foldLineRowLength;
- var row = 0;
- var rowLength = 0;
+ var delta = {
+ action: "removeText",
+ range: range,
+ text: this.getNewLineCharacter()
+ };
+ this._emit("change", { data: delta });
+ };
- var rowCache = this.$rowCache;
- for (var i = 0; i < rowCache.length; i++) {
- if (rowCache[i].screenRow < screenRow) {
- row = rowCache[i].screenRow;
- docRow = rowCache[i].docRow;
- }
- else {
- break;
- }
- }
- var doCache = !rowCache.length || i == rowCache.length;
-
- // clamp row before clamping column, for selection on last line
- var maxRow = this.getLength() - 1;
+ /**
+ * Document.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) {
+ if (text.length == 0 && range.isEmpty())
+ return range.start;
- var foldLine = this.getNextFold(docRow);
- var foldStart = foldLine ? foldLine.start.row : Infinity;
+ // 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;
- 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.getNextFold(docRow);
- foldStart = foldLine ? foldLine.start.row : Infinity;
- }
- }
- if (doCache) {
- rowCache.push({
- docRow: docRow,
- screenRow: row
- });
- }
+ this.remove(range);
+ if (text) {
+ var end = this.insert(range.start, text);
}
-
- if (foldLine && foldLine.start.row <= docRow)
- line = this.getFoldDisplayLine(foldLine);
else {
- line = this.getLine(docRow);
- foldLine = null;
- }
-
- var splits = [];
- if (this.$useWrapMode) {
- 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);
- }
- }
+ end = range.start;
}
- docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
+ return end;
+ };
- // clip row at the end of the document
- if (row + splits.length < screenRow)
- docColumn = Number.MAX_VALUE;
+ /**
+ * Document.applyDeltas(deltas) -> Void
+ *
+ * Applies all the changes previously accumulated. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
+ **/
+ this.applyDeltas = function(deltas) {
+ for (var i=0; i= column) {
- // We remove one character at the end such that the docColumn
- // position returned is not associated to the next row on the
- // screen.
- docColumn = column - 1;
- }
- } else {
- docColumn = Math.min(docColumn, line.length);
+ if (delta.action == "insertLines")
+ this.insertLines(range.start.row, delta.lines);
+ else if (delta.action == "insertText")
+ this.insert(range.start, delta.text);
+ else if (delta.action == "removeLines")
+ this.removeLines(range.start.row, range.end.row - 1);
+ else if (delta.action == "removeText")
+ this.remove(range);
}
+ };
- if (foldLine) {
- return foldLine.idxToPosition(docColumn);
- }
-
- return {
- row: docRow,
- column: docColumn
+ /**
+ * Document.revertDeltas(deltas) -> Void
+ *
+ * Reverts any changes previously applied. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
+ **/
+ this.revertDeltas = function(deltas) {
+ for (var i=deltas.length-1; 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);
}
};
- 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);
+}).call(Document.prototype);
- docRow = pos.row;
- docColumn = pos.column;
-
- var LL = this.$rowCache.length;
+exports.Document = Document;
+});
+/* ***** 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 ***** */
- var wrapData;
- // Special case in wrapMode if the doc is at the end of the document.
- if (this.$useWrapMode) {
- wrapData = this.$wrapData;
- if (docRow > wrapData.length - 1) {
- return {
- row: this.getScreenLength(),
- column: wrapData.length == 0
- ? 0
- : (wrapData[wrapData.length - 1].length - 1)
- };
- }
- }
+define('ace/anchor', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
+"use strict";
- var screenRow = 0;
- var screenColumn = 0;
- var foldStartRow = null;
- var fold = null;
+var oop = require("./lib/oop");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+
+/**
+ * class Anchor
+ *
+ * Defines the floating pointer in the document. Whenever text is inserted or deleted before the cursor, the position of the cursor is updated
+ *
+ **/
+
+/**
+ * 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);
- // 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;
- }
+ this.$onChange = this.onChange.bind(this);
+ doc.on("change", this.$onChange);
+};
- var rowEnd, row = 0;
- var rowCache = this.$rowCache;
+(function() {
- for (var i = 0; i < rowCache.length; i++) {
- if (rowCache[i].docRow < docRow) {
- screenRow = rowCache[i].screenRow;
- row = rowCache[i].docRow;
- } else {
- break;
- }
- }
- var doCache = !rowCache.length || i == rowCache.length;
+ oop.implement(this, EventEmitter);
+
+ /**
+ * Anchor.getPosition() -> Object
+ *
+ * Returns an object identifying the `row` and `column` position of the current anchor.
+ *
+ **/
- var foldLine = this.getNextFold(row);
- var foldStart = foldLine ?foldLine.start.row :Infinity;
+ this.getPosition = function() {
+ return this.$clipPositionToDocument(this.row, this.column);
+ };
+
+ /**
+ * Anchor.getDocument() -> Document
+ *
+ * Returns the current document.
+ *
+ **/
+
+ this.getDocument = function() {
+ return this.document;
+ };
+
+ /**
+ * Anchor@onChange(e)
+ * - e (Event): Contains data about the event
+ *
+ * Fires whenever the anchor position changes. Events that can trigger this function include `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
+ *
+ **/
- while (row < docRow) {
- if (row >= foldStart) {
- rowEnd = foldLine.end.row + 1;
- if (rowEnd > docRow)
- break;
- foldLine = this.getNextFold(rowEnd);
- foldStart = foldLine ?foldLine.start.row :Infinity;
+ 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 {
- rowEnd = row + 1;
+ else if (range.start.row !== range.end.row && range.start.row < row) {
+ row += range.end.row - range.start.row;
}
-
- screenRow += this.getRowLength(row);
- row = rowEnd;
-
- if (doCache) {
- rowCache.push({
- docRow: row,
- screenRow: screenRow
- });
+ } else if (delta.action === "insertLines") {
+ if (range.start.row <= row) {
+ row += range.end.row - range.start.row;
}
}
-
- // 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 = wrapData[foldStartRow];
- var screenRowOffset = 0;
- while (textLine.length >= wrapRow[screenRowOffset]) {
- screenRow ++;
- screenRowOffset++;
+ 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;
+ }
}
- textLine = textLine.substring(
- wrapRow[screenRowOffset - 1] || 0, textLine.length
- );
}
- return {
- row: screenRow,
- column: this.$getStringScreenWidth(textLine)[0]
- };
+ this.setPosition(row, column, true);
};
- this.documentToScreenColumn = function(row, docColumn) {
- return this.documentToScreenPosition(row, docColumn).column;
- };
+ /**
+ * Anchor.setPosition(row, column, noClip)
+ * - row (Number): The row index to move the anchor to
+ * - column (Number): The column index to move the anchor to
+ * - noClip (Boolean): Identifies if you want the position to be clipped
+ *
+ * Sets the anchor position to the specified row and column. If `noClip` is `true`, the position is not clipped.
+ *
+ **/
- this.documentToScreenRow = function(docRow, docColumn) {
- return this.documentToScreenPosition(docRow, docColumn).row;
+ 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
+ });
};
+
+ /**
+ * Anchor.detach()
+ *
+ * When called, the `'change'` event listener is removed.
+ *
+ **/
- this.getScreenLength = function() {
- var screenRows = 0;
- var lastFoldLine = null;
- var foldLine = null;
- if (!this.$useWrapMode) {
- screenRows = this.getLength();
+ this.detach = function() {
+ this.document.removeEventListener("change", this.$onChange);
+ };
+
+ /** internal, hide
+ * Anchor.clipPositionToDocument(row, column)
+ * - row (Number): The row index to clip the anchor to
+ * - column (Number): The column index to clip the anchor to
+ *
+ * Clips the anchor position to the specified row and column.
+ *
+ **/
- // Remove the folded lines again.
- var foldData = this.$foldData;
- for (var i = 0; i < foldData.length; i++) {
- foldLine = foldData[i];
- screenRows -= foldLine.end.row - foldLine.start.row;
- }
- } else {
- for (var row = 0; row < this.$wrapData.length; row++) {
- if (foldLine = this.getFoldLine(row, lastFoldLine)) {
- row = foldLine.end.row;
- screenRows += 1;
- } else {
- screenRows += this.$wrapData[row].length + 1;
- }
- }
+ 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;
}
-
- 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;
+ 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);
-}).call(EditSession.prototype);
-
-require("ace/edit_session/folding").Folding.call(EditSession.prototype);
-
-exports.EditSession = EditSession;
});
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -9567,7 +12074,6 @@ exports.EditSession = EditSession;
*
* Contributor(s):
* Fabian Jakobs
- * Julian Viereck
*
* 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
@@ -9583,753 +12089,984 @@ exports.EditSession = EditSession;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/selection', ['require', 'exports', 'module' , 'pilot/oop', 'pilot/lang', 'pilot/event_emitter', 'ace/range'], function(require, exports, module) {
+define('ace/background_tokenizer', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
+"use strict";
-var oop = require("pilot/oop");
-var lang = require("pilot/lang");
-var EventEmitter = require("pilot/event_emitter").EventEmitter;
-var Range = require("ace/range").Range;
+var oop = require("./lib/oop");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
/**
- * Keeps cursor position and the text selection of an edit session.
- *
- * The row/columns used in the selection are in document coordinates
- * representing ths coordinates as thez appear in the document
- * before applying soft wrap and folding.
- */
-var Selection = function(session) {
- this.session = session;
- this.doc = session.getDocument();
-
- this.clearSelection();
- this.selectionLead = this.doc.createAnchor(0, 0);
- this.selectionAnchor = this.doc.createAnchor(0, 0);
-
- var _self = this;
- this.selectionLead.on("change", function(e) {
- _self._dispatchEvent("changeCursor");
- if (!_self.$isEmpty)
- _self._dispatchEvent("changeSelection");
- if (!_self.$preventUpdateDesiredColumnOnChange && e.old.column != e.value.column)
- _self.$updateDesiredColumn();
- });
-
- this.selectionAnchor.on("change", function() {
- if (!_self.$isEmpty)
- _self._dispatchEvent("changeSelection");
- });
-};
+ * class BackgroundTokenizer
+ *
+ * Tokenizes the current [[Document `Document`]] in the background, and caches the tokenized rows for future use. If a certain row is changed, everything below that row is re-tokenized.
+ *
+ **/
-(function() {
+/**
+ * new BackgroundTokenizer(tokenizer, editor)
+ * - tokenizer (Tokenizer): The tokenizer to use
+ * - editor (Editor): The editor to associate with
+ *
+ * Creates a new `BackgroundTokenizer` object.
+ *
+ *
+ **/
- oop.implement(this, EventEmitter);
+var BackgroundTokenizer = function(tokenizer, editor) {
+ this.running = false;
+ this.lines = [];
+ this.currentLine = 0;
+ this.tokenizer = tokenizer;
- this.isEmpty = function() {
- return (this.$isEmpty || (
- this.selectionAnchor.row == this.selectionLead.row &&
- this.selectionAnchor.column == this.selectionLead.column
- ));
- };
+ var self = this;
- this.isMultiLine = function() {
- if (this.isEmpty()) {
- return false;
- }
+ this.$worker = function() {
+ if (!self.running) { return; }
- return this.getRange().isMultiLine();
- };
+ var workerStart = new Date();
+ var startLine = self.currentLine;
+ var doc = self.doc;
- this.getCursor = function() {
- return this.selectionLead.getPosition();
- };
+ var processedLines = 0;
- this.setSelectionAnchor = function(row, column) {
- this.selectionAnchor.setPosition(row, column);
+ var len = doc.getLength();
+ while (self.currentLine < len) {
+ self.lines[self.currentLine] = self.$tokenizeRows(self.currentLine, self.currentLine)[0];
+ self.currentLine++;
- if (this.$isEmpty) {
- this.$isEmpty = false;
- this._dispatchEvent("changeSelection");
+ // only check every 5 lines
+ processedLines += 1;
+ if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) {
+ self.fireUpdateEvent(startLine, self.currentLine-1);
+ self.running = setTimeout(self.$worker, 20);
+ return;
+ }
}
- };
- this.getSelectionAnchor = function() {
- if (this.$isEmpty)
- return this.getSelectionLead()
- else
- return this.selectionAnchor.getPosition();
- };
+ self.running = false;
- this.getSelectionLead = function() {
- return this.selectionLead.getPosition();
+ self.fireUpdateEvent(startLine, len - 1);
};
+};
- this.shiftSelection = function(columns) {
- if (this.$isEmpty) {
- this.moveCursorTo(this.selectionLead.row, this.selectionLead.column + columns);
- return;
- };
-
- var anchor = this.getSelectionAnchor();
- var lead = this.getSelectionLead();
+(function(){
- var isBackwards = this.isBackwards();
+ oop.implement(this, EventEmitter);
- if (!isBackwards || anchor.column !== 0)
- this.setSelectionAnchor(anchor.row, anchor.column + columns);
+ /**
+ * BackgroundTokenizer.setTokenizer(tokenizer)
+ * - tokenizer (Tokenizer): The new tokenizer to use
+ *
+ * Sets a new tokenizer for this object.
+ *
+ **/
- if (isBackwards || lead.column !== 0) {
- this.$moveSelection(function() {
- this.moveCursorTo(lead.row, lead.column + columns);
- });
- }
- };
+ this.setTokenizer = function(tokenizer) {
+ this.tokenizer = tokenizer;
+ this.lines = [];
- this.isBackwards = function() {
- var anchor = this.selectionAnchor;
- var lead = this.selectionLead;
- return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));
+ this.start(0);
};
- this.getRange = function() {
- var anchor = this.selectionAnchor;
- var lead = this.selectionLead;
+ /**
+ * BackgroundTokenizer.setDocument(doc)
+ * - doc (Document): The new document to associate with
+ *
+ * Sets a new document to associate with this object.
+ *
+ **/
- if (this.isEmpty())
- return Range.fromPoints(lead, lead);
+ this.setDocument = function(doc) {
+ this.doc = doc;
+ this.lines = [];
- if (this.isBackwards()) {
- return Range.fromPoints(lead, anchor);
- }
- else {
- return Range.fromPoints(anchor, lead);
- }
+ this.stop();
};
- this.clearSelection = function() {
- if (!this.$isEmpty) {
- this.$isEmpty = true;
- this._dispatchEvent("changeSelection");
- }
- };
+ /**
+ * BackgroundTokenizer.fireUpdateEvent(firstRow, lastRow)
+ * - firstRow (Number): The starting row region
+ * - lastRow (Number): The final row region
+ *
+ * Emits the `'update'` event. `firstRow` and `lastRow` are used to define the boundaries of the region to be updated.
+ *
+ **/
- this.selectAll = function() {
- var lastRow = this.doc.getLength() - 1;
- this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length);
- this.moveCursorTo(0, 0);
+ this.fireUpdateEvent = function(firstRow, lastRow) {
+ var data = {
+ first: firstRow,
+ last: lastRow
+ };
+ this._emit("update", {data: data});
};
- 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.$updateDesiredColumn();
- };
+ /**
+ * BackgroundTokenizer.start(startRow)
+ * - startRow (Number): The row to start at
+ *
+ * Starts tokenizing at the row indicated.
+ *
+ **/
- this.$updateDesiredColumn = function() {
- var cursor = this.getCursor();
- this.$desiredColumn = this.session.documentToScreenColumn(cursor.row, cursor.column);
- };
+ this.start = function(startRow) {
+ this.currentLine = Math.min(startRow || 0, this.currentLine,
+ this.doc.getLength());
- this.$moveSelection = function(mover) {
- var lead = this.selectionLead;
- if (this.$isEmpty)
- this.setSelectionAnchor(lead.row, lead.column);
+ // remove all cached items below this line
+ this.lines.splice(this.currentLine, this.lines.length);
- mover.call(this);
+ this.stop();
+ // pretty long delay to prevent the tokenizer from interfering with the user
+ this.running = setTimeout(this.$worker, 700);
};
- this.selectTo = function(row, column) {
- this.$moveSelection(function() {
- this.moveCursorTo(row, column);
- });
- };
+ /**
+ * BackgroundTokenizer.stop()
+ *
+ * Stops tokenizing.
+ *
+ **/
- this.selectToPosition = function(pos) {
- this.$moveSelection(function() {
- this.moveCursorToPosition(pos);
- });
+ this.stop = function() {
+ if (this.running)
+ clearTimeout(this.running);
+ this.running = false;
};
- this.selectUp = function() {
- this.$moveSelection(this.moveCursorUp);
- };
+ /** related to: BackgroundTokenizer.$tokenizeRows
+ * BackgroundTokenizer.getTokens(firstRow, lastRow) -> [Object]
+ * - firstRow (Number): The row to start at
+ * - lastRow (Number): The row to finish at
+ *
+ * Starts tokenizing at the row indicated. Returns a list of objects of the tokenized rows.
+ *
+ **/
- this.selectDown = function() {
- this.$moveSelection(this.moveCursorDown);
+ this.getTokens = function(firstRow, lastRow) {
+ return this.$tokenizeRows(firstRow, lastRow);
};
- this.selectRight = function() {
- this.$moveSelection(this.moveCursorRight);
- };
+ /**
+ * BackgroundTokenizer.getState(row) -> String
+ * - row (Number): The row to start at
+ *
+ * [Returns the state of tokenization for a row.]{: #BackgroundTokenizer.getState}
+ *
+ **/
- this.selectLeft = function() {
- this.$moveSelection(this.moveCursorLeft);
+ this.getState = function(row) {
+ return this.$tokenizeRows(row, row)[0].state;
};
- this.selectLineStart = function() {
- this.$moveSelection(this.moveCursorLineStart);
- };
+ /**
+ * BackgroundTokenizer.$tokenizeRows(firstRow, lastRow) -> [Object]
+ * - startRow (Number): The row to start at
+ * - lastRow (Number): The row to finish at
+ * + ([Object]): A list of the tokenized rows. Each item in the list is an object with two properties, `state` and `start`.
+ *
+ * Tokenizes all the rows within the specified region.
+ *
+ *
+ **/
+ this.$tokenizeRows = function(firstRow, lastRow) {
+ if (!this.doc || isNaN(firstRow) || isNaN(lastRow))
+ return [{'state':'start','tokens':[]}];
+
+ var rows = [];
- this.selectLineEnd = function() {
- this.$moveSelection(this.moveCursorLineEnd);
- };
+ // determine start state
+ var state = "start";
+ var doCache = false;
+ if (firstRow > 0 && this.lines[firstRow - 1]) {
+ state = this.lines[firstRow - 1].state;
+ doCache = true;
+ } else if (firstRow == 0) {
+ state = "start";
+ doCache = true;
+ } else if (this.lines.length > 0) {
+ // Guess that we haven't changed state.
+ state = this.lines[this.lines.length-1].state;
+ }
- this.selectFileEnd = function() {
- this.$moveSelection(this.moveCursorFileEnd);
+ var lines = this.doc.getLines(firstRow, lastRow);
+ for (var row=firstRow; row<=lastRow; row++) {
+ if (!this.lines[row]) {
+ var tokens = this.tokenizer.getLineTokens(lines[row-firstRow] || "", state);
+ var state = tokens.state;
+ rows.push(tokens);
+
+ if (doCache) {
+ this.lines[row] = tokens;
+ }
+ }
+ else {
+ var tokens = this.lines[row];
+ state = tokens.state;
+ rows.push(tokens);
+ }
+ }
+ return rows;
};
- this.selectFileStart = function() {
- this.$moveSelection(this.moveCursorFileStart);
- };
+}).call(BackgroundTokenizer.prototype);
- this.selectWordRight = function() {
- this.$moveSelection(this.moveCursorWordRight);
- };
+exports.BackgroundTokenizer = BackgroundTokenizer;
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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):
+ * Julian Viereck
+ *
+ * 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 ***** */
- this.selectWordLeft = function() {
- this.$moveSelection(this.moveCursorWordLeft);
- };
+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) {
+"use strict";
- this.selectWord = function() {
- var cursor = this.getCursor();
- var range = this.session.getWordRange(cursor.row, cursor.column);
- this.setSelectionRange(range);
- };
+var Range = require("../range").Range;
+var FoldLine = require("./fold_line").FoldLine;
+var Fold = require("./fold").Fold;
+var TokenIterator = require("../token_iterator").TokenIterator;
- this.selectLine = function() {
- var rowStart = this.selectionLead.row;
- var rowEnd;
+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 foldLine = this.session.getFoldLine(rowStart);
- if (foldLine) {
- rowStart = foldLine.start.row;
- rowEnd = foldLine.end.row;
- } else {
- rowEnd = rowStart;
+ 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.setSelectionAnchor(rowStart, 0);
- this.$moveSelection(function() {
- this.moveCursorTo(rowEnd + 1, 0);
- });
- };
-
- this.moveCursorUp = function() {
- this.moveCursorBy(-1, 0);
};
- this.moveCursorDown = function() {
- this.moveCursorBy(1, 0);
- };
+ /*
+ * Returns all folds in the given range. Note, that this will return folds
+ *
+ */
+ this.getFoldsInRange = function(range) {
+ range = range.clone();
+ var start = range.start;
+ var end = range.end;
+ var foldLines = this.$foldData;
+ var foundFolds = [];
- this.moveCursorLeft = function() {
- var cursor = this.selectionLead.getPosition(),
- fold;
+ start.column += 1;
+ end.column -= 1;
- 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);
+ 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;
}
- }
- 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.selectionLead.getPosition(),
- fold;
- if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) {
- this.moveCursorTo(fold.end.row, fold.end.column);
- }
- else if (this.selectionLead.column == this.doc.getLine(this.selectionLead.row).length) {
- if (this.selectionLead.row < this.doc.getLength() - 1) {
- this.moveCursorTo(this.selectionLead.row + 1, 0);
+ 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);
}
}
- else {
- var tabSize = this.session.getTabSize();
- var cursor = this.selectionLead;
- 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);
+ return foundFolds;
+ };
+
+ /*
+ * Returns all folds in the document
+ */
+ 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.moveCursorLineStart = function() {
- var row = this.selectionLead.row;
- var column = this.selectionLead.column;
- var screenRow = this.session.documentToScreenRow(row, column);
+ /*
+ * Returns the string between folds at the given position.
+ * E.g.
+ * foob|arwolrd -> "bar"
+ * foobarwol|rd -> "world"
+ * foobarwolrd ->
+ *
+ * where | means the position of row/column
+ *
+ * The trim option determs if the return string should be trimed according
+ * to the "side" passed with the trim value:
+ *
+ * E.g.
+ * foob|arwolrd -trim=-1> "b"
+ * foobarwol|rd -trim=+1> "rld"
+ * fo|obarwolrd -trim=00> "foo"
+ */
+ this.getFoldStringAt = function(row, column, trim, foldLine) {
+ foldLine = foldLine || this.getFoldLine(row);
+ if (!foldLine)
+ return null;
- // Determ the doc-position of the first character at the screen line.
- var firstColumnPosition = this.session.screenToDocumentPosition(screenRow, 0);
+ 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);
- // Determ the line
- var beforeCursor = this.session.getDisplayLine(
- row, null,
- firstColumnPosition.row, firstColumnPosition.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;
+ };
- 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.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;
};
- this.moveCursorLineEnd = function() {
- var lead = this.selectionLead;
- var lastRowColumnPosition =
- this.session.getDocumentLastRowColumnPosition(lead.row, lead.column);
- this.moveCursorTo(
- lastRowColumnPosition.row,
- lastRowColumnPosition.column
- );
+ // 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.moveCursorFileEnd = function() {
- var row = this.doc.getLength() - 1;
- var column = this.doc.getLine(row).length;
- this.moveCursorTo(row, column);
+ 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.moveCursorFileStart = function() {
- this.moveCursorTo(0, 0);
+ this.$addFoldLine = function(foldLine) {
+ this.$foldData.push(foldLine);
+ this.$foldData.sort(function(a, b) {
+ return a.start.row - b.start.row;
+ });
+ return foldLine;
};
- this.moveCursorWordRight = function() {
- var row = this.selectionLead.row;
- var column = this.selectionLead.column;
- var line = this.doc.getLine(row);
- var rightOfCursor = line.substring(column);
+ /*
+ * Adds a new fold.
+ *
+ * @returns
+ * The new created Fold object or an existing fold object in case the
+ * passed in range fits an existing fold exactly.
+ */
+ 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);
- var match;
- this.session.nonTokenRe.lastIndex = 0;
- this.session.tokenRe.lastIndex = 0;
+ this.$clipRangeToDocument(fold.range);
- var fold;
- if (fold = this.session.getFoldAt(row, column, 1)) {
- this.moveCursorTo(fold.end.row, fold.end.column);
- return;
- } else if (column == line.length) {
- this.moveCursorRight();
- return;
- }
- else if (match = this.session.nonTokenRe.exec(rightOfCursor)) {
- column += this.session.nonTokenRe.lastIndex;
- this.session.nonTokenRe.lastIndex = 0;
- }
- else if (match = this.session.tokenRe.exec(rightOfCursor)) {
- column += this.session.tokenRe.lastIndex;
- this.session.tokenRe.lastIndex = 0;
- }
+ var startRow = fold.start.row;
+ var startColumn = fold.start.column;
+ var endRow = fold.end.row;
+ var endColumn = fold.end.column;
- this.moveCursorTo(row, column);
- };
+ // --- Some checking ---
+ if (fold.placeholder.length < 2)
+ throw "Placeholder has to be at least 2 characters";
- this.moveCursorWordLeft = function() {
- var row = this.selectionLead.row;
- var column = this.selectionLead.column;
+ if (startRow == endRow && endColumn - startColumn < 2)
+ throw "The range has to be at least 2 characters width";
- var fold;
- if (fold = this.session.getFoldAt(row, column, -1)) {
- this.moveCursorTo(fold.start.row, fold.start.column);
- return;
- }
+ var startFold = this.getFoldAt(startRow, startColumn, 1);
+ var endFold = this.getFoldAt(endRow, endColumn, -1);
+ if (startFold && endFold == startFold)
+ return startFold.addSubFold(fold);
- if (column == 0) {
- this.moveCursorLeft();
- return;
+ 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;
}
- var str = this.session.getFoldStringAt(row, column, -1);
- if (str == null) {
- str = this.doc.getLine(row).substring(0, column)
+ // 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;
}
- var leftOfCursor = lang.stringReverse(str);
-
- var match;
- this.session.nonTokenRe.lastIndex = 0;
- this.session.tokenRe.lastIndex = 0;
- if (match = this.session.nonTokenRe.exec(leftOfCursor)) {
- column -= this.session.nonTokenRe.lastIndex;
- this.session.nonTokenRe.lastIndex = 0;
- }
- else if (match = this.session.tokenRe.exec(leftOfCursor)) {
- column -= this.session.tokenRe.lastIndex;
- this.session.tokenRe.lastIndex = 0;
+ 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;
+ }
}
- this.moveCursorTo(row, column);
- };
+ if (!added)
+ foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));
- this.moveCursorBy = function(rows, chars) {
- var screenPos = this.session.documentToScreenPosition(
- this.selectionLead.row,
- this.selectionLead.column
- );
- var screenCol = (chars == 0 && this.$desiredColumn) || screenPos.column;
- var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenCol);
- this.moveCursorTo(docPos.row, docPos.column + chars, chars == 0);
- };
+ if (this.$useWrapMode)
+ this.$updateWrapData(foldLine.start.row, foldLine.start.row);
- this.moveCursorToPosition = function(position) {
- this.moveCursorTo(position.row, position.column);
- };
+ // Notify that fold data has changed.
+ this.$modified = true;
+ this._emit("changeFold", { data: fold });
- this.moveCursorTo = function(row, column, preventUpdateDesiredColumn) {
- // 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.$preventUpdateDesiredColumnOnChange = true;
- this.selectionLead.setPosition(row, column);
- this.$preventUpdateDesiredColumnOnChange = false;
-
- if (!preventUpdateDesiredColumn)
- this.$updateDesiredColumn(this.selectionLead.column);
+ return fold;
};
- this.moveCursorToScreen = function(row, column, preventUpdateDesiredColumn) {
- var pos = this.session.screenToDocumentPosition(row, column);
- row = pos.row;
- column = pos.column;
- this.moveCursorTo(row, column, preventUpdateDesiredColumn);
+ this.addFolds = function(folds) {
+ folds.forEach(function(fold) {
+ this.addFold(fold);
+ }, this);
};
-}).call(Selection.prototype);
+ this.removeFold = function(fold) {
+ var foldLine = fold.foldLine;
+ var startRow = foldLine.start.row;
+ var endRow = foldLine.end.row;
-exports.Selection = Selection;
-});
-/* ***** 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 ***** */
+ 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;
+ }
-define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) {
+ if (this.$useWrapMode) {
+ this.$updateWrapData(startRow, endRow);
+ }
-var Range = function(startRow, startColumn, endRow, endColumn) {
- this.start = {
- row: startRow,
- column: startColumn
+ // Notify that fold data has changed.
+ this.$modified = true;
+ this._emit("changeFold", { data: fold });
};
- this.end = {
- row: endRow,
- column: endColumn
+ 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;
};
-};
-(function() {
-
- this.toString = function() {
- return ("Range: [" + this.start.row + "/" + this.start.column +
- "] -> [" + this.end.row + "/" + this.end.column + "]");
+ this.expandFold = function(fold) {
+ this.removeFold(fold);
+ fold.subFolds.forEach(function(fold) {
+ this.addFold(fold);
+ }, this);
+ fold.subFolds = [];
};
- this.contains = function(row, column) {
- return this.compare(row, column) == 0;
+ this.expandFolds = function(folds) {
+ folds.forEach(function(fold) {
+ this.expandFold(fold);
+ }, this);
};
- /**
- * Compares this range (A) with another range (B), where B is the passed in
- * range.
- *
- * Return values:
- * -2: (B) is infront of (A) and doesn't intersect with (A)
- * -1: (B) begins before (A) but ends inside of (A)
- * 0: (B) is completly inside of (A) OR (A) is complety inside of (B)
- * +1: (B) begins inside of (A) but ends outside of (A)
- * +2: (B) is after (A) and doesn't intersect with (A)
- *
- * 42: FTW state: (B) ends in (A) but starts outside of (A)
- */
- this.compareRange = function(range) {
- var cmp,
- end = range.end,
- start = range.start;
+ 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;
- 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;
+ folds = this.getFoldsInRange(range);
+ if (expandInner) {
+ this.removeFolds(folds);
} else {
- cmp = this.compare(start.row, start.column);
- if (cmp == -1) {
- return -1;
- } else if (cmp == 1) {
- return 42;
- } else {
- return 0;
+ // 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.containsRange = function(range) {
- var cmp = this.compareRange(range);
- return (cmp == -1 || cmp == 0 || cmp == 1);
- }
+ };
- this.isEnd = function(row, column) {
- return this.end.row == row && this.end.column == column;
- }
+ /*
+ * Checks if a given documentRow is folded. This is true if there are some
+ * folded parts such that some parts of the line is still visible.
+ **/
+ this.isRowFolded = function(docRow, startFoldRow) {
+ return !!this.getFoldLine(docRow, startFoldRow);
+ };
- this.isStart = function(row, column) {
- return this.start.row == row && this.start.column == column;
- }
+ this.getRowFoldEnd = function(docRow, startFoldRow) {
+ var foldLine = this.getFoldLine(docRow, startFoldRow);
+ return (foldLine
+ ? foldLine.end.row
+ : docRow);
+ };
- 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;
+ this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) {
+ if (startRow == null) {
+ startRow = foldLine.start.row;
+ startColumn = 0;
}
- }
- 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;
+ if (endRow == null) {
+ endRow = foldLine.end.row;
+ endColumn = this.getLine(endRow).length;
}
- }
- 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;
- }
+ // Build the textline using the FoldLine walker.
+ var doc = this.doc;
+ var textLine = "";
- this.insideStart = function(row, column) {
- if (this.compare(row, column) == 0) {
- if (this.isEnd(row, column)) {
- return false;
- } else {
- return true;
+ foldLine.walk(function(placeholder, row, column, lastColumn) {
+ if (row < startRow) {
+ return;
+ } else if (row == startRow) {
+ if (column < startColumn) {
+ return;
+ }
+ lastColumn = Math.max(startColumn, lastColumn);
}
- }
- return false;
- }
-
- this.insideEnd = function(row, column) {
- if (this.compare(row, column) == 0) {
- if (this.isStart(row, column)) {
- return false;
+ if (placeholder) {
+ textLine += placeholder;
} else {
- return true;
+ textLine += doc.getLine(row).substring(lastColumn, column);
}
- }
- return false;
- }
+ }.bind(this), endRow, endColumn);
+ return textLine;
+ };
- 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);
- };
+ 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);
}
+ };
- if (row < this.start.row)
- return -1;
+ 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);
+ });
- if (row > this.end.row)
- return 1;
+ return fd;
+ };
- if (this.start.row === row)
- return column >= this.start.column ? 0 : -1;
+ this.toggleFold = function(tryToUnfold) {
+ var selection = this.selection;
+ var range = selection.getRange();
+ var fold;
+ var bracketPos;
- if (this.end.row === row)
- return column <= this.end.column ? 0 : 1;
+ if (range.isEmpty()) {
+ var cursor = range.start;
+ fold = this.getFoldAt(cursor.row, cursor.column);
- return 0;
- };
+ 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;
- /**
- * Like .compare(), but if isStart is true, return -1;
- */
- this.compareStart = function(row, column) {
- if (this.start.row == row && this.start.column == column) {
- return -1;
+ range.start.column++;
+ }
+ else {
+ range = this.getCommentFoldRange(cursor.row, cursor.column) || range;
+ }
} else {
- return this.compare(row, column);
+ var folds = this.getFoldsInRange(range);
+ if (tryToUnfold && folds.length) {
+ this.expandFolds(folds);
+ return;
+ }
+ else if (folds.length == 1 ) {
+ fold = folds[0];
+ }
}
- }
- /**
- * Like .compare(), but if isEnd is true, return 1;
- */
- this.compareEnd = function(row, column) {
- if (this.end.row == row && this.end.column == column) {
- return 1;
- } else {
- return this.compare(row, column);
- }
- }
+ if (!fold)
+ fold = this.getFoldAt(range.start.row, range.start.column);
- 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);
+ if (fold && fold.range.toString() == range.toString()) {
+ this.expandFold(fold);
+ return;
}
- }
- this.clipRows = function(firstRow, lastRow) {
- if (this.end.row > lastRow) {
- var end = {
- row: lastRow+1,
- column: 0
- };
+ var placeholder = "...";
+ if (!range.isMultiLine()) {
+ placeholder = this.getTextRange(range);
+ if(placeholder.length < 4)
+ return;
+ placeholder = placeholder.trim().substring(0, 2) + "..";
}
- if (this.start.row > lastRow) {
- var start = {
- row: lastRow+1,
- column: 0
- };
- }
+ this.addFold(placeholder, range);
+ };
- if (this.start.row < firstRow) {
- var start = {
- row: firstRow,
- column: 0
- };
- }
+ 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));
- if (this.end.row < firstRow) {
- var end = {
- row: firstRow,
- column: 0
- };
+ 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;
}
- 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};
+ 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;
- return Range.fromPoints(start || this.start, end || this.end);
+ 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.isEmpty = function() {
- return (this.start.row == this.end.row && this.start.column == this.end.column);
+ this.$foldStyle = style;
+
+ if (style == "manual")
+ this.unfold();
+
+ // reset folding
+ var mode = this.$foldMode;
+ this.$setFolding(null);
+ this.$setFolding(mode);
};
- this.isMultiLine = function() {
- return (this.start.row !== this.end.row);
+ // 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.clone = function() {
- return Range.fromPoints(this.start, this.end);
- };
+ 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;
- 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)
+ if (type == "end")
+ fold = this.getFoldAt(row, 0, -1);
else
- return new Range(this.start.row, 0, this.end.row, 0)
- };
+ fold = this.getFoldAt(row, line.length, 1);
- this.toScreenRange = function(session) {
- var screenPosStart =
- session.documentToScreenPosition(this.start);
- var screenPosEnd =
- session.documentToScreenPosition(this.end);
+ if (fold) {
+ if (addSubfolds)
+ this.removeFold(fold);
+ else
+ this.expandFold(fold);
+ return;
+ }
- return new Range(
- screenPosStart.row, screenPosStart.column,
- screenPosEnd.row, screenPosEnd.column
- );
+ 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.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;
-}).call(Range.prototype);
+ 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);
+ }
+ };
+}
-Range.fromPoints = function(start, end) {
- return new Range(start.row, start.column, end.row, end.column);
-};
+exports.Folding = Folding;
-exports.Range = Range;
});
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
@@ -10353,9 +13090,7 @@ exports.Range = Range;
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Fabian Jakobs
- * Mihai Sucan
- * Chris Spencer
+ * Julian Viereck
*
* 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
@@ -10371,188 +13106,246 @@ exports.Range = Range;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/mode/text', ['require', 'exports', 'module' , 'ace/tokenizer', 'ace/mode/text_highlight_rules', 'ace/mode/behaviour', 'ace/unicode'], function(require, exports, module) {
+define('ace/edit_session/fold_line', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
+"use strict";
-var Tokenizer = require("ace/tokenizer").Tokenizer;
-var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
-var Behaviour = require("ace/mode/behaviour").Behaviour;
-var unicode = require("ace/unicode");
+var Range = require("../range").Range;
-var Mode = function() {
- this.$tokenizer = new Tokenizer(new TextHighlightRules().getRules());
- this.$behaviour = new Behaviour();
-};
+/*
+ * If an array is passed in, the folds are expected to be sorted already.
+ */
+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.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.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.getTokenizer = function() {
- return this.$tokenizer;
- };
+ this.containsRow = function(row) {
+ return row >= this.start.row && row <= this.end.row;
+ }
- this.toggleCommentLines = function(state, doc, startRow, endRow) {
- };
+ this.walk = function(callback, endRow, endColumn) {
+ var lastEnd = 0,
+ folds = this.folds,
+ fold,
+ comp, stop, isNewRow = true;
- this.getNextLineIndent = function(state, line, tab) {
- return "";
- };
+ if (endRow == null) {
+ endRow = this.end.row;
+ endColumn = this.end.column;
+ }
- this.checkOutdent = function(state, line, input) {
- return false;
- };
+ for (var i = 0; i < folds.length; i++) {
+ fold = folds[i];
- this.autoOutdent = function(state, doc, row) {
- };
+ comp = fold.range.compareStart(endRow, endColumn);
+ // This fold is after the endRow/Column.
+ if (comp == -1) {
+ callback(null, endRow, endColumn, lastEnd, isNewRow);
+ return;
+ }
- this.$getIndent = function(line) {
- var match = line.match(/^(\s+)/);
- if (match) {
- return match[1];
- }
+ stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow);
+ stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd);
- return "";
- };
-
- this.createWorker = function(session) {
- return null;
- };
+ // 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;
+ }
- this.highlightSelection = function(editor) {
- var session = editor.session;
- if (!session.$selectionOccurrences)
- session.$selectionOccurrences = [];
+ // 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);
+ }
- if (session.$selectionOccurrences.length)
- this.clearSelectionHighlight(editor);
+ 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;
+ }
- var selection = editor.getSelectionRange();
- if (selection.isEmpty() || selection.isMultiLine())
- return;
+ 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;
+ }
+ }
+ }
- 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));
+ this.split = function(row, column) {
+ var fold = this.getNextFoldTo(row, column).fold,
+ folds = this.folds;
+ var foldData = this.foldData;
- // 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;
+ 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;
- needle = line.substring(selection.start.column, selection.end.column);
- if (!/^[\w\d]+$/.test(needle))
- return;
+ // Remove the folds after row/column and create a new FoldLine
+ // containing these removed folds.
+ folds = folds.splice(i, folds.length - i);
- var cursor = editor.getCursorPosition();
+ var newFoldLine = new FoldLine(foldData, folds);
+ foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);
+ return newFoldLine;
+ }
- var newOptions = {
- wrap: true,
- wholeWord: true,
- caseSensitive: true,
- needle: needle
- };
+ 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);
+ }
- var currentOptions = editor.$search.getOptions();
- editor.$search.set(newOptions);
+ this.toString = function() {
+ var ret = [this.range.toString() + ": [" ];
- var ranges = editor.$search.findAll(session);
- ranges.forEach(function(range) {
- if (!range.contains(cursor.row, cursor.column)) {
- var marker = session.addMarker(range, "ace_selected_word", "text");
- session.$selectionOccurrences.push(marker);
- }
+ this.folds.forEach(function(fold) {
+ ret.push(" " + fold.toString());
});
+ ret.push("]")
+ return ret.join("\n");
+ }
- editor.$search.set(currentOptions);
- };
-
- this.clearSelectionHighlight = function(editor) {
- if (!editor.session.$selectionOccurrences)
- return;
+ this.idxToPosition = function(idx) {
+ var lastFoldEndColumn = 0;
+ var fold;
- editor.session.$selectionOccurrences.forEach(function(marker) {
- editor.session.removeMarker(marker);
- });
+ for (var i = 0; i < this.folds.length; i++) {
+ var fold = this.folds[i];
- editor.session.$selectionOccurrences = [];
- };
-
- 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]]();
+ idx -= fold.start.column - lastFoldEndColumn;
+ if (idx < 0) {
+ return {
+ row: fold.start.row,
+ column: fold.start.column + idx
+ };
}
- }
-
- 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 !== false) {
- return ret;
- }
- }
+ idx -= fold.placeholder.length;
+ if (idx < 0) {
+ return fold.start;
}
+
+ lastFoldEndColumn = fold.end.column;
}
- return false;
+
+ return {
+ row: this.end.row,
+ column: this.end.column + idx
+ };
}
-
-}).call(Mode.prototype);
+}).call(FoldLine.prototype);
-exports.Mode = Mode;
+exports.FoldLine = FoldLine;
});
-/* ***** BEGIN LICENSE BLOCK *****
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
@@ -10573,7 +13366,7 @@ exports.Mode = Mode;
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Fabian Jakobs
+ * Julian Viereck
*
* 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
@@ -10589,135 +13382,86 @@ exports.Mode = Mode;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/tokenizer', ['require', 'exports', 'module' ], function(require, exports, module) {
-
-var Tokenizer = function(rules) {
- this.rules = rules;
+define('ace/edit_session/fold', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
- 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++) {
- // 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);
- });
-
- mapping[matchTotal] = {
- rule: i,
- len: matchcount
- };
- matchTotal += matchcount;
-
- ruleRegExps.push(adjustedregex);
- }
+/*
+ * 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.regExps[key] = new RegExp("(?:(" + ruleRegExps.join(")|(") + ")|(.))", "g");
- }
+ this.sameRow = range.start.row == range.end.row;
+ this.subFolds = [];
};
(function() {
- this.getLineTokens = function(line, startState) {
- var currentState = startState;
- 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]];
+ this.toString = function() {
+ return '"' + this.placeholder + '" ' + this.range.toString();
+ };
- for (var i = 0; i < match.length-2; i++) {
- if (match[i + 1] !== undefined) {
- 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;
+ 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;
+ };
- var next = rule.next;
- if (next && next !== currentState) {
- currentState = next;
- state = this.rules[currentState];
- mapping = this.matchMappings[currentState];
- lastIndex = re.lastIndex;
+ this.addSubFold = function(fold) {
+ if (this.range.isEqual(fold))
+ return this;
- re = this.regExps[currentState];
- re.lastIndex = lastIndex;
- }
- break;
- }
- };
+ if (!this.range.containsRange(fold))
+ throw "A fold can't intersect already existing fold" + fold.range + this.range;
- if (value[0]) {
- if (typeof type == "string") {
- value = [value.join("")];
- type = [type];
- }
- for (var i = 0; i < value.length; i++) {
- 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)
+ 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;
-
- lastIndex = re.lastIndex;
- };
+ }
+ var afterStart = this.subFolds[i];
- if (token.type)
- tokens.push(token);
+ if (cmp == 0)
+ return afterStart.addSubFold(fold)
- return {
- tokens : tokens,
- state : currentState
- };
- };
+ // 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];
-}).call(Tokenizer.prototype);
+ 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);
-exports.Tokenizer = Tokenizer;
});
-/* ***** BEGIN LICENSE BLOCK *****
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
@@ -10754,78 +13498,129 @@ exports.Tokenizer = Tokenizer;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/mode/text_highlight_rules', ['require', 'exports', 'module' , 'pilot/lang'], function(require, exports, module) {
-
-var lang = require("pilot/lang");
+define('ace/token_iterator', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
-var TextHighlightRules = function() {
+/**
+ * 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.
+ *
+ **/
- // regexp must not have capturing parentheses
- // regexps are ordered -> the first match is used
+/**
+ * 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, initialRow)[0].tokens;
- this.$rules = {
- "start" : [{
- token : "empty_line",
- regex : '^$'
- }, {
- token : "text",
- regex : ".+"
- }]
- };
+ var token = session.getTokenAt(initialRow, initialColumn);
+ this.$tokenIndex = token ? token.index : -1;
};
(function() {
-
- this.addRules = function(rules, prefix) {
- for (var key in rules) {
- var state = rules[key];
- for (var i=0; i [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.$rules[prefix + key] = state;
+
+ this.$rowTokens = this.$session.getTokens(this.$row, this.$row)[0].tokens;
+ this.$tokenIndex = this.$rowTokens.length - 1;
}
+
+ return this.$rowTokens[this.$tokenIndex];
};
-
- this.getRules = function() {
- return this.$rules;
- };
-
- this.embedRules = function (HighlightRules, prefix, escapeRules, states) {
- var embedRules = new HighlightRules().getRules();
- if (states) {
- for (var i = 0; i < states.length; i++) {
- states[i] = prefix + states[i];
- }
- } else {
- states = [];
- for (var key in embedRules) {
- states.push(prefix + key);
+
+ /**
+ * TokenIterator.stepForward() -> String
+ *
+ * Tokenizes all the items from the current point until the next row in the document. If the current point is at the end of the file, this function returns `null`. Otherwise, it returns the tokenized string.
+ **/
+ 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.$row)[0].tokens;
+ this.$tokenIndex = 0;
}
- this.addRules(embedRules, prefix);
+
+ return this.$rowTokens[this.$tokenIndex];
+ };
+
+ /**
+ * TokenIterator.getCurrentToken() -> String
+ *
+ * Returns the current tokenized string.
+ *
+ **/
+ this.getCurrentToken = function () {
+ return this.$rowTokens[this.$tokenIndex];
+ };
+
+ /**
+ * TokenIterator.getCurrentTokenRow() -> Number
+ *
+ * Returns the current row.
+ *
+ **/
+ this.getCurrentTokenRow = function () {
+ return this.$row;
+ };
+
+ /**
+ * TokenIterator.getCurrentTokenColumn() -> Number
+ *
+ * Returns the current column.
+ *
+ **/
+ this.getCurrentTokenColumn = function() {
+ var rowTokens = this.$rowTokens;
+ var tokenIndex = this.$tokenIndex;
- for (var i = 0; i < states.length; i++) {
- Array.prototype.unshift.apply(this.$rules[states[i]], lang.deepCopy(escapeRules));
+ // 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;
}
- if (!this.$embeds) {
- this.$embeds = [];
- }
- this.$embeds.push(prefix);
- }
-
- this.getEmbeds = function() {
- return this.$embeds;
- }
-
-}).call(TextHighlightRules.prototype);
+ return column;
+ };
+
+}).call(TokenIterator.prototype);
-exports.TextHighlightRules = TextHighlightRules;
+exports.TokenIterator = TokenIterator;
});
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
@@ -10849,7 +13644,7 @@ exports.TextHighlightRules = TextHighlightRules;
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Chris Spencer
+ * 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
@@ -10865,170 +13660,177 @@ exports.TextHighlightRules = TextHighlightRules;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/mode/behaviour', ['require', 'exports', 'module' ], function(require, exports, module) {
+define('ace/edit_session/bracket_match', ['require', 'exports', 'module' , 'ace/token_iterator'], function(require, exports, module) {
+"use strict";
-var Behaviour = function() {
- this.$behaviours = {};
-};
+var TokenIterator = require("../token_iterator").TokenIterator;
-(function () {
+/**
+ * class BracketMatch
+ *
+ *
+ *
+ *
+ **/
- this.add = function (name, action, callback) {
- switch (undefined) {
- case this.$behaviours:
- this.$behaviours = {};
- case this.$behaviours[name]:
- this.$behaviours[name] = {};
- }
- this.$behaviours[name][action] = callback;
- }
-
- this.addBehaviours = function (behaviours) {
- for (var key in behaviours) {
- for (var action in behaviours[key]) {
- this.add(key, action, behaviours[key][action]);
- }
- }
- }
-
- this.remove = function (name) {
- if (this.$behaviours && this.$behaviours[name]) {
- delete this.$behaviours[name];
+/**
+ * new BracketMatch(position)
+ * - platform (String): Identifier for the platform; must be either `'mac'` or `'win'`
+ * - commands (Array): A list of commands
+ *
+ * TODO
+ *
+ *
+ **/
+function BracketMatch() {
+
+ /**
+ * new findMatchingBracket(position)
+ * - position (Number): Identifier for the platform; must be either `'mac'` or `'win'`
+ * - commands (Array): A list of commands
+ *
+ * TODO
+ *
+ *
+ **/
+ 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;
}
- }
-
- this.inherit = function (mode, filter) {
- if (typeof mode === "function") {
- var behaviours = new mode().getBehaviours(filter);
+
+ if (match[1]) {
+ return this.$findClosingBracket(match[1], position);
} else {
- var behaviours = mode.getBehaviours(filter);
+ return this.$findOpeningBracket(match[2], position);
}
- this.addBehaviours(behaviours);
- }
-
- this.getBehaviours = function (filter) {
- if (!filter) {
- return this.$behaviours;
- } else {
- var ret = {}
- for (var i = 0; i < filter.length; i++) {
- if (this.$behaviours[filter[i]]) {
- ret[filter[i]] = this.$behaviours[filter[i]];
+ };
+
+ this.$brackets = {
+ ")": "(",
+ "(": ")",
+ "]": "[",
+ "[": "]",
+ "{": "}",
+ "}": "{"
+ };
+
+ this.$findOpeningBracket = function(bracket, position) {
+ var openBracket = this.$brackets[bracket];
+ var depth = 1;
+
+ var iterator = new TokenIterator(this, position.row, position.column);
+ var token = iterator.getCurrentToken();
+ if (!token) return null;
+
+ // token.type contains a period-delimited list of token identifiers
+ // (e.g.: "constant.numeric" or "paren.lparen"). Create a pattern that
+ // matches any token containing the same identifiers or a subset. In
+ // addition, if token.type includes "rparen", then also match "lparen".
+ // So if type.token is "paren.rparen", then typeRe will match "lparen.paren".
+ var typeRe = new RegExp("(\\.?" +
+ token.type.replace(".", "|").replace("rparen", "lparen|rparen") + ")+");
+
+ // 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;
}
- return ret;
- }
- }
-}).call(Behaviour.prototype);
+ // Scan backward through the document, looking for the next token
+ // whose type matches typeRe
+ do {
+ token = iterator.stepBackward();
+ } while (token && !typeRe.test(token.type));
-exports.Behaviour = Behaviour;
-});define('ace/unicode', ['require', 'exports', 'module' ], function(require, exports, module) {
+ if (token == null)
+ break;
+
+ value = token.value;
+ valueIndex = value.length - 1;
+ }
+
+ return null;
+ };
-/*
-XRegExp Unicode plugin pack: Categories 1.0
-(c) 2010 Steven Levithan
-MIT License
-
-Uses the Unicode 5.2 character database
+ this.$findClosingBracket = function(bracket, position) {
+ var closingBracket = this.$brackets[bracket];
+ var depth = 1;
-This package for the XRegExp Unicode plugin enables the following Unicode categories (aka properties):
+ var iterator = new TokenIterator(this, position.row, position.column);
+ var token = iterator.getCurrentToken();
+ if (!token) return null;
-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
+ // token.type contains a period-delimited list of token identifiers
+ // (e.g.: "constant.numeric" or "paren.lparen"). Create a pattern that
+ // matches any token containing the same identifiers or a subset. In
+ // addition, if token.type includes "lparen", then also match "rparen".
+ // So if type.token is "lparen.paren", then typeRe will match "paren.rparen".
+ var typeRe = new RegExp("(\\.?" +
+ token.type.replace(".", "|").replace("lparen", "lparen|rparen") + ")+");
-Example usage:
+ // Start searching in token, after the character at position.column
+ var valueIndex = position.column - iterator.getCurrentTokenColumn();
- \p{N}
- \p{Cn}
-*/
+ 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;
+ }
-// will be populated by addUnicodePackage
-exports.packages = {};
+ // Scan forward through the document, looking for the next token
+ // whose type matches typeRe
+ do {
+ token = iterator.stepForward();
+ } while (token && !typeRe.test(token.type));
-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"
-});
+ if (token == null)
+ break;
-function addUnicodePackage (pack) {
- var codePoint = /\w{4}/g;
- for (var name in pack)
- exports.packages[name] = pack[name].replace(codePoint, "\\u$&");
-};
+ valueIndex = 0;
+ }
+
+ return null;
+ };
+}
+exports.BracketMatch = BracketMatch;
-});/* ***** BEGIN LICENSE BLOCK *****
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
@@ -11050,6 +13852,7 @@ function addUnicodePackage (pack) {
*
* Contributor(s):
* Fabian Jakobs
+ * Mihai Sucan
*
* 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
@@ -11065,372 +13868,510 @@ function addUnicodePackage (pack) {
*
* ***** END LICENSE BLOCK ***** */
-define('ace/document', ['require', 'exports', 'module' , 'pilot/oop', 'pilot/event_emitter', 'ace/range', 'ace/anchor'], function(require, exports, module) {
+define('ace/search', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/lib/oop', 'ace/range'], function(require, exports, module) {
+"use strict";
-var oop = require("pilot/oop");
-var EventEmitter = require("pilot/event_emitter").EventEmitter;
-var Range = require("ace/range").Range;
-var Anchor = require("ace/anchor").Anchor;
+var lang = require("./lib/lang");
+var oop = require("./lib/oop");
+var Range = require("./range").Range;
-var Document = function(text) {
- this.$lines = [];
+/**
+ * class Search
+ *
+ * A class designed to handle all sorts of text searches within a [[Document `Document`]].
+ *
+ **/
- if (Array.isArray(text)) {
- this.insertLines(0, text);
- }
- // 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.
- else if (text.length == 0) {
- this.$lines = [""];
- } else {
- this.insert({row: 0, column:0}, text);
- }
+/**
+ * new Search()
+ *
+ * Creates a new `Search` object. The search options contain the following defaults:
+ *
+ * * `needle`: `""`
+ * * `backwards`: `false`
+ * * `wrap`: `false`
+ * * `caseSensitive`: `false`
+ * * `wholeWord`: `false`
+ * * `scope`: `ALL`
+ * * `regExp`: `false`
+ *
+**/
+
+var Search = function() {
+ this.$options = {
+ needle: "",
+ backwards: false,
+ wrap: false,
+ caseSensitive: false,
+ wholeWord: false,
+ scope: Search.ALL,
+ regExp: false
+ };
};
-(function() {
+Search.ALL = 1;
+Search.SELECTION = 2;
- oop.implement(this, EventEmitter);
+(function() {
- 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);
+ /**
+ * 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.getValue = function() {
- return this.getAllLines().join(this.getNewLineCharacter());
+ /**
+ * Search.getOptions() -> Object
+ *
+ * [Returns an object containing all the search options.]{: #Search.getOptions}
+ *
+ **/
+ this.getOptions = function() {
+ return lang.copyObject(this.$options);
};
- this.createAnchor = function(row, column) {
- return new Anchor(this, row, column);
+ /**
+ * Search.find(session) -> Range
+ * - session (EditSession): The session to search with
+ *
+ * Searches for `options.needle`. If found, this method returns the [[Range `Range`]] where the text first occurs. If `options.backwards` is `true`, the search goes backwards in the session.
+ *
+ **/
+ this.find = function(session) {
+ if (!this.$options.needle)
+ return null;
+
+ if (this.$options.backwards) {
+ var iterator = this.$backwardMatchIterator(session);
+ } else {
+ iterator = this.$forwardMatchIterator(session);
+ }
+
+ var firstRange = null;
+ iterator.forEach(function(range) {
+ firstRange = range;
+ return true;
+ });
+
+ return firstRange;
};
- // 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");
+ /**
+ * Search.findAll(session) -> [Range]
+ * - session (EditSession): The session to search with
+ *
+ * Searches for all occurances `options.needle`. If found, this method returns an array of [[Range `Range`s]] where the text first occurs. If `options.backwards` is `true`, the search goes backwards in the session.
+ *
+ **/
+ this.findAll = function(session) {
+ var options = this.$options;
+ if (!options.needle)
+ return [];
+
+ if (options.backwards) {
+ var iterator = this.$backwardMatchIterator(session);
+ } else {
+ iterator = this.$forwardMatchIterator(session);
}
- else
- this.$split = function(text) {
- return text.split(/\r\n|\r|\n/);
- };
+ var ignoreCursor = !options.start && options.wrap && options.scope == Search.ALL;
+ if (ignoreCursor)
+ options.start = {row: 0, column: 0};
- this.$detectNewLine = function(text) {
- var match = text.match(/^.*?(\r?\n)/m);
- if (match) {
- this.$autoNewLine = match[1];
+ var ranges = [];
+ iterator.forEach(function(range) {
+ ranges.push(range);
+ });
+
+ if (ignoreCursor)
+ options.start = null;
+
+ return ranges;
+ };
+
+ /**
+ * Search.replace(input, replacement) -> String
+ * - input (String): The text to search in
+ * - replacement (String): The replacing text
+ * + (String): If `options.regExp` is `true`, this function returns `input` with the replacement already made. Otherwise, this function just returns `replacement`.
+ * If `options.needle` was not found, this function returns `null`.
+ *
+ * Searches for `options.needle` in `input`, and, if found, replaces it with `replacement`.
+ *
+ *
+ *
+ **/
+ this.replace = function(input, replacement) {
+ var re = this.$assembleRegExp();
+ var match = re.exec(input);
+ if (match && match[0].length == input.length) {
+ if (this.$options.regExp) {
+ return input.replace(re, replacement);
+ } else {
+ return replacement;
+ }
} else {
- this.$autoNewLine = "\n";
+ return null;
}
};
- this.getNewLineCharacter = function() {
- switch (this.$newLineMode) {
- case "windows":
- return "\r\n";
+ /** internal, hide
+ * Search.$forwardMatchIterator(session) -> String | Boolean
+ * - session (EditSession): The session to search with
+ *
+ *
+ *
+ **/
+ this.$forwardMatchIterator = function(session) {
+ var re = this.$assembleRegExp();
+ var self = this;
- case "unix":
- return "\n";
+ return {
+ forEach: function(callback) {
+ self.$forwardLineIterator(session).forEach(function(line, startIndex, row) {
+ if (startIndex) {
+ line = line.substring(startIndex);
+ }
- case "auto":
- return this.$autoNewLine;
- }
- },
+ var matches = [];
- this.$autoNewLine = "\n";
- this.$newLineMode = "auto";
- this.setNewLineMode = function(newLineMode) {
- if (this.$newLineMode === newLineMode) return;
+ line.replace(re, function(str) {
+ var offset = arguments[arguments.length-2];
+ matches.push({
+ str: str,
+ offset: startIndex + offset
+ });
+ return str;
+ });
+
+ for (var i=0; i String
+ * - session (EditSession): The session to search with
+ *
+ *
+ *
+ **/
+ this.$backwardMatchIterator = function(session) {
+ var re = this.$assembleRegExp();
+ var self = this;
- this.isNewLine = function(text) {
- return (text == "\r\n" || text == "\r" || text == "\n");
- };
+ return {
+ forEach: function(callback) {
+ self.$backwardLineIterator(session).forEach(function(line, startIndex, row) {
+ if (startIndex) {
+ line = line.substring(startIndex);
+ }
- /**
- * Get a verbatim copy of the given line as it is in the document
- */
- this.getLine = function(row) {
- return this.$lines[row] || "";
- };
+ var matches = [];
- this.getLines = function(firstRow, lastRow) {
- return this.$lines.slice(firstRow, lastRow + 1);
- };
+ line.replace(re, function(str, offset) {
+ matches.push({
+ str: str,
+ offset: startIndex + offset
+ });
+ return str;
+ });
- /**
- * Returns all lines in the document as string array. Warning: The caller
- * should not modify this array!
- */
- this.getAllLines = function() {
- return this.getLines(0, this.getLength());
+ for (var i=matches.length-1; i>= 0; i--) {
+ var match = matches[i];
+ var range = self.$rangeFromMatch(row, match.offset, match.str.length);
+ if (callback(range))
+ return true;
+ }
+ });
+ }
+ };
};
- this.getLength = function() {
- return this.$lines.length;
+ this.$rangeFromMatch = function(row, column, length) {
+ return new Range(row, column, row, column+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);
+ this.$assembleRegExp = function() {
+ if (this.$options.regExp) {
+ var needle = this.$options.needle;
+ } else {
+ needle = lang.escapeRegExp(this.$options.needle);
}
- else {
- var lines = [];
- lines.push(this.$lines[range.start.row].substring(range.start.column));
- lines.push.apply(lines, this.getLines(range.start.row+1, range.end.row-1));
- lines.push(this.$lines[range.end.row].substring(0, range.end.column));
- return lines.join(this.getNewLineCharacter());
+
+ if (this.$options.wholeWord) {
+ needle = "\\b" + needle + "\\b";
}
- };
- 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;
+ var modifier = "g";
+ if (!this.$options.caseSensitive) {
+ modifier += "i";
}
- return position;
- }
- this.insert = function(position, text) {
- if (text.length == 0)
- return position;
+ var re = new RegExp(needle, modifier);
+ return re;
+ };
- position = this.$clipPosition(position);
+ this.$forwardLineIterator = function(session) {
+ var searchSelection = this.$options.scope == Search.SELECTION;
- if (this.getLength() <= 1)
- this.$detectNewLine(text);
+ var range = this.$options.range || session.getSelection().getRange();
+ var start = this.$options.start || range[searchSelection ? "start" : "end"];
- 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];
+ var firstRow = searchSelection ? range.start.row : 0;
+ var firstColumn = searchSelection ? range.start.column : 0;
+ var lastRow = searchSelection ? range.end.row : session.getLength() - 1;
- 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 || "");
+ var wrap = this.$options.wrap;
+ var inWrap = false;
+
+ function getLine(row) {
+ var line = session.getLine(row);
+ if (searchSelection && row == range.end.row) {
+ line = line.substring(0, range.end.column);
+ }
+ if (inWrap && row == start.row) {
+ line = line.substring(0, start.column);
+ }
+ return line;
}
- return position;
- };
- this.insertLines = function(row, lines) {
- if (lines.length == 0)
- return {row: row, column: 0};
+ return {
+ forEach: function(callback) {
+ var row = start.row;
- var args = [row, 0];
- args.push.apply(args, lines);
- this.$lines.splice.apply(this.$lines, args);
+ var line = getLine(row);
+ var startIndex = start.column;
- var range = new Range(row, 0, row + lines.length, 0);
- var delta = {
- action: "insertLines",
- range: range,
- lines: lines
- };
- this._dispatchEvent("change", { data: delta });
- return range.end;
- },
+ var stop = false;
+ inWrap = false;
- this.insertNewLine = function(position) {
- position = this.$clipPosition(position);
- var line = this.$lines[position.row] || "";
+ while (!callback(line, startIndex, row)) {
- this.$lines[position.row] = line.substring(0, position.column);
- this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
+ if (stop) {
+ return;
+ }
- var end = {
- row : position.row + 1,
- column : 0
- };
+ row++;
+ startIndex = 0;
- var delta = {
- action: "insertText",
- range: Range.fromPoints(position, end),
- text: this.getNewLineCharacter()
- };
- this._dispatchEvent("change", { data: delta });
+ if (row > lastRow) {
+ if (wrap) {
+ row = firstRow;
+ startIndex = firstColumn;
+ inWrap = true;
+ } else {
+ return;
+ }
+ }
- return end;
+ if (row == start.row)
+ stop = true;
+
+ line = getLine(row);
+ }
+ }
+ };
};
- this.insertInLine = function(position, text) {
- if (text.length == 0)
- return position;
+ this.$backwardLineIterator = function(session) {
+ var searchSelection = this.$options.scope == Search.SELECTION;
- var line = this.$lines[position.row] || "";
+ var range = this.$options.range || session.getSelection().getRange();
+ var start = this.$options.start || range[searchSelection ? "end" : "start"];
- this.$lines[position.row] = line.substring(0, position.column) + text
- + line.substring(position.column);
+ var firstRow = searchSelection ? range.start.row : 0;
+ var firstColumn = searchSelection ? range.start.column : 0;
+ var lastRow = searchSelection ? range.end.row : session.getLength() - 1;
- var end = {
- row : position.row,
- column : position.column + text.length
- };
+ var wrap = this.$options.wrap;
- var delta = {
- action: "insertText",
- range: Range.fromPoints(position, end),
- text: text
- };
- this._dispatchEvent("change", { data: delta });
+ return {
+ forEach : function(callback) {
+ var row = start.row;
- return end;
- };
+ var line = session.getLine(row).substring(0, start.column);
+ var startIndex = 0;
+ var stop = false;
+ var inWrap = false;
- this.remove = function(range) {
- // clip to document
- range.start = this.$clipPosition(range.start);
- range.end = this.$clipPosition(range.end);
+ while (!callback(line, startIndex, row)) {
- if (range.isEmpty())
- return range.start;
+ if (stop)
+ return;
- var firstRow = range.start.row;
- var lastRow = range.end.row;
+ row--;
+ startIndex = 0;
- if (range.isMultiLine()) {
- var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
- var lastFullRow = lastRow - 1;
+ if (row < firstRow) {
+ if (wrap) {
+ row = lastRow;
+ inWrap = true;
+ } else {
+ return;
+ }
+ }
- if (range.end.column > 0)
- this.removeInLine(lastRow, 0, range.end.column);
+ if (row == start.row)
+ stop = true;
- if (lastFullRow >= firstFullRow)
- this.removeLines(firstFullRow, lastFullRow);
+ line = session.getLine(row);
+ if (searchSelection) {
+ if (row == firstRow)
+ startIndex = firstColumn;
+ else if (row == lastRow)
+ line = line.substring(0, range.end.column);
+ }
- if (firstFullRow != firstRow) {
- this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
- this.removeNewLine(range.start.row);
+ if (inWrap && row == start.row)
+ startIndex = start.column;
+ }
}
- }
- else {
- this.removeInLine(firstRow, range.start.column, range.end.column);
- }
- return range.start;
+ };
};
- this.removeInLine = function(row, startColumn, endColumn) {
- if (startColumn == endColumn)
- return;
+}).call(Search.prototype);
- 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);
+exports.Search = Search;
+});
+define('ace/commands/command_manager', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/keyboard/hash_handler', 'ace/lib/event_emitter'], function(require, exports, module) {
+"use strict";
- var delta = {
- action: "removeText",
- range: range,
- text: removed
- };
- this._dispatchEvent("change", { data: delta });
- return range.start;
- };
+var oop = require("../lib/oop");
+var HashHandler = require("../keyboard/hash_handler").HashHandler;
+var EventEmitter = require("../lib/event_emitter").EventEmitter;
- /**
- * Removes a range of full lines
- *
- * @param firstRow {Integer} The first row to be removed
- * @param lastRow {Integer} The last row to be removed
- * @return {String[]} The removed lines
- */
- this.removeLines = function(firstRow, lastRow) {
- var range = new Range(firstRow, 0, lastRow + 1, 0);
- var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
+/**
+ * class CommandManager
+ *
+ *
+ *
+ *
+ **/
- var delta = {
- action: "removeLines",
- range: range,
- nl: this.getNewLineCharacter(),
- lines: removed
- };
- this._dispatchEvent("change", { data: delta });
- return removed;
- };
+/**
+ * new CommandManager(platform, commands)
+ * - platform (String): Identifier for the platform; must be either `'mac'` or `'win'`
+ * - commands (Array): A list of commands
+ *
+ * TODO
+ *
+ *
+ **/
- this.removeNewLine = function(row) {
- var firstLine = this.getLine(row);
- var secondLine = this.getLine(row+1);
+var CommandManager = function(platform, commands) {
+ this.platform = platform;
+ this.commands = {};
+ this.commmandKeyBinding = {};
- var range = new Range(row, firstLine.length, row+1, 0);
- var line = firstLine + secondLine;
+ this.addCommands(commands);
+
+ this.setDefaultHandler("exec", function(e) {
+ return e.command.exec(e.editor, e.args || {});
+ });
+};
- this.$lines.splice(row, 2, line);
+oop.inherits(CommandManager, HashHandler);
- var delta = {
- action: "removeText",
- range: range,
- text: this.getNewLineCharacter()
- };
- this._dispatchEvent("change", { data: delta });
- };
+(function() {
- this.replace = function(range, text) {
- if (text.length == 0 && range.isEmpty())
- return range.start;
+ oop.implement(this, EventEmitter);
- // 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.exec = function(command, editor, args) {
+ if (typeof command === 'string')
+ command = this.commands[command];
- this.remove(range);
- if (text) {
- var end = this.insert(range.start, text);
- }
- else {
- end = range.start;
+ if (!command)
+ return false;
+
+ if (editor && editor.$readOnly && !command.readOnly)
+ return false;
+
+ try {
+ var retvalue = this._emit("exec", {
+ editor: editor,
+ command: command,
+ args: args
+ });
+ } catch (e) {
+ window.console && window.console.log(e);
+ return true;
}
- return end;
+ return retvalue === false ? false : true;
};
- this.applyDeltas = function(deltas) {
- for (var i=0; i=0; i--) {
- var delta = deltas[i];
+ this.replay = function(editor) {
+ if (this.$inReplay || !this.macro)
+ return;
- var range = Range.fromPoints(delta.range.start, delta.range.end);
+ if (this.recording)
+ return this.toggleRecording();
- 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)
+ 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;
}
};
-}).call(Document.prototype);
+ 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;
-exports.Document = Document;
});
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -11445,15 +14386,16 @@ exports.Document = Document;
* for the specific language governing rights and limitations under the
* License.
*
- * The Original Code is Ajax.org Code Editor (ACE).
+ * The Original Code is Mozilla Skywriter.
*
* The Initial Developer of the Original Code is
- * Ajax.org B.V.
- * Portions created by the Initial Developer are Copyright (C) 2010
+ * Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Fabian Jakobs
+ * Fabian Jakobs
+ * Julian Viereck (julian.viereck@gmail.com)
*
* 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
@@ -11469,162 +14411,274 @@ exports.Document = Document;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/anchor', ['require', 'exports', 'module' , 'pilot/oop', 'pilot/event_emitter'], function(require, exports, module) {
+define('ace/keyboard/hash_handler', ['require', 'exports', 'module' , 'ace/lib/keys'], function(require, exports, module) {
+"use strict";
-var oop = require("pilot/oop");
-var EventEmitter = require("pilot/event_emitter").EventEmitter;
+var keyUtil = require("../lib/keys");
-/**
- * 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
- */
-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);
+function HashHandler(config, platform) {
+ this.platform = platform;
+ this.commands = {};
+ this.commmandKeyBinding = {};
- this.$onChange = this.onChange.bind(this);
- doc.on("change", this.$onChange);
+ this.addCommands(config);
};
(function() {
- oop.implement(this, EventEmitter);
-
- this.getPosition = function() {
- return this.$clipPositionToDocument(this.row, this.column);
+ this.addCommand = function(command) {
+ if (this.commands[command.name])
+ this.removeCommand(command);
+
+ this.commands[command.name] = command;
+
+ if (command.bindKey) {
+ this._buildKeyHash(command);
+ }
};
-
- this.getDocument = function() {
- return this.document;
+
+ 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.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)
+
+ this.bindKey = function(key, command) {
+ if(!key)
return;
-
- if (range.start.row == this.row && range.start.column > this.column)
+
+ 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 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;
- }
- }
+
+ var key = typeof binding == "string" ? binding: binding[this.platform];
+ this.bindKey(key, command);
+ };
+
+ this.parseKeys = function(keys, val) {
+ 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 '-'
}
- this.setPosition(row, column, true);
+ 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;
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
+ * Mihai Sucan
+ *
+ * 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('ace/undomanager', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+
+/**
+ * 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.setPosition = function(row, column, noClip) {
- var pos;
- if (noClip) {
- pos = {
- row: row,
- column: column
- };
+ /**
+ * UndoManager.undo(dontSelect) -> Range
+ * - dontSelect (Boolean): {:dontSelect}
+ *
+ * [Perform an undo operation on the document, reverting the last change. Returns the range of the undo.]{: #UndoManager.undo}
+ **/
+ this.undo = function(dontSelect) {
+ var deltas = this.$undoStack.pop();
+ var undoSelectionRange = null;
+ if (deltas) {
+ undoSelectionRange =
+ this.$doc.undoChanges(deltas, dontSelect);
+ this.$redoStack.push(deltas);
}
- else {
- pos = this.$clipPositionToDocument(row, column);
+ return undoSelectionRange;
+ };
+
+ /**
+ * UndoManager.redo(dontSelect) -> Void
+ * - dontSelect (Boolean): {:dontSelect}
+ *
+ * [Perform a redo operation on the document, reimplementing the last change.]{: #UndoManager.redo}
+ **/
+ this.redo = function(dontSelect) {
+ var deltas = this.$redoStack.pop();
+ var redoSelectionRange = null;
+ if (deltas) {
+ redoSelectionRange =
+ this.$doc.redoChanges(deltas, dontSelect);
+ this.$undoStack.push(deltas);
}
-
- 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._dispatchEvent("change", {
- old: old,
- value: pos
- });
+ return redoSelectionRange;
};
-
- this.detach = function() {
- this.document.removeEventListener("change", this.$onChange);
+
+ /**
+ * UndoManager.reset() -> Void
+ *
+ * Destroys the stack of undo and redo redo operations.
+ **/
+ this.reset = function() {
+ this.$undoStack = [];
+ this.$redoStack = [];
};
-
- 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;
+
+ /**
+ * UndoManager.hasUndo() -> Boolean
+ *
+ * Returns `true` if there are undo operations left to perform.
+ **/
+ this.hasUndo = function() {
+ return this.$undoStack.length > 0;
+ };
+
+ /**
+ * UndoManager.hasRedo() -> Boolean
+ *
+ * Returns `true` if there are redo operations left to perform.
+ **/
+ this.hasRedo = function() {
+ return this.$redoStack.length > 0;
};
-
-}).call(Anchor.prototype);
+}).call(UndoManager.prototype);
+
+exports.UndoManager = UndoManager;
});
-/* ***** BEGIN LICENSE BLOCK *****
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
@@ -11645,7 +14699,9 @@ var Anchor = exports.Anchor = function(doc, row, column) {
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Fabian Jakobs
+ * Fabian Jakobs
+ * Irakli Gozalishvili (http://jeditoolkit.com)
+ * Julian Viereck
*
* 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
@@ -11661,990 +14717,1331 @@ var Anchor = exports.Anchor = function(doc, row, column) {
*
* ***** END LICENSE BLOCK ***** */
-define('ace/background_tokenizer', ['require', 'exports', 'module' , 'pilot/oop', 'pilot/event_emitter'], function(require, exports, module) {
+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', 'text!ace/css/editor.css'], function(require, exports, module) {
+"use strict";
+
+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("text!./css/editor.css");
+
+dom.importCssString(editorCss, "ace_editor");
+
+/**
+ * class VirtualRenderer
+ *
+ * The class that is responsible for drawing everything you see on the screen!
+ *
+ **/
+
+/**
+ * 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.setFadeFoldWidgets(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);
+
+ _self.scroller.className = scrollLeft == 0
+ ? "ace_scroller"
+ : "ace_scroller horscroll";
+ });
+
+ 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);
+
+ /**
+ * VirtualRenderer.setSession(session) -> Void
+ *
+ * Associates an [[EditSession `EditSession`]].
+ **/
+ 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);
+
+ };
+
+ /**
+ * VirtualRenderer.updateLines(firstRow, lastRow) -> Void
+ * - firstRow (Number): The first row to update
+ * - lastRow (Number): The last row to update
+ *
+ * Triggers a partial update of the text, from the range given by the two parameters.
+ **/
+ this.updateLines = function(firstRow, lastRow) {
+ if (lastRow === undefined)
+ lastRow = Infinity;
-var oop = require("pilot/oop");
-var EventEmitter = require("pilot/event_emitter").EventEmitter;
+ if (!this.$changedLines) {
+ this.$changedLines = {
+ firstRow: firstRow,
+ lastRow: lastRow
+ };
+ }
+ else {
+ if (this.$changedLines.firstRow > firstRow)
+ this.$changedLines.firstRow = firstRow;
-var BackgroundTokenizer = function(tokenizer, editor) {
- this.running = false;
- this.lines = [];
- this.currentLine = 0;
- this.tokenizer = tokenizer;
+ if (this.$changedLines.lastRow < lastRow)
+ this.$changedLines.lastRow = lastRow;
+ }
- var self = this;
+ this.$loop.schedule(this.CHANGE_LINES);
+ };
- this.$worker = function() {
- if (!self.running) { return; }
+ /**
+ * VirtualRenderer.updateText() -> Void
+ *
+ * Triggers a full update of the text, for all the rows.
+ **/
+ this.updateText = function() {
+ this.$loop.schedule(this.CHANGE_TEXT);
+ };
- var workerStart = new Date();
- var startLine = self.currentLine;
- var doc = self.doc;
+ /**
+ * VirtualRenderer.updateFull() -> Void
+ *
+ * Triggers a full update of all the layers, for all the rows.
+ **/
+ this.updateFull = function() {
+ this.$loop.schedule(this.CHANGE_FULL);
+ };
- var processedLines = 0;
+ /**
+ * VirtualRenderer.updateFontSize() -> Void
+ *
+ * Updates the font size.
+ **/
+ this.updateFontSize = function() {
+ this.$textLayer.checkForSizeChanges();
+ };
- var len = doc.getLength();
- while (self.currentLine < len) {
- self.lines[self.currentLine] = self.$tokenizeRows(self.currentLine, self.currentLine)[0];
- self.currentLine++;
+ /**
+ * VirtualRenderer.onResize(force) -> Void
+ * - force (Boolean): If `true`, recomputes the size, even if the height and width haven't changed
+ *
+ * [Triggers a resize of the editor.]{: #VirtualRenderer.onResize}
+ **/
+ this.onResize = function(force) {
+ var changes = this.CHANGE_SIZE;
+ var size = this.$size;
- // only check every 5 lines
- processedLines += 1;
- if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) {
- self.fireUpdateEvent(startLine, self.currentLine-1);
- self.running = setTimeout(self.$worker, 20);
- return;
+ var 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;
}
}
- self.running = false;
+ var width = dom.getInnerWidth(this.container);
+ if (force || size.width != width) {
+ size.width = width;
- self.fireUpdateEvent(startLine, len - 1);
+ 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.width = size.scrollerWidth + "px";
+
+ if (this.session.getUseWrapMode() && this.adjustWrapLimit() || force)
+ changes = changes | this.CHANGE_FULL;
+ }
+
+ this.$loop.schedule(changes);
};
-};
-(function(){
+ /**
+ * VirtualRenderer.adjustWrapLimit() -> Void
+ *
+ * Adjusts the wrap limit, which is the number of characters that can fit within the width of the edit area on screen.
+ **/
+ this.adjustWrapLimit = function() {
+ var availableWidth = this.$size.scrollerWidth - this.$padding * 2;
+ var limit = Math.floor(availableWidth / this.characterWidth);
+ return this.session.adjustWrapLimit(limit);
+ };
- oop.implement(this, EventEmitter);
+ /**
+ * VirtualRenderer.setAnimatedScroll(shouldAnimate) -> Void
+ * - shouldAnimate (Boolean): Set to `true` to show animated scrolls
+ *
+ * Identifies whether you want to have an animated scroll or not.
+ *
+ **/
+ this.setAnimatedScroll = function(shouldAnimate){
+ this.$animatedScroll = shouldAnimate;
+ };
- this.setTokenizer = function(tokenizer) {
- this.tokenizer = tokenizer;
- this.lines = [];
+ /**
+ * VirtualRenderer.getAnimatedScroll() -> Boolean
+ *
+ * Returns whether an animated scroll happens or not.
+ **/
+ this.getAnimatedScroll = function() {
+ return this.$animatedScroll;
+ };
- this.start(0);
+ /**
+ * VirtualRenderer.setShowInvisibles(showInvisibles) -> Void
+ * - showInvisibles (Boolean): Set to `true` to show invisibles
+ *
+ * Identifies whether you want to show invisible characters or not.
+ *
+ **/
+ this.setShowInvisibles = function(showInvisibles) {
+ if (this.$textLayer.setShowInvisibles(showInvisibles))
+ this.$loop.schedule(this.CHANGE_TEXT);
};
- this.setDocument = function(doc) {
- this.doc = doc;
- this.lines = [];
+ /**
+ * VirtualRenderer.getShowInvisibles() -> Boolean
+ *
+ * Returns whether invisible characters are being shown or not.
+ **/
+ this.getShowInvisibles = function() {
+ return this.$textLayer.showInvisibles;
+ };
- this.stop();
+ this.$showPrintMargin = true;
+
+ /**
+ * VirtualRenderer.setShowPrintMargin(showPrintMargin)
+ * - showPrintMargin (Boolean): Set to `true` to show the print margin
+ *
+ * Identifies whether you want to show the print margin or not.
+ *
+ **/
+ this.setShowPrintMargin = function(showPrintMargin) {
+ this.$showPrintMargin = showPrintMargin;
+ this.$updatePrintMargin();
};
- this.fireUpdateEvent = function(firstRow, lastRow) {
- var data = {
- first: firstRow,
- last: lastRow
- };
- this._dispatchEvent("update", {data: data});
+ /**
+ * VirtualRenderer.getShowPrintMargin() -> Boolean
+ *
+ * Returns whetherthe print margin is being shown or not.
+ **/
+ this.getShowPrintMargin = function() {
+ return this.$showPrintMargin;
};
- this.start = function(startRow) {
- this.currentLine = Math.min(startRow || 0, this.currentLine,
- this.doc.getLength());
+ this.$printMarginColumn = 80;
- // remove all cached items below this line
- this.lines.splice(this.currentLine, this.lines.length);
+ /**
+ * VirtualRenderer.setPrintMarginColumn(showPrintMargin)
+ * - showPrintMargin (Boolean): Set to `true` to show the print margin column
+ *
+ * Identifies whether you want to show the print margin column or not.
+ *
+ **/
+ this.setPrintMarginColumn = function(showPrintMargin) {
+ this.$printMarginColumn = showPrintMargin;
+ this.$updatePrintMargin();
+ };
- this.stop();
- // pretty long delay to prevent the tokenizer from interfering with the user
- this.running = setTimeout(this.$worker, 700);
+ /**
+ * VirtualRenderer.getPrintMarginColumn() -> Boolean
+ *
+ * Returns whether the print margin column is being shown or not.
+ **/
+ this.getPrintMarginColumn = function() {
+ return this.$printMarginColumn;
};
- this.stop = function() {
- if (this.running)
- clearTimeout(this.running);
- this.running = false;
+ /**
+ * VirtualRenderer.getShowGutter() -> Boolean
+ *
+ * Returns `true` if the gutter is being shown.
+ **/
+ this.getShowGutter = function(){
+ return this.showGutter;
};
- this.getTokens = function(firstRow, lastRow) {
- return this.$tokenizeRows(firstRow, lastRow);
+ /**
+ * VirtualRenderer.setShowGutter(show) -> Void
+ * - show (Boolean): Set to `true` to show the gutter
+ *
+ * Identifies whether you want to show the gutter or not.
+ **/
+ this.setShowGutter = function(show){
+ if(this.showGutter === show)
+ return;
+ this.$gutter.style.display = show ? "block" : "none";
+ this.showGutter = show;
+ this.onResize(true);
};
- this.getState = function(row) {
- return this.$tokenizeRows(row, row)[0].state;
+ this.getFadeFoldWidgets = function(){
+ return dom.hasCssClass(this.$gutter, "ace_fade-fold-widgets");
};
- this.$tokenizeRows = function(firstRow, lastRow) {
- if (!this.doc)
- return [];
-
- var rows = [];
+ this.setFadeFoldWidgets = function(show) {
+ if (show)
+ dom.addCssClass(this.$gutter, "ace_fade-fold-widgets");
+ else
+ dom.removeCssClass(this.$gutter, "ace_fade-fold-widgets");
+ };
- // determine start state
- var state = "start";
- var doCache = false;
- if (firstRow > 0 && this.lines[firstRow - 1]) {
- state = this.lines[firstRow - 1].state;
- doCache = true;
- } else if (firstRow == 0) {
- state = "start";
- doCache = true;
- } else if (this.lines.length > 0) {
- // Guess that we haven't changed state.
- state = this.lines[this.lines.length-1].state;
+ 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;
}
- var lines = this.doc.getLines(firstRow, lastRow);
- for (var row=firstRow; row<=lastRow; row++) {
- if (!this.lines[row]) {
- var tokens = this.tokenizer.getLineTokens(lines[row-firstRow] || "", state);
- var state = tokens.state;
- rows.push(tokens);
+ this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none";
+ this.$updateGutterLineHighlight();
+ };
- if (doCache) {
- this.lines[row] = tokens;
- }
- }
- else {
- var tokens = this.lines[row];
- state = tokens.state;
- rows.push(tokens);
- }
+ this.getHighlightGutterLine = function() {
+ return this.$highlightGutterLine;
+ };
+
+ this.$updateGutterLineHighlight = function() {
+ this.$gutterLineHighlight.style.top = this.$cursorLayer.$pixelPos.top + "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);
}
- return rows;
+
+ var style = this.$printMarginEl.style;
+ style.left = ((this.characterWidth * this.$printMarginColumn) + this.$padding) + "px";
+ style.visibility = this.$showPrintMargin ? "visible" : "hidden";
+ };
+
+ /**
+ * VirtualRenderer.getContainerElement() -> DOMElement
+ *
+ * Returns the root element containing this renderer.
+ **/
+ this.getContainerElement = function() {
+ return this.container;
+ };
+
+ /**
+ * VirtualRenderer.getMouseEventTarget() -> DOMElement
+ *
+ * Returns the element that the mouse events are attached to
+ **/
+ this.getMouseEventTarget = function() {
+ return this.content;
+ };
+
+ /**
+ * VirtualRenderer.getTextAreaContainer() -> DOMElement
+ *
+ * Returns the element to which the hidden text area is added.
+ **/
+ 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)
+ return;
+
+ posLeft += (this.showGutter ? this.$gutterLayer.gutterWidth : 0) - this.scrollLeft;
+ var bounds = this.container.getBoundingClientRect();
+ this.textarea.style.left = (bounds.left + posLeft) + "px";
+ this.textarea.style.top = (bounds.top + posTop) + "px";
+ };
+
+ /**
+ * VirtualRenderer.getFirstVisibleRow() -> Number
+ *
+ * [Returns the index of the first visible row.]{: #VirtualRenderer.getFirstVisibleRow}
+ **/
+ this.getFirstVisibleRow = function() {
+ return this.layerConfig.firstRow;
+ };
+
+ /**
+ * VirtualRenderer.getFirstFullyVisibleRow() -> Number
+ *
+ * Returns the index of the first fully visible row. "Fully" here means that the characters in the row are not truncated; that the top and the bottom of the row are on the screen.
+ **/
+ this.getFirstFullyVisibleRow = function() {
+ return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1);
};
-}).call(BackgroundTokenizer.prototype);
+ /**
+ * VirtualRenderer.getLastFullyVisibleRow() -> Number
+ *
+ * Returns the index of the last fully visible row. "Fully" here means that the characters in the row are not truncated; that the top and the bottom of the row are on the screen.
+ **/
+ this.getLastFullyVisibleRow = function() {
+ var flint = Math.floor((this.layerConfig.height + this.layerConfig.offset) / this.layerConfig.lineHeight);
+ return this.layerConfig.firstRow - 1 + flint;
+ };
-exports.BackgroundTokenizer = BackgroundTokenizer;
-});
-/* vim:ts=4:sts=4:sw=4:
- * ***** 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):
- * Julian Viereck
- *
- * 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 ***** */
+ /**
+ * VirtualRenderer.getLastVisibleRow() -> Number
+ *
+ * [Returns the index of the last visible row.]{: #VirtualRenderer.getLastVisibleRow}
+ **/
+ this.getLastVisibleRow = function() {
+ return this.layerConfig.lastRow;
+ };
-define('ace/edit_session/folding', ['require', 'exports', 'module' , 'ace/range', 'ace/edit_session/fold_line', 'ace/edit_session/fold'], function(require, exports, module) {
+ this.$padding = null;
-var Range = require("ace/range").Range;
-var FoldLine = require("ace/edit_session/fold_line").FoldLine;
-var Fold = require("ace/edit_session/fold").Fold;
+ /**
+ * VirtualRenderer.setPadding(padding) -> Void
+ * - padding (Number): A new padding value (in pixels)
+ *
+ * Sets the padding for all the layers.
+ *
+ **/
+ 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();
+ };
-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;
- }
- }
+ * VirtualRenderer.getHScrollBarAlwaysVisible() -> Boolean
+ *
+ * Returns whether the horizontal scrollbar is set to be always visible.
+ **/
+ this.getHScrollBarAlwaysVisible = function() {
+ return this.$horizScrollAlwaysVisible;
};
/**
- * Returns all folds in the given range. Note, that this will return folds
- *
- */
- this.getFoldsInRange = function(range) {
- range = range.clone();
- var start = range.start;
- var end = range.end;
- var foldLines = this.$foldData;
- var foundFolds = [];
+ * VirtualRenderer.setHScrollBarAlwaysVisible(alwaysVisible) -> Void
+ * - alwaysVisible (Boolean): Set to `true` to make the horizontal scroll bar visible
+ *
+ * Identifies whether you want to show the horizontal scrollbar or not.
+ **/
+ this.setHScrollBarAlwaysVisible = function(alwaysVisible) {
+ if (this.$horizScrollAlwaysVisible != alwaysVisible) {
+ this.$horizScrollAlwaysVisible = alwaysVisible;
+ if (!this.$horizScrollAlwaysVisible || !this.$horizScroll)
+ this.$loop.schedule(this.CHANGE_SCROLL);
+ }
+ };
- start.column += 1;
- end.column -= 1;
+ this.$updateScrollBar = function() {
+ this.scrollBar.setInnerHeight(this.layerConfig.maxHeight);
+ this.scrollBar.setScrollTop(this.scrollTop);
+ };
- 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;
- }
+ this.$renderChanges = function(changes) {
+ if (!changes || !this.session || !this.container.offsetWidth)
+ return;
- 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);
- }
+ // 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);
}
- return foundFolds;
- }
- /**
- * Returns the string between folds at the given position.
- * E.g.
- * foob|arwolrd -> "bar"
- * foobarwol|rd -> "world"
- * foobarwolrd ->
- *
- * where | means the position of row/column
- *
- * The trim option determs if the return string should be trimed according
- * to the "side" passed with the trim value:
- *
- * E.g.
- * foob|arwolrd -trim=-1> "b"
- * foobarwol|rd -trim=+1> "rld"
- * fo|obarwolrd -trim=00> "foo"
- */
- this.getFoldStringAt = function(row, column, trim, foldLine) {
- var foldLine = foldLine || this.getFoldLine(row);
- if (!foldLine)
- return null;
-
- var lastFold = {
- end: { column: 0 }
- };
- // TODO: Refactor to use getNextFoldTo function.
- for (var i = 0; i < foldLine.folds.length; i++) {
- var fold = foldLine.folds[i];
- var cmp = fold.range.compareEnd(row, column);
- if (cmp == -1) {
- var str = this
- .getLine(fold.start.row)
- .substring(lastFold.end.column, fold.start.column);
- break;
- }
- else if (cmp == 0) {
- return null;
- }
- lastFold = fold;
+ // 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;
}
- 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;
- }
+ // 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);
- 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;
- }
+ 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;
}
- return null;
- }
- // returns the fold which starts after or contains docRow
- this.getNextFold = function(docRow, startFoldLine) {
- var foldData = this.$foldData, ans;
- 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;
+ 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()) {
+ this.$updateScrollBar();
+ if (this.showGutter)
+ this.$gutterLayer.update(this.layerConfig);
}
+ } else if (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);
}
- 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;
- }
+ if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) {
+ this.$markerBack.update(this.layerConfig);
}
- 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;
- }
+ if (changes & this.CHANGE_SIZE)
+ this.$updateScrollBar();
+ };
- /**
- * Adds a new fold.
- *
- * @returns
- * The new created Fold object or an existing fold object in case the
- * passed in range fits an existing fold exactly.
- */
- this.addFold = function(placeholder, range) {
- var foldData = this.$foldData;
- var added = false;
+ this.$computeLayerConfig = function() {
+ var session = this.session;
- if (placeholder instanceof Fold)
- var fold = placeholder;
- else
- fold = new Fold(range, placeholder);
+ var offset = this.scrollTop % this.lineHeight;
+ var minHeight = this.$size.scrollerHeight + this.lineHeight;
- 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";
+ var longestLine = this.$getLongestLine();
- if (startRow == endRow && endColumn - startColumn < 2)
- throw "The range has to be at least 2 characters width";
+ 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 existingFold = this.getFoldAt(startRow, startColumn, 1);
- if (
- existingFold
- && existingFold.range.isEnd(endRow, endColumn)
- && existingFold.range.isStart(startRow, startColumn)
- ) {
- return fold;
+ 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 = { 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;
}
- existingFold = this.getFoldAt(startRow, startColumn, 1);
- if (existingFold && !existingFold.range.isStart(startRow, startColumn))
- throw "A fold can't start inside of an already existing fold";
+ firstRowScreen = session.documentToScreenRow(firstRow, 0);
+ firstRowHeight = session.getRowHeight(lineHeight, firstRow);
- existingFold = this.getFoldAt(endRow, endColumn, -1);
- if (existingFold && !existingFold.range.isEnd(endRow, endColumn))
- throw "A fold can't end inside of an already existing fold";
+ lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1);
+ minHeight = this.$size.scrollerHeight + session.getRowHeight(lineHeight, lastRow)+
+ firstRowHeight;
- if (endRow >= this.doc.getLength())
- throw "End of fold is outside of the document.";
+ offset = this.scrollTop - firstRowScreen * this.lineHeight;
- if (endColumn > this.getLine(endRow).length || startColumn > this.getLine(startRow).length)
- throw "End of fold is outside of the document.";
+ this.layerConfig = {
+ width : longestLine,
+ padding : this.$padding,
+ firstRow : firstRow,
+ firstRowScreen: firstRowScreen,
+ lastRow : lastRow,
+ lineHeight : this.lineHeight,
+ characterWidth : this.characterWidth,
+ minHeight : minHeight,
+ maxHeight : maxHeight,
+ offset : offset,
+ height : this.$size.scrollerHeight
+ };
- // 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 debugging.
+ // console.log(JSON.stringify(this.layerConfig));
- 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.
- 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;
- }
- }
+ this.$gutter.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";
- if (!added)
- foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));
+ // Horizontal scrollbar visibility may have changed, which changes
+ // the client height of the scroller
+ if (horizScrollChanged)
+ this.onResize(true);
+ };
- if (this.$useWrapMode)
- this.$updateWrapData(foldLine.start.row, foldLine.start.row);
+ this.$updateLines = function() {
+ var firstRow = this.$changedLines.firstRow;
+ var lastRow = this.$changedLines.lastRow;
+ this.$changedLines = null;
- // Notify that fold data has changed.
- this.$modified = true;
- this._dispatchEvent("changeFold", { data: fold });
+ var layerConfig = this.layerConfig;
- return fold;
+ // if the update changes the width of the document do a full redraw
+ if (layerConfig.width != this.$getLongestLine())
+ return this.$textLayer.update(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.addFolds = function(folds) {
- folds.forEach(function(fold) {
- this.addFold(fold);
- }, this);
+ 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.removeFold = function(fold) {
- var foldLine = fold.foldLine;
- var startRow = foldLine.start.row;
- var endRow = foldLine.end.row;
+ /**
+ * VirtualRenderer.updateFrontMarkers() -> Void
+ *
+ * Schedules an update to all the front markers in the document.
+ **/
+ this.updateFrontMarkers = function() {
+ this.$markerFront.setMarkers(this.session.getMarkers(true));
+ this.$loop.schedule(this.CHANGE_MARKER_FRONT);
+ };
- var foldLines = this.$foldData,
- 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.
- {
- var newFoldLine = foldLine.split(fold.start.row, fold.start.column);
- newFoldLine.folds.shift();
- foldLine.start.row = folds[0].start.row;
- foldLine.start.column = folds[0].start.column;
- this.$addFoldLine(newFoldLine);
- }
+ /**
+ * VirtualRenderer.updateBackMarkers() -> Void
+ *
+ * Schedules an update to all the back markers in the document.
+ **/
+ this.updateBackMarkers = function() {
+ this.$markerBack.setMarkers(this.session.getMarkers());
+ this.$loop.schedule(this.CHANGE_MARKER_BACK);
+ };
- if (this.$useWrapMode) {
- this.$updateWrapData(startRow, endRow);
- }
+ /**
+ * VirtualRenderer.addGutterDecoration(row, className) -> Void
+ * - row (Number): The row number
+ * - className (String): The class to add
+ *
+ * Adds `className` to the `row`, to be used for CSS stylings and whatnot.
+ **/
+ this.addGutterDecoration = function(row, className){
+ this.$gutterLayer.addGutterDecoration(row, className);
+ this.$loop.schedule(this.CHANGE_GUTTER);
+ };
- // Notify that fold data has changed.
- this.$modified = true;
- this._dispatchEvent("changeFold", { data: fold });
- }
+ /**
+ * VirtualRenderer.removeGutterDecoration(row, className)-> Void
+ * - row (Number): The row number
+ * - className (String): The class to add
+ *
+ * Removes `className` from the `row`.
+ **/
+ this.removeGutterDecoration = function(row, className){
+ this.$gutterLayer.removeGutterDecoration(row, className);
+ this.$loop.schedule(this.CHANGE_GUTTER);
+ };
- 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]);
- }
+ /**
+ * VirtualRenderer.setBreakpoints(rows) -> Void
+ * - rows (Array): An array containg row numbers
+ *
+ * Sets a breakpoint for every row number indicated on `rows`.
+ **/
+ this.setBreakpoints = function(rows) {
+ this.$gutterLayer.setBreakpoints(rows);
+ this.$loop.schedule(this.CHANGE_GUTTER);
+ };
- cloneFolds.forEach(function(fold) {
- this.removeFold(fold);
- }, this);
- this.$modified = true;
- }
+ /**
+ * VirtualRenderer.setAnnotations(annotations) -> Void
+ * - annotations (Array): An array containing annotations
+ *
+ * Sets annotations for the gutter.
+ **/
+ this.setAnnotations = function(annotations) {
+ this.$gutterLayer.setAnnotations(annotations);
+ this.$loop.schedule(this.CHANGE_GUTTER);
+ };
- this.expandFold = function(fold) {
- this.removeFold(fold);
- fold.subFolds.forEach(function(fold) {
- this.addFold(fold);
- }, this);
- fold.subFolds = [];
- }
+ /**
+ * VirtualRenderer.updateCursor() -> Void
+ *
+ * Updates the cursor icon.
+ **/
+ this.updateCursor = function() {
+ this.$loop.schedule(this.CHANGE_CURSOR);
+ };
- this.expandFolds = function(folds) {
- folds.forEach(function(fold) {
- this.expandFold(fold);
- }, this);
- }
+ /**
+ * VirtualRenderer.hideCursor() -> Void
+ *
+ * Hides the cursor icon.
+ **/
+ this.hideCursor = function() {
+ this.$cursorLayer.hideCursor();
+ };
/**
- * Checks if a given documentRow is folded. This is true if there are some
- * folded parts such that some parts of the line is still visible.
- **/
- this.isRowFolded = function(docRow, startFoldRow) {
- return !!this.getFoldLine(docRow, startFoldRow);
+ * VirtualRenderer.showCursor() -> Void
+ *
+ * Shows the cursor icon.
+ **/
+ this.showCursor = function() {
+ this.$cursorLayer.showCursor();
};
- this.getRowFoldEnd = function(docRow, startFoldRow) {
- var foldLine = this.getFoldLine(docRow, startFoldRow);
- return (foldLine
- ? foldLine.end.row
- : docRow)
+ 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.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) {
- if (startRow == null) {
- startRow = foldLine.start.row;
- startColumn = 0;
- }
+ /**
+ * VirtualRenderer.scrollCursorIntoView(cursor, offset) -> Void
+ *
+ * Scrolls the cursor into the first visibile area of the editor
+ **/
+ this.scrollCursorIntoView = function(cursor, offset) {
+ // the editor is not visible
+ if (this.$size.scrollerHeight === 0)
+ return;
- if (endRow == null) {
- endRow = foldLine.end.row;
- endColumn = this.getLine(endRow).length;
+ 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);
}
- // Build the textline using the FoldLine walker.
- var line = "";
- var doc = this.doc;
- var textLine = "";
+ var scrollLeft = this.scrollLeft;
- foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) {
- 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;
+ 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.getDisplayLine = function(row, endColumn, startRow, startColumn) {
- var foldLine = this.getFoldLine(row);
+ /** related to: EditSession.getScrollTop
+ * VirtualRenderer.getScrollTop() -> Number
+ *
+ * {:EditSession.getScrollTop}
+ **/
+ this.getScrollTop = function() {
+ return this.session.getScrollTop();
+ };
- 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);
- }
+ /** related to: EditSession.getScrollLeft
+ * VirtualRenderer.getScrollLeft() -> Number
+ *
+ * {:EditSession.getScrollLeft}
+ **/
+ this.getScrollLeft = function() {
+ return this.session.getScrollLeft();
};
- this.$cloneFoldData = function() {
- var foldData = this.$foldData;
- var fd = [];
- fd = this.$foldData.map(function(foldLine) {
- var folds = foldLine.folds.map(function(fold) {
- return fold.clone();
- });
- return new FoldLine(fd, folds);
- });
+ /**
+ * VirtualRenderer.getScrollTopRow() -> Number
+ *
+ * Returns the first visible row, regardless of whether it's fully visible or not.
+ **/
+ this.getScrollTopRow = function() {
+ return this.scrollTop / this.lineHeight;
+ };
- return fd;
+ /**
+ * VirtualRenderer.getScrollBottomRow() -> Number
+ *
+ * Returns the last visible row, regardless of whether it's fully visible or not.
+ **/
+ this.getScrollBottomRow = function() {
+ return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1);
};
-}
-exports.Folding = Folding;
+ /** related to: EditSession.setScrollTop
+ * VirtualRenderer.scrollToRow(row) -> Void
+ * - row (Number): A row id
+ *
+ * Gracefully scrolls the top of the editor to the row indicated.
+ **/
+ this.scrollToRow = function(row) {
+ this.session.setScrollTop(row * this.lineHeight);
+ };
-});/* vim:ts=4:sts=4:sw=4:
- * ***** 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):
- * Julian Viereck
- *
- * 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 ***** */
+ this.STEPS = 8;
+ this.$calcSteps = function(fromValue, toValue){
+ var i = 0;
+ var l = this.STEPS;
+ var steps = [];
-define('ace/edit_session/fold_line', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
+ var func = function(t, x_min, dx) {
+ return dx * (Math.pow(t - 1, 3) + 1) + x_min;
+ };
-var Range = require("ace/range").Range;
+ for (i = 0; i < l; ++i)
+ steps.push(func(i / this.STEPS, fromValue, toValue - fromValue));
+
+ return steps;
+ };
+
+ /**
+ * VirtualRenderer.scrollToLine(line, center, animate, callback) -> Void
+ * - line (Number): A line number
+ * - center (Boolean): If `true`, centers the editor the to indicated line
+ * - animate (Boolean): If `true` animates scrolling
+ * - callback (Function): Function to be called after the animation has finished
+ *
+ * Gracefully scrolls the editor to the row indicated.
+ **/
+ 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;
-/**
- * If the an array is passed in, the folds are expected to be sorted already.
- */
-function FoldLine(foldData, folds) {
- this.foldData = foldData;
- if (Array.isArray(folds)) {
- this.folds = folds;
- } else {
- folds = this.folds = [ folds ];
- }
+ var initialScroll = this.scrollTop;
+ this.session.setScrollTop(offset);
+ if (animate !== false)
+ this.animateScrolling(initialScroll, callback);
+ };
- 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.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 {
+ this.$inScrollAnimation = false;
+ clearInterval(_self.$timer);
+
+ _self.session.$scrollTop = -1;
+ _self.session.setScrollTop(toValue);
+ callback && callback();
+ }
+ }, 10);
+ }
+ };
+
+ /**
+ * VirtualRenderer.scrollToY(scrollTop) -> Number
+ * - scrollTop (Number): The position to scroll to
+ *
+ * Scrolls the editor to the y pixel indicated.
+ *
+ **/
+ 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.folds.forEach(function(fold) {
- fold.setFoldLine(this);
- }, this);
-}
+ /**
+ * VirtualRenderer.scrollToX(scrollLeft) -> Number
+ * - scrollLeft (Number): The position to scroll to
+ *
+ * Scrolls the editor to the x pixel indicated.
+ *
+ **/
+ this.scrollToX = function(scrollLeft) {
+ if (scrollLeft <= this.$padding)
+ scrollLeft = 0;
+
+ if (this.scrollLeft !== scrollLeft)
+ this.scrollLeft = scrollLeft;
+ this.$loop.schedule(this.CHANGE_H_SCROLL);
+ };
-(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;
- });
- }
+ * VirtualRenderer.scrollBy(deltaX, deltaY) -> Void
+ * - deltaX (Number): The x value to scroll by
+ * - deltaY (Number): The y value to scroll by
+ *
+ * Scrolls the editor across both x- and y-axes.
+ **/
+ this.scrollBy = function(deltaX, deltaY) {
+ deltaY && this.session.setScrollTop(this.session.getScrollTop() + deltaY);
+ deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX);
+ };
- 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;
- }
+ /**
+ * VirtualRenderer.isScrollableBy(deltaX, deltaY) -> Boolean
+ * - deltaX (Number): The x value to scroll by
+ * - deltaY (Number): The y value to scroll by
+ *
+ * Returns `true` if you can still scroll by either parameter; in other words, you haven't reached the end of the file or line.
+ **/
+ 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();
- this.containsRow = function(row) {
- return row >= this.start.row && row <= this.end.row;
- }
+ 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);
- this.walk = function(callback, endRow, endColumn) {
- var lastEnd = 0,
- folds = this.folds,
- fold,
- comp, stop, isNewRow = true;
+ return {row: row, column: col, side: offset - col > 0 ? 1 : -1};
+ };
- if (endRow == null) {
- endRow = this.end.row;
- endColumn = this.end.column;
- }
+ 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
+ );
- for (var i = 0; i < folds.length; i++) {
- fold = folds[i];
+ return this.session.screenToDocumentPosition(row, Math.max(col, 0));
+ };
- comp = fold.range.compareStart(endRow, endColumn);
- // This fold is after the endRow/Column.
- if (comp == -1) {
- callback(null, endRow, endColumn, lastEnd, isNewRow);
- return;
- }
+ /**
+ * VirtualRenderer.textToScreenCoordinates(row, column) -> Object
+ * - row (Number): The document row position
+ * - column (Number): The document column position
+ *
+ * Returns an object containing the `pageX` and `pageY` coordinates of the document position.
+ *
+ *
+ **/
+ this.textToScreenCoordinates = function(row, column) {
+ var canvasPos = this.scroller.getBoundingClientRect();
+ var pos = this.session.documentToScreenPosition(row, column);
- stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow);
- stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd);
+ var x = this.$padding + Math.round(pos.column * this.characterWidth);
+ var y = pos.row * this.lineHeight;
- // 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;
- }
+ return {
+ pageX: canvasPos.left + x - this.scrollLeft,
+ pageY: canvasPos.top + y - this.scrollTop
+ };
+ };
- // 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);
- }
+ /**
+ * VirtualRenderer.visualizeFocus() -> Void
+ *
+ * Focuses the current container.
+ **/
+ this.visualizeFocus = function() {
+ dom.addCssClass(this.container, "ace_focus");
+ };
- 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;
- }
+ /**
+ * VirtualRenderer.visualizeBlur() -> Void
+ *
+ * Blurs the current container.
+ **/
+ this.visualizeBlur = function() {
+ dom.removeCssClass(this.container, "ace_focus");
+ };
- 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)
- {
- throw "Moving characters inside of a fold should never be reached";
- } 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;
- }
+ /** internal, hide
+ * VirtualRenderer.showComposition(position) -> Void
+ * - position (Number):
+ *
+ **/
+ this.showComposition = function(position) {
+ if (!this.$composition) {
+ this.$composition = dom.createElement("div");
+ this.$composition.className = "ace_composition";
+ this.content.appendChild(this.$composition);
}
- }
- this.split = function(row, column) {
- var fold = this.getNextFoldTo(row, column).fold,
- folds = this.folds;
- var foldData = this.foldData;
+ this.$composition.innerHTML = " ";
- 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;
+ var pos = this.$cursorLayer.getPixelPosition();
+ var style = this.$composition.style;
+ style.top = pos.top + "px";
+ style.left = (pos.left + this.$padding) + "px";
+ style.height = this.lineHeight + "px";
- // Remove the folds after row/column and create a new FoldLine
- // containing these removed folds.
- folds = folds.splice(i, folds.length - i);
+ this.hideCursor();
+ };
- var newFoldLine = new FoldLine(foldData, folds);
- foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);
- return newFoldLine;
- }
+ /**
+ * VirtualRenderer.setCompositionText(text) -> Void
+ * - text (String): A string of text to use
+ *
+ * Sets the inner text of the current composition to `text`.
+ **/
+ this.setCompositionText = function(text) {
+ dom.setInnerText(this.$composition, text);
+ };
- 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);
- }
+ /**
+ * VirtualRenderer.hideComposition() -> Void
+ *
+ * Hides the current composition.
+ **/
+ this.hideComposition = function() {
+ this.showCursor();
- this.toString = function() {
- var ret = [this.range.toString() + ": [" ];
+ if (!this.$composition)
+ return;
- this.folds.forEach(function(fold) {
- ret.push(" " + fold.toString());
- });
- ret.push("]")
- return ret.join("\n");
- }
+ var style = this.$composition.style;
+ style.top = "-10000px";
+ style.left = "-10000px";
+ };
- this.idxToPosition = function(idx) {
- var lastFoldEndColumn = 0;
- var fold;
+ this._loadTheme = function(name, callback) {
+ if (!config.get("packaged"))
+ return callback();
- for (var i = 0; i < this.folds.length; i++) {
- var fold = this.folds[i];
+ var base = name.split("/").pop();
+ var filename = config.get("themePath") + "/theme-" + base + config.get("suffix");
+ net.loadScript(filename, callback);
+ };
- idx -= fold.start.column - lastFoldEndColumn;
- if (idx < 0) {
- return {
- row: fold.start.row,
- column: fold.start.column + idx
- };
- }
+ /**
+ * VirtualRenderer.setTheme(theme) -> Void
+ * - theme (String): The path to a theme
+ *
+ * [Sets a new theme for the editor. `theme` should exist, and be a directory path, like `ace/theme/textmate`.]{: #VirtualRenderer.setTheme}
+ **/
+ this.setTheme = function(theme) {
+ var _self = this;
- idx -= fold.placeholder.length;
- if (idx < 0) {
- return fold.start;
- }
+ this.$themeValue = theme;
+ if (!theme || typeof theme == "string") {
+ var moduleName = theme || "ace/theme/textmate";
- lastFoldEndColumn = fold.end.column;
+ 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);
}
- return {
- row: this.end.row,
- column: this.end.column + idx
- };
- }
-}).call(FoldLine.prototype);
+ function afterLoad(theme) {
+ dom.importCssString(
+ theme.cssText,
+ theme.cssClass,
+ _self.container.ownerDocument
+ );
-exports.FoldLine = FoldLine;
-});/* vim:ts=4:sts=4:sw=4:
- * ***** 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):
- * Julian Viereck
- *
- * 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 ***** */
+ if (_self.$theme)
+ dom.removeCssClass(_self.container, _self.$theme);
-define('ace/edit_session/fold', ['require', 'exports', 'module' ], function(require, exports, module) {
+ _self.$theme = theme ? theme.cssClass : null;
-/**
- * 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;
+ if (_self.$theme)
+ dom.addCssClass(_self.container, _self.$theme);
- this.sameRow = range.start.row == range.end.row;
- this.subFolds = [];
-};
+ 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();
+ }
+ }
+ };
+
+ /**
+ * VirtualRenderer.getTheme() -> String
+ *
+ * [Returns the path of the current theme.]{: #VirtualRenderer.getTheme}
+ **/
+ this.getTheme = function() {
+ return this.$themeValue;
+ };
-(function() {
+ // 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.
- this.toString = function() {
- return '"' + this.placeholder + '" ' + this.range.toString();
+ /**
+ * VirtualRenderer.setStyle(style) -> Void
+ * - 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.setFoldLine = function(foldLine) {
- this.foldLine = foldLine;
- this.subFolds.forEach(function(fold) {
- fold.setFoldLine(foldLine);
- });
+ /**
+ * VirtualRenderer.unsetStyle(style) -> Void
+ * - style (String): A class name
+ *
+ * [Removes the class `style` from the editor.]{: #VirtualRenderer.unsetStyle}
+ **/
+ this.unsetStyle = function unsetStyle(style) {
+ dom.removeCssClass(this.container, style);
};
- 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;
+ /**
+ * VirtualRenderer.destroy()
+ *
+ * Destroys the text and cursor layers for this renderer.
+ **/
+ this.destroy = function() {
+ this.$textLayer.destroy();
+ this.$cursorLayer.destroy();
};
-}).call(Fold.prototype);
+}).call(VirtualRenderer.prototype);
-});/* vim:ts=4:sts=4:sw=4:
+exports.VirtualRenderer = VirtualRenderer;
+});
+/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@@ -12667,7 +16064,7 @@ var Fold = exports.Fold = function(range, placeholder) {
*
* Contributor(s):
* Fabian Jakobs
- * Mihai Sucan
+ * Julian Viereck
*
* 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
@@ -12683,300 +16080,153 @@ var Fold = exports.Fold = function(range, placeholder) {
*
* ***** END LICENSE BLOCK ***** */
-define('ace/search', ['require', 'exports', 'module' , 'pilot/lang', 'pilot/oop', 'ace/range'], function(require, exports, module) {
-
-var lang = require("pilot/lang");
-var oop = require("pilot/oop");
-var Range = require("ace/range").Range;
-
-var Search = function() {
- this.$options = {
- needle: "",
- backwards: false,
- wrap: false,
- caseSensitive: false,
- wholeWord: false,
- scope: Search.ALL,
- regExp: false
- };
-};
-
-Search.ALL = 1;
-Search.SELECTION = 2;
+define('ace/layer/gutter', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
+"use strict";
-(function() {
+var dom = require("../lib/dom");
+var oop = require("../lib/oop");
+var EventEmitter = require("../lib/event_emitter").EventEmitter;
- this.set = function(options) {
- oop.mixin(this.$options, options);
- return this;
- };
+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.getOptions = function() {
- return lang.copyObject(this.$options);
- };
-
- this.find = function(session) {
- if (!this.$options.needle)
- return null;
-
- if (this.$options.backwards) {
- var iterator = this.$backwardMatchIterator(session);
- } else {
- iterator = this.$forwardMatchIterator(session);
- }
-
- var firstRange = null;
- iterator.forEach(function(range) {
- firstRange = range;
- return true;
- });
-
- return firstRange;
- };
-
- this.findAll = function(session) {
- if (!this.$options.needle)
- return [];
-
- if (this.$options.backwards) {
- var iterator = this.$backwardMatchIterator(session);
- } else {
- iterator = this.$forwardMatchIterator(session);
- }
-
- var ranges = [];
- iterator.forEach(function(range) {
- ranges.push(range);
- });
-
- return ranges;
- };
-
- this.replace = function(input, replacement) {
- var re = this.$assembleRegExp();
- var match = re.exec(input);
- if (match && match[0].length == input.length) {
- if (this.$options.regExp) {
- return input.replace(re, replacement);
- } else {
- return replacement;
- }
- } else {
- return null;
- }
- };
-
- this.$forwardMatchIterator = function(session) {
- var re = this.$assembleRegExp();
- var self = this;
-
- return {
- forEach: function(callback) {
- self.$forwardLineIterator(session).forEach(function(line, startIndex, row) {
- if (startIndex) {
- line = line.substring(startIndex);
- }
-
- var matches = [];
-
- line.replace(re, function(str) {
- var offset = arguments[arguments.length-2];
- matches.push({
- str: str,
- offset: startIndex + offset
- });
- return str;
- });
-
- for (var i=0; i= 0; i--) {
- var match = matches[i];
- var range = self.$rangeFromMatch(row, match.offset, match.str.length);
- if (callback(range))
- return true;
- }
- });
- }
- };
- };
-
- this.$rangeFromMatch = function(row, column, length) {
- return new Range(row, column, row, column+length);
- };
-
- this.$assembleRegExp = function() {
- if (this.$options.regExp) {
- var needle = this.$options.needle;
- } else {
- needle = lang.escapeRegExp(this.$options.needle);
- }
-
- if (this.$options.wholeWord) {
- needle = "\\b" + needle + "\\b";
- }
-
- var modifier = "g";
- if (!this.$options.caseSensitive) {
- modifier += "i";
- }
-
- var re = new RegExp(needle, modifier);
- return re;
- };
-
- this.$forwardLineIterator = function(session) {
- var searchSelection = this.$options.scope == Search.SELECTION;
-
- var range = session.getSelection().getRange();
- var start = session.getSelection().getCursor();
-
- var firstRow = searchSelection ? range.start.row : 0;
- var firstColumn = searchSelection ? range.start.column : 0;
- var lastRow = searchSelection ? range.end.row : session.getLength() - 1;
-
- var wrap = this.$options.wrap;
- var inWrap = false;
-
- function getLine(row) {
- var line = session.getLine(row);
- if (searchSelection && row == range.end.row) {
- line = line.substring(0, range.end.column);
- }
- if (inWrap && row == start.row) {
- line = line.substring(0, start.column);
- }
- return line;
- }
-
- return {
- forEach: function(callback) {
- var row = start.row;
-
- var line = getLine(row);
- var startIndex = start.column;
-
- var stop = false;
- inWrap = false;
-
- while (!callback(line, startIndex, row)) {
-
- if (stop) {
- return;
- }
-
- row++;
- startIndex = 0;
+ this.gutterWidth = 0;
- if (row > lastRow) {
- if (wrap) {
- row = firstRow;
- startIndex = firstColumn;
- inWrap = true;
- } else {
- return;
- }
- }
+ this.$breakpoints = [];
+ this.$annotations = [];
+ this.$decorations = [];
+};
- if (row == start.row)
- stop = true;
+(function() {
- line = getLine(row);
- }
- }
- };
+ oop.implement(this, EventEmitter);
+
+ this.setSession = function(session) {
+ this.session = session;
};
- this.$backwardLineIterator = function(session) {
- var searchSelection = this.$options.scope == Search.SELECTION;
+ this.addGutterDecoration = function(row, className){
+ if (!this.$decorations[row])
+ this.$decorations[row] = "";
+ this.$decorations[row] += " " + className;
+ };
- var range = session.getSelection().getRange();
- var start = searchSelection ? range.end : range.start;
+ this.removeGutterDecoration = function(row, className){
+ this.$decorations[row] = this.$decorations[row].replace(" " + className, "");
+ };
- var firstRow = searchSelection ? range.start.row : 0;
- var firstColumn = searchSelection ? range.start.column : 0;
- var lastRow = searchSelection ? range.end.row : session.getLength() - 1;
+ this.setBreakpoints = function(rows) {
+ this.$breakpoints = rows.concat();
+ };
- var wrap = this.$options.wrap;
+ 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;
- return {
- forEach : function(callback) {
- var row = start.row;
+ 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;
- row--;
- startIndex = 0;
+ var annotation = this.$annotations[i] || emptyAnno;
+ html.push("", (i+1));
- if (row < firstRow) {
- if (wrap) {
- row = lastRow;
- inWrap = true;
- } else {
- return;
- }
- }
+ 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(
+ ""
+ );
+ }
- if (row == start.row)
- stop = true;
+ var wrappedRowLength = this.session.getRowLength(i) - 1;
+ while (wrappedRowLength--) {
+ html.push("
\xA6");
+ }
- line = session.getLine(row);
- if (searchSelection) {
- if (row == firstRow)
- startIndex = firstColumn;
- else if (row == lastRow)
- line = line.substring(0, range.end.column);
- }
+ html.push("
");
- if (inWrap && row == start.row)
- startIndex = start.column;
- }
- }
- };
+ i++;
+ }
+ this.element = dom.setInnerHtml(this.element, html.join(""));
+ this.element.style.height = config.minHeight + "px";
+
+ var gutterWidth = this.element.offsetWidth;
+ if (gutterWidth !== this.gutterWidth) {
+ this.gutterWidth = gutterWidth;
+ this._emit("changeGutterWidth", gutterWidth);
+ }
};
-}).call(Search.prototype);
+ 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.getShowFoldWidgets = function() {
+ return this.$showFoldWidgets;
+ };
+
+}).call(Gutter.prototype);
+
+exports.Gutter = Gutter;
-exports.Search = Search;
});
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
@@ -13001,7 +16251,7 @@ exports.Search = Search;
*
* Contributor(s):
* Fabian Jakobs
- * Mihai Sucan
+ * Julian Viereck
*
* 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
@@ -13017,59 +16267,179 @@ exports.Search = Search;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/undomanager', ['require', 'exports', 'module' ], function(require, exports, module) {
+define('ace/layer/marker', ['require', 'exports', 'module' , 'ace/range', 'ace/lib/dom'], function(require, exports, module) {
+"use strict";
-var UndoManager = function() {
- this.reset();
+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.execute = function(options) {
- var deltas = options.args[0];
- this.$doc = options.args[1];
- this.$undoStack.push(deltas);
- this.$redoStack = [];
+ 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];
+
+ 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");
+ }
};
- 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;
+ // Draws a multi line marker, where lines span the full width
+ this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig, type) {
+ var padding = type === "background" ? 0 : this.$padding;
+ var layerWidth = layerConfig.width + 2 * this.$padding - padding;
+ // from selection start to the end of the line
+ var height = layerConfig.lineHeight;
+ var width = Math.round(layerWidth - (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(
+ ""
+ );
+
+ // from start of the last line to the selection end
+ top = this.$getTop(range.end.row, layerConfig);
+ width = Math.round(range.end.column * layerConfig.characterWidth);
+
+ stringBuilder.push(
+ ""
+ );
+
+ // all the complete lines
+ height = (range.end.row - range.start.row - 1) * layerConfig.lineHeight;
+ if (height < 0)
+ return;
+ top = this.$getTop(range.start.row + 1, layerConfig);
+
+ stringBuilder.push(
+ ""
+ );
};
- 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;
- };
+ // 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;
- this.reset = function() {
- this.$undoStack = [];
- this.$redoStack = [];
- };
+ if (type === "background")
+ var width = layerConfig.width;
+ else
+ width = Math.round((range.end.column + (extraLength || 0) - range.start.column) * layerConfig.characterWidth);
- this.hasUndo = function() {
- return this.$undoStack.length > 0;
- };
+ var top = this.$getTop(range.start.row, layerConfig);
+ var left = Math.round(
+ padding + range.start.column * layerConfig.characterWidth
+ );
- this.hasRedo = function() {
- return this.$redoStack.length > 0;
+ stringBuilder.push(
+ ""
+ );
};
-}).call(UndoManager.prototype);
+}).call(Marker.prototype);
+
+exports.Marker = Marker;
-exports.UndoManager = UndoManager;
});
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
@@ -13093,820 +16463,791 @@ exports.UndoManager = UndoManager;
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Fabian Jakobs
+ * Fabian Jakobs
+ * Julian Viereck
+ * Mihai Sucan
* Irakli Gozalishvili (http://jeditoolkit.com)
- * Julian Viereck
*
* 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('ace/virtual_renderer', ['require', 'exports', 'module' , 'pilot/oop', 'pilot/dom', 'pilot/event', 'pilot/useragent', 'ace/layer/gutter', 'ace/layer/marker', 'ace/layer/text', 'ace/layer/cursor', 'ace/scrollbar', 'ace/renderloop', 'pilot/event_emitter', 'text/ace/css/editor.css'], function(require, exports, module) {
-
-var oop = require("pilot/oop");
-var dom = require("pilot/dom");
-var event = require("pilot/event");
-var useragent = require("pilot/useragent");
-var GutterLayer = require("ace/layer/gutter").Gutter;
-var MarkerLayer = require("ace/layer/marker").Marker;
-var TextLayer = require("ace/layer/text").Text;
-var CursorLayer = require("ace/layer/cursor").Cursor;
-var ScrollBar = require("ace/scrollbar").ScrollBar;
-var RenderLoop = require("ace/renderloop").RenderLoop;
-var EventEmitter = require("pilot/event_emitter").EventEmitter;
-var editorCss = require("text/ace/css/editor.css");
-
-// import CSS once
-dom.importCssString(editorCss);
-
-var VirtualRenderer = function(container, theme) {
- this.container = container;
- dom.addCssClass(this.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.$gutterLayer = new GutterLayer(this.$gutter);
- 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 = true;
- this.$horizScrollAlwaysVisible = true;
-
- this.scrollBar = new ScrollBar(container);
- this.scrollBar.addEventListener("scroll", this.onScroll.bind(this));
-
- this.scrollTop = 0;
-
- this.cursorPos = {
- row : 0,
- column : 0
- };
-
- var _self = this;
- this.$textLayer.addEventListener("changeCharaterSize", function() {
- _self.characterWidth = textLayer.getCharacterWidth();
- _self.lineHeight = textLayer.getLineHeight();
- _self.$updatePrintMargin();
- _self.onResize(true);
-
- _self.$loop.schedule(_self.CHANGE_FULL);
- });
- event.addListener(this.$gutter, "click", this.$onGutterClick.bind(this));
- event.addListener(this.$gutter, "dblclick", this.$onGutterClick.bind(this));
-
- 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.$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;
-
- oop.implement(this, EventEmitter);
-
- this.setSession = function(session) {
- this.session = session;
- 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);
- };
-
- /**
- * Triggers partial update of the text layer
- */
- 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);
- };
-
- /**
- * Triggers full update of the text layer
- */
- this.updateText = function() {
- this.$loop.schedule(this.CHANGE_TEXT);
- };
-
- /**
- * Triggers a full update of all layers
- */
- this.updateFull = function() {
- this.$loop.schedule(this.CHANGE_FULL);
- };
-
- this.updateFontSize = function() {
- this.$textLayer.checkForSizeChanges();
- };
-
- /**
- * Triggers resize of the editor
- */
- this.onResize = function(force) {
- var changes = this.CHANGE_SIZE;
- var size = this.$size;
-
- var 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.scrollToY(this.getScrollTop());
- changes = changes | this.CHANGE_FULL;
- }
- }
-
- var width = dom.getInnerWidth(this.container);
- if (force || 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.width = size.scrollerWidth + "px";
-
- if (this.session.getUseWrapMode() && this.adjustWrapLimit() || force)
- changes = changes | this.CHANGE_FULL;
- }
-
- this.$loop.schedule(changes);
- };
-
- this.adjustWrapLimit = function(){
- var availableWidth = this.$size.scrollerWidth - this.$padding * 2;
- var limit = Math.floor(availableWidth / this.characterWidth) - 1;
- return this.session.adjustWrapLimit(limit);
- };
+ * 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 ***** */
- this.$onGutterClick = function(e) {
- var pageX = event.getDocumentX(e);
- var pageY = event.getDocumentY(e);
+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) {
+"use strict";
- this._dispatchEvent("gutter" + e.type, {
- row: this.screenToTextCoordinates(pageX, pageY).row,
- htmlEvent: e
- });
- };
+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;
- this.setShowInvisibles = function(showInvisibles) {
- if (this.$textLayer.setShowInvisibles(showInvisibles))
- this.$loop.schedule(this.CHANGE_TEXT);
- };
+var Text = function(parentEl) {
+ this.element = dom.createElement("div");
+ this.element.className = "ace_layer ace_text-layer";
+ parentEl.appendChild(this.element);
- this.getShowInvisibles = function() {
- return this.$textLayer.showInvisibles;
- };
+ this.$characterSize = this.$measureSizes() || {width: 0, height: 0};
+ this.$pollSizeChanges();
+};
- this.$showPrintMargin = true;
- this.setShowPrintMargin = function(showPrintMargin) {
- this.$showPrintMargin = showPrintMargin;
- this.$updatePrintMargin();
- };
+(function() {
- this.getShowPrintMargin = function() {
- return this.$showPrintMargin;
- };
+ oop.implement(this, EventEmitter);
- this.$printMarginColumn = 80;
- this.setPrintMarginColumn = function(showPrintMargin) {
- this.$printMarginColumn = showPrintMargin;
- this.$updatePrintMargin();
- };
+ this.EOF_CHAR = "\xB6"; //"¶";
+ this.EOL_CHAR = "\xAC"; //"¬";
+ this.TAB_CHAR = "\u2192"; //"→";
+ this.SPACE_CHAR = "\xB7"; //"·";
+ this.$padding = 0;
- this.getPrintMarginColumn = function() {
- return this.$printMarginColumn;
+ this.setPadding = function(padding) {
+ this.$padding = padding;
+ this.element.style.padding = "0 " + padding + "px";
};
- this.getShowGutter = function(){
- return this.showGutter;
+ this.getLineHeight = function() {
+ return this.$characterSize.height || 1;
};
- this.setShowGutter = function(show){
- if(this.showGutter === show)
- return;
- this.$gutter.style.display = show ? "block" : "none";
- this.showGutter = show;
- this.onResize(true);
+ this.getCharacterWidth = function() {
+ return this.$characterSize.width || 1;
};
- 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);
+ 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});
}
-
- var style = this.$printMarginEl.style;
- style.left = ((this.characterWidth * this.$printMarginColumn) + this.$padding * 2) + "px";
- style.visibility = this.$showPrintMargin ? "visible" : "hidden";
- };
-
- this.getContainerElement = function() {
- return this.container;
};
- this.getMouseEventTarget = function() {
- return this.content;
+ this.$pollSizeChanges = function() {
+ var self = this;
+ this.$pollSizeChangesTimer = setInterval(function() {
+ self.checkForSizeChanges();
+ }, 500);
};
- this.getTextAreaContainer = function() {
- return this.container;
+ this.$fontStyles = {
+ fontFamily : 1,
+ fontSize : 1,
+ fontWeight : 1,
+ fontStyle : 1,
+ lineHeight : 1
};
- this.moveTextAreaToCursor = function(textarea) {
- // in IE the native cursor always shines through
- if (useragent.isIE)
- return;
-
- var pos = this.$cursorLayer.getPixelPosition();
- if (!pos)
- return;
+ this.$measureSizes = useragent.isIE || useragent.isOldGecko ? function() {
+ var n = 1000;
+ if (!this.$measureNode) {
+ var measureNode = this.$measureNode = dom.createElement("div");
+ var style = measureNode.style;
- var bounds = this.content.getBoundingClientRect();
- var offset = this.layerConfig.offset;
+ style.width = style.height = "auto";
+ style.left = style.top = (-n * 40) + "px";
- textarea.style.left = (bounds.left + pos.left + this.$padding) + "px";
- textarea.style.top = (bounds.top + pos.top - this.scrollTop + offset) + "px";
- };
+ style.visibility = "hidden";
+ style.position = "fixed";
+ style.overflow = "visible";
+ style.whiteSpace = "nowrap";
- this.getFirstVisibleRow = function() {
- return this.layerConfig.firstRow;
- };
+ // 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);
- this.getFirstFullyVisibleRow = function() {
- return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1);
- };
+ 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;
- this.getLastFullyVisibleRow = function() {
- var flint = Math.floor((this.layerConfig.height + this.layerConfig.offset) / this.layerConfig.lineHeight);
- return this.layerConfig.firstRow - 1 + flint;
- };
+ var style = this.$measureNode.style;
+ var computedStyle = dom.computedStyle(this.element);
+ for (var prop in this.$fontStyles)
+ style[prop] = computedStyle[prop];
- this.getLastVisibleRow = function() {
- return this.layerConfig.lastRow;
- };
+ var size = {
+ height: this.$measureNode.offsetHeight,
+ width: this.$measureNode.offsetWidth / (n * 2)
+ };
- 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();
- };
+ // 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;
- this.getHScrollBarAlwaysVisible = function() {
- return this.$horizScrollAlwaysVisible;
- };
+ return size;
+ }
+ : function() {
+ if (!this.$measureNode) {
+ var measureNode = this.$measureNode = dom.createElement("div");
+ var style = measureNode.style;
- this.setHScrollBarAlwaysVisible = function(alwaysVisible) {
- if (this.$horizScrollAlwaysVisible != alwaysVisible) {
- this.$horizScrollAlwaysVisible = alwaysVisible;
- if (!this.$horizScrollAlwaysVisible || !this.$horizScroll)
- this.$loop.schedule(this.CHANGE_SCROLL);
- }
- };
+ style.width = style.height = "auto";
+ style.left = style.top = -100 + "px";
- this.onScroll = function(e) {
- this.scrollToY(e.data);
- };
+ style.visibility = "hidden";
+ style.position = "fixed";
+ style.overflow = "visible";
+ style.whiteSpace = "nowrap";
- this.$updateScrollBar = function() {
- this.scrollBar.setInnerHeight(this.layerConfig.maxHeight);
- this.scrollBar.setScrollTop(this.scrollTop);
- };
+ measureNode.innerHTML = "X";
- this.$renderChanges = function(changes) {
- if (!changes || !this.session)
- return;
+ var container = this.element.parentNode;
+ while (container && !dom.hasCssClass(container, "ace_editor"))
+ container = container.parentNode;
- // 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();
+ if (!container)
+ return this.$measureNode = null;
- // full
- if (changes & this.CHANGE_FULL) {
- 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.$updateScrollBar();
- return;
+ container.appendChild(measureNode);
}
+
+ var rect = this.$measureNode.getBoundingClientRect();
- // scrolling
- if (changes & this.CHANGE_SCROLL) {
- if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES)
- this.$textLayer.update(this.layerConfig);
- else
- this.$textLayer.scrollLines(this.layerConfig);
+ var size = {
+ height: rect.height,
+ width: rect.width
+ };
- if (this.showGutter)
- this.$gutterLayer.update(this.layerConfig);
- this.$markerBack.update(this.layerConfig);
- this.$markerFront.update(this.layerConfig);
- this.$cursorLayer.update(this.layerConfig);
- this.$updateScrollBar();
- return;
- }
+ // 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;
- if (changes & this.CHANGE_TEXT) {
- this.$textLayer.update(this.layerConfig);
- if (this.showGutter)
- this.$gutterLayer.update(this.layerConfig);
- }
- else if (changes & this.CHANGE_LINES) {
- this.$updateLines();
- this.$updateScrollBar();
- if (this.showGutter)
- this.$gutterLayer.update(this.layerConfig);
- } else if (changes & this.CHANGE_GUTTER) {
- if (this.showGutter)
- this.$gutterLayer.update(this.layerConfig);
- }
+ return size;
+ };
- if (changes & this.CHANGE_CURSOR)
- this.$cursorLayer.update(this.layerConfig);
+ this.setSession = function(session) {
+ this.session = session;
+ };
- if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) {
- this.$markerFront.update(this.layerConfig);
- }
+ this.showInvisibles = false;
+ this.setShowInvisibles = function(showInvisibles) {
+ if (this.showInvisibles == showInvisibles)
+ return false;
- if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) {
- this.$markerBack.update(this.layerConfig);
+ this.showInvisibles = showInvisibles;
+ return true;
+ };
+
+ this.$tabStrings = [];
+ this.$computeTabString = function() {
+ var tabSize = this.session.getTabSize();
+ var tabStr = this.$tabStrings = [0];
+ for (var i = 1; i < tabSize + 1; i++) {
+ if (this.showInvisibles) {
+ tabStr.push(""
+ + this.TAB_CHAR
+ + new Array(i).join(" ")
+ + "");
+ } else {
+ tabStr.push(new Array(i+1).join(" "));
+ }
}
- 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;
+ this.updateLines = function(config, firstRow, lastRow) {
+ this.$computeTabString();
+ // 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 longestLine = this.$getLongestLine();
- var widthChanged = this.layerConfig.width != longestLine;
+ var first = Math.max(firstRow, config.firstRow);
+ var last = Math.min(lastRow, config.lastRow);
- 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";
+ var lineElements = this.element.childNodes;
+ var lineElementsIdx = 0;
- var maxHeight = this.session.getScreenLength() * this.lineHeight;
- this.scrollTop = Math.max(0, Math.min(this.scrollTop, maxHeight - this.$size.scrollerHeight));
+ 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 lineCount = Math.ceil(minHeight / this.lineHeight) - 1;
- var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight));
- var lastRow = firstRow + lineCount;
+ for (var i=first; i<=last; i++) {
+ var lineElement = lineElements[lineElementsIdx++];
+ if (!lineElement)
+ continue;
- // Map lines on the screen to lines in the document.
- var firstRowScreen, firstRowHeight;
- var lineHeight = { lineHeight: this.lineHeight };
- firstRow = session.screenToDocumentRow(firstRow, 0);
+ var html = [];
+ var tokens = this.session.getTokens(i, i);
+ this.$renderLine(html, i, tokens[0].tokens, !this.$useLineGroups());
+ lineElement = dom.setInnerHtml(lineElement, html.join(""));
- // 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;
+ i = this.session.getRowFoldEnd(i);
}
+ };
- firstRowScreen = session.documentToScreenRow(firstRow, 0);
- firstRowHeight = session.getRowHeight(lineHeight, firstRow);
-
- lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1);
- minHeight = this.$size.scrollerHeight + session.getRowHeight(lineHeight, lastRow)+
- firstRowHeight;
+ this.scrollLines = function(config) {
+ this.$computeTabString();
+ var oldConfig = this.config;
+ this.config = config;
- offset = this.scrollTop - firstRowScreen * this.lineHeight;
+ if (!oldConfig || oldConfig.lastRow < config.firstRow)
+ return this.update(config);
- this.layerConfig = {
- width : longestLine,
- padding : this.$padding,
- firstRow : firstRow,
- firstRowScreen: firstRowScreen,
- lastRow : lastRow,
- lineHeight : this.lineHeight,
- characterWidth : this.characterWidth,
- minHeight : minHeight,
- maxHeight : maxHeight,
- offset : offset,
- height : this.$size.scrollerHeight
- };
+ if (config.lastRow < oldConfig.firstRow)
+ return this.update(config);
- // For debugging.
- // console.log(JSON.stringify(this.layerConfig));
+ 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);
- this.$gutterLayer.element.style.marginTop = (-offset) + "px";
- this.content.style.marginTop = (-offset) + "px";
- this.content.style.width = longestLine + "px";
- this.content.style.height = minHeight + "px";
+ if (oldConfig.lastRow > config.lastRow)
+ for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--)
+ el.removeChild(el.lastChild);
- // scroller.scrollWidth was smaller than scrollLeft we needed
- if (this.$desiredScrollLeft) {
- this.scrollToX(this.$desiredScrollLeft);
- this.$desiredScrollLeft = 0;
+ 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);
}
- // Horizontal scrollbar visibility may have changed, which changes
- // the client height of the scroller
- if (horizScrollChanged)
- this.onResize(true);
+ if (config.lastRow > oldConfig.lastRow) {
+ var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);
+ el.appendChild(fragment);
+ }
};
- this.$updateLines = function() {
- var firstRow = this.$changedLines.firstRow;
- var lastRow = this.$changedLines.lastRow;
- this.$changedLines = null;
+ 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;
- var layerConfig = this.layerConfig;
+ 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 the update changes the width of the document do a full redraw
- if (layerConfig.width != this.$getLongestLine())
- return this.$textLayer.update(layerConfig);
+ var container = dom.createElement("div");
- if (firstRow > layerConfig.lastRow + 1) { return; }
- if (lastRow < layerConfig.firstRow) { return; }
+ var html = [];
+ // Get the tokens per line as there might be some lines in between
+ // beeing folded.
+ // OPTIMIZE: If there is a long block of unfolded lines, just make
+ // this call once for that big block of unfolded lines.
+ var tokens = this.session.getTokens(row, row);
+ if (tokens.length == 1)
+ this.$renderLine(html, row, tokens[0].tokens, false);
- // if the last row is unknown -> redraw everything
- if (lastRow === Infinity) {
- if (this.showGutter)
- this.$gutterLayer.update(layerConfig);
- this.$textLayer.update(layerConfig);
- return;
- }
+ // 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]);
+ }
- // else update only the changed rows
- this.$textLayer.updateLines(layerConfig, firstRow, lastRow);
+ row++;
+ }
+ return fragment;
};
- this.$getLongestLine = function() {
- var charCount = this.session.getScreenWidth() + 1;
- if (this.$textLayer.showInvisibles)
- charCount += 1;
-
- return Math.max(this.$size.scrollerWidth, Math.round(charCount * this.characterWidth));
- };
+ this.update = function(config) {
+ this.$computeTabString();
+ this.config = config;
- this.updateFrontMarkers = function() {
- this.$markerFront.setMarkers(this.session.getMarkers(true));
- this.$loop.schedule(this.CHANGE_MARKER_FRONT);
- };
+ var html = [];
+ var firstRow = config.firstRow, lastRow = config.lastRow;
- this.updateBackMarkers = function() {
- this.$markerBack.setMarkers(this.session.getMarkers());
- this.$loop.schedule(this.CHANGE_MARKER_BACK);
- };
+ var row = firstRow;
+ var foldLine = this.session.getNextFoldLine(row);
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
- this.addGutterDecoration = function(row, className){
- this.$gutterLayer.addGutterDecoration(row, className);
- this.$loop.schedule(this.CHANGE_GUTTER);
- };
+ 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;
- this.removeGutterDecoration = function(row, className){
- this.$gutterLayer.removeGutterDecoration(row, className);
- this.$loop.schedule(this.CHANGE_GUTTER);
- };
+ if (this.$useLineGroups())
+ html.push("")
- this.setBreakpoints = function(rows) {
- this.$gutterLayer.setBreakpoints(rows);
- this.$loop.schedule(this.CHANGE_GUTTER);
- };
+ // Get the tokens per line as there might be some lines in between
+ // beeing folded.
+ // OPTIMIZE: If there is a long block of unfolded lines, just make
+ // this call once for that big block of unfolded lines.
+ var tokens = this.session.getTokens(row, row);
+ if (tokens.length == 1)
+ this.$renderLine(html, row, tokens[0].tokens, false);
- this.setAnnotations = function(annotations) {
- this.$gutterLayer.setAnnotations(annotations);
- this.$loop.schedule(this.CHANGE_GUTTER);
- };
+ if (this.$useLineGroups())
+ html.push("
"); // end the line group
- this.updateCursor = function() {
- this.$loop.schedule(this.CHANGE_CURSOR);
+ row++;
+ }
+ this.element = dom.setInnerHtml(this.element, html.join(""));
};
- this.hideCursor = function() {
- this.$cursorLayer.hideCursor();
+ this.$textToken = {
+ "text": true,
+ "rparen": true,
+ "lparen": true
};
- this.showCursor = function() {
- this.$cursorLayer.showCursor();
- };
+ this.$renderToken = function(stringBuilder, screenColumn, token, value) {
+ var self = this;
+ var replaceReg = /\t|&|<|( +)|([\u0000-\u0019\u00a0\u2000-\u200b\u2028\u2029\u3000])|[\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 + "";
+ }
+ };
- this.scrollCursorIntoView = function() {
- // the editor is not visible
- if (this.$size.scrollerHeight === 0)
- return;
+ var output = value.replace(replaceReg, replaceFunc);
- var pos = this.$cursorLayer.getPixelPosition();
+ 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;
+ };
- var left = pos.left + this.$padding;
- var top = pos.top;
+ this.$renderLineCore = function(stringBuilder, lastRow, tokens, splits, onlyContents) {
+ var chars = 0;
+ var split = 0;
+ var splitChars;
+ var screenColumn = 0;
+ var self = this;
- if (this.scrollTop > top) {
- this.scrollToY(top);
- }
+ if (!splits || splits.length == 0)
+ splitChars = Number.MAX_VALUE;
+ else
+ splitChars = splits[0];
- if (this.scrollTop + this.$size.scrollerHeight < top + this.lineHeight) {
- this.scrollToY(top + this.lineHeight - this.$size.scrollerHeight);
+ if (!onlyContents) {
+ stringBuilder.push(""
+ );
}
+
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+ var value = token.value;
- var scrollLeft = this.scroller.scrollLeft;
+ if (chars + value.length < splitChars) {
+ screenColumn = self.$renderToken(
+ stringBuilder, screenColumn, token, value
+ );
+ chars += value.length;
+ }
+ else {
+ while (chars + value.length >= splitChars) {
+ screenColumn = self.$renderToken(
+ stringBuilder, screenColumn,
+ token, value.substring(0, splitChars - chars)
+ );
+ value = value.substring(splitChars - chars);
+ chars = splitChars;
+
+ if (!onlyContents) {
+ stringBuilder.push("
",
+ ""
+ );
+ }
- if (scrollLeft > left) {
- this.scrollToX(left);
+ split ++;
+ screenColumn = 0;
+ splitChars = splits[split] || Number.MAX_VALUE;
+ }
+ if (value.length != 0) {
+ chars += value.length;
+ screenColumn = self.$renderToken(
+ stringBuilder, screenColumn, token, value
+ );
+ }
+ }
}
- if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) {
- if (left > this.layerConfig.width)
- this.$desiredScrollLeft = left + 2 * this.characterWidth;
+ if (this.showInvisibles) {
+ if (lastRow !== this.session.getLength() - 1)
+ stringBuilder.push("" + this.EOL_CHAR + "");
else
- this.scrollToX(Math.round(left + this.characterWidth - this.$size.scrollerWidth));
+ stringBuilder.push("" + this.EOF_CHAR + "");
}
+ if (!onlyContents)
+ stringBuilder.push("
");
};
- this.getScrollTop = function() {
- return this.scrollTop;
+ this.$renderLine = function(stringBuilder, row, tokens, onlyContents) {
+ // Check if the line to render is folded or not. If not, things are
+ // simple, otherwise, we need to fake some things...
+ if (!this.session.isRowFolded(row)) {
+ var splits = this.session.getRowSplitData(row);
+ this.$renderLineCore(stringBuilder, row, tokens, splits, onlyContents);
+ } else {
+ this.$renderFoldLine(stringBuilder, row, tokens, onlyContents);
+ }
};
- this.getScrollLeft = function() {
- return this.scroller.scrollLeft;
- };
+ this.$renderFoldLine = function(stringBuilder, row, tokens, onlyContents) {
+ var session = this.session,
+ foldLine = session.getFoldLine(row),
+ renderTokens = [];
- this.getScrollTopRow = function() {
- return this.scrollTop / this.lineHeight;
- };
+ function addTokens(tokens, from, to) {
+ var idx = 0, col = 0;
+ while ((col + tokens[idx].value.length) < from) {
+ col += tokens[idx].value.length;
+ idx++;
- this.getScrollBottomRow = function() {
- return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1);
- };
+ 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);
+ }
- this.scrollToRow = function(row) {
- this.scrollToY(row * this.lineHeight);
- };
+ renderTokens.push({
+ type: tokens[idx].type,
+ value: value
+ });
- this.scrollToLine = function(line, center) {
- var lineHeight = { lineHeight: this.lineHeight };
- var offset = 0;
- for (var l = 1; l < line; l++) {
- offset += this.session.getRowHeight(lineHeight, l-1);
- }
+ col = from + value.length;
+ idx += 1;
+ }
- if (center) {
- offset -= this.$size.scrollerHeight / 2;
+ while (col < to) {
+ var value = tokens[idx].value;
+ if (value.length + col > to) {
+ value = value.substring(0, to - col);
+ }
+ renderTokens.push({
+ type: tokens[idx].type,
+ value: value
+ });
+ col += value.length;
+ idx += 1;
+ }
}
- this.scrollToY(offset);
+
+ foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) {
+ if (placeholder) {
+ renderTokens.push({
+ type: "fold",
+ value: placeholder
+ });
+ } else {
+ if (isNewRow) {
+ tokens = this.session.getTokens(row, row)[0].tokens;
+ }
+ if (tokens.length != 0) {
+ addTokens(tokens, lastColumn, column);
+ }
+ }
+ }.bind(this), foldLine.end.row, this.session.getLine(foldLine.end.row).length);
+
+ // TODO: Build a fake splits array!
+ var splits = this.session.$useWrapMode?this.session.$wrapData[row]:null;
+ this.$renderLineCore(stringBuilder, row, renderTokens, splits, onlyContents);
+ };
+
+ 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.scrollToY = function(scrollTop) {
- // after calling scrollBar.setScrollTop
- // scrollbar sends us event with same scrollTop. ignore it
- scrollTop = Math.max(0, scrollTop);
- if (this.scrollTop !== scrollTop) {
- this.$loop.schedule(this.CHANGE_SCROLL);
- this.scrollTop = scrollTop;
- }
+ this.destroy = function() {
+ clearInterval(this.$pollSizeChangesTimer);
+ if (this.$measureNode)
+ this.$measureNode.parentNode.removeChild(this.$measureNode);
+ delete this.$measureNode;
};
- this.scrollToX = function(scrollLeft) {
- if (scrollLeft <= this.$padding)
- scrollLeft = 0;
+}).call(Text.prototype);
- this.scroller.scrollLeft = scrollLeft;
- };
+exports.Text = Text;
- this.scrollBy = function(deltaX, deltaY) {
- deltaY && this.scrollToY(this.scrollTop + deltaY);
- deltaX && this.scrollToX(this.scroller.scrollLeft + deltaX);
- };
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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
+ * Julian Viereck
+ *
+ * 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 ***** */
- this.screenToTextCoordinates = function(pageX, pageY) {
- var canvasPos = this.scroller.getBoundingClientRect();
+define('ace/layer/cursor', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
+"use strict";
- var col = Math.round((pageX + this.scroller.scrollLeft - canvasPos.left - this.$padding - dom.getPageScrollLeft())
- / this.characterWidth);
- var row = Math.floor((pageY + this.scrollTop - canvasPos.top - dom.getPageScrollTop())
- / this.lineHeight);
+var dom = require("../lib/dom");
- return this.session.screenToDocumentPosition(row, Math.max(col, 0));
- };
+var Cursor = function(parentEl) {
+ this.element = dom.createElement("div");
+ this.element.className = "ace_layer ace_cursor-layer";
+ parentEl.appendChild(this.element);
- this.textToScreenCoordinates = function(row, column) {
- var canvasPos = this.scroller.getBoundingClientRect();
- var pos = this.session.documentToScreenPosition(row, column);
+ this.isVisible = false;
- var x = this.$padding + Math.round(pos.column * this.characterWidth);
- var y = pos.row * this.lineHeight;
+ this.cursors = [];
+ this.cursor = this.addCursor();
+};
- return {
- pageX: canvasPos.left + x - this.getScrollLeft(),
- pageY: canvasPos.top + y - this.getScrollTop()
- };
+(function() {
+
+ this.$padding = 0;
+ this.setPadding = function(padding) {
+ this.$padding = padding;
};
- this.visualizeFocus = function() {
- dom.addCssClass(this.container, "ace_focus");
+ this.setSession = function(session) {
+ this.session = session;
};
- this.visualizeBlur = function() {
- dom.removeCssClass(this.container, "ace_focus");
+ 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.showComposition = function(position) {
- if (!this.$composition) {
- this.$composition = dom.createElement("div");
- this.$composition.className = "ace_composition";
- this.content.appendChild(this.$composition);
+ this.removeCursor = function() {
+ if (this.cursors.length > 1) {
+ var el = this.cursors.pop();
+ el.parentNode.removeChild(el);
+ return el;
}
+ };
- this.$composition.innerHTML = " ";
+ this.hideCursor = function() {
+ this.isVisible = false;
+ for (var i = this.cursors.length; i--; )
+ dom.addCssClass(this.cursors[i], "ace_hidden");
+ clearInterval(this.blinkId);
+ };
- var pos = this.$cursorLayer.getPixelPosition();
- var style = this.$composition.style;
- style.top = pos.top + "px";
- style.left = (pos.left + this.$padding) + "px";
- style.height = this.lineHeight + "px";
+ this.showCursor = function() {
+ this.isVisible = true;
+ for (var i = this.cursors.length; i--; )
+ dom.removeCssClass(this.cursors[i], "ace_hidden");
- this.hideCursor();
+ this.element.style.visibility = "";
+ this.restartTimer();
};
- this.setCompositionText = function(text) {
- dom.setInnerText(this.$composition, text);
+ 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.hideComposition = function() {
- this.showCursor();
+ this.getPixelPosition = function(position, onScreen) {
+ if (!this.config || !this.session) {
+ return {
+ left : 0,
+ top : 0
+ };
+ }
- if (!this.$composition)
- return;
+ 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;
- var style = this.$composition.style;
- style.top = "-10000px";
- style.left = "-10000px";
+ return {
+ left : cursorLeft,
+ top : cursorTop
+ };
};
- this.setTheme = function(theme) {
- var _self = this;
-
- this.$themeValue = theme;
- if (!theme || typeof theme == "string") {
- theme = theme || "ace/theme/textmate";
- require([theme], function(theme) {
- afterLoad(theme);
- });
- } else {
- afterLoad(theme);
- }
+ this.update = function(config) {
+ this.config = config;
- function afterLoad(theme) {
- if (_self.$theme)
- dom.removeCssClass(_self.container, _self.$theme);
+ if (this.session.selectionMarkerCount > 0) {
+ var selections = this.session.$selectionMarkers;
+ var i = 0, sel, cursorIndex = 0;
- _self.$theme = theme ? theme.cssClass : null;
+ for (var i = selections.length; i--; ) {
+ sel = selections[i];
+ var pixelPos = this.getPixelPosition(sel.cursor, true);
- if (_self.$theme)
- dom.addCssClass(_self.container, _self.$theme);
+ var style = (this.cursors[cursorIndex++] || this.addCursor()).style;
- // force re-measure of the gutter width
- if (_self.$size) {
- _self.$size.width = 0;
- _self.onResize();
+ 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();
}
- };
- this.getTheme = function() {
- return this.$themeValue;
- };
+ var overwrite = this.session.getOverwrite();
+ if (overwrite != this.overwrite)
+ this.$setOverite(overwrite);
- // 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.
+ // cache for textarea and gutter highlight
+ this.$pixelPos = pixelPos;
- this.setStyle = function setStyle(style) {
- dom.addCssClass(this.container, style);
+ this.restartTimer();
};
- this.unsetStyle = function unsetStyle(style) {
- dom.removeCssClass(this.container, style);
+ 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() {
- this.$textLayer.destroy();
- this.$cursorLayer.destroy();
- };
+ clearInterval(this.blinkId);
+ }
-}).call(VirtualRenderer.prototype);
+}).call(Cursor.prototype);
+
+exports.Cursor = Cursor;
-exports.VirtualRenderer = VirtualRenderer;
});
-/* vim:ts=4:sts=4:sw=4:
- * ***** BEGIN LICENSE BLOCK *****
+/* ***** 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
@@ -13928,7 +17269,7 @@ exports.VirtualRenderer = VirtualRenderer;
*
* Contributor(s):
* Fabian Jakobs
- * Julian Viereck
+ * Irakli Gozalishvili (http://jeditoolkit.com)
*
* 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
@@ -13944,110 +17285,520 @@ exports.VirtualRenderer = VirtualRenderer;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/layer/gutter', ['require', 'exports', 'module' , 'pilot/dom'], function(require, exports, module) {
+define('ace/scrollbar', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/event', 'ace/lib/event_emitter'], function(require, exports, module) {
+"use strict";
-var dom = require("pilot/dom");
+var oop = require("./lib/oop");
+var dom = require("./lib/dom");
+var event = require("./lib/event");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
-var Gutter = function(parentEl) {
+/**
+ * class ScrollBar
+ *
+ * A set of methods for setting and retrieving the editor's scrollbar.
+ *
+ **/
+
+/**
+ * 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_layer ace_gutter-layer";
- parentEl.appendChild(this.element);
+ this.element.className = "ace_sb";
- this.$breakpoints = [];
- this.$annotations = [];
- this.$decorations = [];
+ 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.setSession = function(session) {
- this.session = session;
+ /**
+ * ScrollBar@onScroll
+ *
+ * Emitted when the scroll bar, well, scrolls.
+ *
+ **/
+ this.onScroll = function() {
+ this._emit("scroll", {data: this.element.scrollTop});
};
- this.addGutterDecoration = function(row, className){
- if (!this.$decorations[row])
- this.$decorations[row] = "";
- this.$decorations[row] += " ace_" + className;
- }
-
- this.removeGutterDecoration = function(row, className){
- this.$decorations[row] = this.$decorations[row].replace(" ace_" + className, "");
+ /**
+ * ScrollBar.getWidth() -> Number
+ *
+ * Returns the width of the scroll bar.
+ *
+ **/
+ this.getWidth = function() {
+ return this.width;
};
- this.setBreakpoints = function(rows) {
- this.$breakpoints = rows.concat();
+ /**
+ * ScrollBar.setHeight(height)
+ * - height (Number): The new height
+ *
+ * Sets the height of the scroll bar, in pixels.
+ *
+ **/
+ this.setHeight = function(height) {
+ this.element.style.height = height + "px";
};
- 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;
+ /**
+ * ScrollBar.setInnerHeight(height)
+ * - height (Number): The new inner height
+ *
+ * Sets the inner height of the scroll bar, in pixels.
+ *
+ **/
+ this.setInnerHeight = function(height) {
+ this.inner.style.height = height + "px";
+ };
- var rowInfo = this.$annotations[row] = {
- text: []
- };
- for (var i=0; i
+ * Irakli Gozalishvili (http://jeditoolkit.com)
+ *
+ * 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 ***** */
- while (true) {
- if(i > foldStart) {
- i = fold.end.row + 1;
- fold = this.session.getNextFold(i);
- foldStart = fold ?fold.start.row :Infinity;
- }
- if(i > lastRow)
- break;
+define('ace/renderloop', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) {
+"use strict";
- var annotation = this.$annotations[i] || emptyAnno;
- html.push("", (i+1));
+var event = require("./lib/event");
- var wrappedRowLength = this.session.getRowLength(i) - 1;
- while (wrappedRowLength--) {
- html.push("
¦
");
- }
+/** internal, hide
+ * class RenderLoop
+ *
+ * Batches changes (that force something to be redrawn) in the background.
+ *
+ **/
- html.push("");
+/** internal, hide
+ * new RenderLoop(onRender, win)
+ *
+ *
+ *
+**/
+var RenderLoop = function(onRender, win) {
+ this.onRender = onRender;
+ this.pending = false;
+ this.changes = 0;
+ this.window = win || window;
+};
- i++;
+(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);
}
- this.element = dom.setInnerHtml(this.element, html.join(""));
- this.element.style.height = config.minHeight + "px";
};
-}).call(Gutter.prototype);
-
-exports.Gutter = Gutter;
+}).call(RenderLoop.prototype);
+exports.RenderLoop = RenderLoop;
});
+define("text!ace/css/editor.css", [], "\n" +
+ ".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-x: scroll;\n" +
+ " overflow-y: 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_composition {\n" +
+ " position: absolute;\n" +
+ " background: #555;\n" +
+ " color: #DDD;\n" +
+ " z-index: 4;\n" +
+ "}\n" +
+ "\n" +
+ ".ace_gutter {\n" +
+ " position: absolute;\n" +
+ " overflow : hidden;\n" +
+ " height: 100%;\n" +
+ " width: auto;\n" +
+ " cursor: default;\n" +
+ " z-index: 1000;\n" +
+ "}\n" +
+ "\n" +
+ ".ace_gutter_active_line {\n" +
+ " position: absolute;\n" +
+ " right: 0;\n" +
+ " width: 100%;\n" +
+ "}\n" +
+ "\n" +
+ ".ace_gutter.horscroll {\n" +
+ " box-shadow: 0px 0px 20px rgba(0,0,0,0.4);\n" +
+ "}\n" +
+ "\n" +
+ ".ace_gutter-cell {\n" +
+ " padding-left: 19px;\n" +
+ " padding-right: 6px;\n" +
+ "}\n" +
+ "\n" +
+ ".ace_gutter-cell.ace_error {\n" +
+ " background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%F5or%F5%87%88%F5nr%F4ns%EBmq%F5z%7F%DDJT%DEKS%DFOW%F1Yc%F2ah%CE(7%CE)8%D18E%DD%40M%F2KZ%EBU%60%F4%60m%DCir%C8%16(%C8%19*%CE%255%F1%3FR%F1%3FS%E6%AB%B5%CA%5DI%CEn%5E%F7%A2%9A%C9G%3E%E0a%5B%F7%89%85%F5yy%F6%82%80%ED%82%80%FF%BF%BF%E3%C4%C4%FF%FF%FF%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%25%00%2C%00%00%00%00%10%00%10%00%00%06p%C0%92pH%2C%1A%8F%C8%D2H%93%E1d4%23%E4%88%D3%09mB%1DN%B48%F5%90%40%60%92G%5B%94%20%3E%22%D2%87%24%FA%20%24%C5%06A%00%20%B1%07%02B%A38%89X.v%17%82%11%13q%10%0Fi%24%0F%8B%10%7BD%12%0Ei%09%92%09%0EpD%18%15%24%0A%9Ci%05%0C%18F%18%0B%07%04%01%04%06%A0H%18%12%0D%14%0D%12%A1I%B3%B4%B5IA%00%3B\");\n" +
+ " background-repeat: no-repeat;\n" +
+ " background-position: 2px center;\n" +
+ "}\n" +
+ "\n" +
+ ".ace_gutter-cell.ace_warning {\n" +
+ " background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%FF%DBr%FF%DE%81%FF%E2%8D%FF%E2%8F%FF%E4%96%FF%E3%97%FF%E5%9D%FF%E6%9E%FF%EE%C1%FF%C8Z%FF%CDk%FF%D0s%FF%D4%81%FF%D5%82%FF%D5%83%FF%DC%97%FF%DE%9D%FF%E7%B8%FF%CCl%7BQ%13%80U%15%82W%16%81U%16%89%5B%18%87%5B%18%8C%5E%1A%94d%1D%C5%83-%C9%87%2F%C6%84.%C6%85.%CD%8B2%C9%871%CB%8A3%CD%8B5%DC%98%3F%DF%9BB%E0%9CC%E1%A5U%CB%871%CF%8B5%D1%8D6%DB%97%40%DF%9AB%DD%99B%E3%B0p%E7%CC%AE%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%2F%00%2C%00%00%00%00%10%00%10%00%00%06a%C0%97pH%2C%1A%8FH%A1%ABTr%25%87%2B%04%82%F4%7C%B9X%91%08%CB%99%1C!%26%13%84*iJ9(%15G%CA%84%14%01%1A%97%0C%03%80%3A%9A%3E%81%84%3E%11%08%B1%8B%20%02%12%0F%18%1A%0F%0A%03'F%1C%04%0B%10%16%18%10%0B%05%1CF%1D-%06%07%9A%9A-%1EG%1B%A0%A1%A0U%A4%A5%A6BA%00%3B\");\n" +
+ " background-repeat: no-repeat;\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-repeat: no-repeat;\n" +
+ " background-position: 2px center;\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: fixed;\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_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" +
+ " min-width: 40px;\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_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 1px 1px;\n" +
+ " display: inline-block;\n" +
+ " height: 14px;\n" +
+ " width: 11px;\n" +
+ " vertical-align: text-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 5px;\n" +
+ "\n" +
+ " border-radius: 3px;\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:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n" +
+ " -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n" +
+ " -webkit-box-shadow:inset 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:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n" +
+ " box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n" +
+ " background-position: center 4px;\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:inset 0 1px 1px rgba(255, 255, 255);\n" +
+ " -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n" +
+ " -webkit-box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n" +
+ " -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n" +
+ " box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n" +
+ " box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\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: 0.5s opacity;\n" +
+ " -webkit-transition: 0.5s opacity;\n" +
+ " -o-transition: 0.5s opacity;\n" +
+ " -ms-transition: 0.5s opacity;\n" +
+ " transition: 0.5s opacity;\n" +
+ " opacity: 0;\n" +
+ "}\n" +
+ ".ace_fade-fold-widgets:hover .ace_fold-widget {\n" +
+ " -moz-transition-duration: 0.05s;\n" +
+ " -webkit-transition-duration: 0.05s;\n" +
+ " -o-transition-duration: 0.05s;\n" +
+ " -ms-transition-duration: 0.05s;\n" +
+ " transition-duration: 0.05s;\n" +
+ " -moz-transition-delay: 0.2s;\n" +
+ " -webkit-transition-delay: 0.2s;\n" +
+ " -o-transition-delay: 0.2s;\n" +
+ " -ms-transition-delay: 0.2s;\n" +
+ " transition-delay: 0.2s; \n" +
+ " opacity:1;\n" +
+ "}\n" +
+ "");
+
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -14070,8 +17821,7 @@ exports.Gutter = Gutter;
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Fabian Jakobs
- * Julian Viereck
+ * Harutyun Amirjanyan
*
* 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
@@ -14087,187 +17837,730 @@ exports.Gutter = Gutter;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/layer/marker', ['require', 'exports', 'module' , 'ace/range', 'pilot/dom'], function(require, exports, module) {
+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 Range = require("ace/range").Range;
-var dom = require("pilot/dom");
+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");
+exports.commands = require("./commands/multi_select_commands");
-var Marker = function(parentEl) {
- this.element = dom.createElement("div");
- this.element.className = "ace_layer ace_marker-layer";
- parentEl.appendChild(this.element);
-};
+// 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);
- this.$padding = 0;
+// extend Selection
+(function() {
+ // list of ranges in reverse addition order
+ this.ranges = null;
- this.setPadding = function(padding) {
- this.$padding = padding;
+ // automatically sorted list of ranges
+ this.rangeList = null;
+
+ /** extension
+ * Selection.addRange(range, $blockChangeEvents)
+ * - range (Range): The new range to add
+ * - $blockChangeEvents (Boolean): Whether or not to block changing events
+ *
+ * Adds a range to a selection by entering multiselect mode, if necessary.
+ **/
+ 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.setSession = function(session) {
- this.session = session;
+
+ 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.setMarkers = function(markers) {
- this.markers = markers;
+ /** extension
+ * Selection.substractPoint(pos) -> Range
+ * - pos (Range): The position to remove, as a `{row, column}` object
+ *
+ * Removes a Range containing pos (if it exists).
+ **/
+ this.substractPoint = function(pos) {
+ var removed = this.rangeList.substractPoint(pos);
+ if (removed) {
+ this.$onRemoveRange(removed);
+ return removed[0];
+ }
};
- this.update = function(config) {
- var config = config || this.config;
- if (!config)
+ /** extension
+ * Selection.mergeOverlappingRanges()
+ *
+ * Merges overlapping ranges ensuring consistency after changes
+ **/
+ 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.config = config;
+ this.rangeList = new RangeList();
+ this.ranges = [];
+ this.rangeCount = 0;
+ };
+ this.getAllRanges = function() {
+ return this.rangeList.ranges.concat();
+ };
- var html = [];
- for ( var key in this.markers) {
- var marker = this.markers[key];
+ 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);
- var range = marker.range.clipRows(config.firstRow, config.lastRow);
- if (range.isEmpty()) continue;
+ 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;
- 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);
+ 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);
+ }
+ };
+
+ /** extension
+ * Selection.rectangularRangeBlock(screenCursor, screenAnchor, includeEmptyLines) -> Range
+ * - screenCursor (Cursor): The cursor to use
+ * - screenAnchor (Anchor): The anchor to use
+ * - includeEmptyLins (Boolean): If true, this includes ranges inside the block which are empty due to clipping
+ *
+ * Gets list of ranges composing rectangular block on the screen
+ *
+ */
+ 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;
}
- 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
- );
- }
+ 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++;
}
- else {
- this.drawSingleLineMarker(
- html, range, marker.clazz, config,
- null, marker.type
- );
+ for (var i = end; i >= start; i--) {
+ if (rectSel[i].isEmpty())
+ rectSel.splice(i, 1);
}
}
- this.element = dom.setInnerHtml(this.element, html.join(""));
+
+ return rectSel;
};
+}).call(Selection.prototype);
- this.$getTop = function(row, layerConfig) {
- return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
+// 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();
+ };
+
+ /** extension
+ * Editor.addSelectionMarker(orientedRange) -> Range
+ * - orientedRange (Range): A range containing a cursor
+ *
+ * Adds the selection and cursor.
+ **/
+ 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;
+ };
+
+ /** extension
+ * Editor.removeSelectionMarker(range)
+ * - range (Range): The selection range added with [[Editor.addSelectionMarker `addSelectionMarker()`]].
+ *
+ * Removes the selection marker.
+ **/
+ 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(exports.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(exports.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 (!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();
+ };
+
+ /** extension
+ * Editor.forEachSelection(cmd, args)
+ * - cmd (String): The command to execute
+ * - args (String): Any arguments for the command
+ *
+ * Executes a command for each selection range.
+ **/
+ 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();
+ };
+
+ /** extension
+ * Editor.exitMultiSelectMode() -> Void
+ *
+ * Removes all the selections except the last added one.
+ **/
+ 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;
+ };
+
+ this.onPaste = function(text) {
+ this._emit("paste", text);
+ if (!this.inMultiSelectMode)
+ return this.insert(text);
+
+ var lines = text.split(this.session.getDocument().getNewLineCharacter());
+ var ranges = this.selection.rangeList.ranges;
+
+ if (lines.length > ranges.length) {
+ this.commands.exec("insertstring", this, text);
+ return;
+ }
+
+ for (var i = ranges.length; i--; ) {
+ var range = ranges[i];
+ if (!range.isEmpty())
+ this.session.remove(range);
+
+ this.session.insert(range.start, lines[i]);
+ }
+ };
+
+ /** extension
+ * Editor.findAll(dir, options) -> Number
+ * - needle: text to find
+ * - options: search options
+ * - additive: keeps
+ *
+ * Finds and selects all the occurences of `needle`.
+ **/
+ 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);
};
- /**
- * Draws a marker, which spans a range of text in a single line
- */
- this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
- // selection start
- var row = range.start.row;
+ /** extension
+ * Editor.transposeSelections(dir)
+ * - dir (Number): The direction to rotate selections
+ *
+ * Transposes the selected ranges.
+ **/
+ 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;
+ }
+ }
- var lineRange = new Range(
- row, range.start.column,
- row, this.session.getScreenLastRowColumn(row)
- );
- this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, "text");
+ /** 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;
- // selection end
- row = range.end.row;
- lineRange = new Range(row, 0, row, range.end.column);
- this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, "text");
+ 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);
- 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");
+ 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);
- /**
- * Draws a multi line marker, where lines span the full width
- */
- this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig, type) {
- // from selection start to the end of the line
- var padding = type === "background" ? 0 : this.$padding;
- var height = layerConfig.lineHeight;
- var width = Math.round(layerConfig.width - (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(
- ""
- );
+function isSamePoint(p1, p2) {
+ return p1.row == p2.row && p1.column == p2.column;
+}
- // from start of the last line to the selection end
- top = this.$getTop(range.end.row, layerConfig);
- width = Math.round(range.end.column * layerConfig.characterWidth);
+// 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);
+ }
- stringBuilder.push(
- ""
- );
+ session.multiSelect.on("addRange", this.$onAddRange);
+ session.multiSelect.on("removeRange", this.$onRemoveRange);
+ session.multiSelect.on("multiSelect", this.$onMultiSelect);
+ session.multiSelect.on("singleSelect", this.$onSingleSelect);
- // all the complete lines
- height = (range.end.row - range.start.row - 1) * layerConfig.lineHeight;
- if (height < 0)
- return;
- top = this.$getTop(range.start.row + 1, layerConfig);
- width = layerConfig.width;
+ // this.$onSelectionChange = this.onSelectionChange.bind(this);
- stringBuilder.push(
- ""
- );
- };
+ if (this.inMultiSelectMode != session.selection.inMultiSelectMode) {
+ if (session.selection.inMultiSelectMode)
+ this.$onMultiSelect();
+ else
+ this.$onSingleSelect();
+ }
+};
- /**
- * Draws a marker which covers one single full line
- */
- this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength, type) {
- var padding = type === "background" ? 0 : this.$padding;
- var height = layerConfig.lineHeight;
+// 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);
- if (type === "background")
- var width = layerConfig.width;
- else
- width = Math.round((range.end.column + (extraLength || 0) - range.start.column) * layerConfig.characterWidth);
+ exports.onSessionChange.call(editor, editor);
+ editor.on("changeSession", exports.onSessionChange.bind(editor));
- var top = this.$getTop(range.start.row, layerConfig);
- var left = Math.round(
- padding + range.start.column * layerConfig.characterWidth
- );
+ editor.on("mousedown", onMouseDown);
+ editor.commands.addCommands(exports.commands.defaultCommands);
- stringBuilder.push(
- ""
- );
- };
+ addAltCursorListeners(editor);
+}
-}).call(Marker.prototype);
+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 = "";
+ }
+ });
-exports.Marker = Marker;
+ event.addListener(el, "keyup", reset);
+ event.addListener(el, "blur", reset);
+ function reset() {
+ if (altCursor) {
+ contentEl.style.cursor = "";
+ altCursor = false;
+ }
+ }
+}
+
+exports.MultiSelect = MultiSelect;
});
-/* vim:ts=4:sts=4:sw=4:
- * ***** BEGIN LICENSE BLOCK *****
+/* ***** 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
@@ -14288,9 +18581,7 @@ exports.Marker = Marker;
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Fabian Jakobs
- * Julian Viereck
- * Mihai Sucan
+ * Harutyun Amirjanyan
*
* 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
@@ -14306,504 +18597,469 @@ exports.Marker = Marker;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/layer/text', ['require', 'exports', 'module' , 'pilot/oop', 'pilot/dom', 'pilot/lang', 'pilot/useragent', 'pilot/event_emitter'], function(require, exports, module) {
-
-var oop = require("pilot/oop");
-var dom = require("pilot/dom");
-var lang = require("pilot/lang");
-var useragent = require("pilot/useragent");
-var EventEmitter = require("pilot/event_emitter").EventEmitter;
+define('ace/range_list', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
-var Text = function(parentEl) {
- this.element = dom.createElement("div");
- this.element.className = "ace_layer ace_text-layer";
- this.element.style.width = "auto";
- parentEl.appendChild(this.element);
- this.$characterSize = this.$measureSizes() || {width: 0, height: 0};
- this.$pollSizeChanges();
+var RangeList = function() {
+ this.ranges = [];
};
(function() {
-
- oop.implement(this, EventEmitter);
-
- this.EOF_CHAR = "¶";
- this.EOL_CHAR = "¬";
- this.TAB_CHAR = "→";
- this.SPACE_CHAR = "·";
- 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._dispatchEvent("changeCharaterSize", {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 = 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 = "absolute";
- 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 (document.body) {
- document.body.appendChild(measureNode);
- } else {
- var container = this.element.parentNode;
- while (!dom.hasCssClass(container, "ace_editor"))
- container = container.parentNode;
- container.appendChild(measureNode);
- }
-
- }
-
- 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;
+ this.comparePoints = function(p1, p2) {
+ return p1.row - p2.row || p1.column - p2.column;
};
- this.setSession = function(session) {
- this.session = session;
- };
+ this.pointIndex = function(pos, startIndex) {
+ var list = this.ranges;
- this.showInvisibles = false;
- this.setShowInvisibles = function(showInvisibles) {
- if (this.showInvisibles == showInvisibles)
- return false;
+ for (var i = startIndex || 0; i < list.length; i++) {
+ var range = list[i];
+ var cmp = this.comparePoints(pos, range.end);
- this.showInvisibles = showInvisibles;
- return true;
- };
+ if (cmp > 0)
+ continue;
+ if (cmp == 0)
+ return i;
+ cmp = this.comparePoints(pos, range.start);
+ if (cmp >= 0)
+ return i;
- this.$tabStrings = [];
- this.$computeTabString = function() {
- var tabSize = this.session.getTabSize();
- var tabStr = this.$tabStrings = [0];
- for (var i = 1; i < tabSize + 1; i++) {
- if (this.showInvisibles) {
- tabStr.push(""
- + this.TAB_CHAR
- + new Array(i).join(" ")
- + "");
- } else {
- tabStr.push(new Array(i+1).join(" "));
- }
+ return -i-1;
}
-
+ return -i - 1;
};
- this.updateLines = function(config, firstRow, lastRow) {
- this.$computeTabString();
- // 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)) {
- break;
- } else {
- row = foldLine.end.row;
- }
- }
- lineElementsIdx ++;
- }
+ this.add = function(range) {
+ var startIndex = this.pointIndex(range.start);
+ if (startIndex < 0)
+ startIndex = -startIndex - 1;
- for (var i=first; i<=last; i++) {
- var lineElement = lineElements[lineElementsIdx++];
- if (!lineElement)
- continue;
+ var endIndex = this.pointIndex(range.end, startIndex);
- var html = [];
- var tokens = this.session.getTokens(i, i);
- this.$renderLine(html, i, tokens[0].tokens, true);
- lineElement = dom.setInnerHtml(lineElement, html.join(""));
+ if (endIndex < 0)
+ endIndex = -endIndex - 1;
+ else
+ endIndex++;
- i = this.session.getRowFoldEnd(i);
+ 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.scrollLines = function(config) {
- this.$computeTabString();
- var oldConfig = this.config;
- this.config = config;
+ this.substractPoint = function(pos) {
+ var i = this.pointIndex(pos);
- if (!oldConfig || oldConfig.lastRow < config.firstRow)
- return this.update(config);
+ if (i >= 0)
+ return this.ranges.splice(i, 1);
+ };
- if (config.lastRow < oldConfig.firstRow)
- return this.update(config);
+ // 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;
- 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 (cmp == 0 && !(range.isEmpty() || next.isEmpty()))
+ continue;
- if (oldConfig.lastRow > config.lastRow)
- for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--)
- el.removeChild(el.lastChild);
+ if (this.comparePoints(range.end, next.end) < 0) {
+ range.end.row = next.end.row;
+ range.end.column = next.end.column;
+ }
- 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);
+ list.splice(i, 1);
+ removed.push(next);
+ next = range;
+ i--;
}
- if (config.lastRow > oldConfig.lastRow) {
- var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);
- el.appendChild(fragment);
- }
+ return removed;
};
- this.$renderLinesFragment = function(config, firstRow, lastRow) {
- var fragment = document.createDocumentFragment(),
- row = firstRow,
- fold = this.session.getNextFold(row),
- foldStart = fold ?fold.start.row :Infinity;
+ this.contains = function(row, column) {
+ return this.pointIndex({row: row, column: column}) >= 0;
+ };
- while (true) {
- if(row > foldStart) {
- row = fold.end.row+1;
- fold = this.session.getNextFold(row);
- foldStart = fold ?fold.start.row :Infinity;
- }
- if(row > lastRow)
- break;
+ this.containsPoint = function(pos) {
+ return this.pointIndex(pos) >= 0;
+ };
- var container = dom.createElement("div");
+ this.rangeAtPoint = function(pos) {
+ var i = this.pointIndex(pos);
+ if (i >= 0)
+ return this.ranges[i];
+ };
- var html = [];
- // Get the tokens per line as there might be some lines in between
- // beeing folded.
- // OPTIMIZE: If there is a long block of unfolded lines, just make
- // this call once for that big block of unfolded lines.
- var tokens = this.session.getTokens(row, row);
- if (tokens.length == 1)
- this.$renderLine(html, row, tokens[0].tokens, false);
- // don't use setInnerHtml since we are working with an empty DIV
- container.innerHTML = html.join("");
- var lines = container.childNodes
- while(lines.length)
- fragment.appendChild(lines[0]);
+ this.clipRows = function(startRow, endRow) {
+ var list = this.ranges;
+ if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow)
+ return [];
- row++;
+ 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 fragment;
+ return clipped;
};
- this.update = function(config) {
- this.$computeTabString();
- this.config = config;
+ this.removeAll = function() {
+ return this.ranges.splice(0, this.ranges.length);
+ };
- var html = [];
- var firstRow = config.firstRow, lastRow = config.lastRow;
+ this.attach = function(session) {
+ if (this.session)
+ this.detach();
- var row = firstRow,
- fold = this.session.getNextFold(row),
- foldStart = fold ?fold.start.row :Infinity;
+ this.session = session;
+ this.onChange = this.$onChange.bind(this);
- while (true) {
- if(row > foldStart) {
- row = fold.end.row+1;
- fold = this.session.getNextFold(row);
- foldStart = fold ?fold.start.row :Infinity;
- }
- if(row > lastRow)
- break;
+ this.session.on('change', this.onChange);
+ };
- // Get the tokens per line as there might be some lines in between
- // beeing folded.
- // OPTIMIZE: If there is a long block of unfolded lines, just make
- // this call once for that big block of unfolded lines.
- var tokens = this.session.getTokens(row, row);
- if (tokens.length == 1)
- this.$renderLine(html, row, tokens[0].tokens, false);
+ this.detach = function() {
+ if (!this.session)
+ return;
+ this.session.removeListener('change', this.onChange);
+ this.session = null;
+ };
- row++;
+ 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;
}
- this.element = dom.setInnerHtml(this.element, html.join(""));
- };
+ var startRow = start.row;
+ var endRow = end.row;
+ var lineDif = endRow - startRow;
- this.$textToken = {
- "text": true,
- "rparen": true,
- "lparen": true
- };
+ var colDiff = -start.column + end.column;
- this.$renderToken = function(stringBuilder, screenColumn, token, value) {
- var self = this;
- var replaceReg = /\t|&|<|( +)|([\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000])|[\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 (c.charCodeAt(0) == 32) {
- return new Array(c.length+1).join(" ");
- } else if (c == "\t") {
- var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx);
- screenColumn += tabSize - 1;
- return self.$tabStrings[tabSize];
- } else if (c == "&") {
- if (useragent.isOldGecko)
- return "&";
- else
- return "&";
- } else if (c == "<") {
- return "<";
- } else if (c.match(/[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/)) {
- if (self.showInvisibles) {
- var space = new Array(c.length+1).join(self.SPACE_CHAR);
- return "" + space + "";
- } else {
- return " ";
- }
- } else {
- screenColumn += 1;
- return "" + c + "";
- }
- };
+ var ranges = this.ranges;
- var output = value.replace(replaceReg, replaceFunc);
+ 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 (!this.$textToken[token.type]) {
- var classes = "ace_" + token.type.replace(/\./g, " ace_");
- stringBuilder.push("", output, "");
+ 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;
+ }
}
- else {
- stringBuilder.push(output);
+
+ if (lineDif != 0 && i < n) {
+ for (; i < n; i++) {
+ var r = ranges[i];
+ r.start.row += lineDif;
+ r.end.row += lineDif;
+ }
}
- return screenColumn + value.length;
};
- this.$renderLineCore = function(stringBuilder, lastRow, tokens, splits, onlyContents) {
- var chars = 0;
- var split = 0;
- var splitChars;
- var characterWidth = this.config.characterWidth;
- var screenColumn = 0;
- var self = this;
+}).call(RangeList.prototype);
- if (!splits || splits.length == 0)
- splitChars = Number.MAX_VALUE;
- else
- splitChars = splits[0];
+exports.RangeList = RangeList;
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** 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):
+ * Harutyun Amirjanyan
+ *
+ * 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 ***** */
- if (!onlyContents) {
- stringBuilder.push(""
- );
- }
-
- for (var i = 0; i < tokens.length; i++) {
- var token = tokens[i];
- var value = token.value;
+define('ace/mouse/multi_select_handler', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) {
- if (chars + value.length < splitChars) {
- screenColumn = self.$renderToken(
- stringBuilder, screenColumn, token, value
- );
- chars += value.length;
- }
- else {
- while (chars + value.length >= splitChars) {
- screenColumn = self.$renderToken(
- stringBuilder, screenColumn,
- token, value.substring(0, splitChars - chars)
- );
- value = value.substring(splitChars - chars);
- chars = splitChars;
-
- if (!onlyContents) {
- stringBuilder.push("
",
- ""
- );
- }
+var event = require("../lib/event");
- split ++;
- screenColumn = 0;
- splitChars = splits[split] || Number.MAX_VALUE;
- }
- if (value.length != 0) {
- chars += value.length;
- screenColumn = self.$renderToken(
- stringBuilder, screenColumn, token, value
- );
- }
+
+// 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 (!ctrl && !alt) {
+ if (e.editor.inMultiSelectMode) {
+ if (button == 0) {
+ e.editor.exitMultiSelectMode();
+ } else if (button == 2) {
+ var editor = e.editor;
+ var selectionEmpty = editor.selection.isEmpty();
+ editor.textInput.onContextMenu({x: e.clientX, y: e.clientY}, selectionEmpty);
+ event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose);
+ e.stop();
}
}
+ return;
+ }
- if (this.showInvisibles) {
- if (lastRow !== this.session.getLength() - 1)
- stringBuilder.push("" + this.EOL_CHAR + "");
- else
- stringBuilder.push("" + this.EOF_CHAR + "");
- }
- stringBuilder.push("
");
- };
+ 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));
- this.$renderLine = function(stringBuilder, row, tokens, onlyContents) {
- // Check if the line to render is folded or not. If not, things are
- // simple, otherwise, we need to fake some things...
- if (!this.session.isRowFolded(row)) {
- var splits = this.session.getRowSplitData(row);
- this.$renderLineCore(stringBuilder, row, tokens, splits, onlyContents);
- } else {
- this.$renderFoldLine(stringBuilder, row, tokens, onlyContents);
- }
+
+ var mouseX = e.x, mouseY = e.y;
+ var onMouseSelection = function(e) {
+ mouseX = e.clientX;
+ mouseY = e.clientY;
};
- this.$renderFoldLine = function(stringBuilder, row, tokens, onlyContents) {
- var session = this.session,
- foldLine = session.getFoldLine(row),
- renderTokens = [];
+ var blockSelect = function() {
+ var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
+ var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column);
- function addTokens(tokens, from, to) {
- var idx = 0, col = 0;
- while ((col + tokens[idx].value.length) < from) {
- col += tokens[idx].value.length;
- idx++;
+ if (isSamePoint(screenCursor, newCursor)
+ && isSamePoint(cursor, selection.selectionLead))
+ return;
+ screenCursor = newCursor;
- 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);
- }
+ 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;
- renderTokens.push({
- type: tokens[idx].type,
- value: value
- });
+
- col = from + value.length;
- idx += 1;
- }
+ if (ctrl && !shift && !alt && button == 0) {
+ if (!isMultiSelect && inSelection)
+ return; // dragging
- while (col < to) {
- var value = tokens[idx].value;
- if (value.length + col > to) {
- value = value.substring(0, to - col);
- }
- renderTokens.push({
- type: tokens[idx].type,
- value: value
- });
- col += value.length;
- idx += 1;
- }
+ if (!isMultiSelect) {
+ var range = selection.toOrientedRange();
+ editor.addSelectionMarker(range);
}
- foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) {
- if (placeholder) {
- renderTokens.push({
- type: "fold",
- value: placeholder
- });
- } else {
- if (isNewRow) {
- tokens = this.session.getTokens(row, row)[0].tokens;
- }
- if (tokens.length != 0) {
- addTokens(tokens, lastColumn, column);
+ 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);
}
- }.bind(this), foldLine.end.row, this.session.getLine(foldLine.end.row).length);
+ });
- // TODO: Build a fake splits array!
- var splits = this.session.$useWrapMode?this.session.$wrapData[row]:null;
- this.$renderLineCore(stringBuilder, row, renderTokens, splits, onlyContents);
- };
+ } else if (!shift && alt && button == 0) {
+ e.stop();
- this.destroy = function() {
- clearInterval(this.$pollSizeChangesTimer);
- if (this.$measureNode)
- this.$measureNode.parentNode.removeChild(this.$measureNode);
- delete this.$measureNode;
- };
+ if (isMultiSelect && !ctrl)
+ selection.toSingleRange();
+ else if (!isMultiSelect && ctrl)
+ selection.addRange();
-}).call(Text.prototype);
+ selection.moveCursorToPosition(pos);
+ selection.clearSelection();
-exports.Text = Text;
+ 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;
});
/* vim:ts=4:sts=4:sw=4:
* ***** 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):
+ * Harutyun Amirjanyan
+ *
+ * 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('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
+}, {
+ name: "singleSelection",
+ bindKey: "esc",
+ exec: function(editor) { editor.exitMultiSelectMode(); },
+ readonly: true,
+ isAvailable: function(editor) {return editor.inMultiSelectMode}
+}];
+
+// commands active in multiselect mode
+exports.multiEditCommands = {"singleSelection": "esc"};
+
+var HashHandler = require("../keyboard/hash_handler").HashHandler;
+exports.keyboardHandler = new HashHandler(exports.multiEditCommands);
+
+});
+/* ***** 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
@@ -14825,7 +19081,6 @@ exports.Text = Text;
*
* Contributor(s):
* Fabian Jakobs
- * Julian Viereck
*
* 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
@@ -14841,111 +19096,133 @@ exports.Text = Text;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/layer/cursor', ['require', 'exports', 'module' , 'pilot/dom'], function(require, exports, module) {
+define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/config'], function(require, exports, module) {
+"use strict";
-var dom = require("pilot/dom");
+var oop = require("../lib/oop");
+var EventEmitter = require("../lib/event_emitter").EventEmitter;
+var config = require("../config");
-var Cursor = function(parentEl) {
- this.element = dom.createElement("div");
- this.element.className = "ace_layer ace_cursor-layer";
- parentEl.appendChild(this.element);
+var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
- this.cursor = dom.createElement("div");
- this.cursor.className = "ace_cursor ace_hidden";
- this.element.appendChild(this.cursor);
+ this.changeListener = this.changeListener.bind(this);
- this.isVisible = false;
-};
+ if (config.get("packaged")) {
+ this.$worker = new Worker(config.get("workerPath") + "/" + packagedJs);
+ }
+ else {
+ var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
+ this.$worker = new Worker(workerUrl);
-(function() {
+ var tlns = {};
+ for (var i=0; i
+ * Julian Viereck (julian.viereck@gmail.com)
*
* 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
@@ -14985,57 +19262,223 @@ exports.Cursor = Cursor;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/scrollbar', ['require', 'exports', 'module' , 'pilot/oop', 'pilot/dom', 'pilot/event', 'pilot/event_emitter'], function(require, exports, module) {
+define('ace/keyboard/state_handler', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
-var oop = require("pilot/oop");
-var dom = require("pilot/dom");
-var event = require("pilot/event");
-var EventEmitter = require("pilot/event_emitter").EventEmitter;
+// If you're developing a new keymapping and want to get an idea what's going
+// on, then enable debugging.
+var DEBUG = false;
-var ScrollBar = function(parent) {
- this.element = dom.createElement("div");
- this.element.className = "ace_sb";
+function StateHandler(keymapping) {
+ this.keymapping = this.$buildKeymappingRegex(keymapping);
+}
- this.inner = dom.createElement("div");
- this.element.appendChild(this.inner);
+StateHandler.prototype = {
+ /*
+ * Build the RegExp from the keymapping as RegExp can't stored directly
+ * in the metadata JSON and as the RegExp used to match the keys/buffer
+ * need to be adapted.
+ */
+ $buildKeymappingRegex: function(keymapping) {
+ for (var state in keymapping) {
+ this.$buildBindingsRegex(keymapping[state]);
+ }
+ return keymapping;
+ },
- parent.appendChild(this.element);
+ $buildBindingsRegex: function(bindings) {
+ // Escape a given Regex string.
+ bindings.forEach(function(binding) {
+ if (binding.key) {
+ binding.key = new RegExp('^' + binding.key + '$');
+ } else if (Array.isArray(binding.regex)) {
+ if (!('key' in binding))
+ binding.key = new RegExp('^' + binding.regex[1] + '$');
+ binding.regex = new RegExp(binding.regex.join('') + '$');
+ } else if (binding.regex) {
+ binding.regex = new RegExp(binding.regex + '$');
+ }
+ });
+ },
- // 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
- this.width = dom.scrollbarWidth();
- this.element.style.width = (this.width || 15) + "px";
+ $composeBuffer: function(data, hashId, key, e) {
+ // Initialize the data object.
+ if (data.state == null || data.buffer == null) {
+ data.state = "start";
+ data.buffer = "";
+ }
- event.addListener(this.element, "scroll", this.onScroll.bind(this));
-};
+ var keyArray = [];
+ if (hashId & 1) keyArray.push("ctrl");
+ if (hashId & 8) keyArray.push("command");
+ if (hashId & 2) keyArray.push("option");
+ if (hashId & 4) keyArray.push("shift");
+ if (key) keyArray.push(key);
-(function() {
- oop.implement(this, EventEmitter);
+ var symbolicName = keyArray.join("-");
+ var bufferToUse = data.buffer + symbolicName;
- this.onScroll = function() {
- this._dispatchEvent("scroll", {data: this.element.scrollTop});
- };
+ // Don't add the symbolic name to the key buffer if the alt_ key is
+ // part of the symbolic name. If it starts with alt_, this means
+ // that the user hit an alt keycombo and there will be a single,
+ // new character detected after this event, which then will be
+ // added to the buffer (e.g. alt_j will result in ∆).
+ //
+ // We test for 2 and not for & 2 as we only want to exclude the case where
+ // the option key is pressed alone.
+ if (hashId != 2) {
+ data.buffer = bufferToUse;
+ }
- this.getWidth = function() {
- return this.width;
- };
+ var bufferObj = {
+ bufferToUse: bufferToUse,
+ symbolicName: symbolicName,
+ };
+
+ if (e) {
+ bufferObj.keyIdentifier = e.keyIdentifier
+ }
+
+ return bufferObj;
+ },
+
+ $find: function(data, buffer, symbolicName, hashId, key, keyIdentifier) {
+ // Holds the command to execute and the args if a command matched.
+ var result = {};
+
+ // Loop over all the bindings of the keymap until a match is found.
+ this.keymapping[data.state].some(function(binding) {
+ var match;
+
+ // Check if the key matches.
+ if (binding.key && !binding.key.test(symbolicName)) {
+ return false;
+ }
+
+ // Check if the regex matches.
+ if (binding.regex && !(match = binding.regex.exec(buffer))) {
+ return false;
+ }
+
+ // Check if the match function matches.
+ if (binding.match && !binding.match(buffer, hashId, key, symbolicName, keyIdentifier)) {
+ return false;
+ }
+
+ // Check for disallowed matches.
+ if (binding.disallowMatches) {
+ for (var i = 0; i < binding.disallowMatches.length; i++) {
+ if (!!match[binding.disallowMatches[i]]) {
+ return false;
+ }
+ }
+ }
+
+ // If there is a command to execute, then figure out the
+ // command and the arguments.
+ if (binding.exec) {
+ result.command = binding.exec;
+
+ // Build the arguments.
+ if (binding.params) {
+ var value;
+ result.args = {};
+ binding.params.forEach(function(param) {
+ if (param.match != null && match != null) {
+ value = match[param.match] || param.defaultValue;
+ } else {
+ value = param.defaultValue;
+ }
+
+ if (param.type === 'number') {
+ value = parseInt(value);
+ }
+
+ result.args[param.name] = value;
+ });
+ }
+ data.buffer = "";
+ }
+
+ // Handle the 'then' property.
+ if (binding.then) {
+ data.state = binding.then;
+ data.buffer = "";
+ }
+
+ // If no command is set, then execute the "null" fake command.
+ if (result.command == null) {
+ result.command = "null";
+ }
+
+ if (DEBUG) {
+ console.log("KeyboardStateMapper#find", binding);
+ }
+ return true;
+ });
+
+ if (result.command) {
+ return result;
+ } else {
+ data.buffer = "";
+ return false;
+ }
+ },
- this.setHeight = function(height) {
- this.element.style.height = height + "px";
- };
+ /*
+ * This function is called by keyBinding.
+ */
+ handleKeyboard: function(data, hashId, key, keyCode, e) {
+ // If we pressed any command key but no other key, then ignore the input.
+ // Otherwise "shift-" is added to the buffer, and later on "shift-g"
+ // which results in "shift-shift-g" which doesn't make sense.
+ if (hashId != 0 && (key == "" || key == String.fromCharCode(0))) {
+ return null;
+ }
- this.setInnerHeight = function(height) {
- this.inner.style.height = height + "px";
- };
+ // Compute the current value of the keyboard input buffer.
+ var r = this.$composeBuffer(data, hashId, key, e);
+ var buffer = r.bufferToUse;
+ var symbolicName = r.symbolicName;
+ var keyId = r.keyIdentifier;
- this.setScrollTop = function(scrollTop) {
- this.element.scrollTop = scrollTop;
- };
+ r = this.$find(data, buffer, symbolicName, hashId, key, keyId);
+ if (DEBUG) {
+ console.log("KeyboardStateMapper#match", buffer, symbolicName, r);
+ }
-}).call(ScrollBar.prototype);
+ return r;
+ }
+}
-exports.ScrollBar = ScrollBar;
+/*
+ * This is a useful matching function and therefore is defined here so that
+ * users of KeyboardStateMapper can use it.
+ *
+ * @return boolean
+ * If no command key (Command|Option|Shift|Ctrl) is pressed, it
+ * returns true. If the only the Shift key is pressed + a character
+ * true is returned as well. Otherwise, false is returned.
+ * Summing up, the function returns true whenever the user typed
+ * a normal character on the keyboard and no shortcut.
+ */
+exports.matchCharacterOnly = function(buffer, hashId, key, symbolicName) {
+ // If no command keys are pressed, then catch the input.
+ if (hashId == 0) {
+ return true;
+ }
+ // If only the shift key is pressed and a character key, then
+ // catch that input as well.
+ else if ((hashId == 4) && key.length == 1) {
+ return true;
+ }
+ // Otherwise, we let the input got through.
+ else {
+ return false;
+ }
+};
+
+exports.StateHandler = StateHandler;
});
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -15058,7 +19501,7 @@ exports.ScrollBar = ScrollBar;
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Fabian Jakobs
+ * Zef Hemel
*
* 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
@@ -15073,73 +19516,247 @@ exports.ScrollBar = ScrollBar;
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
+define('ace/placeholder', ['require', 'exports', 'module' , 'ace/range', 'ace/lib/event_emitter', 'ace/lib/oop'], function(require, exports, module) {
+"use strict";
-define('ace/renderloop', ['require', 'exports', 'module' , 'pilot/event'], function(require, exports, module) {
+var Range = require('./range').Range;
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+var oop = require("./lib/oop");
-var event = require("pilot/event");
-
-var RenderLoop = function(onRender) {
- this.onRender = onRender;
- this.pending = false;
- this.changes = 0;
-};
+/**
+ * class PlaceHolder
+ *
+ * TODO
+ *
+ **/
-(function() {
+/**
+ * new PlaceHolder(session, length, pos, others, mainClass, othersClass)
+ * - session (Document): The document to associate with the anchor
+ * - length (Number): The starting row position
+ * - pos (Number): The starting column position
+ * - others (String):
+ * - mainClass (String):
+ * - othersClass (String):
+ *
+ * TODO
+ *
+ **/
- this.schedule = function(change) {
- //this.onRender(change);
- //return;
- this.changes = this.changes | change;
- if (!this.pending) {
- this.pending = true;
- var _self = this;
- this.setTimeoutZero(function() {
- _self.pending = false;
- var changes = _self.changes;
- _self.changes = 0;
- _self.onRender(changes);
- })
- }
+var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) {
+ var _self = this;
+ this.length = length;
+ this.session = session;
+ this.doc = session.getDocument();
+ this.mainClass = mainClass;
+ this.othersClass = othersClass;
+ this.$onUpdate = this.onUpdate.bind(this);
+ this.doc.on("change", this.$onUpdate);
+ this.$others = others;
+
+ this.$onCursorChange = function() {
+ setTimeout(function() {
+ _self.onCursorChange();
+ });
};
+
+ this.$pos = pos;
+ // Used for reset
+ var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1};
+ this.$undoStackDepth = undoStack.length;
+ this.setup();
- this.setTimeoutZero = window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.msRequestAnimationFrame;
+ session.selection.on("changeCursor", this.$onCursorChange);
+};
+
+(function() {
- if (this.setTimeoutZero) {
+ oop.implement(this, EventEmitter);
- this.setTimeoutZero = this.setTimeoutZero.bind(window)
- } else if (window.postMessage) {
+ /**
+ * PlaceHolder.setup()
+ *
+ * TODO
+ *
+ **/
+ this.setup = function() {
+ var _self = this;
+ var doc = this.doc;
+ var session = this.session;
+ var pos = this.$pos;
- this.messageName = "zero-timeout-message";
+ this.pos = doc.createAnchor(pos.row, pos.column);
+ this.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false);
+ this.pos.on("change", function(event) {
+ session.removeMarker(_self.markerId);
+ _self.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.mainClass, null, false);
+ });
+ this.others = [];
+ this.$others.forEach(function(other) {
+ var anchor = doc.createAnchor(other.row, other.column);
+ _self.others.push(anchor);
+ });
+ session.setUndoSelect(false);
+ };
+
+ /**
+ * PlaceHolder.showOtherMarkers()
+ *
+ * TODO
+ *
+ **/
+ this.showOtherMarkers = function() {
+ if(this.othersActive) return;
+ var session = this.session;
+ var _self = this;
+ this.othersActive = true;
+ this.others.forEach(function(anchor) {
+ anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false);
+ anchor.on("change", function(event) {
+ session.removeMarker(anchor.markerId);
+ anchor.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.othersClass, null, false);
+ });
+ });
+ };
+
+ /**
+ * PlaceHolder.hideOtherMarkers()
+ *
+ * Hides all over markers in the [[EditSession `EditSession`]] that are not the currently selected one.
+ *
+ **/
+ this.hideOtherMarkers = function() {
+ if(!this.othersActive) return;
+ this.othersActive = false;
+ for (var i = 0; i < this.others.length; i++) {
+ this.session.removeMarker(this.others[i].markerId);
+ }
+ };
- this.setTimeoutZero = function(callback) {
- if (!this.attached) {
- var _self = this;
- event.addListener(window, "message", function(e) {
- if (_self.callback && e.data == _self.messageName) {
- event.stopPropagation(e);
- _self.callback();
+ /**
+ * PlaceHolder@onUpdate(e)
+ *
+ * Emitted when the place holder updates.
+ *
+ **/
+ this.onUpdate = function(event) {
+ var delta = event.data;
+ var range = delta.range;
+ if(range.start.row !== range.end.row) return;
+ if(range.start.row !== this.pos.row) return;
+ if (this.$updating) return;
+ this.$updating = true;
+ var lengthDiff = delta.action === "insertText" ? range.end.column - range.start.column : range.start.column - range.end.column;
+
+ if(range.start.column >= 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);
}
- });
- this.attached = true;
+ } 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.callback = callback;
- window.postMessage(this.messageName, "*");
}
+ this.$updating = false;
+ };
+
+ /**
+ * PlaceHolder@onCursorChange(e)
+ *
+ * Emitted when the cursor changes.
+ *
+ **/
- } else {
-
- this.setTimeoutZero = function(callback) {
- setTimeout(callback, 0);
+ 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);
}
- }
+ };
+
+ /**
+ * PlaceHolder.detach()
+ *
+ * TODO
+ *
+ **/
+ 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);
+ };
+
+ /**
+ * PlaceHolder.cancel()
+ *
+ * TODO
+ *
+ **/
+ 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);
-}).call(RenderLoop.prototype);
-exports.RenderLoop = RenderLoop;
+exports.PlaceHolder = PlaceHolder;
});
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -15178,11 +19795,12 @@ exports.RenderLoop = RenderLoop;
*
* ***** END LICENSE BLOCK ***** */
-define('ace/theme/textmate', ['require', 'exports', 'module' , 'pilot/dom'], function(require, exports, module) {
-
- var dom = require("pilot/dom");
+define('ace/theme/textmate', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
+"use strict";
- var cssText = ".ace-tm .ace_editor {\
+exports.isDark = false;
+exports.cssClass = "ace-tm";
+exports.cssText = ".ace-tm .ace_editor {\
border: 2px solid rgb(159, 159, 159);\
}\
\
@@ -15191,19 +19809,8 @@ define('ace/theme/textmate', ['require', 'exports', 'module' , 'pilot/dom'], fun
}\
\
.ace-tm .ace_gutter {\
- width: 50px;\
background: #e8e8e8;\
color: #333;\
- overflow : hidden;\
-}\
-\
-.ace-tm .ace_gutter-layer {\
- width: 100%;\
- text-align: right;\
-}\
-\
-.ace-tm .ace_gutter-layer .ace_gutter-cell {\
- padding-right: 6px;\
}\
\
.ace-tm .ace_print_margin {\
@@ -15211,6 +19818,10 @@ define('ace/theme/textmate', ['require', 'exports', 'module' , 'pilot/dom'], fun
background: #e8e8e8;\
}\
\
+.ace-tm .ace_fold {\
+ background-color: #6B72E6;\
+}\
+\
.ace-tm .ace_text-layer {\
cursor: text;\
}\
@@ -15228,10 +19839,15 @@ define('ace/theme/textmate', ['require', 'exports', 'module' , 'pilot/dom'], fun
color: rgb(191, 191, 191);\
}\
\
+.ace-tm .ace_line .ace_storage,\
.ace-tm .ace_line .ace_keyword {\
color: blue;\
}\
\
+.ace-tm .ace_line .ace_constant {\
+ color: rgb(197, 6, 11);\
+}\
+\
.ace-tm .ace_line .ace_constant.ace_buildin {\
color: rgb(88, 72, 246);\
}\
@@ -15245,13 +19861,8 @@ define('ace/theme/textmate', ['require', 'exports', 'module' , 'pilot/dom'], fun
}\
\
.ace-tm .ace_line .ace_invalid {\
- background-color: rgb(153, 0, 0);\
- color: white;\
-}\
-\
-.ace-tm .ace_line .ace_fold {\
- background-color: #E4E4E4;\
- border-radius: 3px;\
+ background-color: rgba(255, 0, 0, 0.1);\
+ color: red;\
}\
\
.ace-tm .ace_line .ace_support.ace_function {\
@@ -15299,10 +19910,29 @@ define('ace/theme/textmate', ['require', 'exports', 'module' , 'pilot/dom'], fun
color: rgb(104, 104, 91);\
}\
\
+.ace-tm .ace_entity.ace_name.ace_function {\
+ color: #0000A2;\
+}\
+\
+.ace-tm .ace_markup.ace_markupine {\
+ text-decoration:underline;\
+}\
+\
+.ace-tm .ace_markup.ace_heading {\
+ color: rgb(12, 7, 255);\
+}\
+\
+.ace-tm .ace_markup.ace_list {\
+ color:rgb(185, 6, 144);\
+}\
+\
.ace-tm .ace_marker-layer .ace_selection {\
background: rgb(181, 213, 255);\
}\
-\
+.ace-tm.multiselect .ace_selection.start {\
+ box-shadow: 0 0 3px 0px white;\
+ border-radius: 2px;\
+}\
.ace-tm .ace_marker-layer .ace_step {\
background: rgb(252, 255, 0);\
}\
@@ -15319,2001 +19949,33 @@ define('ace/theme/textmate', ['require', 'exports', 'module' , 'pilot/dom'], fun
.ace-tm .ace_marker-layer .ace_active_line {\
background: rgba(0, 0, 0, 0.07);\
}\
+.ace-tm .ace_gutter_active_line{\
+ background-color : #dcdcdc;\
+}\
\
.ace-tm .ace_marker-layer .ace_selected_word {\
background: rgb(250, 250, 255);\
border: 1px solid rgb(200, 200, 250);\
}\
\
+.ace-tm .ace_meta.ace_tag {\
+ color:rgb(28, 2, 255);\
+}\
+\
.ace-tm .ace_string.ace_regex {\
color: rgb(255, 0, 0)\
}";
- // import CSS once
- dom.importCssString(cssText);
-
- exports.cssClass = "ace-tm";
-});
-/* ***** 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 DomTemplate.
- *
- * The Initial Developer of the Original Code is Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Joe Walker (jwalker@mozilla.com) (original author)
- *
- * 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('pilot/environment', ['require', 'exports', 'module' , 'pilot/settings'], function(require, exports, module) {
-
-
-var settings = require("pilot/settings").settings;
-
-/**
- * Create an environment object
- */
-function create() {
- return {
- settings: settings
- };
-};
-
-exports.create = create;
-
-
+var dom = require("../lib/dom");
+dom.importCssString(exports.cssText, exports.cssClass);
});
-define("text/cockpit/ui/cli_view.css", [], "" +
- "#cockpitInput { padding-left: 16px; }" +
- "" +
- ".cptOutput { overflow: auto; position: absolute; z-index: 999; display: none; }" +
- "" +
- ".cptCompletion { padding: 0; position: absolute; z-index: -1000; }" +
- ".cptCompletion.VALID { background: #FFF; }" +
- ".cptCompletion.INCOMPLETE { background: #DDD; }" +
- ".cptCompletion.INVALID { background: #DDD; }" +
- ".cptCompletion span { color: #FFF; }" +
- ".cptCompletion span.INCOMPLETE { color: #DDD; border-bottom: 2px dotted #F80; }" +
- ".cptCompletion span.INVALID { color: #DDD; border-bottom: 2px dotted #F00; }" +
- "span.cptPrompt { color: #66F; font-weight: bold; }" +
- "" +
- "" +
- ".cptHints {" +
- " color: #000;" +
- " position: absolute;" +
- " border: 1px solid rgba(230, 230, 230, 0.8);" +
- " background: rgba(250, 250, 250, 0.8);" +
- " -moz-border-radius-topleft: 10px;" +
- " -moz-border-radius-topright: 10px;" +
- " border-top-left-radius: 10px; border-top-right-radius: 10px;" +
- " z-index: 1000;" +
- " padding: 8px;" +
- " display: none;" +
- "}" +
- "" +
- ".cptFocusPopup { display: block; }" +
- ".cptFocusPopup.cptNoPopup { display: none; }" +
- "" +
- ".cptHints ul { margin: 0; padding: 0 15px; }" +
- "" +
- ".cptGt { font-weight: bold; font-size: 120%; }" +
- "");
-
-define("text/cockpit/ui/request_view.css", [], "" +
- ".cptRowIn {" +
- " display: box; display: -moz-box; display: -webkit-box;" +
- " box-orient: horizontal; -moz-box-orient: horizontal; -webkit-box-orient: horizontal;" +
- " box-align: center; -moz-box-align: center; -webkit-box-align: center;" +
- " color: #333;" +
- " background-color: #EEE;" +
- " width: 100%;" +
- " font-family: consolas, courier, monospace;" +
- "}" +
- ".cptRowIn > * { padding-left: 2px; padding-right: 2px; }" +
- ".cptRowIn > img { cursor: pointer; }" +
- ".cptHover { display: none; }" +
- ".cptRowIn:hover > .cptHover { display: block; }" +
- ".cptRowIn:hover > .cptHover.cptHidden { display: none; }" +
- ".cptOutTyped {" +
- " box-flex: 1; -moz-box-flex: 1; -webkit-box-flex: 1;" +
- " font-weight: bold; color: #000; font-size: 120%;" +
- "}" +
- ".cptRowOutput { padding-left: 10px; line-height: 1.2em; }" +
- ".cptRowOutput strong," +
- ".cptRowOutput b," +
- ".cptRowOutput th," +
- ".cptRowOutput h1," +
- ".cptRowOutput h2," +
- ".cptRowOutput h3 { color: #000; }" +
- ".cptRowOutput a { font-weight: bold; color: #666; text-decoration: none; }" +
- ".cptRowOutput a: hover { text-decoration: underline; cursor: pointer; }" +
- ".cptRowOutput input[type=password]," +
- ".cptRowOutput input[type=text]," +
- ".cptRowOutput textarea {" +
- " color: #000; font-size: 120%;" +
- " background: transparent; padding: 3px;" +
- " border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;" +
- "}" +
- ".cptRowOutput table," +
- ".cptRowOutput td," +
- ".cptRowOutput th { border: 0; padding: 0 2px; }" +
- ".cptRowOutput .right { text-align: right; }" +
- "");
-
-define("text/ace/css/editor.css", [], ".ace_editor {" +
- " position: absolute;" +
- " overflow: hidden;" +
- " font-family: Monaco, \"Menlo\", \"Courier New\", monospace;" +
- " font-size: 12px;" +
- "}" +
- "" +
- ".ace_scroller {" +
- " position: absolute;" +
- " overflow-x: scroll;" +
- " overflow-y: hidden;" +
- "}" +
- "" +
- ".ace_content {" +
- " position: absolute;" +
- " box-sizing: border-box;" +
- " -moz-box-sizing: border-box;" +
- " -webkit-box-sizing: border-box;" +
- "}" +
- "" +
- ".ace_composition {" +
- " position: absolute;" +
- " background: #555;" +
- " color: #DDD;" +
- " z-index: 4;" +
- "}" +
- "" +
- ".ace_gutter {" +
- " position: absolute;" +
- " overflow-x: hidden;" +
- " overflow-y: hidden;" +
- " height: 100%;" +
- "}" +
- "" +
- ".ace_gutter-cell.ace_error {" +
- " background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%F5or%F5%87%88%F5nr%F4ns%EBmq%F5z%7F%DDJT%DEKS%DFOW%F1Yc%F2ah%CE(7%CE)8%D18E%DD%40M%F2KZ%EBU%60%F4%60m%DCir%C8%16(%C8%19*%CE%255%F1%3FR%F1%3FS%E6%AB%B5%CA%5DI%CEn%5E%F7%A2%9A%C9G%3E%E0a%5B%F7%89%85%F5yy%F6%82%80%ED%82%80%FF%BF%BF%E3%C4%C4%FF%FF%FF%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%25%00%2C%00%00%00%00%10%00%10%00%00%06p%C0%92pH%2C%1A%8F%C8%D2H%93%E1d4%23%E4%88%D3%09mB%1DN%B48%F5%90%40%60%92G%5B%94%20%3E%22%D2%87%24%FA%20%24%C5%06A%00%20%B1%07%02B%A38%89X.v%17%82%11%13q%10%0Fi%24%0F%8B%10%7BD%12%0Ei%09%92%09%0EpD%18%15%24%0A%9Ci%05%0C%18F%18%0B%07%04%01%04%06%A0H%18%12%0D%14%0D%12%A1I%B3%B4%B5IA%00%3B\");" +
- " background-repeat: no-repeat;" +
- " background-position: 4px center;" +
- "}" +
- "" +
- ".ace_gutter-cell.ace_warning {" +
- " background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%FF%DBr%FF%DE%81%FF%E2%8D%FF%E2%8F%FF%E4%96%FF%E3%97%FF%E5%9D%FF%E6%9E%FF%EE%C1%FF%C8Z%FF%CDk%FF%D0s%FF%D4%81%FF%D5%82%FF%D5%83%FF%DC%97%FF%DE%9D%FF%E7%B8%FF%CCl%7BQ%13%80U%15%82W%16%81U%16%89%5B%18%87%5B%18%8C%5E%1A%94d%1D%C5%83-%C9%87%2F%C6%84.%C6%85.%CD%8B2%C9%871%CB%8A3%CD%8B5%DC%98%3F%DF%9BB%E0%9CC%E1%A5U%CB%871%CF%8B5%D1%8D6%DB%97%40%DF%9AB%DD%99B%E3%B0p%E7%CC%AE%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%2F%00%2C%00%00%00%00%10%00%10%00%00%06a%C0%97pH%2C%1A%8FH%A1%ABTr%25%87%2B%04%82%F4%7C%B9X%91%08%CB%99%1C!%26%13%84*iJ9(%15G%CA%84%14%01%1A%97%0C%03%80%3A%9A%3E%81%84%3E%11%08%B1%8B%20%02%12%0F%18%1A%0F%0A%03'F%1C%04%0B%10%16%18%10%0B%05%1CF%1D-%06%07%9A%9A-%1EG%1B%A0%A1%A0U%A4%A5%A6BA%00%3B\");" +
- " background-repeat: no-repeat;" +
- " background-position: 4px center;" +
- "}" +
- "" +
- ".ace_editor .ace_sb {" +
- " position: absolute;" +
- " overflow-x: hidden;" +
- " overflow-y: scroll;" +
- " right: 0;" +
- "}" +
- "" +
- ".ace_editor .ace_sb div {" +
- " position: absolute;" +
- " width: 1px;" +
- " left: 0;" +
- "}" +
- "" +
- ".ace_editor .ace_print_margin_layer {" +
- " z-index: 0;" +
- " position: absolute;" +
- " overflow: hidden;" +
- " margin: 0;" +
- " left: 0;" +
- " height: 100%;" +
- " width: 100%;" +
- "}" +
- "" +
- ".ace_editor .ace_print_margin {" +
- " position: absolute;" +
- " height: 100%;" +
- "}" +
- "" +
- ".ace_editor textarea {" +
- " position: fixed;" +
- " z-index: -1;" +
- " width: 10px;" +
- " height: 30px;" +
- " opacity: 0;" +
- " background: transparent;" +
- " appearance: none;" +
- " -moz-appearance: none;" +
- " border: none;" +
- " resize: none;" +
- " outline: none;" +
- " overflow: hidden;" +
- "}" +
- "" +
- ".ace_layer {" +
- " z-index: 1;" +
- " position: absolute;" +
- " overflow: hidden;" +
- " white-space: nowrap;" +
- " height: 100%;" +
- " width: 100%;" +
- "}" +
- "" +
- ".ace_text-layer {" +
- " color: black;" +
- "}" +
- "" +
- ".ace_cjk {" +
- " display: inline-block;" +
- " text-align: center;" +
- "}" +
- "" +
- ".ace_cursor-layer {" +
- " z-index: 4;" +
- " cursor: text;" +
- " /* setting pointer-events: none; here will break mouse wheel scrolling in Safari */" +
- "}" +
- "" +
- ".ace_cursor {" +
- " z-index: 4;" +
- " position: absolute;" +
- "}" +
- "" +
- ".ace_cursor.ace_hidden {" +
- " opacity: 0.2;" +
- "}" +
- "" +
- ".ace_line {" +
- " white-space: nowrap;" +
- "}" +
- "" +
- ".ace_marker-layer {" +
- " cursor: text;" +
- " pointer-events: none;" +
- "}" +
- "" +
- ".ace_marker-layer .ace_step {" +
- " position: absolute;" +
- " z-index: 3;" +
- "}" +
- "" +
- ".ace_marker-layer .ace_selection {" +
- " position: absolute;" +
- " z-index: 4;" +
- "}" +
- "" +
- ".ace_marker-layer .ace_bracket {" +
- " position: absolute;" +
- " z-index: 5;" +
- "}" +
- "" +
- ".ace_marker-layer .ace_active_line {" +
- " position: absolute;" +
- " z-index: 2;" +
- "}" +
- "" +
- ".ace_marker-layer .ace_selected_word {" +
- " position: absolute;" +
- " z-index: 6;" +
- " box-sizing: border-box;" +
- " -moz-box-sizing: border-box;" +
- " -webkit-box-sizing: border-box;" +
- "}" +
- "" +
- ".ace_line .ace_fold {" +
- " cursor: pointer;" +
- "}" +
- "" +
- ".ace_dragging .ace_marker-layer, .ace_dragging .ace_text-layer {" +
- " cursor: move;" +
- "}" +
- "");
-
-define("text/build/demo/styles.css", [], "html {" +
- " height: 100%;" +
- " width: 100%;" +
- " overflow: hidden;" +
- "}" +
- "" +
- "body {" +
- " overflow: hidden;" +
- " margin: 0;" +
- " padding: 0;" +
- " height: 100%;" +
- " width: 100%;" +
- " font-family: Arial, Helvetica, sans-serif, Tahoma, Verdana, sans-serif;" +
- " font-size: 12px;" +
- " background: rgb(14, 98, 165);" +
- " color: white;" +
- "}" +
- "" +
- "#logo {" +
- " padding: 15px;" +
- " margin-left: 65px;" +
- "}" +
- "" +
- "#editor {" +
- " position: absolute;" +
- " top: 0px;" +
- " left: 280px;" +
- " bottom: 0px;" +
- " right: 0px;" +
- " background: white;" +
- "}" +
- "" +
- "#controls {" +
- " padding: 5px;" +
- "}" +
- "" +
- "#controls td {" +
- " text-align: right;" +
- "}" +
- "" +
- "#controls td + td {" +
- " text-align: left;" +
- "}" +
- "" +
- "#cockpitInput {" +
- " position: absolute;" +
- " left: 280px;" +
- " right: 0px;" +
- " bottom: 0;" +
- "" +
- " border: none; outline: none;" +
- " font-family: consolas, courier, monospace;" +
- " font-size: 120%;" +
- "}" +
- "" +
- "#cockpitOutput {" +
- " padding: 10px;" +
- " margin: 0 15px;" +
- " border: 1px solid #AAA;" +
- " -moz-border-radius-topleft: 10px;" +
- " -moz-border-radius-topright: 10px;" +
- " border-top-left-radius: 4px; border-top-right-radius: 4px;" +
- " background: #DDD; color: #000;" +
- "}");
-
-define("text/build_support/style.css", [], "body {" +
- " margin:0;" +
- " padding:0;" +
- " background-color:#e6f5fc;" +
- " " +
- "}" +
- "" +
- "H2, H3, H4 {" +
- " font-family:Trebuchet MS;" +
- " font-weight:bold;" +
- " margin:0;" +
- " padding:0;" +
- "}" +
- "" +
- "H2 {" +
- " font-size:28px;" +
- " color:#263842;" +
- " padding-bottom:6px;" +
- "}" +
- "" +
- "H3 {" +
- " font-family:Trebuchet MS;" +
- " font-weight:bold;" +
- " font-size:22px;" +
- " color:#253741;" +
- " margin-top:43px;" +
- " margin-bottom:8px;" +
- "}" +
- "" +
- "H4 {" +
- " font-family:Trebuchet MS;" +
- " font-weight:bold;" +
- " font-size:21px;" +
- " color:#222222;" +
- " margin-bottom:4px;" +
- "}" +
- "" +
- "P {" +
- " padding:13px 0;" +
- " margin:0;" +
- " line-height:22px;" +
- "}" +
- "" +
- "UL{" +
- " line-height : 22px;" +
- "}" +
- "" +
- "PRE{" +
- " background : #333;" +
- " color : white;" +
- " padding : 10px;" +
- "}" +
- "" +
- "#header {" +
- " height : 227px;" +
- " position:relative;" +
- " overflow:hidden;" +
- " background: url(images/background.png) repeat-x 0 0;" +
- " border-bottom:1px solid #c9e8fa; " +
- "}" +
- "" +
- "#header .content .signature {" +
- " font-family:Trebuchet MS;" +
- " font-size:11px;" +
- " color:#ebe4d6;" +
- " position:absolute;" +
- " bottom:5px;" +
- " right:42px;" +
- " letter-spacing : 1px;" +
- "}" +
- "" +
- ".content {" +
- " width:970px;" +
- " position:relative;" +
- " overflow:hidden;" +
- " margin:0 auto;" +
- "}" +
- "" +
- "#header .content {" +
- " height:184px;" +
- " margin-top:22px;" +
- "}" +
- "" +
- "#header .content .logo {" +
- " width : 282px;" +
- " height : 184px;" +
- " background:url(images/logo.png) no-repeat 0 0;" +
- " position:absolute;" +
- " top:0;" +
- " left:0;" +
- "}" +
- "" +
- "#header .content .title {" +
- " width : 605px;" +
- " height : 58px;" +
- " background:url(images/ace.png) no-repeat 0 0;" +
- " position:absolute;" +
- " top:98px;" +
- " left:329px;" +
- "}" +
- "" +
- "#wrapper {" +
- " background:url(images/body_background.png) repeat-x 0 0;" +
- " min-height:250px;" +
- "}" +
- "" +
- "#wrapper .content {" +
- " font-family:Arial;" +
- " font-size:14px;" +
- " color:#222222;" +
- " width:1000px;" +
- "}" +
- "" +
- "#wrapper .content .column1 {" +
- " position:relative;" +
- " overflow:hidden;" +
- " float:left;" +
- " width:315px;" +
- " margin-right:31px;" +
- "}" +
- "" +
- "#wrapper .content .column2 {" +
- " position:relative;" +
- " overflow:hidden;" +
- " float:left;" +
- " width:600px;" +
- " padding-top:47px;" +
- "}" +
- "" +
- ".fork_on_github {" +
- " width:310px;" +
- " height:80px;" +
- " background:url(images/fork_on_github.png) no-repeat 0 0;" +
- " position:relative;" +
- " overflow:hidden;" +
- " margin-top:49px;" +
- " cursor:pointer;" +
- "}" +
- "" +
- ".fork_on_github:hover {" +
- " background-position:0 -80px;" +
- "}" +
- "" +
- ".divider {" +
- " height:3px;" +
- " background-color:#bedaea;" +
- " margin-bottom:3px;" +
- "}" +
- "" +
- ".menu {" +
- " padding:23px 0 0 24px;" +
- "}" +
- "" +
- "UL.content-list {" +
- " padding:15px;" +
- " margin:0;" +
- "}" +
- "" +
- "UL.menu-list {" +
- " padding:0;" +
- " margin:0 0 20px 0;" +
- " list-style-type:none;" +
- " line-height : 16px;" +
- "}" +
- "" +
- "UL.menu-list LI {" +
- " color:#2557b4;" +
- " font-family:Trebuchet MS;" +
- " font-size:14px;" +
- " padding:7px 0;" +
- " border-bottom:1px dotted #d6e2e7;" +
- "}" +
- "" +
- "UL.menu-list LI:last-child {" +
- " border-bottom:0;" +
- "}" +
- "" +
- "A {" +
- " color:#2557b4;" +
- " text-decoration:none;" +
- "}" +
- "" +
- "A:hover {" +
- " text-decoration:underline;" +
- "}" +
- "" +
- "P#first{" +
- " background : rgba(255,255,255,0.5);" +
- " padding : 20px;" +
- " font-size : 16px;" +
- " line-height : 24px;" +
- " margin : 0 0 20px 0;" +
- "}" +
- "" +
- "#footer {" +
- " height:40px;" +
- " position:relative;" +
- " overflow:hidden;" +
- " background:url(images/bottombar.png) repeat-x 0 0;" +
- " position:relative;" +
- " margin-top:40px;" +
- "}" +
- "" +
- "UL.menu-footer {" +
- " padding:0;" +
- " margin:8px 11px 0 0;" +
- " list-style-type:none;" +
- " float:right;" +
- "}" +
- "" +
- "UL.menu-footer LI {" +
- " color:white;" +
- " font-family:Arial;" +
- " font-size:12px;" +
- " display:inline-block;" +
- " margin:0 1px;" +
- "}" +
- "" +
- "UL.menu-footer LI A {" +
- " color:#8dd0ff;" +
- " text-decoration:none;" +
- "}" +
- "" +
- "UL.menu-footer LI A:hover {" +
- " text-decoration:underline;" +
- "}" +
- "" +
- "" +
- "" +
- "" +
- "");
-
-define("text/demo/styles.css", [], "html {" +
- " height: 100%;" +
- " width: 100%;" +
- " overflow: hidden;" +
- "}" +
- "" +
- "body {" +
- " overflow: hidden;" +
- " margin: 0;" +
- " padding: 0;" +
- " height: 100%;" +
- " width: 100%;" +
- " font-family: Arial, Helvetica, sans-serif, Tahoma, Verdana, sans-serif;" +
- " font-size: 12px;" +
- " background: rgb(14, 98, 165);" +
- " color: white;" +
- "}" +
- "" +
- "#logo {" +
- " padding: 15px;" +
- " margin-left: 65px;" +
- "}" +
- "" +
- "#editor {" +
- " position: absolute;" +
- " top: 0px;" +
- " left: 280px;" +
- " bottom: 0px;" +
- " right: 0px;" +
- " background: white;" +
- "}" +
- "" +
- "#controls {" +
- " padding: 5px;" +
- "}" +
- "" +
- "#controls td {" +
- " text-align: right;" +
- "}" +
- "" +
- "#controls td + td {" +
- " text-align: left;" +
- "}" +
- "" +
- "#cockpitInput {" +
- " position: absolute;" +
- " left: 280px;" +
- " right: 0px;" +
- " bottom: 0;" +
- "" +
- " border: none; outline: none;" +
- " font-family: consolas, courier, monospace;" +
- " font-size: 120%;" +
- "}" +
- "" +
- "#cockpitOutput {" +
- " padding: 10px;" +
- " margin: 0 15px;" +
- " border: 1px solid #AAA;" +
- " -moz-border-radius-topleft: 10px;" +
- " -moz-border-radius-topright: 10px;" +
- " border-top-left-radius: 4px; border-top-right-radius: 4px;" +
- " background: #DDD; color: #000;" +
- "}");
-
-define("text/deps/csslint/demos/demo.css", [], "@charset \"UTF-8\";" +
- "" +
- "@import url(\"booya.css\") print,screen;" +
- "@import \"whatup.css\" screen;" +
- "@import \"wicked.css\";" +
- "" +
- "@namespace \"http://www.w3.org/1999/xhtml\";" +
- "@namespace svg \"http://www.w3.org/2000/svg\";" +
- "" +
- "li.inline #foo {" +
- " background: url(\"something.png\");" +
- " display: inline;" +
- " padding-left: 3px;" +
- " padding-right: 7px;" +
- " border-right: 1px dotted #066;" +
- "}" +
- "" +
- "li.last.first {" +
- " display: inline;" +
- " padding-left: 3px !important;" +
- " padding-right: 3px;" +
- " border-right: 0px;" +
- "}" +
- "" +
- "@media print {" +
- " li.inline {" +
- " color: black;" +
- " }" +
- "" +
- "" +
- "@charset \"UTF-8\"; " +
- "" +
- "@page {" +
- " margin: 10%;" +
- " counter-increment: page;" +
- "" +
- " @top-center {" +
- " font-family: sans-serif;" +
- " font-weight: bold;" +
- " font-size: 2em;" +
- " content: counter(page);" +
- " }" +
- "}");
-
-define("text/deps/requirejs/dist/ie.css", [], "" +
- "body .sect {" +
- " display: none;" +
- "}" +
- "" +
- "" +
- "#content ul.index {" +
- " list-style: none;" +
- "}" +
- "");
-
-define("text/deps/requirejs/dist/main.css", [], "@font-face {" +
- " font-family: Inconsolata;" +
- " src: url(\"fonts/Inconsolata.ttf\");" +
- "}" +
- "" +
- "* {" +
- " -moz-box-sizing: border-box;" +
- " -webkit-box-sizing: border-box;" +
- " box-sizing: border-box;" +
- " margin: 0;" +
- " padding: 0;" +
- "}" +
- "" +
- "body {" +
- " font-size: 12px;" +
- " line-height: 21px;" +
- " background-color: #fff;" +
- " font-family: \"Helvetica Neue\", Helvetica, Arial, Verdana, sans-serif;" +
- " color: #0a0a0a;" +
- "}" +
- "" +
- "#wrapper {" +
- " margin: 0;" +
- "}" +
- "" +
- "#grid {" +
- " position: fixed;" +
- " top: 0;" +
- " left: 0;" +
- " width: 796px;" +
- " background-image: url(\"i/grid.png\");" +
- " z-index: 100;" +
- "}" +
- "" +
- "pre {" +
- " line-height: 18px;" +
- " font-size: 13px;" +
- " margin: 7px 0 21px;" +
- " padding: 5px 10px;" +
- " overflow: auto;" +
- " background-color: #fafafa;" +
- " border: 1px solid #e6e6e6;" +
- " -moz-border-radius: 5px;" +
- " -webkit-border-radius: 5px;" +
- " border-radius: 5px;" +
- " -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);" +
- " -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);" +
- " box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);" +
- "}" +
- "" +
- "/*" +
- " typography stuff" +
- "*/" +
- ".mono {" +
- " font-family: \"Inconsolata\", Andale Mono, Monaco, Monospace;" +
- "}" +
- "" +
- ".sans {" +
- " font-family: \"Helvetica Neue\", Helvetica, Arial, Verdana, sans-serif;" +
- "}" +
- "" +
- ".serif {" +
- " font-family: \"Georgia\", Times New Roman, Times, serif;" +
- "}" +
- "" +
- "a {" +
- " color: #2e87dd;" +
- " text-decoration: none;" +
- "}" +
- "" +
- "a:hover {" +
- " text-decoration: underline;" +
- "}" +
- "" +
- "/*" +
- " navigation" +
- "*/" +
- "" +
- "#navBg {" +
- " background-color: #f2f2f2;" +
- " background-image: url(\"i/shadow.png\");" +
- " background-position: right top;" +
- " background-repeat: repeat-y;" +
- " width: 220px;" +
- " position: fixed;" +
- " top: 0;" +
- " left: 0;" +
- " z-index: 0;" +
- "}" +
- "" +
- "#nav {" +
- " background-image: url(\"i/logo.png\");" +
- " background-repeat: no-repeat;" +
- " background-position: center 10px;" +
- " width: 220px;" +
- " float: left;" +
- " margin: 0;" +
- " padding: 150px 20px 0;" +
- " font-size: 13px;" +
- " text-shadow: 1px 1px #fff;" +
- " position: relative;" +
- " z-index: 1;" +
- "}" +
- "" +
- "#nav .homeImageLink {" +
- " position: absolute;" +
- " display: block;" +
- " top: 10px;" +
- " left: 0;" +
- " width: 220px;" +
- " height: 138px;" +
- "}" +
- "#nav ul {" +
- " list-style-type:none;" +
- " padding: 0;" +
- " margin: 21px 0 0 0;" +
- "}" +
- "" +
- "#nav ul li {" +
- " width: 100%;" +
- "}" +
- "" +
- "#nav ul li.version {" +
- " text-align: center;" +
- " color: #4d4d4d;" +
- "}" +
- "" +
- "#nav h1 {" +
- " color: #4d4d4d;" +
- " text-align: center;" +
- " font-size: 15px;" +
- " font-weight: normal;" +
- " text-transform: uppercase;" +
- " letter-spacing: 3px;" +
- "}" +
- "" +
- "span.spacer {" +
- " color: #2e87dd;" +
- " margin: 0 3px 0 5px;" +
- " background-image: url(\"i/dot.png\");" +
- " background-repeat: repeat-x;" +
- " background-position: left 13px;" +
- "}" +
- "" +
- "/*" +
- " icons" +
- "*/" +
- "" +
- "span.icon {" +
- " width: 16px;" +
- " display: block;" +
- " background-image: url(\"i/sprite.png\");" +
- " background-repeat: no-repeat;" +
- "}" +
- "" +
- "span.icon.home {" +
- " background-position: center 5px;" +
- "}" +
- "" +
- "span.icon.start {" +
- " background-position: center -27px;" +
- "}" +
- "" +
- "span.icon.download {" +
- " background-position: center -59px;" +
- "}" +
- "" +
- "span.icon.api {" +
- " background-position: center -89px;" +
- "}" +
- "" +
- "span.icon.optimize {" +
- " background-position: center -119px;" +
- "}" +
- "" +
- "span.icon.script {" +
- " background-position: center -150px;" +
- "}" +
- "" +
- "span.icon.question {" +
- " background-position: center -182px;" +
- "}" +
- "" +
- "span.icon.requirement {" +
- " background-position: center -214px;" +
- "}" +
- "" +
- "span.icon.history {" +
- " background-position: center -247px;" +
- "}" +
- "" +
- "span.icon.help {" +
- " background-position: center -279px;" +
- "}" +
- "" +
- "span.icon.blog {" +
- " background-position: center -311px;" +
- "}" +
- "" +
- "span.icon.twitter {" +
- " background-position: center -343px;" +
- "}" +
- "" +
- "span.icon.git {" +
- " background-position: center -375px;" +
- "}" +
- "" +
- "span.icon.fork {" +
- " background-position: center -407px;" +
- "}" +
- "" +
- "/*" +
- " content" +
- "*/" +
- "" +
- "#content {" +
- " margin: 0 0 0 220px;" +
- " padding: 0 20px;" +
- " background-color: #fff;" +
- " font-family: \"Georgia\", Times New Roman, Times, serif;" +
- " position: relative;" +
- "}" +
- "" +
- "#content p {" +
- " padding: 7px 0;" +
- " color: #333;" +
- " font-size: 14px;" +
- "}" +
- "" +
- "#content h1," +
- "#content h2," +
- "#content h3," +
- "#content h4," +
- "#content h5 {" +
- " font-weight: normal;" +
- " padding: 21px 0 7px;" +
- "}" +
- "" +
- "#content h1 {" +
- " font-size: 21px;" +
- "}" +
- "" +
- "#content h2 {" +
- " padding: 0 0 18px 0;" +
- " margin: 0 0 7px 0;" +
- " font-weight: normal;" +
- " font-size: 21px;" +
- " line-height: 24px;" +
- " text-align: center;" +
- " color: #222;" +
- " background-image: url(\"i/arrow.png\");" +
- " background-repeat: no-repeat;" +
- " background-position: center bottom;" +
- " font-family: \"Inconsolata\", Andale Mono, Monaco, Monospace;" +
- " text-transform: uppercase;" +
- " letter-spacing: 2px;" +
- " text-shadow: 1px 1px 0 #fff;" +
- "}" +
- "" +
- "#content h2 a {" +
- " color: #222;" +
- "}" +
- "" +
- "#content h2 a:hover," +
- "#content h3 a:hover," +
- "#content h4 a:hover {" +
- " text-decoration: none;" +
- "}" +
- "" +
- "span.sectionMark {" +
- " display: block;" +
- " color: #aaa;" +
- " text-shadow: 1px 1px 0 #fff;" +
- " font-size: 15px;" +
- " font-family: \"Inconsolata\", Andale Mono, Monaco, Monospace;" +
- "}" +
- "" +
- "#content h3 {" +
- " font-size: 17px;" +
- "}" +
- "" +
- "#content h4 {" +
- " padding-top: 0;" +
- " font-size: 15px;" +
- "}" +
- "" +
- "#content h5 {" +
- " font-size: 10px;" +
- "}" +
- "" +
- "#content ul {" +
- " list-style-type: disc;" +
- "}" +
- "" +
- "#content ul," +
- "#content ol {" +
- " /* border-left: 1px solid #333; */" +
- " color: #333;" +
- " font-size: 14px;" +
- " list-style-position: outside;" +
- " margin: 7px 0 21px 0;" +
- " /* padding: 0 0 0 28px; */" +
- "}" +
- "" +
- "#content ul {" +
- " font-style: italic;" +
- "}" +
- "" +
- "#content ol {" +
- " border: none;" +
- " list-style-position: inside;" +
- " padding: 0;" +
- " font-family: \"Georgia\", Times New Roman, Times, serif;" +
- "}" +
- "" +
- "#content ul ul," +
- "#content ol ol {" +
- " border: none;" +
- " padding: 0;" +
- " margin: 0 0 0 28px;" +
- "}" +
- "" +
- "#content .section {" +
- " padding: 48px 0;" +
- " background-image: url(\"i/line.png\");" +
- " background-repeat: no-repeat;" +
- " background-position: center bottom;" +
- " width: 576px;" +
- " margin: 0 auto;" +
- "}" +
- "" +
- "#content .section .subSection {" +
- " padding: 0 0 0 48px;" +
- " margin: 28px 0 0 0;" +
- " display: block;" +
- " border-left: 2px solid #ddd;" +
- "}" +
- "" +
- "#content .section:last-child {" +
- " background-image: none;" +
- "}" +
- "" +
- "#content .note {" +
- " color: #222;" +
- " background-color: #ffff99;" +
- " padding: 5px 10px;" +
- " margin: 7px 0;" +
- " display: inline-block;" +
- "}" +
- "" +
- "/*" +
- " page directory" +
- "*/" +
- "" +
- "#content #directory.section {" +
- " background-color: #fff;" +
- " width: 576px;" +
- "}" +
- "" +
- "#content #directory.section ul ul ul {" +
- " margin: 0 0 0 48px;" +
- "}" +
- "" +
- "#content #directory.section ul ul li {" +
- " background-image: url(\"i/sprite.png\");" +
- " background-repeat: no-repeat;" +
- " background-position: left -437px;" +
- " padding-left: 18px;" +
- " font-style: normal;" +
- "}" +
- "" +
- "#content #directory h1 {" +
- " padding: 0 0 65px 0;" +
- " margin: 0 0 14px 0;" +
- " font-weight: normal;" +
- " font-size: 21px;" +
- " text-align: center;" +
- " text-transform: uppercase;" +
- " letter-spacing: 2px;" +
- " color: #222;" +
- " background-image: url(\"i/arrow-x.png\");" +
- " background-repeat: no-repeat;" +
- " background-position: center bottom;" +
- " font-family: \"Inconsolata\", Andale Mono, Monaco, Monospace;" +
- "}" +
- "" +
- "" +
- "#content ul.index {" +
- " padding: 0;" +
- " background-color: transparent;" +
- " border: none;" +
- " -moz-box-shadow: none;" +
- " font-style: normal;" +
- " font-family: \"Inconsolata\", Andale Mono, Monaco, Monospace;" +
- "}" +
- "" +
- "#content ul.index li {" +
- " width: 100%;" +
- " font-size: 15px;" +
- " color: #333;" +
- " padding: 0 0 7px 0;" +
- "}" +
- "" +
- "" +
- "/*" +
- " intro page specific" +
- "*/" +
- "" +
- "#content #intro {" +
- " width: 576px;" +
- " margin: 0 auto;" +
- " padding: 21px 0;" +
- "}" +
- "" +
- "#content #intro p," +
- "#content #intro h1 {" +
- " font-size: 19px;" +
- " line-height: 28px;" +
- " color: green;" +
- " letter-spacing: 2px;" +
- " padding: 0 0 28px 0;" +
- "}" +
- "" +
- "#content #intro p:last-child," +
- "#content #intro h1:last-child {" +
- " padding: 0;" +
- "}" +
- "" +
- "#content #intro p a {" +
- " color: green;" +
- " text-decoration: underline;" +
- "}" +
- "" +
- "/*" +
- " download page" +
- "*/" +
- "" +
- "#content h4 a.download {" +
- " -webkit-border-radius: 5px;" +
- " -moz-border-radius: 5px;" +
- " background-color: #F2F2F2;" +
- " background-image: url(\"i/sprite.png\"), -moz-linear-gradient(center top , #FAFAFA 0%, #F2F2F2 100%);" +
- " background-image: url(\"i/sprite.png\"), -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fafafa), color-stop(100%, #f2f2f2));" +
- " background-position: 7px -58px, center center;" +
- " background-repeat: no-repeat, no-repeat;" +
- " border: 1px solid #CCCCCC;" +
- " color: #333333;" +
- " font-size: 12px;" +
- " margin: 0 0 0 5px;" +
- " padding: 0 10px 0 25px;" +
- " text-shadow: 1px 1px 0 #FFFFFF;" +
- "}" +
- "" +
- "/*" +
- " footer" +
- "*/" +
- "#footer {" +
- " color: #4d4d4d;" +
- " padding: 65px 20px 20px;" +
- " margin: 20px 0 0 220px;" +
- " text-align: center;" +
- " display: block;" +
- " font-size: 13px;" +
- " background-image: url(\"i/arrow-x.png\");" +
- " background-repeat: no-repeat;" +
- " background-position: center top;" +
- " background-color: #fff;" +
- "}" +
- "" +
- "#footer .line {" +
- " display: block;" +
- "}" +
- "" +
- "#footer .line a {" +
- " color: #4d4d4d;" +
- " text-decoration: underline;" +
- "}" +
- "" +
- "/*" +
- " Pygments manni style" +
- "*/" +
- "" +
- "code {background-color: #fafafa; color: #333;}" +
- "" +
- "code .comment {color: green; font-style: italic}" +
- "code .comment.preproc {color: #099; font-style: normal}" +
- "code .comment.special {font-weight: bold}" +
- "" +
- "code .keyword {color: #069; font-weight: bold}" +
- "code .keyword.pseudo {font-weight: normal}" +
- "code .keyword.type {color: #078}" +
- "" +
- "code .operator {color: #555}" +
- "code .operator.word {color: #000; font-weight: bold}" +
- "" +
- "code .name.builtin {color: #366}" +
- "code .name.function {color: #c0f}" +
- "code .name.class {color: #0a8; font-weight: bold}" +
- "code .name.namespace {color: #0cf; font-weight: bold}" +
- "code .name.exception {color: #c00; font-weight: bold}" +
- "code .name.variable {color: #033}" +
- "code .name.constant {color: #360}" +
- "code .name.label {color: #99f}" +
- "code .name.entity {color: #999; font-weight: bold}" +
- "code .name.attribute {color: #309}" +
- "code .name.tag {color: #309; font-weight: bold}" +
- "code .name.decorator {color: #99f}" +
- "" +
- "code .string {color: #c30}" +
- "code .string.doc {font-style: italic}" +
- "code .string.interpol {color: #a00}" +
- "code .string.escape {color: #c30; font-weight: bold}" +
- "code .string.regex {color: #3aa}" +
- "code .string.symbol {color: #fc3}" +
- "code .string.other {color: #c30}" +
- "" +
- "code .number {color: #f60}" +
- "" +
- "" +
- "/*" +
- " webkit scroll bars" +
- "*/" +
- "" +
- "pre::-webkit-scrollbar {" +
- " width: 6px;" +
- " height: 6px;" +
- "}" +
- "" +
- "pre::-webkit-scrollbar-button:start:decrement," +
- "pre::-webkit-scrollbar-button:end:increment {" +
- " display: block;" +
- " height: 0;" +
- " width: 0;" +
- "}" +
- "" +
- "pre::-webkit-scrollbar-button:vertical:increment," +
- "pre::-webkit-scrollbar-button:horizontal:increment {" +
- " background-color: transparent;" +
- " display: block;" +
- " height: 0;" +
- " width: 0;" +
- "}" +
- "" +
- "pre::-webkit-scrollbar-track-piece {" +
- " -webkit-border-radius: 3px;" +
- "}" +
- "" +
- "pre::-webkit-scrollbar-thumb:vertical {" +
- " background-color: #aaa;" +
- " -webkit-border-radius: 3px;" +
- "" +
- "}" +
- "" +
- "pre::-webkit-scrollbar-thumb:horizontal {" +
- " background-color: #aaa;" +
- " -webkit-border-radius: 3px;" +
- "}" +
- "" +
- "/*" +
- " hbox" +
- "*/" +
- "" +
- ".hbox {" +
- " display: -webkit-box;" +
- " -webkit-box-orient: horizontal;" +
- " -webkit-box-align: stretch;" +
- "" +
- " display: -moz-box;" +
- " -moz-box-orient: horizontal;" +
- " -moz-box-align: stretch;" +
- "" +
- " display: box;" +
- " box-orient: horizontal;" +
- " box-align: stretch;" +
- "" +
- " width: 100%;" +
- "}" +
- "" +
- ".hbox > * {" +
- " -webkit-box-flex: 0;" +
- " -moz-box-flex: 0;" +
- " box-flex: 0;" +
- " display: block;" +
- "}" +
- "" +
- ".vbox {" +
- " display: -webkit-box;" +
- " -webkit-box-orient: vertical;" +
- " -webkit-box-align: stretch;" +
- "" +
- " display: -moz-box;" +
- " -moz-box-orient: vertical;" +
- " -moz-box-align: stretch;" +
- "" +
- " display: box;" +
- " box-orient: vertical;" +
- " box-align: stretch;" +
- "}" +
- "" +
- ".vbox > * {" +
- " -webkit-box-flex: 0;" +
- " -moz-box-flex: 0;" +
- " box-flex: 0;" +
- " display: block;" +
- "}" +
- "" +
- ".spacer {" +
- " -webkit-box-flex: 1;" +
- " -moz-box-flex: 1;" +
- " box-flex: 1;" +
- "}" +
- "" +
- ".reverse {" +
- " -webkit-box-direction: reverse;" +
- " -moz-box-direction: reverse;" +
- " box-direction: reverse;" +
- "}" +
- "" +
- ".boxFlex0 {" +
- " -webkit-box-flex: 0;" +
- " -moz-box-flex: 0;" +
- " box-flex: 0;" +
- "}" +
- "" +
- ".boxFlex1, .boxFlex {" +
- " -webkit-box-flex: 1;" +
- " -moz-box-flex: 1;" +
- " box-flex: 1;" +
- "}" +
- "" +
- ".boxFlex2 {" +
- " -webkit-box-flex: 2;" +
- " -moz-box-flex: 2;" +
- " box-flex: 2;" +
- "}" +
- "" +
- ".boxGroup1 {" +
- " -webkit-box-flex-group: 1;" +
- " -moz-box-flex-group: 1;" +
- " box-flex-group: 1;" +
- "}" +
- "" +
- ".boxGroup2 {" +
- " -webkit-box-flex-group: 2;" +
- " -moz-box-flex-group: 2;" +
- " box-flex-group: 2;" +
- "}" +
- "" +
- ".start {" +
- " -webkit-box-pack: start;" +
- " -moz-box-pack: start;" +
- " box-pack: start;" +
- "}" +
- "" +
- ".end {" +
- " -webkit-box-pack: end;" +
- " -moz-box-pack: end;" +
- " box-pack: end;" +
- "}" +
- "" +
- ".center {" +
- " -webkit-box-pack: center;" +
- " -moz-box-pack: center;" +
- " box-pack: center;" +
- "}" +
- "" +
- "/*" +
- " clearfix" +
- "*/" +
- "" +
- ".clearfix:after {" +
- " content: \".\";" +
- " display: block;" +
- " clear: both;" +
- " visibility: hidden;" +
- " line-height: 0;" +
- " height: 0;" +
- "}" +
- "" +
- "html[xmlns] .clearfix {" +
- " display: block;" +
- "}" +
- "" +
- "* html .clearfix {" +
- " height: 1%;" +
- "}");
-
-define("text/lib/ace/css/editor.css", [], ".ace_editor {" +
- " position: absolute;" +
- " overflow: hidden;" +
- " font-family: Monaco, \"Menlo\", \"Courier New\", monospace;" +
- " font-size: 12px;" +
- "}" +
- "" +
- ".ace_scroller {" +
- " position: absolute;" +
- " overflow-x: scroll;" +
- " overflow-y: hidden;" +
- "}" +
- "" +
- ".ace_content {" +
- " position: absolute;" +
- " box-sizing: border-box;" +
- " -moz-box-sizing: border-box;" +
- " -webkit-box-sizing: border-box;" +
- "}" +
- "" +
- ".ace_composition {" +
- " position: absolute;" +
- " background: #555;" +
- " color: #DDD;" +
- " z-index: 4;" +
- "}" +
- "" +
- ".ace_gutter {" +
- " position: absolute;" +
- " overflow-x: hidden;" +
- " overflow-y: hidden;" +
- " height: 100%;" +
- "}" +
- "" +
- ".ace_gutter-cell.ace_error {" +
- " background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%F5or%F5%87%88%F5nr%F4ns%EBmq%F5z%7F%DDJT%DEKS%DFOW%F1Yc%F2ah%CE(7%CE)8%D18E%DD%40M%F2KZ%EBU%60%F4%60m%DCir%C8%16(%C8%19*%CE%255%F1%3FR%F1%3FS%E6%AB%B5%CA%5DI%CEn%5E%F7%A2%9A%C9G%3E%E0a%5B%F7%89%85%F5yy%F6%82%80%ED%82%80%FF%BF%BF%E3%C4%C4%FF%FF%FF%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%25%00%2C%00%00%00%00%10%00%10%00%00%06p%C0%92pH%2C%1A%8F%C8%D2H%93%E1d4%23%E4%88%D3%09mB%1DN%B48%F5%90%40%60%92G%5B%94%20%3E%22%D2%87%24%FA%20%24%C5%06A%00%20%B1%07%02B%A38%89X.v%17%82%11%13q%10%0Fi%24%0F%8B%10%7BD%12%0Ei%09%92%09%0EpD%18%15%24%0A%9Ci%05%0C%18F%18%0B%07%04%01%04%06%A0H%18%12%0D%14%0D%12%A1I%B3%B4%B5IA%00%3B\");" +
- " background-repeat: no-repeat;" +
- " background-position: 4px center;" +
- "}" +
- "" +
- ".ace_gutter-cell.ace_warning {" +
- " background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%FF%DBr%FF%DE%81%FF%E2%8D%FF%E2%8F%FF%E4%96%FF%E3%97%FF%E5%9D%FF%E6%9E%FF%EE%C1%FF%C8Z%FF%CDk%FF%D0s%FF%D4%81%FF%D5%82%FF%D5%83%FF%DC%97%FF%DE%9D%FF%E7%B8%FF%CCl%7BQ%13%80U%15%82W%16%81U%16%89%5B%18%87%5B%18%8C%5E%1A%94d%1D%C5%83-%C9%87%2F%C6%84.%C6%85.%CD%8B2%C9%871%CB%8A3%CD%8B5%DC%98%3F%DF%9BB%E0%9CC%E1%A5U%CB%871%CF%8B5%D1%8D6%DB%97%40%DF%9AB%DD%99B%E3%B0p%E7%CC%AE%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%2F%00%2C%00%00%00%00%10%00%10%00%00%06a%C0%97pH%2C%1A%8FH%A1%ABTr%25%87%2B%04%82%F4%7C%B9X%91%08%CB%99%1C!%26%13%84*iJ9(%15G%CA%84%14%01%1A%97%0C%03%80%3A%9A%3E%81%84%3E%11%08%B1%8B%20%02%12%0F%18%1A%0F%0A%03'F%1C%04%0B%10%16%18%10%0B%05%1CF%1D-%06%07%9A%9A-%1EG%1B%A0%A1%A0U%A4%A5%A6BA%00%3B\");" +
- " background-repeat: no-repeat;" +
- " background-position: 4px center;" +
- "}" +
- "" +
- ".ace_editor .ace_sb {" +
- " position: absolute;" +
- " overflow-x: hidden;" +
- " overflow-y: scroll;" +
- " right: 0;" +
- "}" +
- "" +
- ".ace_editor .ace_sb div {" +
- " position: absolute;" +
- " width: 1px;" +
- " left: 0;" +
- "}" +
- "" +
- ".ace_editor .ace_print_margin_layer {" +
- " z-index: 0;" +
- " position: absolute;" +
- " overflow: hidden;" +
- " margin: 0;" +
- " left: 0;" +
- " height: 100%;" +
- " width: 100%;" +
- "}" +
- "" +
- ".ace_editor .ace_print_margin {" +
- " position: absolute;" +
- " height: 100%;" +
- "}" +
- "" +
- ".ace_editor textarea {" +
- " position: fixed;" +
- " z-index: -1;" +
- " width: 10px;" +
- " height: 30px;" +
- " opacity: 0;" +
- " background: transparent;" +
- " appearance: none;" +
- " -moz-appearance: none;" +
- " border: none;" +
- " resize: none;" +
- " outline: none;" +
- " overflow: hidden;" +
- "}" +
- "" +
- ".ace_layer {" +
- " z-index: 1;" +
- " position: absolute;" +
- " overflow: hidden;" +
- " white-space: nowrap;" +
- " height: 100%;" +
- " width: 100%;" +
- "}" +
- "" +
- ".ace_text-layer {" +
- " color: black;" +
- "}" +
- "" +
- ".ace_cjk {" +
- " display: inline-block;" +
- " text-align: center;" +
- "}" +
- "" +
- ".ace_cursor-layer {" +
- " z-index: 4;" +
- " cursor: text;" +
- " /* setting pointer-events: none; here will break mouse wheel scrolling in Safari */" +
- "}" +
- "" +
- ".ace_cursor {" +
- " z-index: 4;" +
- " position: absolute;" +
- "}" +
- "" +
- ".ace_cursor.ace_hidden {" +
- " opacity: 0.2;" +
- "}" +
- "" +
- ".ace_line {" +
- " white-space: nowrap;" +
- "}" +
- "" +
- ".ace_marker-layer {" +
- " cursor: text;" +
- " pointer-events: none;" +
- "}" +
- "" +
- ".ace_marker-layer .ace_step {" +
- " position: absolute;" +
- " z-index: 3;" +
- "}" +
- "" +
- ".ace_marker-layer .ace_selection {" +
- " position: absolute;" +
- " z-index: 4;" +
- "}" +
- "" +
- ".ace_marker-layer .ace_bracket {" +
- " position: absolute;" +
- " z-index: 5;" +
- "}" +
- "" +
- ".ace_marker-layer .ace_active_line {" +
- " position: absolute;" +
- " z-index: 2;" +
- "}" +
- "" +
- ".ace_marker-layer .ace_selected_word {" +
- " position: absolute;" +
- " z-index: 6;" +
- " box-sizing: border-box;" +
- " -moz-box-sizing: border-box;" +
- " -webkit-box-sizing: border-box;" +
- "}" +
- "" +
- ".ace_line .ace_fold {" +
- " cursor: pointer;" +
- "}" +
- "" +
- ".ace_dragging .ace_marker-layer, .ace_dragging .ace_text-layer {" +
- " cursor: move;" +
- "}" +
- "");
-
-define("text/node_modules/uglify-js/docstyle.css", [], "html { font-family: \"Lucida Grande\",\"Trebuchet MS\",sans-serif; font-size: 12pt; }" +
- "body { max-width: 60em; }" +
- ".title { text-align: center; }" +
- ".todo { color: red; }" +
- ".done { color: green; }" +
- ".tag { background-color:lightblue; font-weight:normal }" +
- ".target { }" +
- ".timestamp { color: grey }" +
- ".timestamp-kwd { color: CadetBlue }" +
- "p.verse { margin-left: 3% }" +
- "pre {" +
- " border: 1pt solid #AEBDCC;" +
- " background-color: #F3F5F7;" +
- " padding: 5pt;" +
- " font-family: monospace;" +
- " font-size: 90%;" +
- " overflow:auto;" +
- "}" +
- "pre.src {" +
- " background-color: #eee; color: #112; border: 1px solid #000;" +
- "}" +
- "table { border-collapse: collapse; }" +
- "td, th { vertical-align: top; }" +
- "dt { font-weight: bold; }" +
- "div.figure { padding: 0.5em; }" +
- "div.figure p { text-align: center; }" +
- ".linenr { font-size:smaller }" +
- ".code-highlighted {background-color:#ffff00;}" +
- ".org-info-js_info-navigation { border-style:none; }" +
- "#org-info-js_console-label { font-size:10px; font-weight:bold;" +
- " white-space:nowrap; }" +
- ".org-info-js_search-highlight {background-color:#ffff00; color:#000000;" +
- " font-weight:bold; }" +
- "" +
- "sup {" +
- " vertical-align: baseline;" +
- " position: relative;" +
- " top: -0.5em;" +
- " font-size: 80%;" +
- "}" +
- "" +
- "sup a:link, sup a:visited {" +
- " text-decoration: none;" +
- " color: #c00;" +
- "}" +
- "" +
- "sup a:before { content: \"[\"; color: #999; }" +
- "sup a:after { content: \"]\"; color: #999; }" +
- "" +
- "h1.title { border-bottom: 4px solid #000; padding-bottom: 5px; margin-bottom: 2em; }" +
- "" +
- "#postamble {" +
- " color: #777;" +
- " font-size: 90%;" +
- " padding-top: 1em; padding-bottom: 1em; border-top: 1px solid #999;" +
- " margin-top: 2em;" +
- " padding-left: 2em;" +
- " padding-right: 2em;" +
- " text-align: right;" +
- "}" +
- "" +
- "#postamble p { margin: 0; }" +
- "" +
- "#footnotes { border-top: 1px solid #000; }" +
- "" +
- "h1 { font-size: 200% }" +
- "h2 { font-size: 175% }" +
- "h3 { font-size: 150% }" +
- "h4 { font-size: 125% }" +
- "" +
- "h1, h2, h3, h4 { font-family: \"Bookman\",Georgia,\"Times New Roman\",serif; font-weight: normal; }" +
- "" +
- "@media print {" +
- " html { font-size: 11pt; }" +
- "}" +
- "");
-
-define("text/support/cockpit/lib/cockpit/ui/cli_view.css", [], "" +
- "#cockpitInput { padding-left: 16px; }" +
- "" +
- ".cptOutput { overflow: auto; position: absolute; z-index: 999; display: none; }" +
- "" +
- ".cptCompletion { padding: 0; position: absolute; z-index: -1000; }" +
- ".cptCompletion.VALID { background: #FFF; }" +
- ".cptCompletion.INCOMPLETE { background: #DDD; }" +
- ".cptCompletion.INVALID { background: #DDD; }" +
- ".cptCompletion span { color: #FFF; }" +
- ".cptCompletion span.INCOMPLETE { color: #DDD; border-bottom: 2px dotted #F80; }" +
- ".cptCompletion span.INVALID { color: #DDD; border-bottom: 2px dotted #F00; }" +
- "span.cptPrompt { color: #66F; font-weight: bold; }" +
- "" +
- "" +
- ".cptHints {" +
- " color: #000;" +
- " position: absolute;" +
- " border: 1px solid rgba(230, 230, 230, 0.8);" +
- " background: rgba(250, 250, 250, 0.8);" +
- " -moz-border-radius-topleft: 10px;" +
- " -moz-border-radius-topright: 10px;" +
- " border-top-left-radius: 10px; border-top-right-radius: 10px;" +
- " z-index: 1000;" +
- " padding: 8px;" +
- " display: none;" +
- "}" +
- "" +
- ".cptFocusPopup { display: block; }" +
- ".cptFocusPopup.cptNoPopup { display: none; }" +
- "" +
- ".cptHints ul { margin: 0; padding: 0 15px; }" +
- "" +
- ".cptGt { font-weight: bold; font-size: 120%; }" +
- "");
-
-define("text/support/cockpit/lib/cockpit/ui/request_view.css", [], "" +
- ".cptRowIn {" +
- " display: box; display: -moz-box; display: -webkit-box;" +
- " box-orient: horizontal; -moz-box-orient: horizontal; -webkit-box-orient: horizontal;" +
- " box-align: center; -moz-box-align: center; -webkit-box-align: center;" +
- " color: #333;" +
- " background-color: #EEE;" +
- " width: 100%;" +
- " font-family: consolas, courier, monospace;" +
- "}" +
- ".cptRowIn > * { padding-left: 2px; padding-right: 2px; }" +
- ".cptRowIn > img { cursor: pointer; }" +
- ".cptHover { display: none; }" +
- ".cptRowIn:hover > .cptHover { display: block; }" +
- ".cptRowIn:hover > .cptHover.cptHidden { display: none; }" +
- ".cptOutTyped {" +
- " box-flex: 1; -moz-box-flex: 1; -webkit-box-flex: 1;" +
- " font-weight: bold; color: #000; font-size: 120%;" +
- "}" +
- ".cptRowOutput { padding-left: 10px; line-height: 1.2em; }" +
- ".cptRowOutput strong," +
- ".cptRowOutput b," +
- ".cptRowOutput th," +
- ".cptRowOutput h1," +
- ".cptRowOutput h2," +
- ".cptRowOutput h3 { color: #000; }" +
- ".cptRowOutput a { font-weight: bold; color: #666; text-decoration: none; }" +
- ".cptRowOutput a: hover { text-decoration: underline; cursor: pointer; }" +
- ".cptRowOutput input[type=password]," +
- ".cptRowOutput input[type=text]," +
- ".cptRowOutput textarea {" +
- " color: #000; font-size: 120%;" +
- " background: transparent; padding: 3px;" +
- " border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;" +
- "}" +
- ".cptRowOutput table," +
- ".cptRowOutput td," +
- ".cptRowOutput th { border: 0; padding: 0 2px; }" +
- ".cptRowOutput .right { text-align: right; }" +
- "");
-
-define("text/tool/Theme.tmpl.css", [], ".%cssClass% .ace_editor {" +
- " border: 2px solid rgb(159, 159, 159);" +
- "}" +
- "" +
- ".%cssClass% .ace_editor.ace_focus {" +
- " border: 2px solid #327fbd;" +
- "}" +
- "" +
- ".%cssClass% .ace_gutter {" +
- " width: 50px;" +
- " background: #e8e8e8;" +
- " color: #333;" +
- " overflow : hidden;" +
- "}" +
- "" +
- ".%cssClass% .ace_gutter-layer {" +
- " width: 100%;" +
- " text-align: right;" +
- "}" +
- "" +
- ".%cssClass% .ace_gutter-layer .ace_gutter-cell {" +
- " padding-right: 6px;" +
- "}" +
- "" +
- ".%cssClass% .ace_print_margin {" +
- " width: 1px;" +
- " background: %printMargin%;" +
- "}" +
- "" +
- ".%cssClass% .ace_scroller {" +
- " background-color: %background%;" +
- "}" +
- "" +
- ".%cssClass% .ace_text-layer {" +
- " cursor: text;" +
- " color: %foreground%;" +
- "}" +
- "" +
- ".%cssClass% .ace_cursor {" +
- " border-left: 2px solid %cursor%;" +
- "}" +
- "" +
- ".%cssClass% .ace_cursor.ace_overwrite {" +
- " border-left: 0px;" +
- " border-bottom: 1px solid %overwrite%;" +
- "}" +
- " " +
- ".%cssClass% .ace_marker-layer .ace_selection {" +
- " background: %selection%;" +
- "}" +
- "" +
- ".%cssClass% .ace_marker-layer .ace_step {" +
- " background: %step%;" +
- "}" +
- "" +
- ".%cssClass% .ace_marker-layer .ace_bracket {" +
- " margin: -1px 0 0 -1px;" +
- " border: 1px solid %bracket%;" +
- "}" +
- "" +
- ".%cssClass% .ace_marker-layer .ace_active_line {" +
- " background: %active_line%;" +
- "}" +
- "" +
- " " +
- ".%cssClass% .ace_invisible {" +
- " %invisible%" +
- "}" +
- "" +
- ".%cssClass% .ace_keyword {" +
- " %keyword%" +
- "}" +
- "" +
- ".%cssClass% .ace_keyword.ace_operator {" +
- " %keyword.operator%" +
- "}" +
- "" +
- ".%cssClass% .ace_constant {" +
- " %constant%" +
- "}" +
- "" +
- ".%cssClass% .ace_constant.ace_language {" +
- " %constant.language%" +
- "}" +
- "" +
- ".%cssClass% .ace_constant.ace_library {" +
- " %constant.library%" +
- "}" +
- "" +
- ".%cssClass% .ace_constant.ace_numeric {" +
- " %constant.numeric%" +
- "}" +
- "" +
- ".%cssClass% .ace_invalid {" +
- " %invalid%" +
- "}" +
- "" +
- ".%cssClass% .ace_invalid.ace_illegal {" +
- " %invalid.illegal%" +
- "}" +
- "" +
- ".%cssClass% .ace_invalid.ace_deprecated {" +
- " %invalid.deprecated%" +
- "}" +
- "" +
- ".%cssClass% .ace_support {" +
- " %support%" +
- "}" +
- "" +
- ".%cssClass% .ace_support.ace_function {" +
- " %support.function%" +
- "}" +
- "" +
- ".%cssClass% .ace_function.ace_buildin {" +
- " %function.buildin%" +
- "}" +
- "" +
- ".%cssClass% .ace_string {" +
- " %string%" +
- "}" +
- "" +
- ".%cssClass% .ace_string.ace_regexp {" +
- " %string.regexp%" +
- "}" +
- "" +
- ".%cssClass% .ace_comment {" +
- " %comment%" +
- "}" +
- "" +
- ".%cssClass% .ace_comment.ace_doc {" +
- " %comment.doc%" +
- "}" +
- "" +
- ".%cssClass% .ace_comment.ace_doc.ace_tag {" +
- " %comment.doc.tag%" +
- "}" +
- "" +
- ".%cssClass% .ace_variable {" +
- " %variable%" +
- "}" +
- "" +
- ".%cssClass% .ace_variable.ace_language {" +
- " %variable.language%" +
- "}" +
- "" +
- ".%cssClass% .ace_xml_pe {" +
- " %xml_pe%" +
- "}" +
- "" +
- ".%cssClass% .ace_collab.ace_user1 {" +
- " %collab.user1% " +
- "}");
-
-define("text/styles.css", [], "html {" +
- " height: 100%;" +
- " width: 100%;" +
- " overflow: hidden;" +
- "}" +
- "" +
- "body {" +
- " overflow: hidden;" +
- " margin: 0;" +
- " padding: 0;" +
- " height: 100%;" +
- " width: 100%;" +
- " font-family: Arial, Helvetica, sans-serif, Tahoma, Verdana, sans-serif;" +
- " font-size: 12px;" +
- " background: rgb(14, 98, 165);" +
- " color: white;" +
- "}" +
- "" +
- "#logo {" +
- " padding: 15px;" +
- " margin-left: 65px;" +
- "}" +
- "" +
- "#editor {" +
- " position: absolute;" +
- " top: 0px;" +
- " left: 280px;" +
- " bottom: 0px;" +
- " right: 0px;" +
- " background: white;" +
- "}" +
- "" +
- "#controls {" +
- " padding: 5px;" +
- "}" +
- "" +
- "#controls td {" +
- " text-align: right;" +
- "}" +
- "" +
- "#controls td + td {" +
- " text-align: left;" +
- "}" +
- "" +
- "#cockpitInput {" +
- " position: absolute;" +
- " left: 280px;" +
- " right: 0px;" +
- " bottom: 0;" +
- "" +
- " border: none; outline: none;" +
- " font-family: consolas, courier, monospace;" +
- " font-size: 120%;" +
- "}" +
- "" +
- "#cockpitOutput {" +
- " padding: 10px;" +
- " margin: 0 15px;" +
- " border: 1px solid #AAA;" +
- " -moz-border-radius-topleft: 10px;" +
- " -moz-border-radius-topright: 10px;" +
- " border-top-left-radius: 4px; border-top-right-radius: 4px;" +
- " background: #DDD; color: #000;" +
- "}");
-
-/* ***** 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 Mozilla Skywriter.
- *
- * The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Kevin Dangoor (kdangoor@mozilla.com)
- *
- * 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 ***** */
-
-require(["ace/ace"], function(ace) {
- window.ace = ace;
-});
\ No newline at end of file
+;
+ (function() {
+ window.require(["ace/ace"], function(a) {
+ 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/ux/aceeditor/ace-0.2.0/src/ace.js b/ux/aceeditor/ace-0.2.0/src/ace.js
index d3b0ccc..e8277ee 100755
--- a/ux/aceeditor/ace-0.2.0/src/ace.js
+++ b/ux/aceeditor/ace-0.2.0/src/ace.js
@@ -1 +1,10 @@
-(function(){var a=function(){return this}();if(a.require&&a.define)require.packaged=!0;else{var b=function(a,c,d){typeof a!="string"?b.original?b.original.apply(window,arguments):(console.error("dropping module because define wasn't a string."),console.trace()):(arguments.length==2&&(d=c),define.modules||(define.modules={}),define.modules[a]=d)};a.define&&(b.original=a.define),a.define=b;var c=function(a,b){if(Object.prototype.toString.call(a)==="[object Array]"){var e=[];for(var f=0,g=a.length;f=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=2)var d=arguments[1];else do{if(c in this){d=this[c--];break}if(--c<0)throw new TypeError}while(!0);for(;c>=0;c--)c in this&&(d=a.call(null,d,this[c],c,this));return d}),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){var b=this.length;if(!b)return-1;var c=arguments[1]||0;if(c>=b)return-1;c<0&&(c+=b);for(;c=0;c--){if(!h(this,c))continue;if(a===this[c])return c}return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(a){return a.__proto__||a.constructor.prototype});if(!Object.getOwnPropertyDescriptor){var n="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(a,b){if(typeof a!="object"&&typeof a!="function"||a===null)throw new TypeError(n+a);if(!h(a,b))return undefined;var c,d,e;c={enumerable:!0,configurable:!0};if(m){var f=a.__proto__;a.__proto__=g;var d=k(a,b),e=l(a,b);a.__proto__=f;if(d||e){d&&(descriptor.get=d),e&&(descriptor.set=e);return descriptor}}descriptor.value=a[b];return descriptor}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(a){return Object.keys(a)}),Object.create||(Object.create=function(a,b){var c;if(a===null)c={"__proto__":null};else{if(typeof a!="object")throw new TypeError("typeof prototype["+typeof a+"] != 'object'");var d=function(){};d.prototype=a,c=new d,c.__proto__=a}typeof b!="undefined"&&Object.defineProperties(c,b);return c});if(!Object.defineProperty){var o="Property description must be an object: ",p="Object.defineProperty called on non-object: ",q="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(a,b,c){if(typeof a!="object"&&typeof a!="function")throw new TypeError(p+a);if(typeof a!="object"||a===null)throw new TypeError(o+c);if(h(c,"value"))if(m&&(k(a,b)||l(a,b))){var d=a.__proto__;a.__proto__=g,delete a[b],a[b]=c.value,a.prototype}else a[b]=c.value;else{if(!m)throw new TypeError(q);h(c,"get")&&i(a,b,c.get),h(c,"set")&&j(a,b,c.set)}return a}}Object.defineProperties||(Object.defineProperties=function(a,b){for(var c in b)h(b,c)&&Object.defineProperty(a,c,b[c]);return a}),Object.seal||(Object.seal=function(a){return a}),Object.freeze||(Object.freeze=function(a){return a});try{Object.freeze(function(){})}catch(r){Object.freeze=function(a){return function b(b){return typeof b=="function"?b:a(b)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(a){return a}),Object.isSealed||(Object.isSealed=function(a){return!1}),Object.isFrozen||(Object.isFrozen=function(a){return!1}),Object.isExtensible||(Object.isExtensible=function(a){return!0});if(!Object.keys){var s=!0,t=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],u=t.length;for(var v in{toString:null})s=!1;Object.keys=function W(a){if(typeof a!="object"&&typeof a!="function"||a===null)throw new TypeError("Object.keys called on a non-object");var W=[];for(var b in a)h(a,b)&&W.push(b);if(s)for(var c=0,d=u;c=7?new a(c,d,e,f,g,h,i):j>=6?new a(c,d,e,f,g,h):j>=5?new a(c,d,e,f,g):j>=4?new a(c,d,e,f):j>=3?new a(c,d,e):j>=2?new a(c,d):j>=1?new a(c):new a;k.constructor=b;return k}return a.apply(this,arguments)},c=new RegExp("^(?:((?:[+-]\\d\\d)?\\d\\d\\d\\d)(?:-(\\d\\d)(?:-(\\d\\d))?)?)?(?:T(\\d\\d):(\\d\\d)(?::(\\d\\d)(?:\\.(\\d\\d\\d))?)?)?(?:Z|([+-])(\\d\\d):(\\d\\d))?$");for(var d in a)b[d]=a[d];b.now=a.now,b.UTC=a.UTC,b.prototype=a.prototype,b.prototype.constructor=b,b.parse=function e(b){var d=c.exec(b);if(d){d.shift();var e=d[0]===undefined;for(var f=0;f<10;f++){if(f===7)continue;d[f]=+(d[f]||(f<3?1:0)),f===1&&d[f]--}if(e)return((d[3]*60+d[4])*60+d[5])*1e3+d[6];var g=(d[8]*60+d[9])*60*1e3;d[6]==="-"&&(g=-g);return a.UTC.apply(this,d.slice(0,7))+g}return a.parse.apply(this,arguments)};return b}(Date));if(!String.prototype.trim){var w=/^\s\s*/,x=/\s\s*$/;String.prototype.trim=function(){return String(this).replace(w,"").replace(x,"")}}}),define("ace/ace",["require","exports","module","pilot/index","pilot/fixoldbrowsers","pilot/plugin_manager","pilot/dom","pilot/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/theme/textmate","pilot/environment"],function(a,b,c){a("pilot/index"),a("pilot/fixoldbrowsers");var d=a("pilot/plugin_manager").catalog;d.registerPlugins(["pilot/index"]);var e=a("pilot/dom"),f=a("pilot/event"),g=a("ace/editor").Editor,h=a("ace/edit_session").EditSession,i=a("ace/undomanager").UndoManager,j=a("ace/virtual_renderer").VirtualRenderer;b.edit=function(b){typeof b=="string"&&(b=document.getElementById(b));var c=new h(e.getInnerText(b));c.setUndoManager(new i),b.innerHTML="";var k=new g(new j(b,a("ace/theme/textmate")));k.setSession(c);var l=a("pilot/environment").create();d.startupPlugins({env:l}).then(function(){l.document=c,l.editor=k,k.resize(),f.addListener(window,"resize",function(){k.resize()}),b.env=l}),k.env=l;return k}}),define("pilot/index",["require","exports","module","pilot/fixoldbrowsers","pilot/types/basic","pilot/types/command","pilot/types/settings","pilot/commands/settings","pilot/commands/basic","pilot/settings/canon","pilot/canon"],function(a,b,c){b.startup=function(b,c){a("pilot/fixoldbrowsers"),a("pilot/types/basic").startup(b,c),a("pilot/types/command").startup(b,c),a("pilot/types/settings").startup(b,c),a("pilot/commands/settings").startup(b,c),a("pilot/commands/basic").startup(b,c),a("pilot/settings/canon").startup(b,c),a("pilot/canon").startup(b,c)},b.shutdown=function(b,c){a("pilot/types/basic").shutdown(b,c),a("pilot/types/command").shutdown(b,c),a("pilot/types/settings").shutdown(b,c),a("pilot/commands/settings").shutdown(b,c),a("pilot/commands/basic").shutdown(b,c),a("pilot/settings/canon").shutdown(b,c),a("pilot/canon").shutdown(b,c)}}),define("pilot/types/basic",["require","exports","module","pilot/types"],function(a,b,c){function m(a){if(a instanceof e)this.subtype=a;else{if(typeof a!="string")throw new Error("Can' handle array subtype");this.subtype=d.getType(a);if(this.subtype==null)throw new Error("Unknown array subtype: "+a)}}function l(a){if(typeof a.defer!="function")throw new Error("Instances of DeferredType need typeSpec.defer to be a function that returns a type");Object.keys(a).forEach(function(b){this[b]=a[b]},this)}function j(a){if(!Array.isArray(a.data)&&typeof a.data!="function")throw new Error("instances of SelectionType need typeSpec.data to be an array or function that returns an array:"+JSON.stringify(a));Object.keys(a).forEach(function(b){this[b]=a[b]},this)}var d=a("pilot/types"),e=d.Type,f=d.Conversion,g=d.Status,h=new e;h.stringify=function(a){return a},h.parse=function(a){if(typeof a!="string")throw new Error("non-string passed to text.parse()");return new f(a)},h.name="text";var i=new e;i.stringify=function(a){return a?""+a:null},i.parse=function(a){if(typeof a!="string")throw new Error("non-string passed to number.parse()");if(a.replace(/\s/g,"").length===0)return new f(null,g.INCOMPLETE,"");var b=new f(parseInt(a,10));isNaN(b.value)&&(b.status=g.INVALID,b.message="Can't convert \""+a+'" to a number.');return b},i.decrement=function(a){return a-1},i.increment=function(a){return a+1},i.name="number",j.prototype=new e,j.prototype.stringify=function(a){return a},j.prototype.parse=function(a){if(typeof a!="string")throw new Error("non-string passed to parse()");if(!this.data)throw new Error("Missing data on selection type extension.");var b=typeof this.data=="function"?this.data():this.data,c=!1,d,e=[];b.forEach(function(b){a==b?(d=this.fromString(b),c=!0):b.indexOf(a)===0&&e.push(this.fromString(b))},this);if(c)return new f(d);this.noMatch&&this.noMatch();if(e.length>0){var h="Possibilities"+(a.length===0?"":" for '"+a+"'");return new f(null,g.INCOMPLETE,h,e)}var h="Can't use '"+a+"'.";return new f(null,g.INVALID,h,e)},j.prototype.fromString=function(a){return a},j.prototype.decrement=function(a){var b=typeof this.data=="function"?this.data():this.data,c;if(a==null)c=b.length-1;else{var d=this.stringify(a),c=b.indexOf(d);c=c===0?b.length-1:c-1}return this.fromString(b[c])},j.prototype.increment=function(a){var b=typeof this.data=="function"?this.data():this.data,c;if(a==null)c=0;else{var d=this.stringify(a),c=b.indexOf(d);c=c===b.length-1?0:c+1}return this.fromString(b[c])},j.prototype.name="selection",b.SelectionType=j;var k=new j({name:"bool",data:["true","false"],stringify:function(a){return""+a},fromString:function(a){return a==="true"?!0:!1}});l.prototype=new e,l.prototype.stringify=function(a){return this.defer().stringify(a)},l.prototype.parse=function(a){return this.defer().parse(a)},l.prototype.decrement=function(a){var b=this.defer();return b.decrement?b.decrement(a):undefined},l.prototype.increment=function(a){var b=this.defer();return b.increment?b.increment(a):undefined},l.prototype.name="deferred",b.DeferredType=l,m.prototype=new e,m.prototype.stringify=function(a){return a.join(" ")},m.prototype.parse=function(a){return this.defer().parse(a)},m.prototype.name="array";var n=!1;b.startup=function(){n||(n=!0,d.registerType(h),d.registerType(i),d.registerType(k),d.registerType(j),d.registerType(l),d.registerType(m))},b.shutdown=function(){n=!1,d.unregisterType(h),d.unregisterType(i),d.unregisterType(k),d.unregisterType(j),d.unregisterType(l),d.unregisterType(m)}}),define("pilot/types",["require","exports","module"],function(a,b,c){function h(a,b){if(a.substr(-2)==="[]"){var c=a.slice(0,-2);return new g.array(c)}var d=g[a];typeof d=="function"&&(d=new d(b));return d}function f(){}function e(a,b,c,e){this.value=a,this.status=b||d.VALID,this.message=c,this.predictions=e||[]}var d={VALID:{toString:function(){return"VALID"},valueOf:function(){return 0}},INCOMPLETE:{toString:function(){return"INCOMPLETE"},valueOf:function(){return 1}},INVALID:{toString:function(){return"INVALID"},valueOf:function(){return 2}},combine:function(a){var b=d.VALID;for(var c=0;cb.valueOf()&&(b=a[c]);return b}};b.Status=d,b.Conversion=e,f.prototype={stringify:function(a){throw new Error("not implemented")},parse:function(a){throw new Error("not implemented")},name:undefined,increment:function(a){return undefined},decrement:function(a){return undefined},getDefault:function(){return this.parse("")}},b.Type=f;var g={};b.registerType=function(a){if(typeof a=="object"){if(!(a instanceof f))throw new Error("Can't registerType using: "+a);if(!a.name)throw new Error("All registered types must have a name");g[a.name]=a}else{if(typeof a!="function")throw new Error("Unknown type: "+a);if(!a.prototype.name)throw new Error("All registered types must have a name");g[a.prototype.name]=a}},b.registerTypes=function(a){Object.keys(a).forEach(function(c){var d=a[c];d.name=c,b.registerType(d)})},b.deregisterType=function(a){delete g[a.name]},b.getType=function(a){if(typeof a=="string")return h(a);if(typeof a=="object"){if(!a.name)throw new Error("Missing 'name' member to typeSpec");return h(a.name,a)}throw new Error("Can't extract type from "+a)}}),define("pilot/types/command",["require","exports","module","pilot/canon","pilot/types/basic","pilot/types"],function(a,b,c){var d=a("pilot/canon"),e=a("pilot/types/basic").SelectionType,f=a("pilot/types"),g=new e({name:"command",data:function(){return d.getCommandNames()},stringify:function(a){return a.name},fromString:function(a){return d.getCommand(a)}});b.startup=function(){f.registerType(g)},b.shutdown=function(){f.unregisterType(g)}}),define("pilot/canon",["require","exports","module","pilot/console","pilot/stacktrace","pilot/oop","pilot/useragent","pilot/keys","pilot/event_emitter","pilot/typecheck","pilot/catalog","pilot/types","pilot/lang"],function(a,b,c){function J(a){a=a||{},this.command=a.command,this.args=a.args,this.typed=a.typed,this._begunOutput=!1,this.start=new Date,this.end=null,this.completed=!1,this.error=!1}function G(a,b,c,e,f){function h(){a.exec(b,g.args,g),!g.isAsync&&!g.isDone&&g.done()}typeof a=="string"&&(a=q[a]);if(!a)return!1;var g=new J({sender:c,command:a,args:e||{},typed:f});if(g.getStatus()==l.INVALID){d.error("Canon.exec: Invalid parameter(s) passed to "+a.name);return!1}if(g.getStatus()==l.INCOMPLETE){var i,j=b[c];if(!j||!j.getArgsProvider||!(i=j.getArgsProvider()))i=F;i(g,function(){g.getStatus()==l.VALID&&h()});return!0}h();return!0}function F(a,b){var c=a.args,d=a.command.params;for(var e=0;eI)H.shiftObject();b._dispatchEvent("output",{requests:H,request:this})},J.prototype.doneWithError=function(a){this.error=!0,this.done(a)},J.prototype.async=function(){this.isAsync=!0,this._begunOutput||this._beginOutput()},J.prototype.output=function(a){this._begunOutput||this._beginOutput(),typeof a!="string"&&!(a instanceof Node)&&(a=a.toString()),this.outputs.push(a),this.isDone=!0,this._dispatchEvent("output",{});return this},J.prototype.done=function(a){this.completed=!0,this.end=new Date,this.duration=this.end.getTime()-this.start.getTime(),a&&this.output(a),this.isDone||(this.isDone=!0,this._dispatchEvent("output",{}))},b.Request=J}),define("pilot/console",["require","exports","module"],function(a,b,c){var d=function(){},e=["assert","count","debug","dir","dirxml","error","group","groupEnd","info","log","profile","profileEnd","time","timeEnd","trace","warn"];typeof window=="undefined"?e.forEach(function(a){b[a]=function(){var b=Array.prototype.slice.call(arguments),c={op:"log",method:a,args:b};postMessage(JSON.stringify(c))}}):e.forEach(function(a){window.console&&window.console[a]?b[a]=Function.prototype.bind.call(window.console[a],window.console):b[a]=d})}),define("pilot/stacktrace",["require","exports","module","pilot/useragent","pilot/console"],function(a,b,c){function i(){}function g(a){for(var b=0;b\s*\(/gm,"{anonymous}()@").split("\n")},firefox:function(a){var b=a.stack;if(!b){e.log(a);return[]}b=b.replace(/(?:\n@:0)?\s+$/m,""),b=b.replace(/^\(/gm,"{anonymous}(");return b.split("\n")},opera:function(a){var b=a.message.split("\n"),c="{anonymous}",d=/Line\s+(\d+).*?script\s+(http\S+)(?:.*?in\s+function\s+(\S+))?/i,e,f,g;for(e=4,f=0,g=b.length;e=0,b.isIPad=e.indexOf("iPad")>=0,b.OS={LINUX:"LINUX",MAC:"MAC",WINDOWS:"WINDOWS"},b.getOS=function(){return b.isMac?b.OS.MAC:b.isLinux?b.OS.LINUX:b.OS.WINDOWS}}),define("pilot/oop",["require","exports","module"],function(a,b,c){b.inherits=function(){var a=function(){};return function(b,c){a.prototype=c.prototype,b.super_=c.prototype,b.prototype=new a,b.prototype.constructor=b}}(),b.mixin=function(a,b){for(var c in b)a[c]=b[c]},b.implement=function(a,c){b.mixin(a,c)}}),define("pilot/keys",["require","exports","module","pilot/oop"],function(a,b,c){var d=a("pilot/oop"),e=function(){var a={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",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:'"'}};for(i in a.FUNCTION_KEYS){var b=a.FUNCTION_KEYS[i].toUpperCase();a[b]=parseInt(i,10)}d.mixin(a,a.MODIFIER_KEYS),d.mixin(a,a.PRINTABLE_KEYS),d.mixin(a,a.FUNCTION_KEYS);return a}();d.mixin(b,e),b.keyCodeToString=function(a){return(e[a]||String.fromCharCode(a)).toLowerCase()}}),define("pilot/event_emitter",["require","exports","module"],function(a,b,c){var d={};d._emit=d._dispatchEvent=function(a,b){this._eventRegistry=this._eventRegistry||{};var c=this._eventRegistry[a];if(!!c&&!!c.length){var b=b||{};b.type=a;for(var d=0;d'+c.name+" = "+c.value+"
"})}else b.value===undefined?d=""+setting.name+" = "+setting.get():(b.setting.set(b.value),d="Setting: "+b.setting.name+" = "+b.setting.get());c.done(d)}},e={name:"unset",params:[{name:"setting",type:"setting",description:"The name of the setting to return to defaults"}],description:"unset a setting entirely",exec:function(a,b,c){var d=a.settings.get(b.setting);d?(d.reset(),c.done("Reset "+d.name+" to default: "+a.settings.get(b.setting))):c.doneWithError("No setting with the name "+b.setting+".")}},f=a("pilot/canon");b.startup=function(a,b){f.addCommand(d),f.addCommand(e)},b.shutdown=function(a,b){f.removeCommand(d),f.removeCommand(e)}}),define("pilot/commands/basic",["require","exports","module","pilot/typecheck","pilot/canon"],function(require,exports,module){var checks=require("pilot/typecheck"),canon=require("pilot/canon"),helpCommandSpec={name:"help",params:[{name:"search",type:"text",description:"Search string to narrow the output.",defaultValue:null}],description:"Get help on the available commands.",exec:function(a,b,c){var d=[],e=canon.getCommand(b.search);if(e&&e.exec)d.push(e.description?e.description:"No description for "+b.search);else{var f=!1;e?(d.push("Sub-Commands of "+e.name+"
"),d.push(""+e.description+"
")):b.search?(b.search=="hidden"&&(b.search="",f=!0),d.push("Commands starting with '"+b.search+"':
")):d.push("Available Commands:
");var g=canon.getCommandNames();g.sort(),d.push("");for(var h=0;h"),d.push('| '+e.name+" | "),d.push(""+e.description+" | "),d.push("")}d.push("
")}c.done(d.join(""))}},evalCommandSpec={name:"eval",params:[{name:"javascript",type:"text",description:"The JavaScript to evaluate"}],description:"evals given js code and show the result",hidden:!0,exec:function(env,args,request){var result,javascript=args.javascript;try{result=eval(javascript)}catch(e){result="Error: "+e.message+""}var msg="",type="",x;if(checks.isFunction(result))msg=(result+"").replace(/\n/g,"
").replace(/ /g," "),type="function";else if(checks.isObject(result)){Array.isArray(result)?type="array":type="object";var items=[],value;for(x in result)result.hasOwnProperty(x)&&(checks.isFunction(result[x])?value="[function]":checks.isObject(result[x])?value="[object]":value=result[x],items.push({name:x,value:value}));items.sort(function(a,b){return a.name.toLowerCase()"+items[x].name+": "+items[x].value+"
"}else msg=result,type=typeof result;request.done("Result for eval '"+javascript+"'"+" (type: "+type+"):
"+msg)}},canon=require("pilot/canon");exports.startup=function(a,b){canon.addCommand(helpCommandSpec),canon.addCommand(evalCommandSpec)},exports.shutdown=function(a,b){canon.removeCommand(helpCommandSpec),canon.removeCommand(evalCommandSpec)}}),define("pilot/settings/canon",["require","exports","module"],function(a,b,c){var d={name:"historyLength",description:"How many typed commands do we recall for reference?",type:"number",defaultValue:50};b.startup=function(a,b){a.env.settings.addSetting(d)},b.shutdown=function(a,b){a.env.settings.removeSetting(d)}}),define("pilot/plugin_manager",["require","exports","module","pilot/promise"],function(a,b,c){var d=a("pilot/promise").Promise;b.REASONS={APP_STARTUP:1,APP_SHUTDOWN:2,PLUGIN_ENABLE:3,PLUGIN_DISABLE:4,PLUGIN_INSTALL:5,PLUGIN_UNINSTALL:6,PLUGIN_UPGRADE:7,PLUGIN_DOWNGRADE:8},b.Plugin=function(a){this.name=a,this.status=this.INSTALLED},b.Plugin.prototype={NEW:0,INSTALLED:1,REGISTERED:2,STARTED:3,UNREGISTERED:4,SHUTDOWN:5,install:function(b,c){var e=new d;if(this.status>this.NEW){e.resolve(this);return e}a([this.name],function(a){a.install&&a.install(b,c),this.status=this.INSTALLED,e.resolve(this)}.bind(this));return e},register:function(b,c){var e=new d;if(this.status!=this.INSTALLED){e.resolve(this);return e}a([this.name],function(a){a.register&&a.register(b,c),this.status=this.REGISTERED,e.resolve(this)}.bind(this));return e},startup:function(c,e){e=e||b.REASONS.APP_STARTUP;var f=new d;if(this.status!=this.REGISTERED){f.resolve(this);return f}a([this.name],function(a){a.startup&&a.startup(c,e),this.status=this.STARTED,f.resolve(this)}.bind(this));return f},shutdown:function(b,c){this.status==this.STARTED&&(pluginModule=a(this.name),pluginModule.shutdown&&pluginModule.shutdown(b,c))}},b.PluginCatalog=function(){this.plugins={}},b.PluginCatalog.prototype={registerPlugins:function(a,c,e){var f=[];a.forEach(function(a){var d=this.plugins[a];d===undefined&&(d=new b.Plugin(a),this.plugins[a]=d,f.push(d.register(c,e)))}.bind(this));return d.group(f)},startupPlugins:function(a,b){var c=[];for(var e in this.plugins){var f=this.plugins[e];c.push(f.startup(a,b))}return d.group(c)}},b.catalog=new b.PluginCatalog}),define("pilot/promise",["require","exports","module","pilot/console","pilot/stacktrace"],function(a,b,c){var d=a("pilot/console"),e=a("pilot/stacktrace").Trace,f=-1,g=0,h=1,i=0,j=!1,k=[],l=[];Promise=function(){this._status=g,this._value=undefined,this._onSuccessHandlers=[],this._onErrorHandlers=[],this._id=i++,k[this._id]=this},Promise.prototype.isPromise=!0,Promise.prototype.isComplete=function(){return this._status!=g},Promise.prototype.isResolved=function(){return this._status==h},Promise.prototype.isRejected=function(){return this._status==f},Promise.prototype.then=function(a,b){typeof a=="function"&&(this._status===h?a.call(null,this._value):this._status===g&&this._onSuccessHandlers.push(a)),typeof b=="function"&&(this._status===f?b.call(null,this._value):this._status===g&&this._onErrorHandlers.push(b));return this},Promise.prototype.chainPromise=function(a){var b=new Promise;b._chainedFrom=this,this.then(function(c){try{b.resolve(a(c))}catch(d){b.reject(d)}},function(a){b.reject(a)});return b},Promise.prototype.resolve=function(a){return this._complete(this._onSuccessHandlers,h,a,"resolve")},Promise.prototype.reject=function(a){return this._complete(this._onErrorHandlers,f,a,"reject")},Promise.prototype._complete=function(a,b,c,f){if(this._status!=g){d.group("Promise already closed"),d.error("Attempted "+f+"() with ",c),d.error("Previous status = ",this._status,", previous value = ",this._value),d.trace(),this._completeTrace&&(d.error("Trace of previous completion:"),this._completeTrace.log(5)),d.groupEnd();return this}j&&(this._completeTrace=new e(new Error)),this._status=b,this._value=c,a.forEach(function(a){a.call(null,this._value)},this),this._onSuccessHandlers.length=0,this._onErrorHandlers.length=0,delete k[this._id],l.push(this);while(l.length>20)l.shift();return this},Promise.group=function(a){a instanceof Array||(a=Array.prototype.slice.call(arguments));if(a.length===0)return(new Promise).resolve([]);var b=new Promise,c=[],d=0,e=function(e){return function(g){c[e]=g,d++,b._status!==f&&d===a.length&&b.resolve(c)}};a.forEach(function(a,c){var d=e(c),f=b.reject.bind(b);a.then(d,f)});return b},b.Promise=Promise,b._outstanding=k,b._recent=l}),define("pilot/dom",["require","exports","module"],function(a,b,c){var d="http://www.w3.org/1999/xhtml";b.createElement=function(a,b){return document.createElementNS?document.createElementNS(b||d,a):document.createElement(a)},b.setText=function(a,b){a.innerText!==undefined&&(a.innerText=b),a.textContent!==undefined&&(a.textContent=b)},document.documentElement.classList?(b.hasCssClass=function(a,b){return a.classList.contains(b)},b.addCssClass=function(a,b){a.classList.add(b)},b.removeCssClass=function(a,b){a.classList.remove(b)},b.toggleCssClass=function(a,b){return a.classList.toggle(b)}):(b.hasCssClass=function(a,b){var c=a.className.split(/\s+/g);return c.indexOf(b)!==-1},b.addCssClass=function(a,c){b.hasCssClass(a,c)||(a.className+=" "+c)},b.removeCssClass=function(a,b){var c=a.className.split(/\s+/g);for(;;){var d=c.indexOf(b);if(d==-1)break;c.splice(d,1)}a.className=c.join(" ")},b.toggleCssClass=function(a,b){var c=a.className.split(/\s+/g),d=!0;for(;;){var e=c.indexOf(b);if(e==-1)break;d=!1,c.splice(e,1)}d&&c.push(b),a.className=c.join(" ");return d}),b.setCssClass=function(a,c,d){d?b.addCssClass(a,c):b.removeCssClass(a,c)},b.importCssString=function(a,b){b=b||document;if(b.createStyleSheet){var c=b.createStyleSheet();c.cssText=a}else{var e=b.createElementNS?b.createElementNS(d,"style"):b.createElement("style");e.appendChild(b.createTextNode(a));var f=b.getElementsByTagName("head")[0]||b.documentElement;f.appendChild(e)}},b.getInnerWidth=function(a){return parseInt(b.computedStyle(a,"paddingLeft"))+parseInt(b.computedStyle(a,"paddingRight"))+a.clientWidth},b.getInnerHeight=function(a){return parseInt(b.computedStyle(a,"paddingTop"))+parseInt(b.computedStyle(a,"paddingBottom"))+a.clientHeight},window.pageYOffset!==undefined?(b.getPageScrollTop=function(){return window.pageYOffset},b.getPageScrollLeft=function(){return window.pageXOffset}):(b.getPageScrollTop=function(){return document.body.scrollTop},b.getPageScrollLeft=function(){return document.body.scrollLeft}),window.getComputedStyle?b.computedStyle=function(a,b){return b?(window.getComputedStyle(a,"")||{})[b]||"":window.getComputedStyle(a,"")||{}}:b.computedStyle=function(a,b){return b?a.currentStyle[b]:a.currentStyle},b.scrollbarWidth=function(){var a=b.createElement("p");a.style.width="100%",a.style.minWidth="0px",a.style.height="200px";var c=b.createElement("div"),d=c.style;d.position="absolute",d.left="-10000px",d.overflow="hidden",d.width="200px",d.minWidth="0px",d.height="150px",c.appendChild(a);var e=document.body||document.documentElement;e.appendChild(c);var f=a.offsetWidth;d.overflow="scroll";var g=a.offsetWidth;f==g&&(g=c.clientWidth),e.removeChild(c);return f-g},b.setInnerHtml=function(a,b){var c=a.cloneNode(!1);c.innerHTML=b,a.parentNode.replaceChild(c,a);return c},b.setInnerText=function(a,b){document.body&&"textContent"in document.body?a.textContent=b:a.innerText=b},b.getInnerText=function(a){return document.body&&"textContent"in document.body?a.textContent:a.innerText||a.textContent||""},b.getParentWindow=function(a){return a.defaultView||a.parentWindow},b.getSelectionStart=function(a){var b;try{b=a.selectionStart||0}catch(c){b=0}return b},b.setSelectionStart=function(a,b){return a.selectionStart=b},b.getSelectionEnd=function(a){var b;try{b=a.selectionEnd||0}catch(c){b=0}return b},b.setSelectionEnd=function(a,b){return a.selectionEnd=b}}),define("pilot/event",["require","exports","module","pilot/keys","pilot/useragent","pilot/dom"],function(a,b,c){function g(a,b,c){var f=0;e.isOpera&&e.isMac?f=0|(b.metaKey?1:0)|(b.altKey?2:0)|(b.shiftKey?4:0)|(b.ctrlKey?8:0):f=0|(b.ctrlKey?1:0)|(b.altKey?2:0)|(b.shiftKey?4:0)|(b.metaKey?8:0);if(c in d.MODIFIER_KEYS){switch(d.MODIFIER_KEYS[c]){case"Alt":f=2;break;case"Shift":f=4;break;case"Ctrl":f=1;break;default:f=8}c=0}f&8&&(c==91||c==93)&&(c=0);return f!=0||c in d.FUNCTION_KEYS?a(b,f,c):!1}var d=a("pilot/keys"),e=a("pilot/useragent"),f=a("pilot/dom");b.addListener=function(a,b,c){if(a.addEventListener)return a.addEventListener(b,c,!1);if(a.attachEvent){var d=function(){c(window.event)};c._wrapper=d,a.attachEvent("on"+b,d)}},b.removeListener=function(a,b,c){if(a.removeEventListener)return a.removeEventListener(b,c,!1);a.detachEvent&&a.detachEvent("on"+b,c._wrapper||c)},b.stopEvent=function(a){b.stopPropagation(a),b.preventDefault(a);return!1},b.stopPropagation=function(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0},b.preventDefault=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},b.getDocumentX=function(a){return a.clientX?a.clientX+f.getPageScrollLeft():a.pageX},b.getDocumentY=function(a){return a.clientY?a.clientY+f.getPageScrollTop():a.pageY},b.getButton=function(a){if(a.type=="dblclick")return 0;if(a.type=="contextmenu")return 2;return a.preventDefault?a.button:{1:0,2:2,4:1}[a.button]},document.documentElement.setCapture?b.capture=function(a,c,d){function f(e){c&&c(e),d&&d(),b.removeListener(a,"mousemove",c),b.removeListener(a,"mouseup",f),b.removeListener(a,"losecapture",f),a.releaseCapture()}function e(a){c(a);return b.stopPropagation(a)}b.addListener(a,"mousemove",c),b.addListener(a,"mouseup",f),b.addListener(a,"losecapture",f),a.setCapture()}:b.capture=function(a,b,c){function e(a){b&&b(a),c&&c(),document.removeEventListener("mousemove",d,!0),document.removeEventListener("mouseup",e,!0),a.stopPropagation()}function d(a){b(a),a.stopPropagation()}document.addEventListener("mousemove",d,!0),document.addEventListener("mouseup",e,!0)},b.addMouseWheelListener=function(a,c){var d=function(a){a.wheelDelta!==undefined?a.wheelDeltaX!==undefined?(a.wheelX=-a.wheelDeltaX/8,a.wheelY=-a.wheelDeltaY/8):(a.wheelX=0,a.wheelY=-a.wheelDelta/8):a.axis&&a.axis==a.HORIZONTAL_AXIS?(a.wheelX=(a.detail||0)*5,a.wheelY=0):(a.wheelX=0,a.wheelY=(a.detail||0)*5),c(a)};b.addListener(a,"DOMMouseScroll",d),b.addListener(a,"mousewheel",d)},b.addMultiMouseDownListener=function(a,c,d,f,g){var h=0,i,j,k=function(a){h+=1,h==1&&(i=a.clientX,j=a.clientY,setTimeout(function(){h=0},f||600));var e=b.getButton(a)==c;if(!e||Math.abs(a.clientX-i)>5||Math.abs(a.clientY-j)>5)h=0;h==d&&(h=0,g(a));if(e)return b.preventDefault(a)};b.addListener(a,"mousedown",k),e.isIE&&b.addListener(a,"dblclick",k)},b.addCommandKeyListener=function(a,c){var d=b.addListener;if(e.isOldGecko){var f=null;d(a,"keydown",function(a){f=a.keyCode}),d(a,"keypress",function(a){return g(c,a,f)})}else{var h=null;d(a,"keydown",function(a){h=a.keyIdentifier||a.keyCode;return g(c,a,a.keyCode)}),e.isMac&&e.isOpera&&d(a,"keypress",function(a){var b=a.keyIdentifier||a.keyCode;if(h!==b)return g(c,a,a.keyCode);h=null})}}}),define("ace/editor",["require","exports","module","pilot/fixoldbrowsers","pilot/oop","pilot/event","pilot/lang","pilot/useragent","ace/keyboard/textinput","ace/mouse_handler","ace/keyboard/keybinding","ace/edit_session","ace/search","ace/range","pilot/event_emitter"],function(a,b,c){a("pilot/fixoldbrowsers");var d=a("pilot/oop"),e=a("pilot/event"),f=a("pilot/lang"),g=a("pilot/useragent"),h=a("ace/keyboard/textinput").TextInput,i=a("ace/mouse_handler").MouseHandler,j=a("ace/keyboard/keybinding").KeyBinding,k=a("ace/edit_session").EditSession,l=a("ace/search").Search,m=a("ace/range").Range,n=a("pilot/event_emitter").EventEmitter,o=function(a,b){var c=a.getContainerElement();this.container=c,this.renderer=a,this.textInput=new h(a.getTextAreaContainer(),this),this.keyBinding=new j(this),g.isIPad||(this.$mouseHandler=new i(this)),this.$blockScrolling=0,this.$search=(new l).set({wrap:!0}),this.setSession(b||new k(""))};(function(){d.implement(this,n),this.$forwardEvents={gutterclick:1,gutterdblclick:1},this.$originalAddEventListener=this.addEventListener,this.$originalRemoveEventListener=this.removeEventListener,this.addEventListener=function(a,b){return this.$forwardEvents[a]?this.renderer.addEventListener(a,b):this.$originalAddEventListener(a,b)},this.removeEventListener=function(a,b){return this.$forwardEvents[a]?this.renderer.removeEventListener(a,b):this.$originalRemoveEventListener(a,b)},this.setKeyboardHandler=function(a){this.keyBinding.setKeyboardHandler(a)},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(a){if(this.session!=a){if(this.session){var b=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);var c=this.session.getSelection();c.removeEventListener("changeCursor",this.$onCursorChange),c.removeEventListener("changeSelection",this.$onSelectionChange),this.session.setScrollTopRow(this.renderer.getScrollTopRow())}this.session=a,this.$onDocumentChange=this.onDocumentChange.bind(this),a.addEventListener("change",this.$onDocumentChange),this.renderer.setSession(a),this.$onChangeMode=this.onChangeMode.bind(this),a.addEventListener("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),a.addEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.updateText.bind(this.renderer),a.addEventListener("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),a.addEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),a.addEventListener("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),a.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.selection=a.getSelection(),this.selection.addEventListener("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.addEventListener("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.onCursorChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.scrollToRow(a.getScrollTopRow()),this.renderer.updateFull(),this._dispatchEvent("changeSession",{session:a,oldSession:b})}},this.getSession=function(){return this.session},this.getSelection=function(){return this.selection},this.resize=function(){this.renderer.onResize()},this.setTheme=function(a){this.renderer.setTheme(a)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(a){this.renderer.setStyle(a)},this.unsetStyle=function(a){this.renderer.unsetStyle(a)},this.setFontSize=function(a){this.container.style.fontSize=a},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(!this.$highlightPending){var a=this;this.$highlightPending=!0,setTimeout(function(){a.$highlightPending=!1;var b=a.session.findMatchingBracket(a.getCursorPosition());if(b){var c=new m(b.row,b.column,b.row,b.column+1);a.session.$bracketHighlight=a.session.addMarker(c,"ace_bracket","text")}},10)}},this.focus=function(){var a=this;g.isIE||setTimeout(function(){a.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(){this.renderer.showCursor(),this.renderer.visualizeFocus(),this._dispatchEvent("focus")},this.onBlur=function(){this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._dispatchEvent("blur")},this.onDocumentChange=function(a){var b=a.data,c=b.range;if(c.start.row==c.end.row&&b.action!="insertLines"&&b.action!="removeLines")var d=c.end.row;else d=Infinity;this.renderer.updateLines(c.start.row,d),this.renderer.updateCursor()},this.onTokenizerUpdate=function(a){var b=a.data;this.renderer.updateLines(b.first,b.last)},this.onCursorChange=function(a){this.renderer.updateCursor(),this.$blockScrolling||this.renderer.scrollCursorIntoView(),this.renderer.moveTextAreaToCursor(this.textInput.getElement()),this.$highlightBrackets(),this.$updateHighlightActiveLine()},this.$updateHighlightActiveLine=function(){var a=this.getSession();a.$highlightLineMarker&&a.removeMarker(a.$highlightLineMarker),a.$highlightLineMarker=null;if(this.getHighlightActiveLine()&&(this.getSelectionStyle()!="line"||!this.selection.isMultiLine())){var b=this.getCursorPosition(),c=this.session.getFoldLine(b.row),d;c?d=new m(c.start.row,0,c.end.row+1,0):d=new m(b.row,0,b.row+1,0),a.$highlightLineMarker=a.addMarker(d,"ace_active_line","background")}},this.onSelectionChange=function(a){var b=this.getSession();b.$selectionMarker&&b.removeMarker(b.$selectionMarker),b.$selectionMarker=null;if(!this.selection.isEmpty()){var c=this.selection.getRange(),d=this.getSelectionStyle();b.$selectionMarker=b.addMarker(c,"ace_selection",d)}else this.$updateHighlightActiveLine();this.$highlightSelectedWord&&this.session.getMode().highlightSelection(this)},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.setBreakpoints(this.session.getBreakpoints())},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(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getCopyText=function(){return this.selection.isEmpty()?"":this.session.getTextRange(this.getSelectionRange())},this.onCut=function(){this.$readOnly||this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection())},this.insert=function(a){if(!this.$readOnly){var b=this.session,c=b.getMode(),d=this.getCursorPosition();if(this.getBehavioursEnabled()){var e=c.transformAction(b.getState(d.row),"insertion",this,b,a);e&&(a=e.text)}a=a.replace("\t",this.session.getTabString());if(!this.selection.isEmpty()){var d=this.session.remove(this.getSelectionRange());this.clearSelection()}else if(this.session.getOverwrite()){var f=new m.fromPoints(d,d);f.end.column+=a.length,this.session.remove(f)}this.clearSelection();var g=d.column,h=b.getState(d.row),i=c.checkOutdent(h,b.getLine(d.row),a),j=b.getLine(d.row),k=c.getNextLineIndent(h,j.slice(0,d.column),b.getTabString()),l=b.insert(d,a);e&&e.selection&&(e.selection.length==2?this.selection.setSelectionRange(new m(d.row,g+e.selection[0],d.row,g+e.selection[1])):this.selection.setSelectionRange(new m(d.row+e.selection[0],e.selection[1],d.row+e.selection[2],e.selection[3])));var h=b.getState(d.row);if(b.getDocument().isNewLine(a)){this.moveCursorTo(d.row+1,0);var n=b.getTabSize(),o=Number.MAX_VALUE;for(var p=d.row+1;p<=l.row;++p){var q=0;j=b.getLine(p);for(var r=0;r0;++r)j.charAt(r)=="\t"?s-=n:j.charAt(r)==" "&&(s-=1);b.remove(new m(p,0,p,r))}b.indentRows(d.row+1,l.row,k)}else i&&c.autoOutdent(h,b,d.row)}},this.onTextInput=function(a,b){if(b&&a.length==1){var c=this.keyBinding.onCommandKey({},0,null,a);c||this.insert(a)}else this.keyBinding.onTextInput(a)},this.onCommandKey=function(a,b,c){this.keyBinding.onCommandKey(a,b,c)},this.setOverwrite=function(a){this.session.setOverwrite(a)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(a){this.$mouseHandler.setScrollSpeed(a)},this.getScrollSpeed=function(){return this.$mouseHandler.getScrollSpeed()},this.$selectionStyle="line",this.setSelectionStyle=function(a){this.$selectionStyle!=a&&(this.$selectionStyle=a,this.onSelectionChange(),this._dispatchEvent("changeSelectionStyle",{data:a}))},this.getSelectionStyle=function(){return this.$selectionStyle},this.$highlightActiveLine=!0,this.setHighlightActiveLine=function(a){this.$highlightActiveLine!=a&&(this.$highlightActiveLine=a,this.$updateHighlightActiveLine())},this.getHighlightActiveLine=function(){return this.$highlightActiveLine},this.$highlightSelectedWord=!0,this.setHighlightSelectedWord=function(a){this.$highlightSelectedWord!=a&&(this.$highlightSelectedWord=a,a?this.session.getMode().highlightSelection(this):this.session.getMode().clearSelectionHighlight(this))},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setShowInvisibles=function(a){this.getShowInvisibles()!=a&&this.renderer.setShowInvisibles(a)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setShowPrintMargin=function(a){this.renderer.setShowPrintMargin(a)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(a){this.renderer.setPrintMarginColumn(a)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.$readOnly=!1,this.setReadOnly=function(a){this.$readOnly=a},this.getReadOnly=function(){return this.$readOnly},this.$modeBehaviours=!0,this.setBehavioursEnabled=function(a){this.$modeBehaviours=a},this.getBehavioursEnabled=function(){return this.$modeBehaviours},this.removeRight=function(){this.$readOnly||(this.selection.isEmpty()&&this.selection.selectRight(),this.session.remove(this.getSelectionRange()),this.clearSelection())},this.removeLeft=function(){if(!this.$readOnly){this.selection.isEmpty()&&this.selection.selectLeft();var a=this.getSelectionRange();if(this.getBehavioursEnabled()){var b=this.session,c=b.getState(a.start.row),d=b.getMode().transformAction(c,"deletion",this,b,a);d!==!1&&(a=d)}this.session.remove(a),this.clearSelection()}},this.removeWordRight=function(){this.$readOnly||(this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection())},this.removeWordLeft=function(){this.$readOnly||(this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection())},this.removeToLineStart=function(){this.$readOnly||(this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection())},this.removeToLineEnd=function(){if(!this.$readOnly){this.selection.isEmpty()&&this.selection.selectLineEnd();var a=this.getSelectionRange();a.start.column==a.end.column&&a.start.row==a.end.row&&(a.end.column=0,a.end.row++),this.session.remove(a),this.clearSelection()}},this.splitLine=function(){if(!this.$readOnly){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var a=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(a)}},this.transposeLetters=function(){if(!this.$readOnly){if(!this.selection.isEmpty())return;var a=this.getCursorPosition(),b=a.column;if(b==0)return;var c=this.session.getLine(a.row);if(b=this.getFirstVisibleRow()&&a<=this.getLastVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$getPageDownRow=function(){return this.renderer.getScrollBottomRow()},this.$getPageUpRow=function(){var a=this.renderer.getScrollTopRow(),b=this.renderer.getScrollBottomRow();return a-(b-a)},this.selectPageDown=function(){var a=this.$getPageDownRow()+Math.floor(this.$getVisibleRowCount()/2);this.scrollPageDown();var b=this.getSelection(),c=this.session.documentToScreenPosition(b.getSelectionLead()),d=this.session.screenToDocumentPosition(a,c.column);b.selectTo(d.row,d.column)},this.selectPageUp=function(){var a=this.renderer.getScrollTopRow()-this.renderer.getScrollBottomRow(),b=this.$getPageUpRow()+Math.round(a/2);this.scrollPageUp();var c=this.getSelection(),d=this.session.documentToScreenPosition(c.getSelectionLead()),e=this.session.screenToDocumentPosition(b,d.column);c.selectTo(e.row,e.column)},this.gotoPageDown=function(){var a=this.$getPageDownRow(),b=this.getCursorPositionScreen().column;this.scrollToRow(a),this.getSelection().moveCursorToScreen(a,b)},this.gotoPageUp=function(){var a=this.$getPageUpRow(),b=this.getCursorPositionScreen().column;this.scrollToRow(a),this.getSelection().moveCursorToScreen(a,b)},this.scrollPageDown=function(){this.scrollToRow(this.$getPageDownRow())},this.scrollPageUp=function(){this.renderer.scrollToRow(this.$getPageUpRow())},this.scrollToRow=function(a){this.renderer.scrollToRow(a)},this.scrollToLine=function(a,b){this.renderer.scrollToLine(a,b)},this.centerSelection=function(){var a=this.getSelectionRange(),b=Math.floor(a.start.row+(a.end.row-a.start.row)/2);this.renderer.scrollToLine(b,!0)},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(a,b){this.selection.moveCursorTo(a,b)},this.moveCursorToPosition=function(a){this.selection.moveCursorToPosition(a)},this.gotoLine=function(a,b){this.selection.clearSelection(),this.$blockScrolling+=1,this.moveCursorTo(a-1,b||0),this.$blockScrolling-=1,this.isRowVisible(this.getCursorPosition().row)||this.scrollToLine(a,!0)},this.navigateTo=function(a,b){this.clearSelection(),this.moveCursorTo(a,b)},this.navigateUp=function(a){this.selection.clearSelection(),a=a||1,this.selection.moveCursorBy(-a,0)},this.navigateDown=function(a){this.selection.clearSelection(),a=a||1,this.selection.moveCursorBy(a,0)},this.navigateLeft=function(a){if(!this.selection.isEmpty()){var b=this.getSelectionRange().start;this.moveCursorToPosition(b)}else{a=a||1;while(a--)this.selection.moveCursorLeft()}this.clearSelection()},this.navigateRight=function(a){if(!this.selection.isEmpty()){var b=this.getSelectionRange().end;this.moveCursorToPosition(b)}else{a=a||1;while(a--)this.selection.moveCursorRight()}this.clearSelection()},this.navigateLineStart=function(){this.selection.moveCursorLineStart(),this.clearSelection()},this.navigateLineEnd=function(){this.selection.moveCursorLineEnd(),this.clearSelection()},this.navigateFileEnd=function(){this.selection.moveCursorFileEnd(),this.clearSelection()},this.navigateFileStart=function(){this.selection.moveCursorFileStart(),this.clearSelection()},this.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},this.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},this.replace=function(a,b){b&&this.$search.set(b);var c=this.$search.find(this.session);!c||(this.$tryReplace(c,a),c!==null&&this.selection.setSelectionRange(c))},this.replaceAll=function(a,b){b&&this.$search.set(b);var c=this.$search.findAll(this.session);if(!!c.length){var d=this.getSelectionRange();this.clearSelection(),this.selection.moveCursorTo(0,0),this.$blockScrolling+=1;for(var e=c.length-1;e>=0;--e)this.$tryReplace(c[e],a);this.selection.setSelectionRange(d),this.$blockScrolling-=1}},this.$tryReplace=function(a,b){var c=this.session.getTextRange(a),b=this.$search.replace(c,b);if(b!==null){a.end=this.session.replace(a,b);return a}return null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(a,b){this.clearSelection(),b=b||{},b.needle=a,this.$search.set(b),this.$find()},this.findNext=function(a){a=a||{},typeof a.backwards=="undefined"&&(a.backwards=!1),this.$search.set(a),this.$find()},this.findPrevious=function(a){a=a||{},typeof a.backwards=="undefined"&&(a.backwards=!0),this.$search.set(a),this.$find()},this.$find=function(a){this.selection.isEmpty()||this.$search.set({needle:this.session.getTextRange(this.getSelectionRange())}),typeof a!="undefined"&&this.$search.set({backwards:a});var b=this.$search.find(this.session);b&&(this.gotoLine(b.end.row+1,b.end.column),this.selection.setSelectionRange(b))},this.undo=function(){this.session.getUndoManager().undo()},this.redo=function(){this.session.getUndoManager().redo()},this.destroy=function(){this.renderer.destroy()}}).call(o.prototype),b.Editor=o}),define("ace/keyboard/textinput",["require","exports","module","pilot/event","pilot/useragent","pilot/dom"],function(a,b,c){var d=a("pilot/event"),e=a("pilot/useragent"),f=a("pilot/dom"),g=function(a,b){function u(){return document.activeElement===c}function l(a){if(!i){var d=a||c.value;if(d){d.charCodeAt(d.length-1)==g.charCodeAt(0)?(d=d.slice(0,-1),d&&b.onTextInput(d,!j)):b.onTextInput(d,!j);if(!u())return!1}}i=!1,j=!1,c.value=g,c.select()}var c=f.createElement("textarea");c.style.left="-10000px",a.appendChild(c);var g=String.fromCharCode(0);l();var h=!1,i=!1,j=!1,k="",m=function(a){setTimeout(function(){h||l(a.data)},0)},n=function(a){e.isIE&&c.value.charCodeAt(0)>128||setTimeout(function(){h||l()},0)},o=function(a){h=!0,b.onCompositionStart(),e.isGecko||setTimeout(p,0)},p=function(){!h||b.onCompositionUpdate(c.value)},q=function(a){h=!1,b.onCompositionEnd()},r=function(a){i=!0;var d=b.getCopyText();d?c.value=d:a.preventDefault(),c.select(),setTimeout(function(){l()},0)},s=function(a){i=!0;var d=b.getCopyText();d?(c.value=d,b.onCut()):a.preventDefault(),c.select(),setTimeout(function(){l()},0)};d.addCommandKeyListener(c,b.onCommandKey.bind(b));if(e.isIE){var t={13:1,27:1};d.addListener(c,"keyup",function(a){h&&(!c.value||t[a.keyCode])&&setTimeout(q,0);(c.value.charCodeAt(0)|0)<129||(h?p():o())})}c.attachEvent?d.addListener(c,"propertychange",n):e.isChrome||e.isSafari?d.addListener(c,"textInput",m):e.isIE?d.addListener(c,"textinput",m):d.addListener(c,"input",m),d.addListener(c,"paste",function(a){j=!0,a.clipboardData&&a.clipboardData.getData?(l(a.clipboardData.getData("text/plain")),a.preventDefault()):n()}),e.isIE?(d.addListener(c,"beforecopy",function(a){var c=b.getCopyText();c?clipboardData.setData("Text",c):a.preventDefault()}),d.addListener(a,"keydown",function(a){if(a.ctrlKey&&a.keyCode==88){var c=b.getCopyText();c&&(clipboardData.setData("Text",c),b.onCut()),d.preventDefault(a)}})):(d.addListener(c,"copy",r),d.addListener(c,"cut",s)),d.addListener(c,"compositionstart",o),e.isGecko&&d.addListener(c,"text",p),e.isWebKit&&d.addListener(c,"keyup",p),d.addListener(c,"compositionend",q),d.addListener(c,"blur",function(){b.onBlur()}),d.addListener(c,"focus",function(){b.onFocus(),c.select()}),this.focus=function(){b.onFocus(),c.select(),c.focus()},this.blur=function(){c.blur()},this.isFocused=u,this.getElement=function(){return c},this.onContextMenu=function(a,b){a&&(k||(k=c.style.cssText),c.style.cssText="position:fixed; z-index:1000;left:"+(a.x-2)+"px; top:"+(a.y-2)+"px;"),b&&(c.value="")},this.onContextMenuClose=function(){setTimeout(function(){k&&(c.style.cssText=k,k=""),l()},0)}};b.TextInput=g}),define("ace/mouse_handler",["require","exports","module","pilot/event","pilot/dom","pilot/browser_focus"],function(a,b,c){var d=a("pilot/event"),e=a("pilot/dom"),f=a("pilot/browser_focus").BrowserFocus,g=0,h=1,i=2,j=250,k=5,l=function(a){this.editor=a,this.browserFocus=new f,d.addListener(a.container,"mousedown",function(b){a.focus();return d.preventDefault(b)}),d.addListener(a.container,"selectstart",function(a){return d.preventDefault(a)});var b=a.renderer.getMouseEventTarget();d.addListener(b,"mousedown",this.onMouseDown.bind(this)),d.addMultiMouseDownListener(b,0,2,500,this.onMouseDoubleClick.bind(this)),d.addMultiMouseDownListener(b,0,3,600,this.onMouseTripleClick.bind(this)),d.addMultiMouseDownListener(b,0,4,600,this.onMouseQuadClick.bind(this)),d.addMouseWheelListener(b,this.onMouseWheel.bind(this))};(function(){this.$scrollSpeed=1,this.setScrollSpeed=function(a){this.$scrollSpeed=a},this.getScrollSpeed=function(){return this.$scrollSpeed},this.$getEventPosition=function(a){var b=d.getDocumentX(a),c=d.getDocumentY(a),e=this.editor.renderer.screenToTextCoordinates(b,c);e.row=Math.max(0,Math.min(e.row,this.editor.session.getLength()-1));return e},this.$distance=function(a,b,c,d){return Math.sqrt(Math.pow(c-a,2)+Math.pow(d-b,2))},this.onMouseDown=function(a){function D(b){a.shiftKey?l.selection.selectToPosition(b):m.$clickSelection||(l.moveCursorToPosition(b),l.selection.clearSelection(b.row,b.column)),p=h}if(!(!this.browserFocus.isFocused()||(new Date).getTime()-this.browserFocus.lastFocus<20||!this.editor.isFocused())){var b=d.getDocumentX(a),c=d.getDocumentY(a),f=this.$getEventPosition(a),l=this.editor,m=this,n=l.getSelectionRange(),o=n.isEmpty(),p=g,q=!1,r=d.getButton(a);if(r!==0){o&&l.moveCursorToPosition(f),r==2&&(l.textInput.onContextMenu({x:b,y:c},o),d.capture(l.container,function(){},l.textInput.onContextMenuClose));return}var s=l.session.getFoldAt(f.row,f.column,1);if(s){l.selection.setSelectionRange(s.range);return}q=!l.getReadOnly()&&!o&&n.contains(f.row,f.column),q||D(f);var t,u,v=l.getOverwrite(),w=(new Date).getTime(),x,y,z=function(a){t=d.getDocumentX(a),u=d.getDocumentY(a)},A=function(){clearInterval(G),p==g?D(f):p==i&&B(),m.$clickSelection=null,p=g},B=function(){e.removeCssClass(l.container,"ace_dragging"),l.session.removeMarker(dragSelectionMarker),m.$clickSelection||x||(l.moveCursorToPosition(f),l.selection.clearSelection(f.row,f.column));if(!!x){if(y.contains(x.row,x.column)){x=null;return}l.clearSelection();var a=l.moveText(y,x);if(!a){x=null;return}l.selection.setSelectionRange(a)}},C=function(){if(t!==undefined&&u!==undefined){if(p==g){var a=m.$distance(b,c,t,u),d=(new Date).getTime();if(a>k){p=h;var f=l.renderer.screenToTextCoordinates(t,u);f.row=Math.max(0,Math.min(f.row,l.session.getLength()-1)),D(f)}else if(d-w>j){p=i,y=l.getSelectionRange();var n=l.getSelectionStyle();dragSelectionMarker=l.session.addMarker(y,"ace_selection",n),l.clearSelection(),e.addCssClass(l.container,"ace_dragging")}}p==i?F():p==h&&E()}},E=function(){var a=l.renderer.screenToTextCoordinates(t,u);a.row=Math.max(0,Math.min(a.row,l.session.getLength()-1));if(m.$clickSelection)if(m.$clickSelection.contains(a.row,a.column))l.selection.setSelectionRange(m.$clickSelection);else{if(m.$clickSelection.compare(a.row,a.column)==-1)var b=m.$clickSelection.end;else var b=m.$clickSelection.start;l.selection.setSelectionAnchor(b.row,b.column),l.selection.selectToPosition(a)}else l.selection.selectToPosition(a);l.renderer.scrollCursorIntoView()},F=function(){x=l.renderer.screenToTextCoordinates(t,u),x.row=Math.max(0,Math.min(x.row,l.session.getLength()-1)),l.moveCursorToPosition(x)};d.capture(l.container,z,A);var G=setInterval(C,20);return d.preventDefault(a)}},this.onMouseDoubleClick=function(a){var b=this.editor,c=this.$getEventPosition(a),d=b.session.getFoldAt(c.row,c.column,1);d?b.session.expandFold(d):(b.moveCursorToPosition(c),b.selection.selectWord(),this.$clickSelection=b.getSelectionRange())},this.onMouseTripleClick=function(a){var b=this.$getEventPosition(a);this.editor.moveCursorToPosition(b),this.editor.selection.selectLine(),this.$clickSelection=this.editor.getSelectionRange()},this.onMouseQuadClick=function(a){this.editor.selectAll(),this.$clickSelection=this.editor.getSelectionRange()},this.onMouseWheel=function(a){var b=this.$scrollSpeed*2;this.editor.renderer.scrollBy(a.wheelX*b,a.wheelY*b);return d.preventDefault(a)}}).call(l.prototype),b.MouseHandler=l}),define("pilot/browser_focus",["require","exports","module","pilot/oop","pilot/event","pilot/event_emitter"],function(a,b,c){var d=a("pilot/oop"),e=a("pilot/event"),f=a("pilot/event_emitter").EventEmitter,g=function(a){a=a||window,this.lastFocus=(new Date).getTime(),this._isFocused=!0;var b=this;e.addListener(a,"blur",function(a){b._setFocused(!1)}),e.addListener(a,"focus",function(a){b._setFocused(!0)})};(function(){d.implement(this,f),this.isFocused=function(){return this._isFocused},this._setFocused=function(a){this._isFocused!=a&&(a&&(this.lastFocus=(new Date).getTime()),this._isFocused=a,this._emit("changeFocus"))}}).call(g.prototype),b.BrowserFocus=g}),define("ace/keyboard/keybinding",["require","exports","module","pilot/useragent","pilot/keys","pilot/event","pilot/settings","pilot/canon","ace/commands/default_commands"],function(a,b,c){var d=a("pilot/useragent"),e=a("pilot/keys"),f=a("pilot/event"),g=a("pilot/settings").settings,h=a("pilot/canon");a("ace/commands/default_commands");var i=function(a){this.$editor=a,this.$data={},this.$keyboardHandler=null};(function(){this.setKeyboardHandler=function(a){this.$keyboardHandler!=a&&(this.$data={},this.$keyboardHandler=a)},this.getKeyboardHandler=function(){return this.$keyboardHandler},this.$callKeyboardHandler=function(a,b,c,d){var e={editor:this.$editor},g;this.$keyboardHandler&&(g=this.$keyboardHandler.handleKeyboard(this.$data,b,c,d,a));if(!g||!g.command)b!=0||d!=0?g={command:h.findKeyCommand(e,"editor",b,c)}:g={command:"inserttext",args:{text:c}};var i=!1;g&&(i=h.exec(g.command,e,"editor",g.args),i&&f.stopEvent(a));return i},this.onCommandKey=function(a,b,c,d){d||(d=e.keyCodeToString(c));return this.$callKeyboardHandler(a,b,d,c)},this.onTextInput=function(a){return this.$callKeyboardHandler({},0,a,0)}}).call(i.prototype),b.KeyBinding=i}),define("ace/commands/default_commands",["require","exports","module","pilot/lang","pilot/canon"],function(a,b,c){function f(a,b){return{win:a,mac:b,sender:"editor"}}var d=a("pilot/lang"),e=a("pilot/canon");e.addCommand({name:"null",exec:function(a,b,c){}}),e.addCommand({name:"selectall",bindKey:f("Ctrl-A","Command-A"),exec:function(a,b,c){a.editor.selectAll()}}),e.addCommand({name:"removeline",bindKey:f("Ctrl-D","Command-D"),exec:function(a,b,c){a.editor.removeLines()}}),e.addCommand({name:"gotoline",bindKey:f("Ctrl-L","Command-L"),exec:function(a,b,c){var d=parseInt(prompt("Enter line number:"));isNaN(d)||a.editor.gotoLine(d)}}),e.addCommand({name:"togglecomment",bindKey:f("Ctrl-7","Command-7"),exec:function(a,b,c){a.editor.toggleCommentLines()}}),e.addCommand({name:"findnext",bindKey:f("Ctrl-K","Command-G"),exec:function(a,b,c){a.editor.findNext()}}),e.addCommand({name:"findprevious",bindKey:f("Ctrl-Shift-K","Command-Shift-G"),exec:function(a,b,c){a.editor.findPrevious()}}),e.addCommand({name:"find",bindKey:f("Ctrl-F","Command-F"),exec:function(a,b,c){var d=prompt("Find:");a.editor.find(d)}}),e.addCommand({name:"replace",bindKey:f("Ctrl-R","Command-Option-F"),exec:function(a,b,c){var d=prompt("Find:");if(!!d){var e=prompt("Replacement:");if(!e)return;a.editor.replace(e,{needle:d})}}}),e.addCommand({name:"replaceall",bindKey:f("Ctrl-Shift-R","Command-Shift-Option-F"),exec:function(a,b,c){var d=prompt("Find:");if(!!d){var e=prompt("Replacement:");if(!e)return;a.editor.replaceAll(e,{needle:d})}}}),e.addCommand({name:"undo",bindKey:f("Ctrl-Z","Command-Z"),exec:function(a,b,c){a.editor.undo()}}),e.addCommand({name:"redo",bindKey:f("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(a,b,c){a.editor.redo()}}),e.addCommand({name:"overwrite",bindKey:f("Insert","Insert"),exec:function(a,b,c){a.editor.toggleOverwrite()}}),e.addCommand({name:"copylinesup",bindKey:f("Ctrl-Alt-Up","Command-Option-Up"),exec:function(a,b,c){a.editor.copyLinesUp()}}),e.addCommand({name:"movelinesup",bindKey:f("Alt-Up","Option-Up"),exec:function(a,b,c){a.editor.moveLinesUp()}}),e.addCommand({name:"selecttostart",bindKey:f("Ctrl-Shift-Home|Alt-Shift-Up","Command-Shift-Up"),exec:function(a,b,c){a.editor.getSelection().selectFileStart()}}),e.addCommand({name:"gotostart",bindKey:f("Ctrl-Home|Ctrl-Up","Command-Home|Command-Up"),exec:function(a,b,c){a.editor.navigateFileStart()}}),e.addCommand({name:"selectup",bindKey:f("Shift-Up","Shift-Up"),exec:function(a,b,c){a.editor.getSelection().selectUp()}}),e.addCommand({name:"golineup",bindKey:f("Up","Up|Ctrl-P"),exec:function(a,b,c){a.editor.navigateUp(b.times)}}),e.addCommand({name:"copylinesdown",bindKey:f("Ctrl-Alt-Down","Command-Option-Down"),exec:function(a,b,c){a.editor.copyLinesDown()}}),e.addCommand({name:"movelinesdown",bindKey:f("Alt-Down","Option-Down"),exec:function(a,b,c){a.editor.moveLinesDown()}}),e.addCommand({name:"selecttoend",bindKey:f("Ctrl-Shift-End|Alt-Shift-Down","Command-Shift-Down"),exec:function(a,b,c){a.editor.getSelection().selectFileEnd()}}),e.addCommand({name:"gotoend",bindKey:f("Ctrl-End|Ctrl-Down","Command-End|Command-Down"),exec:function(a,b,c){a.editor.navigateFileEnd()}}),e.addCommand({name:"selectdown",bindKey:f("Shift-Down","Shift-Down"),exec:function(a,b,c){a.editor.getSelection().selectDown()}}),e.addCommand({name:"golinedown",bindKey:f("Down","Down|Ctrl-N"),exec:function(a,b,c){a.editor.navigateDown(b.times)}}),e.addCommand({name:"selectwordleft",bindKey:f("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(a,b,c){a.editor.getSelection().selectWordLeft()}}),e.addCommand({name:"gotowordleft",bindKey:f("Ctrl-Left","Option-Left"),exec:function(a,b,c){a.editor.navigateWordLeft()}}),e.addCommand({name:"selecttolinestart",bindKey:f("Alt-Shift-Left","Command-Shift-Left"),exec:function(a,b,c){a.editor.getSelection().selectLineStart()}}),e.addCommand({name:"gotolinestart",bindKey:f("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(a,b,c){a.editor.navigateLineStart()}}),e.addCommand({name:"selectleft",bindKey:f("Shift-Left","Shift-Left"),exec:function(a,b,c){a.editor.getSelection().selectLeft()}}),e.addCommand({name:"gotoleft",bindKey:f("Left","Left|Ctrl-B"),exec:function(a,b,c){a.editor.navigateLeft(b.times)}}),e.addCommand({name:"selectwordright",bindKey:f("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(a,b,c){a.editor.getSelection().selectWordRight()}}),e.addCommand({name:"gotowordright",bindKey:f("Ctrl-Right","Option-Right"),exec:function(a,b,c){a.editor.navigateWordRight()}}),e.addCommand({name:"selecttolineend",bindKey:f("Alt-Shift-Right","Command-Shift-Right"),exec:function(a,b,c){a.editor.getSelection().selectLineEnd()}}),e.addCommand({name:"gotolineend",bindKey:f("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(a,b,c){a.editor.navigateLineEnd()}}),e.addCommand({name:"selectright",bindKey:f("Shift-Right","Shift-Right"),exec:function(a,b,c){a.editor.getSelection().selectRight()}}),e.addCommand({name:"gotoright",bindKey:f("Right","Right|Ctrl-F"),exec:function(a,b,c){a.editor.navigateRight(b.times)}}),e.addCommand({name:"selectpagedown",bindKey:f("Shift-PageDown","Shift-PageDown"),exec:function(a,b,c){a.editor.selectPageDown()}}),e.addCommand({name:"pagedown",bindKey:f(null,"PageDown"),exec:function(a,b,c){a.editor.scrollPageDown()}}),e.addCommand({name:"gotopagedown",bindKey:f("PageDown","Option-PageDown|Ctrl-V"),exec:function(a,b,c){a.editor.gotoPageDown()}}),e.addCommand({name:"selectpageup",bindKey:f("Shift-PageUp","Shift-PageUp"),exec:function(a,b,c){a.editor.selectPageUp()}}),e.addCommand({name:"pageup",bindKey:f(null,"PageUp"),exec:function(a,b,c){a.editor.scrollPageUp()}}),e.addCommand({name:"gotopageup",bindKey:f("PageUp","Option-PageUp"),exec:function(a,b,c){a.editor.gotoPageUp()}}),e.addCommand({name:"selectlinestart",bindKey:f("Shift-Home","Shift-Home"),exec:function(a,b,c){a.editor.getSelection().selectLineStart()}}),e.addCommand({name:"selectlineend",bindKey:f("Shift-End","Shift-End"),exec:function(a,b,c){a.editor.getSelection().selectLineEnd()}}),e.addCommand({name:"del",bindKey:f("Delete","Delete|Ctrl-D"),exec:function(a,b,c){a.editor.removeRight()}}),e.addCommand({name:"backspace",bindKey:f("Ctrl-Backspace|Command-Backspace|Option-Backspace|Shift-Backspace|Backspace","Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(a,b,c){a.editor.removeLeft()}}),e.addCommand({name:"removetolinestart",bindKey:f(null,"Option-Backspace"),exec:function(a,b,c){a.editor.removeToLineStart()}}),e.addCommand({name:"removetolineend",bindKey:f(null,"Ctrl-K"),exec:function(a,b,c){a.editor.removeToLineEnd()}}),e.addCommand({name:"removewordleft",bindKey:f("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(a,b,c){a.editor.removeWordLeft()}}),e.addCommand({name:"removewordright",bindKey:f(null,"Alt-Delete"),exec:function(a,b,c){a.editor.removeWordRight()}}),e.addCommand({name:"outdent",bindKey:f("Shift-Tab","Shift-Tab"),exec:function(a,b,c){a.editor.blockOutdent()}}),e.addCommand({name:"indent",bindKey:f("Tab","Tab"),exec:function(a,b,c){a.editor.indent()}}),e.addCommand({name:"inserttext",exec:function(a,b,c){a.editor.insert(d.stringRepeat(b.text||"",b.times||1))}}),e.addCommand({name:"centerselection",bindKey:f(null,"Ctrl-L"),exec:function(a,b,c){a.editor.centerSelection()}}),e.addCommand({name:"splitline",bindKey:f(null,"Ctrl-O"),exec:function(a,b,c){a.editor.splitLine()}}),e.addCommand({name:"transposeletters",bindKey:f("Ctrl-T","Ctrl-T"),exec:function(a,b,c){a.editor.transposeLetters()}})}),define("ace/edit_session",["require","exports","module","pilot/oop","pilot/lang","pilot/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/edit_session/folding"],function(a,b,c){var d=a("pilot/oop"),e=a("pilot/lang"),f=a("pilot/event_emitter").EventEmitter,g=a("ace/selection").Selection,h=a("ace/mode/text").Mode,j=a("ace/range").Range,k=a("ace/document").Document,l=a("ace/background_tokenizer").BackgroundTokenizer,m=function(a,b){this.$modified=!0,this.$breakpoints=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$rowCache=[],this.$wrapData=[],this.$foldData=[],this.$foldData.toString=function(){var a="";this.forEach(function(b){a+="\n"+b.toString()});return a},a instanceof k?this.setDocument(a):this.setDocument(new k(a)),this.selection=new g(this),b?this.setMode(b):this.setMode(new h)};(function(){function o(a){return a<4352?!1:a>=4352&&a<=4447||a>=4515&&a<=4519||a>=4602&&a<=4607||a>=9001&&a<=9002||a>=11904&&a<=11929||a>=11931&&a<=12019||a>=12032&&a<=12245||a>=12272&&a<=12283||a>=12288&&a<=12350||a>=12353&&a<=12438||a>=12441&&a<=12543||a>=12549&&a<=12589||a>=12593&&a<=12686||a>=12688&&a<=12730||a>=12736&&a<=12771||a>=12784&&a<=12830||a>=12832&&a<=12871||a>=12880&&a<=13054||a>=13056&&a<=19903||a>=19968&&a<=42124||a>=42128&&a<=42182||a>=43360&&a<=43388||a>=44032&&a<=55203||a>=55216&&a<=55238||a>=55243&&a<=55291||a>=63744&&a<=64255||a>=65040&&a<=65049||a>=65072&&a<=65106||a>=65108&&a<=65126||a>=65128&&a<=65131||a>=65281&&a<=65376||a>=65504&&a<=65510}d.implement(this,f),this.setDocument=function(a){if(this.doc)throw new Error("Document is already set");this.doc=a,a.on("change",this.onChange.bind(this)),this.on("changeFold",this.onChangeFold.bind(this))},this.getDocument=function(){return this.doc},this.$resetRowCache=function(a){if(a==0)this.$rowCache=[];else{var b=this.$rowCache;for(var c=0;c=a){b.splice(c,b.length);return}}},this.onChangeFold=function(a){var b=a.data;this.$resetRowCache(b.start.row)},this.onChange=function(a){var b=a.data;this.$modified=!0,this.$resetRowCache(b.range.start.row);var c=this.$updateInternalDataOnChange(a);!this.$fromUndo&&this.$undoManager&&!b.ignore&&(this.$deltasDoc.push(b),c&&c.length!=0&&this.$deltasFold.push({action:"removeFolds",folds:c}),this.$informUndoManager.schedule()),this.bgTokenizer.start(b.range.start.row),this._dispatchEvent("change",a)},this.setValue=function(a){this.doc.setValue(a),this.selection.moveCursorTo(0,0),this.selection.clearSelection(),this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.getUndoManager().reset()},this.getValue=this.toString=function(){return this.doc.getValue()},this.getSelection=function(){return this.selection},this.getState=function(a){return this.bgTokenizer.getState(a)},this.getTokens=function(a,b){return this.bgTokenizer.getTokens(a,b)},this.setUndoManager=function(a){this.$undoManager=a,this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(a){var b=this;this.$syncInformUndoManager=function(){b.$informUndoManager.cancel(),b.$deltasFold.length&&(b.$deltas.push({group:"fold",deltas:b.$deltasFold}),b.$deltasFold=[]),b.$deltasDoc.length&&(b.$deltas.push({group:"doc",deltas:b.$deltasDoc}),b.$deltasDoc=[]),b.$deltas.length>0&&a.execute({action:"aceupdate",args:[b.$deltas,b]}),b.$deltas=[]},this.$informUndoManager=e.deferredCall(this.$syncInformUndoManager)}},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?e.stringRepeat(" ",this.getTabSize()):"\t"},this.$useSoftTabs=!0,this.setUseSoftTabs=function(a){this.$useSoftTabs!==a&&(this.$useSoftTabs=a)},this.getUseSoftTabs=function(){return this.$useSoftTabs},this.$tabSize=4,this.setTabSize=function(a){!isNaN(a)&&this.$tabSize!==a&&(this.$modified=!0,this.$tabSize=a,this._dispatchEvent("changeTabSize"))},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(a){return this.$useSoftTabs&&a.column%this.$tabSize==0},this.$overwrite=!1,this.setOverwrite=function(a){this.$overwrite!=a&&(this.$overwrite=a,this._dispatchEvent("changeOverwrite"))},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(a){this.$breakpoints=[];for(var b=0;b0&&(d=!!c.charAt(b-1).match(this.tokenRe)),d||(d=!!c.charAt(b).match(this.tokenRe));var e=d?this.tokenRe:this.nonTokenRe,f=b;if(f>0){do f--;while(f>=0&&c.charAt(f).match(e));f++}var g=b;while(g=0){var h=g.charAt(d);if(h==c){f-=1;if(f==0)return{row:e,column:d}}else h==a&&(f+=1);d-=1}e-=1;if(e<0)break;var g=this.getLine(e),d=g.length-1}return null},this.$findClosingBracket=function(a,b){var c=this.$brackets[a],d=b.column,e=b.row,f=1,g=this.getLine(e),h=this.getLength();for(;;){while(d=h)break;var g=this.getLine(e),d=0}return null},this.insert=function(a,b){return this.doc.insert(a,b)},this.remove=function(a){return this.doc.remove(a)},this.undoChanges=function(a,b){if(!!a.length){this.$fromUndo=!0;var c=null;for(var d=a.length-1;d!=-1;d--)delta=a[d],delta.group=="doc"?(this.doc.revertDeltas(delta.deltas),c=this.$getUndoSelection(delta.deltas,!0,c)):delta.deltas.forEach(function(a){this.addFolds(a.folds)},this);this.$fromUndo=!1,c&&!b&&this.selection.setSelectionRange(c);return c}},this.redoChanges=function(a,b){if(!!a.length){this.$fromUndo=!0;var c=null;for(var d=0;d=this.doc.getLength()-1)return 0;var c=this.doc.removeLines(a,b);this.doc.insertLines(a+1,c);return 1},this.duplicateLines=function(a,b){var a=this.$clipRowToDocument(a),b=this.$clipRowToDocument(b),c=this.getLines(a,b);this.doc.insertLines(a,c);var d=b-a+1;return d},this.$clipRowToDocument=function(a){return Math.max(0,Math.min(a,this.doc.getLength()-1))},this.$clipPositionToDocument=function(a,b){b=Math.max(0,b);if(a<0)a=0,b=0;else{var c=this.doc.getLength();a>=c?(a=c-1,b=this.doc.getLine(c-1).length):b=Math.min(this.doc.getLine(a).length,b)}return{row:a,column:b}},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(a){if(a!=this.$useWrapMode){this.$useWrapMode=a,this.$modified=!0,this.$resetRowCache(0);if(a){var b=this.getLength();this.$wrapData=[];for(i=0;i0){this.$wrapLimit=b,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._dispatchEvent("changeWrapLimit"));return!0}return!1},this.$constrainWrapLimit=function(a){var b=this.$wrapLimitRange.min;b&&(a=Math.max(b,a));var c=this.$wrapLimitRange.max;c&&(a=Math.min(c,a));return Math.max(1,a)},this.getWrapLimit=function(){return this.$wrapLimit},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(a){var b=this.$useWrapMode,c,d=a.data.action,e=a.data.range.start.row,f=a.data.range.end.row,g=a.data.range.start,h=a.data.range.end,i=null;d.indexOf("Lines")!=-1?(d=="insertLines"?f=e+a.data.lines.length:f=e,c=a.data.lines.length):c=f-e;if(c!=0)if(d.indexOf("remove")!=-1){b&&this.$wrapData.splice(e,c);var j=this.$foldData;i=this.getFoldsInRange(a.data.range),this.removeFolds(i);var k=this.getFoldLine(h.row),l=0;if(k){k.addRemoveChars(h.row,h.column,g.column-h.column),k.shiftRow(-c);var m=this.getFoldLine(e);m&&m!==k&&(m.merge(k),k=m),l=j.indexOf(k)+1}for(l;l=h.row&&k.shiftRow(-c)}f=e}else{var n;if(b){n=[e,0];for(var o=0;o=e&&k.shiftRow(c)}}else{var q;c=Math.abs(a.data.range.start.column-a.data.range.end.column),d.indexOf("remove")!=-1&&(i=this.getFoldsInRange(a.data.range),this.removeFolds(i),c=-c);var k=this.getFoldLine(e);k&&k.addRemoveChars(e,g.column,c)}b&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),b&&this.$updateWrapData(e,f);return i},this.$updateWrapData=function(a,b){var c=this.doc.getAllLines(),d=this.getTabSize(),f=this.$wrapData,i=this.$wrapLimit,j,l,m=a;b=Math.min(b,c.length-1);while(m<=b){l=this.getFoldLine(m);if(!l)j=this.$getDisplayTokens(e.stringTrimRight(c[m]));else{j=[],l.walk(function(a,b,d,e){var f;if(a){f=this.$getDisplayTokens(a,j.length),f[0]=g;for(var i=1;i=k)j.pop()}f[m]=this.$computeWrapSplits(j,i,d),m=this.getRowFoldEnd(m)+1}};var b=1,c=2,g=3,h=4,k=10,m=11,n=12;this.$computeWrapSplits=function(a,b,c){function j(b){var c=a.slice(f,b),e=c.length;c.join("").replace(/12/g,function(a){e-=1}).replace(/2/g,function(a){e-=1}),i+=e,d.push(i),f=b}if(a.length==0)return[];var c=this.getTabSize(),d=[],e=a.length,f=0,i=0;while(e-f>b){var l=f+b;if(a[l]>=k){while(a[l]>=k)l++;j(l);continue}if(a[l]==g||a[l]==h){for(l;l!=f-1;l--)if(a[l]==g)break;if(l>f){j(l);continue}l=f+b;for(l;l=g){l++;break}if(l>f){j(l);continue}l=f+b,j(f+b)}return d},this.$getDisplayTokens=function(a,d){var e=[],f;d=d||0;for(var g=0;gb)break}return[c,e]},this.getRowLength=function(a){return!this.$useWrapMode||!this.$wrapData[a]?1:this.$wrapData[a].length+1},this.getRowHeight=function(a,b){return this.getRowLength(b)*a.lineHeight},this.getScreenLastRowColumn=function(a){return this.documentToScreenColumn(a,this.doc.getLine(a).length)},this.getDocumentLastRowColumn=function(a,b){var c=this.documentToScreenRow(a,b);return this.getScreenLastRowColumn(c)},this.getDocumentLastRowColumnPosition=function(a,b){var c=this.documentToScreenRow(a,b);return this.screenToDocumentPosition(c,Number.MAX_VALUE/10)},this.getRowSplitData=function(a){return this.$useWrapMode?this.$wrapData[a]:undefined},this.getScreenTabSize=function(a){return this.$tabSize-a%this.$tabSize},this.screenToDocumentRow=function(a,b){return this.screenToDocumentPosition(a,b).row},this.screenToDocumentColumn=function(a,b){return this.screenToDocumentPosition(a,b).column},this.screenToDocumentPosition=function(a,b){if(a<0)return{row:0,column:0};var c,d=0,e=0,f,g,h=0,i=0,j=this.$rowCache;for(var k=0;k=a||d>=m)break;h+=i,d++,d>o&&(d=n.end.row+1,n=this.getNextFold(d),o=n?n.start.row:Infinity),l&&j.push({docRow:d,screenRow:h})}n&&n.start.row<=d?c=this.getFoldDisplayLine(n):(c=this.getLine(d),n=null);var p=[];this.$useWrapMode&&(p=this.$wrapData[d],p&&(f=p[a-h],a>h&&p.length&&(e=p[a-h-1]||p[p.length-1],c=c.substring(e)))),e+=this.$getStringScreenWidth(c,b)[1],h+p.length=f&&(e=f-1):e=Math.min(e,c.length);return n?n.idxToPosition(e):{row:d,column:e}},this.documentToScreenPosition=function(a,b){if(typeof b=="undefined")var c=this.$clipPositionToDocument(a.row,a.column);else c=this.$clipPositionToDocument(a,b);a=c.row,b=c.column;var d=this.$rowCache.length,e;if(this.$useWrapMode){e=this.$wrapData;if(a>e.length-1)return{row:this.getScreenLength(),column:e.length==0?0:e[e.length-1].length-1}}var f=0,g=0,h=null,i=null;i=this.getFoldAt(a,b,1),i&&(a=i.start.row,b=i.start.column);var j,k=0,l=this.$rowCache;for(var m=0;m=p){j=o.end.row+1;if(j>a)break;o=this.getNextFold(j),p=o?o.start.row:Infinity}else j=k+1;f+=this.getRowLength(k),k=j,n&&l.push({docRow:k,screenRow:f})}var q="";o&&k>=p?(q=this.getFoldDisplayLine(o,a,b),h=o.start.row):(q=this.getLine(a).substring(0,b),h=a);if(this.$useWrapMode){var r=e[h],s=0;while(q.length>=r[s])f++,s++;q=q.substring(r[s-1]||0,q.length)}return{row:f,column:this.$getStringScreenWidth(q)[0]}},this.documentToScreenColumn=function(a,b){return this.documentToScreenPosition(a,b).column},this.documentToScreenRow=function(a,b){return this.documentToScreenPosition(a,b).row},this.getScreenLength=function(){var a=0,b=null,c=null;if(!this.$useWrapMode){a=this.getLength();var d=this.$foldData;for(var e=0;eb.row||a.row==b.row&&a.column>b.column},this.getRange=function(){var a=this.selectionAnchor,b=this.selectionLead;return this.isEmpty()?g.fromPoints(b,b):this.isBackwards()?g.fromPoints(b,a):g.fromPoints(a,b)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._dispatchEvent("changeSelection"))},this.selectAll=function(){var a=this.doc.getLength()-1;this.setSelectionAnchor(a,this.doc.getLine(a).length),this.moveCursorTo(0,0)},this.setSelectionRange=function(a,b){b?(this.setSelectionAnchor(a.end.row,a.end.column),this.selectTo(a.start.row,a.start.column)):(this.setSelectionAnchor(a.start.row,a.start.column),this.selectTo(a.end.row,a.end.column)),this.$updateDesiredColumn()},this.$updateDesiredColumn=function(){var a=this.getCursor();this.$desiredColumn=this.session.documentToScreenColumn(a.row,a.column)},this.$moveSelection=function(a){var b=this.selectionLead;this.$isEmpty&&this.setSelectionAnchor(b.row,b.column),a.call(this)},this.selectTo=function(a,b){this.$moveSelection(function(){this.moveCursorTo(a,b)})},this.selectToPosition=function(a){this.$moveSelection(function(){this.moveCursorToPosition(a)})},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.selectWord=function(){var a=this.getCursor(),b=this.session.getWordRange(a.row,a.column);this.setSelectionRange(b)},this.selectLine=function(){var a=this.selectionLead.row,b,c=this.session.getFoldLine(a);c?(a=c.start.row,b=c.end.row):b=a,this.setSelectionAnchor(a,0),this.$moveSelection(function(){this.moveCursorTo(b+1,0)})},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.moveCursorLeft=function(){var a=this.selectionLead.getPosition(),b;if(b=this.session.getFoldAt(a.row,a.column,-1))this.moveCursorTo(b.start.row,b.start.column);else if(a.column==0)a.row>0&&this.moveCursorTo(a.row-1,this.doc.getLine(a.row-1).length);else{var c=this.session.getTabSize();this.session.isTabStop(a)&&this.doc.getLine(a.row).slice(a.column-c,a.column).split(" ").length-1==c?this.moveCursorBy(0,-c):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var a=this.selectionLead.getPosition(),b;if(b=this.session.getFoldAt(a.row,a.column,1))this.moveCursorTo(b.end.row,b.end.column);else if(this.selectionLead.column==this.doc.getLine(this.selectionLead.row).length)this.selectionLead.row ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(a,b){return this.compare(a,b)==0},this.compareRange=function(a){var b,c=a.end,d=a.start;b=this.compare(c.row,c.column);if(b==1){b=this.compare(d.row,d.column);return b==1?2:b==0?1:0}if(b==-1)return-2;b=this.compare(d.row,d.column);return b==-1?-1:b==1?42:0},this.containsRange=function(a){var b=this.compareRange(a);return b==-1||b==0||b==1},this.isEnd=function(a,b){return this.end.row==a&&this.end.column==b},this.isStart=function(a,b){return this.start.row==a&&this.start.column==b},this.setStart=function(a,b){typeof a=="object"?(this.start.column=a.column,this.start.row=a.row):(this.start.row=a,this.start.column=b)},this.setEnd=function(a,b){typeof a=="object"?(this.end.column=a.column,this.end.row=a.row):(this.end.row=a,this.end.column=b)},this.inside=function(a,b){if(this.compare(a,b)==0)return this.isEnd(a,b)||this.isStart(a,b)?!1:!0;return!1},this.insideStart=function(a,b){if(this.compare(a,b)==0)return this.isEnd(a,b)?!1:!0;return!1},this.insideEnd=function(a,b){if(this.compare(a,b)==0)return this.isStart(a,b)?!1:!0;return!1},this.compare=function(a,b){if(!this.isMultiLine()&&a===this.start.row)return bthis.end.column?1:0;return athis.end.row?1:this.start.row===a?b>=this.start.column?0:-1:this.end.row===a?b<=this.end.column?0:1:0},this.compareStart=function(a,b){return this.start.row==a&&this.start.column==b?-1:this.compare(a,b)},this.compareEnd=function(a,b){return this.end.row==a&&this.end.column==b?1:this.compare(a,b)},this.compareInside=function(a,b){return this.end.row==a&&this.end.column==b?1:this.start.row==a&&this.start.column==b?-1:this.compare(a,b)},this.clipRows=function(a,b){if(this.end.row>b)var c={row:b+1,column:0};if(this.start.row>b)var e={row:b+1,column:0};if(this.start.row=0&&/^[\w\d]/.test(h)||e<=g&&/[\w\d]$/.test(h))return;h=f.substring(c.start.column,c.end.column);if(!/^[\w\d]+$/.test(h))return;var i=a.getCursorPosition(),j={wrap:!0,wholeWord:!0,caseSensitive:!0,needle:h},k=a.$search.getOptions();a.$search.set(j);var l=a.$search.findAll(b);l.forEach(function(a){if(!a.contains(i.row,i.column)){var c=b.addMarker(a,"ace_selected_word","text");b.$selectionOccurrences.push(c)}}),a.$search.set(k)}},this.clearSelectionHighlight=function(a){!a.session.$selectionOccurrences||(a.session.$selectionOccurrences.forEach(function(b){a.session.removeMarker(b)}),a.session.$selectionOccurrences=[])},this.createModeDelegates=function(a){if(!!this.$embeds){this.$modes={};for(var b=0;b1&&(m=g.slice(n+2,n+1+e[n].len)),typeof l.token=="function"?k=l.token.apply(this,m):k=l.token;var o=l.next;o&&o!==c&&(c=o,d=this.rules[c],e=this.matchMappings[c],i=f.lastIndex,f=this.regExps[c],f.lastIndex=i);break}if(m[0]){typeof k=="string"&&(m=[m.join("")],k=[k]);for(var n=0;n=b&&(a.row=Math.max(0,b-1),a.column=this.getLine(b-1).length);return a},this.insert=function(a,b){if(b.length==0)return a;a=this.$clipPosition(a),this.getLength()<=1&&this.$detectNewLine(b);var c=this.$split(b),d=c.splice(0,1)[0],e=c.length==0?null:c.splice(c.length-1,1)[0];a=this.insertInLine(a,d),e!==null&&(a=this.insertNewLine(a),a=this.insertLines(a.row,c),a=this.insertInLine(a,e||""));return a},this.insertLines=function(a,b){if(b.length==0)return{row:a,column:0};var c=[a,0];c.push.apply(c,b),this.$lines.splice.apply(this.$lines,c);var d=new f(a,0,a+b.length,0),e={action:"insertLines",range:d,lines:b};this._dispatchEvent("change",{data:e});return d.end},this.insertNewLine=function(a){a=this.$clipPosition(a);var b=this.$lines[a.row]||"";this.$lines[a.row]=b.substring(0,a.column),this.$lines.splice(a.row+1,0,b.substring(a.column,b.length));var c={row:a.row+1,column:0},d={action:"insertText",range:f.fromPoints(a,c),text:this.getNewLineCharacter()};this._dispatchEvent("change",{data:d});return c},this.insertInLine=function(a,b){if(b.length==0)return a;var c=this.$lines[a.row]||"";this.$lines[a.row]=c.substring(0,a.column)+b+c.substring(a.column);var d={row:a.row,column:a.column+b.length},e={action:"insertText",range:f.fromPoints(a,d),text:b};this._dispatchEvent("change",{data:e});return d},this.remove=function(a){a.start=this.$clipPosition(a.start),a.end=this.$clipPosition(a.end);if(a.isEmpty())return a.start;var b=a.start.row,c=a.end.row;if(a.isMultiLine()){var d=a.start.column==0?b:b+1,e=c-1;a.end.column>0&&this.removeInLine(c,0,a.end.column),e>=d&&this.removeLines(d,e),d!=b&&(this.removeInLine(b,a.start.column,this.getLine(b).length),this.removeNewLine(a.start.row))}else this.removeInLine(b,a.start.column,a.end.column);return a.start},this.removeInLine=function(a,b,c){if(b!=c){var d=new f(a,b,a,c),e=this.getLine(a),g=e.substring(b,c),h=e.substring(0,b)+e.substring(c,e.length);this.$lines.splice(a,1,h);var i={action:"removeText",range:d,text:g};this._dispatchEvent("change",{data:i});return d.start}},this.removeLines=function(a,b){var c=new f(a,0,b+1,0),d=this.$lines.splice(a,b-a+1),e={action:"removeLines",range:c,nl:this.getNewLineCharacter(),lines:d};this._dispatchEvent("change",{data:e});return d},this.removeNewLine=function(a){var b=this.getLine(a),c=this.getLine(a+1),d=new f(a,b.length,a+1,0),e=b+c;this.$lines.splice(a,2,e);var g={action:"removeText",range:d,text:this.getNewLineCharacter()};this._dispatchEvent("change",{data:g})},this.replace=function(a,b){if(b.length==0&&a.isEmpty())return a.start;if(b==this.getTextRange(a))return a.end;this.remove(a);if(b)var c=this.insert(a.start,b);else c=a.start;return c},this.applyDeltas=function(a){for(var b=0;b=0;b--){var c=a[b],d=f.fromPoints(c.range.start,c.range.end);c.action=="insertLines"?this.removeLines(d.start.row,d.end.row-1):c.action=="insertText"?this.remove(d):c.action=="removeLines"?this.insertLines(d.start.row,c.lines):c.action=="removeText"&&this.insert(d.start,c.text)}}}).call(h.prototype),b.Document=h}),define("ace/anchor",["require","exports","module","pilot/oop","pilot/event_emitter"],function(a,b,c){var d=a("pilot/oop"),e=a("pilot/event_emitter").EventEmitter,f=b.Anchor=function(a,b,c){this.document=a,typeof c=="undefined"?this.setPosition(b.row,b.column):this.setPosition(b,c),this.$onChange=this.onChange.bind(this),a.on("change",this.$onChange)};(function(){d.implement(this,e),this.getPosition=function(){return this.$clipPositionToDocument(this.row,this.column)},this.getDocument=function(){return this.document},this.onChange=function(a){var b=a.data,c=b.range;if(c.start.row!=c.end.row||c.start.row==this.row){if(c.start.row>this.row)return;if(c.start.row==this.row&&c.start.column>this.column)return;var d=this.row,e=this.column;b.action==="insertText"?c.start.row===d&&c.start.column<=e?c.start.row===c.end.row?e+=c.end.column-c.start.column:(e-=c.start.column,d+=c.end.row-c.start.row):c.start.row!==c.end.row&&c.start.row=e?e=c.start.column:e=Math.max(0,e-(c.end.column-c.start.column)):c.start.row!==c.end.row&&c.start.row=this.document.getLength()?(c.row=Math.max(0,this.document.getLength()-1),c.column=this.document.getLine(c.row).length):a<0?(c.row=0,c.column=0):(c.row=a,c.column=Math.min(this.document.getLine(c.row).length,Math.max(0,b))),b<0&&(c.column=0);return c}}).call(f.prototype)}),define("ace/background_tokenizer",["require","exports","module","pilot/oop","pilot/event_emitter"],function(a,b,c){var d=a("pilot/oop"),e=a("pilot/event_emitter").EventEmitter,f=function(a,b){this.running=!1,this.lines=[],this.currentLine=0,this.tokenizer=a;var c=this;this.$worker=function(){if(!!c.running){var a=new Date,b=c.currentLine,d=c.doc,e=0,f=d.getLength();while(c.currentLine20){c.fireUpdateEvent(b,c.currentLine-1),c.running=setTimeout(c.$worker,20);return}}c.running=!1,c.fireUpdateEvent(b,f-1)}}};(function(){d.implement(this,e),this.setTokenizer=function(a){this.tokenizer=a,this.lines=[],this.start(0)},this.setDocument=function(a){this.doc=a,this.lines=[],this.stop()},this.fireUpdateEvent=function(a,b){var c={first:a,last:b};this._dispatchEvent("update",{data:c})},this.start=function(a){this.currentLine=Math.min(a||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(a,b){return this.$tokenizeRows(a,b)},this.getState=function(a){return this.$tokenizeRows(a,a)[0].state},this.$tokenizeRows=function(a,b){if(!this.doc)return[];var c=[],d="start",e=!1;a>0&&this.lines[a-1]?(d=this.lines[a-1].state,e=!0):a==0?(d="start",e=!0):this.lines.length>0&&(d=this.lines[this.lines.length-1].state);var f=this.doc.getLines(a,b);for(var g=a;g<=b;g++)if(!this.lines[g]){var h=this.tokenizer.getLineTokens(f[g-a]||"",d),d=h.state;c.push(h),e&&(this.lines[g]=h)}else{var h=this.lines[g];d=h.state,c.push(h)}return c}}).call(f.prototype),b.BackgroundTokenizer=f}),define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold"],function(a,b,c){function g(){this.getFoldAt=function(a,b,c){var d=this.getFoldLine(a);if(!d)return null;var e=d.folds;for(var f=0;f=a)return e;if(e.end.row>a)return null}return null},this.getNextFold=function(a,b){var c=this.$foldData,d,e=0;b&&(e=c.indexOf(b)),e==-1&&(e=0);for(e;e=a)return f}return null},this.getFoldedRowCount=function(a,b){var c=this.$foldData,d=b-a+1;for(var e=0;e=b){h=a?d-=b-h:d=0);break}g>=a&&(h>=a?d-=g-h:d-=g-a+1)}return d},this.$addFoldLine=function(a){this.$foldData.push(a),this.$foldData.sort(function(a,b){return a.start.row-b.start.row});return a},this.addFold=function(a,b){var c=this.$foldData,d=!1;if(a instanceof f)var g=a;else g=new f(b,a);var h=g.start.row,i=g.start.column,j=g.end.row,k=g.end.column;if(g.placeholder.length<2)throw"Placeholder has to be at least 2 characters";if(h==j&&k-i<2)throw"The range has to be at least 2 characters width";var l=this.getFoldAt(h,i,1);if(l&&l.range.isEnd(j,k)&&l.range.isStart(h,i))return g;l=this.getFoldAt(h,i,1);if(l&&!l.range.isStart(h,i))throw"A fold can't start inside of an already existing fold";l=this.getFoldAt(j,k,-1);if(l&&!l.range.isEnd(j,k))throw"A fold can't end inside of an already existing fold";if(j>=this.doc.getLength())throw"End of fold is outside of the document.";if(k>this.getLine(j).length||i>this.getLine(h).length)throw"End of fold is outside of the document.";var m=this.getFoldsInRange(g.range);m.length>0&&(this.removeFolds(m),g.subFolds=m);for(var n=0;nthis.endRow)throw"Can't add a fold to this FoldLine as it has no connection";this.folds.push(a),this.folds.sort(function(a,b){return-a.range.compareEnd(b.start.row,b.start.column)}),this.range.compareEnd(a.start.row,a.start.column)>0?(this.end.row=a.end.row,this.end.column=a.end.column):this.range.compareStart(a.end.row,a.end.column)<0&&(this.start.row=a.start.row,this.start.column=a.start.column)}else if(a.start.row==this.end.row)this.folds.push(a),this.end.row=a.end.row,this.end.column=a.end.column;else if(a.end.row==this.start.row)this.folds.unshift(a),this.start.row=a.start.row,this.start.column=a.start.column;else throw"Trying to add fold to FoldRow that doesn't have a matching row";a.foldLine=this},this.containsRow=function(a){return a>=this.start.row&&a<=this.end.row},this.walk=function(a,b,c){var d=0,e=this.folds,f,g,h,i=!0;b==null&&(b=this.end.row,c=this.end.column);for(var j=0;j=0;h--){var i=g[h],j=c.$rangeFromMatch(f,i.offset,i.str.length);if(d(j))return!0}})}}},this.$rangeFromMatch=function(a,b,c){return new f(a,b,a,b+c)},this.$assembleRegExp=function(){if(this.$options.regExp)var a=this.$options.needle;else a=d.escapeRegExp(this.$options.needle);this.$options.wholeWord&&(a="\\b"+a+"\\b");var b="g";this.$options.caseSensitive||(b+="i");var c=new RegExp(a,b);return c},this.$forwardLineIterator=function(a){function k(e){var f=a.getLine(e);b&&e==c.end.row&&(f=f.substring(0,c.end.column)),j&&e==d.row&&(f=f.substring(0,d.column));return f}var b=this.$options.scope==g.SELECTION,c=a.getSelection().getRange(),d=a.getSelection().getCursor(),e=b?c.start.row:0,f=b?c.start.column:0,h=b?c.end.row:a.getLength()-1,i=this.$options.wrap,j=!1;return{forEach:function(a){var b=d.row,c=k(b),g=d.column,l=!1;j=!1;while(!a(c,g,b)){if(l)return;b++,g=0;if(b>h)if(i)b=e,g=f,j=!0;else return;b==d.row&&(l=!0),c=k(b)}}}},this.$backwardLineIterator=function(a){var b=this.$options.scope==g.SELECTION,c=a.getSelection().getRange(),d=b?c.end:c.start,e=b?c.start.row:0,f=b?c.start.column:0,h=b?c.end.row:a.getLength()-1,i=this.$options.wrap;return{forEach:function(g){var j=d.row,k=a.getLine(j).substring(0,d.column),l=0,m=!1,n=!1;while(!g(k,l,j)){if(m)return;j--,l=0;if(j0},this.hasRedo=function(){return this.$redoStack.length>0}}).call(d.prototype),b.UndoManager=d}),define("ace/virtual_renderer",["require","exports","module","pilot/oop","pilot/dom","pilot/event","pilot/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/renderloop","pilot/event_emitter","text/ace/css/editor.css"],function(a,b,c){var d=a("pilot/oop"),e=a("pilot/dom"),f=a("pilot/event"),g=a("pilot/useragent"),h=a("ace/layer/gutter").Gutter,i=a("ace/layer/marker").Marker,j=a("ace/layer/text").Text,k=a("ace/layer/cursor").Cursor,l=a("ace/scrollbar").ScrollBar,m=a("ace/renderloop").RenderLoop,n=a("pilot/event_emitter").EventEmitter,o=a("text/ace/css/editor.css");e.importCssString(o);var p=function(a,b){this.container=a,e.addCssClass(this.container,"ace_editor"),this.setTheme(b),this.$gutter=e.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.scroller=e.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=e.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.$gutterLayer=new h(this.$gutter),this.$markerBack=new i(this.content);var c=this.$textLayer=new j(this.content);this.canvas=c.element,this.$markerFront=new i(this.content),this.characterWidth=c.getCharacterWidth(),this.lineHeight=c.getLineHeight(),this.$cursorLayer=new k(this.content),this.$cursorPadding=8,this.$horizScroll=!0,this.$horizScrollAlwaysVisible=!0,this.scrollBar=new l(a),this.scrollBar.addEventListener("scroll",this.onScroll.bind(this)),this.scrollTop=0,this.cursorPos={row:0,column:0};var d=this;this.$textLayer.addEventListener("changeCharaterSize",function(){d.characterWidth=c.getCharacterWidth(),d.lineHeight=c.getLineHeight(),d.$updatePrintMargin(),d.onResize(!0),d.$loop.schedule(d.CHANGE_FULL)}),f.addListener(this.$gutter,"click",this.$onGutterClick.bind(this)),f.addListener(this.$gutter,"dblclick",this.$onGutterClick.bind(this)),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 m(this.$renderChanges.bind(this)),this.$loop.schedule(this.CHANGE_FULL),this.setPadding(4),this.$updatePrintMargin()};(function(){this.showGutter=!0,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,d.implement(this,n),this.setSession=function(a){this.session=a,this.$cursorLayer.setSession(a),this.$markerBack.setSession(a),this.$markerFront.setSession(a),this.$gutterLayer.setSession(a),this.$textLayer.setSession(a),this.$loop.schedule(this.CHANGE_FULL)},this.updateLines=function(a,b){b===undefined&&(b=Infinity),this.$changedLines?(this.$changedLines.firstRow>a&&(this.$changedLines.firstRow=a),this.$changedLines.lastRowc.lastRow+1)){if(bc&&this.scrollToY(c),this.scrollTop+this.$size.scrollerHeightb&&this.scrollToX(b),d+this.$size.scrollerWidththis.layerConfig.width?this.$desiredScrollLeft=b+2*this.characterWidth:this.scrollToX(Math.round(b+this.characterWidth-this.$size.scrollerWidth)))}},this.getScrollTop=function(){return this.scrollTop},this.getScrollLeft=function(){return this.scroller.scrollLeft},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(a){this.scrollToY(a*this.lineHeight)},this.scrollToLine=function(a,b){var c={lineHeight:this.lineHeight},d=0;for(var e=1;eh&&(e=g.end.row+1,g=this.session.getNextFold(e),h=g?g.start.row:Infinity);if(e>f)break;var i=this.$annotations[e]||b;c.push("",e+1);var j=this.session.getRowLength(e)-1;while(j--)c.push("
¦
");c.push(""),e++}this.element=d.setInnerHtml(this.element,c.join("")),this.element.style.height=a.minHeight+"px"}}).call(e.prototype),b.Gutter=e}),define("ace/layer/marker",["require","exports","module","ace/range","pilot/dom"],function(a,b,c){var d=a("ace/range").Range,e=a("pilot/dom"),f=function(a){this.element=e.createElement("div"),this.element.className="ace_layer ace_marker-layer",a.appendChild(this.element)};(function(){this.$padding=0,this.setPadding=function(a){this.$padding=a},this.setSession=function(a){this.session=a},this.setMarkers=function(a){this.markers=a},this.update=function(a){var a=a||this.config;if(!!a){this.config=a;var b=[];for(var c in this.markers){var d=this.markers[c],f=d.range.clipRows(a.firstRow,a.lastRow);if(f.isEmpty())continue;f=f.toScreenRange(this.session);if(d.renderer){var g=this.$getTop(f.start.row,a),h=Math.round(this.$padding+f.start.column*a.characterWidth);d.renderer(b,f,h,g,a)}else f.isMultiLine()?d.type=="text"?this.drawTextMarker(b,f,d.clazz,a):this.drawMultiLineMarker(b,f,d.clazz,a,d.type):this.drawSingleLineMarker(b,f,d.clazz,a,null,d.type)}this.element=e.setInnerHtml(this.element,b.join(""))}},this.$getTop=function(a,b){return(a-b.firstRowScreen)*b.lineHeight},this.drawTextMarker=function(a,b,c,e){var f=b.start.row,g=new d(f,b.start.column,f,this.session.getScreenLastRowColumn(f));this.drawSingleLineMarker(a,g,c,e,1,"text"),f=b.end.row,g=new d(f,0,f,b.end.column),this.drawSingleLineMarker(a,g,c,e,0,"text");for(f=b.start.row+1;f"),i=this.$getTop(b.end.row,d),h=Math.round(b.end.column*d.characterWidth),a.push(""),g=(b.end.row-b.start.row-1)*d.lineHeight;g<0||(i=this.$getTop(b.start.row+1,d),h=d.width,a.push(""))},this.drawSingleLineMarker=function(a,b,c,d,e,f){var g=f==="background"?0:this.$padding,h=d.lineHeight;if(f==="background")var i=d.width;else i=Math.round((b.end.column+(e||0)-b.start.column)*d.characterWidth);var j=this.$getTop(b.start.row,d),k=Math.round(g+b.start.column*d.characterWidth);a.push("")}}).call(f.prototype),b.Marker=f}),define("ace/layer/text",["require","exports","module","pilot/oop","pilot/dom","pilot/lang","pilot/useragent","pilot/event_emitter"],function(a,b,c){var d=a("pilot/oop"),e=a("pilot/dom"),f=a("pilot/lang"),g=a("pilot/useragent"),h=a("pilot/event_emitter").EventEmitter,i=function(a){this.element=e.createElement("div"),this.element.className="ace_layer ace_text-layer",this.element.style.width="auto",a.appendChild(this.element),this.$characterSize=this.$measureSizes()||{width:0,height:0},this.$pollSizeChanges()};(function(){d.implement(this,h),this.EOF_CHAR="¶",this.EOL_CHAR="¬",this.TAB_CHAR="→",this.SPACE_CHAR="·",this.$padding=0,this.setPadding=function(a){this.$padding=a,this.element.style.padding="0 "+a+"px"},this.getLineHeight=function(){return this.$characterSize.height||1},this.getCharacterWidth=function(){return this.$characterSize.width||1},this.checkForSizeChanges=function(){var a=this.$measureSizes();a&&(this.$characterSize.width!==a.width||this.$characterSize.height!==a.height)&&(this.$characterSize=a,this._dispatchEvent("changeCharaterSize",{data:a}))},this.$pollSizeChanges=function(){var a=this;this.$pollSizeChangesTimer=setInterval(function(){a.checkForSizeChanges()},500)},this.$fontStyles={fontFamily:1,fontSize:1,fontWeight:1,fontStyle:1,lineHeight:1},this.$measureSizes=function(){var a=1e3;if(!this.$measureNode){var b=this.$measureNode=e.createElement("div"),c=b.style;c.width=c.height="auto",c.left=c.top=-a*40+"px",c.visibility="hidden",c.position="absolute",c.overflow="visible",c.whiteSpace="nowrap",b.innerHTML=f.stringRepeat("Xy",a);if(document.body)document.body.appendChild(b);else{var d=this.element.parentNode;while(!e.hasCssClass(d,"ace_editor"))d=d.parentNode;d.appendChild(b)}}var c=this.$measureNode.style,g=e.computedStyle(this.element);for(var h in this.$fontStyles)c[h]=g[h];var i={height:this.$measureNode.offsetHeight,width:this.$measureNode.offsetWidth/(a*2)};return i.width==0&&i.height==0?null:i},this.setSession=function(a){this.session=a},this.showInvisibles=!1,this.setShowInvisibles=function(a){if(this.showInvisibles==a)return!1;this.showInvisibles=a;return!0},this.$tabStrings=[],this.$computeTabString=function(){var a=this.session.getTabSize(),b=this.$tabStrings=[0];for(var c=1;c"+this.TAB_CHAR+Array(c).join(" ")+""):b.push(Array(c+1).join(" "))},this.updateLines=function(a,b,c){this.$computeTabString(),(this.config.lastRow!=a.lastRow||this.config.firstRow!=a.firstRow)&&this.scrollLines(a),this.config=a;var d=Math.max(b,a.firstRow),f=Math.min(c,a.lastRow),g=this.element.childNodes,h=0;for(var i=a.firstRow;i0;d--)c.removeChild(c.firstChild);if(b.lastRow>a.lastRow)for(var d=this.session.getFoldedRowCount(a.lastRow+1,b.lastRow);d>0;d--)c.removeChild(c.lastChild);if(a.firstRowb.lastRow){var e=this.$renderLinesFragment(a,b.lastRow+1,a.lastRow);c.appendChild(e)}},this.$renderLinesFragment=function(a,b,c){var d=document.createDocumentFragment(),f=b,g=this.session.getNextFold(f),h=g?g.start.row:Infinity;for(;;){f>h&&(f=g.end.row+1,g=this.session.getNextFold(f),h=g?g.start.row:Infinity);if(f>c)break;var i=e.createElement("div"),j=[],k=this.session.getTokens(f,f);k.length==1&&this.$renderLine(j,f,k[0].tokens,!1),i.innerHTML=j.join("");var l=i.childNodes;while(l.length)d.appendChild(l[0]);f++}return d},this.update=function(a){this.$computeTabString(),this.config=a;var b=[],c=a.firstRow,d=a.lastRow,f=c,g=this.session.getNextFold(f),h=g?g.start.row:Infinity;for(;;){f>h&&(f=g.end.row+1,g=this.session.getNextFold(f),h=g?g.start.row:Infinity);if(f>d)break;var i=this.session.getTokens(f,f);i.length==1&&this.$renderLine(b,f,i[0].tokens,!1),f++}this.element=e.setInnerHtml(this.element,b.join(""))},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(a,b,c,d){var e=this,f=/\t|&|<|( +)|([\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000])|[\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,h=function(a,c,d,f,h){if(a.charCodeAt(0)==32)return Array(a.length+1).join(" ");if(a=="\t"){var i=e.session.getScreenTabSize(b+f);b+=i-1;return e.$tabStrings[i]}if(a=="&")return g.isOldGecko?"&":"&";if(a=="<")return"<";if(a.match(/[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/)){if(e.showInvisibles){var j=Array(a.length+1).join(e.SPACE_CHAR);return""+j+""}return" "}b+=1;return""+a+""},i=d.replace(f,h);if(!this.$textToken[c.type]){var j="ace_"+c.type.replace(/\./g," ace_");a.push("",i,"")}else a.push(i);return b+d.length},this.$renderLineCore=function(a,b,c,d,e){var f=0,g=0,h,i=this.config.characterWidth,j=0,k=this;!d||d.length==0?h=Number.MAX_VALUE:h=d[0],e||a.push("");for(var l=0;l=h)j=k.$renderToken(a,j,m,n.substring(0,h-f)),n=n.substring(h-f),f=h,e||a.push("
",""),g++,j=0,h=d[g]||Number.MAX_VALUE;n.length!=0&&(f+=n.length,j=k.$renderToken(a,j,m,n))}}this.showInvisibles&&(b!==this.session.getLength()-1?a.push(""+this.EOL_CHAR+""):a.push(""+this.EOF_CHAR+"")),a.push("
")},this.$renderLine=function(a,b,c,d){if(!this.session.isRowFolded(b)){var e=this.session.getRowSplitData(b);this.$renderLineCore(a,b,c,e,d)}else this.$renderFoldLine(a,b,c,d)},this.$renderFoldLine=function(a,b,c,d){function h(a,b,c){var d=0,e=0;while(e+a[d].value.lengthc-b&&(f=f.substring(0,c-b)),g.push({type:a[d].type,value:f}),e=b+f.length,d+=1}while(ec&&(f=f.substring(0,c-e)),g.push({type:a[d].type,value:f}),e+=f.length,d+=1}}var e=this.session,f=e.getFoldLine(b),g=[];f.walk(function(a,b,d,e,f){a?g.push({type:"fold",value:a}):(f&&(c=this.session.getTokens(b,b)[0].tokens),c.length!=0&&h(c,e,d))}.bind(this),f.end.row,this.session.getLine(f.end.row).length);var i=this.session.$useWrapMode?this.session.$wrapData[b]:null;this.$renderLineCore(a,b,g,i,d)},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(i.prototype),b.Text=i}),define("ace/layer/cursor",["require","exports","module","pilot/dom"],function(a,b,c){var d=a("pilot/dom"),e=function(a){this.element=d.createElement("div"),this.element.className="ace_layer ace_cursor-layer",a.appendChild(this.element),this.cursor=d.createElement("div"),this.cursor.className="ace_cursor ace_hidden",this.element.appendChild(this.cursor),this.isVisible=!1};(function(){this.$padding=0,this.setPadding=function(a){this.$padding=a},this.setSession=function(a){this.session=a},this.hideCursor=function(){this.isVisible=!1,d.addCssClass(this.cursor,"ace_hidden"),clearInterval(this.blinkId)},this.showCursor=function(){this.isVisible=!0,d.removeCssClass(this.cursor,"ace_hidden"),this.cursor.style.visibility="visible",this.restartTimer()},this.restartTimer=function(){clearInterval(this.blinkId);if(!!this.isVisible){var a=this.cursor;this.blinkId=setInterval(function(){a.style.visibility="hidden",setTimeout(function(){a.style.visibility="visible"},400)},1e3)}},this.getPixelPosition=function(a){if(!this.config||!this.session)return{left:0,top:0};var b=this.session.selection.getCursor(),c=this.session.documentToScreenPosition(b),d=Math.round(this.$padding+c.column*this.config.characterWidth),e=(c.row-(a?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:d,top:e}},this.update=function(a){this.config=a,this.pixelPos=this.getPixelPosition(!0),this.cursor.style.left=this.pixelPos.left+"px",this.cursor.style.top=this.pixelPos.top+"px",this.cursor.style.width=a.characterWidth+"px",this.cursor.style.height=a.lineHeight+"px";var b=this.session.getOverwrite();b!=this.overwrite&&(this.overwrite=b,b?d.addCssClass(this.cursor,"ace_overwrite"):d.removeCssClass(this.cursor,"ace_overwrite")),this.restartTimer()},this.destroy=function(){clearInterval(this.blinkId)}}).call(e.prototype),b.Cursor=e}),define("ace/scrollbar",["require","exports","module","pilot/oop","pilot/dom","pilot/event","pilot/event_emitter"],function(a,b,c){var d=a("pilot/oop"),e=a("pilot/dom"),f=a("pilot/event"),g=a("pilot/event_emitter").EventEmitter,h=function(a){this.element=e.createElement("div"),this.element.className="ace_sb",this.inner=e.createElement("div"),this.element.appendChild(this.inner),a.appendChild(this.element),this.width=e.scrollbarWidth(),this.element.style.width=(this.width||15)+"px",f.addListener(this.element,"scroll",this.onScroll.bind(this))};(function(){d.implement(this,g),this.onScroll=function(){this._dispatchEvent("scroll",{data:this.element.scrollTop})},this.getWidth=function(){return this.width},this.setHeight=function(a){this.element.style.height=a+"px"},this.setInnerHeight=function(a){this.inner.style.height=a+"px"},this.setScrollTop=function(a){this.element.scrollTop=a}}).call(h.prototype),b.ScrollBar=h}),define("ace/renderloop",["require","exports","module","pilot/event"],function(a,b,c){var d=a("pilot/event"),e=function(a){this.onRender=a,this.pending=!1,this.changes=0};(function(){this.schedule=function(a){this.changes=this.changes|a;if(!this.pending){this.pending=!0;var b=this;this.setTimeoutZero(function(){b.pending=!1;var a=b.changes;b.changes=0,b.onRender(a)})}},this.setTimeoutZero=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame,this.setTimeoutZero?this.setTimeoutZero=this.setTimeoutZero.bind(window):window.postMessage?(this.messageName="zero-timeout-message",this.setTimeoutZero=function(a){if(!this.attached){var b=this;d.addListener(window,"message",function(a){b.callback&&a.data==b.messageName&&(d.stopPropagation(a),b.callback())}),this.attached=!0}this.callback=a,window.postMessage(this.messageName,"*")}):this.setTimeoutZero=function(a){setTimeout(a,0)}}).call(e.prototype),b.RenderLoop=e}),define("ace/theme/textmate",["require","exports","module","pilot/dom"],function(a,b,c){var d=a("pilot/dom"),e=".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 width: 50px;\n background: #e8e8e8;\n color: #333;\n overflow : hidden;\n}\n\n.ace-tm .ace_gutter-layer {\n width: 100%;\n text-align: right;\n}\n\n.ace-tm .ace_gutter-layer .ace_gutter-cell {\n padding-right: 6px;\n}\n\n.ace-tm .ace_print_margin {\n width: 1px;\n background: #e8e8e8;\n}\n\n.ace-tm .ace_text-layer {\n cursor: text;\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_keyword {\n color: blue;\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: rgb(153, 0, 0);\n color: white;\n}\n\n.ace-tm .ace_line .ace_fold {\n background-color: #E4E4E4;\n border-radius: 3px;\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_marker-layer .ace_selection {\n background: rgb(181, 213, 255);\n}\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_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_string.ace_regex {\n color: rgb(255, 0, 0)\n}";d.importCssString(e),b.cssClass="ace-tm"}),define("pilot/environment",["require","exports","module","pilot/settings"],function(a,b,c){function e(){return{settings:d}}var d=a("pilot/settings").settings;b.create=e}),define("text/cockpit/ui/cli_view.css",[],"#cockpitInput { padding-left: 16px; }.cptOutput { overflow: auto; position: absolute; z-index: 999; display: none; }.cptCompletion { padding: 0; position: absolute; z-index: -1000; }.cptCompletion.VALID { background: #FFF; }.cptCompletion.INCOMPLETE { background: #DDD; }.cptCompletion.INVALID { background: #DDD; }.cptCompletion span { color: #FFF; }.cptCompletion span.INCOMPLETE { color: #DDD; border-bottom: 2px dotted #F80; }.cptCompletion span.INVALID { color: #DDD; border-bottom: 2px dotted #F00; }span.cptPrompt { color: #66F; font-weight: bold; }.cptHints { color: #000; position: absolute; border: 1px solid rgba(230, 230, 230, 0.8); background: rgba(250, 250, 250, 0.8); -moz-border-radius-topleft: 10px; -moz-border-radius-topright: 10px; border-top-left-radius: 10px; border-top-right-radius: 10px; z-index: 1000; padding: 8px; display: none;}.cptFocusPopup { display: block; }.cptFocusPopup.cptNoPopup { display: none; }.cptHints ul { margin: 0; padding: 0 15px; }.cptGt { font-weight: bold; font-size: 120%; }"),define("text/cockpit/ui/request_view.css",[],".cptRowIn { display: box; display: -moz-box; display: -webkit-box; box-orient: horizontal; -moz-box-orient: horizontal; -webkit-box-orient: horizontal; box-align: center; -moz-box-align: center; -webkit-box-align: center; color: #333; background-color: #EEE; width: 100%; font-family: consolas, courier, monospace;}.cptRowIn > * { padding-left: 2px; padding-right: 2px; }.cptRowIn > img { cursor: pointer; }.cptHover { display: none; }.cptRowIn:hover > .cptHover { display: block; }.cptRowIn:hover > .cptHover.cptHidden { display: none; }.cptOutTyped { box-flex: 1; -moz-box-flex: 1; -webkit-box-flex: 1; font-weight: bold; color: #000; font-size: 120%;}.cptRowOutput { padding-left: 10px; line-height: 1.2em; }.cptRowOutput strong,.cptRowOutput b,.cptRowOutput th,.cptRowOutput h1,.cptRowOutput h2,.cptRowOutput h3 { color: #000; }.cptRowOutput a { font-weight: bold; color: #666; text-decoration: none; }.cptRowOutput a: hover { text-decoration: underline; cursor: pointer; }.cptRowOutput input[type=password],.cptRowOutput input[type=text],.cptRowOutput textarea { color: #000; font-size: 120%; background: transparent; padding: 3px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;}.cptRowOutput table,.cptRowOutput td,.cptRowOutput th { border: 0; padding: 0 2px; }.cptRowOutput .right { text-align: right; }"),define("text/ace/css/editor.css",[],'.ace_editor { position: absolute; overflow: hidden; font-family: Monaco, "Menlo", "Courier New", monospace; font-size: 12px;}.ace_scroller { position: absolute; overflow-x: scroll; overflow-y: hidden;}.ace_content { position: absolute; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;}.ace_composition { position: absolute; background: #555; color: #DDD; z-index: 4;}.ace_gutter { position: absolute; overflow-x: hidden; overflow-y: hidden; height: 100%;}.ace_gutter-cell.ace_error { background-image: url("data:image/gif,GIF89a%10%00%10%00%D5%00%00%F5or%F5%87%88%F5nr%F4ns%EBmq%F5z%7F%DDJT%DEKS%DFOW%F1Yc%F2ah%CE(7%CE)8%D18E%DD%40M%F2KZ%EBU%60%F4%60m%DCir%C8%16(%C8%19*%CE%255%F1%3FR%F1%3FS%E6%AB%B5%CA%5DI%CEn%5E%F7%A2%9A%C9G%3E%E0a%5B%F7%89%85%F5yy%F6%82%80%ED%82%80%FF%BF%BF%E3%C4%C4%FF%FF%FF%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%25%00%2C%00%00%00%00%10%00%10%00%00%06p%C0%92pH%2C%1A%8F%C8%D2H%93%E1d4%23%E4%88%D3%09mB%1DN%B48%F5%90%40%60%92G%5B%94%20%3E%22%D2%87%24%FA%20%24%C5%06A%00%20%B1%07%02B%A38%89X.v%17%82%11%13q%10%0Fi%24%0F%8B%10%7BD%12%0Ei%09%92%09%0EpD%18%15%24%0A%9Ci%05%0C%18F%18%0B%07%04%01%04%06%A0H%18%12%0D%14%0D%12%A1I%B3%B4%B5IA%00%3B"); background-repeat: no-repeat; background-position: 4px center;}.ace_gutter-cell.ace_warning { background-image: url("data:image/gif,GIF89a%10%00%10%00%D5%00%00%FF%DBr%FF%DE%81%FF%E2%8D%FF%E2%8F%FF%E4%96%FF%E3%97%FF%E5%9D%FF%E6%9E%FF%EE%C1%FF%C8Z%FF%CDk%FF%D0s%FF%D4%81%FF%D5%82%FF%D5%83%FF%DC%97%FF%DE%9D%FF%E7%B8%FF%CCl%7BQ%13%80U%15%82W%16%81U%16%89%5B%18%87%5B%18%8C%5E%1A%94d%1D%C5%83-%C9%87%2F%C6%84.%C6%85.%CD%8B2%C9%871%CB%8A3%CD%8B5%DC%98%3F%DF%9BB%E0%9CC%E1%A5U%CB%871%CF%8B5%D1%8D6%DB%97%40%DF%9AB%DD%99B%E3%B0p%E7%CC%AE%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%2F%00%2C%00%00%00%00%10%00%10%00%00%06a%C0%97pH%2C%1A%8FH%A1%ABTr%25%87%2B%04%82%F4%7C%B9X%91%08%CB%99%1C!%26%13%84*iJ9(%15G%CA%84%14%01%1A%97%0C%03%80%3A%9A%3E%81%84%3E%11%08%B1%8B%20%02%12%0F%18%1A%0F%0A%03\'F%1C%04%0B%10%16%18%10%0B%05%1CF%1D-%06%07%9A%9A-%1EG%1B%A0%A1%A0U%A4%A5%A6BA%00%3B"); background-repeat: no-repeat; background-position: 4px center;}.ace_editor .ace_sb { position: absolute; overflow-x: hidden; overflow-y: scroll; right: 0;}.ace_editor .ace_sb div { position: absolute; width: 1px; left: 0;}.ace_editor .ace_print_margin_layer { z-index: 0; position: absolute; overflow: hidden; margin: 0; left: 0; height: 100%; width: 100%;}.ace_editor .ace_print_margin { position: absolute; height: 100%;}.ace_editor textarea { position: fixed; z-index: -1; width: 10px; height: 30px; opacity: 0; background: transparent; appearance: none; -moz-appearance: none; border: none; resize: none; outline: none; overflow: hidden;}.ace_layer { z-index: 1; position: absolute; overflow: hidden; white-space: nowrap; height: 100%; width: 100%;}.ace_text-layer { color: black;}.ace_cjk { display: inline-block; text-align: center;}.ace_cursor-layer { z-index: 4; cursor: text; /* setting pointer-events: none; here will break mouse wheel scrolling in Safari */}.ace_cursor { z-index: 4; position: absolute;}.ace_cursor.ace_hidden { opacity: 0.2;}.ace_line { white-space: nowrap;}.ace_marker-layer { cursor: text; pointer-events: none;}.ace_marker-layer .ace_step { position: absolute; z-index: 3;}.ace_marker-layer .ace_selection { position: absolute; z-index: 4;}.ace_marker-layer .ace_bracket { position: absolute; z-index: 5;}.ace_marker-layer .ace_active_line { position: absolute; z-index: 2;}.ace_marker-layer .ace_selected_word { position: absolute; z-index: 6; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;}.ace_line .ace_fold { cursor: pointer;}.ace_dragging .ace_marker-layer, .ace_dragging .ace_text-layer { cursor: move;}'),define("text/build/demo/styles.css",[],"html { height: 100%; width: 100%; overflow: hidden;}body { overflow: hidden; margin: 0; padding: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif, Tahoma, Verdana, sans-serif; font-size: 12px; background: rgb(14, 98, 165); color: white;}#logo { padding: 15px; margin-left: 65px;}#editor { position: absolute; top: 0px; left: 280px; bottom: 0px; right: 0px; background: white;}#controls { padding: 5px;}#controls td { text-align: right;}#controls td + td { text-align: left;}#cockpitInput { position: absolute; left: 280px; right: 0px; bottom: 0; border: none; outline: none; font-family: consolas, courier, monospace; font-size: 120%;}#cockpitOutput { padding: 10px; margin: 0 15px; border: 1px solid #AAA; -moz-border-radius-topleft: 10px; -moz-border-radius-topright: 10px; border-top-left-radius: 4px; border-top-right-radius: 4px; background: #DDD; color: #000;}"),define("text/build_support/style.css",[],"body { margin:0; padding:0; background-color:#e6f5fc; }H2, H3, H4 { font-family:Trebuchet MS; font-weight:bold; margin:0; padding:0;}H2 { font-size:28px; color:#263842; padding-bottom:6px;}H3 { font-family:Trebuchet MS; font-weight:bold; font-size:22px; color:#253741; margin-top:43px; margin-bottom:8px;}H4 { font-family:Trebuchet MS; font-weight:bold; font-size:21px; color:#222222; margin-bottom:4px;}P { padding:13px 0; margin:0; line-height:22px;}UL{ line-height : 22px;}PRE{ background : #333; color : white; padding : 10px;}#header { height : 227px; position:relative; overflow:hidden; background: url(images/background.png) repeat-x 0 0; border-bottom:1px solid #c9e8fa; }#header .content .signature { font-family:Trebuchet MS; font-size:11px; color:#ebe4d6; position:absolute; bottom:5px; right:42px; letter-spacing : 1px;}.content { width:970px; position:relative; overflow:hidden; margin:0 auto;}#header .content { height:184px; margin-top:22px;}#header .content .logo { width : 282px; height : 184px; background:url(images/logo.png) no-repeat 0 0; position:absolute; top:0; left:0;}#header .content .title { width : 605px; height : 58px; background:url(images/ace.png) no-repeat 0 0; position:absolute; top:98px; left:329px;}#wrapper { background:url(images/body_background.png) repeat-x 0 0; min-height:250px;}#wrapper .content { font-family:Arial; font-size:14px; color:#222222; width:1000px;}#wrapper .content .column1 { position:relative; overflow:hidden; float:left; width:315px; margin-right:31px;}#wrapper .content .column2 { position:relative; overflow:hidden; float:left; width:600px; padding-top:47px;}.fork_on_github { width:310px; height:80px; background:url(images/fork_on_github.png) no-repeat 0 0; position:relative; overflow:hidden; margin-top:49px; cursor:pointer;}.fork_on_github:hover { background-position:0 -80px;}.divider { height:3px; background-color:#bedaea; margin-bottom:3px;}.menu { padding:23px 0 0 24px;}UL.content-list { padding:15px; margin:0;}UL.menu-list { padding:0; margin:0 0 20px 0; list-style-type:none; line-height : 16px;}UL.menu-list LI { color:#2557b4; font-family:Trebuchet MS; font-size:14px; padding:7px 0; border-bottom:1px dotted #d6e2e7;}UL.menu-list LI:last-child { border-bottom:0;}A { color:#2557b4; text-decoration:none;}A:hover { text-decoration:underline;}P#first{ background : rgba(255,255,255,0.5); padding : 20px; font-size : 16px; line-height : 24px; margin : 0 0 20px 0;}#footer { height:40px; position:relative; overflow:hidden; background:url(images/bottombar.png) repeat-x 0 0; position:relative; margin-top:40px;}UL.menu-footer { padding:0; margin:8px 11px 0 0; list-style-type:none; float:right;}UL.menu-footer LI { color:white; font-family:Arial; font-size:12px; display:inline-block; margin:0 1px;}UL.menu-footer LI A { color:#8dd0ff; text-decoration:none;}UL.menu-footer LI A:hover { text-decoration:underline;}"),define("text/demo/styles.css",[],"html { height: 100%; width: 100%; overflow: hidden;}body { overflow: hidden; margin: 0; padding: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif, Tahoma, Verdana, sans-serif; font-size: 12px; background: rgb(14, 98, 165); color: white;}#logo { padding: 15px; margin-left: 65px;}#editor { position: absolute; top: 0px; left: 280px; bottom: 0px; right: 0px; background: white;}#controls { padding: 5px;}#controls td { text-align: right;}#controls td + td { text-align: left;}#cockpitInput { position: absolute; left: 280px; right: 0px; bottom: 0; border: none; outline: none; font-family: consolas, courier, monospace; font-size: 120%;}#cockpitOutput { padding: 10px; margin: 0 15px; border: 1px solid #AAA; -moz-border-radius-topleft: 10px; -moz-border-radius-topright: 10px; border-top-left-radius: 4px; border-top-right-radius: 4px; background: #DDD; color: #000;}"),define("text/deps/csslint/demos/demo.css",[],'@charset "UTF-8";@import url("booya.css") print,screen;@import "whatup.css" screen;@import "wicked.css";@namespace "http://www.w3.org/1999/xhtml";@namespace svg "http://www.w3.org/2000/svg";li.inline #foo { background: url("something.png"); display: inline; padding-left: 3px; padding-right: 7px; border-right: 1px dotted #066;}li.last.first { display: inline; padding-left: 3px !important; padding-right: 3px; border-right: 0px;}@media print { li.inline { color: black; }@charset "UTF-8"; @page { margin: 10%; counter-increment: page; @top-center { font-family: sans-serif; font-weight: bold; font-size: 2em; content: counter(page); }}'),define("text/deps/requirejs/dist/ie.css",[],"body .sect { display: none;}#content ul.index { list-style: none;}"),define("text/deps/requirejs/dist/main.css",[],'@font-face { font-family: Inconsolata; src: url("fonts/Inconsolata.ttf");}* { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; margin: 0; padding: 0;}body { font-size: 12px; line-height: 21px; background-color: #fff; font-family: "Helvetica Neue", Helvetica, Arial, Verdana, sans-serif; color: #0a0a0a;}#wrapper { margin: 0;}#grid { position: fixed; top: 0; left: 0; width: 796px; background-image: url("i/grid.png"); z-index: 100;}pre { line-height: 18px; font-size: 13px; margin: 7px 0 21px; padding: 5px 10px; overflow: auto; background-color: #fafafa; border: 1px solid #e6e6e6; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);}/* typography stuff*/.mono { font-family: "Inconsolata", Andale Mono, Monaco, Monospace;}.sans { font-family: "Helvetica Neue", Helvetica, Arial, Verdana, sans-serif;}.serif { font-family: "Georgia", Times New Roman, Times, serif;}a { color: #2e87dd; text-decoration: none;}a:hover { text-decoration: underline;}/* navigation*/#navBg { background-color: #f2f2f2; background-image: url("i/shadow.png"); background-position: right top; background-repeat: repeat-y; width: 220px; position: fixed; top: 0; left: 0; z-index: 0;}#nav { background-image: url("i/logo.png"); background-repeat: no-repeat; background-position: center 10px; width: 220px; float: left; margin: 0; padding: 150px 20px 0; font-size: 13px; text-shadow: 1px 1px #fff; position: relative; z-index: 1;}#nav .homeImageLink { position: absolute; display: block; top: 10px; left: 0; width: 220px; height: 138px;}#nav ul { list-style-type:none; padding: 0; margin: 21px 0 0 0;}#nav ul li { width: 100%;}#nav ul li.version { text-align: center; color: #4d4d4d;}#nav h1 { color: #4d4d4d; text-align: center; font-size: 15px; font-weight: normal; text-transform: uppercase; letter-spacing: 3px;}span.spacer { color: #2e87dd; margin: 0 3px 0 5px; background-image: url("i/dot.png"); background-repeat: repeat-x; background-position: left 13px;}/* icons*/span.icon { width: 16px; display: block; background-image: url("i/sprite.png"); background-repeat: no-repeat;}span.icon.home { background-position: center 5px;}span.icon.start { background-position: center -27px;}span.icon.download { background-position: center -59px;}span.icon.api { background-position: center -89px;}span.icon.optimize { background-position: center -119px;}span.icon.script { background-position: center -150px;}span.icon.question { background-position: center -182px;}span.icon.requirement { background-position: center -214px;}span.icon.history { background-position: center -247px;}span.icon.help { background-position: center -279px;}span.icon.blog { background-position: center -311px;}span.icon.twitter { background-position: center -343px;}span.icon.git { background-position: center -375px;}span.icon.fork { background-position: center -407px;}/* content*/#content { margin: 0 0 0 220px; padding: 0 20px; background-color: #fff; font-family: "Georgia", Times New Roman, Times, serif; position: relative;}#content p { padding: 7px 0; color: #333; font-size: 14px;}#content h1,#content h2,#content h3,#content h4,#content h5 { font-weight: normal; padding: 21px 0 7px;}#content h1 { font-size: 21px;}#content h2 { padding: 0 0 18px 0; margin: 0 0 7px 0; font-weight: normal; font-size: 21px; line-height: 24px; text-align: center; color: #222; background-image: url("i/arrow.png"); background-repeat: no-repeat; background-position: center bottom; font-family: "Inconsolata", Andale Mono, Monaco, Monospace; text-transform: uppercase; letter-spacing: 2px; text-shadow: 1px 1px 0 #fff;}#content h2 a { color: #222;}#content h2 a:hover,#content h3 a:hover,#content h4 a:hover { text-decoration: none;}span.sectionMark { display: block; color: #aaa; text-shadow: 1px 1px 0 #fff; font-size: 15px; font-family: "Inconsolata", Andale Mono, Monaco, Monospace;}#content h3 { font-size: 17px;}#content h4 { padding-top: 0; font-size: 15px;}#content h5 { font-size: 10px;}#content ul { list-style-type: disc;}#content ul,#content ol { /* border-left: 1px solid #333; */ color: #333; font-size: 14px; list-style-position: outside; margin: 7px 0 21px 0; /* padding: 0 0 0 28px; */}#content ul { font-style: italic;}#content ol { border: none; list-style-position: inside; padding: 0; font-family: "Georgia", Times New Roman, Times, serif;}#content ul ul,#content ol ol { border: none; padding: 0; margin: 0 0 0 28px;}#content .section { padding: 48px 0; background-image: url("i/line.png"); background-repeat: no-repeat; background-position: center bottom; width: 576px; margin: 0 auto;}#content .section .subSection { padding: 0 0 0 48px; margin: 28px 0 0 0; display: block; border-left: 2px solid #ddd;}#content .section:last-child { background-image: none;}#content .note { color: #222; background-color: #ffff99; padding: 5px 10px; margin: 7px 0; display: inline-block;}/* page directory*/#content #directory.section { background-color: #fff; width: 576px;}#content #directory.section ul ul ul { margin: 0 0 0 48px;}#content #directory.section ul ul li { background-image: url("i/sprite.png"); background-repeat: no-repeat; background-position: left -437px; padding-left: 18px; font-style: normal;}#content #directory h1 { padding: 0 0 65px 0; margin: 0 0 14px 0; font-weight: normal; font-size: 21px; text-align: center; text-transform: uppercase; letter-spacing: 2px; color: #222; background-image: url("i/arrow-x.png"); background-repeat: no-repeat; background-position: center bottom; font-family: "Inconsolata", Andale Mono, Monaco, Monospace;}#content ul.index { padding: 0; background-color: transparent; border: none; -moz-box-shadow: none; font-style: normal; font-family: "Inconsolata", Andale Mono, Monaco, Monospace;}#content ul.index li { width: 100%; font-size: 15px; color: #333; padding: 0 0 7px 0;}/* intro page specific*/#content #intro { width: 576px; margin: 0 auto; padding: 21px 0;}#content #intro p,#content #intro h1 { font-size: 19px; line-height: 28px; color: green; letter-spacing: 2px; padding: 0 0 28px 0;}#content #intro p:last-child,#content #intro h1:last-child { padding: 0;}#content #intro p a { color: green; text-decoration: underline;}/* download page*/#content h4 a.download { -webkit-border-radius: 5px; -moz-border-radius: 5px; background-color: #F2F2F2; background-image: url("i/sprite.png"), -moz-linear-gradient(center top , #FAFAFA 0%, #F2F2F2 100%); background-image: url("i/sprite.png"), -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fafafa), color-stop(100%, #f2f2f2)); background-position: 7px -58px, center center; background-repeat: no-repeat, no-repeat; border: 1px solid #CCCCCC; color: #333333; font-size: 12px; margin: 0 0 0 5px; padding: 0 10px 0 25px; text-shadow: 1px 1px 0 #FFFFFF;}/* footer*/#footer { color: #4d4d4d; padding: 65px 20px 20px; margin: 20px 0 0 220px; text-align: center; display: block; font-size: 13px; background-image: url("i/arrow-x.png"); background-repeat: no-repeat; background-position: center top; background-color: #fff;}#footer .line { display: block;}#footer .line a { color: #4d4d4d; text-decoration: underline;}/* Pygments manni style*/code {background-color: #fafafa; color: #333;}code .comment {color: green; font-style: italic}code .comment.preproc {color: #099; font-style: normal}code .comment.special {font-weight: bold}code .keyword {color: #069; font-weight: bold}code .keyword.pseudo {font-weight: normal}code .keyword.type {color: #078}code .operator {color: #555}code .operator.word {color: #000; font-weight: bold}code .name.builtin {color: #366}code .name.function {color: #c0f}code .name.class {color: #0a8; font-weight: bold}code .name.namespace {color: #0cf; font-weight: bold}code .name.exception {color: #c00; font-weight: bold}code .name.variable {color: #033}code .name.constant {color: #360}code .name.label {color: #99f}code .name.entity {color: #999; font-weight: bold}code .name.attribute {color: #309}code .name.tag {color: #309; font-weight: bold}code .name.decorator {color: #99f}code .string {color: #c30}code .string.doc {font-style: italic}code .string.interpol {color: #a00}code .string.escape {color: #c30; font-weight: bold}code .string.regex {color: #3aa}code .string.symbol {color: #fc3}code .string.other {color: #c30}code .number {color: #f60}/* webkit scroll bars*/pre::-webkit-scrollbar { width: 6px; height: 6px;}pre::-webkit-scrollbar-button:start:decrement,pre::-webkit-scrollbar-button:end:increment { display: block; height: 0; width: 0;}pre::-webkit-scrollbar-button:vertical:increment,pre::-webkit-scrollbar-button:horizontal:increment { background-color: transparent; display: block; height: 0; width: 0;}pre::-webkit-scrollbar-track-piece { -webkit-border-radius: 3px;}pre::-webkit-scrollbar-thumb:vertical { background-color: #aaa; -webkit-border-radius: 3px;}pre::-webkit-scrollbar-thumb:horizontal { background-color: #aaa; -webkit-border-radius: 3px;}/* hbox*/.hbox {\tdisplay: -webkit-box;\t-webkit-box-orient: horizontal;\t-webkit-box-align: stretch;\tdisplay: -moz-box;\t-moz-box-orient: horizontal;\t-moz-box-align: stretch;\tdisplay: box;\tbox-orient: horizontal;\tbox-align: stretch;\twidth: 100%;}.hbox > * {\t-webkit-box-flex: 0;\t-moz-box-flex: 0;\tbox-flex: 0;\tdisplay: block;}.vbox {\tdisplay: -webkit-box;\t-webkit-box-orient: vertical;\t-webkit-box-align: stretch;\tdisplay: -moz-box;\t-moz-box-orient: vertical;\t-moz-box-align: stretch;\tdisplay: box;\tbox-orient: vertical;\tbox-align: stretch;}.vbox > * {\t-webkit-box-flex: 0;\t-moz-box-flex: 0;\tbox-flex: 0;\tdisplay: block;}.spacer {\t-webkit-box-flex: 1;\t-moz-box-flex: 1;\tbox-flex: 1;}.reverse {\t-webkit-box-direction: reverse;\t-moz-box-direction: reverse;\tbox-direction: reverse;}.boxFlex0 {\t-webkit-box-flex: 0;\t-moz-box-flex: 0;\tbox-flex: 0;}.boxFlex1, .boxFlex {\t-webkit-box-flex: 1;\t-moz-box-flex: 1;\tbox-flex: 1;}.boxFlex2 {\t-webkit-box-flex: 2;\t-moz-box-flex: 2;\tbox-flex: 2;}.boxGroup1 {\t-webkit-box-flex-group: 1;\t-moz-box-flex-group: 1;\tbox-flex-group: 1;}.boxGroup2 {\t-webkit-box-flex-group: 2;\t-moz-box-flex-group: 2;\tbox-flex-group: 2;}.start {\t-webkit-box-pack: start;\t-moz-box-pack: start;\tbox-pack: start;}.end {\t-webkit-box-pack: end;\t-moz-box-pack: end;\tbox-pack: end;}.center {\t-webkit-box-pack: center;\t-moz-box-pack: center;\tbox-pack: center;}/* clearfix*/.clearfix:after {\tcontent: ".";\tdisplay: block;\tclear: both;\tvisibility: hidden;\tline-height: 0;\theight: 0;}html[xmlns] .clearfix {\tdisplay: block;}* html .clearfix {\theight: 1%;}'),define("text/lib/ace/css/editor.css",[],'.ace_editor { position: absolute; overflow: hidden; font-family: Monaco, "Menlo", "Courier New", monospace; font-size: 12px;}.ace_scroller { position: absolute; overflow-x: scroll; overflow-y: hidden;}.ace_content { position: absolute; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;}.ace_composition { position: absolute; background: #555; color: #DDD; z-index: 4;}.ace_gutter { position: absolute; overflow-x: hidden; overflow-y: hidden; height: 100%;}.ace_gutter-cell.ace_error { background-image: url("data:image/gif,GIF89a%10%00%10%00%D5%00%00%F5or%F5%87%88%F5nr%F4ns%EBmq%F5z%7F%DDJT%DEKS%DFOW%F1Yc%F2ah%CE(7%CE)8%D18E%DD%40M%F2KZ%EBU%60%F4%60m%DCir%C8%16(%C8%19*%CE%255%F1%3FR%F1%3FS%E6%AB%B5%CA%5DI%CEn%5E%F7%A2%9A%C9G%3E%E0a%5B%F7%89%85%F5yy%F6%82%80%ED%82%80%FF%BF%BF%E3%C4%C4%FF%FF%FF%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%25%00%2C%00%00%00%00%10%00%10%00%00%06p%C0%92pH%2C%1A%8F%C8%D2H%93%E1d4%23%E4%88%D3%09mB%1DN%B48%F5%90%40%60%92G%5B%94%20%3E%22%D2%87%24%FA%20%24%C5%06A%00%20%B1%07%02B%A38%89X.v%17%82%11%13q%10%0Fi%24%0F%8B%10%7BD%12%0Ei%09%92%09%0EpD%18%15%24%0A%9Ci%05%0C%18F%18%0B%07%04%01%04%06%A0H%18%12%0D%14%0D%12%A1I%B3%B4%B5IA%00%3B"); background-repeat: no-repeat; background-position: 4px center;}.ace_gutter-cell.ace_warning { background-image: url("data:image/gif,GIF89a%10%00%10%00%D5%00%00%FF%DBr%FF%DE%81%FF%E2%8D%FF%E2%8F%FF%E4%96%FF%E3%97%FF%E5%9D%FF%E6%9E%FF%EE%C1%FF%C8Z%FF%CDk%FF%D0s%FF%D4%81%FF%D5%82%FF%D5%83%FF%DC%97%FF%DE%9D%FF%E7%B8%FF%CCl%7BQ%13%80U%15%82W%16%81U%16%89%5B%18%87%5B%18%8C%5E%1A%94d%1D%C5%83-%C9%87%2F%C6%84.%C6%85.%CD%8B2%C9%871%CB%8A3%CD%8B5%DC%98%3F%DF%9BB%E0%9CC%E1%A5U%CB%871%CF%8B5%D1%8D6%DB%97%40%DF%9AB%DD%99B%E3%B0p%E7%CC%AE%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%2F%00%2C%00%00%00%00%10%00%10%00%00%06a%C0%97pH%2C%1A%8FH%A1%ABTr%25%87%2B%04%82%F4%7C%B9X%91%08%CB%99%1C!%26%13%84*iJ9(%15G%CA%84%14%01%1A%97%0C%03%80%3A%9A%3E%81%84%3E%11%08%B1%8B%20%02%12%0F%18%1A%0F%0A%03\'F%1C%04%0B%10%16%18%10%0B%05%1CF%1D-%06%07%9A%9A-%1EG%1B%A0%A1%A0U%A4%A5%A6BA%00%3B"); background-repeat: no-repeat; background-position: 4px center;}.ace_editor .ace_sb { position: absolute; overflow-x: hidden; overflow-y: scroll; right: 0;}.ace_editor .ace_sb div { position: absolute; width: 1px; left: 0;}.ace_editor .ace_print_margin_layer { z-index: 0; position: absolute; overflow: hidden; margin: 0; left: 0; height: 100%; width: 100%;}.ace_editor .ace_print_margin { position: absolute; height: 100%;}.ace_editor textarea { position: fixed; z-index: -1; width: 10px; height: 30px; opacity: 0; background: transparent; appearance: none; -moz-appearance: none; border: none; resize: none; outline: none; overflow: hidden;}.ace_layer { z-index: 1; position: absolute; overflow: hidden; white-space: nowrap; height: 100%; width: 100%;}.ace_text-layer { color: black;}.ace_cjk { display: inline-block; text-align: center;}.ace_cursor-layer { z-index: 4; cursor: text; /* setting pointer-events: none; here will break mouse wheel scrolling in Safari */}.ace_cursor { z-index: 4; position: absolute;}.ace_cursor.ace_hidden { opacity: 0.2;}.ace_line { white-space: nowrap;}.ace_marker-layer { cursor: text; pointer-events: none;}.ace_marker-layer .ace_step { position: absolute; z-index: 3;}.ace_marker-layer .ace_selection { position: absolute; z-index: 4;}.ace_marker-layer .ace_bracket { position: absolute; z-index: 5;}.ace_marker-layer .ace_active_line { position: absolute; z-index: 2;}.ace_marker-layer .ace_selected_word { position: absolute; z-index: 6; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;}.ace_line .ace_fold { cursor: pointer;}.ace_dragging .ace_marker-layer, .ace_dragging .ace_text-layer { cursor: move;}'),define("text/node_modules/uglify-js/docstyle.css",[],'html { font-family: "Lucida Grande","Trebuchet MS",sans-serif; font-size: 12pt; }body { max-width: 60em; }.title { text-align: center; }.todo { color: red; }.done { color: green; }.tag { background-color:lightblue; font-weight:normal }.target { }.timestamp { color: grey }.timestamp-kwd { color: CadetBlue }p.verse { margin-left: 3% }pre { border: 1pt solid #AEBDCC; background-color: #F3F5F7; padding: 5pt; font-family: monospace; font-size: 90%; overflow:auto;}pre.src { background-color: #eee; color: #112; border: 1px solid #000;}table { border-collapse: collapse; }td, th { vertical-align: top; }dt { font-weight: bold; }div.figure { padding: 0.5em; }div.figure p { text-align: center; }.linenr { font-size:smaller }.code-highlighted {background-color:#ffff00;}.org-info-js_info-navigation { border-style:none; }#org-info-js_console-label { font-size:10px; font-weight:bold; white-space:nowrap; }.org-info-js_search-highlight {background-color:#ffff00; color:#000000; font-weight:bold; }sup { vertical-align: baseline; position: relative; top: -0.5em; font-size: 80%;}sup a:link, sup a:visited { text-decoration: none; color: #c00;}sup a:before { content: "["; color: #999; }sup a:after { content: "]"; color: #999; }h1.title { border-bottom: 4px solid #000; padding-bottom: 5px; margin-bottom: 2em; }#postamble { color: #777; font-size: 90%; padding-top: 1em; padding-bottom: 1em; border-top: 1px solid #999; margin-top: 2em; padding-left: 2em; padding-right: 2em; text-align: right;}#postamble p { margin: 0; }#footnotes { border-top: 1px solid #000; }h1 { font-size: 200% }h2 { font-size: 175% }h3 { font-size: 150% }h4 { font-size: 125% }h1, h2, h3, h4 { font-family: "Bookman",Georgia,"Times New Roman",serif; font-weight: normal; }@media print { html { font-size: 11pt; }}'),define("text/support/cockpit/lib/cockpit/ui/cli_view.css",[],"#cockpitInput { padding-left: 16px; }.cptOutput { overflow: auto; position: absolute; z-index: 999; display: none; }.cptCompletion { padding: 0; position: absolute; z-index: -1000; }.cptCompletion.VALID { background: #FFF; }.cptCompletion.INCOMPLETE { background: #DDD; }.cptCompletion.INVALID { background: #DDD; }.cptCompletion span { color: #FFF; }.cptCompletion span.INCOMPLETE { color: #DDD; border-bottom: 2px dotted #F80; }.cptCompletion span.INVALID { color: #DDD; border-bottom: 2px dotted #F00; }span.cptPrompt { color: #66F; font-weight: bold; }.cptHints { color: #000; position: absolute; border: 1px solid rgba(230, 230, 230, 0.8); background: rgba(250, 250, 250, 0.8); -moz-border-radius-topleft: 10px; -moz-border-radius-topright: 10px; border-top-left-radius: 10px; border-top-right-radius: 10px; z-index: 1000; padding: 8px; display: none;}.cptFocusPopup { display: block; }.cptFocusPopup.cptNoPopup { display: none; }.cptHints ul { margin: 0; padding: 0 15px; }.cptGt { font-weight: bold; font-size: 120%; }"),define("text/support/cockpit/lib/cockpit/ui/request_view.css",[],".cptRowIn { display: box; display: -moz-box; display: -webkit-box; box-orient: horizontal; -moz-box-orient: horizontal; -webkit-box-orient: horizontal; box-align: center; -moz-box-align: center; -webkit-box-align: center; color: #333; background-color: #EEE; width: 100%; font-family: consolas, courier, monospace;}.cptRowIn > * { padding-left: 2px; padding-right: 2px; }.cptRowIn > img { cursor: pointer; }.cptHover { display: none; }.cptRowIn:hover > .cptHover { display: block; }.cptRowIn:hover > .cptHover.cptHidden { display: none; }.cptOutTyped { box-flex: 1; -moz-box-flex: 1; -webkit-box-flex: 1; font-weight: bold; color: #000; font-size: 120%;}.cptRowOutput { padding-left: 10px; line-height: 1.2em; }.cptRowOutput strong,.cptRowOutput b,.cptRowOutput th,.cptRowOutput h1,.cptRowOutput h2,.cptRowOutput h3 { color: #000; }.cptRowOutput a { font-weight: bold; color: #666; text-decoration: none; }.cptRowOutput a: hover { text-decoration: underline; cursor: pointer; }.cptRowOutput input[type=password],.cptRowOutput input[type=text],.cptRowOutput textarea { color: #000; font-size: 120%; background: transparent; padding: 3px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;}.cptRowOutput table,.cptRowOutput td,.cptRowOutput th { border: 0; padding: 0 2px; }.cptRowOutput .right { text-align: right; }"),define("text/tool/Theme.tmpl.css",[],".%cssClass% .ace_editor { border: 2px solid rgb(159, 159, 159);}.%cssClass% .ace_editor.ace_focus { border: 2px solid #327fbd;}.%cssClass% .ace_gutter { width: 50px; background: #e8e8e8; color: #333; overflow : hidden;}.%cssClass% .ace_gutter-layer { width: 100%; text-align: right;}.%cssClass% .ace_gutter-layer .ace_gutter-cell { padding-right: 6px;}.%cssClass% .ace_print_margin { width: 1px; background: %printMargin%;}.%cssClass% .ace_scroller { background-color: %background%;}.%cssClass% .ace_text-layer { cursor: text; color: %foreground%;}.%cssClass% .ace_cursor { border-left: 2px solid %cursor%;}.%cssClass% .ace_cursor.ace_overwrite { border-left: 0px; border-bottom: 1px solid %overwrite%;} .%cssClass% .ace_marker-layer .ace_selection { background: %selection%;}.%cssClass% .ace_marker-layer .ace_step { background: %step%;}.%cssClass% .ace_marker-layer .ace_bracket { margin: -1px 0 0 -1px; border: 1px solid %bracket%;}.%cssClass% .ace_marker-layer .ace_active_line { background: %active_line%;} .%cssClass% .ace_invisible { %invisible%}.%cssClass% .ace_keyword { %keyword%}.%cssClass% .ace_keyword.ace_operator { %keyword.operator%}.%cssClass% .ace_constant { %constant%}.%cssClass% .ace_constant.ace_language { %constant.language%}.%cssClass% .ace_constant.ace_library { %constant.library%}.%cssClass% .ace_constant.ace_numeric { %constant.numeric%}.%cssClass% .ace_invalid { %invalid%}.%cssClass% .ace_invalid.ace_illegal { %invalid.illegal%}.%cssClass% .ace_invalid.ace_deprecated { %invalid.deprecated%}.%cssClass% .ace_support { %support%}.%cssClass% .ace_support.ace_function { %support.function%}.%cssClass% .ace_function.ace_buildin { %function.buildin%}.%cssClass% .ace_string { %string%}.%cssClass% .ace_string.ace_regexp { %string.regexp%}.%cssClass% .ace_comment { %comment%}.%cssClass% .ace_comment.ace_doc { %comment.doc%}.%cssClass% .ace_comment.ace_doc.ace_tag { %comment.doc.tag%}.%cssClass% .ace_variable { %variable%}.%cssClass% .ace_variable.ace_language { %variable.language%}.%cssClass% .ace_xml_pe { %xml_pe%}.%cssClass% .ace_collab.ace_user1 { %collab.user1% }"),define("text/styles.css",[],"html { height: 100%; width: 100%; overflow: hidden;}body { overflow: hidden; margin: 0; padding: 0; height: 100%; width: 100%; font-family: Arial, Helvetica, sans-serif, Tahoma, Verdana, sans-serif; font-size: 12px; background: rgb(14, 98, 165); color: white;}#logo { padding: 15px; margin-left: 65px;}#editor { position: absolute; top: 0px; left: 280px; bottom: 0px; right: 0px; background: white;}#controls { padding: 5px;}#controls td { text-align: right;}#controls td + td { text-align: left;}#cockpitInput { position: absolute; left: 280px; right: 0px; bottom: 0; border: none; outline: none; font-family: consolas, courier, monospace; font-size: 120%;}#cockpitOutput { padding: 10px; margin: 0 15px; border: 1px solid #AAA; -moz-border-radius-topleft: 10px; -moz-border-radius-topright: 10px; border-top-left-radius: 4px; border-top-right-radius: 4px; background: #DDD; color: #000;}"),require(["ace/ace"],function(a){window.ace=a})
\ No newline at end of file
+(function(){function g(a){if(typeof requirejs!="undefined"){var e=b.define;b.define=function(a,b,c){return typeof c!="function"?e.apply(this,arguments):e(a,b,function(a,d,e){return b[2]=="module"&&(e.packaged=!0),c.apply(this,arguments)})},b.define.packaged=!0;return}var f=function(a,b){return d("",a,b)};f.packaged=!0;var g=b;a&&(b[a]||(b[a]={}),g=b[a]),g.define&&(c.original=g.define),g.define=c,g.require&&(d.original=g.require),g.require=f}var a="",b=function(){return this}(),c=function(a,b,d){if(typeof a!="string"){c.original?c.original.apply(window,arguments):(console.error("dropping module because define wasn't a string."),console.trace());return}arguments.length==2&&(d=b),c.modules||(c.modules={}),c.modules[a]=d},d=function(a,b,c){if(Object.prototype.toString.call(b)==="[object Array]"){var e=[];for(var g=0,h=b.length;g1&&h(b,"")>-1&&(i=RegExp(this.source,d.replace.call(g(this),"g","")),d.replace.call(a.slice(b.index),i,function(){for(var a=1;ab.index&&this.lastIndex--}return b},f||(RegExp.prototype.test=function(a){var b=d.exec.call(this,a);return b&&this.global&&!b[0].length&&this.lastIndex>b.index&&this.lastIndex--,!!b})}),define("ace/lib/es5-shim",["require","exports","module"],function(a,b,c){function p(a){try{return Object.defineProperty(a,"sentinel",{}),"sentinel"in a}catch(b){}}Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=g.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,h=c.apply(f,d.concat(g.call(arguments)));return h!==null&&Object(h)===h?h:f}return c.apply(b,d.concat(g.call(arguments)))};return e});var d=Function.prototype.call,e=Array.prototype,f=Object.prototype,g=e.slice,h=d.bind(f.toString),i=d.bind(f.hasOwnProperty),j,k,l,m,n;if(n=i(f,"__defineGetter__"))j=d.bind(f.__defineGetter__),k=d.bind(f.__defineSetter__),l=d.bind(f.__lookupGetter__),m=d.bind(f.__lookupSetter__);Array.isArray||(Array.isArray=function(b){return h(b)=="[object Array]"}),Array.prototype.forEach||(Array.prototype.forEach=function(b){var c=G(this),d=arguments[1],e=0,f=c.length>>>0;if(h(b)!="[object Function]")throw new TypeError;while(e>>0,e=Array(d),f=arguments[1];if(h(b)!="[object Function]")throw new TypeError;for(var g=0;g>>0,e=[],f=arguments[1];if(h(b)!="[object Function]")throw new TypeError;for(var g=0;g>>0,e=arguments[1];if(h(b)!="[object Function]")throw new TypeError;for(var f=0;f>>0,e=arguments[1];if(h(b)!="[object Function]")throw new TypeError;for(var f=0;f>>0;if(h(b)!="[object Function]")throw new TypeError;if(!d&&arguments.length==1)throw new TypeError;var e=0,f;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);for(;e>>0;if(h(b)!="[object Function]")throw new TypeError;if(!d&&arguments.length==1)throw new TypeError;var e,f=d-1;if(arguments.length>=2)e=arguments[1];else do{if(f in c){e=c[f--];break}if(--f<0)throw new TypeError}while(!0);do f in this&&(e=b.call(void 0,e,c[f],f,c));while(f--);return e}),Array.prototype.indexOf||(Array.prototype.indexOf=function(b){var c=G(this),d=c.length>>>0;if(!d)return-1;var e=0;arguments.length>1&&(e=E(arguments[1])),e=e>=0?e:Math.max(0,d+e);for(;e>>0;if(!d)return-1;var e=d-1;arguments.length>1&&(e=Math.min(e,E(arguments[1]))),e=e>=0?e:d-Math.abs(e);for(;e>=0;e--)if(e in c&&b===c[e])return e;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(b){return b.__proto__||(b.constructor?b.constructor.prototype:f)});if(!Object.getOwnPropertyDescriptor){var o="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(b,c){if(typeof b!="object"&&typeof b!="function"||b===null)throw new TypeError(o+b);if(!i(b,c))return;var d,e,g;d={enumerable:!0,configurable:!0};if(n){var h=b.__proto__;b.__proto__=f;var e=l(b,c),g=m(b,c);b.__proto__=h;if(e||g)return e&&(d.get=e),g&&(d.set=g),d}return d.value=b[c],d}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(b){return Object.keys(b)}),Object.create||(Object.create=function(b,c){var d;if(b===null)d={__proto__:null};else{if(typeof b!="object")throw new TypeError("typeof prototype["+typeof b+"] != 'object'");var e=function(){};e.prototype=b,d=new e,d.__proto__=b}return c!==void 0&&Object.defineProperties(d,c),d});if(Object.defineProperty){var q=p({}),r=typeof document=="undefined"||p(document.createElement("div"));if(!q||!r)var s=Object.defineProperty}if(!Object.defineProperty||s){var t="Property description must be an object: ",u="Object.defineProperty called on non-object: ",v="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(b,c,d){if(typeof b!="object"&&typeof b!="function"||b===null)throw new TypeError(u+b);if(typeof d!="object"&&typeof d!="function"||d===null)throw new TypeError(t+d);if(s)try{return s.call(Object,b,c,d)}catch(e){}if(i(d,"value"))if(n&&(l(b,c)||m(b,c))){var g=b.__proto__;b.__proto__=f,delete b[c],b[c]=d.value,b.__proto__=g}else b[c]=d.value;else{if(!n)throw new TypeError(v);i(d,"get")&&j(b,c,d.get),i(d,"set")&&k(b,c,d.set)}return b}}Object.defineProperties||(Object.defineProperties=function(b,c){for(var d in c)i(c,d)&&Object.defineProperty(b,d,c[d]);return b}),Object.seal||(Object.seal=function(b){return b}),Object.freeze||(Object.freeze=function(b){return b});try{Object.freeze(function(){})}catch(w){Object.freeze=function(b){return function(c){return typeof c=="function"?c:b(c)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(b){return b}),Object.isSealed||(Object.isSealed=function(b){return!1}),Object.isFrozen||(Object.isFrozen=function(b){return!1}),Object.isExtensible||(Object.isExtensible=function(b){if(Object(b)===b)throw new TypeError;var c="";while(i(b,c))c+="?";b[c]=!0;var d=i(b,c);return delete b[c],d});if(!Object.keys){var x=!0,y=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],z=y.length;for(var A in{toString:null})x=!1;Object.keys=function H(a){if(typeof a!="object"&&typeof a!="function"||a===null)throw new TypeError("Object.keys called on a non-object");var H=[];for(var b in a)i(a,b)&&H.push(b);if(x)for(var c=0,d=z;c9999?"+":"")+("00000"+Math.abs(e)).slice(0<=e&&e<=9999?-4:-6),c=b.length;while(c--)d=b[c],d<10&&(b[c]="0"+d);return e+"-"+b.slice(0,2).join("-")+"T"+b.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};Date.now||(Date.now=function(){return(new Date).getTime()}),Date.prototype.toJSON||(Date.prototype.toJSON=function(b){if(typeof this.toISOString!="function")throw new TypeError;return this.toISOString()}),Date.parse("+275760-09-13T00:00:00.000Z")!==864e13&&(Date=function(a){var b=function e(b,c,d,f,g,h,i){var j=arguments.length;if(this instanceof a){var k=j==1&&String(b)===b?new a(e.parse(b)):j>=7?new a(b,c,d,f,g,h,i):j>=6?new a(b,c,d,f,g,h):j>=5?new a(b,c,d,f,g):j>=4?new a(b,c,d,f):j>=3?new a(b,c,d):j>=2?new a(b,c):j>=1?new a(b):new a;return k.constructor=e,k}return a.apply(this,arguments)},c=new RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$");for(var d in a)b[d]=a[d];return b.now=a.now,b.UTC=a.UTC,b.prototype=a.prototype,b.prototype.constructor=b,b.parse=function(d){var e=c.exec(d);if(e){e.shift();for(var f=1;f<7;f++)e[f]=+(e[f]||(f<3?1:0)),f==1&&e[f]--;var g=+e.pop(),h=+e.pop(),i=e.pop(),j=0;if(i){if(h>23||g>59)return NaN;j=(h*60+g)*6e4*(i=="+"?-1:1)}var k=+e[0];return 0<=k&&k<=99?(e[0]=k+400,a.UTC.apply(this,e)+j-126227808e5):a.UTC.apply(this,e)+j}return a.parse.apply(this,arguments)},b}(Date));var B=" \n\f\r \u2028\u2029";if(!String.prototype.trim||B.trim()){B="["+B+"]";var C=new RegExp("^"+B+B+"*"),D=new RegExp(B+B+"*$");String.prototype.trim=function(){return String(this).replace(C,"").replace(D,"")}}var E=function(a){return a=+a,a!==a?a=0:a!==0&&a!==1/0&&a!==-Infinity&&(a=(a>0||-1)*Math.floor(Math.abs(a))),a},F="a"[0]!="a",G=function(a){if(a==null)throw new TypeError;return F&&typeof a=="string"&&a?a.split(""):Object(a)}}),define("ace/lib/dom",["require","exports","module"],function(a,b,c){"use strict";var d="http://www.w3.org/1999/xhtml";b.createElement=function(a,b){return document.createElementNS?document.createElementNS(b||d,a):document.createElement(a)},b.setText=function(a,b){a.innerText!==undefined&&(a.innerText=b),a.textContent!==undefined&&(a.textContent=b)},b.hasCssClass=function(a,b){var c=a.className.split(/\s+/g);return c.indexOf(b)!==-1},b.addCssClass=function(a,c){b.hasCssClass(a,c)||(a.className+=" "+c)},b.removeCssClass=function(a,b){var c=a.className.split(/\s+/g);for(;;){var d=c.indexOf(b);if(d==-1)break;c.splice(d,1)}a.className=c.join(" ")},b.toggleCssClass=function(a,b){var c=a.className.split(/\s+/g),d=!0;for(;;){var e=c.indexOf(b);if(e==-1)break;d=!1,c.splice(e,1)}return d&&c.push(b),a.className=c.join(" "),d},b.setCssClass=function(a,c,d){d?b.addCssClass(a,c):b.removeCssClass(a,c)},b.hasCssString=function(a,b){var c=0,d;b=b||document;if(b.createStyleSheet&&(d=b.styleSheets)){while(c5||Math.abs(a.clientY-j)>5)h=0;h==d&&(h=0,g(a));if(e)return b.preventDefault(a)};b.addListener(a,"mousedown",k),e.isOldIE&&b.addListener(a,"dblclick",k)},b.addCommandKeyListener=function(a,c){var d=b.addListener;if(e.isOldGecko||e.isOpera){var f=null;d(a,"keydown",function(a){f=a.keyCode}),d(a,"keypress",function(a){return g(c,a,f)})}else{var h=null;d(a,"keydown",function(a){return h=a.keyIdentifier||a.keyCode,g(c,a,a.keyCode)})}};if(window.postMessage){var h=1;b.nextTick=function(a,c){c=c||window;var d="zero-timeout-message-"+h;b.addListener(c,"message",function e(f){f.data==d&&(b.stopPropagation(f),b.removeListener(c,"message",e),a())}),c.postMessage(d,"*")}}else b.nextTick=function(a,b){b=b||window,window.setTimeout(a,0)}}),define("ace/lib/keys",["require","exports","module","ace/lib/oop"],function(a,b,c){"use strict";var d=a("./oop"),e=function(){var a={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:'"'}};for(var b in a.FUNCTION_KEYS){var c=a.FUNCTION_KEYS[b].toUpperCase();a[c]=parseInt(b,10)}return d.mixin(a,a.MODIFIER_KEYS),d.mixin(a,a.PRINTABLE_KEYS),d.mixin(a,a.FUNCTION_KEYS),a}();d.mixin(b,e),b.keyCodeToString=function(a){return(e[a]||String.fromCharCode(a)).toLowerCase()}}),define("ace/lib/oop",["require","exports","module"],function(a,b,c){"use strict",b.inherits=function(){var a=function(){};return function(b,c){a.prototype=c.prototype,b.super_=c.prototype,b.prototype=new a,b.prototype.constructor=b}}(),b.mixin=function(a,b){for(var c in b)a[c]=b[c]},b.implement=function(a,c){b.mixin(a,c)}}),define("ace/lib/useragent",["require","exports","module"],function(a,b,c){"use strict";var d=(navigator.platform.match(/mac|win|linux/i)||["other"])[0].toLowerCase(),e=navigator.userAgent;b.isWin=d=="win",b.isMac=d=="mac",b.isLinux=d=="linux",b.isIE=navigator.appName=="Microsoft Internet Explorer"&&parseFloat(navigator.userAgent.match(/MSIE ([0-9]+[\.0-9]+)/)[1]),b.isOldIE=b.isIE&&b.isIE<9,b.isGecko=b.isMozilla=window.controllers&&window.navigator.product==="Gecko",b.isOldGecko=b.isGecko&&parseInt((navigator.userAgent.match(/rv\:(\d+)/)||[])[1],10)<4,b.isOpera=window.opera&&Object.prototype.toString.call(window.opera)=="[object Opera]",b.isWebKit=parseFloat(e.split("WebKit/")[1])||undefined,b.isChrome=parseFloat(e.split(" Chrome/")[1])||undefined,b.isAIR=e.indexOf("AdobeAIR")>=0,b.isIPad=e.indexOf("iPad")>=0,b.isTouchPad=e.indexOf("TouchPad")>=0,b.OS={LINUX:"LINUX",MAC:"MAC",WINDOWS:"WINDOWS"},b.getOS=function(){return b.isMac?b.OS.MAC:b.isLinux?b.OS.LINUX:b.OS.WINDOWS}}),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(a,b,c){"use strict",a("./lib/fixoldbrowsers");var d=a("./lib/oop"),e=a("./lib/lang"),f=a("./lib/useragent"),g=a("./keyboard/textinput").TextInput,h=a("./mouse/mouse_handler").MouseHandler,i=a("./mouse/fold_handler").FoldHandler,j=a("./keyboard/keybinding").KeyBinding,k=a("./edit_session").EditSession,l=a("./search").Search,m=a("./range").Range,n=a("./lib/event_emitter").EventEmitter,o=a("./commands/command_manager").CommandManager,p=a("./commands/default_commands").commands,q=function(a,b){var c=a.getContainerElement();this.container=c,this.renderer=a,this.commands=new o(f.isMac?"mac":"win",p),this.textInput=new g(a.getTextAreaContainer(),this),this.renderer.textarea=this.textInput.getElement(),this.keyBinding=new j(this),f.isIPad||(this.$mouseHandler=new h(this),new i(this)),this.$blockScrolling=0,this.$search=(new l).set({wrap:!0}),this.setSession(b||new k(""))};(function(){d.implement(this,n),this.setKeyboardHandler=function(a){this.keyBinding.setKeyboardHandler(a)},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(a){if(this.session==a)return;if(this.session){var b=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 c=this.session.getSelection();c.removeEventListener("changeCursor",this.$onCursorChange),c.removeEventListener("changeSelection",this.$onSelectionChange)}this.session=a,this.$onDocumentChange=this.onDocumentChange.bind(this),a.addEventListener("change",this.$onDocumentChange),this.renderer.setSession(a),this.$onChangeMode=this.onChangeMode.bind(this),a.addEventListener("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),a.addEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.updateText.bind(this.renderer),a.addEventListener("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),a.addEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),a.addEventListener("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),a.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=a.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:a,oldSession:b})},this.getSession=function(){return this.session},this.getSelection=function(){return this.selection},this.resize=function(){this.renderer.onResize()},this.setTheme=function(a){this.renderer.setTheme(a)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(a){this.renderer.setStyle(a)},this.unsetStyle=function(a){this.renderer.unsetStyle(a)},this.setFontSize=function(a){this.container.style.fontSize=a,this.renderer.updateFontSize()},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var a=this;this.$highlightPending=!0,setTimeout(function(){a.$highlightPending=!1;var b=a.session.findMatchingBracket(a.getCursorPosition());if(b){var c=new m(b.row,b.column,b.row,b.column+1);a.session.$bracketHighlight=a.session.addMarker(c,"ace_bracket","text")}},10)},this.focus=function(){var a=this;setTimeout(function(){a.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(){this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit("focus")},this.onBlur=function(){this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit("blur")},this.$cursorChange=function(){this.renderer.updateCursor()},this.onDocumentChange=function(a){var b=a.data,c=b.range,d;c.start.row==c.end.row&&b.action!="insertLines"&&b.action!="removeLines"?d=c.end.row:d=Infinity,this.renderer.updateLines(c.start.row,d),this._emit("change",a),this.$cursorChange()},this.onTokenizerUpdate=function(a){var b=a.data;this.renderer.updateLines(b.first,b.last)},this.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},this.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},this.onCursorChange=function(){this.$cursorChange(),this.$blockScrolling||this.renderer.scrollCursorIntoView(),this.$highlightBrackets(),this.$updateHighlightActiveLine()},this.$updateHighlightActiveLine=function(){var a=this.getSession();a.$highlightLineMarker&&a.removeMarker(a.$highlightLineMarker),a.$highlightLineMarker=null;if(this.$highlightActiveLine){var b=this.getCursorPosition(),c=this.session.getFoldLine(b.row);if(this.getSelectionStyle()!="line"||!this.selection.isMultiLine()){var d;c?d=new m(c.start.row,0,c.end.row+1,0):d=new m(b.row,0,b.row+1,0),a.$highlightLineMarker=a.addMarker(d,"ace_active_line","background")}}},this.onSelectionChange=function(a){var b=this.getSession();b.$selectionMarker&&b.removeMarker(b.$selectionMarker),b.$selectionMarker=null;if(!this.selection.isEmpty()){var c=this.selection.getRange(),d=this.getSelectionStyle();b.$selectionMarker=b.addMarker(c,"ace_selection",d)}else this.$updateHighlightActiveLine();this.$highlightSelectedWord&&this.session.getMode().highlightSelection(this)},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.setBreakpoints(this.session.getBreakpoints())},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(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getCopyText=function(){var a="";return this.selection.isEmpty()||(a=this.session.getTextRange(this.getSelectionRange())),this._emit("copy",a),a},this.onCopy=function(){this.commands.exec("copy",this)},this.onCut=function(){this.commands.exec("cut",this)},this.onPaste=function(a){this._emit("paste",a),this.insert(a)},this.insert=function(a){var b=this.session,c=b.getMode(),d=this.getCursorPosition();if(this.getBehavioursEnabled()){var e=c.transformAction(b.getState(d.row),"insertion",this,b,a);e&&(a=e.text)}a=a.replace(" ",this.session.getTabString());if(!this.selection.isEmpty())d=this.session.remove(this.getSelectionRange()),this.clearSelection();else if(this.session.getOverwrite()){var f=new m.fromPoints(d,d);f.end.column+=a.length,this.session.remove(f)}this.clearSelection();var g=d.column,h=b.getState(d.row),i=c.checkOutdent(h,b.getLine(d.row),a),j=b.getLine(d.row),k=c.getNextLineIndent(h,j.slice(0,d.column),b.getTabString()),l=b.insert(d,a);e&&e.selection&&(e.selection.length==2?this.selection.setSelectionRange(new m(d.row,g+e.selection[0],d.row,g+e.selection[1])):this.selection.setSelectionRange(new m(d.row+e.selection[0],e.selection[1],d.row+e.selection[2],e.selection[3])));var h=b.getState(d.row);if(b.getDocument().isNewLine(a)){this.moveCursorTo(d.row+1,0);var n=b.getTabSize(),o=Number.MAX_VALUE;for(var p=d.row+1;p<=l.row;++p){var q=0;j=b.getLine(p);for(var r=0;r0;++r)j.charAt(r)==" "?s-=n:j.charAt(r)==" "&&(s-=1);b.remove(new m(p,0,p,r))}b.indentRows(d.row+1,l.row,k)}i&&c.autoOutdent(h,b,d.row)},this.onTextInput=function(a){this.keyBinding.onTextInput(a)},this.onCommandKey=function(a,b,c){this.keyBinding.onCommandKey(a,b,c)},this.setOverwrite=function(a){this.session.setOverwrite(a)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(a){this.$mouseHandler.setScrollSpeed(a)},this.getScrollSpeed=function(){return this.$mouseHandler.getScrollSpeed()},this.setDragDelay=function(a){this.$mouseHandler.setDragDelay(a)},this.getDragDelay=function(){return this.$mouseHandler.getDragDelay()},this.$selectionStyle="line",this.setSelectionStyle=function(a){if(this.$selectionStyle==a)return;this.$selectionStyle=a,this.onSelectionChange(),this._emit("changeSelectionStyle",{data:a})},this.getSelectionStyle=function(){return this.$selectionStyle},this.$highlightActiveLine=!0,this.setHighlightActiveLine=function(a){if(this.$highlightActiveLine==a)return;this.$highlightActiveLine=a,this.$updateHighlightActiveLine()},this.getHighlightActiveLine=function(){return this.$highlightActiveLine},this.$highlightGutterLine=!0,this.setHighlightGutterLine=function(a){if(this.$highlightGutterLine==a)return;this.renderer.setHighlightGutterLine(a)},this.getHighlightGutterLine=function(){return this.$highlightGutterLine},this.$highlightSelectedWord=!0,this.setHighlightSelectedWord=function(a){if(this.$highlightSelectedWord==a)return;this.$highlightSelectedWord=a,a?this.session.getMode().highlightSelection(this):this.session.getMode().clearSelectionHighlight(this)},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(a){this.renderer.setAnimatedScroll(a)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(a){if(this.getShowInvisibles()==a)return;this.renderer.setShowInvisibles(a)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setShowPrintMargin=function(a){this.renderer.setShowPrintMargin(a)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(a){this.renderer.setPrintMarginColumn(a)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.$readOnly=!1,this.setReadOnly=function(a){this.$readOnly=a},this.getReadOnly=function(){return this.$readOnly},this.$modeBehaviours=!0,this.setBehavioursEnabled=function(a){this.$modeBehaviours=a},this.getBehavioursEnabled=function(){return this.$modeBehaviours},this.setShowFoldWidgets=function(a){var b=this.renderer.$gutterLayer;if(b.getShowFoldWidgets()==a)return;this.renderer.$gutterLayer.setShowFoldWidgets(a),this.$showFoldWidgets=a,this.renderer.updateFull()},this.getShowFoldWidgets=function(){return this.renderer.$gutterLayer.getShowFoldWidgets()},this.setFadeFoldWidgets=function(a){this.renderer.setFadeFoldWidgets(a)},this.getFadeFoldWidgets=function(){return this.renderer.getFadeFoldWidgets()},this.remove=function(a){this.selection.isEmpty()&&(a=="left"?this.selection.selectLeft():this.selection.selectRight());var b=this.getSelectionRange();if(this.getBehavioursEnabled()){var c=this.session,d=c.getState(b.start.row),e=c.getMode().transformAction(d,"deletion",this,c,b);e&&(b=e)}this.session.remove(b),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var a=this.getSelectionRange();a.start.column==a.end.column&&a.start.row==a.end.row&&(a.end.column=0,a.end.row++),this.session.remove(a),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var a=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(a)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var a=this.getCursorPosition(),b=a.column;if(b===0)return;var c=this.session.getLine(a.row),d,e;b=this.getFirstVisibleRow()&&a<=this.getLastVisibleRow()},this.isRowFullyVisible=function(a){return a>=this.renderer.getFirstFullyVisibleRow()&&a<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(a,b){var c=this.renderer,d=this.renderer.layerConfig,e=a*Math.floor(d.height/d.lineHeight);this.$blockScrolling++,b==1?this.selection.$moveSelection(function(){this.moveCursorBy(e,0)}):b==0&&(this.selection.moveCursorBy(e,0),this.selection.clearSelection()),this.$blockScrolling--;var f=c.scrollTop;c.scrollBy(0,e*d.lineHeight),b!=null&&c.scrollCursorIntoView(null,.5),c.animateScrolling(f)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(a){this.renderer.scrollToRow(a)},this.scrollToLine=function(a,b,c,d){this.renderer.scrollToLine(a,b,c,d)},this.centerSelection=function(){var a=this.getSelectionRange(),b=Math.floor(a.start.row+(a.end.row-a.start.row)/2);this.renderer.scrollToLine(b,!0)},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(a,b){this.selection.moveCursorTo(a,b)},this.moveCursorToPosition=function(a){this.selection.moveCursorToPosition(a)},this.jumpToMatching=function(){var a=this.getCursorPosition(),b=this.session.findMatchingBracket(a);b||(a.column+=1,b=this.session.findMatchingBracket(a)),b||(a.column-=2,b=this.session.findMatchingBracket(a)),b&&(this.clearSelection(),this.moveCursorTo(b.row,b.column))},this.gotoLine=function(a,b,c){this.selection.clearSelection(),this.session.unfold({row:a-1,column:b||0}),this.$blockScrolling+=1,this.moveCursorTo(a-1,b||0),this.$blockScrolling-=1,this.isRowFullyVisible(a-1)||this.scrollToLine(a-1,!0,c)},this.navigateTo=function(a,b){this.clearSelection(),this.moveCursorTo(a,b)},this.navigateUp=function(a){this.selection.clearSelection(),a=a||1,this.selection.moveCursorBy(-a,0)},this.navigateDown=function(a){this.selection.clearSelection(),a=a||1,this.selection.moveCursorBy(a,0)},this.navigateLeft=function(a){if(!this.selection.isEmpty()){var b=this.getSelectionRange().start;this.moveCursorToPosition(b)}else{a=a||1;while(a--)this.selection.moveCursorLeft()}this.clearSelection()},this.navigateRight=function(a){if(!this.selection.isEmpty()){var b=this.getSelectionRange().end;this.moveCursorToPosition(b)}else{a=a||1;while(a--)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 a=this.renderer.scrollTop;this.selection.moveCursorFileEnd(),this.clearSelection(),this.renderer.animateScrolling(a)},this.navigateFileStart=function(){var a=this.renderer.scrollTop;this.selection.moveCursorFileStart(),this.clearSelection(),this.renderer.animateScrolling(a)},this.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},this.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},this.replace=function(a,b){b&&this.$search.set(b);var c=this.$search.find(this.session),d=0;return c?(this.$tryReplace(c,a)&&(d=1),c!==null&&(this.selection.setSelectionRange(c),this.renderer.scrollSelectionIntoView(c.start,c.end)),d):d},this.replaceAll=function(a,b){b&&this.$search.set(b);var c=this.$search.findAll(this.session),d=0;if(!c.length)return d;this.$blockScrolling+=1;var e=this.getSelectionRange();this.clearSelection(),this.selection.moveCursorTo(0,0);for(var f=c.length-1;f>=0;--f)this.$tryReplace(c[f],a)&&d++;return this.selection.setSelectionRange(e),this.$blockScrolling-=1,d},this.$tryReplace=function(a,b){var c=this.session.getTextRange(a);return b=this.$search.replace(c,b),b!==null?(a.end=this.session.replace(a,b),a):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(a,b,c){this.clearSelection(),b=b||{},b.needle=a,this.$search.set(b),this.$find(!1,c)},this.findNext=function(a,b){a=a||{},this.$search.set(a),this.$find(!1,b)},this.findPrevious=function(a,b){a=a||{},this.$search.set(a),this.$find(!0,b)},this.$find=function(a,b){this.selection.isEmpty()||this.$search.set({needle:this.session.getTextRange(this.getSelectionRange())}),typeof a!="undefined"&&this.$search.set({backwards:a});var c=this.$search.find(this.session);if(c){this.$blockScrolling+=1,this.session.unfold(c),this.selection.setSelectionRange(c),this.$blockScrolling-=1;var d=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(c.start,c.end,.5),this.renderer.animateScrolling(d)}},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy()}}).call(q.prototype),b.Editor=q}),define("ace/lib/lang",["require","exports","module"],function(a,b,c){"use strict",b.stringReverse=function(a){return a.split("").reverse().join("")},b.stringRepeat=function(a,b){return(new Array(b+1)).join(a)};var d=/^\s\s*/,e=/\s\s*$/;b.stringTrimLeft=function(a){return a.replace(d,"")},b.stringTrimRight=function(a){return a.replace(e,"")},b.copyObject=function(a){var b={};for(var c in a)b[c]=a[c];return b},b.copyArray=function(a){var b=[];for(var c=0,d=a.length;c1&&(d.charAt(0)==g?d=d.substr(1):d.charAt(d.length-1)==g&&(d=d.slice(0,-1))),d&&d!=g&&(j?b.onPaste(d):b.onTextInput(d));if(!v())return!1}}i=!1,j=!1,c.value=g,l()}function v(){return document.activeElement===c}var c=f.createElement("textarea");e.isTouchPad&&c.setAttribute("x-palm-disable-auto-cap",!0),c.setAttribute("wrap","off"),c.style.left="-10000px",c.style.position="fixed",a.insertBefore(c,a.firstChild);var g=String.fromCharCode(0);m();var h=!1,i=!1,j=!1,k="",n=function(a){setTimeout(function(){h||m(a.data)},0)},o=function(a){if(e.isOldIE&&c.value.charCodeAt(0)>128)return;setTimeout(function(){h||m()},0)},p=function(a){h=!0,b.onCompositionStart(),e.isGecko||setTimeout(q,0)},q=function(){if(!h)return;b.onCompositionUpdate(c.value)},r=function(a){h=!1,b.onCompositionEnd()},s=function(a){i=!0;var d=b.getCopyText();d?c.value=d:a.preventDefault(),l(),setTimeout(function(){m()},0)},t=function(a){i=!0;var d=b.getCopyText();d?(c.value=d,b.onCut()):a.preventDefault(),l(),setTimeout(function(){m()},0)};d.addCommandKeyListener(c,b.onCommandKey.bind(b));if(e.isOldIE){var u={13:1,27:1};d.addListener(c,"keyup",function(a){h&&(!c.value||u[a.keyCode])&&setTimeout(r,0);if((c.value.charCodeAt(0)|0)<129)return;h?q():p()})}"onpropertychange"in c&&!("oninput"in c)?d.addListener(c,"propertychange",o):d.addListener(c,"input",n),d.addListener(c,"paste",function(a){j=!0,a.clipboardData&&a.clipboardData.getData?(m(a.clipboardData.getData("text/plain")),a.preventDefault()):o()}),"onbeforecopy"in c&&typeof clipboardData!="undefined"?(d.addListener(c,"beforecopy",function(a){var c=b.getCopyText();c?clipboardData.setData("Text",c):a.preventDefault()}),d.addListener(a,"keydown",function(a){if(a.ctrlKey&&a.keyCode==88){var c=b.getCopyText();c&&(clipboardData.setData("Text",c),b.onCut()),d.preventDefault(a)}})):(d.addListener(c,"copy",s),d.addListener(c,"cut",t)),d.addListener(c,"compositionstart",p),e.isGecko&&d.addListener(c,"text",q),e.isWebKit&&d.addListener(c,"keyup",q),d.addListener(c,"compositionend",r),d.addListener(c,"blur",function(){b.onBlur()}),d.addListener(c,"focus",function(){b.onFocus(),l()}),this.focus=function(){b.onFocus(),l(),c.focus()},this.blur=function(){c.blur()},this.isFocused=v,this.getElement=function(){return c},this.onContextMenu=function(a,b){a&&(k||(k=c.style.cssText),c.style.cssText="position:fixed; z-index:1000;left:"+(a.x-2)+"px; top:"+(a.y-2)+"px;"),b&&(c.value="")},this.onContextMenuClose=function(){setTimeout(function(){k&&(c.style.cssText=k,k=""),m()},0)}};b.TextInput=g}),define("ace/mouse/mouse_handler",["require","exports","module","ace/lib/event","ace/mouse/default_handlers","ace/mouse/default_gutter_handler","ace/mouse/mouse_event"],function(a,b,c){"use strict";var d=a("../lib/event"),e=a("./default_handlers").DefaultHandlers,f=a("./default_gutter_handler").GutterHandler,g=a("./mouse_event").MouseEvent,h=function(a){this.editor=a,new e(this),new f(this),d.addListener(a.container,"mousedown",function(b){return a.focus(),d.preventDefault(b)}),d.addListener(a.container,"selectstart",function(a){return d.preventDefault(a)});var b=a.renderer.getMouseEventTarget();d.addListener(b,"mousedown",this.onMouseEvent.bind(this,"mousedown")),d.addListener(b,"click",this.onMouseEvent.bind(this,"click")),d.addListener(b,"mousemove",this.onMouseMove.bind(this,"mousemove")),d.addMultiMouseDownListener(b,0,2,500,this.onMouseEvent.bind(this,"dblclick")),d.addMultiMouseDownListener(b,0,3,600,this.onMouseEvent.bind(this,"tripleclick")),d.addMultiMouseDownListener(b,0,4,600,this.onMouseEvent.bind(this,"quadclick")),d.addMouseWheelListener(a.container,this.onMouseWheel.bind(this,"mousewheel"));var c=a.renderer.$gutter;d.addListener(c,"mousedown",this.onMouseEvent.bind(this,"guttermousedown")),d.addListener(c,"click",this.onMouseEvent.bind(this,"gutterclick")),d.addListener(c,"dblclick",this.onMouseEvent.bind(this,"gutterdblclick")),d.addListener(c,"mousemove",this.onMouseMove.bind(this,"gutter"))};(function(){this.$scrollSpeed=1,this.setScrollSpeed=function(a){this.$scrollSpeed=a},this.getScrollSpeed=function(){return this.$scrollSpeed},this.onMouseEvent=function(a,b){this.editor._emit(a,new g(b,this.editor))},this.$dragDelay=250,this.setDragDelay=function(a){this.$dragDelay=a},this.getDragDelay=function(){return this.$dragDelay},this.onMouseMove=function(a,b){var c=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;if(!c||!c.length)return;this.editor._emit(a,new g(b,this.editor))},this.onMouseWheel=function(a,b){var c=new g(b,this.editor);c.speed=this.$scrollSpeed*2,c.wheelX=b.wheelX,c.wheelY=b.wheelY,this.editor._emit(a,c)},this.setState=function(a){this.state=a},this.captureMouse=function(a,b){b&&this.setState(b),this.x=a.x,this.y=a.y;var c=this.editor.renderer.$keepTextAreaAtCursor;this.editor.renderer.$keepTextAreaAtCursor=!1;var e=this,f=function(a){e.x=a.clientX,e.y=a.clientY},g=function(a){clearInterval(i),e[e.state+"End"]&&e[e.state+"End"](a),e.$clickSelection=null,e.editor.renderer.$keepTextAreaAtCursor=c,e.editor.renderer.$moveTextAreaToCursor()},h=function(){e[e.state]&&e[e.state]()};d.capture(this.editor.container,f,g);var i=setInterval(h,20);a.preventDefault()}}).call(h.prototype),b.MouseHandler=h}),define("ace/mouse/default_handlers",["require","exports","module","ace/lib/dom","ace/lib/browser_focus"],function(a,b,c){function g(a){a.$clickSelection=null,a.browserFocus=new e;var b=a.editor;b.setDefaultHandler("mousedown",this.onMouseDown.bind(a)),b.setDefaultHandler("dblclick",this.onDoubleClick.bind(a)),b.setDefaultHandler("tripleclick",this.onTripleClick.bind(a)),b.setDefaultHandler("quadclick",this.onQuadClick.bind(a)),b.setDefaultHandler("mousewheel",this.onScroll.bind(a));var c=["select","startSelect","drag","dragEnd","dragWait","dragWaitEnd","startDrag"];c.forEach(function(b){a[b]=this[b]},this),a.selectByLines=this.extendSelectionBy.bind(a,"getLineRange"),a.selectByWords=this.extendSelectionBy.bind(a,"getWordRange")}function h(a,b,c,d){return Math.sqrt(Math.pow(c-a,2)+Math.pow(d-b,2))}"use strict";var d=a("../lib/dom"),e=a("../lib/browser_focus").BrowserFocus,f=5;(function(){this.onMouseDown=function(a){this.mousedownEvent=a;var b=a.inSelection(),c=a.getDocumentPosition(),d=this.editor,e=this;this.ev=a;var f=d.getSelectionRange(),g=f.isEmpty(),h=a.getButton();if(h!==0){g&&(d.moveCursorToPosition(c),d.selection.clearSelection()),this.moveTextarea=function(){d.textInput.onContextMenu({x:e.x,y:e.y})},this.moveTextareaEnd=d.textInput.onContextMenuClose,d.textInput.onContextMenu({x:this.x,y:this.y},g),this.captureMouse(a,"moveTextarea");return}if(b&&!d.isFocused()){d.focus();return}if(!b||this.$clickSelection||a.getShiftKey())this.startSelect(c);else if(b){var i=a.domEvent;i.ctrlKey||i.altKey?this.startDrag():(this.mousedownEvent.time=(new Date).getTime(),this.setState("dragWait"))}this.captureMouse(a)},this.startSelect=function(a){a=a||this.editor.renderer.screenToTextCoordinates(this.x,this.y),this.mousedownEvent.getShiftKey()?this.editor.selection.selectToPosition(a):this.$clickSelection||(this.editor.moveCursorToPosition(a),this.editor.selection.clearSelection()),this.setState("select")},this.select=function(){var a,b=this.editor,c=b.renderer.screenToTextCoordinates(this.x,this.y);if(this.$clickSelection){var d=this.$clickSelection.comparePoint(c);d==-1?a=this.$clickSelection.end:d==1?a=this.$clickSelection.start:(c=this.$clickSelection.end,a=this.$clickSelection.start),b.selection.setSelectionAnchor(a.row,a.column)}b.selection.selectToPosition(c),b.renderer.scrollCursorIntoView()},this.extendSelectionBy=function(a){var b,c=this.editor,d=c.renderer.screenToTextCoordinates(this.x,this.y),e=c.selection[a](d.row,d.column);if(this.$clickSelection){var f=this.$clickSelection.comparePoint(e.start),g=this.$clickSelection.comparePoint(e.end);f==-1&&g<=0?(b=this.$clickSelection.end,d=e.start):g==1&&f>=0?(b=this.$clickSelection.start,d=e.end):f==-1&&g==1?(d=e.end,b=e.start):(d=this.$clickSelection.end,b=this.$clickSelection.start),c.selection.setSelectionAnchor(b.row,b.column)}c.selection.selectToPosition(d),c.renderer.scrollCursorIntoView()},this.startDrag=function(){var a=this.editor;this.setState("drag"),this.dragRange=a.getSelectionRange();var b=a.getSelectionStyle();this.dragSelectionMarker=a.session.addMarker(this.dragRange,"ace_selection",b),a.clearSelection(),d.addCssClass(a.container,"ace_dragging"),this.$dragKeybinding||(this.$dragKeybinding={handleKeyboard:function(a,b,c,d){if(c=="esc")return{command:this.command}},command:{exec:function(a){var b=a.$mouseHandler;b.dragCursor=null,b.dragEnd(),b.startSelect()}}}),a.keyBinding.addKeyboardHandler(this.$dragKeybinding)},this.dragWait=function(){var a=h(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),b=(new Date).getTime(),c=this.editor;a>f?this.startSelect():b-this.mousedownEvent.time>c.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(a){this.mousedownEvent.domEvent=a,this.startSelect()},this.drag=function(){var a=this.editor;this.dragCursor=a.renderer.screenToTextCoordinates(this.x,this.y),a.moveCursorToPosition(this.dragCursor),a.renderer.scrollCursorIntoView()},this.dragEnd=function(a){var b=this.editor,c=this.dragCursor,e=this.dragRange;d.removeCssClass(b.container,"ace_dragging"),b.session.removeMarker(this.dragSelectionMarker),b.keyBinding.removeKeyboardHandler(this.$dragKeybinding);if(!c)return;b.clearSelection();if(a&&(a.ctrlKey||a.altKey)){var f=b.session,g=e;g.end=f.insert(c,f.getTextRange(e)),g.start=c}else{if(e.contains(c.row,c.column))return;var g=b.moveText(e,c)}if(!g)return;b.selection.setSelectionRange(g)},this.onDoubleClick=function(a){var b=a.getDocumentPosition(),c=this.editor;this.setState("selectByWords"),c.moveCursorToPosition(b),c.selection.selectWord(),this.$clickSelection=c.getSelectionRange()},this.onTripleClick=function(a){var b=a.getDocumentPosition(),c=this.editor;this.setState("selectByLines"),c.moveCursorToPosition(b),c.selection.selectLine(),this.$clickSelection=c.getSelectionRange()},this.onQuadClick=function(a){var b=this.editor;b.selectAll(),this.$clickSelection=b.getSelectionRange(),this.setState("select")},this.onScroll=function(a){var b=this.editor,c=b.renderer.isScrollableBy(a.wheelX*a.speed,a.wheelY*a.speed);if(c)this.$passScrollEvent=!1;else{if(this.$passScrollEvent)return;if(!this.$scrollStopTimeout){var d=this;this.$scrollStopTimeout=setTimeout(function(){d.$passScrollEvent=!0,d.$scrollStopTimeout=null},200)}}return b.renderer.scrollBy(a.wheelX*a.speed,a.wheelY*a.speed),a.preventDefault()}}).call(g.prototype),b.DefaultHandlers=g}),define("ace/lib/browser_focus",["require","exports","module","ace/lib/oop","ace/lib/event","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("./oop"),e=a("./event"),f=a("./event_emitter").EventEmitter,g=function(a){a=a||window,this.lastFocus=(new Date).getTime(),this._isFocused=!0;var b=this;"onfocusin"in a.document?(e.addListener(a.document,"focusin",function(a){b._setFocused(!0)}),e.addListener(a.document,"focusout",function(a){b._setFocused(!!a.toElement)})):(e.addListener(a,"blur",function(a){b._setFocused(!1)}),e.addListener(a,"focus",function(a){b._setFocused(!0)}))};(function(){d.implement(this,f),this.isFocused=function(){return this._isFocused},this._setFocused=function(a){if(this._isFocused==a)return;a&&(this.lastFocus=(new Date).getTime()),this._isFocused=a,this._emit("changeFocus")}}).call(g.prototype),b.BrowserFocus=g}),define("ace/lib/event_emitter",["require","exports","module"],function(a,b,c){"use strict";var d={};d._emit=d._dispatchEvent=function(a,b){this._eventRegistry=this._eventRegistry||{},this._defaultHandlers=this._defaultHandlers||{};var c=this._eventRegistry[a]||[],d=this._defaultHandlers[a];if(!c.length&&!d)return;b=b||{},b.type=a,b.stopPropagation||(b.stopPropagation=function(){this.propagationStopped=!0}),b.preventDefault||(b.preventDefault=function(){this.defaultPrevented=!0});for(var e=0;e=4352&&a<=4447||a>=4515&&a<=4519||a>=4602&&a<=4607||a>=9001&&a<=9002||a>=11904&&a<=11929||a>=11931&&a<=12019||a>=12032&&a<=12245||a>=12272&&a<=12283||a>=12288&&a<=12350||a>=12353&&a<=12438||a>=12441&&a<=12543||a>=12549&&a<=12589||a>=12593&&a<=12686||a>=12688&&a<=12730||a>=12736&&a<=12771||a>=12784&&a<=12830||a>=12832&&a<=12871||a>=12880&&a<=13054||a>=13056&&a<=19903||a>=19968&&a<=42124||a>=42128&&a<=42182||a>=43360&&a<=43388||a>=44032&&a<=55203||a>=55216&&a<=55238||a>=55243&&a<=55291||a>=63744&&a<=64255||a>=65040&&a<=65049||a>=65072&&a<=65106||a>=65108&&a<=65126||a>=65128&&a<=65131||a>=65281&&a<=65376||a>=65504&&a<=65510}e.implement(this,h),this.setDocument=function(a){if(this.doc)throw new Error("Document is already set");this.doc=a,a.on("change",this.onChange.bind(this)),this.on("changeFold",this.onChangeFold.bind(this)),this.bgTokenizer&&(this.bgTokenizer.setDocument(this.getDocument()),this.bgTokenizer.start(0))},this.getDocument=function(){return this.doc},this.$resetRowCache=function(a){if(a==0){this.$rowCache=[];return}var b=this.$rowCache;for(var c=0;c=a){b.splice(c,b.length);return}},this.onChangeFold=function(a){var b=a.data;this.$resetRowCache(b.start.row)},this.onChange=function(a){var b=a.data;this.$modified=!0,this.$resetRowCache(b.range.start.row);var c=this.$updateInternalDataOnChange(a);!this.$fromUndo&&this.$undoManager&&!b.ignore&&(this.$deltasDoc.push(b),c&&c.length!=0&&this.$deltasFold.push({action:"removeFolds",folds:c}),this.$informUndoManager.schedule()),this.bgTokenizer.start(b.range.start.row),this._emit("change",a)},this.setValue=function(a){this.doc.setValue(a),this.selection.moveCursorTo(0,0),this.selection.clearSelection(),this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.getUndoManager().reset()},this.getValue=this.toString=function(){return this.doc.getValue()},this.getSelection=function(){return this.selection},this.getState=function(a){return this.bgTokenizer.getState(a)},this.getTokens=function(a,b){return this.bgTokenizer.getTokens(a,b)},this.getTokenAt=function(a,b){var c=this.bgTokenizer.getTokens(a,a)[0].tokens,d,e=0;if(b==null)f=c.length-1,e=this.getLine(a).length;else for(var f=0;f=b)break}return d=c[f],d?(d.index=f,d.start=e-d.value.length,d):null},this.setUndoManager=function(a){this.$undoManager=a,this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(a){var b=this;this.$syncInformUndoManager=function(){b.$informUndoManager.cancel(),b.$deltasFold.length&&(b.$deltas.push({group:"fold",deltas:b.$deltasFold}),b.$deltasFold=[]),b.$deltasDoc.length&&(b.$deltas.push({group:"doc",deltas:b.$deltasDoc}),b.$deltasDoc=[]),b.$deltas.length>0&&a.execute({action:"aceupdate",args:[b.$deltas,b]}),b.$deltas=[]},this.$informUndoManager=f.deferredCall(this.$syncInformUndoManager)}},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?f.stringRepeat(" ",this.getTabSize()):" "},this.$useSoftTabs=!0,this.setUseSoftTabs=function(a){if(this.$useSoftTabs===a)return;this.$useSoftTabs=a},this.getUseSoftTabs=function(){return this.$useSoftTabs},this.$tabSize=4,this.setTabSize=function(a){if(isNaN(a)||this.$tabSize===a)return;this.$modified=!0,this.$tabSize=a,this._emit("changeTabSize")},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(a){return this.$useSoftTabs&&a.column%this.$tabSize==0},this.$overwrite=!1,this.setOverwrite=function(a){if(this.$overwrite==a)return;this.$overwrite=a,this._emit("changeOverwrite")},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(a){this.$breakpoints=[];for(var b=0;b0&&(d=!!c.charAt(b-1).match(this.tokenRe)),d||(d=!!c.charAt(b).match(this.tokenRe));var e=d?this.tokenRe:this.nonTokenRe,f=b;if(f>0){do f--;while(f>=0&&c.charAt(f).match(e));f++}var g=b;while(g=this.doc.getLength()-1)return 0;var c=this.doc.removeLines(a,b);return this.doc.insertLines(a+1,c),1},this.duplicateLines=function(a,b){var a=this.$clipRowToDocument(a),b=this.$clipRowToDocument(b),c=this.getLines(a,b);this.doc.insertLines(a,c);var d=b-a+1;return d},this.$clipRowToDocument=function(a){return Math.max(0,Math.min(a,this.doc.getLength()-1))},this.$clipColumnToRow=function(a,b){return b<0?0:Math.min(this.doc.getLine(a).length,b)},this.$clipPositionToDocument=function(a,b){b=Math.max(0,b);if(a<0)a=0,b=0;else{var c=this.doc.getLength();a>=c?(a=c-1,b=this.doc.getLine(c-1).length):b=Math.min(this.doc.getLine(a).length,b)}return{row:a,column:b}},this.$clipRangeToDocument=function(a){a.start.row<0?(a.start.row=0,a.start.column=0):a.start.column=this.$clipColumnToRow(a.start.row,a.start.column);var b=this.doc.getLength()-1;return a.end.row>b?(a.end.row=b,a.end.column=this.doc.getLine(b).length):a.end.column=this.$clipColumnToRow(a.end.row,a.end.column),a},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(a){if(a!=this.$useWrapMode){this.$useWrapMode=a,this.$modified=!0,this.$resetRowCache(0);if(a){var b=this.getLength();this.$wrapData=[];for(var c=0;c0?(this.$wrapLimit=b,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._emit("changeWrapLimit")),!0):!1},this.$constrainWrapLimit=function(a){var b=this.$wrapLimitRange.min;b&&(a=Math.max(b,a));var c=this.$wrapLimitRange.max;return c&&(a=Math.min(c,a)),Math.max(1,a)},this.getWrapLimit=function(){return this.$wrapLimit},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(a){var b=this.$useWrapMode,c,d=a.data.action,e=a.data.range.start.row,f=a.data.range.end.row,g=a.data.range.start,h=a.data.range.end,i=null;d.indexOf("Lines")!=-1?(d=="insertLines"?f=e+a.data.lines.length:f=e,c=a.data.lines?a.data.lines.length:f-e):c=f-e;if(c!=0)if(d.indexOf("remove")!=-1){b&&this.$wrapData.splice(e,c);var j=this.$foldData;i=this.getFoldsInRange(a.data.range),this.removeFolds(i);var k=this.getFoldLine(h.row),l=0;if(k){k.addRemoveChars(h.row,h.column,g.column-h.column),k.shiftRow(-c);var m=this.getFoldLine(e);m&&m!==k&&(m.merge(k),k=m),l=j.indexOf(k)+1}for(l;l=h.row&&k.shiftRow(-c)}f=e}else{var n;if(b){n=[e,0];for(var o=0;o=e&&k.shiftRow(c)}}else{c=Math.abs(a.data.range.start.column-a.data.range.end.column),d.indexOf("remove")!=-1&&(i=this.getFoldsInRange(a.data.range),this.removeFolds(i),c=-c);var k=this.getFoldLine(e);k&&k.addRemoveChars(e,g.column,c)}return b&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),b&&this.$updateWrapData(e,f),i},this.$updateWrapData=function(a,b){var c=this.doc.getAllLines(),d=this.getTabSize(),e=this.$wrapData,g=this.$wrapLimit,h,j,k=a;b=Math.min(b,c.length-1);while(k<=b){j=this.getFoldLine(k,j);if(!j)h=this.$getDisplayTokens(f.stringTrimRight(c[k])),e[k]=this.$computeWrapSplits(h,g,d),k++;else{h=[],j.walk(function(a,b,d,e){var f;if(a){f=this.$getDisplayTokens(a,h.length),f[0]=i;for(var g=1;g=o)h.pop();e[j.start.row]=this.$computeWrapSplits(h,g,d),k=j.end.row+1}}};var b=1,c=2,i=3,l=4,n=9,o=10,p=11,q=12;this.$computeWrapSplits=function(a,b){function g(b){var d=a.slice(e,b),g=d.length;d.join("").replace(/12/g,function(){g-=1}).replace(/2/g,function(){g-=1}),f+=g,c.push(f),e=b}if(a.length==0)return[];var c=[],d=a.length,e=0,f=0;while(d-e>b){var h=e+b;if(a[h]>=o){while(a[h]>=o)h++;g(h);continue}if(a[h]==i||a[h]==l){for(h;h!=e-1;h--)if(a[h]==i)break;if(h>e){g(h);continue}h=e+b;for(h;hj&&a[h]j&&a[h]==n)h--;if(h>j){g(++h);continue}h=e+b,g(h)}return c},this.$getDisplayTokens=function(a,d){var e=[],f;d=d||0;for(var g=0;g39&&h<48||h>57&&h<64?e.push(n):h>=4352&&r(h)?e.push(b,c):e.push(b)}return e},this.$getStringScreenWidth=function(a,b,c){if(b==0)return[0,0];b==null&&(b=c+a.length*Math.max(this.getTabSize(),2)),c=c||0;var d,e;for(e=0;e=4352&&r(d)?c+=2:c+=1;if(c>b)break}return[c,e]},this.getRowLength=function(a){return!this.$useWrapMode||!this.$wrapData[a]?1:this.$wrapData[a].length+1},this.getRowHeight=function(a,b){return this.getRowLength(b)*a.lineHeight},this.getScreenLastRowColumn=function(a){var b=this.screenToDocumentPosition(a,Number.MAX_VALUE);return this.documentToScreenColumn(b.row,b.column)},this.getDocumentLastRowColumn=function(a,b){var c=this.documentToScreenRow(a,b);return this.getScreenLastRowColumn(c)},this.getDocumentLastRowColumnPosition=function(a,b){var c=this.documentToScreenRow(a,b);return this.screenToDocumentPosition(c,Number.MAX_VALUE/10)},this.getRowSplitData=function(a){return this.$useWrapMode?this.$wrapData[a]:undefined},this.getScreenTabSize=function(a){return this.$tabSize-a%this.$tabSize},this.screenToDocumentRow=function(a,b){return this.screenToDocumentPosition(a,b).row},this.screenToDocumentColumn=function(a,b){return this.screenToDocumentPosition(a,b).column},this.screenToDocumentPosition=function(a,b){if(a<0)return{row:0,column:0};var c,d=0,e=0,f,g=0,h=0,i=this.$rowCache;for(var j=0;j=a||d>=l)break;g+=h,d++,d>n&&(d=m.end.row+1,m=this.getNextFoldLine(d,m),n=m?m.start.row:Infinity),k&&i.push({docRow:d,screenRow:g})}if(m&&m.start.row<=d)c=this.getFoldDisplayLine(m),d=m.start.row;else{if(g+h<=a||d>l)return{row:l,column:this.getLine(l).length};c=this.getLine(d),m=null}if(this.$useWrapMode){var o=this.$wrapData[d];o&&(f=o[a-g],a>g&&o.length&&(e=o[a-g-1]||o[o.length-1],c=c.substring(e)))}return e+=this.$getStringScreenWidth(c,b)[1],this.$useWrapMode&&e>=f&&(e=f-1),m?m.idxToPosition(e):{row:d,column:e}},this.documentToScreenPosition=function(a,b){if(typeof b=="undefined")var c=this.$clipPositionToDocument(a.row,a.column);else c=this.$clipPositionToDocument(a,b);a=c.row,b=c.column;var d;if(this.$useWrapMode){d=this.$wrapData;if(a>d.length-1)return{row:this.getScreenLength(),column:d.length==0?0:d[d.length-1].length-1}}var e=0,f=null,g=null;g=this.getFoldAt(a,b,1),g&&(a=g.start.row,b=g.start.column);var h,i=0,j=this.$rowCache;for(var k=0;k=n){h=m.end.row+1;if(h>a)break;m=this.getNextFoldLine(h,m),n=m?m.start.row:Infinity}else h=i+1;e+=this.getRowLength(i),i=h,l&&j.push({docRow:i,screenRow:e})}var o="";m&&i>=n?(o=this.getFoldDisplayLine(m,a,b),f=m.start.row):(o=this.getLine(a).substring(0,b),f=a);if(this.$useWrapMode){var p=d[f],q=0;while(o.length>=p[q])e++,q++;o=o.substring(p[q-1]||0,o.length)}return{row:e,column:this.$getStringScreenWidth(o)[0]}},this.documentToScreenColumn=function(a,b){return this.documentToScreenPosition(a,b).column},this.documentToScreenRow=function(a,b){return this.documentToScreenPosition(a,b).row},this.getScreenLength=function(){var a=0,b=null;if(!this.$useWrapMode){a=this.getLength();var c=this.$foldData;for(var d=0;dg&&(f=b.end.row+1,b=this.$foldData[d++],g=b?b.start.row:Infinity)}return a}}).call(n.prototype),a("./edit_session/folding").Folding.call(n.prototype),a("./edit_session/bracket_match").BracketMatch.call(n.prototype),b.EditSession=n}),define("ace/config",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return a.replace(/-(.)/g,function(a,b){return b.toUpperCase()})}"no use strict";var d=a("./lib/lang"),e=function(){return this}(),f={packaged:!1,workerPath:"",modePath:"",themePath:"",suffix:".js"};b.get=function(a){if(!f.hasOwnProperty(a))throw new Error("Unknown confik key: "+a);return f[a]},b.set=function(a,b){if(!f.hasOwnProperty(a))throw new Error("Unknown confik key: "+a);f[a]=b},b.all=function(){return d.copyObject(f)},b.init=function(){f.packaged=a.packaged||c.packaged||e.define&&define.packaged;if(!e.document)return"";var d={},h="",i,j=document.getElementsByTagName("script");for(var k=0;kb.row||a.row==b.row&&a.column>b.column},this.getRange=function(){var a=this.anchor,b=this.lead;return this.isEmpty()?g.fromPoints(b,b):this.isBackwards()?g.fromPoints(b,a):g.fromPoints(a,b)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){var a=this.doc.getLength()-1;this.setSelectionAnchor(a,this.doc.getLine(a).length),this.moveCursorTo(0,0)},this.setSelectionRange=function(a,b){a.isEmpty()?(this.lead.setPosition(a.start.row,a.start.column),this.clearSelection()):b?(this.$isEmpty=!1,this.anchor.setPosition(a.end.row,a.end.column),this.lead.setPosition(a.start.row,a.start.column)):(this.$isEmpty=!1,this.anchor.setPosition(a.start.row,a.start.column),this.lead.setPosition(a.end.row,a.end.column)),this.$desiredColumn=null},this.$moveSelection=function(a){var b=this.lead;this.$isEmpty&&this.setSelectionAnchor(b.row,b.column),a.call(this)},this.selectTo=function(a,b){this.$moveSelection(function(){this.moveCursorTo(a,b)})},this.selectToPosition=function(a){this.$moveSelection(function(){this.moveCursorToPosition(a)})},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(a,b){if(typeof b=="undefined"){var c=a||this.lead;a=c.row,b=c.column}return this.session.getWordRange(a,b)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var a=this.getCursor(),b=this.session.getAWordRange(a.row,a.column);this.setSelectionRange(b)},this.getLineRange=function(a,b){var c=typeof a=="number"?a:this.lead.row,d,e=this.session.getFoldLine(c);return e?(c=e.start.row,d=e.end.row):d=c,b?new g(c,0,d,this.session.getLine(d).length):new g(c,0,d+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 a=this.lead.getPosition(),b;if(b=this.session.getFoldAt(a.row,a.column,-1))this.moveCursorTo(b.start.row,b.start.column);else if(a.column==0)a.row>0&&this.moveCursorTo(a.row-1,this.doc.getLine(a.row-1).length);else{var c=this.session.getTabSize();this.session.isTabStop(a)&&this.doc.getLine(a.row).slice(a.column-c,a.column).split(" ").length-1==c?this.moveCursorBy(0,-c):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var a=this.lead.getPosition(),b;if(b=this.session.getFoldAt(a.row,a.column,1))this.moveCursorTo(b.end.row,b.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row=c.length){this.moveCursorTo(a,c.length),this.moveCursorRight(),a0&&this.moveCursorWordLeft();return}if(g=this.session.tokenRe.exec(f))b-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(a,b)},this.$shortWordEndIndex=function(a){var b,c=0,d,e=/\s/,f=this.session.tokenRe;f.lastIndex=0;if(b=this.session.tokenRe.exec(a))c=this.session.tokenRe.lastIndex;else{while((d=a[c])&&e.test(d))c++;if(c<=1){f.lastIndex=0;while((d=a[c])&&!f.test(d)){f.lastIndex=0,c++;if(e.test(d)){if(c>2){c--;break}while((d=a[c])&&e.test(d))c++;if(c>2)break}}}}return f.lastIndex=0,c},this.moveCursorShortWordRight=function(){var a=this.lead.row,b=this.lead.column,c=this.doc.getLine(a),d=c.substring(b),e=this.session.getFoldAt(a,b,1);if(e)return this.moveCursorTo(e.end.row,e.end.column);if(b==c.length)return this.moveCursorRight();var f=this.$shortWordEndIndex(d);this.moveCursorTo(a,b+f)},this.moveCursorShortWordLeft=function(){var a=this.lead.row,b=this.lead.column,c;if(c=this.session.getFoldAt(a,b,-1))return this.moveCursorTo(c.start.row,c.start.column);if(b==0)return this.moveCursorLeft();var d=this.session.getLine(a).substring(0,b),f=e.stringReverse(d),g=this.$shortWordEndIndex(f);return this.moveCursorTo(a,b-g)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(a,b){var c=this.session.documentToScreenPosition(this.lead.row,this.lead.column);b===0&&(this.$desiredColumn?c.column=this.$desiredColumn:this.$desiredColumn=c.column);var d=this.session.screenToDocumentPosition(c.row+a,c.column);this.moveCursorTo(d.row,d.column+b,b===0)},this.moveCursorToPosition=function(a){this.moveCursorTo(a.row,a.column)},this.moveCursorTo=function(a,b,c){var d=this.session.getFoldAt(a,b,1);d&&(a=d.start.row,b=d.start.column),this.$keepDesiredColumnOnChange=!0,this.lead.setPosition(a,b),this.$keepDesiredColumnOnChange=!1,c||(this.$desiredColumn=null)},this.moveCursorToScreen=function(a,b,c){var d=this.session.screenToDocumentPosition(a,b);this.moveCursorTo(d.row,d.column,c)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(a){this.setSelectionRange(a,a.cursor==a.start),this.$desiredColumn=a.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(a){var b=this.getRange();return a?(a.start.column=b.start.column,a.start.row=b.start.row,a.end.column=b.end.column,a.end.row=b.end.row):a=b,a.cursor=this.isBackwards()?a.start:a.end,a.desiredColumn=this.$desiredColumn,a}}).call(h.prototype),b.Selection=h}),define("ace/range",["require","exports","module"],function(a,b,c){"use strict";var d=function(a,b,c,d){this.start={row:a,column:b},this.end={row:c,column:d}};(function(){this.isEqual=function(a){return this.start.row==a.start.row&&this.end.row==a.end.row&&this.start.column==a.start.column&&this.end.column==a.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(a,b){return this.compare(a,b)==0},this.compareRange=function(a){var b,c=a.end,d=a.start;return b=this.compare(c.row,c.column),b==1?(b=this.compare(d.row,d.column),b==1?2:b==0?1:0):b==-1?-2:(b=this.compare(d.row,d.column),b==-1?-1:b==1?42:0)},this.comparePoint=function(a){return this.compare(a.row,a.column)},this.containsRange=function(a){return this.comparePoint(a.start)==0&&this.comparePoint(a.end)==0},this.intersects=function(a){var b=this.compareRange(a);return b==-1||b==0||b==1},this.isEnd=function(a,b){return this.end.row==a&&this.end.column==b},this.isStart=function(a,b){return this.start.row==a&&this.start.column==b},this.setStart=function(a,b){typeof a=="object"?(this.start.column=a.column,this.start.row=a.row):(this.start.row=a,this.start.column=b)},this.setEnd=function(a,b){typeof a=="object"?(this.end.column=a.column,this.end.row=a.row):(this.end.row=a,this.end.column=b)},this.inside=function(a,b){return this.compare(a,b)==0?this.isEnd(a,b)||this.isStart(a,b)?!1:!0:!1},this.insideStart=function(a,b){return this.compare(a,b)==0?this.isEnd(a,b)?!1:!0:!1},this.insideEnd=function(a,b){return this.compare(a,b)==0?this.isStart(a,b)?!1:!0:!1},this.compare=function(a,b){return!this.isMultiLine()&&a===this.start.row?b