From 11ac88c012ffe63281d3df62a871d3f7131667d1 Mon Sep 17 00:00:00 2001 From: Joe Walker Date: Thu, 23 Dec 2010 15:30:55 +0000 Subject: [PATCH 01/59] move cockpit/pilot to a submodules --- .gitmodules | 3 + demo/boot.js | 61 +- editor.html | 45 +- plugins/cockpit/cli.js | 1083 ------------------ plugins/cockpit/index.js | 59 - plugins/cockpit/test/assert.js | 317 ----- plugins/cockpit/test/testCli.js | 359 ------ plugins/cockpit/test/testNothing.js | 40 - plugins/cockpit/ui/cliView.css | 164 --- plugins/cockpit/ui/cliView.js | 369 ------ plugins/cockpit/ui/images/closer.png | Bin 669 -> 0 bytes plugins/cockpit/ui/images/dot_clear.gif | Bin 42 -> 0 bytes plugins/cockpit/ui/images/minus.png | Bin 604 -> 0 bytes plugins/cockpit/ui/images/pinaction.png | Bin 1502 -> 0 bytes plugins/cockpit/ui/images/pinin.png | Bin 1199 -> 0 bytes plugins/cockpit/ui/images/pinout.png | Bin 1553 -> 0 bytes plugins/cockpit/ui/images/pins.png | Bin 1712 -> 0 bytes plugins/cockpit/ui/images/plus.png | Bin 635 -> 0 bytes plugins/cockpit/ui/images/throbber.gif | Bin 10819 -> 0 bytes plugins/cockpit/ui/requestView.css | 39 - plugins/cockpit/ui/requestView.html | 28 - plugins/cockpit/ui/requestView.js | 149 --- plugins/cockpit/ui/settings.js | 85 -- plugins/pilot/canon.js | 342 ------ plugins/pilot/catalog.js | 65 -- plugins/pilot/commands/basic.js | 263 ----- plugins/pilot/commands/history.js | 117 -- plugins/pilot/commands/settings.js | 135 --- plugins/pilot/console.js | 76 -- plugins/pilot/dom.js | 154 --- plugins/pilot/domtemplate.js | 404 ------- plugins/pilot/event.js | 242 ---- plugins/pilot/event_emitter.js | 84 -- plugins/pilot/fixoldbrowsers.js | 164 --- plugins/pilot/index.js | 73 -- plugins/pilot/keyboard/index.js | 459 -------- plugins/pilot/keyboard/keyutil.js | 273 ----- plugins/pilot/keyboard/tests/testKeyboard.js | 99 -- plugins/pilot/lang.js | 107 -- plugins/pilot/oop.js | 58 - plugins/pilot/plugin_manager.js | 158 --- plugins/pilot/promise.js | 264 ----- plugins/pilot/proxy.js | 83 -- plugins/pilot/rangeutils.js | 185 --- plugins/pilot/settings.js | 303 ----- plugins/pilot/settings/canon.js | 57 - plugins/pilot/stacktrace.js | 332 ------ plugins/pilot/tests/testRangeutils.js | 163 --- plugins/pilot/typecheck.js | 80 -- plugins/pilot/types.js | 262 ----- plugins/pilot/types/basic.js | 291 ----- plugins/pilot/types/command.js | 75 -- plugins/pilot/types/settings.js | 109 -- plugins/pilot/useragent.js | 92 -- support/cockpit | 1 + 55 files changed, 79 insertions(+), 8292 deletions(-) delete mode 100644 plugins/cockpit/cli.js delete mode 100644 plugins/cockpit/index.js delete mode 100644 plugins/cockpit/test/assert.js delete mode 100644 plugins/cockpit/test/testCli.js delete mode 100644 plugins/cockpit/test/testNothing.js delete mode 100644 plugins/cockpit/ui/cliView.css delete mode 100644 plugins/cockpit/ui/cliView.js delete mode 100644 plugins/cockpit/ui/images/closer.png delete mode 100644 plugins/cockpit/ui/images/dot_clear.gif delete mode 100644 plugins/cockpit/ui/images/minus.png delete mode 100644 plugins/cockpit/ui/images/pinaction.png delete mode 100644 plugins/cockpit/ui/images/pinin.png delete mode 100644 plugins/cockpit/ui/images/pinout.png delete mode 100644 plugins/cockpit/ui/images/pins.png delete mode 100644 plugins/cockpit/ui/images/plus.png delete mode 100644 plugins/cockpit/ui/images/throbber.gif delete mode 100644 plugins/cockpit/ui/requestView.css delete mode 100644 plugins/cockpit/ui/requestView.html delete mode 100644 plugins/cockpit/ui/requestView.js delete mode 100644 plugins/cockpit/ui/settings.js delete mode 100644 plugins/pilot/canon.js delete mode 100644 plugins/pilot/catalog.js delete mode 100644 plugins/pilot/commands/basic.js delete mode 100644 plugins/pilot/commands/history.js delete mode 100644 plugins/pilot/commands/settings.js delete mode 100644 plugins/pilot/console.js delete mode 100644 plugins/pilot/dom.js delete mode 100644 plugins/pilot/domtemplate.js delete mode 100644 plugins/pilot/event.js delete mode 100644 plugins/pilot/event_emitter.js delete mode 100644 plugins/pilot/fixoldbrowsers.js delete mode 100644 plugins/pilot/index.js delete mode 100644 plugins/pilot/keyboard/index.js delete mode 100644 plugins/pilot/keyboard/keyutil.js delete mode 100644 plugins/pilot/keyboard/tests/testKeyboard.js delete mode 100644 plugins/pilot/lang.js delete mode 100644 plugins/pilot/oop.js delete mode 100644 plugins/pilot/plugin_manager.js delete mode 100644 plugins/pilot/promise.js delete mode 100644 plugins/pilot/proxy.js delete mode 100644 plugins/pilot/rangeutils.js delete mode 100644 plugins/pilot/settings.js delete mode 100644 plugins/pilot/settings/canon.js delete mode 100644 plugins/pilot/stacktrace.js delete mode 100644 plugins/pilot/tests/testRangeutils.js delete mode 100644 plugins/pilot/typecheck.js delete mode 100644 plugins/pilot/types.js delete mode 100644 plugins/pilot/types/basic.js delete mode 100644 plugins/pilot/types/command.js delete mode 100644 plugins/pilot/types/settings.js delete mode 100644 plugins/pilot/useragent.js create mode 160000 support/cockpit diff --git a/.gitmodules b/.gitmodules index 346eb6aa..0927bff1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "support/node-htmlparser"] path = support/node-htmlparser url = git://github.com/tautologistics/node-htmlparser.git +[submodule "support/cockpit"] + path = support/cockpit + url = git://github.com/joewalker/cockpit.git diff --git a/demo/boot.js b/demo/boot.js index 2997b5ed..bbf08f18 100644 --- a/demo/boot.js +++ b/demo/boot.js @@ -35,17 +35,36 @@ * * ***** END LICENSE BLOCK ***** */ +/* +setupPlugins(function(plugin_manager, settings) { + var data = { env: { settings: settings } }; + plugin_manager.catalog.startupPlugins(data, plugin_manager.REASONS.APP_STARTUP).then(function() { + var demo_startup = require("demo_startup"); + demo_startup.launch(data.env); + }); +}); + // TODO: Yuck! A global function -var setupPlugins = function(config, callback) { - config = config || {}; +var setupPlugins = function(callback) { + var config = { + pluginDirs: { + "../demo": { + singleFiles: ["demo_startup"] + } + } + }; + if (!config.pluginDirs) { config.pluginDirs = {}; } // config.pluginDirs["../lib"] = { // packages: ["ace"] // }; - config.pluginDirs["../plugins"] = { - packages: ["pilot", "cockpit"] + config.pluginDirs["../support/cockpit/support/pilot/lib"] = { + packages: [ "pilot" ] + }; + config.pluginDirs["../support/cockpit/lib"] = { + packages: [ "cockpit" ] }; var knownPlugins = []; @@ -99,7 +118,7 @@ var setupPlugins = function(config, callback) { main: "index", lib: "." }); - knownPlugins.push(packages[i]); + knownPlugins.push(packages[i] + "/index"); } } if (dirInfo.singleFiles) { @@ -125,3 +144,35 @@ var setupPlugins = function(config, callback) { }); }); }; +*/ + +var config = { + packagePaths: { + "../lib": [ + { name:"ace", lib: "." } + ], + "../support/cockpit/lib": [ + { name: "cockpit", main: "index", lib: "." } + ], + "../support/cockpit/support/pilot/lib": [ + { name: "pilot", main: "index", lib: "." } + ] + }, + paths: { demo_startup: "../demo/demo_startup" } +}; + +var deps = [ "pilot/fixoldbrowsers", "pilot/plugin_manager", "pilot/settings", + "pilot/environment", "demo_startup" ]; + +require(config, deps, function() { + var catalog = require("pilot/plugin_manager").catalog; + var REASON_START = require("pilot/plugin_manager").REASONS.APP_STARTUP; + var settings = require("pilot/settings").settings; + + catalog.registerPlugins([ "pilot/index", "cockpit/index" ]).then(function() { + var env = require("pilot/environment").create(); + catalog.startupPlugins({ env:env }, REASON_START).then(function() { + require("demo_startup").launch(env); + }); + }); +}); diff --git a/editor.html b/editor.html index 2e66ea17..a6b28321 100644 --- a/editor.html +++ b/editor.html @@ -46,10 +46,24 @@ display: none; } - #cockpit { + #cockpitInput { position: absolute; width: 100%; 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; } @@ -177,31 +191,10 @@ echo $output; ?> - + - - - - - + + - \ No newline at end of file + diff --git a/plugins/cockpit/cli.js b/plugins/cockpit/cli.js deleted file mode 100644 index df183782..00000000 --- a/plugins/cockpit/cli.js +++ /dev/null @@ -1,1083 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - - -var console = require('pilot/console'); -var lang = require('pilot/lang'); -var oop = require('pilot/oop'); -var EventEmitter = require('pilot/event_emitter').EventEmitter; - -//var keyboard = require('keyboard/keyboard'); -var types = require('pilot/types'); -var Status = require('pilot/types').Status; -var Conversion = require('pilot/types').Conversion; -var canon = require('pilot/canon'); - -/** - * Normally type upgrade is done when the owning command is registered, but - * out commandParam isn't part of a command, so it misses out. - */ -exports.startup = function(data, reason) { - canon.upgradeType(commandParam); -}; - -/** - * The information required to tell the user there is a problem with their - * input. - * TODO: There a several places where {start,end} crop up. Perhaps we should - * have a Cursor object. - */ -function Hint(status, message, start, end, predictions) { - this.status = status; - this.message = message; - - if (typeof start === 'number') { - this.start = start; - this.end = end; - this.predictions = predictions; - } - else { - var arg = start; - this.start = arg.start; - this.end = arg.end; - this.predictions = arg.predictions; - } -} -Hint.prototype = { -}; -/** - * Loop over the array of hints finding the one we should display. - * @param hints array of hints - */ -Hint.sort = function(hints, cursor) { - // Calculate 'distance from cursor' - if (cursor !== undefined) { - hints.forEach(function(hint) { - if (hint.start === Argument.AT_CURSOR) { - hint.distance = 0; - } - else if (cursor < hint.start) { - hint.distance = hint.start - cursor; - } - else if (cursor > hint.end) { - hint.distance = cursor - hint.end; - } - else { - hint.distance = 0; - } - }, this); - } - // Sort - hints.sort(function(hint1, hint2) { - // Compare first based on distance from cursor - if (cursor !== undefined) { - var diff = hint1.distance - hint2.distance; - if (diff != 0) { - return diff; - } - } - // otherwise go with hint severity - return hint2.status - hint1.status; - }); - // tidy-up - if (cursor !== undefined) { - hints.forEach(function(hint) { - delete hint.distance; - }, this); - } - return hints; -}; -exports.Hint = Hint; - -/** - * A Hint that arose as a result of a Conversion - */ -function ConversionHint(conversion, arg) { - this.status = conversion.status; - this.message = conversion.message; - if (arg) { - this.start = arg.start; - this.end = arg.end; - } - else { - this.start = 0; - this.end = 0; - } - this.predictions = conversion.predictions; -}; -oop.inherits(ConversionHint, Hint); - - -/** - * We record where in the input string an argument comes so we can report errors - * against those string positions. - * We publish a 'change' event when-ever the text changes - * @param emitter Arguments use something else to pass on change events. - * Currently this will be the creating Requisition. This prevents dependency - * loops and prevents us from needing to merge listener lists. - * @param text The string (trimmed) that contains the argument - * @param start The position of the text in the original input string - * @param end See start - * @param priorSpace Knowledge of the whitespace used prior to this argument in - * the input string allows us to re-generate the original input from the - * arguments. - * @constructor - */ -function Argument(emitter, text, start, end, priorSpace) { - this.emitter = emitter; - this.setText(text); - this.start = start; - this.end = end; - this.priorSpace = priorSpace; -} -Argument.prototype = { - /** - * Return the result of merging these arguments - */ - merge: function(following) { - if (following.emitter != this.emitter) { - throw new Error('Can\'t merge Arguments from different EventEmitters'); - } - return new Argument( - this.emitter, - this.text + following.priorSpace + following.text, - this.start, following.end, - this.priorSpace); - }, - - /** - * See notes on events in Assignment. We might need to hook changes here - * into a CliRequisition so they appear of the command line. - */ - setText: function(text) { - if (text == null) { - throw new Error('Illegal text for Argument: ' + text); - } - var ev = { argument: this, oldText: this.text, text: text }; - this.text = text; - this.emitter._dispatchEvent('argumentChange', ev); - }, - - /** - * Helper when we're putting arguments back together - */ - toString: function() { - return this.priorSpace + this.text; - } -}; -/** - * Merge an array of arguments into a single argument. - * All Arguments in the array are expected to have the same emitter - */ -Argument.merge = function(argArray, start, end) { - start = (start === undefined) ? 0 : start; - end = (end === undefined) ? argArray.length : end; - - var joined; - for (var i = start; i < end; i++) { - var arg = argArray[i]; - if (!joined) { - joined = arg; - } - else { - joined = joined.merge(arg); - } - } - return joined; -}; -/** - * We sometimes need a way to say 'this error occurs where ever the cursor is' - */ -Argument.AT_CURSOR = -1; - - -/** - * A link between a parameter and the data for that parameter. - * The data for the parameter is available as in the preferred type and as - * an Argument for the CLI. - *

We also record validity information where applicable. - *

For values, null and undefined have distinct definitions. null means - * that a value has been provided, undefined means that it has not. - * Thus, null is a valid default value, and common because it identifies an - * parameter that is optional. undefined means there is no value from - * the command line. - * @constructor - */ -function Assignment(param, requisition) { - this.param = param; - this.requisition = requisition; - this.setValue(param.defaultValue); -}; -Assignment.prototype = { - /** - * The parameter that we are assigning to - * @readonly - */ - param: undefined, - - /** - * Report on the status of the last parse() conversion. - * @see types.Conversion - */ - conversion: undefined, - - /** - * The current value in a type as specified by param.type - */ - value: undefined, - - /** - * The string version of the current value - */ - arg: undefined, - - /** - * The current value (i.e. not the string representation) - * Use setValue() to mutate - */ - value: undefined, - setValue: function(value) { - if (this.value === value) { - return; - } - - if (value === undefined) { - value = this.param.defaultValue; - this.arg = undefined; - } - this.value = value; - - var text = (value == null) ? '' : this.param.type.stringify(value); - if (this.arg) { - this.arg.setText(text); - } - - this.conversion = undefined; - this.requisition._assignmentChanged(this); - }, - - /** - * The textual representation of the current value - * Use setValue() to mutate - */ - arg: undefined, - setArgument: function(arg) { - if (this.arg === arg) { - return; - } - this.arg = arg; - this.conversion = this.param.type.parse(arg.text); - this.conversion.arg = arg; // TODO: make this automatic? - this.value = this.conversion.value; - this.requisition._assignmentChanged(this); - }, - - /** - * Create a list of the hints associated with this parameter assignment. - * Generally there will be only one hint generated because we're currently - * only displaying one hint at a time, ordering by distance from cursor - * and severity. Since distance from cursor will be the same for all hints - * from this assignment all but the most severe will ever be used. It might - * make sense with more experience to alter this to function to be getHint() - */ - getHint: function() { - // Allow the parameter to provide documentation - if (this.param.getCustomHint && this.value && this.arg) { - var hint = this.param.getCustomHint(this.value, this.arg); - if (hint) { - return hint; - } - } - - // If there is no argument, use the cursor position - var message = '' + this.param.name + ': '; - if (this.param.description) { - // TODO: This should be a short description - do we need to trim? - message += this.param.description.trim(); - - // Ensure the help text ends with '. ' - if (message.charAt(message.length - 1) !== '.') { - message += '.'; - } - if (message.charAt(message.length - 1) !== ' ') { - message += ' '; - } - } - var status = Status.VALID; - var start = this.arg ? this.arg.start : Argument.AT_CURSOR; - var end = this.arg ? this.arg.end : Argument.AT_CURSOR; - var predictions; - - // Non-valid conversions will have useful information to pass on - if (this.conversion) { - status = this.conversion.status; - if (this.conversion.message) { - message += this.conversion.message; - } - predictions = this.conversion.predictions; - } - - // Hint if the param is required, but not provided - var argProvided = this.arg && this.arg.text !== ''; - var dataProvided = this.value !== undefined || argProvided; - if (this.param.defaultValue === undefined && !dataProvided) { - status = Status.INVALID; - message += 'Required<\strong>'; - } - - return new Hint(status, message, start, end, predictions); - }, - - /** - * Basically setValue(conversion.predictions[0]) done in a safe - * way. - */ - complete: function() { - if (this.conversion && this.conversion.predictions && - this.conversion.predictions.length > 0) { - this.setValue(this.conversion.predictions[0]); - } - }, - - /** - * Replace the current value with the lower value if such a concept - * exists. - */ - decrement: function() { - var replacement = this.param.type.decrement(this.value); - if (replacement != null) { - this.setValue(replacement); - } - }, - - /** - * Replace the current value with the higher value if such a concept - * exists. - */ - increment: function() { - var replacement = this.param.type.increment(this.value); - if (replacement != null) { - this.setValue(replacement); - } - }, - - /** - * Helper when we're rebuilding command lines. - */ - toString: function() { - return this.arg ? this.arg.toString() : ''; - } -}; -exports.Assignment = Assignment; - - -/** - * This is a special parameter to reflect the command itself. - */ -var commandParam = { - name: 'command', - type: 'command', - description: 'The command to execute', - - /** - * Provide some documentation for a command. - */ - getCustomHint: function(command, arg) { - var docs = []; - docs.push(' > '); - docs.push(command.name); - if (command.params && command.params.length > 0) { - command.params.forEach(function(param) { - if (param.defaultValue === undefined) { - docs.push(' [' + param.name + ']'); - } - else { - docs.push(' [' + param.name + ']'); - } - }, this); - } - docs.push('
'); - - docs.push(command.description ? command.description : '(No description)'); - docs.push('
'); - - if (command.params && command.params.length > 0) { - docs.push('

'); - } - - return new Hint(Status.VALID, docs.join(''), arg); - } -}; - -/** - * A Requisition collects the information needed to execute a command. - * There is no point in a requisition for parameter-less commands because there - * is no information to collect. A Requisition is a collection of assignments - * of values to parameters, each handled by an instance of Assignment. - * CliRequisition adds functions for parsing input from a command line to this - * class. - *

Events

- * We publish the following events:
    - *
  • argumentChange: The text of some argument has changed. It is likely that - * any UI component displaying this argument will need to be updated. (Note that - * this event is actually published by the Argument itself - see the docs for - * Argument for more details) - * The event object looks like: { argument: A, oldText: B, text: B } - *
  • commandChange: The command has changed. It is likely that a UI - * structure will need updating to match the parameters of the new command. - * The event object looks like { command: A } - * @constructor - */ -function Requisition(env) { - this.env = env; - this.commandAssignment = new Assignment(commandParam, this); -} - -Requisition.prototype = { - /** - * The command that we are about to execute. - * @see setCommandConversion() - * @readonly - */ - commandAssignment: undefined, - - /** - * The count of assignments. Excludes the commandAssignment - * @readonly - */ - assignmentCount: undefined, - - /** - * The object that stores of Assignment objects that we are filling out. - * The Assignment objects are stored under their param.name for named - * lookup. Note: We make use of the property of Javascript objects that - * they are not just hashmaps, but linked-list hashmaps which iterate in - * insertion order. - * Excludes the commandAssignment. - */ - _assignments: undefined, - - /** - * The store of hints generated by the assignments. We are trying to prevent - * the UI from needing to access this in broad form, but instead use - * methods that query part of this structure. - */ - _hints: undefined, - - /** - * When the command changes, we need to keep a bunch of stuff in sync - */ - _assignmentChanged: function(assignment) { - // This is all about re-creating Assignments - if (assignment.param.name !== 'command') { - return; - } - - this._assignments = {}; - - if (assignment.value) { - assignment.value.params.forEach(function(param) { - this._assignments[param.name] = new Assignment(param, this); - }, this); - } - - this.assignmentCount = Object.keys(this._assignments).length; - this._dispatchEvent('commandChange', { command: assignment.value }); - }, - - /** - * Assignments have an order, so we need to store them in an array. - * But we also need named access ... - */ - getAssignment: function(nameOrNumber) { - var name = (typeof nameOrNumber === 'string') ? - nameOrNumber : - Object.keys(this._assignments)[nameOrNumber]; - return this._assignments[name]; - }, - - /** - * Where parameter name == assignment names - they are the same. - */ - getParameterNames: function() { - return Object.keys(this._assignments); - }, - - /** - * A *shallow* clone of the assignments. - * This is useful for systems that wish to go over all the assignments - * finding values one way or another and wish to trim an array as they go. - */ - cloneAssignments: function() { - return Object.keys(this._assignments).map(function(name) { - return this._assignments[name]; - }, this); - }, - - /** - * Collect the statuses from the Assignments. - * The hints returned are sorted by severity - */ - _updateHints: function() { - // TODO: work out when to clear this out for the plain Requisition case - // this._hints = []; - this._hints.push(this.commandAssignment.getHint()); - Object.keys(this._assignments).map(function(name) { - // Only use assignments with an argument - var assignment = this._assignments[name]; - if (assignment.arg) { - this._hints.push(assignment.getHint()); - } - }, this); - Hint.sort(this._hints); - - // We would like to put some initial help here, but for anyone but - // a complete novice a 'type help' message is very annoying, so we - // need to find a way to only display this message once, or for - // until the user click a 'close' button or similar - // TODO: Add special case for '' input - }, - - /** - * Returns the most severe status - */ - getWorstHint: function() { - return this._hints[0]; - }, - - /** - * Extract the names and values of all the assignments, and return as - * an object. - */ - getArgs: function() { - var args = {}; - Object.keys(this._assignments).forEach(function(name) { - args[name] = this.getAssignment(name).value; - }, this); - return args; - }, - - /** - * Reset all the assignments to their default values - */ - setDefaultValues: function() { - Object.keys(this._assignments).forEach(function(name) { - this._assignments[name].setValue(undefined); - }, this); - }, - - /** - * Helper to call canon.exec - */ - exec: function() { - var command = this.commandAssignment.value; - canon.exec(command, this.env, this.getArgs(), this.toCanonicalString()); - }, - - /** - * Extract a canonical version of the input - */ - toCanonicalString: function() { - var line = []; - line.push(this.commandAssignment.value.name); - Object.keys(this._assignments).forEach(function(name) { - var assignment = this._assignments[name]; - var type = assignment.param.type; - // TODO: This will cause problems if there is a non-default value - // after a default value. Also we need to decide when to use - // named parameters in place of positional params. Both can wait. - if (assignment.value !== assignment.param.defaultValue) { - line.push(' '); - line.push(type.stringify(assignment.value)); - } - }, this); - return line.join(''); - } -}; -oop.implement(Requisition.prototype, EventEmitter); -exports.Requisition = Requisition; - - -/** - * An object used during command line parsing to hold the various intermediate - * data steps. - *

    The 'output' of the update is held in 2 objects: input.hints which is an - * array of hints to display to the user. In the future this will become a - * single value. - *

    The other output value is input.requisition which gives access to an - * args object for use in executing the final command. - * - *

    The majority of the functions in this class are called in sequence by the - * constructor. Their task is to add to hints fill out the requisition. - *

    The general sequence is:

      - *
    • _tokenize(): convert _typed into _parts - *
    • _split(): convert _parts into _command and _unparsedArgs - *
    • _assign(): convert _unparsedArgs into requisition - *
    - * - * @param typed {string} The instruction as typed by the user so far - * @param options {object} A list of optional named parameters. Can be any of: - * flags: Flags for us to check against the predicates specified with the - * commands. Defaulted to keyboard.buildFlags({ }); - * if not specified. - * @constructor - */ -function CliRequisition(env, options) { - Requisition.call(this, env); - - if (options && options.flags) { - /** - * TODO: We were using a default of keyboard.buildFlags({ }); - * This allowed us to have commands that only existed in certain contexts - * - i.e. Javascript specific commands. - */ - this.flags = options.flags; - } -} -oop.inherits(CliRequisition, Requisition); -(function() { - /** - * Called by the UI when ever the user interacts with a command line input - * @param input A structure that details the state of the input field. - * It should look something like: { typed:a, cursor: { start:b, end:c } } - * Where a is the contents of the input field, and b and c are the start - * and end of the cursor/selection respectively. - */ - CliRequisition.prototype.update = function(input) { - this.input = input; - this._hints = []; - - var args = this._tokenize(input.typed); - this._split(args); - - if (this.commandAssignment.value) { - this._assign(args); - } - - this._updateHints(); - }; - - /** - * Return an array of Status scores so we can create a marked up - * version of the command line input. - */ - CliRequisition.prototype.getInputStatusMarkup = function() { - // 'scores' is an array which tells us what chars are errors - // Initialize with everything VALID - var scores = this.toString().split('').map(function(char) { - return Status.VALID; - }); - // For all chars in all hints, check and upgrade the score - this._hints.forEach(function(hint) { - for (var i = hint.start; i <= hint.end; i++) { - if (hint.status > scores[i]) { - scores[i] = hint.status; - } - } - }, this); - return scores; - }; - - /** - * Reconstitute the input from the args - */ - CliRequisition.prototype.toString = function() { - // All the params - var parts = Object.keys(this._assignments).map(function(name) { - return this._assignments[name].toString(); - }, this); - // Prefix with the command - parts.unshift(this.commandAssignment.toString()); - return parts.join(''); - }; - - var superUpdateHints = CliRequisition.prototype._updateHints; - /** - * Marks up hints in a number of ways: - * - Makes INCOMPLETE hints that are not near the cursor INVALID since - * they can't be completed by typing - * - Finds the most severe hint, and annotates the array with it - * - Finds the hint to display, and also annotates the array with it - * TODO: I'm wondering if array annotation is evil and we should replace - * this with an object. Need to find out more. - */ - CliRequisition.prototype._updateHints = function() { - superUpdateHints.call(this); - - // Not knowing about cursor positioning, the requisition and assignments - // can't know this, but anything they mark as INCOMPLETE is actually - // INVALID unless the cursor is actually inside that argument. - var c = this.input.cursor; - this._hints.forEach(function(hint) { - var startInHint = c.start >= hint.start && c.start <= hint.end; - var endInHint = c.end >= hint.start && c.end <= hint.end; - var inHint = startInHint || endInHint; - if (!inHint && hint.status === Status.INCOMPLETE) { - hint.status = Status.INVALID; - } - }, this); - - Hint.sort(this._hints); - }; - - /** - * Accessor for the hints array. - * While we could just use the hints property, using getHints() is - * preferred for symmetry with Requisition where it needs a function due to - * lack of an atomic update system. - */ - CliRequisition.prototype.getHints = function() { - return this._hints; - }; - - /** - * Look through the arguments attached to our assignments for the assignment - * at the given position. - */ - CliRequisition.prototype.getAssignmentAt = function(position) { - var arg = this.commandAssignment.arg; - if (arg && position <= arg.end) { - return this.commandAssignment; - } - - var names = Object.keys(this._assignments); - for (var i = 0; i < names.length; i++) { - var assignment = this._assignments[names[i]]; - if (assignment.arg && position <= assignment.arg.end) { - return assignment; - } - } - - // We can only have got here if - throw new Error('position (' + position + - ') is off end of requisition (' + this.toString() + ')'); - }; - - /** - * Split up the input taking into account ' and " - */ - CliRequisition.prototype._tokenize = function(typed) { - // For blank input, place a dummy empty argument into the list - if (typed == null || typed.length === 0) { - return [ new Argument(this, '', 0, 0, '') ]; - } - - var OUTSIDE = 1; // The last character was whitespace - var IN_SIMPLE = 2; // The last character was part of a parameter - var IN_SINGLE_Q = 3; // We're inside a single quote: ' - var IN_DOUBLE_Q = 4; // We're inside double quotes: " - - var mode = OUTSIDE; - - // First we un-escape. This list was taken from: - // https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Core_Language_Features#Unicode - // We are generally converting to their real values except for \', \" - // and '\ ' which we are converting to unicode private characters so we - // can distinguish them from ', " and ' ', which have special meaning. - // They need swapping back post-split - see unescape() - typed = typed - .replace(/\\\\/g, '\\') - .replace(/\\b/g, '\b') - .replace(/\\f/g, '\f') - .replace(/\\n/g, '\n') - .replace(/\\r/g, '\r') - .replace(/\\t/g, '\t') - .replace(/\\v/g, '\v') - .replace(/\\n/g, '\n') - .replace(/\\r/g, '\r') - .replace(/\\ /g, '\uF000') - .replace(/\\'/g, '\uF001') - .replace(/\\"/g, '\uF002'); - - function unescape(str) { - return str - .replace(/\uF000/g, ' ') - .replace(/\uF001/g, '\'') - .replace(/\uF002/g, '"'); - } - - var i = 0; - var start = 0; // Where did this section start? - var priorSpace = ''; - var args = []; - - while (true) { - if (i >= typed.length) { - // There is no more - tidy up - if (mode !== OUTSIDE) { - var str = unescape(typed.substring(start, i)); - args.push(new Argument(this, str, start, i, priorSpace)); - } - else { - if (i !== start) { - // There's a bunch of whitespace at the end of the - // command treat it as another arg without any content - priorSpace = typed.substring(start, i); - args.push(new Argument(this, '', i, i, priorSpace)); - } - } - break; - } - - var c = typed[i]; - switch (mode) { - case OUTSIDE: - if (c === '\'') { - priorSpace = typed.substring(start, i); - mode = IN_SINGLE_Q; - start = i + 1; - } - else if (c === '"') { - priorSpace = typed.substring(start, i); - mode = IN_DOUBLE_Q; - start = i + 1; - } - else if (/ /.test(c)) { - // Still whitespace, do nothing - } - else { - priorSpace = typed.substring(start, i); - mode = IN_SIMPLE; - start = i; - } - break; - - case IN_SIMPLE: - // There is an edge case of xx'xx which we are assuming to - // be a single parameter (and same with ") - if (c === ' ') { - var str = unescape(typed.substring(start, i)); - args.push(new Argument(this, str, start, i, priorSpace)); - mode = OUTSIDE; - start = i; - priorSpace = ''; - } - break; - - case IN_SINGLE_Q: - if (c === '\'') { - var str = unescape(typed.substring(start, i)); - args.push(new Argument(this, str, start, i, priorSpace)); - mode = OUTSIDE; - start = i + 1; - priorSpace = ''; - } - break; - - case IN_DOUBLE_Q: - if (c === '"') { - var str = unescape(typed.substring(start, i)); - args.push(new Argument(this, str, start, i, priorSpace)); - mode = OUTSIDE; - start = i + 1; - priorSpace = ''; - } - break; - } - - i++; - } - - return args; - }; - - /** - * Looks in the canon for a command extension that matches what has been - * typed at the command line. - */ - CliRequisition.prototype._split = function(args) { - var argsUsed = 1; - var arg; - - while (argsUsed <= args.length) { - var arg = Argument.merge(args, 0, argsUsed); - this.commandAssignment.setArgument(arg); - - if (!this.commandAssignment.value) { - // Not found. break with value == null - break; - } - - /* - // Previously we needed a way to hide commands depending context. - // We have not resurrected that feature yet. - if (!keyboard.flagsMatch(command.predicates, this.flags)) { - // If the predicates say 'no match' then go LA LA LA - command = null; - break; - } - */ - - if (this.commandAssignment.value.exec) { - // Valid command, break with command valid - for (var i = 0; i < argsUsed; i++) { - args.shift(); - } - break; - } - - argsUsed++; - } - - return; - }; - - /** - * Work out which arguments are applicable to which parameters. - *

    This takes #_command.params and #_unparsedArgs and creates a map of - * param names to 'assignment' objects, which have the following properties: - *

      - *
    • param - The matching parameter. - *
    • index - Zero based index into where the match came from on the input - *
    • value - The matching input - *
    - */ - CliRequisition.prototype._assign = function(args) { - if (args.length === 0) { - this.setDefaultValues(); - return; - } - - // Create an error if the command does not take parameters, but we have - // been given them ... - if (this.assignmentCount === 0) { - // TODO: previously we were doing some extra work to avoid this if - // we determined that we had args that were all whitespace, but - // probably given our tighter tokenize() this won't be an issue? - this._hints.push(new Hint(Status.INVALID, - this.commandAssignment.value.name + ' does not take any parameters', - Argument.merge(args))); - return; - } - - // Special case: if there is only 1 parameter, and that's of type - // text we put all the params into the first param - if (this.assignmentCount === 1) { - var assignment = this.getAssignment(0); - if (assignment.param.type.name === 'text') { - assignment.setArgument(Argument.merge(args)); - return; - } - } - - var assignments = this.cloneAssignments(); - var names = this.getParameterNames(); - - // Extract all the named parameters - var used = []; - assignments.forEach(function(assignment) { - var namedArgText = '--' + assignment.name; - - var i = 0; - while (true) { - var arg = args[i]; - if (namedArgText !== arg.text) { - i++; - if (i >= args.length) { - break; - } - continue; - } - - // boolean parameters don't have values, default to false - if (assignment.param.type.name === 'boolean') { - assignment.setValue(true); - } - else { - if (i + 1 < args.length) { - // Missing value portion of this named param - this._hints.push(new Hint(Status.INCOMPLETE, - 'Missing value for: ' + namedArgText, - args[i])); - } - else { - args.splice(i + 1, 1); - assignment.setArgument(args[i + 1]); - } - } - - lang.arrayRemove(names, assignment.name); - args.splice(i, 1); - // We don't need to i++ if we splice - } - }, this); - - // What's left are positional parameters assign in order - names.forEach(function(name) { - var assignment = this.getAssignment(name); - if (args.length === 0) { - // No more values - assignment.setValue(undefined); // i.e. default - } - else { - var arg = args[0]; - args.splice(0, 1); - assignment.setArgument(arg); - } - }, this); - - if (args.length > 0) { - var remaining = Argument.merge(args); - this._hints.push(new Hint(Status.INVALID, - 'Input \'' + remaining.text + '\' makes no sense.', - remaining)); - } - }; - -})(); -exports.CliRequisition = CliRequisition; - - -}); diff --git a/plugins/cockpit/index.js b/plugins/cockpit/index.js deleted file mode 100644 index 5011915b..00000000 --- a/plugins/cockpit/index.js +++ /dev/null @@ -1,59 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - -exports.startup = function(data, reason) { - - require('cockpit/cli').startup(data, reason); - window.testCli = require('cockpit/test/testCli'); - - require('cockpit/ui/settings').startup(data, reason); - require('cockpit/ui/cliView').startup(data, reason); -}; - -/* -exports.shutdown(data, reason) { - deps.forEach(function(dep) { - var module = require(dep); - if (typeof module.shutdown === "function") { - module.shutdown(data, reason); - } - }); -}; -*/ -}); diff --git a/plugins/cockpit/test/assert.js b/plugins/cockpit/test/assert.js deleted file mode 100644 index d0d1b93a..00000000 --- a/plugins/cockpit/test/assert.js +++ /dev/null @@ -1,317 +0,0 @@ -/* ***** 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) - * - * 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(function(require, exports, module) { - -var test = { - - success: function(message) { - console.log(message); - }, - - fail: function(message) { - test._recordThrow("fail", arguments); - }, - - assertTrue: function(value) { - if (!value) { - test._recordThrow("assertTrue", arguments); - } - }, - - verifyTrue: function(value) { - if (!value) { - test._recordTrace("verifyTrue", arguments); - } - }, - - assertFalse: function(value) { - if (value) { - test._recordThrow("assertFalse", arguments); - } - }, - - verifyFalse: function(value) { - if (value) { - test._recordTrace("verifyFalse", arguments); - } - }, - - assertNull: function(value) { - if (value !== null) { - test._recordThrow("assertNull", arguments); - } - }, - - verifyNull: function(value) { - if (value !== null) { - test._recordTrace("verifyNull", arguments); - } - }, - - assertNotNull: function(value) { - if (value === null) { - test._recordThrow("assertNotNull", arguments); - } - }, - - verifyNotNull: function(value) { - if (value === null) { - test._recordTrace("verifyNotNull", arguments); - } - }, - - assertUndefined: function(value) { - if (value !== undefined) { - test._recordThrow("assertUndefined", arguments); - } - }, - - verifyUndefined: function(value) { - if (value !== undefined) { - test._recordTrace("verifyUndefined", arguments); - } - }, - - assertNotUndefined: function(value) { - if (value === undefined) { - test._recordThrow("assertNotUndefined", arguments); - } - }, - - verifyNotUndefined: function(value) { - if (value === undefined) { - test._recordTrace("verifyNotUndefined", arguments); - } - }, - - assertNaN: function(value) { - if (!isNaN(value)) { - test._recordThrow("assertNaN", arguments); - } - }, - - verifyNaN: function(value) { - if (!isNaN(value)) { - test._recordTrace("verifyNaN", arguments); - } - }, - - assertNotNaN: function(value) { - if (isNaN(value)) { - test._recordThrow("assertNotNaN", arguments); - } - }, - - verifyNotNaN: function(value) { - if (isNaN(value)) { - test._recordTrace("verifyNotNaN", arguments); - } - }, - - assertEqual: function(expected, actual) { - if (!test._isEqual(expected, actual)) { - test._recordThrow("assertEqual", arguments); - } - }, - - verifyEqual: function(expected, actual) { - if (!test._isEqual(expected, actual)) { - test._recordTrace("verifyEqual", arguments); - } - }, - - assertNotEqual: function(expected, actual) { - if (test._isEqual(expected, actual)) { - test._recordThrow("assertNotEqual", arguments); - } - }, - - verifyNotEqual: function(expected, actual) { - if (test._isEqual(expected, actual)) { - test._recordTrace("verifyNotEqual", arguments); - } - }, - - assertSame: function(expected, actual) { - if (expected !== actual) { - test._recordThrow("assertSame", arguments); - } - }, - - verifySame: function(expected, actual) { - if (expected !== actual) { - test._recordTrace("verifySame", arguments); - } - }, - - assertNotSame: function(expected, actual) { - if (expected !== actual) { - test._recordThrow("assertNotSame", arguments); - } - }, - - verifyNotSame: function(expected, actual) { - if (expected !== actual) { - test._recordTrace("verifyNotSame", arguments); - } - }, - - _recordTrace: function() { - test._record.apply(this, arguments); - console.trace(); - }, - - _recordThrow: function() { - test._record.apply(this, arguments); - throw new Error(); - }, - - _record: function() { - console.error(arguments); - var message = arguments[0] + "("; - var data = arguments[1]; - if (typeof data == "string") { - message += data; - } - else { - for (var i = 0; i < data.length; i++) { - if (i != 0){message += ", ";} - message += data[i]; - } - } - message += ")"; - console.log(message); - }, - - _isEqual: function(expected, actual, depth) { - if (!depth){depth = 0;} - // Rather than failing we assume that it works! - if (depth > 10) { - return true; - } - - if (expected == null) { - if (actual != null) { - console.log("expected: null, actual non-null: ", actual); - return false; - } - return true; - } - - if (typeof(expected) == "number" && isNaN(expected)) { - if (!(typeof(actual) == "number" && isNaN(actual))) { - console.log("expected: NaN, actual non-NaN: ", actual); - return false; - } - return true; - } - - if (actual == null) { - if (expected != null) { - console.log("actual: null, expected non-null: ", expected); - return false; - } - return true; // we wont get here of course ... - } - - if (typeof expected == "object") { - if (!(typeof actual == "object")) { - console.log("expected object, actual not an object"); - return false; - } - - var actualLength = 0; - for (var prop in actual) { - if (typeof actual[prop] != "function" || - typeof expected[prop] != "function") { - var nest = test._isEqual(actual[prop], expected[prop], depth + 1); - if (typeof nest != "boolean" || !nest) { - console.log("element '" + prop + "' does not match: " + nest); - return false; - } - } - actualLength++; - } - - // need to check length too - var expectedLength = 0; - for (prop in expected) expectedLength++; - if (actualLength != expectedLength) { - console.log("expected object size = " + expectedLength + - ", actual object size = " + actualLength); - return false; - } - return true; - } - - if (actual != expected) { - console.log("expected = " + expected + " (type=" + typeof expected + "), " + - "actual = " + actual + " (type=" + typeof actual + ")"); - return false; - } - - if (expected instanceof Array) { - if (!(actual instanceof Array)) { - console.log("expected array, actual not an array"); - return false; - } - if (actual.length != expected.length) { - console.log("expected array length = " + expected.length + - ", actual array length = " + actual.length); - return false; - } - for (var i = 0; i < actual.length; i++) { - var inner = test._isEqual(actual[i], expected[i], depth + 1); - if (typeof inner != "boolean" || !inner) { - console.log("element " + i + " does not match: " + inner); - return false; - } - } - - return true; - } - - return true; - } -}; - - -exports.test = test; - - -}); diff --git a/plugins/cockpit/test/testCli.js b/plugins/cockpit/test/testCli.js deleted file mode 100644 index 26caf643..00000000 --- a/plugins/cockpit/test/testCli.js +++ /dev/null @@ -1,359 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - - -var test = require('cockpit/test/assert').test; -var Status = require('pilot/types').Status; -var settings = require('pilot/settings').settings; -var tokenize = require('cockpit/cli')._tokenize; -var split = require('cockpit/cli')._split; -var CliRequisition = require('cockpit/cli').CliRequisition; - - -exports.testAll = function() { - exports.testTokenize(); - exports.testSplit(); - exports.testCli(); - return "testAll Completed"; -}; - -exports.testTokenize = function() { - var args; - var cli = new CliRequisition(); - - args = cli._tokenize(''); - test.verifyEqual(1, args.length); - test.verifyEqual('', args[0].text); - test.verifyEqual(0, args[0].start); - test.verifyEqual(0, args[0].end); - test.verifyEqual('', args[0].priorSpace); - - args = cli._tokenize('s'); - test.verifyEqual(1, args.length); - test.verifyEqual('s', args[0].text); - test.verifyEqual(0, args[0].start); - test.verifyEqual(1, args[0].end); - test.verifyEqual('', args[0].priorSpace); - - args = cli._tokenize(' '); - test.verifyEqual(1, args.length); - test.verifyEqual('', args[0].text); - test.verifyEqual(1, args[0].start); - test.verifyEqual(1, args[0].end); - test.verifyEqual(' ', args[0].priorSpace); - - args = cli._tokenize('s s'); - test.verifyEqual(2, args.length); - test.verifyEqual('s', args[0].text); - test.verifyEqual(0, args[0].start); - test.verifyEqual(1, args[0].end); - test.verifyEqual('', args[0].priorSpace); - test.verifyEqual('s', args[1].text); - test.verifyEqual(2, args[1].start); - test.verifyEqual(3, args[1].end); - test.verifyEqual(' ', args[1].priorSpace); - - args = cli._tokenize(' 1234 \'12 34\''); - test.verifyEqual(2, args.length); - test.verifyEqual('1234', args[0].text); - test.verifyEqual(1, args[0].start); - test.verifyEqual(5, args[0].end); - test.verifyEqual(' ', args[0].priorSpace); - test.verifyEqual('12 34', args[1].text); - test.verifyEqual(8, args[1].start); - test.verifyEqual(13, args[1].end); - test.verifyEqual(' ', args[1].priorSpace); - - args = cli._tokenize('12\'34 "12 34" \\'); // 12'34 "12 34" \ - test.verifyEqual(3, args.length); - test.verifyEqual('12\'34', args[0].text); - test.verifyEqual(0, args[0].start); - test.verifyEqual(5, args[0].end); - test.verifyEqual('', args[0].priorSpace); - test.verifyEqual('12 34', args[1].text); - test.verifyEqual(7, args[1].start); - test.verifyEqual(12, args[1].end); - test.verifyEqual(' ', args[1].priorSpace); - test.verifyEqual('\\', args[2].text); - test.verifyEqual(14, args[2].start); - test.verifyEqual(15, args[2].end); - test.verifyEqual(' ', args[2].priorSpace); - - args = cli._tokenize('a\\ b \\t\\n\\r \\\'x\\\" \'d'); // a_b \t\n\r \'x\" 'd - test.verifyEqual(4, args.length); - test.verifyEqual('a b', args[0].text); - test.verifyEqual(0, args[0].start); - test.verifyEqual(3, args[0].end); - test.verifyEqual('', args[0].priorSpace); - test.verifyEqual('\t\n\r', args[1].text); - test.verifyEqual(4, args[1].start); - test.verifyEqual(7, args[1].end); - test.verifyEqual(' ', args[1].priorSpace); - test.verifyEqual('\'x"', args[2].text); - test.verifyEqual(8, args[2].start); - test.verifyEqual(11, args[2].end); - test.verifyEqual(' ', args[2].priorSpace); - test.verifyEqual('d', args[3].text); - test.verifyEqual(13, args[3].start); - test.verifyEqual(14, args[3].end); - test.verifyEqual(' ', args[3].priorSpace); - - return "testTokenize Completed"; -}; - -exports.testSplit = function() { - var args; - var cli = new CliRequisition(); - - args = cli._tokenize('s'); - cli._split(args); - test.verifyEqual(1, args.length); - test.verifyEqual('s', args[0].text); - test.verifyNull(cli.commandAssignment.value); - - args = cli._tokenize('set'); - cli._split(args); - test.verifyEqual([], args); - test.verifyEqual('set', cli.commandAssignment.value.name); - - args = cli._tokenize('set a b'); - cli._split(args); - test.verifyEqual('set', cli.commandAssignment.value.name); - test.verifyEqual(2, args.length); - test.verifyEqual('a', args[0].text); - test.verifyEqual('b', args[1].text); - - // TODO: add tests for sub commands - return "testSplit Completed"; -}; - -exports.testCli = function() { - var settingAssignment; - var valueAssignment; - var cli = new CliRequisition(); - var debug = true; - var worst; - var display; - var statuses; - - function update(input) { - cli.update(input); - - if (debug) { - console.log('####### TEST: typed="' + input.typed + - '" cur=' + input.cursor.start + - ' cli=', cli); - } - - worst = cli.getWorstHint(); - display = cli.getAssignmentAt(input.cursor.start).getHint(); - statuses = cli.getInputStatusMarkup().map(function(status) { - return status.valueOf(); - }).join(''); - - if (cli.commandAssignment.value && cli.commandAssignment.value.name === 'set') { - settingAssignment = cli.getAssignment('setting'); - valueAssignment = cli.getAssignment('value'); - } - else { - settingAssignment = undefined; - valueAssignment = undefined; - } - } - - function verifyPredictionsContains(name, predictions) { - return predictions.every(function(prediction) { - return name === prediction || name === prediction.name; - }, this); - } - - var historyLengthSetting = settings.getSetting('historyLength'); - - update({ typed: '', cursor: { start: 0, end: 0 } }); - test.verifyEqual('', statuses); - test.verifyEqual(1, cli._hints.length); - test.verifyEqual(Status.INCOMPLETE, display.status); - test.verifyEqual(0, display.start); - test.verifyEqual(0, display.end); - test.verifyEqual(display, worst); - test.verifyNull(cli.commandAssignment.value); - - update({ typed: ' ', cursor: { start: 1, end: 1 } }); - test.verifyEqual('0', statuses); - test.verifyEqual(1, cli._hints.length); - test.verifyEqual(Status.INCOMPLETE, display.status); - test.verifyEqual(1, display.start); - test.verifyEqual(1, display.end); - test.verifyEqual(display, worst); - test.verifyNull(cli.commandAssignment.value); - - update({ typed: ' ', cursor: { start: 0, end: 0 } }); - test.verifyEqual('0', statuses); - test.verifyEqual(1, cli._hints.length); - test.verifyEqual(Status.INCOMPLETE, display.status); - test.verifyEqual(1, display.start); - test.verifyEqual(1, display.end); - test.verifyEqual(display, worst); - test.verifyNull(cli.commandAssignment.value); - - update({ typed: 's', cursor: { start: 1, end: 1 } }); - test.verifyEqual('1', statuses); - test.verifyEqual(1, cli._hints.length); - test.verifyEqual(Status.INCOMPLETE, display.status); - test.verifyEqual(0, display.start); - test.verifyEqual(1, display.end); - test.verifyEqual(display, worst); - test.verifyTrue(display.predictions.length > 0); - // This is slightly fragile because it depends on the configuration - // TODO: Mock, but first we need a way to have a clear canon. - test.verifyTrue(display.predictions.length < 20); - verifyPredictionsContains('set', display.predictions); - test.verifyNull(cli.commandAssignment.value); - - update({ typed: 'set', cursor: { start: 3, end: 3 } }); - test.verifyEqual('000', statuses); - test.verifyEqual(1, cli._hints.length); - test.verifyEqual(Status.VALID, display.status); - test.verifyEqual(0, display.start); - test.verifyEqual(3, display.end); - test.verifyEqual('set', cli.commandAssignment.value.name); - - update({ typed: 'set ', cursor: { start: 4, end: 4 } }); - test.verifyEqual('0000', statuses); - test.verifyEqual(2, cli._hints.length); - test.verifyEqual(Status.VALID, display.status); - test.verifyEqual(4, display.start); - test.verifyEqual(4, display.end); - test.verifyEqual(display, worst); - test.verifyEqual('set', cli.commandAssignment.value.name); - - update({ typed: 'set ', cursor: { start: 2, end: 2 } }); - test.verifyEqual('0000', statuses); - test.verifyEqual(2, cli._hints.length); - test.verifyEqual(Status.VALID, display.status); - test.verifyEqual(0, display.start); - test.verifyEqual(3, display.end); - test.verifyEqual('set', cli.commandAssignment.value.name); - - update({ typed: 'set h', cursor: { start: 5, end: 5 } }); - test.verifyEqual('00001', statuses); - test.verifyEqual(2, cli._hints.length); - test.verifyEqual(Status.INCOMPLETE, display.status); - test.verifyEqual(4, display.start); - test.verifyEqual(5, display.end); - test.verifyTrue(display.predictions.length > 0); - verifyPredictionsContains('historyLength', display.predictions); - test.verifyEqual('set', cli.commandAssignment.value.name); - test.verifyEqual('h', settingAssignment.arg.text); - test.verifyEqual(undefined, settingAssignment.value); - - update({ typed: 'set historyLengt', cursor: { start: 16, end: 16 } }); - test.verifyEqual('0000111111111111', statuses); - test.verifyEqual(2, cli._hints.length); - test.verifyEqual(Status.INCOMPLETE, display.status); - test.verifyEqual(4, display.start); - test.verifyEqual(16, display.end); - test.verifyEqual(1, display.predictions.length); - verifyPredictionsContains('historyLength', display.predictions); - test.verifyEqual('set', cli.commandAssignment.value.name); - test.verifyEqual('historyLengt', settingAssignment.arg.text); - test.verifyEqual(undefined, settingAssignment.value); - - update({ typed: 'set historyLengt', cursor: { start: 1, end: 1 } }); - test.verifyEqual('0000222222222222', statuses); - test.verifyEqual(2, cli._hints.length); - test.verifyEqual(Status.VALID, display.status); - test.verifyEqual(0, display.start); - test.verifyEqual(3, display.end); - test.verifyEqual(Status.INVALID, worst.status); - test.verifyEqual(4, worst.start); - test.verifyEqual(16, worst.end); - test.verifyEqual(1, worst.predictions.length); - verifyPredictionsContains('historyLength', worst.predictions); - test.verifyEqual('set', cli.commandAssignment.value.name); - test.verifyEqual('historyLengt', settingAssignment.arg.text); - test.verifyEqual(undefined, settingAssignment.value); - - update({ typed: 'set historyLengt ', cursor: { start: 17, end: 17 } }); - // TODO: would '00002222222222220' be better? - test.verifyEqual('00002222222222222', statuses); - test.verifyEqual(3, cli._hints.length); - test.verifyEqual(Status.VALID, display.status); - test.verifyEqual(17, display.start); - test.verifyEqual(17, display.end); - test.verifyEqual(Status.INVALID, worst.status); - test.verifyEqual(4, worst.start); - test.verifyEqual(16, worst.end); - test.verifyEqual(1, worst.predictions.length); - verifyPredictionsContains('historyLength', worst.predictions); - test.verifyEqual('set', cli.commandAssignment.value.name); - test.verifyEqual('historyLengt', settingAssignment.arg.text); - test.verifyEqual(undefined, settingAssignment.value); - - update({ typed: 'set historyLength', cursor: { start: 17, end: 17 } }); - test.verifyEqual('00000000000000000', statuses); - test.verifyEqual(2, cli._hints.length); - test.verifyEqual('set', cli.commandAssignment.value.name); - test.verifyEqual('historyLength', settingAssignment.arg.text); - test.verifyEqual(historyLengthSetting, settingAssignment.value); - - update({ typed: 'set historyLength ', cursor: { start: 18, end: 18 } }); - test.verifyEqual('000000000000000000', statuses); - test.verifyEqual(3, cli._hints.length); - test.verifyEqual('set', cli.commandAssignment.value.name); - test.verifyEqual('historyLength', settingAssignment.arg.text); - test.verifyEqual(historyLengthSetting, settingAssignment.value); - - update({ typed: 'set historyLength 6', cursor: { start: 19, end: 19 } }); - test.verifyEqual('0000000000000000000', statuses); - test.verifyEqual(3, cli._hints.length); - test.verifyEqual('set', cli.commandAssignment.value.name); - test.verifyEqual('historyLength', settingAssignment.arg.text); - test.verifyEqual(historyLengthSetting, settingAssignment.value); - test.verifyEqual('6', valueAssignment.arg.text); - test.verifyEqual(6, valueAssignment.value); - test.verifyEqual('number', typeof valueAssignment.value); - - // TODO: Add test to see that a command without mandatory param causes INVALID - - return "testCli Completed"; -}; - - -}); diff --git a/plugins/cockpit/test/testNothing.js b/plugins/cockpit/test/testNothing.js deleted file mode 100644 index 567b575a..00000000 --- a/plugins/cockpit/test/testNothing.js +++ /dev/null @@ -1,40 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - -}); diff --git a/plugins/cockpit/ui/cliView.css b/plugins/cockpit/ui/cliView.css deleted file mode 100644 index dafd72de..00000000 --- a/plugins/cockpit/ui/cliView.css +++ /dev/null @@ -1,164 +0,0 @@ - -#cockpit { - background: transparent; - border: none; outline: none; - font-family: consolas, courier, monospace; - font-size: 120%; - padding-left: 16px; -} - -.cptOutput { - border: 1px solid #AAA; - -moz-border-radius-topleft: 10px; - -moz-border-radius-topright: 10px; - border-top-left-radius: 4px; border-top-right-radius: 4px; - padding: 10px; - margin: 0 15px; - background: #DDD; color: #000; - overflow: auto; - position: absolute; - z-index: 999; - display: none; -} - -#cockpit:focus ~ .cptOutput { - display: block; -} - -.cptCompletion { - color: #999; - padding: 0 0 5px 2px; - position: absolute; - z-index: -1000; - font-family: consolas, courier, monospace; - font-size: 120%; -} - -.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; -} - -.cptHints ul { margin: 0; padding: 0 15px; } - -#cockpit:focus ~ .cptHints { - display: block; -} - -#cockpit:focus ~ .cptHints.cptNoHints { - display: none; -} - -.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 article { - margin-left: 25px; - padding: 8px; - z-index: 1; - color: @text; - display: block; - border: 2px @border_bg solid; - border-bottom: 0; - font-size: 90%; - -moz-border-top-colors: @border_bg @border_fg; - -moz-border-left-colors: @border_bg @border_fg; - -moz-border-right-colors: @border_bg @bg; - -moz-border-radius-topleft: 10px; - -moz-border-radius-topright: 10px; - border-top-left-radius: 10px; border-top-right-radius: 10px; - background: @input_bg2; - background: -moz-linear-gradient(top, @input_bg_light, @input_bg); - background: -webkit-gradient(linear, left top, left bottom, from(@input_bg_light), to(@input_bg)); - -webkit-box-shadow: rgba(0, 0, 0, 0.5) 0px 1px 10px 3px; - -moz-box-shadow: rgba(0, 0, 0, 0.5) 0px 1px 10px 3px; - max-width: 500px; -} -.cptHints article h1 { font-size: 110%; text-align: center; } -.cptHints article h2 { font-size: 95%; } -.cptHints article h3 { font-size: 90%; } -.cptHints article table th, -.cptHints article label { color: @hi_text; } -.cptHints article h1, -.cptHints article h2, -.cptHints article h3 { margin: 2px 0 1px 0; color: @hi_text; } -.cptHints article p, -.cptHints article pre, - - - - - -/* Global visual styles */ -.cptBrackets { color: @hi_text; } -.cptGt { color: @theme_text; font-weight: bold; font-size: 120%; } - -/* Use absolute positioning to put all children 100%x100% */ -.cptStack { - position: relative; -} -.cptStack > * { - position: absolute; - top: 0; height: 100%; bottom: 0; left: 0; width: 100%; right: 0; -} - - - - - - - - -/* The input area */ -.cptInput { - border-top: 1px solid @border_bg; - background: @input_bg; - background: -moz-linear-gradient(top, @input_bg, @input_bg2); - background: -webkit-gradient(linear, left top, left bottom, from(@input_bg), to(@input_bg2)); - - position: absolute; - height: 25px; right: 0; bottom: 0; left: 0; -} - -.cptKbd { - position: absolute; - top: 0; right: 0; bottom: 0; left: 40px; -} - -.cptOutput input.cptCliInput { - color: @hi_text; font-size: 120%; font-family: @fonts; - background: transparent; - outline: none; border: 0; - box-shadow: none; -moz-box-shadow: none; -webkit-box-shadow: none; - padding: 4px 0 0 0; - width: 100%; -} -.cptOutput input.cptCliInput:focus { - outline: none; border: 0; - box-shadow: none; -moz-box-shadow: none; -webkit-box-shadow: none; -} - - diff --git a/plugins/cockpit/ui/cliView.js b/plugins/cockpit/ui/cliView.js deleted file mode 100644 index ee12e65f..00000000 --- a/plugins/cockpit/ui/cliView.js +++ /dev/null @@ -1,369 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - - -var editorCss = require("text!cockpit/ui/cliView.css"); -var dom = require("pilot/dom"); -dom.importCssString(editorCss); - -var canon = require("pilot/canon"); -var Status = require('pilot/types').Status; -var keyutil = require('pilot/keyboard/keyutil'); - -var CliRequisition = require('cockpit/cli').CliRequisition; -var Hint = require('cockpit/cli').Hint; -var RequestView = require('cockpit/ui/requestView').RequestView; - -var NO_HINT = new Hint(Status.VALID, '', 0, 0); - -/** - * On startup we need to: - * 1. Add 3 sets of elements to the DOM for: - * - command line output - * - input hints - * - completion - * 2. Attach a set of events so the command line works - */ -exports.startup = function(data, reason) { - var cli = new CliRequisition(data.env); - var cliView = new CliView(cli, data.env); -}; - -/** - * A class to handle the simplest UI implementation - */ -function CliView(cli, env) { - this.cli = cli; - this.doc = document; - this.win = this.doc.defaultView; - - // TODO: we should have a better way to specify command lines??? - this.element = this.doc.getElementById('cockpit'); - if (!this.element) { - console.log('No element with an id of cockpit. Bailing on cli'); - return; - } - - this.settings = env.settings; - this.hintDirection = this.settings.getSetting('hintDirection'); - this.outputDirection = this.settings.getSetting('outputDirection'); - this.outputHeight = this.settings.getSetting('outputHeight'); - - // If the requisition tells us something has changed, we use this to know - // if we should ignore it - this.isUpdating = false; - - this.createElements(); - this.update(); -} -CliView.prototype = { - /** - * Create divs for completion, hints and output - */ - createElements: function() { - var input = this.element; - - this.completer = this.doc.createElement('div'); - this.completer.className = 'cptCompletion VALID'; - input.parentNode.insertBefore(this.completer, input.nextSibling); - - this.hinter = this.doc.createElement('div'); - this.hinter.className = 'cptHints'; - input.parentNode.insertBefore(this.hinter, input.nextSibling); - - this.output = this.doc.createElement('div'); - this.output.className = 'cptOutput'; - input.parentNode.insertBefore(this.output, input.nextSibling); - - this.win.addEventListener('resize', this.resizer.bind(this), false); - this.hintDirection.addEventListener('change', this.resizer.bind(this)); - this.outputDirection.addEventListener('change', this.resizer.bind(this)); - this.resizer(); - - var setMaxOutputHeight = function() { - this.output.style.maxHeight = this.outputHeight.get() + 'px'; - }.bind(this); - this.outputHeight.addEventListener('change', setMaxOutputHeight); - setMaxOutputHeight(); - - canon.addEventListener('output', function(ev) { - new RequestView(ev.request, this); - }.bind(this)); - - keyutil.addKeyDownListener(input, this.onKeyDown.bind(this)); - input.addEventListener('keyup', this.onKeyUp.bind(this), true); - // cursor position affects hint severity. TODO: shortcuts for speed - input.addEventListener('mouseup', function(ev) { - this.isUpdating = true; - this.update(); - this.isUpdating = false; - }.bind(this), false); - - this.cli.addEventListener('argumentChange', this.onArgChange.bind(this)); - }, - - /** - * We need to see the output of the latest command entered - */ - scrollOutputToBottom: function() { - // Certain browsers have a bug such that scrollHeight is too small - // when content does not fill the client area of the element - var scrollHeight = Math.max(this.output.scrollHeight, this.output.clientHeight); - this.output.scrollTop = scrollHeight - this.output.clientHeight; - }, - - /** - * To be called on window resize or any time we want to align the elements - * with the input box. - */ - resizer: function() { - var rect = this.element.getClientRects()[0]; - - this.completer.style.top = rect.top + 'px'; - this.completer.style.height = rect.height + 'px'; - this.completer.style.left = rect.left + 'px'; - this.completer.style.width = rect.width + 'px'; - - if (this.hintDirection.get() === 'below') { - this.hinter.style.top = rect.bottom + 'px'; - this.hinter.style.bottom = 'auto'; - } - else { - this.hinter.style.top = 'auto'; - this.hinter.style.bottom = (this.win.innerHeight - rect.top) + 'px'; - } - this.hinter.style.left = (rect.left + 30) + 'px'; - this.hinter.style.maxWidth = (rect.width - 110) + 'px'; - - if (this.outputDirection.get() === 'below') { - this.output.style.top = rect.bottom + 'px'; - this.output.style.bottom = 'auto'; - } - else { - this.output.style.top = 'auto'; - this.output.style.bottom = (this.win.innerHeight - rect.top) + 'px'; - } - this.output.style.left = rect.left + 'px'; - this.output.style.width = (rect.width - 80) + 'px'; - }, - - /** - * Ensure that TAB isn't handled by the browser - */ - onKeyDown: function(ev) { - var handled; - // var handled = keyboardManager.processKeyEvent(ev, this, { - // isCommandLine: true, isKeyUp: false - // }); - if (ev.keyCode === keyutil.KeyHelper.KEY.TAB || - ev.keyCode === keyutil.KeyHelper.KEY.UP || - ev.keyCode === keyutil.KeyHelper.KEY.DOWN) { - return true; - } - return handled; - }, - - /** - * The main keyboard processing loop - */ - onKeyUp: function(ev) { - var handled; - /* - var handled = keyboardManager.processKeyEvent(ev, this, { - isCommandLine: true, isKeyUp: true - }); - */ - - // RETURN does a special exec/highlight thing - if (ev.keyCode === keyutil.KeyHelper.KEY.RETURN) { - var worst = this.cli.getWorstHint(); - // Deny RETURN unless the command might work - if (worst.status === Status.VALID) { - this.cli.exec(); - this.element.value = ''; - } - else { - // If we've denied RETURN because the command was not VALID, - // select the part of the command line that is causing problems - // TODO: if there are 2 errors are we picking the right one? - this.element.selectionStart = worst.start; - this.element.selectionEnd = worst.end; - } - } - - this.update(); - - // Special actions which delegate to the assignment - var current = this.cli.getAssignmentAt(this.element.selectionStart); - if (current) { - // TAB does a special complete thing - if (ev.keyCode === keyutil.KeyHelper.KEY.TAB) { - current.complete(); - this.update(); - } - - // UP/DOWN look for some history - if (ev.keyCode === keyutil.KeyHelper.KEY.UP) { - current.increment(); - this.update(); - } - if (ev.keyCode === keyutil.KeyHelper.KEY.DOWN) { - current.decrement(); - this.update(); - } - } - - return handled; - }, - - /** - * Actually parse the input and make sure we're all up to date - */ - update: function() { - this.isUpdating = true; - var input = { - typed: this.element.value, - cursor: { - start: this.element.selectionStart, - end: this.element.selectionEnd - } - }; - this.cli.update(input); - - var display = this.cli.getAssignmentAt(input.cursor.start).getHint(); - - // 1. Update the completer with prompt/error marker/TAB info - this.completer.classList.remove(Status.VALID.toString()); - this.completer.classList.remove(Status.INCOMPLETE.toString()); - this.completer.classList.remove(Status.INVALID.toString()); - // TODO: borked implementation? This is modern browser only. Fix - // dom.removeCssClass(completer, Status.VALID.toString()); - // dom.removeCssClass(completer, Status.INCOMPLETE.toString()); - // dom.removeCssClass(completer, Status.INVALID.toString()); - - var completion = '> '; - if (this.element.value.length > 0) { - var scores = this.cli.getInputStatusMarkup(); - completion += this.markupStatusScore(scores); - } - - // Display the "-> prediction" at the end of the completer - if (this.element.value.length > 0 && - display.predictions && display.predictions.length > 0) { - var tab = display.predictions[0]; - completion += '  ⇥ ' + (tab.name ? tab.name : tab); - } - this.completer.innerHTML = completion; - this.completer.classList.add(this.cli.getWorstHint().status.toString()); - // dom.addCssClass(input, this.cli.getWorstHint().status.toString()); - - // 2. Update the hint element - var hint = ''; - if (this.element.value.length !== 0) { - hint += display.message; - if (display.predictions && display.predictions.length > 0) { - hint += ': [ '; - display.predictions.forEach(function(prediction) { - hint += (prediction.name ? prediction.name : prediction); - hint += ' | '; - }, this); - hint = hint.replace(/\| $/, ']'); - } - } - - this.hinter.innerHTML = hint; - if (hint.length === 0) { - this.hinter.classList.add('cptNoHints'); - } - else { - this.hinter.classList.remove('cptNoHints'); - } - - this.isUpdating = false; - }, - - /** - * Markup an array of Status values with spans - */ - markupStatusScore: function(scores) { - var completion = ''; - // Create mark-up - var i = 0; - var lastStatus = -1; - while (true) { - if (lastStatus !== scores[i]) { - completion += ''; - lastStatus = scores[i]; - } - completion += this.element.value[i]; - i++; - if (i === this.element.value.length) { - completion += ''; - break; - } - if (lastStatus !== scores[i]) { - completion += ''; - } - } - - return completion; - }, - - /** - * Update the input element to reflect the changed argument - */ - onArgChange: function(ev) { - if (this.isUpdating) { - return; - } - - var prefix = this.element.value.substring(0, ev.argument.start); - var suffix = this.element.value.substring(ev.argument.end); - var insert = typeof ev.text === 'string' ? ev.text : ev.text.name; - this.element.value = prefix + insert + suffix; - // Fix the cursor. - var insertEnd = (prefix + insert).length; - this.element.selectionStart = insertEnd; - this.element.selectionEnd = insertEnd; - } -}; -exports.CliView = CliView; - - -}); diff --git a/plugins/cockpit/ui/images/closer.png b/plugins/cockpit/ui/images/closer.png deleted file mode 100644 index d49bf2040a11eac0583fe8c5ba977d8289e0454a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 669 zcmV;O0%HA%P)Wa|n@xYW+l8iS+;6d1psFfdE?15H-YXW1r8yXj#Wq;*i%zG*0ScBRiG$BOX$>Fh0z^@S&*%He+yN;V z3_fJni;qSlTy_ue?9O+r2TriFXM=2x@bq>K>9u3LYb@ZPBfu~WtIcLJWR~S-zuyOe zZ$36qziwi6X^8EOuh0!0A(x50mV$3>34$PiVu=x1FP8`+=kZWRWXr_vp@5ZhBV2S( z_sOgqM<)~BFRMuX`xz__sJF>vLN5nJR`BX&2(+<;AHPI+JRSrB0TMtmm&?7MOD>g4amiJyRe!x+N4wqTe!801 z>qRIO;*!f|v!#EuN-LdClgKy!Bl1U?OlB_f-vSH(!8j5q2U-HB00000NkvXXu0mjf D?{qAq diff --git a/plugins/cockpit/ui/images/dot_clear.gif b/plugins/cockpit/ui/images/dot_clear.gif deleted file mode 100644 index 1d9a4f524c97fa9d148cc15d7e114acce53520a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42 rcmZ?wbhEHbWMp7uX!y@?;J^U}1_s5SEQ~;kK?g*DWEdD3jTo!}%isql diff --git a/plugins/cockpit/ui/images/minus.png b/plugins/cockpit/ui/images/minus.png deleted file mode 100644 index 4c029f119428c7a7bec59c874033989c9ed1dbb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 604 zcmV-i0;BzjP)Px#24YJ`L;%tN(g4!zrp4d@000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXN1 z4ly#a3B!>900G=dL_t(2&xMjPOB-<*#((#|mxPc%L=Hp)B3u?rC#S9%X0I&YaKY(w*(Qr77mb=c<*zI;Z!0~)O_oFBxNfH2RwHn44R##WYz`b)K*qjFvh&SyuAGC?Ck7#z+^I+7;7z!MuUG5 z$1x(p=H})d&~{bza5kHn<;igz^BhG{aC39hTw7Z^bVX!$u~?9%X}R!t2B=o6<-d!? z0ukADRrO_>rZ|p6Q51ZCKjp=`ePX=+?XdgVC(m;LRMmGy(6}nU~DuRsOm3QRWCfx+YW*N5#fJ$o`&Bu!JoFhsKlEz2^R%_hF@--*bPUR_ zT2z%JS1OeXtyYV6yNxks@9gaCXIZ&^zuy6lN28HHolXgYpge73V}q@&tub(LdU`s1 q(p7-{{e1&`c&6kZPfkwClK%n4MbXcFG@p+E00004Tx0C)j~RL^S@K@|QrZmG~B2wH0nvUrdpNm;9CMbtL^5n^i$+aIn^?(HA4aZWV5ov6ELTdbo0FI&wK{O>*+w4vx20?>!`FrQsdJlnHR>OPy zcd~b_n$otK2Za4V;76L-DzNVtaSB-y0*E}{p()372;bw_^6ZZ}PI-92wGS&j#91PI zKs7DSe@(bk%_Y-7gGe}(^>I=@oY#w#*Bu9GZf3^F5WP>3rn}7Ut74&?PWBFvy`A)a zPP5)V!Xd&78LdA?xQ(9mjMYElVd13a#D+Z_7&Y|xU=_C-srWU*6kiZcC!$nw*)9$7 zn6CX+@=AhmkT}X@VSsa5NKe;HZuq)~1$`#h6R+ZTR#D-3j}vF!)ZOnz+5)dI4jl{{ z44Mr{P!L4~VVJN`K!!XTF*LGrKO?IK8z<8w`3e3jI8lUGNUta*C8 zn(P`s>{pjD=7Kek#B;Fw@hxAK%$F&Q6vg9J^Xf~4by_hu-=A!MJ3Znq&n~srbFGPs zH&&aMXZ>nO`|hf|ljc?VPhR!${AbO?W8x_>CU%PFA&Hm8F7cAsOREdwU~R_;ot1_u z(ruCYB-LPGn!NQdT|ZlRy+(fw^-+`=%+gee_kY4FWHg<*4sZI8+sFJD270UUORdLHO0nA4V) z%{fwsET5CQ>B?eK%uw4yQc~9?*JVo2}ze(;aRcp*ceL#HUJSllrgm5wQKR zQu+C;QrUh^8rFfA`ftFz{YAidi-`aL010qNS#tmY3ljhU3ljkVnw%H_00NdtL_t(I z5q(o#NK`=-K4*4jckgaDTDCuRDP^HBaw!UWNh&O;ASiNu=)vCfIg5}W+VxF+@P~Ym zO2`UgB}4;#=|@EA2SHo=K?9W{bFnnc-M#F+d#9P3*ES;$cbIeMeBU`|INu=W9M&~N zgmpk<9Wq+66|zY4`+p7Le+eYmY7Mc?FFB%79*ss<@uD%yWK4ol7Ft=BFDRt1p|)rI z-UZ$pt?0Gmt*xyt+n2jdf=DDn+uN(y2mq6TN41r8eCQPC?~Y~o%Q7CTIo&V7tA#{S zuUP6zHR0wM;_bl5&BtR0N>hGAXC~zt9lolrmeGBUo*g^KDd$y+M>!mS6JN%@`kDci z8p<;xbj_dqxGUsOpI6=UM~k=2po_W)Y-Xac128dbKAk;|iGniJ7w3{clc|niFxXE6 zzE?*|@=PfBH1VWpuUlN;8-OnEraJ+abpW@RqAEtfyqKqa!H2`|&)#ah(qlJF4R26@ zrt~7u0tJm`L35&Ma0e2T0~3|gCZa0fNV3IBik6q;7fNzhQhOIGiQJQ=}WvCq6V$w2n?4LGiHZ zxs5RNcK4D={gm(}1h?UQJ^fufSN*v~Ca9{eHsnq&w;j44k86wIV=S97U~DpfzGEQ2 z`9b2$iPDA6?cL-1>*AxKg|Uf)>A}gZ<(%L6(N$65u;wo_$eG`%t&H%&ll((uPXeHM zTdq(nv9$3G(8;~l`QM`ZBc!`mFTUt#xLz+ou}fhk7K=HAkI#j`ETTA%h>mUF-sMX} zDM;DPjF?9ufF}JlWk07*qoM6N<$ Ef@=2EWdHyG diff --git a/plugins/cockpit/ui/images/pinin.png b/plugins/cockpit/ui/images/pinin.png deleted file mode 100644 index e761de0e29fa8068b3ed731148c11ea72910b112..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1199 zcmV;g1W@~lP)4Tx0C)j~RL^S@K@|QrZmG~B2wH0nvUrdpNm;9CMbtL^5n^i$+aIn^?(HA4aZWV5ov6ELTdbo0FI&wK{O>*+w4vx20?>!`FrQsdJlnHR>OPy zcd~b_n$otK2Za4V;76L-DzNVtaSB-y0*E}{p()372;bw_^6ZZ}PI-92wGS&j#91PI zKs7DSe@(bk%_Y-7gGe}(^>I=@oY#w#*Bu9GZf3^F5WP>3rn}7Ut74&?PWBFvy`A)a zPP5)V!Xd&78LdA?xQ(9mjMYElVd13a#D+Z_7&Y|xU=_C-srWU*6kiZcC!$nw*)9$7 zn6CX+@=AhmkT}X@VSsa5NKe;HZuq)~1$`#h6R+ZTR#D-3j}vF!)ZOnz+5)dI4jl{{ z44Mr{P!L4~VVJN`K!!XTF*LGrKO?IK8z<8w`3e3jI8lUGNUta*C8 zn(P`s>{pjD=7Kek#B;Fw@hxAK%$F&Q6vg9J^Xf~4by_hu-=A!MJ3Znq&n~srbFGPs zH&&aMXZ>nO`|hf|ljc?VPhR!${AbO?W8x_>CU%PFA&Hm8F7cAsOREdwU~R_;ot1_u z(ruCYB-LPGn!NQdT|ZlRy+(fw^-+`=%+gee_kY4FWHg<*4sZI8+sFJD270UUORdLHO0nA4V) z%{fwsET5CQ>B?eK%uw4yQc~9?*JVo2}ze(;aRcp*ceL#HUJSllrgm5wQKR zQu+C;QrUh^8rFfA`ftFz{YAidi-`aL010qNS#tmY3ljhU3ljkVnw%H_00C!7L_t(I z5v`LwO9Md=hG)-2qk%vQMGFxNH3)tbYG>o0v9S??MIcq+3K48<{4+LoVxbWvY9YZw z(IOB?j7D$WXTyXT3{m31amUX4K0CWJXRNg{NW{9$xm+$Y6a>dcWX-`x$s1!{-8Sc+ zQM4U~VX4z&IxEQM^ZTiIHM=u^Y2v~6%9@dpquUi*ZKe(ig~Faf+5pU(o^ z8BGfyt~M8XX1;rcYP3TN=%w$w?g8`}CAZx#RHGgbU`XgQt>U(S8cx>8p+Sp>%{+h! zV@T*Ttx^akeYA~e(Bc8`KZ68`7-*DR2oe36m<_k)+xzRENg;oEe*s~@-UB<3B~<_b N002ovPDHLkV1hZZHWvT@ diff --git a/plugins/cockpit/ui/images/pinout.png b/plugins/cockpit/ui/images/pinout.png deleted file mode 100644 index a53536240f06b181b48db5903d463409e87d0192..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1553 zcmV+s2JZQZP)4Tx0C)j~RL^S@K@|QrZmG~B2wH0nvUrdpNm;9CMbtL^5n^i$+aIn^?(HA4aZWV5ov6ELTdbo0FI&wK{O>*+w4vx20?>!`FrQsdJlnHR>OPy zcd~b_n$otK2Za4V;76L-DzNVtaSB-y0*E}{p()372;bw_^6ZZ}PI-92wGS&j#91PI zKs7DSe@(bk%_Y-7gGe}(^>I=@oY#w#*Bu9GZf3^F5WP>3rn}7Ut74&?PWBFvy`A)a zPP5)V!Xd&78LdA?xQ(9mjMYElVd13a#D+Z_7&Y|xU=_C-srWU*6kiZcC!$nw*)9$7 zn6CX+@=AhmkT}X@VSsa5NKe;HZuq)~1$`#h6R+ZTR#D-3j}vF!)ZOnz+5)dI4jl{{ z44Mr{P!L4~VVJN`K!!XTF*LGrKO?IK8z<8w`3e3jI8lUGNUta*C8 zn(P`s>{pjD=7Kek#B;Fw@hxAK%$F&Q6vg9J^Xf~4by_hu-=A!MJ3Znq&n~srbFGPs zH&&aMXZ>nO`|hf|ljc?VPhR!${AbO?W8x_>CU%PFA&Hm8F7cAsOREdwU~R_;ot1_u z(ruCYB-LPGn!NQdT|ZlRy+(fw^-+`=%+gee_kY4FWHg<*4sZI8+sFJD270UUORdLHO0nA4V) z%{fwsET5CQ>B?eK%uw4yQc~9?*JVo2}ze(;aRcp*ceL#HUJSllrgm5wQKR zQu+C;QrUh^8rFfA`ftFz{YAidi-`aL010qNS#tmY3ljhU3ljkVnw%H_00PNLL_t(I z5p7dlNEA^NK4*4jomF>1U9ly#QV@zTL9ib!416)d=wW@Tj2?V36r?|U*`}8sViB=| zwpt?SA(e_m>>|o_(e(t$*zVCeBxp$B;1_*!* zfG(O~$Qx{XeXO?3JnGzJ9uO0s;ahz7^Tu<*`t)~1!dSUH7U{OZ;jWfTlec2+m6dWH zusDEfXpl6eWmR|a}592Y5td+g2G05}zt~p3fI0w|@`5V0%LBDH;z( zrmHHVg)Aj81T?{|J0dgHBm3KX8r~sF)oBHG4}?rZ`a7FljCK5YA9LRa(M`=XbyH^! z&=|PorFz8M#RS%+AVI;o!53E-7L*CZ42l3Iyxp$YMNfkl9bd>i?|`anR(8<0Dhy?9#i zEP;t02Qo9Q)fC84N&{8Mn){*;GS>FfLXrFoffa)rn7Qn5(E$P>scPg_AQEb1f`M3; z)jyVc>JL6>vMSORk$aZ0z!apG9f!oT>6rh`l$->u$jMgn#SgJk9Emny&v@0<=HSpF z4yFUe+iNw?RuEvMmpq+eYzR^DJ-S)a;gaQF12fV2gS9&zXXnJG3Bh`Md$R(8!0)tV zdh%UZfA{(Qj`cC0-woec4Tr;#f7f}Ov0xMW`}z#7Boqos{oUQxPoyT+!meyr9WCeZ zM0#&~v42?S?#q6=GdnZC*_qjoP)dO?Vj~4cR`Q+W)0I_=rw&!;>jyz9AE<$P@Axyb z)@P+5zqc&TUpD=hJ%Kq8c0Mn2$(A#D&8x?xnCw8?0Q{0fgCMr~WaGC>kRA%!@99?hK+ zH*W6KA%mVL^BkV$Jo2sN>u4O&E(3x7YJ`B0w1v{zT7&EuQg-9y-G}ncc7QezK_om_ zbxMNE0CuS^5qBjnN<_u|QgLyy`H#bU|GrVUTFu>6#|&dB~Yb-O`& z>(!hmWGh#=J@e?feK(qqYf%im zeV9EHJY5XXgp533Hl#zD?{1qv+qVg99TEh1@!$de_eI&qXQI=%g#kCSfkWpt71`&Z0m?-9Y876|cKm=&E{6nC)ldQy}UJ7pjA-zTVLU z2v8`hFv6tqolyNCk}CY@as7el(GAfgC;mjv>GFxwI-_MtPz5SU&}h-`yfkWuH9o$Q z=lK;TvuSEYd4(T~SfhBiy9;0Hbgvz+sViFRiX|fHR4GUTNpjW`RCp-!(vR+MhHasA zGluvn5C&*r%Oa}jCWT>S=jE_>K$K0-o&dRWr|~jlhV2$^|FASdkd0Vpn5rp`js?Ye zp0p%q3xRtE5TXf3si+63MjaC~_#=-qj!3PIfo4y0PHJjuQCN}N?bgnH_o>?Q4SsRYx zUZk)xmV-PlWX=Ei<0+Hdt)LTSqT>j0FvHOz;89{e4vA}+6Y30DfVd|_G0{T;S8qLr zI}IJ+4a(qUDfUO?Oa7)t%Tto}dC=(A(J*XCuRX-0} z98>3wAO}Wh{zy=tFhS$H}Be^;>W zK9qq)6sf9HX@Cfnqa4R864A3d6}kurip*LK1(~WuFG4UVYaPvOHp?t)ln?+-8Ru82 zEQ?0!SAaD6CGZAh(&D4gbYI0H!cH*nvjcNb_{r$wTHK^PEyG_;R179R81x)eH?%>7 z^azYb7WF8t`@zMV5q(n2D%z0K= zJ?#q@dXcBiHX&)`a2k{eBqv0IS7G-G1B3L}KNhOjyC(D!hcA8_weMPadn<|7iHamc z`KF z@6XTAKl|kR|2f~ae#wQr?VG+uomph*pF?*jC16NWM6dbt*fM_#?X&GwD(M#;d=nR3K0`VFD2Hdw1OKt zbZAjoS=sw+EmSih(H90)+jEP)Px#24YJ`L;%tN(g4!zrp4d@000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXN1 z4l)%yE+sht00H|+L_t(2&vlZqYg17a#((#omt@EV%OfQTltAJTaq3W9Lrn&uh`6*% zEfo9<0?y(rIJ*^VhfWrhf(W4mGC4V9Xg~>pKvEJy3-6`87v8%LX&wstjfe9)-#MI5 zS!-FTR;wAH2|NKF-Ic!sUx9b+cH3L^suj4sydLHE_I)3KFE4%p@bu&T1dijF>2!K8pU*cPt@X})J|_&r zq#+DL9u$^?JkKMYPAB)y=X12yJC2Av48stm6mcB$?d33m07h@dT#gkxAId~g1b~Q? z9j*1PwKg5cF>xI8=X+KXM_4Qt%Qq;6)><49={t_I>H9t+!sGXa#0jAIx^Rat!E82* zi2QU!mnlOYIk?n1qPi?$BafJlv2rL-}lKG%hXdC zW60%lY;A4b02S$WySHa&XP3s9y~Scd5Co)BDXg`K2tg#IQYnhXB9%%7W6a*^>FJLo za{K%HHQ=b%>y?MYA+y;mS#4uugKD+f2M$k8PTGHE72x3DzyPoQ6Y{sm$Hz&?e*?bu V*c&phTIm1)002ovPDHLkV1kf!6Gs35 diff --git a/plugins/cockpit/ui/images/throbber.gif b/plugins/cockpit/ui/images/throbber.gif deleted file mode 100644 index d84f653789e5008da64ff04ee109471284a9e284..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10819 zcmb`NXHZjX->;L91QJksO+b()O%YU3Q9(BX7GztHZs?ta9(o#~_ui}YE>aZ(NQ;0- z4L$TKAR+=54({iD-gD-B-kDi5`LJfznl!Zf0ITjX< zw6M*zDXDPSXu-&SbaR}=R&4ujA5*e1nqVdtemfLlxx z`s#5BI0&c9darz3!be?Y&*jZS&Z2>wmCzZLYxvcVFEuibNYYPB`m&$J-Rx)@D*04o zQ0OwUmSFchNrnlj2T)s)Gr&C2Prg6aM)1H`_mp4%?qu?o`(VE#&GW*GcLAry)Qyy@ zP@T?#XC#pNRmRj>uA#tm{av$OoZPH>>1{b86PN6c>^*y8|LLmhWxpra-8aVrjJsOi z;=jpGH(P!$IOVIf^`^t?M}?r#!R}&JRD0l7dc)_{cGnlrr_9D4Zjv!N&aZpo$*<5CIc zuGfFt7)2?sV;7#@mew$jr3u<{#*I{W=Ed6K_PbGo<4rA zaS?%j>0xM6Vz3_`8{rcifFn3~MMBbJJ&5H|NqP2J80bF>K?wP0C3FfPpb%D&wao_s zroo{en|}Z1p$Qn&)tbgSF*N1Y|6zV`q~CRAbrCVvGq*b8=KpzqapU9H!|BnY9otey z43Xk|Oozzg0PXT%20b<=T~i2dl2r(A zga<9}Cd=GdF0g%EfS08;p%0Hh^^UXelY9ZY>GUc z;>9Z}@7v%w-|d6=QLbXTgo5}g-O^5{yUz6`a9bDrJgBsLD{xM9Usiwr1(Wr2HcZw2 z78s0RvkB%orAC1B#7d&=(+@B$-3c-;qE!!e=J|4EvQYS=uPgAI_p&l6USAd#Qj$DR z-|+kX?fv9^^v17dqtAmIx2#oUe}R8>hzQU4zH6<2;qiN^0CWuGm1hG&c=U8rp>W)o zo}r*cx3L+wiDX|Ozul@q;AqclHK>S(u!zGaK3B6)8H4BPpbO-NIjA7Ki!bM!ETbS*()i|B2;8B#A zLFMhDq018GGB<&lC0)16O}+9$R${{ zs%UMOujW!j!PTq4@S6%+bMe~~%JbF&nyN3!FjQ4p$hY(Q53DXheK(>$4+iJHy({Dz z4q#@M<%d3+=oXKh;bB>dV#q3~?qGMo0gEJAginDTO)-G-A_dj8RM|ZJb5^8AEnBKg z+F@aU^w4^Nk4wRil|I2e7KFJ1r;S?$sie`Z@8KxI(o3HIM(7wR~WfbY#LDA_#?OkBzLVmnToDcbn{FQK`)ak+yj zpUY42b7n*32UxEagSpADk4s@=nhtY^E7?Kkj|5ippL|khFDk4!S}&{LI@+k}I{#y{ zcFg}a)4zv{AVym((-oUN+yaJg;|A(;+oxfxlu_{ub&{4D!;N2Jhc)XAsQ9tq)t zcMHHzkO8uGgRn9U55t-I2BQ0hMn?J&){}!XBQU7VfQ{wSFx|~>b7pL1A{epwm1!l^ z_Hb!?mA;`HnbmM<7oN+^8#LdZrt6pO&*i*chQ%-5Iwnd)hv z8&V^MquCryH5TxvHhN_urMX-sv1$xpusn}UHgJ*D?0JZMMFtRY5bPH#I&o6~|Ab+x%flC2dGyv$@=CI(Y*zhdq3-@sTyeGqp^LxJl^;F z$%PR8Eg3%FHU{b$_cL2kL2=>Id-u~jA72v5)7d-Y&sP39JW>#om zC3F;HjDT!9C?SUkW9wuPXlg{wtIDzJ0k)e&YYir(FwI`(bBJyYecM8g{oFpJiwu(6yO}z8=sHm72iJRfU*oD|9tZeWE;N8&I^)x?f`eKw zL&b8TVx1QTdTr4y`md?Q5_0*O59-Oaqkq4;?~%`24(Qb2v}pkJusza~X25y&l!Be0 zo73&Ttdg*VRs|tB^$?}|2N&CgwwB9aDh}9@sQbKE)tkF{91Mx{3iR@G_jmLO^kqf(+YzwNXa?38k1#US z4{zt`l%9$AXTYFyGoqri3eyvlQ=+ln-bv-S+IS4olGR$)*b@zbcb$Ocge*28Ctw+3 zf)DitMB9EEp6;{pkC~btgCaf#EG*JuCkKZ|nKtLProX_JC+wixiwEvMj@;WBwPTy` z%L6axG%AeLZm~{1Rh7p<@K0DN@;FNM0s+J*7L4?oQzJ$SF&_s%5XM^)VkQ5+t+#{9 zf0(RbeY0qwrVyO2U^`(1;}R#PavO!pu2(M)BuTgmB~V<&hLg_)?pquxmh|SSG@k#K z`c17nfuruC4GxD>KMmo~B+BPFO|!@@bhHbj@W#zpaby|~nmGH;{cC4lB7J9;LM+!; z3|FqEcZ?kAl4ZwJ$u0cSGIfjs7p(*Q?;Hz8u;8tRLKB|-*yP)>K^KcO7^?~Akf@xC zA_MeF0)#o3S4{6NRsg!t6*Km%-&c4KHYlkhS&?Mtw#HKz=i{$(=rZ5OY4owe7wdXz z=GCJ|^cKY7szeL;)w^up0+-Yl*hTV=Mze5g;Jj;^@a*<73G+y z-t08LgRH@hg-lIrngw}&=@wMsKI@r7klNG5LAmHb$onEQ?G#TBe29=abF?kLs}wcP z%Ii}|ZEyMq2l)bDp6<1I1=v(ba!OHgN+B4s`+Yf}drkjTD#q-bbyN+1!7|wUh$fj5 z!m*y4^IQC2l!4t%%9xQQoi=_+#XZ|DWKOP-*IBmMZm#5|Zc?shje)96oWR-anGyxN zm6C{&{0X(ZNkK(gCBu zI2?@0RxQdKZ4im3!y1z>Yb`U0L=~Qm-VXR7ofaN}h)&)J`ngr8+A2;J$gv=O`DWp< z&jFQd_gFh;X>seOtr)cOh&ex8@G0_9m+YX8qcz8i?)fH37I}7K+FEEU&|!i$manv; z^3Z%%-P5%pM#$hR_(qWOR6nbPV>Rf3Xy_jBjsd58pCHSPrH^-+A6{07y?Ck+a%bb^ zgW>Unhy5c<34#@s=p$=2bs3!VAUO9t1)aw9lT=(KJekb$%-Br%Ot*lLo^mc#+2f*kMW(^0Cf5`IlOZW2=Yx)1kLbDF|SFOdGBIN^5tM$IKtUR*=^v;k#u$)%$ z-=T^9#(8*pdb!xa{9z1eVmLX-KMdmy^>qudB$5(X1MEYQsU#O%a7>5@!43ydWa@+a?mu(Co~;R4+P9}u0gSlom}} z9D`O@4-5{^(Cw#oMrS8N_7-Q8w$_-wXRd{f1@$+$^|6VpKf$%*fwD}pXFWt(8BRiu zoskY5M~V^_HyUoJjw693Zyg&rs49pOK_X8=Eyj1n@5M`U8u5*v1fXb~hgq2|hh#V7 zB`t*m7{>}Vku4GQ>y@HyPnxQi^yTrVl8=k--^kq)%}IfR*nOUr38Pv`^%%*Y#Y(5{ zOg3Qt)-JXBC}+|L`#s%}X6kgg1rA-vuz!d*@4zrKdW56&&EAEHyDg*vTrJ+N39pQ7 z>b0AE;)LH4q^sZ!RTpa-X3>OP$>%9>9@+P=RgniyOU`Mc z6=BG0d&@O}7rIOywRXV$D23J9Az?10`p`ux3H)J4>7liD+iNQYhd~%GPKrLN;q%C20LT#c@Gz!u-V45N z5=32*D$a`4kP7}-e#GN^hDRS*Jg4PJ%NxOaT9MjLY{Yym z?&5`hY_Tpo&g+^x+9+<`y?3VIoQ(kh{HR}fnj}4uG6CgVwOt5q=?@0R2yf|~zZb79 zGau6vQ!-X@t3|z}F}N}DypaZUEVbog%UW?rxfV<;l07dC_-;TzxiSw}+Pu}-wdEtl z%%F+Ff&6xVND>_NVKZ3~uhXY`F+#YKc!PZ{n@rT>5FzN53+dvi=r+inxAKn>w2Q_{ zF#aX_HsfB>j!K5jFb`7BGLSIOZ5@-b_H)=dBTzF z?*k*e--=wH!SoBi)uvrV6Ym@^t8C)zETAMGv?~G@5(*>wdP9Rl;v%roq!?EB@Weo0 zhSao#WZ%=-9(Li8`PKp9CCJR=Se!>B*~c~1K?D0Al(-UEEB>IQx0eag6CVPhGL4Q6 zn{6N^x|(bZiwVv_umlKgR( zg%8PRfguiFUzape#qRUmfIStzpY*_TD?f!I(VwTKZtzRWePy8h?>iC`hd9b#D87qD z+*K&TWIg9*Q9FfaYcgT~&B$wn5}xuFquBkrFk2qg;KI&jQb4aVY=zM;62}_kW)ntt zZ@xnEy;5pVXTPtPsDH<@#aaB^6~~WXz^x^frbRkAn|}qIWey|Rn-T)8L7rcY+4M6= z@Hc*(tdUa{flHxp`#dIp$nDuTiHl`brB}UPL;KviP|-T+JUqs1c>UHC+GMC%?&*KSc zlk+V{lhGcwHc^U9e<{y_1>G>hpruyqTxb*?`_N1Dn)O+aFvn;$GQ#Y;Alb=XC(r7J z6+H_MFp(GbXNm64HN=MKY1<5kxQXKb-W89vRZxhdfObPxMw9w3DN01}WTz~v8Xrky zCXQw|;4R`Ms}Y|K&1~&X1^=z9v|@7+-Xwu`?BvNycI;c3Op5K$8;g|!oEw2m zRMX7DSh$i<9>abUYDFR@u2Y3i3~G@OKh2vgc>ssmFVRMpdVVML0 z{i^YlBio{sh}0}}=an@2tKrX*)5qnRN1YBP`Pw)sIDjX6B+6UpkRE-h#VRiteh|D7 zX;_!0=6?4|1KxmStXv6sKM~gIx0<+-Mm|)n=a}sXK|u1xQ_7R2N}L{_jPHw ziid2qwmcl6u8Da!Y*ML$Kd-u$!Nc_>jIK=v0c~9F3D&j-%Go{tFlZd&>TaRv&}YJ< zSqtLhC{n`@Q$yCvJQ_Iat3V7A7y#t+uQZ!b?q0d#8OQ~R!KpWaC5hopzXX+&L+?|R zje?`3W$9kj73_S>N4YAM8TLDR2YpU!H>7=Il`<*s7JH!wU=YjKD;$Q46+gEA;mA|B zzu*5!KYut<`QP-D#RmG<>XblGYrE9-{?m_4+nvx*WUXkXe-$TIWm;H?MaT=`W$Ei{ z?eBplz|cOY$pPW91S@D_bV#f>GSDX2(+lRD=yE#1Gb}eMDX1_s6jPcXoD*A3PAYUl zXjmdmO=K8y(^+v|P*#DH=Jf-jhcNg@PR3|Vuurdh#%YtdK?l(2EYpBT_S(v7PpIS4 z=Sio~k+0COqVFpMNBheyYH4B-v-Ow_+Ba8JAr1&TXtwn2xJ@VP%!SBB*t2DA z71rQf3mxGVYM~M{av&uL_Z|q9HPZ|GQ=V|nQ!{WYX`p({igvfo*p}g2XZOr@=Hv>J zJ)EQd7c<`@Gl&2O=jaEeRs{%?nBwS$vf*N%%c0QSaDAXnBSBF^+t<6Ye}s0Dup)A9 zLts|V+4!o|^3B}1=M9qOrwDZ(90UfFXh7rcymQL+EW`Ax%MS2Z*241{Zp({pD<1DM z`Bc7ql2d)AzPrcwdHuRni^gKrlPB{OFn(+a;_4hT zj#9G{aCg3OU}(h&N^FI)Nz@q-1thBIIR3{HXMH%FqVZ(pd17v;v-^NrAkvK9OMp`} z^&|R~zxIaCeeMt;v#%?Ukzb1Nj6*L9_2dN!pmb1hMw4th0Un;>W8Q<+>NoG-%G;*<5h*M2F>VQZp-jo0&K{~#qEPH=gy*d?+7FwQ<;8=W}kwu>A zvch(Rkos~Ei|WWM9?GF*c4DsNTF%D@A#Hfw>4fy~B5Jp)EBieOJfxUoY+9*MTYkY` za?k*n1JtfJsu;&fnpd)$h&q%AmQ9pYH=j-03@J}#lqsQl2T_iF-xu4Z7SU4d`aw;T7=D)KY4Vk=w7jO{I@&s=uEIVm z=;{QuH2UTAn0(mgz2GWLJ6vM!EqDX5WiB0Q-v;1d!l**9ONOg0DHox}1$pYtfPywl zZvdG=!oW43qs&9x-}>>&BraynNU~SizD||V*IUNc@OkQ$S0?i29$V(FgT0C&A!}N% z`^IQ|bst>)yr<0+HBMN<_Y6Y;UeI{{qJu{5FrwVLf5MV?p>L~Ze1|;U8+ss-Gt&(I z&+&5}l57}K;P+{1C~k7X%{%f8vXQ=D0zFuAd2vJd;u6`ssbrSV>@Pf^wJhR2&;PWq zPS^ibC;tPK|0^c{W_1!sXs7dIkT#bZt8ANKS= zV?KUu^m`cL=*uSP_nn;wlWBNwIA8Ri#>A9^JQt(-ciW#Cj-AmCU9|(ub>Sr5d{I+} z35y>Gzt`jdF~mvAL^||b6z_;v)M|MEtFhLOV1fIp94an+$Po#U zs>x;gZ|xcFg^d!0=WE@?-&lr!uSUT}d7hs}j&CoveRDXtrlb!5|v>#s{L zJ}nZ?*?@x>J+%Do9q&MxIdRNgP*z|Eg@;G%-1#}ro!8Wq=bADq*u7?p!cxdh5pUC( znnv{V{^ly@mHFlimHWT2sNKz^3|7InduFG$hT0|jny z3MjHmV{)-P%6uq7K;K9%`AfN;xg9r13k3&rJpqR7ic@f5_WG*qXtl0^6sj6@%rffoWPf#lXb%!Vhm;VceDW* zPY&j@!nT22YX% zY_jZ3iofYksvWtQTcq^3Bs{ONvbrOK!#}3h2$ekK$e(<&dIvH&sa>mXF(I<(AAvg)^OF~3OLsJ4_*7i920^daYke6O@ zfsxgr&fX9Pi+^we;$S_Uiar4flR#e|0-95c=sAfwOs%P2Bec;8OzrecYd9LVKwFyY zKEcT+@4>aPjiJ@8?WNru(Ba~z+kv@^QL|SGOriXLcmgzqbMZA~YY^07aRREeZf7+- z0}rRsn;lirt_WtKW88Z_mpeUi2!53YO~uyx$qM#nVz#>$)M#1G9TKcnbRhbUX#rS@ zW34als;$8TxVuDWC`XY?xb!m_sy>WKnJZg$8N$NHmLGBMpSncxK}`W&fLw=J2z{gb zJ#F$0dd0vnZ3k`Ah&WsFGK_Zz93ybH;PpPGYUUJ^nBmX>UlqN3?Ak^`c0(oT6Gl=! zvWV{+xRGO%pp7~#pJL{g)?{lYQ1B2>?$T2E*4tm^d1~H%xT{hLVP@u#eWW^tomm|! zJ);zv;q-R7YxeGiUxGVdx7xTh2mFn_mz&_1$~;-7{eJF7=2b=_y;|HGXdPp`ps!bz zTCuTT{>+3qY^s3J{;41}P~_W0fc=N6IyJ0!0?!KzguuDyfBhV}YzmEx2%b}r48@9s z^!>$k7A5N46%ImpsG6Id*}c4A%Bv7(YK8c1Z3IYZ<{uYMQN@2mb9}gd<4F zCkMrjGEs0|Jg8d!fboWJFHonfc+69lAL3#ZEe4mAR4ij%>%P#k3#kGBDBdgx>rgbnil_y5MpW{c# zvDxsm9~QN4a(9fK`-N6z$|lRHjxTaERRKaAr~%&KheCATy4S4srcBo>3&&ZQyqNmqbm@Zm)>gemJL^00wvU9u z+D_NO`Lqfc<&UI5WTI_KKc38qy?W_AIsKI`p^Bx~F7!$jbgdZyL&Etz*1)RF-Lm1=TjQJ@AecnfXzx+p1KB>qB-fe=P zF^0^`I$~M#7P5t;wYe#ohI*mNGOm1mCD3~fRa9un)^oj zK6+_2{p z+Z3P>0P+xKKH)!;;*Ky5p-cZvco-QujC$*;MZ2On{yHwG#j53LMY5=xy;Z=-R8Ps`%uTgRK>oU&lv8J~7# z2+xv%aK)C=+zc$8S@L9Lyf@$w2${8?c3W6aLC=KK(sd-;R)g`u_+mJaf%@L7N!wi^Bh8IXKO6Wm?9Y=MeDxCQ?8Wk#d5Y3W8 zA%bsiQm;FPpEXg=iLmEsH1#U{@?#@r`ATp_rJGijSp?!>eLIR*;f+Kj66CuT&3aO3 zF*Cg1qsW&+3TQ53k`}4Zv+e4}Mlbr)#$4XjvFKS2$%X0@(@$v_-`=M3%w#cY+MG`c zttm^jCFpA*6E(8#Ug~+kU?e_#r8LlDklGX23e-h+4!}_)aE&?rRH4k^xZ`!BcPzbp z1)5y>NkevRoqf|&Zla#J>0y0dzUg&Mw(phxmGznO&ZURaP(0paW5&Mg`*+`N*!lX< zJvHqjNC7m_;x?B~y^+kyhR6=!0!p;H * { 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; } diff --git a/plugins/cockpit/ui/requestView.html b/plugins/cockpit/ui/requestView.html deleted file mode 100644 index 5ecbfc1b..00000000 --- a/plugins/cockpit/ui/requestView.html +++ /dev/null @@ -1,28 +0,0 @@ - -
    - -
    - - -
    >
    -
    ${request.typed}
    - - -
    - Hide command output - Show command output - Remove this command from the history - -
    - - -
    -
    - -
    -
    diff --git a/plugins/cockpit/ui/requestView.js b/plugins/cockpit/ui/requestView.js deleted file mode 100644 index 8e21d3ca..00000000 --- a/plugins/cockpit/ui/requestView.js +++ /dev/null @@ -1,149 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - -var dom = require("pilot/dom"); -var event = require("pilot/event"); -var requestViewHtml = require("text!cockpit/ui/requestView.html"); -var Templater = require("pilot/domtemplate").Templater; - -var requestViewCss = require("text!cockpit/ui/requestView.css"); -dom.importCssString(requestViewCss); - -/** - * Pull the HTML into the DOM, but don't add it to the document - */ -var templates = document.createElement('div'); -templates.innerHTML = requestViewHtml; -var row = templates.querySelector('.cptRow'); - -/** - * Adds a row to the CLI output display - */ -function RequestView(request, cliView) { - this.request = request; - this.cliView = cliView; - - this.imagePath = '/plugins/ace/plugins/cockpit/lib/ui/images'; - - // Elements attached to this by the templater. For info only - this.rowin = null; - this.rowout = null; - this.output = null; - this.hide = null; - this.show = null; - this.duration = null; - this.throb = null; - - new Templater().processNode(row.cloneNode(true), this); - - this.cliView.output.appendChild(this.rowin); - this.cliView.output.appendChild(this.rowout); - - this.request.addEventListener('output', this.onRequestChange.bind(this)); -}; - -RequestView.prototype = { - /** - * A single click on an invocation line in the console copies the command to - * the command line - */ - copyToInput: function() { - this.cliView.element.value = this.request.typed; - }, - - /** - * A double click on an invocation line in the console executes the command - */ - executeRequest: function(ev) { - this.cliView.cli.update({ - typed: this.request.typed, - cursor: { start:0, end:0 } - }); - this.cliView.cli.exec(); - }, - - hideOutput: function(ev) { - this.output.style.display = 'none'; - dom.addCssClass(this.hide, 'cmd_hidden'); - dom.removeCssClass(this.show, 'cmd_hidden'); - - event.stopPropagation(ev); - }, - - showOutput: function(ev) { - this.output.style.display = 'block'; - dom.removeCssClass(this.hide, 'cmd_hidden'); - dom.addCssClass(this.show, 'cmd_hidden'); - - event.stopPropagation(ev); - }, - - remove: function(ev) { - this.cliView.output.removeChild(this.rowin); - this.cliView.output.removeChild(this.rowout); - event.stopPropagation(ev); - }, - - onRequestChange: function(ev) { - this.duration.innerHTML = this.request.duration ? - 'completed in ' + (this.request.duration / 1000) + ' sec ' : - ''; - - this.output.innerHTML = ''; - this.request.outputs.forEach(function(output) { - var node; - if (typeof output == 'string') { - node = document.createElement('p'); - node.innerHTML = output; - } else { - node = output; - } - this.output.appendChild(node); - }, this); - this.cliView.scrollOutputToBottom(); - - dom.setCssClass(this.output, 'cmd_error', this.request.error); - - this.throb.style.display = this.request.completed ? 'none' : 'block'; - } -}; -exports.RequestView = RequestView; - - -}); diff --git a/plugins/cockpit/ui/settings.js b/plugins/cockpit/ui/settings.js deleted file mode 100644 index dea79554..00000000 --- a/plugins/cockpit/ui/settings.js +++ /dev/null @@ -1,85 +0,0 @@ -/* ***** 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) - * - * 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(function(require, exports, module) { - - -var types = require("pilot/types"); -var SelectionType = require('pilot/types/basic').SelectionType; - -var direction = new SelectionType({ - name: 'direction', - data: [ 'above', 'below' ] -}); - -var hintDirectionSetting = { - name: "hintDirection", - description: "Are hints shown above or below the command line?", - type: "direction", - defaultValue: "above" -}; - -var outputDirectionSetting = { - name: "outputDirection", - description: "Is the output window shown above or below the command line?", - type: "direction", - defaultValue: "above" -}; - -var outputHeightSetting = { - name: "outputHeight", - description: "What height should the output panel be?", - type: "number", - defaultValue: 300 -}; - -exports.startup = function(data, reason) { - types.registerType(direction); - data.env.settings.addSetting(hintDirectionSetting); - data.env.settings.addSetting(outputDirectionSetting); - data.env.settings.addSetting(outputHeightSetting); -}; - -exports.shutdown = function(data, reason) { - types.unregisterType(direction); - data.env.settings.removeSetting(hintDirectionSetting); - data.env.settings.removeSetting(outputDirectionSetting); - data.env.settings.removeSetting(outputHeightSetting); -}; - - -}); diff --git a/plugins/pilot/canon.js b/plugins/pilot/canon.js deleted file mode 100644 index 3a4165a0..00000000 --- a/plugins/pilot/canon.js +++ /dev/null @@ -1,342 +0,0 @@ -/* ***** 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) - * - * 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(function(require, exports, module) { - -var console = require('pilot/console'); -var Trace = require('pilot/stacktrace').Trace; -var oop = require('pilot/oop'); -var EventEmitter = require('pilot/event_emitter').EventEmitter; -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); -}; - -/** - * Manage a list of commands in the current canon - */ - -/** - * 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(); - } -}; - -/** - * A lookup hash of our registered commands - */ -var commands = {}; - -/** - * A sorted list of command names, we regularly want them in order, so pre-sort - */ -var commandNames = []; - -/** - * 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(param); - }, this); - commands[command.name] = command; - - commandNames.push(command.name); - commandNames.sort(); -}; - -function upgradeType(param) { - var lookup = param.type; - param.type = types.getType(lookup); - if (param.type == null) { - throw new Error('In ' + command.name + '/' + param.name + - ': can\'t find type for: ' + JSON.stringify(lookup)); - } -} - -function removeCommand(command) { - var name = (typeof command === 'string' ? command : command.name); - delete commands[name]; - lang.arrayRemove(commandNames, name); -}; - -function getCommand(name) { - return commands[name]; -}; - -function getCommandNames() { - return commandNames; -}; - -/** - * Entry point for keyboard accelerators or anything else that knows - * everything it needs to about the command params - * @param command Either a command, or the name of one - */ -function exec(command, env, args, typed) { - if (typeof command === 'string') { - command = commands[command]; - } - if (!command) { - // TODO: Should we complain more than returning false? - return false; - } - - // TODO: Ugg. really? - env.selection = env.editor.getSelection(); - - var request = new Request({ - command: command, - args: args, - typed: typed - }); - command.exec(env, args || {}, request); - return true; -}; - -exports.removeCommand = removeCommand; -exports.addCommand = addCommand; -exports.getCommand = getCommand; -exports.getCommandNames = getCommandNames; -exports.exec = exec; -exports.upgradeType = upgradeType; - - -/** - * We publish a 'output' event whenever new command begins output - * TODO: make this more obvious - */ -oop.implement(exports, EventEmitter); - - -/** - * 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. - */ - -/** - * The array of requests that wish to announce their presence - */ -var requests = []; - -/** - * How many requests do we store? - */ -var maxRequestLength = 100; - -/** - * 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 || {}; - - // Will be used in the keyboard case and the cli case - this.command = options.command; - - // Will be used only in the cli case - this.args = options.args; - this.typed = options.typed; - - // Have we been initialized? - this._begunOutput = false; - - this.start = new Date(); - this.end = null; - this.completed = false; - this.error = false; -}; - -oop.implement(Request.prototype, EventEmitter); - -/** - * 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(); - } - - exports._dispatchEvent('output', { requests: requests, request: this }); -}; - -/** - * Sugar for: - *
    request.error = true; request.done(output);
    - */ -Request.prototype.doneWithError = function(content) { - this.error = true; - this.done(content); -}; - -/** - * Declares that this function will not be automatically done when - * the command exits - */ -Request.prototype.async = function() { - if (!this._begunOutput) { - this._beginOutput(); - } -}; - -/** - * 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(); - } - - if (typeof content !== 'string' && !(content instanceof Node)) { - content = content.toString(); - } - - this.outputs.push(content); - this._dispatchEvent('output', {}); - - return this; -}; - -/** - * 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(); - - if (content) { - this.output(content); - } - - this._dispatchEvent('output', {}); -}; -exports.Request = Request; - - -}); diff --git a/plugins/pilot/catalog.js b/plugins/pilot/catalog.js deleted file mode 100644 index 5acb69e5..00000000 --- a/plugins/pilot/catalog.js +++ /dev/null @@ -1,65 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - - -var extensionSpecs = {}; - -exports.addExtensionSpec = function(extensionSpec) { - extensionSpecs[extensionSpec.name] = extensionSpec; -}; - -exports.removeExtensionSpec = function(extensionSpec) { - if (typeof extensionSpec === "string") { - delete extensionSpecs[extensionSpec]; - } - else { - delete extensionSpecs[extensionSpec.name]; - } -}; - -exports.getExtensionSpec = function(name) { - return extensionSpecs[name]; -}; - -exports.getExtensionSpecs = function() { - return Object.keys(extensionSpecs); -}; - - -}); diff --git a/plugins/pilot/commands/basic.js b/plugins/pilot/commands/basic.js deleted file mode 100644 index 68b34fa8..00000000 --- a/plugins/pilot/commands/basic.js +++ /dev/null @@ -1,263 +0,0 @@ -/* ***** 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): - * Skywriter Team (skywriter@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(function(require, exports, module) { - -var checks = require("pilot/typecheck"); -var canon = require('pilot/canon'); - -/** - * 'help' command - */ -var 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(env, args, request) { - var output = []; - - var command = canon.getCommand(args.search); - if (command && command.exec) { - // caught a real command - output.push(command.description ? - command.description : - 'No description for ' + args.search); - } else { - var showHidden = false; - - if (!args.search) { - output.push('

    Welcome to Skywriter - Code in the Cloud

    '); - } - - if (command) { - // We must be looking at sub-commands - output.push('

    Sub-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(''); - output.push(''); - output.push(''); - } - output.push('
    ' + command.name + '' + command.description + '
    '); - - if (!args.search) { - output.push('For more information, see the Skywriter Wiki.'); - } - } - - request.done(output.join('')); - } -}; - -/** - * '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'; - } - - var items = []; - var value; - - for (x in result) { - if (result.hasOwnProperty(x)) { - if (checks.isFunction(result[x])) { - value = '[function]'; - } else if (checks.isObject(result[x])) { - value = '[object]'; - } else { - value = result[x]; - } - - items.push({name: x, value: value}); - } - } - - items.sort(function(a,b) { - return (a.name.toLowerCase() < b.name.toLowerCase()) ? -1 : 1; - }); - - for (x = 0; x < items.length; x++) { - msg += '' + items[x].name + ': ' + items[x].value + '
    '; - } - - } else { - msg = result; - type = typeof result; - } - - request.done('Result for eval \'' + javascript + '\'' + - ' (type: '+ type+'):

    '+ msg); - } -}; - -/** - * 'version' command - */ -var versionCommandSpec = { - name: 'version', - description: 'show the Skywriter version', - hidden: true, - exec: function(env, args, request) { - var version = 'Skywriter ' + skywriter.versionNumber + ' (' + - skywriter.versionCodename + ')'; - request.done(version); - } -}; - -/** - * 'skywriter' command - */ -var skywriterCommandSpec = { - name: 'skywriter', - hidden: true, - exec: function(env, args, request) { - var index = Math.floor(Math.random() * messages.length); - request.done('Skywriter ' + messages[index]); - } -}; -var messages = [ - 'really wants you to trick it out in some way.', - 'is your Web editor.', - 'would love to be like Emacs on the Web.', - 'is written on the Web platform, so you can tweak it.' -]; - - -var canon = require('pilot/canon'); - -exports.startup = function(data, reason) { - canon.addCommand(helpCommandSpec); - canon.addCommand(evalCommandSpec); - // canon.addCommand(versionCommandSpec); - canon.addCommand(skywriterCommandSpec); -}; - -exports.shutdown = function(data, reason) { - canon.removeCommand(helpCommandSpec); - canon.removeCommand(evalCommandSpec); - // canon.removeCommand(versionCommandSpec); - canon.removeCommand(skywriterCommandSpec); -}; - - -}); diff --git a/plugins/pilot/commands/history.js b/plugins/pilot/commands/history.js deleted file mode 100644 index 39f99b3d..00000000 --- a/plugins/pilot/commands/history.js +++ /dev/null @@ -1,117 +0,0 @@ -/* ***** 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): - * Skywriter Team (skywriter@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(function(require, exports, module) { - - -/** - * CLI 'up' - * Decrement the 'current entry' pointer - */ -var historyPreviousCommandSpec = { - name: "historyPrevious", - predicates: { isCommandLine: true, isKeyUp: true }, - key: "up", - exec: function(args, request) { - if (pointer > 0) { - pointer--; - } - - var display = history.requests[pointer].typed; - env.commandLine.setInput(display); - } -}; - -/** - * CLI 'down' - * Increment the 'current entry' pointer - */ -var historyNextCommandSpec = { - name: "historyNext", - predicates: { isCommandLine: true, isKeyUp: true }, - key: "down", - exec: function(args, request) { - if (pointer < history.requests.length) { - pointer++; - } - - var display = (pointer === history.requests.length) - ? '' - : history.requests[pointer].typed; - - env.commandLine.setInput(display); - } -}; - -/** - * 'history' command - */ -var historyCommandSpec = { - name: "history", - description: "Show history of the commands", - exec: function(args, request) { - var output = []; - output.push(''); - var count = 1; - - history.requests.forEach(function(request) { - output.push(''); - output.push(''); - output.push(''); - output.push(''); - count++; - }); - output.push('
    ' + count + '' + request.typed + '
    '); - - request.done(output.join('')); - } -}; - -/** - * The pointer to the command that we show on up|down - */ -var pointer = 0; - -/** - * Reset the pointer to the latest command execution - */ -exports.addedRequestOutput = function() { - pointer = history.requests.length; -}; - - -}); diff --git a/plugins/pilot/commands/settings.js b/plugins/pilot/commands/settings.js deleted file mode 100644 index 1cfb9ae6..00000000 --- a/plugins/pilot/commands/settings.js +++ /dev/null @@ -1,135 +0,0 @@ -/* ***** 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): - * Skywriter Team (skywriter@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(function(require, exports, module) { - - -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); - } -}; - -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; - } - - setting.reset(); - request.done('Reset ' + setting.name + ' to default: ' + - env.settings.get(args.setting)); - } -}; - -var canon = require('pilot/canon'); - -exports.startup = function(data, reason) { - canon.addCommand(setCommandSpec); - canon.addCommand(unsetCommandSpec); -}; - -exports.shutdown = function(data, reason) { - canon.removeCommand(setCommandSpec); - canon.removeCommand(unsetCommandSpec); -}; - - -}); diff --git a/plugins/pilot/console.js b/plugins/pilot/console.js deleted file mode 100644 index c386f855..00000000 --- a/plugins/pilot/console.js +++ /dev/null @@ -1,76 +0,0 @@ -/* ***** 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(function(require, exports, module) { - -/** - * This object represents a "safe console" object that forwards debugging - * messages appropriately without creating a dependency on Firebug in Firefox. - */ - -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; - } - }); -} - -}); diff --git a/plugins/pilot/dom.js b/plugins/pilot/dom.js deleted file mode 100644 index 585ec820..00000000 --- a/plugins/pilot/dom.js +++ /dev/null @@ -1,154 +0,0 @@ -/* ***** 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 Services B.V. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Fabian Jakobs - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -define(function(require, exports, module) { - -exports.setText = function(elem, text) { - if (elem.innerText !== undefined) { - elem.innerText = text; - } - if (elem.textContent !== undefined) { - elem.textContent = text; - } -}; - -exports.hasCssClass = function(el, name) { - var classes = el.className.split(/\s+/g); - return classes.indexOf(name) !== -1; -}; - -/** -* 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; - } -}; - -/** - * 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); - } -}; - -/** -* 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; - } - classes.splice(index, 1); - } - el.className = classes.join(" "); -}; - -exports.importCssString = function(cssText, doc){ - doc = doc || document; - - if (doc.createStyleSheet) { - var sheet = doc.createStyleSheet(); - sheet.cssText = cssText; - } - else { - var style = doc.createElement("style"); - style.appendChild(doc.createTextNode(cssText)); - doc.getElementsByTagName("head")[0].appendChild(style); - } -}; - -exports.getInnerWidth = function(element) { - return (parseInt(exports.computedStyle(element, "paddingLeft")) - + parseInt(exports.computedStyle(element, "paddingRight")) + element.clientWidth); -}; - -exports.getInnerHeight = function(element) { - return (parseInt(exports.computedStyle(element, "paddingTop")) - + parseInt(exports.computedStyle(element, "paddingBottom")) + element.clientHeight); -}; - -exports.computedStyle = function(element, style) { - if (window.getComputedStyle) { - return (window.getComputedStyle(element, "") || {})[style] || ""; - } - else { - return element.currentStyle[style]; - } -}; - -exports.scrollbarWidth = function() { - - var inner = document.createElement('p'); - inner.style.width = "100%"; - inner.style.height = "200px"; - - var outer = document.createElement("div"); - var style = outer.style; - - style.position = "absolute"; - style.left = "-10000px"; - style.overflow = "hidden"; - style.width = "200px"; - style.height = "150px"; - - outer.appendChild(inner); - document.body.appendChild(outer); - var noScrollbar = inner.offsetWidth; - - style.overflow = "scroll"; - var withScrollbar = inner.offsetWidth; - - if (noScrollbar == withScrollbar) { - withScrollbar = outer.clientWidth; - } - - document.body.removeChild(outer); - - return noScrollbar-withScrollbar; -}; - -}); diff --git a/plugins/pilot/domtemplate.js b/plugins/pilot/domtemplate.js deleted file mode 100644 index ffb6804a..00000000 --- a/plugins/pilot/domtemplate.js +++ /dev/null @@ -1,404 +0,0 @@ -/* ***** 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(function(require, exports, module) { - - -// WARNING: do not 'use_strict' without reading the notes in envEval; - -/** - * A templater that allows one to quickly template DOM nodes. - */ -function Templater() { - this.scope = []; -}; - -/** - * Recursive function to walk the tree processing the attributes as it goes. - * @param node the node to process. If you pass a string in instead of a DOM - * element, it is assumed to be an id for use with document.getElementById() - * @param data the data to use for node processing. - */ -Templater.prototype.processNode = function(node, data) { - if (typeof node === 'string') { - node = document.getElementById(node); - } - if (data === null || data === undefined) { - data = {}; - } - this.scope.push(node.nodeName + (node.id ? '#' + node.id : '')); - try { - // Process attributes - if (node.attributes && node.attributes.length) { - // We need to handle 'foreach' and 'if' first because they might stop - // some types of processing from happening, and foreach must come first - // because it defines new data on which 'if' might depend. - if (node.hasAttribute('foreach')) { - this.processForEach(node, data); - return; - } - if (node.hasAttribute('if')) { - if (!this.processIf(node, data)) { - return; - } - } - // Only make the node available once we know it's not going away - data.__element = node; - // It's good to clean up the attributes when we've processed them, - // but if we do it straight away, we mess up the array index - var attrs = Array.prototype.slice.call(node.attributes); - for (var i = 0; i < attrs.length; i++) { - var value = attrs[i].value; - var name = attrs[i].name; - this.scope.push(name); - try { - if (name === 'save') { - // Save attributes are a setter using the node - value = this.stripBraces(value); - this.property(value, data, node); - node.removeAttribute('save'); - } else if (name.substring(0, 2) === 'on') { - // Event registration relies on property doing a bind - value = this.stripBraces(value); - var func = this.property(value, data); - if (typeof func !== 'function') { - this.handleError('Expected ' + value + - ' to resolve to a function, but got ' + typeof func); - } - node.removeAttribute(name); - var capture = node.hasAttribute('capture' + name.substring(2)); - node.addEventListener(name.substring(2), func, capture); - if (capture) { - node.removeAttribute('capture' + name.substring(2)); - } - } else { - // Replace references in all other attributes - var self = this; - var newValue = value.replace(/\$\{[^}]*\}/g, function(path) { - return self.envEval(path.slice(2, -1), data, value); - }); - // Remove '_' prefix of attribute names so the DOM won't try - // to use them before we've processed the template - if (name.charAt(0) === '_') { - node.removeAttribute(name); - node.setAttribute(name.substring(1), newValue); - } else if (value !== newValue) { - attrs[i].value = newValue; - } - } - } finally { - this.scope.pop(); - } - } - } - - // Loop through our children calling processNode. First clone them, so the - // set of nodes that we visit will be unaffected by additions or removals. - var childNodes = Array.prototype.slice.call(node.childNodes); - for (var j = 0; j < childNodes.length; j++) { - this.processNode(childNodes[j], data); - } - - if (node.nodeType === Node.TEXT_NODE) { - this.processTextNode(node, data); - } - } finally { - this.scope.pop(); - } -}; - -/** - * Handle - * @param node An element with an 'if' attribute - * @param data The data to use with envEval - * @returns true if processing should continue, false otherwise - */ -Templater.prototype.processIf = function(node, data) { - this.scope.push('if'); - try { - var originalValue = node.getAttribute('if'); - var value = this.stripBraces(originalValue); - var recurse = true; - try { - var reply = this.envEval(value, data, originalValue); - recurse = !!reply; - } catch (ex) { - this.handleError('Error with \'' + value + '\'', ex); - recurse = false; - } - if (!recurse) { - node.parentNode.removeChild(node); - } - node.removeAttribute('if'); - return recurse; - } finally { - this.scope.pop(); - } -}; - -/** - * Handle and the special case of - * - * @param node An element with a 'foreach' attribute - * @param data The data to use with envEval - */ -Templater.prototype.processForEach = function(node, data) { - this.scope.push('foreach'); - try { - var originalValue = node.getAttribute('foreach'); - var value = originalValue; - - var paramName = 'param'; - if (value.charAt(0) === '$') { - // No custom loop variable name. Use the default: 'param' - value = this.stripBraces(value); - } else { - // Extract the loop variable name from 'NAME in ${ARRAY}' - var nameArr = value.split(' in '); - paramName = nameArr[0].trim(); - value = this.stripBraces(nameArr[1].trim()); - } - node.removeAttribute('foreach'); - try { - var self = this; - // Process a single iteration of a loop - var processSingle = function(member, clone, ref) { - ref.parentNode.insertBefore(clone, ref); - data[paramName] = member; - self.processNode(clone, data); - delete data[paramName]; - }; - - // processSingle is no good for nodes where we want to work on - // the childNodes rather than the node itself - var processAll = function(scope, member) { - self.scope.push(scope); - try { - if (node.nodeName === 'LOOP') { - for (var i = 0; i < node.childNodes.length; i++) { - var clone = node.childNodes[i].cloneNode(true); - processSingle(member, clone, node); - } - } else { - var clone = node.cloneNode(true); - clone.removeAttribute('foreach'); - processSingle(member, clone, node); - } - } finally { - self.scope.pop(); - } - }; - - var reply = this.envEval(value, data, originalValue); - if (Array.isArray(reply)) { - reply.forEach(function(data, i) { - processAll('' + i, data); - }, this); - } else { - for (var param in reply) { - if (reply.hasOwnProperty(param)) { - processAll(param, param); - } - } - } - node.parentNode.removeChild(node); - } catch (ex) { - this.handleError('Error with \'' + value + '\'', ex); - } - } finally { - this.scope.pop(); - } -}; - -/** - * Take a text node and replace it with another text node with the ${...} - * sections parsed out. We replace the node by altering node.parentNode but - * we could probably use a DOM Text API to achieve the same thing. - * @param node The Text node to work on - * @param data The data to use in calls to envEval - */ -Templater.prototype.processTextNode = function(node, data) { - // Replace references in other attributes - var value = node.data; - // We can't use the string.replace() with function trick (see generic - // attribute processing in processNode()) because we need to support - // functions that return DOM nodes, so we can't have the conversion to a - // string. - // Instead we process the string as an array of parts. In order to split - // the string up, we first replace '${' with '\uF001$' and '}' with '\uF002' - // We can then split using \uF001 or \uF002 to get an array of strings - // where scripts are prefixed with $. - // \uF001 and \uF002 are just unicode chars reserved for private use. - value = value.replace(/\$\{([^}]*)\}/g, '\uF001$$$1\uF002'); - var parts = value.split(/\uF001|\uF002/); - if (parts.length > 1) { - parts.forEach(function(part) { - if (part === null || part === undefined || part === '') { - return; - } - if (part.charAt(0) === '$') { - part = this.envEval(part.slice(1), data, node.data); - } - // It looks like this was done a few lines above but see envEval - if (part === null) { - part = "null"; - } - if (part === undefined) { - part = "undefined"; - } - // if (isDOMElement(part)) { ... } - if (typeof part.cloneNode !== 'function') { - part = node.ownerDocument.createTextNode(part.toString()); - } - node.parentNode.insertBefore(part, node); - }, this); - node.parentNode.removeChild(node); - } -}; - -/** - * Warn of string does not begin '${' and end '}' - * @param str the string to check. - * @return The string stripped of ${ and }, or untouched if it does not match - */ -Templater.prototype.stripBraces = function(str) { - if (!str.match(/\$\{.*\}/g)) { - this.handleError('Expected ' + str + ' to match ${...}'); - return str; - } - return str.slice(2, -1); -}; - -/** - * Combined getter and setter that works with a path through some data set. - * For example: - *
      - *
    • property('a.b', { a: { b: 99 }}); // returns 99 - *
    • property('a', { a: { b: 99 }}); // returns { b: 99 } - *
    • property('a', { a: { b: 99 }}, 42); // returns 99 and alters the - * input data to be { a: { b: 42 }} - *
    - * @param path An array of strings indicating the path through the data, or - * a string to be cut into an array using split('.') - * @param data An object to look in for the path argument - * @param newValue (optional) If defined, this value will replace the - * original value for the data at the path specified. - * @return The value pointed to by path before any - * newValue is applied. - */ -Templater.prototype.property = function(path, data, newValue) { - this.scope.push(path); - try { - if (typeof path === 'string') { - path = path.split('.'); - } - var value = data[path[0]]; - if (path.length === 1) { - if (newValue !== undefined) { - data[path[0]] = newValue; - } - if (typeof value === 'function') { - return function() { - return value.apply(data, arguments); - }; - } - return value; - } - if (!value) { - this.handleError('Can\'t find path=' + path); - return null; - } - return this.property(path.slice(1), value, newValue); - } finally { - this.scope.pop(); - } -}; - -/** - * Like eval, but that creates a context of the variables in env in - * which the script is evaluated. - * WARNING: This script uses 'with' which is generally regarded to be evil. - * The alternative is to create a Function at runtime that takes X parameters - * according to the X keys in the env object, and then call that function using - * the values in the env object. This is likely to be slow, but workable. - * @param script The string to be evaluated. - * @param env The environment in which to eval the script. - * @param context Optional debugging string in case of failure - * @return The return value of the script, or the error message if the script - * execution failed. - */ -Templater.prototype.envEval = function(script, env, context) { - with (env) { - try { - this.scope.push(context); - return eval(script); - } catch (ex) { - this.handleError('Template error evaluating \'' + script + '\'', ex); - return script; - } finally { - this.scope.pop(); - } - } -}; - -/** - * A generic way of reporting errors, for easy overloading in different - * environments. - * @param message the error message to report. - * @param ex optional associated exception. - */ -Templater.prototype.handleError = function(message, ex) { - this.logError(message); - this.logError('In: ' + this.scope.join(' > ')); - if (ex) { - this.logError(ex); - } -}; - - -/** - * A generic way of reporting errors, for easy overloading in different - * environments. - * @param message the error message to report. - */ -Templater.prototype.logError = function(message) { - console.log(message); -}; - -exports.Templater = Templater; - - -}); diff --git a/plugins/pilot/event.js b/plugins/pilot/event.js deleted file mode 100644 index 34621fe6..00000000 --- a/plugins/pilot/event.js +++ /dev/null @@ -1,242 +0,0 @@ -/* ***** 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 Services B.V. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Fabian Jakobs - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -define(function(require, exports, module) { - -var useragent = require("pilot/useragent"); - -exports.addListener = function(elem, type, callback) { - if (elem.addEventListener) { - return elem.addEventListener(type, callback, false); - } - if (elem.attachEvent) { - var wrapper = function() { - callback(window.event); - }; - callback._wrapper = wrapper; - elem.attachEvent("on" + type, wrapper); - } -}; - -exports.removeListener = function(elem, type, callback) { - if (elem.removeEventListener) { - return elem.removeEventListener(type, callback, false); - } - if (elem.detachEvent) { - elem.detachEvent("on" + type, callback._wrapper || callback); - } -}; - -/** -* Prevents propagation and clobbers the default action of the passed event -*/ -exports.stopEvent = function(e) { - exports.stopPropagation(e); - exports.preventDefault(e); - return false; -}; - -exports.stopPropagation = function(e) { - if (e.stopPropagation) - e.stopPropagation(); - else - e.cancelBubble = true; -}; - -exports.preventDefault = function(e) { - if (e.preventDefault) - e.preventDefault(); - else - e.returnValue = false; -}; - -exports.getDocumentX = function(e) { - if (e.clientX) { - var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; - return e.clientX + scrollLeft; - } else { - return e.pageX; - } -}; - -exports.getDocumentY = function(e) { - if (e.clientY) { - var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; - return e.clientY + scrollTop; - } else { - return e.pageX; - } -}; - -/** - * @return {Number} 0 for left button, 1 for middle button, 2 for right button - */ -exports.getButton = function(e) { - // DOM Event - if (e.preventDefault) { - return e.button; - } - // old IE - else { - return Math.max(e.button - 1, 2); - } -}; - -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(); - - el.removeEventListener("mousemove", onMouseMove, true); - el.removeEventListener("mouseup", onMouseUp, true); - - e.stopPropagation(); - } - - el.addEventListener("mousemove", onMouseMove, true); - el.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); - }; - 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); - } - - if (exports.getButton(e) != button - || Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5) - clicks = 0; - - if (clicks == count) { - clicks = 0; - callback(e); - } - return exports.preventDefault(e); - }; - - exports.addListener(el, "mousedown", listener); - useragent.isIE && exports.addListener(el, "dblclick", listener); -}; - -exports.addKeyListener = function(el, callback) { - var lastDown = null; - - exports.addListener(el, "keydown", function(e) { - lastDown = e.keyIdentifier || e.keyCode; - return callback(e); - }); - - // repeated keys are fired as keypress and not keydown events - if (useragent.isMac && (useragent.isGecko || useragent.isOpera)) { - exports.addListener(el, "keypress", function(e) { - var keyId = e.keyIdentifier || e.keyCode; - if (lastDown !== keyId) { - return callback(e); - } else { - lastDown = null; - } - }); - } -}; - -}); diff --git a/plugins/pilot/event_emitter.js b/plugins/pilot/event_emitter.js deleted file mode 100644 index 7a31f6ba..00000000 --- a/plugins/pilot/event_emitter.js +++ /dev/null @@ -1,84 +0,0 @@ -/* ***** 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 Services B.V. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Fabian Jakobs - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -define(function(require, exports, module) { - -var EventEmitter = {}; - -EventEmitter._dispatchEvent = function(eventName, e) { - this._eventRegistry = this._eventRegistry || {}; - - var listeners = this._eventRegistry[eventName]; - if (!listeners || !listeners.length) return; - - var e = e || {}; - e.type = eventName; - - for (var i=0; i>> 0; - if (len === 0) - return -1; - - var n = 0; - if (arguments.length > 0) { - n = Number(arguments[1]); - if (n !== n) - n = 0; - else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) - n = (n > 0 || -1) * Math.floor(Math.abs(n)); - } - - if (n >= len) - return -1; - - var k = n >= 0 - ? n - : Math.max(len - Math.abs(n), 0); - - for (; k < len; k++) { - if (k in t && t[k] === searchElement) - return k; - } - return -1; - }; -} - -// from MDC -// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach -if (!Array.prototype.forEach) { - Array.prototype.forEach = function(fun /*, thisp */) { - if (this === void 0 || this === null) - throw new TypeError(); - - var t = Object(this); - var len = t.length >>> 0; - if (typeof fun !== "function") - throw new TypeError(); - - var thisp = arguments[1]; - for (var i = 0; i < len; i++) { - if (i in t) - fun.call(thisp, t[i], i, t); - } - }; -} - -/** - * Retrieves the list of keys on an object. - */ -if (!Object.keys) { - Object.keys = function(obj) { - var k, ret = []; - for (k in obj) { - if (obj.hasOwnProperty(k)) { - ret.push(k); - } - } - return ret; - }; -} - -if (!Function.prototype.bind) { - // from MDC - // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind - Function.prototype.bind = function (obj) { - var slice = [].slice; - var args = slice.call(arguments, 1); - var self = this; - var nop = function () {}; - - // optimize common case - if (arguments.length == 1) { - var bound = function() { - return self.apply(this instanceof nop ? this : obj, arguments); - }; - } - else { - var bound = function () { - return self.apply( - this instanceof nop ? this : ( obj || {} ), - args.concat( slice.call(arguments) ) - ); - }; - } - - nop.prototype = self.prototype; - bound.prototype = new nop(); - - // From Narwhal - bound.name = this.name; - bound.displayName = this.displayName; - bound.length = this.length; - bound.unbound = self; - - return bound; - }; -} - -exports.globalsLoaded = true; - -}); \ No newline at end of file diff --git a/plugins/pilot/index.js b/plugins/pilot/index.js deleted file mode 100644 index 5166a833..00000000 --- a/plugins/pilot/index.js +++ /dev/null @@ -1,73 +0,0 @@ -/* ***** 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 ***** */ - -var deps = [ - "pilot/fixoldbrowsers", - "pilot/types/basic", - "pilot/types/command", - "pilot/types/settings", - "pilot/commands/settings", - "pilot/commands/basic", - // "pilot/commands/history", - "pilot/settings/canon", - "pilot/canon" -]; - -var packages = deps.slice(); -packages.unshift("require", "exports", "module"); - -define(packages, function(require, exports, module) { - -exports.startup = function(data, reason) { - deps.forEach(function(dep) { - var module = require(dep); - if (typeof module.startup === "function") { - module.startup(data, reason); - } - }); -}; -/* -exports.shutdown(data, reason) { - deps.forEach(function(dep) { - var module = require(dep); - if (typeof module.shutdown === "function") { - module.shutdown(data, reason); - } - }); -}; -*/ -}); diff --git a/plugins/pilot/keyboard/index.js b/plugins/pilot/keyboard/index.js deleted file mode 100644 index 87e6281f..00000000 --- a/plugins/pilot/keyboard/index.js +++ /dev/null @@ -1,459 +0,0 @@ -/* ***** 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): - * Skywriter Team (skywriter@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(function(request, exports, module) { - -var console = require('pilot/console'); -var Trace = require('pilot/stacktrace').Trace; -var keyutil = require('pilot/keyboard/keyutil'); -var history = require('canon/history'); -var Request = require('canon/request').Request; -var env = require('environment').env; - -exports.keymappings = {}; - -exports.addKeymapping = function(mapping) { - exports.keymappings[mapping.name] = mapping; -}; - -exports.removeKeymapping = function(name) { - delete exports.keymapping[name]; -}; - -exports.startup = function(data, reason) { - var settings = data.env.settings; - // TODO register this - // catalog.addExtensionSpec("keymapping", { - // "description": "A keymapping defines how keystrokes are interpreted.", - // "params": [ - // { - // "name": "states", - // "required": true, - // "description": - // "Holds the states and all the informations about the keymapping. See docs: pluginguide/keymapping" - // } - // ] - // }); - settings.settingChange.add({ - match: "customKeymapping", - ref: exports.keyboardManager, - func: exports.keyboardManager._customKeymappingChanged - .bind(exports.keyboardManager) - }); -}; - -exports.shutdown = function(data, reason) { - var settings = data.env.settings; - settings.settingChange.remove(exports.keyboardManager); -}; - - -/* - * Things to do to sanitize this code: - * - 'no command' is a bizarre special value at the very least it should be a - * constant to make typos more obvious, but it would be better to refactor - * so that a natural value like null worked. - * - sender seems to be totally customized to the editor case, and the functions - * that we assume that it has make no sense for the commandLine case. We - * should either document and implement the same function set for both cases - * or admit that the cases are different enough to have separate - * implementations. - * - remove remaining sproutcore-isms - * - fold buildFlags into processKeyEvent or something better, preferably the - * latter. We don't want the environment to become a singleton - */ - -/** - * Every time we call processKeyEvent, we pass in some flags that require the - * same processing to set them up. This function can be called to do that - * setup. - * @param env Probably environment.env - * @param flags Probably {} (but check other places where this is called) - */ -exports.buildFlags = function(flags) { - flags.context = env.contexts[0]; - return flags; -}; - -/** - * The canon, or the repository of commands, contains functions to process - * events and dispatch command messages to targets. - * @class - */ -var KeyboardManager = function() { }; - -KeyboardManager.prototype = { - _customKeymappingCache: { states: {} }, - - /** - * Searches through the command canon for an event matching the given flags - * with a key equivalent matching the given SproutCore event, and, if the - * command is found, sends a message to the appropriate target. - * - * This will get a couple of upgrades in the not-too-distant future: - * 1. caching in the Canon for fast lookup based on key - * 2. there will be an extra layer in between to allow remapping via - * user preferences and keyboard mapping plugins - * - * @return True if a matching command was found, false otherwise. - */ - processKeyEvent: function(evt, sender, flags) { - // Use our modified commandCodes function to detect the meta key in - // more circumstances than SproutCore alone does. - var symbolicName = keyutil.commandCodes(evt, true)[0]; - if (util.none(symbolicName)) { - return false; - } - - // TODO: Maybe it should be the job of our caller to do this? - exports.buildFlags(flags); - - flags.isCommandKey = true; - return this._matchCommand(symbolicName, sender, flags); - }, - - _matchCommand: function(symbolicName, sender, flags) { - var match = this._findCommandExtension(symbolicName, sender, flags); - if (match && match.commandExt !== 'no command') { - if (flags.isTextView) { - sender.resetKeyBuffers(); - } - - var commandExt = match.commandExt; - commandExt.load(function(command) { - var request = new Request({ - command: command, - commandExt: commandExt - }); - history.execute(match.args, request); - }); - return true; - } - - // 'no command' is returned if a keyevent is handled but there is no - // command executed (for example when switchting the keyboard state). - if (match && match.commandExt === 'no command') { - return true; - } else { - return false; - } - }, - - _buildBindingsRegex: function(bindings) { - // Escape a given Regex string. - bindings.forEach(function(binding) { - if (!util.none(binding.key)) { - binding.key = new RegExp('^' + binding.key + '$'); - } else if (Array.isArray(binding.regex)) { - binding.key = new RegExp('^' + binding.regex[1] + '$'); - binding.regex = new RegExp(binding.regex.join('') + '$'); - } else { - binding.regex = new RegExp(binding.regex + '$'); - } - }); - }, - - /** - * 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 (state in keymapping.states) { - this._buildBindingsRegex(keymapping.states[state]); - } - keymapping._convertedRegExp = true; - }, - - /** - * Loop through the commands in the canon, looking for something that - * matches according to #_commandMatches, and return that. - */ - _findCommandExtension: function(symbolicName, sender, flags) { - // If the flags indicate that we handle the textView's input then take - // a look at keymappings as well. - if (flags.isTextView) { - var currentState = sender._keyState; - - // 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 ∆). - if (!flags.isCommandKey || symbolicName.indexOf('alt_') === -1) { - sender._keyBuffer += - symbolicName.replace(/ctrl_meta|meta/,'ctrl'); - sender._keyMetaBuffer += symbolicName; - } - - // List of all the keymappings to look at. - var ak = [ this._customKeymappingCache ]; - - // Get keymapping extension points. - ak = ak.concat(catalog.getExtensions('keymapping')); - - for (var i = 0; i < ak.length; i++) { - // Check if the keymapping has the current state. - if (util.none(ak[i].states[currentState])) { - continue; - } - - if (util.none(ak[i]._convertedRegExp)) { - this._buildKeymappingRegex(ak[i]); - } - - // Try to match the current mapping. - var result = this._bindingsMatch( - symbolicName, - flags, - sender, - ak[i]); - - if (!util.none(result)) { - return result; - } - } - } - - var commandExts = catalog.getExtensions('command'); - var reply = null; - var args = {}; - - symbolicName = symbolicName.replace(/ctrl_meta|meta/,'ctrl'); - - commandExts.some(function(commandExt) { - if (this._commandMatches(commandExt, symbolicName, flags)) { - reply = commandExt; - return true; - } - return false; - }.bind(this)); - - return util.none(reply) ? null : { commandExt: reply, args: args }; - }, - - - /** - * Checks if the given parameters fit to one binding in the given bindings. - * Returns the command and arguments if a command was matched. - */ - _bindingsMatch: function(symbolicName, flags, sender, keymapping) { - var match; - var commandExt = null; - var args = {}; - var bufferToUse; - - if (!util.none(keymapping.hasMetaKey)) { - bufferToUse = sender._keyBuffer; - } else { - bufferToUse = sender._keyMetaBuffer; - } - - // Add the alt_key to the buffer as we don't want it to be in the buffer - // that is saved but for matching, it needs to be there. - if (symbolicName.indexOf('alt_') === 0 && flags.isCommandKey) { - bufferToUse += symbolicName; - } - - // Loop over all the bindings of the keymapp until a match is found. - keymapping.states[sender._keyState].some(function(binding) { - // 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(bufferToUse))) { - return false; - } - - // Check for disallowed matches. - if (binding.disallowMatches) { - for (var i = 0; i < binding.disallowMatches.length; i++) { - if (!!match[binding.disallowMatches[i]]) { - return true; - } - } - } - - // Check predicates. - if (!exports.flagsMatch(binding.predicates, flags)) { - return false; - } - - // If there is a command to execute, then figure out the - // comand and the arguments. - if (binding.exec) { - // Get the command. - commandExt = catalog.getExtensionByKey('command', binding.exec); - if (util.none(commandExt)) { - throw new Error('Can\'t find command ' + binding.exec + - ' in state=' + sender._keyState + - ', symbolicName=' + symbolicName); - } - - // Bulid the arguments. - if (binding.params) { - var value; - binding.params.forEach(function(param) { - if (!util.none(param.match) && !util.none(match)) { - value = match[param.match] || param.defaultValue; - } else { - value = param.defaultValue; - } - - if (param.type === 'number') { - value = parseInt(value, 10); - } - - args[param.name] = value; - }); - } - sender.resetKeyBuffers(); - } - - // Handle the 'then' property. - if (binding.then) { - sender._keyState = binding.then; - sender.resetKeyBuffers(); - } - - // If there is no command matched now, then return a 'false' - // command to stop matching. - if (util.none(commandExt)) { - commandExt = 'no command'; - } - - return true; - }); - - if (util.none(commandExt)) { - return null; - } - - return { commandExt: commandExt, args: args }; - }, - - /** - * Check that the given command fits the given key name and flags. - */ - _commandMatches: function(commandExt, symbolicName, flags) { - var mappedKeys = commandExt.key; - if (!mappedKeys) { - return false; - } - - // Check predicates - if (!exports.flagsMatch(commandExt.predicates, flags)) { - return false; - } - - if (typeof(mappedKeys) === 'string') { - if (mappedKeys != symbolicName) { - return false; - } - return true; - } - - if (!Array.isArray(mappedKeys)) { - mappedKeys = [mappedKeys]; - commandExt.key = mappedKeys; - } - - for (var i = 0; i < mappedKeys.length; i++) { - var keymap = mappedKeys[i]; - if (typeof(keymap) === 'string') { - if (keymap == symbolicName) { - return true; - } - continue; - } - - if (keymap.key != symbolicName) { - continue; - } - - return exports.flagsMatch(keymap.predicates, flags); - } - return false; - }, - - /** - * Build a cache of custom keymappings whenever the associated setting - * changes. - */ - _customKeymappingChanged: function(settingName, value) { - var ckc = this._customKeymappingCache = - JSON.parse(value); - - ckc.states = ckc.states || {}; - - for (state in ckc.states) { - this._buildBindingsRegex(ckc.states[state]); - } - ckc._convertedRegExp = true; - } -}; - -/** - * - */ -exports.flagsMatch = function(predicates, flags) { - if (util.none(predicates)) { - return true; - } - - if (!flags) { - return false; - } - - for (var flagName in predicates) { - if (flags[flagName] !== predicates[flagName]) { - return false; - } - } - - return true; -}; - -/** - * The global exported KeyboardManager - */ -exports.keyboardManager = new KeyboardManager(); - - -}); diff --git a/plugins/pilot/keyboard/keyutil.js b/plugins/pilot/keyboard/keyutil.js deleted file mode 100644 index 12bc3a99..00000000 --- a/plugins/pilot/keyboard/keyutil.js +++ /dev/null @@ -1,273 +0,0 @@ -/*! @license -========================================================================== -SproutCore -- JavaScript Application Framework -copyright 2006-2009, Sprout Systems Inc., Apple Inc. and contributors. - -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: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -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. - -SproutCore and the SproutCore logo are trademarks of Sprout Systems, Inc. - -For more information about SproutCore, visit http://www.sproutcore.com - - -========================================================================== -@license */ - -// Most of the following code is taken from SproutCore with a few changes. - -define(function(require, exports, module) { - -var event = require('pilot/event'); -var useragent = require('pilot/useragent'); - -/** - * Helper functions and hashes for key handling. - */ -exports.KeyHelper = function() { - var ret = { - MODIFIER_KEYS: { - 16: 'shift', 17: 'ctrl', 18: 'alt', 224: 'meta' - }, - - FUNCTION_KEYS : { - 8: 'backspace', 9: 'tab', 13: 'return', 19: 'pause', - 27: 'escape', 33: 'pageup', 34: 'pagedown', 35: 'end', - 36: 'home', 37: 'left', 38: 'up', 39: 'right', - 40: 'down', 44: 'printscreen', 45: 'insert', 46: 'delete', - 112: 'f1', 113: 'f2', 114: 'f3', 115: 'f4', - 116: 'f5', 117: '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: '\"' - }, - - /** - * Create the lookup table for Firefox to convert charCodes to keyCodes - * in the keyPress event. - */ - PRINTABLE_KEYS_CHARCODE: {}, - - /** - * Allow us to lookup keyCodes by symbolic name rather than number - */ - KEY: {} - }; - - // Create the PRINTABLE_KEYS_CHARCODE hash. - for (var i in ret.PRINTABLE_KEYS) { - var k = ret.PRINTABLE_KEYS[i]; - ret.PRINTABLE_KEYS_CHARCODE[k.charCodeAt(0)] = i; - if (k.toUpperCase() != k) { - ret.PRINTABLE_KEYS_CHARCODE[k.toUpperCase().charCodeAt(0)] = i; - } - } - - // A reverse map of FUNCTION_KEYS - for (i in ret.FUNCTION_KEYS) { - var name = ret.FUNCTION_KEYS[i].toUpperCase(); - ret.KEY[name] = parseInt(i, 10); - } - - return ret; -}(); - -/** - * Determines if the keyDown event is a non-printable or function key. - * These kinds of events are processed as keyboard shortcuts. - * If no shortcut handles the event, then it will be sent as a regular - * keyDown event. - * @private - */ -var isFunctionOrNonPrintableKey = function(evt) { - return !!(evt.altKey || evt.ctrlKey || evt.metaKey || - ((evt.charCode !== evt.which) && - exports.KeyHelper.FUNCTION_KEYS[evt.which])); -}; - -/** - * Returns character codes for the event. - * The first value is the normalized code string, with any Shift or Ctrl - * characters added to the beginning. - * The second value is the char string by itself. - * @return {Array} - */ -exports.commandCodes = function(evt, dontIgnoreMeta) { - var code = evt._keyCode || evt.keyCode; - var charCode = (evt._charCode === undefined ? evt.charCode : evt._charCode); - var ret = null; - var key = null; - var modifiers = ''; - var lowercase; - var allowShift = true; - - // Absent a value for 'keyCode' or 'which', we can't compute the - // command codes. Bail out. - if (code === 0 && evt.which === 0) { - return false; - } - - // If the charCode is not zero, then we do not handle a command key - // here. Bail out. - if (charCode !== 0) { - return false; - } - - // Check for modifier keys. - if (exports.KeyHelper.MODIFIER_KEYS[charCode]) { - return [exports.KeyHelper.MODIFIER_KEYS[charCode], null]; - } - - // handle function keys. - if (code) { - ret = exports.KeyHelper.FUNCTION_KEYS[code]; - if (!ret && (evt.altKey || evt.ctrlKey || evt.metaKey)) { - ret = exports.KeyHelper.PRINTABLE_KEYS[code]; - // Don't handle the shift key if the combo is - // (meta_|ctrl_) - // This is necessary for the French keyboard. On that keyboard, - // you have to hold down the shift key to access the number - // characters. - if (code > 47 && code < 58) { - allowShift = evt.altKey; - } - } - - if (ret) { - if (evt.altKey) { - modifiers += 'alt_'; - } - if (evt.ctrlKey) { - modifiers += 'ctrl_'; - } - if (evt.metaKey) { - modifiers += 'meta_'; - } - } else if (evt.ctrlKey || evt.metaKey) { - return false; - } - } - - // otherwise just go get the right key. - if (!ret) { - code = evt.which; - key = ret = String.fromCharCode(code); - lowercase = ret.toLowerCase(); - - if (evt.metaKey) { - modifiers = 'meta_'; - ret = lowercase; - - } else ret = null; - } - - if (evt.shiftKey && ret && allowShift) { - modifiers += 'shift_'; - } - - if (ret) { - ret = modifiers + ret; - } - - if (!dontIgnoreMeta && ret) { - ret = ret.replace(/ctrl_meta|meta/,'ctrl'); - } - - return [ret, key]; -}; - -// Note: Most of the following code is taken from SproutCore with a few changes. - -/** - * Firefox sends a few key events twice: the first time to the keydown event - * and then later again to the keypress event. To handle them correct, they - * should be processed only once. Due to this, we will skip these events - * in keydown and handle them then in keypress. - */ -exports.addKeyDownListener = function(element, boundFunction) { - - var handleBoundFunction = function(ev) { - var handled = boundFunction(ev); - // If the boundFunction returned true, then stop the event. - if (handled) { - event.stopEvent(ev); - } - return handled; - }; - - element.addEventListener('keydown', function(ev) { - if (useragent.isGecko) { - // Check for function keys (like DELETE, TAB, LEFT, RIGHT...) - if (exports.KeyHelper.FUNCTION_KEYS[ev.keyCode]) { - return true; - // Check for command keys (like ctrl_c, ctrl_z...) - } else if ((ev.ctrlKey || ev.metaKey) && - exports.KeyHelper.PRINTABLE_KEYS[ev.keyCode]) { - return true; - } - } - - if (isFunctionOrNonPrintableKey(ev)) { - return handleBoundFunction(ev); - } - - return true; - }, false); - - element.addEventListener('keypress', function(ev) { - if (useragent.isGecko) { - // If this is a function key, we have to use the keyCode. - if (exports.KeyHelper.FUNCTION_KEYS[ev.keyCode]) { - return handleBoundFunction(ev); - } else if ((ev.ctrlKey || ev.metaKey) && - exports.KeyHelper.PRINTABLE_KEYS_CHARCODE[ev.charCode]){ - // Check for command keys (like ctrl_c, ctrl_z...). - // For command keys have to convert the charCode to a keyCode - // as it has been sent from the keydown event to be in line - // with the other browsers implementations. - - // FF does not allow let you change the keyCode or charCode - // property. Store to a custom keyCode/charCode variable. - // The getCommandCodes() function takes care of these - // special variables. - ev._keyCode = exports.KeyHelper.PRINTABLE_KEYS_CHARCODE[ev.charCode]; - ev._charCode = 0; - return handleBoundFunction(ev); - } - } - - // normal processing: send keyDown for printable keys. - if (ev.charCode !== undefined && ev.charCode === 0) { - return true; - } - - return handleBoundFunction(ev); - }, false); -}; - -}); diff --git a/plugins/pilot/keyboard/tests/testKeyboard.js b/plugins/pilot/keyboard/tests/testKeyboard.js deleted file mode 100644 index 17918935..00000000 --- a/plugins/pilot/keyboard/tests/testKeyboard.js +++ /dev/null @@ -1,99 +0,0 @@ -require.def(['require', 'exports', 'module', - 'keyboard/keyboard', - 'keyboard/tests/plugindev' -], function(require, exports, module, - keyboard, - t -) { - -/* ***** 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): - * Skywriter Team (skywriter@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 ***** */ - - - - -exports.testKeyMatching = function() { - var km = keyboard.keyboardManager; - var command = {}; - t.equal(km._commandMatches(command, 'meta_z', {}), false, - 'no keymapping means false'); - - command = { - key: 'meta_z' - }; - t.equal(km._commandMatches(command, 'meta_z', {}), true, - 'matching keys, simple string'); - t.equal(km._commandMatches(command, 'meta_a', {}), false, - 'not matching key, simple string'); - - command = { - key: {key: 'meta_z', predicates: {isGreen: true}} - }; - t.equal(km._commandMatches(command, 'meta_z', {}), false, - 'object with not matching predicate'); - t.equal(km._commandMatches(command, 'meta_z', {isGreen: true}), true, - 'object with matching key and predicate'); - t.equal(km._commandMatches(command, 'meta_a', {isGreen: true}), false, - 'object with not matching key'); - t.equal(km._commandMatches(command, 'meta_a', {isGreen: false}), false, - 'object with neither matching'); - t.equal(km._commandMatches(command, 'meta_z', {isGreen: false}), false, - 'object with matching key and but different predicate'); - - command = { - key: ['meta_b', {key: 'meta_z', predicates: {isGreen: true}}, - {key: 'meta_c'}] - }; - t.equal(km._commandMatches(command, 'meta_z', {}), false, - 'list: object with not matching predicate'); - t.equal(km._commandMatches(command, 'meta_z', {isGreen: true}), true, - 'list: object with matching key and predicate'); - t.equal(km._commandMatches(command, 'meta_a', {isGreen: true}), false, - 'list: object with not matching key'); - t.equal(km._commandMatches(command, 'meta_a', {isGreen: false}), false, - 'list: object with neither matching'); - t.equal(km._commandMatches(command, 'meta_z', {isGreen: false}), false, - 'list: object with matching key and but different predicate'); - t.equal(km._commandMatches(command, 'meta_b'), true, - 'list: simple key match'); - t.equal(km._commandMatches(command, 'meta_c'), true, - 'list: object without predicate match'); - t.equal(km._commandMatches(command, 'meta_c', {isGreen: false}), true, - 'list: flags don\'t matter without predicates'); -}; - -}); diff --git a/plugins/pilot/lang.js b/plugins/pilot/lang.js deleted file mode 100644 index b8b946e1..00000000 --- a/plugins/pilot/lang.js +++ /dev/null @@ -1,107 +0,0 @@ -/* ***** 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 Services B.V. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Fabian Jakobs - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -define(function(require, exports, module) { - -exports.stringReverse = function(string) { - return string.split("").reverse().join(""); -}; - -exports.stringRepeat = function (string, count) { - return new Array(count + 1).join(string); -}; - -exports.copyObject = function(obj) { - var copy = {}; - for (var key in obj) { - copy[key] = obj[key]; - } - return copy; -}; - -exports.arrayToMap = function(arr) { - var map = {}; - 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(function(require, exports, module) { - -exports.inherits = function(ctor, superCtor) { - var tempCtor = function() {}; - tempCtor.prototype = superCtor.prototype; - ctor.super_ = superCtor.prototype; - ctor.prototype = new tempCtor(); - ctor.prototype.constructor = ctor; -}; - -exports.mixin = function(obj, mixin) { - for (var key in mixin) { - obj[key] = mixin[key]; - } -}; - -exports.implement = function(proto, mixin) { - exports.mixin(proto, mixin); -}; - -}); diff --git a/plugins/pilot/plugin_manager.js b/plugins/pilot/plugin_manager.js deleted file mode 100644 index d004240d..00000000 --- a/plugins/pilot/plugin_manager.js +++ /dev/null @@ -1,158 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - -var Promise = require("pilot/promise").Promise; - -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 -}; - -exports.Plugin = function(name) { - this.name = name; - this.status = this.INSTALLED; -}; - -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); - } - 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) { - 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; - }, - - shutdown: function(data, reason) { - if (this.status != this.STARTED) { - return; - } - pluginModule = require(this.name); - if (pluginModule.shutdown) { - pluginModule.shutdown(data, reason); - } - } -}; - -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); - }, - - 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); - } -}; - -exports.catalog = new exports.PluginCatalog(); - -}); diff --git a/plugins/pilot/promise.js b/plugins/pilot/promise.js deleted file mode 100644 index 8bd9f971..00000000 --- a/plugins/pilot/promise.js +++ /dev/null @@ -1,264 +0,0 @@ -/* ***** 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) - * - * 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(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; - -/** - * Outstanding promises. Handy list for debugging only. - */ -var _outstanding = []; - -/** - * Recently resolved promises. Also for debugging only. - */ -var _recent = []; - -/** - * 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; -}; - -/** - * Yeay for RTTI. - */ -Promise.prototype.isPromise = true; - -/** - * Have we either been resolve()ed or reject()ed? - */ -Promise.prototype.isComplete = function() { - return this._status != PENDING; -}; - -/** - * Have we resolve()ed? - */ -Promise.prototype.isResolved = function() { - return this._status == SUCCESS; -}; - -/** - * Have we reject()ed? - */ -Promise.prototype.isRejected = function() { - return this._status == ERROR; -}; - -/** - * 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); - } - } - - if (typeof onError === 'function') { - if (this._status === ERROR) { - onError.call(null, this._value); - } else if (this._status === PENDING) { - this._onErrorHandlers.push(onError); - } - } - - return this; -}; - -/** - * 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; -}; - -/** - * Supply the fulfillment of a promise - */ -Promise.prototype.resolve = function(data) { - return this._complete(this._onSuccessHandlers, SUCCESS, data, 'resolve'); -}; - -/** - * Renege on a promise - */ -Promise.prototype.reject = function(data) { - return this._complete(this._onErrorHandlers, ERROR, data, 'reject'); -}; - -/** - * 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; - } - - if (_traceCompletion) { - this._completeTrace = new Trace(new Error()); - } - - this._status = status; - this._value = data; - - // 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(); - } - - return this; -}; - -/** - * 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); - } - - // If the original array has nothing in it, return now to avoid waiting - if (promiseList.length === 0) { - return new Promise().resolve([]); - } - - 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); - } - } - }; - }; - - promiseList.forEach(function(promise, index) { - var onSuccess = onSuccessFactory(index); - var onError = groupPromise.reject.bind(groupPromise); - promise.then(onSuccess, onError); - }); - - return groupPromise; -}; - -exports.Promise = Promise; -exports._outstanding = _outstanding; -exports._recent = _recent; - -}); diff --git a/plugins/pilot/proxy.js b/plugins/pilot/proxy.js deleted file mode 100644 index 88d76a54..00000000 --- a/plugins/pilot/proxy.js +++ /dev/null @@ -1,83 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - -var Promise = require('pilot/promise').Promise; - -exports.xhr = function(method, url, async, beforeSendCallback) { - var pr = new Promise(); - - if (!skywriter.proxy || !skywriter.proxy.xhr) { - var req = new XMLHttpRequest(); - req.onreadystatechange = function() { - if (req.readyState !== 4) { - return; - } - - var status = req.status; - if (status !== 0 && status !== 200) { - var error = new Error(req.responseText + ' (Status ' + req.status + ")"); - error.xhr = req; - pr.reject(error); - return; - } - - pr.resolve(req.responseText); - }.bind(this); - - req.open("GET", url, async); - if (beforeSendCallback) { - beforeSendCallback(req); - } - req.send(); - } else { - skywriter.proxy.xhr.call(this, method, url, async, beforeSendCallback, pr); - } - - return pr; -}; - -exports.Worker = function(url) { - if (!skywriter.proxy || !skywriter.proxy.worker) { - return new Worker(url); - } else { - return new skywriter.proxy.worker(url); - } -}; - -}); diff --git a/plugins/pilot/rangeutils.js b/plugins/pilot/rangeutils.js deleted file mode 100644 index b4714f7b..00000000 --- a/plugins/pilot/rangeutils.js +++ /dev/null @@ -1,185 +0,0 @@ -/* ***** 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): - * Patrick Walton (pwalton@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(function(require, exports, module) { - -var util = require("util/util"); - -/** - * Returns the result of adding the two positions. - */ -exports.addPositions = function(a, b) { - return { row: a.row + b.row, col: a.col + b.col }; -}; - -/** Returns a copy of the given range. */ -exports.cloneRange = function(range) { - var oldStart = range.start, oldEnd = range.end; - var newStart = { row: oldStart.row, col: oldStart.col }; - var newEnd = { row: oldEnd.row, col: oldEnd.col }; - return { start: newStart, end: newEnd }; -}; - -/** - * Given two positions a and b, returns a negative number if a < b, 0 if a = b, - * or a positive number if a > b. - */ -exports.comparePositions = function(positionA, positionB) { - var rowDiff = positionA.row - positionB.row; - return rowDiff === 0 ? positionA.col - positionB.col : rowDiff; -}; - -/** - * Returns true if the two ranges are equal and false otherwise. - */ -exports.equal = function(rangeA, rangeB) { - return (exports.comparePositions(rangeA.start, rangeB.start) === 0 && - exports.comparePositions(rangeA.end, rangeB.end) === 0); -}; - -exports.extendRange = function(range, delta) { - var end = range.end; - return { - start: range.start, - end: { - row: end.row + delta.row, - col: end.col + delta.col - } - }; -}; - -/** - * Given two sets of ranges, returns the ranges of characters that exist in one - * of the sets but not both. - */ -exports.intersectRangeSets = function(setA, setB) { - var stackA = util.clone(setA), stackB = util.clone(setB); - var result = []; - while (stackA.length > 0 && stackB.length > 0) { - var rangeA = stackA.shift(), rangeB = stackB.shift(); - var startDiff = exports.comparePositions(rangeA.start, rangeB.start); - var endDiff = exports.comparePositions(rangeA.end, rangeB.end); - - if (exports.comparePositions(rangeA.end, rangeB.start) < 0) { - // A is completely before B - result.push(rangeA); - stackB.unshift(rangeB); - } else if (exports.comparePositions(rangeB.end, rangeA.start) < 0) { - // B is completely before A - result.push(rangeB); - stackA.unshift(rangeA); - } else if (startDiff < 0) { // A starts before B - result.push({ start: rangeA.start, end: rangeB.start }); - stackA.unshift({ start: rangeB.start, end: rangeA.end }); - stackB.unshift(rangeB); - } else if (startDiff === 0) { // A and B start at the same place - if (endDiff < 0) { // A ends before B - stackB.unshift({ start: rangeA.end, end: rangeB.end }); - } else if (endDiff > 0) { // A ends after B - stackA.unshift({ start: rangeB.end, end: rangeA.end }); - } - } else if (startDiff > 0) { // A starts after B - result.push({ start: rangeB.start, end: rangeA.start }); - stackA.unshift(rangeA); - stackB.unshift({ start: rangeA.start, end: rangeB.end }); - } - } - return result.concat(stackA, stackB); -}; - -exports.isZeroLength = function(range) { - return range.start.row === range.end.row && - range.start.col === range.end.col; -}; - -/** - * Returns the greater of the two positions. - */ -exports.maxPosition = function(a, b) { - return exports.comparePositions(a, b) > 0 ? a : b; -}; - -/** - * Converts a range with swapped 'end' and 'start' values into one with the - * values in the correct order. - * - * TODO: Unit test. - */ -exports.normalizeRange = function(range) { - return this.comparePositions(range.start, range.end) < 0 ? range : - { start: range.end, end: range.start }; -}; - -/** - * Returns a single range that spans the entire given set of ranges. - */ -exports.rangeSetBoundaries = function(rangeSet) { - return { - start: rangeSet[0].start, - end: rangeSet[rangeSet.length - 1].end - }; -}; - -exports.toString = function(range) { - var start = range.start, end = range.end; - return '[ ' + start.row + ', ' + start.col + ' ' + end.row + ',' + + end.col +' ]'; -}; - -/** - * Returns the union of the two ranges. - */ -exports.unionRanges = function(a, b) { - return { - start: a.start.row < b.start.row || - (a.start.row === b.start.row && a.start.col < b.start.col) ? - a.start : b.start, - end: a.end.row > b.end.row || - (a.end.row === b.end.row && a.end.col > b.end.col) ? - a.end : b.end - }; -}; - -exports.isPosition = function(pos) { - return !util.none(pos) && !util.none(pos.row) && !util.none(pos.col); -}; - -exports.isRange = function(range) { - return (!util.none(range) && exports.isPosition(range.start) && - exports.isPosition(range.end)); -}; - -}); \ No newline at end of file diff --git a/plugins/pilot/settings.js b/plugins/pilot/settings.js deleted file mode 100644 index 70653570..00000000 --- a/plugins/pilot/settings.js +++ /dev/null @@ -1,303 +0,0 @@ -/* ***** 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) - * - * 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(function(require, exports, module) { - -/** - * This plug-in manages settings. - */ - -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' -}; - -exports.startup = function(data, reason) { - catalog.addExtensionSpec(settingExtensionSpec); -}; - -exports.shutdown = function(data, reason) { - catalog.removeExtensionSpec(settingExtensionSpec); -}; - - -/** - * 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; - - Object.keys(settingSpec).forEach(function(key) { - this[key] = settingSpec[key]; - }, this); - - 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)); - } - - if (!this.name) { - throw new Error('Setting.name == undefined. Ignoring.', this); - } - - if (!this.defaultValue === undefined) { - throw new Error('Setting.defaultValue == undefined', this); - } - - this.value = this.defaultValue; -} -Setting.prototype = { - get: function() { - return this.value; - }, - - set: function(value) { - if (this.value === value) { - return; - } - - this.value = value; - if (this._settings.persister) { - this._settings.persister.persistValue(this._settings, this.name, value); - } - - this._dispatchEvent('change', { setting: this, value: value }); - }, - - /** - * Reset the value of the key setting to it's default - */ - resetValue: function() { - this.set(this.defaultValue); - } -}; -oop.implement(Setting.prototype, EventEmitter); - - -/** - * 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 = {}; - - // Storage for the active settings - this._settings = {}; - // We often want sorted setting names. Cache - this._settingNames = []; - - if (persister) { - this.setPersister(persister); - } -}; - -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(); - }, - - removeSetting: function(setting) { - var name = (typeof setting === 'string' ? setting : setting.name); - delete this._settings[name]; - util.arrayRemove(this._settingNames, name); - }, - - getSettingNames: function() { - return this._settingNames; - }, - - getSetting: function(name) { - return this._settings[name]; - }, - - /** - * 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); - } - }, - - resetAll: function() { - this.getSettingNames().forEach(function(key) { - this.resetValue(key); - }, this); - }, - - /** - * 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; - }, - - /** - * Prime the local cache with the defaults. - */ - _loadDefaultValues: function() { - this._loadFromObject(this._getDefaultValues()); - }, - - /** - * 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]); - } - } - } - }, - - /** - * 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)); - }, - - /** - * The default initial settings - */ - _getDefaultValues: function() { - return this.getSettingNames().map(function(key) { - return this._settings[key].spec.defaultValue; - }.bind(this)); - } -}; -exports.settings = new Settings(); - -/** - * Save the settings in a cookie - * This code has not been tested since reboot - * @constructor - */ -function CookiePersister() { -}; - -CookiePersister.prototype = { - loadInitialValues: function(settings) { - settings._loadDefaultValues(); - var data = cookie.get('settings'); - settings._loadFromObject(JSON.parse(data)); - }, - - 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; - } - } -}; - -exports.CookiePersister = CookiePersister; - -}); diff --git a/plugins/pilot/settings/canon.js b/plugins/pilot/settings/canon.js deleted file mode 100644 index 5ad36d50..00000000 --- a/plugins/pilot/settings/canon.js +++ /dev/null @@ -1,57 +0,0 @@ -/* ***** 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) - * - * 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(function(require, exports, module) { - - -var historyLengthSetting = { - name: "historyLength", - description: "How many typed commands do we recall for reference?", - type: "number", - defaultValue: 50 -}; - -exports.startup = function(data, reason) { - data.env.settings.addSetting(historyLengthSetting); -}; - -exports.shutdown = function(data, reason) { - data.env.settings.removeSetting(historyLengthSetting); -}; - - -}); diff --git a/plugins/pilot/stacktrace.js b/plugins/pilot/stacktrace.js deleted file mode 100644 index b5094e73..00000000 --- a/plugins/pilot/stacktrace.js +++ /dev/null @@ -1,332 +0,0 @@ -define(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. - - - -/** - * 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'; - } - - // SC doesn't do any detection of Chrome at this time. - - // 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'; - } - } - 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'); - }, - - firefox: function(e) { - var stack = e.stack; - if (!stack) { - console.log(e); - return []; - } - // 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; - - 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+/, ''); - } - } - - lines.splice(j, lines.length - j); - return lines; - }, - - // Safari, Opera 9+, IE, and others - other: function(curr) { - var ANON = '{anonymous}', fnRE = /function\s*([\w\-$]+)?\s*\(/i, stack = [], j = 0, fn, args; - - 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) + ')'; - - //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; - } -}; - -/** - * - */ -function NameGuesser() { -} - -NameGuesser.prototype = { - - sourceCache: {}, - - 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; - }, - - 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) {} - } - }, - - getSource: function(url) { - if (!(url in this.sourceCache)) { - this.sourceCache[url] = this.ajax(url).split('\n'); - } - return this.sourceCache[url]; - }, - - 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; - }, - - guessFunctionName: function(url, lineNo) { - try { - return this.guessFunctionNameFromLines(lineNo, this.getSource(url)); - } catch (e) { - return 'getSource failed with url: ' + url + ', exception: ' + e.toString(); - } - }, - - 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 '(?)'; - } -}; - -var guesser = new NameGuesser(); - -var frameIgnorePatterns = [ - /http:\/\/localhost:4020\/sproutcore.js:/ -]; - -exports.ignoreFramesMatching = function(regex) { - frameIgnorePatterns.push(regex); -}; - -/** - * 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 (guess) { - this._stack = guesser.guessFunctions(this._stack); - } -}; - -/** - * 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; - } - - 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; - } - }); - if (display) { - console.debug(frame); - printed++; - } - } -}; - -}); diff --git a/plugins/pilot/tests/testRangeutils.js b/plugins/pilot/tests/testRangeutils.js deleted file mode 100644 index d96c43a4..00000000 --- a/plugins/pilot/tests/testRangeutils.js +++ /dev/null @@ -1,163 +0,0 @@ -require.def(['require', 'exports', 'module', - 'rangeutils/tests/plugindev', - 'rangeutils/tests/utils/range' -], function(require, exports, module, - t, - Range -) { - -/* ***** 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): - * Skywriter Team (skywriter@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 ***** */ - - - - -exports.testAddPositions = function() { - t.deepEqual(Range.addPositions({ row: 0, col: 0 }, - { row: 0, col: 0 }), { row: 0, col: 0 }, '0,0 + 0,0 and 0,0'); - t.deepEqual(Range.addPositions({ row: 1, col: 0 }, - { row: 2, col: 0 }), { row: 3, col: 0 }, '1,0 + 2,0 and 3,0'); - t.deepEqual(Range.addPositions({ row: 0, col: 1 }, - { row: 0, col: 1 }), { row: 0, col: 2 }, '0,1 + 0,1 and 0,2'); - t.deepEqual(Range.addPositions({ row: 1, col: 2 }, - { row: -1, col: -2 }), { row: 0, col: 0 }, '1,2 + -1,-2 and 0,0'); -}; - -exports.testCloneRange = function() { - var oldRange = { start: { row: 1, col: 2 }, end: { row: 3, col: 4 } }; - var newRange = Range.cloneRange(oldRange); - t.deepEqual(oldRange, newRange, "the old range and the new range"); - t.ok(oldRange.start !== newRange.start, "the old range's start position " + - "is distinct from the new range's start position"); - t.ok(oldRange.end !== newRange.end, "the old range's end position is " + - "distinct from the new range's end position"); - t.ok(oldRange !== newRange, "the old range is distinct from the new " + - "range"); -}; - -exports.testComparePositions = function() { - t.equal(Range.comparePositions({ row: 0, col: 0 }, - { row: 0, col: 0 }), 0, '0,0 = 0,0'); - t.ok(Range.comparePositions({ row: 0, col: 0 }, - { row: 1, col: 0 }) < 0, '0,0 < 1,0'); - t.ok(Range.comparePositions({ row: 0, col: 0 }, - { row: 0, col: 1 }) < 0, '0,0 < 0,1'); - t.ok(Range.comparePositions({ row: 1, col: 0 }, - { row: 0, col: 0 }) > 0, '1,0 > 0,0'); - t.ok(Range.comparePositions({ row: 0, col: 1 }, - { row: 0, col: 0 }) > 0, '0,1 > 0,0'); -}; - -exports.testExtendRange = function() { - t.deepEqual(Range.extendRange({ - start: { row: 1, col: 2 }, - end: { row: 3, col: 4 } - }, { row: 5, col: 6 }), { - start: { row: 1, col: 2 }, - end: { row: 8, col: 10 } - }, '[ 1,2 3,4 ] extended by 5,6 = [ 1,2 8,10 ]'); - t.deepEqual(Range.extendRange({ - start: { row: 7, col: 8 }, - end: { row: 9, col: 10 } - }, { row: 0, col: 0 }), { - start: { row: 7, col: 8 }, - end: { row: 9, col: 10 } - }, '[ 7,8 9,10 ] extended by 0,0 remains the same'); -}; - -exports.testMaxPosition = function() { - t.deepEqual(Range.maxPosition({ row: 0, col: 0 }, - { row: 0, col: 0 }), { row: 0, col: 0 }, 'max(0,0 0,0) = 0,0'); - t.deepEqual(Range.maxPosition({ row: 0, col: 0 }, - { row: 1, col: 0 }), { row: 1, col: 0 }, 'max(0,0 1,0) = 1,0'); - t.deepEqual(Range.maxPosition({ row: 0, col: 0 }, - { row: 0, col: 1 }), { row: 0, col: 1 }, 'max(0,0 0,1) = 0,1'); - t.deepEqual(Range.maxPosition({ row: 1, col: 0 }, - { row: 0, col: 0 }), { row: 1, col: 0 }, 'max(1,0 0,0) = 1,0'); - t.deepEqual(Range.maxPosition({ row: 0, col: 1 }, - { row: 0, col: 0 }), { row: 0, col: 1 }, 'max(0,1 0,0) = 0,1'); -}; - -exports.testNormalizeRange = function() { - t.deepEqual(Range.normalizeRange({ - start: { row: 0, col: 0 }, - end: { row: 0, col: 0 } - }), { - start: { row: 0, col: 0 }, - end: { row: 0, col: 0 } - }, 'normalize(0,0 0,0) and (0,0 0,0)'); - t.deepEqual(Range.normalizeRange({ - start: { row: 1, col: 2 }, - end: { row: 3, col: 4 } - }), { - start: { row: 1, col: 2 }, - end: { row: 3, col: 4 } - }, 'normalize(1,2 3,4) and (1,2 3,4)'); - t.deepEqual(Range.normalizeRange({ - start: { row: 4, col: 3 }, - end: { row: 2, col: 1 } - }), { - start: { row: 2, col: 1 }, - end: { row: 4, col: 3 } - }, 'normalize(4,3 2,1) and (2,1 4,3)'); -}; - -exports.testUnionRanges = function() { - t.deepEqual(Range.unionRanges({ - start: { row: 1, col: 2 }, - end: { row: 3, col: 4 } - }, { - start: { row: 5, col: 6 }, - end: { row: 7, col: 8 } - }), { - start: { row: 1, col: 2 }, - end: { row: 7, col: 8 } - }, '[ 1,2 3,4 ] union [ 5,6 7,8 ] = [ 1,2 7,8 ]'); - t.deepEqual(Range.unionRanges({ - start: { row: 4, col: 4 }, - end: { row: 5, col: 5 } - }, { - start: { row: 3, col: 3 }, - end: { row: 4, col: 5 } - }), { - start: { row: 3, col: 3 }, - end: { row: 5, col: 5 } - }, '[ 4,4 5,5 ] union [ 3,3 4,5 ] = [ 3,3 5,5 ]'); -}; - - -}); diff --git a/plugins/pilot/typecheck.js b/plugins/pilot/typecheck.js deleted file mode 100644 index 40ea1630..00000000 --- a/plugins/pilot/typecheck.js +++ /dev/null @@ -1,80 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - -var objectToString = Object.prototype.toString; - -/** - * Return true if it is a String - */ -exports.isString = function(it) { - return it && objectToString.call(it) === "[object String]"; -}; - -/** - * Returns true if it is a Boolean. - */ -exports.isBoolean = function(it) { - return it && objectToString.call(it) === "[object Boolean]"; -}; - -/** - * Returns true if it is a Number. - */ -exports.isNumber = function(it) { - return it && objectToString.call(it) === "[object Number]" && isFinite(it); -}; - -/** - * Hack copied from dojo. - */ -exports.isObject = function(it) { - return it !== undefined && - (it === null || typeof it == "object" || - Array.isArray(it) || exports.isFunction(it)); -}; - -/** - * Is the passed object a function? - * From dojo.isFunction() - */ -exports.isFunction = function(it) { - return it && objectToString.call(it) === "[object Function]"; -}; - -}); \ No newline at end of file diff --git a/plugins/pilot/types.js b/plugins/pilot/types.js deleted file mode 100644 index 0a95972f..00000000 --- a/plugins/pilot/types.js +++ /dev/null @@ -1,262 +0,0 @@ -/* ***** 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 ***** */ - -define(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 < arguments; i++) { - if (arguments[i] > combined) { - combined = arguments[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; - } -}; -exports.Type = Type; - -/** - * Private registry of types - * Invariant: types[name] = type.name - */ -var types = {}; - -/** - * 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); - } -}; - -/** - * 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) { - var type = types[name]; - if (typeof type === 'function') { - // TODO: should we complain if typeSpec is a string? - type = new type(typeSpec); - } - return type; -} - -/** - * Find a type, previously registered using #registerType() - */ -exports.getType = function(typeSpec) { - if (typeof typeSpec === 'string') { - return reconstituteType(typeSpec, 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); -}; - - -}); diff --git a/plugins/pilot/types/basic.js b/plugins/pilot/types/basic.js deleted file mode 100644 index 9d775f6a..00000000 --- a/plugins/pilot/types/basic.js +++ /dev/null @@ -1,291 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - -var types = require("pilot/types"); -var Type = types.Type; -var Conversion = types.Conversion; -var Status = types.Status; - -/** - * 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; -}; - -text.parse = function(value) { - if (typeof value != 'string') { - throw new Error('non-string passed to text.parse()'); - } - 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; - } - 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, ''); - } - - var reply = new Conversion(parseInt(value, 10)); - if (isNaN(reply.value)) { - reply.status = Status.INVALID; - reply.message = 'Can\'t convert "' + value + '" to a number.'; - } - - return reply; -}; - -number.decrement = function(value) { - return value - 1; -}; - -number.increment = function(value) { - return value + 1; -}; - -number.name = 'number'; - -/** - * One of a known set of options - */ -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)); - } - Object.keys(typeSpec).forEach(function(key) { - this[key] = typeSpec[key]; - }, this); -}; - -SelectionType.prototype = new Type(); - -SelectionType.prototype.stringify = function(value) { - return value; -}; - -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; - - // 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; - } - else if (option.indexOf(str) === 0) { - completions.push(this.fromString(option)); - } - }, this); - - if (hasMatched) { - return new Conversion(matchedValue); - } - else { - // This is something of a hack. settings - if (this.noMatch) { - this.noMatch(); - } - - if (completions.length > 0) { - var msg = 'Possibilities' + - (str.length === 0 ? '' : ' for \'' + str + '\''); - return new Conversion(null, Status.INCOMPLETE, msg, completions); - } - else { - var msg = 'Can\'t use \'' + str + '\'.'; - return new Conversion(null, Status.INVALID, msg, completions); - } - } -}; - -SelectionType.prototype.fromString = function(str) { - return str; -}; - -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]); -}; - -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); - } - return this.fromString(data[index]); -}; - -SelectionType.prototype.name = 'selection'; - -/** - * SelectionType is a base class for other types - */ -exports.SelectionType = SelectionType; - -/** - * 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; - } -}); - - -/** - * One of a known set of options - */ -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'); - } - 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); -}; - -DeferredType.prototype.parse = function(value) { - return this.defer().parse(value); -}; - -DeferredType.prototype.decrement = function(value) { - var deferred = this.defer(); - return (deferred.decrement ? deferred.decrement(value) : undefined); -}; - -DeferredType.prototype.increment = function(value) { - var deferred = this.defer(); - return (deferred.increment ? deferred.increment(value) : undefined); -}; - -DeferredType.prototype.name = 'deferred'; - -/** - * DeferredType is a base class for other types - */ -exports.DeferredType = DeferredType; - -/** - * Registration and de-registration. - */ -exports.startup = function() { - types.registerType(text); - types.registerType(number); - types.registerType(bool); - types.registerType(SelectionType); - types.registerType(DeferredType); -}; - -exports.shutdown = function() { - types.unregisterType(text); - types.unregisterType(number); - types.unregisterType(bool); - types.unregisterType(SelectionType); - types.unregisterType(DeferredType); -}; - - -}); diff --git a/plugins/pilot/types/command.js b/plugins/pilot/types/command.js deleted file mode 100644 index f29c8bc2..00000000 --- a/plugins/pilot/types/command.js +++ /dev/null @@ -1,75 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - -var canon = require("pilot/canon"); -var SelectionType = require("pilot/types/basic").SelectionType; -var types = require("pilot/types"); - - -/** - * 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); - } -}); - - -/** - * Registration and de-registration. - */ -exports.startup = function() { - types.registerType(command); -}; - -exports.shutdown = function() { - types.unregisterType(command); -}; - - -}); diff --git a/plugins/pilot/types/settings.js b/plugins/pilot/types/settings.js deleted file mode 100644 index 065bdca5..00000000 --- a/plugins/pilot/types/settings.js +++ /dev/null @@ -1,109 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { - -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; - - -/** - * 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; - -/** - * 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; - } -}); - -/** - * 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'); - } - } -}); - -var env; - -/** - * 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); -}; - -exports.shutdown = function(data, reason) { - types.unregisterType(setting); - types.unregisterType(settingValue); -}; - - -}); diff --git a/plugins/pilot/useragent.js b/plugins/pilot/useragent.js deleted file mode 100644 index 06c9432e..00000000 --- a/plugins/pilot/useragent.js +++ /dev/null @@ -1,92 +0,0 @@ -/* ***** 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 Services B.V. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Fabian Jakobs - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -define(function(require, exports, module) { - -var os = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase(); -var ua = navigator.userAgent; -var av = navigator.appVersion; - -/** Is the user using a browser that identifies itself as Windows */ -exports.isWin = (os == "win"); - -/** Is the user using a browser that identifies itself as Mac OS */ -exports.isMac = (os == "mac"); - -/** Is the user using a browser that identifies itself as Linux */ -exports.isLinux = (os == "linux"); - -exports.isIE = ! + "\v1"; - -/** Is this Firefox or related? */ -exports.isGecko = exports.isMozilla = window.controllers && window.navigator.product === "Gecko"; - -/** 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.isAIR = ua.indexOf("AdobeAIR") >= 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.OS = { - LINUX: 'LINUX', - MAC: 'MAC', - WINDOWS: 'WINDOWS' -}; - -/** - * 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']; - } -}; - -}); diff --git a/support/cockpit b/support/cockpit new file mode 160000 index 00000000..47df3c34 --- /dev/null +++ b/support/cockpit @@ -0,0 +1 @@ +Subproject commit 47df3c340244b15c272ed87b17cd87659f4bcd0c From 511de83908fe993b0084478378c2969acee5a65c Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Fri, 7 Jan 2011 12:15:25 +0100 Subject: [PATCH 02/59] Simple line wrapping is up but a little bit of a hack right now --- lib/ace/layer/cursor.js | 23 ++------- lib/ace/layer/gutter.js | 2 +- lib/ace/layer/marker.js | 10 +++- lib/ace/layer/text.js | 71 ++++++++++++++++++++------- lib/ace/virtual_renderer.js | 98 ++++++++++++++++++++++++++++++++++--- support/paths.js | 1 + 6 files changed, 160 insertions(+), 45 deletions(-) diff --git a/lib/ace/layer/cursor.js b/lib/ace/layer/cursor.js index 7d1b7fa6..be444747 100644 --- a/lib/ace/layer/cursor.js +++ b/lib/ace/layer/cursor.js @@ -107,14 +107,8 @@ var Cursor = function(parentEl) { top : 0 }; } - - var cursorLeft = Math.round(this.position.column * this.config.characterWidth); - var cursorTop = this.position.row * this.config.lineHeight; - - return { - left : cursorLeft, - top : cursorTop - }; + + return this.config.getPixelPosition(this.position.row, this.position.column); }; this.update = function(config) { @@ -123,17 +117,10 @@ var Cursor = function(parentEl) { this.config = config; - var cursorLeft = Math.round(this.position.column * config.characterWidth); - var cursorTop = this.position.row * config.lineHeight; + this.pixelPos = this.getPixelPosition(); - this.pixelPos = { - left : cursorLeft, - top : cursorTop - }; - - this.cursor.style.left = cursorLeft + "px"; - this.cursor.style.top = (cursorTop - (config.firstRow * config.lineHeight)) - + "px"; + this.cursor.style.left = this.pixelPos.left + "px"; + this.cursor.style.top = this.pixelPos.top + "px"; this.cursor.style.width = config.characterWidth + "px"; this.cursor.style.height = config.lineHeight + "px"; diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index 4202772f..e4591e01 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -71,7 +71,7 @@ var Gutter = function(parentEl) { html.push("

    ", (i+1), "
    "); + "' style='height:", (config.wrapped[i].length + 1) * config.lineHeight, "px;'>", (i+1), ""); html.push(""); } diff --git a/lib/ace/layer/marker.js b/lib/ace/layer/marker.js index 06422bd5..be12014f 100644 --- a/lib/ace/layer/marker.js +++ b/lib/ace/layer/marker.js @@ -85,6 +85,10 @@ var Marker = function(parentEl) { var range = marker.range.clipRows(config.firstRow, config.lastRow); if (range.isEmpty()) continue; + + // TODO: Add this conversion to the range object directly! + range.start = this.config.posToWrappedPos(range.start.row, range.start.column); + range.end = this.config.posToWrappedPos(range.end.row, range.end.column); if (range.isMultiLine()) { if (marker.type == "text") { @@ -121,7 +125,8 @@ var Marker = function(parentEl) { }; this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig) { - var range = range.toScreenRange(this.doc); + // TODO: Add this back. + // var range = range.toScreenRange(this.doc); // from selection start to the end of the line var height = layerConfig.lineHeight; @@ -163,7 +168,8 @@ var Marker = function(parentEl) { }; this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig) { - var range = range.toScreenRange(this.doc); + // TODO: Add this back. + //var range = range.toScreenRange(this.doc); var height = layerConfig.lineHeight; var width = Math.round((range.end.column - range.start.column) * layerConfig.characterWidth); diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index 98ff7bfc..371cd7e6 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -99,7 +99,7 @@ var Text = function(parentEl) { style.width = style.height = "auto"; style.left = style.top = "-1000px"; - + style.visibility = "hidden"; style.position = "absolute"; style.overflow = "visible"; @@ -151,7 +151,7 @@ var Text = function(parentEl) { this.updateLines = function(layerConfig, firstRow, lastRow) { this.$computeTabString(); this.config = layerConfig; - + var first = Math.max(firstRow, layerConfig.firstRow); var last = Math.min(lastRow, layerConfig.lastRow); @@ -166,6 +166,9 @@ var Text = function(parentEl) { var html = []; _self.$renderLine(html, i, tokens[i-first].tokens); lineElement.innerHTML = html.join(""); + // The height of the line might have changed if wrapped mode + // is active. + lineElement.style.height = (layerConfig.wrapped[i].length + 1) * layerConfig.lineHeight + "px"; } }); }; @@ -226,7 +229,7 @@ var Text = function(parentEl) { var lineEl = document.createElement("div"); lineEl.className = "ace_line"; var style = lineEl.style; - style.height = _self.$characterSize.height + "px"; + style.height = (config.wrapped[row].length + 1) * config.lineHeight + "px"; style.width = config.width + "px"; var html = []; @@ -244,15 +247,20 @@ var Text = function(parentEl) { var html = []; var _self = this; - this.tokenizer.getTokens(config.firstRow, config.lastRow, function(tokens) { - for ( var i = config.firstRow; i <= config.lastRow; i++) { - html.push("
    "); - _self.$renderLine(html, i, tokens[i-config.firstRow].tokens), html.push("
    "); - } - - _self.element.innerHTML = html.join(""); + this.$renderLinesFragment(config, config.firstRow, config.lastRow, function(fragment) { + // TODO: Use a proper method to remove all children of the element. + _self.element.innerHTML = ""; + _self.element.appendChild(fragment); }); + // this.tokenizer.getTokens(config.firstRow, config.lastRow, function(tokens) { + // for ( var i = config.firstRow; i <= config.lastRow; i++) { + // html.push("
    "); + // _self.$renderLine(html, i, tokens[i-config.firstRow].tokens), html.push("
    "); + // } + // + // _self.element.innerHTML = html.join(""); + // }); }; this.$textToken = { @@ -262,6 +270,8 @@ var Text = function(parentEl) { }; this.$renderLine = function(stringBuilder, row, tokens) { + stringBuilder.push("
    "); + var wrappedInfo = this.config.wrapped[row]; // if (this.$showInvisibles) { // var self = this; // var spaceRe = /[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]+/g; @@ -275,22 +285,48 @@ var Text = function(parentEl) { var spaceReplace = " "; // } - for ( var i = 0; i < tokens.length; i++) { - var token = tokens[i]; - - var output = token.value + var _self = this; + function addToken(token, value) { + var output = value .replace(/&/g, "&") .replace(/", output, ""); } else { stringBuilder.push(output); } + } + + var chars = 0; + var wrapSection = 0; + var maxChars = wrappedInfo[wrapSection] || 9999; + var value; + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + + if (chars + token.value.length < maxChars) { + addToken(token, token.value); + chars += token.value.length; + } else { + value = token.value; + while (chars + value.length >= maxChars) { + addToken(token, value.substring(0, maxChars - chars)); + value = value.substring(maxChars - chars); + chars = maxChars; + stringBuilder.push("
    "); + wrapSection ++; + maxChars = wrappedInfo[wrapSection] || 9999; + } + if (value.length != 0) { + chars += value.length; + addToken(token, value); + } + } }; if (this.$showInvisibles) { @@ -300,6 +336,7 @@ var Text = function(parentEl) { stringBuilder.push("" + this.EOF_CHAR + ""); } } + stringBuilder.push("
    "); }; }).call(Text.prototype); diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 03c3322e..f3552a21 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -82,7 +82,7 @@ var VirtualRenderer = function(container, theme) { this.$cursorLayer = new CursorLayer(this.content); this.layers = [ this.$markerLayer, textLayer, this.$cursorLayer ]; - + this.scrollBar = new ScrollBar(container); this.scrollBar.addEventListener("scroll", this.onScroll.bind(this)); @@ -118,6 +118,9 @@ var VirtualRenderer = function(container, theme) { }; (function() { + this.layerConfig = { + wrapped: [] + }; this.showGutter = true; @@ -142,10 +145,26 @@ var VirtualRenderer = function(container, theme) { this.$loop.schedule(this.CHANGE_FULL); }; + this.$updateWrappedLinesInfo = function(firstRow, lastRow) { + var WRAPSIZE = 12; + var wrappedInfo = this.layerConfig.wrapped; + var lines = this.lines; + for (var row = firstRow; row <= lastRow; row++) { + var col = 12; + wrappedInfo[row] = []; + while (col < lines[row].length) { + wrappedInfo[row].push(col); + col += 12; + } + } + }; + /** * Triggers partial update of the text layer */ this.updateLines = function(firstRow, lastRow) { + this.$updateWrappedLinesInfo(firstRow, lastRow); + console.log("updateLines", firstRow, lastRow); if (lastRow === undefined) lastRow = Infinity; @@ -400,7 +419,7 @@ var VirtualRenderer = function(container, theme) { var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight)); var lastRow = Math.max(0, Math.min(this.lines.length, firstRow + lineCount) - 1); - var layerConfig = this.layerConfig = { + var layerConfig = oop.mixin(this.layerConfig, { width : longestLine, padding : this.$padding, firstRow : firstRow, @@ -410,7 +429,11 @@ var VirtualRenderer = function(container, theme) { minHeight : minHeight, offset : offset, height : this.$size.scrollerHeight - }; + }); + + // Ensure that there is a wrapped array for all the rows in the current + // view port. + this.$updateWrappedLinesInfo(firstRow, lastRow); for ( var i = 0; i < this.layers.length; i++) { var layer = this.layers[i]; @@ -570,10 +593,12 @@ var VirtualRenderer = function(container, theme) { var row = Math.floor((pageY + this.scrollTop - canvasPos.top) / this.lineHeight); - return { - row : row, - column : this.doc.screenToDocumentColumn(Math.max(0, Math.min(row, this.doc.getLength()-1)), col) - }; + return this.layerConfig.wrappedPosToPos( + row, + col + // TODO: Figure out how to calculate tabs here... + //this.doc.screenToDocumentColumn(Math.max(0, Math.min(row, this.doc.getLength()-1)), col) + ); }; this.textToScreenCoordinates = function(row, column) { @@ -587,6 +612,65 @@ var VirtualRenderer = function(container, theme) { pageY: canvasPos.top + y - this.getScrollTop() } }; + + this.wrappedPosToPos = function(row, column) { + var linesCount = this.wrapped.length; + var realRow = 0; + while (realRow < linesCount && row >= this.wrapped[realRow].length + 1) { + row -= this.wrapped[realRow].length + 1; + realRow ++; + } + return { + row: realRow, + column: column + (realRow < linesCount ? this.wrapped[realRow][row - 1] || 0 : 0) + }; + }; + + this.posToWrappedPos = function(row, column) { + // TODO: Why can it happen, that row is higher then the current count + // of lines (note lines in doc, not only in wrapped!). Happens when + // the cursor is in the last line and the marker "ace_active_line" is + // painted. + if (row > this.wrapped.length - 1) { + row = this.wrapped.length - 1; + column = 99999; + } + + var rows = 0; + for (var i = 0; i < row; i++) { + rows += this.wrapped[i].length + 1; + } + + var col = column; + for (var s = 0; s < this.wrapped[row].length; s++) { + if (column > this.wrapped[row][s]) { + col = column - this.wrapped[row][s]; + rows ++; + } else { + break; + } + } + return { + row: rows, + column: col + }; + }; + + this.getPixelPosition = function(row, column) { + var pos = this.posToWrappedPos(row, column); + var cursorLeft = Math.round(pos.column * this.characterWidth); + var cursorTop = pos.row * this.lineHeight; + + return { + left : cursorLeft, + top : cursorTop + }; + }; + + // TODO: This should get passed in a different way to the cursorLayer! + this.layerConfig.getPixelPosition = this.getPixelPosition; + this.layerConfig.posToWrappedPos = this.posToWrappedPos; + this.layerConfig.wrappedPosToPos = this.wrappedPosToPos; this.visualizeFocus = function() { dom.addCssClass(this.container, "ace_focus"); diff --git a/support/paths.js b/support/paths.js index 1be92a90..552c7022 100644 --- a/support/paths.js +++ b/support/paths.js @@ -4,4 +4,5 @@ require.paths.unshift(__dirname + "/../plugins"); require.paths.unshift(__dirname + "/async/lib"); require.paths.unshift(__dirname + "/node-htmlparser/lib"); require.paths.unshift(__dirname + "/jsdom/lib"); +require.paths.unshift(__dirname + "/cockpit/support/pilot/lib"); require.paths.unshift(__dirname); From c30b9ece8ff68edb6aab0a072fe777d95f438de3 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Sat, 8 Jan 2011 21:14:51 +0100 Subject: [PATCH 03/59] Move wrapping logging into Document. --- demo/demo_startup.js | 1 + lib/ace/document.js | 216 +++++++++++++++++++++++++++++------- lib/ace/layer/cursor.js | 12 +- lib/ace/layer/gutter.js | 12 +- lib/ace/layer/marker.js | 13 +-- lib/ace/layer/text.js | 53 +++++---- lib/ace/range.js | 10 +- lib/ace/virtual_renderer.js | 104 ++--------------- 8 files changed, 244 insertions(+), 177 deletions(-) diff --git a/demo/demo_startup.js b/demo/demo_startup.js index 6ffd8771..dcc9f42a 100644 --- a/demo/demo_startup.js +++ b/demo/demo_startup.js @@ -58,6 +58,7 @@ exports.launch = function(env) { var docs = {}; docs.js = new Document(document.getElementById("jstext").innerHTML); + docs.js.setUseWrapMode(true); docs.js.setMode(new JavaScriptMode()); docs.js.setUndoManager(new UndoManager()); diff --git a/lib/ace/document.js b/lib/ace/document.js index e60dbbd7..67b16daa 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -45,17 +45,18 @@ var TextMode = require("ace/mode/text").Mode; var Range = require("ace/range").Range; var Document = function(text, mode) { - + this.modified = true; this.lines = []; this.selection = new Selection(this); this.$breakpoints = []; + this.$wrapData = []; this.listeners = []; if (mode) { this.setMode(mode); } - + if (Array.isArray(text)) { this.$insertLines(0, text); } else { @@ -159,7 +160,7 @@ var Document = function(text, mode) { this.getTabSize = function() { return this.$tabSize; }; - + this.isTabStop = function(position) { return this.$useSoftTabs && (position.column % this.$tabSize == 0); }; @@ -199,13 +200,13 @@ var Document = function(text, mode) { this.$autoNewLine = "\n"; } }; - + this.tokenRe = /^[\w\d]+/g; this.nonTokenRe = /^[^\w\d]+/g; - + this.getWordRange = function(row, column) { var line = this.getLine(row); - + var inToken = false; if (column > 0) { inToken = !!line.charAt(column - 1).match(this.tokenRe); @@ -321,12 +322,12 @@ var Document = function(text, mode) { }; /** - * Get a verbatim copy of the given line as it is in the document + * Get a verbatim copy of the given line as it is in the document */ this.getLine = function(row) { return this.lines[row] || ""; }; - + /** * Get a line as it is displayed on screen. Tabs are replaced by spaces. */ @@ -455,18 +456,18 @@ var Document = function(text, mode) { : undefined); return end; }; - + /** * @param rows Array[Integer] sorted list of rows */ this.multiRowInsert = function(rows, column, text) { var lines = this.lines; - + for (var i=rows.length-1; i>=0; i--) { var row = rows[i]; if (row >= lines.length) continue; - + var diff = column - lines[row].length; if ( diff > 0) { var padded = lang.stringRepeat(" ", diff) + text; @@ -476,10 +477,10 @@ var Document = function(text, mode) { padded = text; offset = 0; } - + var end = this.$insert({row: row, column: column+offset}, padded, false); } - + if (end) { this.fireChangeEvent(rows[0], rows[rows.length-1] + end.row - rows[0]); return { @@ -593,16 +594,16 @@ var Document = function(text, mode) { this.multiRowRemove = function(rows, range) { if (range.start.row !== rows[0]) throw new TypeError("range must start in the first row!"); - + var height = range.end.row - rows[0]; for (var i=rows.length-1; i>=0; i--) { var row = rows[i]; if (row >= this.lines.length) continue; - + var end = this.$remove(new Range(row, range.start.column, row+height, range.end.column), false); } - + if (end) { if (height < 0) this.fireChangeEvent(rows[0]+height, undefined); @@ -610,7 +611,7 @@ var Document = function(text, mode) { this.fireChangeEvent(rows[0], height == 0 ? rows[rows.length-1] : undefined); } }; - + this.$remove = function(range, fromUndo) { if (range.isEmpty()) return; @@ -639,7 +640,7 @@ var Document = function(text, mode) { this.lines.splice(firstRow, lastRow - firstRow + 1, ""); return range.start; }; - + this.undoChanges = function(deltas) { this.selection.clearSelection(); for (var i=deltas.length-1; i>=0; i--) { @@ -685,7 +686,7 @@ var Document = function(text, mode) { return end; }; - this.indentRows = function(startRow, endRow, indentString) { + this.indentRows = function(startRow, endRow, indentString) { indentString = indentString.replace("\t", this.getTabString()); for (var row=startRow; row<=endRow; row++) { this.$insert({row: row, column:0}, indentString); @@ -698,15 +699,15 @@ var Document = function(text, mode) { var rowRange = range.collapseRows(); var deleteRange = new Range(0, 0, 0, 0); var size = this.getTabSize(); - + for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) { var line = this.getLine(i); - + deleteRange.start.row = i; deleteRange.end.row = i; for (var j = 0; j < size; ++j) if (line.charAt(j) != ' ') - break; + break; if (j < size && line.charAt(j) == '\t') { deleteRange.start.column = j; deleteRange.end.column = j + 1; @@ -722,7 +723,7 @@ var Document = function(text, mode) { } this.fireChangeEvent(range.start.row, range.end.row); return range; - } + } this.moveLinesUp = function(firstRow, lastRow) { if (firstRow <= 0) return 0; @@ -730,7 +731,7 @@ var Document = function(text, mode) { var removed = this.lines.slice(firstRow, lastRow + 1); this.$remove(new Range(firstRow-1, this.lines[firstRow-1].length, lastRow, this.lines[lastRow].length)); this.$insertLines(firstRow - 1, removed); - + this.fireChangeEvent(firstRow - 1, lastRow); return -1; }; @@ -741,7 +742,7 @@ var Document = function(text, mode) { var removed = this.lines.slice(firstRow, lastRow + 1); this.$remove(new Range(firstRow, 0, lastRow + 1, 0)); this.$insertLines(firstRow+1, removed); - + this.fireChangeEvent(firstRow, lastRow + 1); return 1; }; @@ -763,26 +764,72 @@ var Document = function(text, mode) { return Math.max(0, Math.min(row, this.lines.length-1)); }; - this.documentToScreenColumn = function(row, docColumn) { - var tabSize = this.getTabSize(); +}).call(Document.prototype); - var screenColumn = 0; - var remaining = docColumn; - var line = this.getLine(row).split("\t"); - for (var i=0; i len) { - remaining -= (len + 1); - screenColumn += len + tabSize; +(function() { + this.$wrapLimit = 12; + this.$useWrapMode = false; + this.setUseWrapMode = function(useWrapMode) { + var _self = this; + function computeWrapData(e) { + var lines = _self.lines, wrapData = _self.$wrapData; + var wrapLimit = _self.$wrapLimit; + + if (!e.data.lastRow) { + e.data.lastRow = _self.lines.length - 1; } - else { - screenColumn += remaining; - break; + + for (var row = e.data.firstRow; row <= e.data.lastRow; row++) { + var col = wrapLimit; + wrapData[row] = []; + while (col < lines[row].length) { + wrapData[row].push(col); + col += wrapLimit; + } } + }; + + this.$useWrapMode = useWrapMode; + computeWrapData({ data: { firstRow: 0 } }); + this._dispatchEvent("changeWrapMode"); + + if (useWrapMode) { + this.addEventListener("change", computeWrapData); + } else { + this.removeEventListener("change", computeWrapData); + } + }; + + this.getUseWrapMode = function() { + return this.$useWrapMode; + }; + + this.setWrapLimit = function(wrapLimit) { + this.$wrapLimit = wrapLimit; + }; + + this.getWrapLimit = function() { + return this.$wrapLimit; + }; + + this.getRowHeight = function(config, row) { + var rows; + if (!this.$useWrapMode) { + rows = 1; + } else { + rows = this.$wrapData[row].length + 1; } - return screenColumn; + return rows * config.lineHeight; + }; + + this.getRowSplitData = function(row) { + if (!this.$useWrapMode) { + return undefined; + } else { + return this.$wrapData[row]; + } }; this.screenToDocumentColumn = function(row, screenColumn) { @@ -810,7 +857,96 @@ var Document = function(text, mode) { return docColumn; }; -}).call(Document.prototype); + this.screenToDocumentPosition = function(row, column) { + if (!this.$useWrapMode) { + return { + row: row, + column: this.screenToDocumentColumn(row, column) + } + } + + var wrapData = this.$wrapData, linesCount = this.lines.length; + + var docRow = 0; + while (docRow < linesCount && row >= wrapData[docRow].length + 1) { + row -= wrapData[docRow].length + 1; + docRow ++; + } + var docColumn = column + + (docRow < linesCount ? wrapData[docRow][row - 1] || 0 : 0); + + return { + row: docRow, + column: docColumn + }; + }; + + this.documentToScreenColumn = function(row, docColumn) { + var tabSize = this.getTabSize(); + + var screenColumn = 0; + var remaining = docColumn; + + var line = this.getLine(row).split("\t"); + for (var i=0; i len) { + remaining -= (len + 1); + screenColumn += len + tabSize; + } + else { + screenColumn += remaining; + break; + } + } + + return screenColumn; + }; + + this.documentToScreenPosition = function(row, column) { + if (!this.$useWrapMode) { + return { + row: row, + column: this.documentToScreenColumn(row, column) + } + } + + var wrapData = this.$wrapData; + var screenRow = 0; + + // Handle special case where the row is outside of the range of lines. + if (row > wrapData.length - 1) { + for (row = 0; row < wrapData.length; row ++) { + screenRow += wrapData[row].length + 1; + } + return { + row: screenRow, + column: 0 + } + } + + for (var i = 0; i < row; i++) { + screenRow += wrapData[i].length + 1; + } + + var screenColumn = column; + var wrapRowData = wrapData[row]; + for (var split = 0; split < wrapRowData.length; split++) { + if (column > wrapRowData[split]) { + screenColumn = column - wrapRowData[split]; + screenRow ++; + } else { + break; + } + } + + return { + row: screenRow, + column: screenColumn + }; + }; + +}).call(Document.prototype) exports.Document = Document; }); diff --git a/lib/ace/layer/cursor.js b/lib/ace/layer/cursor.js index be444747..8fcbb1c1 100644 --- a/lib/ace/layer/cursor.js +++ b/lib/ace/layer/cursor.js @@ -107,8 +107,16 @@ var Cursor = function(parentEl) { top : 0 }; } - - return this.config.getPixelPosition(this.position.row, this.position.column); + + var pos = this.doc.documentToScreenPosition(this.position.row, + this.position.column); + var cursorLeft = Math.round(pos.column * this.config.characterWidth); + var cursorTop = pos.row * this.config.lineHeight; + + return { + left : cursorLeft, + top : cursorTop + }; }; this.update = function(config) { diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index e4591e01..bd182ddb 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -48,14 +48,18 @@ var Gutter = function(parentEl) { (function() { + this.setDocument = function(doc) { + this.doc = doc; + }; + this.addGutterDecoration = function(row, className){ - if (!this.$decorations[row]) + if (!this.$decorations[row]) this.$decorations[row] = ""; this.$decorations[row] += " ace_" + className; } - + this.removeGutterDecoration = function(row, className){ - this.$decorations[row] = + this.$decorations[row] = this.$decorations[row].replace(" ace_" + className, ""); } @@ -71,7 +75,7 @@ var Gutter = function(parentEl) { html.push("
    ", (i+1), "
    "); + "' style='height:", this.doc.getRowHeight(config, i) + "px'>", (i+1), ""); html.push(""); } diff --git a/lib/ace/layer/marker.js b/lib/ace/layer/marker.js index be12014f..517f1775 100644 --- a/lib/ace/layer/marker.js +++ b/lib/ace/layer/marker.js @@ -85,10 +85,8 @@ var Marker = function(parentEl) { var range = marker.range.clipRows(config.firstRow, config.lastRow); if (range.isEmpty()) continue; - - // TODO: Add this conversion to the range object directly! - range.start = this.config.posToWrappedPos(range.start.row, range.start.column); - range.end = this.config.posToWrappedPos(range.end.row, range.end.column); + + range = range.toScreenRange(this.doc); if (range.isMultiLine()) { if (marker.type == "text") { @@ -105,7 +103,6 @@ var Marker = function(parentEl) { }; this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) { - // selection start var row = range.start.row; var lineRange = new Range(row, range.start.column, row, this.doc.getLine(row).length); @@ -125,9 +122,6 @@ var Marker = function(parentEl) { }; this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig) { - // TODO: Add this back. - // var range = range.toScreenRange(this.doc); - // from selection start to the end of the line var height = layerConfig.lineHeight; var width = Math.round(layerConfig.width - (range.start.column * layerConfig.characterWidth)); @@ -168,9 +162,6 @@ var Marker = function(parentEl) { }; this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig) { - // TODO: Add this back. - //var range = range.toScreenRange(this.doc); - var height = layerConfig.lineHeight; var width = Math.round((range.end.column - range.start.column) * layerConfig.characterWidth); var top = (range.start.row - layerConfig.firstRow) * layerConfig.lineHeight; diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index 371cd7e6..5c26a4f2 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -148,18 +148,19 @@ var Text = function(parentEl) { } }; - this.updateLines = function(layerConfig, firstRow, lastRow) { + this.updateLines = function(config, firstRow, lastRow) { + console.log("layer.text.updateLines", firstRow, lastRow); this.$computeTabString(); - this.config = layerConfig; + this.config = config; - var first = Math.max(firstRow, layerConfig.firstRow); - var last = Math.min(lastRow, layerConfig.lastRow); + var first = Math.max(firstRow, config.firstRow); + var last = Math.min(lastRow, config.lastRow); var lineElements = this.element.childNodes; var _self = this; this.tokenizer.getTokens(first, last, function(tokens) { for ( var i = first; i <= last; i++) { - var lineElement = lineElements[i - layerConfig.firstRow]; + var lineElement = lineElements[i - config.firstRow]; if (!lineElement) continue; @@ -168,7 +169,8 @@ var Text = function(parentEl) { lineElement.innerHTML = html.join(""); // The height of the line might have changed if wrapped mode // is active. - lineElement.style.height = (layerConfig.wrapped[i].length + 1) * layerConfig.lineHeight + "px"; + lineElement.style.height = + _self.doc.getRowHeight(config, i) + "px"; } }); }; @@ -229,7 +231,7 @@ var Text = function(parentEl) { var lineEl = document.createElement("div"); lineEl.className = "ace_line"; var style = lineEl.style; - style.height = (config.wrapped[row].length + 1) * config.lineHeight + "px"; + style.height = _self.doc.getRowHeight(config, row) + "px"; style.width = config.width + "px"; var html = []; @@ -242,6 +244,7 @@ var Text = function(parentEl) { }; this.update = function(config) { + console.log("layer.text.update()"); this.$computeTabString(); this.config = config; @@ -270,8 +273,6 @@ var Text = function(parentEl) { }; this.$renderLine = function(stringBuilder, row, tokens) { - stringBuilder.push("
    "); - var wrappedInfo = this.config.wrapped[row]; // if (this.$showInvisibles) { // var self = this; // var spaceRe = /[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]+/g; @@ -302,25 +303,31 @@ var Text = function(parentEl) { } } - var chars = 0; - var wrapSection = 0; - var maxChars = wrappedInfo[wrapSection] || 9999; - var value; + var splits = this.doc.getRowSplitData(row); + var chars = 0, split = 0, splitChars; + + if (!splits || splits.length == 0) { + splitChars = Number.MAX_VALUE; + } else { + splitChars = splits[0]; + } + + stringBuilder.push("
    "); for (var i = 0; i < tokens.length; i++) { var token = tokens[i]; + var value = token.value; - if (chars + token.value.length < maxChars) { - addToken(token, token.value); - chars += token.value.length; + if (chars + value.length < splitChars) { + addToken(token, value); + chars += value.length; } else { - value = token.value; - while (chars + value.length >= maxChars) { - addToken(token, value.substring(0, maxChars - chars)); - value = value.substring(maxChars - chars); - chars = maxChars; + while (chars + value.length >= splitChars) { + addToken(token, value.substring(0, splitChars - chars)); + value = value.substring(splitChars - chars); + chars = splitChars; stringBuilder.push("
    "); - wrapSection ++; - maxChars = wrappedInfo[wrapSection] || 9999; + split ++; + splitChars = splits[split] || Number.MAX_VALUE; } if (value.length != 0) { chars += value.length; diff --git a/lib/ace/range.js b/lib/ace/range.js index 65775cb0..622ff59f 100644 --- a/lib/ace/range.js +++ b/lib/ace/range.js @@ -137,7 +137,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) { this.clone = function() { return Range.fromPoints(this.start, this.end); }; - + this.collapseRows = function() { if (this.end.column == 0) return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) @@ -146,9 +146,13 @@ var Range = function(startRow, startColumn, endRow, endColumn) { }; this.toScreenRange = function(doc) { + var screenPosStart = + doc.documentToScreenPosition(this.start.row, this.start.column); + var screenPosEnd = + doc.documentToScreenPosition(this.end.row, this.end.column); return new Range( - this.start.row, doc.documentToScreenColumn(this.start.row, this.start.column), - this.end.row, doc.documentToScreenColumn(this.end.row, this.end.column) + screenPosStart.row, screenPosStart.column, + screenPosEnd.row, screenPosEnd.column ); }; diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index f3552a21..ab66a443 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -82,7 +82,7 @@ var VirtualRenderer = function(container, theme) { this.$cursorLayer = new CursorLayer(this.content); this.layers = [ this.$markerLayer, textLayer, this.$cursorLayer ]; - + this.scrollBar = new ScrollBar(container); this.scrollBar.addEventListener("scroll", this.onScroll.bind(this)); @@ -118,10 +118,6 @@ var VirtualRenderer = function(container, theme) { }; (function() { - this.layerConfig = { - wrapped: [] - }; - this.showGutter = true; this.CHANGE_CURSOR = 1; @@ -140,30 +136,16 @@ var VirtualRenderer = function(container, theme) { this.doc = doc; this.$cursorLayer.setDocument(doc); this.$markerLayer.setDocument(doc); + this.$gutterLayer.setDocument(doc); this.$textLayer.setDocument(doc); this.$loop.schedule(this.CHANGE_FULL); }; - this.$updateWrappedLinesInfo = function(firstRow, lastRow) { - var WRAPSIZE = 12; - var wrappedInfo = this.layerConfig.wrapped; - var lines = this.lines; - for (var row = firstRow; row <= lastRow; row++) { - var col = 12; - wrappedInfo[row] = []; - while (col < lines[row].length) { - wrappedInfo[row].push(col); - col += 12; - } - } - }; - /** * Triggers partial update of the text layer */ this.updateLines = function(firstRow, lastRow) { - this.$updateWrappedLinesInfo(firstRow, lastRow); console.log("updateLines", firstRow, lastRow); if (lastRow === undefined) lastRow = Infinity; @@ -351,7 +333,7 @@ var VirtualRenderer = function(container, theme) { this.$renderChanges = function(changes) { if (!changes || !this.doc || !this.$tokenizer) return; - + // text, scrolling and resize changes can cause the view port size to change if (!this.layerConfig || changes & this.CHANGE_FULL || @@ -419,7 +401,7 @@ var VirtualRenderer = function(container, theme) { var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight)); var lastRow = Math.max(0, Math.min(this.lines.length, firstRow + lineCount) - 1); - var layerConfig = oop.mixin(this.layerConfig, { + var layerConfig = this.layerConfig = { width : longestLine, padding : this.$padding, firstRow : firstRow, @@ -429,11 +411,7 @@ var VirtualRenderer = function(container, theme) { minHeight : minHeight, offset : offset, height : this.$size.scrollerHeight - }); - - // Ensure that there is a wrapped array for all the rows in the current - // view port. - this.$updateWrappedLinesInfo(firstRow, lastRow); + }; for ( var i = 0; i < this.layers.length; i++) { var layer = this.layers[i]; @@ -593,84 +571,22 @@ var VirtualRenderer = function(container, theme) { var row = Math.floor((pageY + this.scrollTop - canvasPos.top) / this.lineHeight); - return this.layerConfig.wrappedPosToPos( - row, - col - // TODO: Figure out how to calculate tabs here... - //this.doc.screenToDocumentColumn(Math.max(0, Math.min(row, this.doc.getLength()-1)), col) - ); + return this.doc.screenToDocumentPosition(row, col); }; this.textToScreenCoordinates = function(row, column) { var canvasPos = this.scroller.getBoundingClientRect(); + var pos = this.doc.documentToScreenPosition(row, column); - var x = this.padding + Math.round(this.doc.documentToScreenColumn(row, column) * this.characterWidth); - var y = row * this.lineHeight; + + var x = this.padding + Math.round(pos.column * this.characterWidth); + var y = pos.row * this.lineHeight; return { pageX: canvasPos.left + x - this.getScrollLeft(), pageY: canvasPos.top + y - this.getScrollTop() } }; - - this.wrappedPosToPos = function(row, column) { - var linesCount = this.wrapped.length; - var realRow = 0; - while (realRow < linesCount && row >= this.wrapped[realRow].length + 1) { - row -= this.wrapped[realRow].length + 1; - realRow ++; - } - return { - row: realRow, - column: column + (realRow < linesCount ? this.wrapped[realRow][row - 1] || 0 : 0) - }; - }; - - this.posToWrappedPos = function(row, column) { - // TODO: Why can it happen, that row is higher then the current count - // of lines (note lines in doc, not only in wrapped!). Happens when - // the cursor is in the last line and the marker "ace_active_line" is - // painted. - if (row > this.wrapped.length - 1) { - row = this.wrapped.length - 1; - column = 99999; - } - - var rows = 0; - for (var i = 0; i < row; i++) { - rows += this.wrapped[i].length + 1; - } - - var col = column; - for (var s = 0; s < this.wrapped[row].length; s++) { - if (column > this.wrapped[row][s]) { - col = column - this.wrapped[row][s]; - rows ++; - } else { - break; - } - } - return { - row: rows, - column: col - }; - }; - - this.getPixelPosition = function(row, column) { - var pos = this.posToWrappedPos(row, column); - var cursorLeft = Math.round(pos.column * this.characterWidth); - var cursorTop = pos.row * this.lineHeight; - - return { - left : cursorLeft, - top : cursorTop - }; - }; - - // TODO: This should get passed in a different way to the cursorLayer! - this.layerConfig.getPixelPosition = this.getPixelPosition; - this.layerConfig.posToWrappedPos = this.posToWrappedPos; - this.layerConfig.wrappedPosToPos = this.wrappedPosToPos; this.visualizeFocus = function() { dom.addCssClass(this.container, "ace_focus"); From 609f0628033ecf1aeb99ff70f430b24b48ee4380 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Sat, 8 Jan 2011 23:01:34 +0100 Subject: [PATCH 04/59] Fix problems when scolling + wrapped lines --- lib/ace/document.js | 53 ++++++++++++++++++++++++++++++++----- lib/ace/layer/cursor.js | 7 ++--- lib/ace/layer/marker.js | 12 ++++++--- lib/ace/layer/text.js | 13 ++++++--- lib/ace/virtual_renderer.js | 17 +++++++++--- 5 files changed, 82 insertions(+), 20 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index 67b16daa..d16c769e 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -772,10 +772,14 @@ var Document = function(text, mode) { this.$useWrapMode = false; this.setUseWrapMode = function(useWrapMode) { var _self = this; + function computeWrapData(e) { var lines = _self.lines, wrapData = _self.$wrapData; var wrapLimit = _self.$wrapLimit; + // Remove lines that are no longer there. + wrapData.splice(lines.length, wrapData.length - lines.length); + if (!e.data.lastRow) { e.data.lastRow = _self.lines.length - 1; } @@ -857,6 +861,21 @@ var Document = function(text, mode) { return docColumn; }; + this.screenToDocumentRow = function(row) { + if (!this.$useWrapMode) { + return row; + } + + var wrapData = this.$wrapData, linesCount = this.lines.length; + var docRow = 0; + while (docRow < linesCount && row >= wrapData[docRow].length + 1) { + row -= wrapData[docRow].length + 1; + docRow ++; + } + + return docRow; + }; + this.screenToDocumentPosition = function(row, column) { if (!this.$useWrapMode) { return { @@ -903,7 +922,7 @@ var Document = function(text, mode) { return screenColumn; }; - this.documentToScreenPosition = function(row, column) { + this.documentToScreenRow = function(row) { if (!this.$useWrapMode) { return { row: row, @@ -919,19 +938,27 @@ var Document = function(text, mode) { for (row = 0; row < wrapData.length; row ++) { screenRow += wrapData[row].length + 1; } - return { - row: screenRow, - column: 0 - } + return screenRow; } for (var i = 0; i < row; i++) { screenRow += wrapData[i].length + 1; } + return screenRow; + } + + this.documentToScreenPosition = function(row, column) { + if (!this.$useWrapMode) { + return { + row: row, + column: this.documentToScreenColumn(row, column) + } + } + var screenRow = this.documentToScreenRow(row); var screenColumn = column; - var wrapRowData = wrapData[row]; - for (var split = 0; split < wrapRowData.length; split++) { + var wrapRowData = this.$wrapData[row]; + for (var split = 0; wrapRowData && split < wrapRowData.length; split++) { if (column > wrapRowData[split]) { screenColumn = column - wrapRowData[split]; screenRow ++; @@ -946,6 +973,18 @@ var Document = function(text, mode) { }; }; + this.getScreenLength = function() { + if (!this.$useWrapMode) { + return this.getLength(); + } + + var screenRows = 0; + for (var row = 0; row < this.$wrapData.length; row++) { + screenRows += this.$wrapData[row].length + 1; + } + return screenRows; + } + }).call(Document.prototype) exports.Document = Document; diff --git a/lib/ace/layer/cursor.js b/lib/ace/layer/cursor.js index 8fcbb1c1..f614ca89 100644 --- a/lib/ace/layer/cursor.js +++ b/lib/ace/layer/cursor.js @@ -100,7 +100,7 @@ var Cursor = function(parentEl) { }, 1000); }; - this.getPixelPosition = function() { + this.getPixelPosition = function(onScreen) { if (!this.config || !this.position) { return { left : 0, @@ -111,7 +111,8 @@ var Cursor = function(parentEl) { var pos = this.doc.documentToScreenPosition(this.position.row, this.position.column); var cursorLeft = Math.round(pos.column * this.config.characterWidth); - var cursorTop = pos.row * this.config.lineHeight; + var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) * + this.config.lineHeight; return { left : cursorLeft, @@ -125,7 +126,7 @@ var Cursor = function(parentEl) { this.config = config; - this.pixelPos = this.getPixelPosition(); + this.pixelPos = this.getPixelPosition(true); this.cursor.style.left = this.pixelPos.left + "px"; this.cursor.style.top = this.pixelPos.top + "px"; diff --git a/lib/ace/layer/marker.js b/lib/ace/layer/marker.js index 517f1775..2ef477ab 100644 --- a/lib/ace/layer/marker.js +++ b/lib/ace/layer/marker.js @@ -102,6 +102,10 @@ var Marker = function(parentEl) { this.element.innerHTML = html.join(""); }; + this.$getTop = function(row, layerConfig) { + return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight; + }; + this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) { // selection start var row = range.start.row; @@ -125,7 +129,7 @@ var Marker = function(parentEl) { // from selection start to the end of the line var height = layerConfig.lineHeight; var width = Math.round(layerConfig.width - (range.start.column * layerConfig.characterWidth)); - var top = (range.start.row - layerConfig.firstRow) * layerConfig.lineHeight; + var top = this.$getTop(range.start.row, layerConfig); var left = Math.round(range.start.column * layerConfig.characterWidth); stringBuilder.push( @@ -137,7 +141,7 @@ var Marker = function(parentEl) { ); // from start of the last line to the selection end - var top = (range.end.row - layerConfig.firstRow) * layerConfig.lineHeight; + var top = this.$getTop(range.start.end, layerConfig); var width = Math.round(range.end.column * layerConfig.characterWidth); stringBuilder.push( @@ -151,7 +155,7 @@ var Marker = function(parentEl) { var height = (range.end.row - range.start.row - 1) * layerConfig.lineHeight; if (height < 0) return; - var top = (range.start.row + 1 - layerConfig.firstRow) * layerConfig.lineHeight; + var top = this.$getTop(range.start.row + 1, layerConfig); stringBuilder.push( "
    Date: Sun, 9 Jan 2011 01:08:16 +0100 Subject: [PATCH 05/59] Fix small bug in layer/marker.js#drawMultiLineMarker --- lib/ace/layer/marker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/layer/marker.js b/lib/ace/layer/marker.js index 2ef477ab..452f1d23 100644 --- a/lib/ace/layer/marker.js +++ b/lib/ace/layer/marker.js @@ -141,7 +141,7 @@ var Marker = function(parentEl) { ); // from start of the last line to the selection end - var top = this.$getTop(range.start.end, layerConfig); + var top = this.$getTop(range.end.row, layerConfig); var width = Math.round(range.end.column * layerConfig.characterWidth); stringBuilder.push( From bc4c9c60602698ae4d96e999d5a407245c11c2d9 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Sun, 9 Jan 2011 01:28:03 +0100 Subject: [PATCH 06/59] move () on Selection. Add support for moveDown/Up when in wrapMode --- lib/ace/document.js | 6 +++++- lib/ace/editor.js | 30 ++---------------------------- lib/ace/selection.js | 36 ++++++++++++++++++++++++++---------- 3 files changed, 33 insertions(+), 39 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index d16c769e..197c7442 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -768,7 +768,7 @@ var Document = function(text, mode) { (function() { - this.$wrapLimit = 12; + this.$wrapLimit = 24; this.$useWrapMode = false; this.setUseWrapMode = function(useWrapMode) { var _self = this; @@ -894,6 +894,10 @@ var Document = function(text, mode) { var docColumn = column + (docRow < linesCount ? wrapData[docRow][row - 1] || 0 : 0); + if (this.lines[docRow]) { + docColumn = Math.min(docColumn, this.lines[docRow].length); + } + return { row: docRow, column: docColumn diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 1e7da684..dc62e46e 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -64,7 +64,7 @@ var Editor =function(renderer, doc) { return event.preventDefault(e); }); - var mouseTarget = renderer.getMouseEventTarget(); + var mouseTarget = 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)); @@ -368,13 +368,11 @@ var Editor =function(renderer, doc) { this.onMouseDoubleClick = function(e) { this.selection.selectWord(); this.$clickSelection = this.getSelectionRange(); - this.$updateDesiredColumn(); }; this.onMouseTripleClick = function(e) { this.selection.selectLine(); this.$clickSelection = this.getSelectionRange(); - this.$updateDesiredColumn(); }; this.onMouseWheel = function(e) { @@ -592,7 +590,7 @@ var Editor =function(renderer, doc) { if (this.selection.isEmpty()) this.selection.selectLeft(); - + this.moveCursorToPosition(this.doc.remove(this.getSelectionRange())); this.clearSelection(); }; @@ -633,7 +631,6 @@ var Editor =function(renderer, doc) { var range = this.doc.outdentRows(selection.getRange()); selection.setSelectionRange(range, selection.isBackwards()); - this.$updateDesiredColumn(); }; this.toggleCommentLines = function() { @@ -825,17 +822,14 @@ var Editor =function(renderer, doc) { this.clearSelection = function() { this.selection.clearSelection(); - this.$updateDesiredColumn(); }; this.moveCursorTo = function(row, column) { this.selection.moveCursorTo(row, column); - this.$updateDesiredColumn(); }; this.moveCursorToPosition = function(pos) { this.selection.moveCursorToPosition(pos); - this.$updateDesiredColumn(); }; @@ -854,35 +848,18 @@ var Editor =function(renderer, doc) { this.navigateTo = function(row, column) { this.clearSelection(); this.moveCursorTo(row, column); - this.$updateDesiredColumn(column); }; this.navigateUp = function() { this.selection.clearSelection(); this.selection.moveCursorBy(-1, 0); - - if (this.$desiredColumn) { - var cursor = this.getCursorPosition(); - var column = this.doc.screenToDocumentColumn(cursor.row, this.$desiredColumn); - this.selection.moveCursorTo(cursor.row, column); - } }; this.navigateDown = function() { this.selection.clearSelection(); this.selection.moveCursorBy(1, 0); - - if (this.$desiredColumn) { - var cursor = this.getCursorPosition(); - var column = this.doc.screenToDocumentColumn(cursor.row, this.$desiredColumn); - this.selection.moveCursorTo(cursor.row, column); - } }; - this.$updateDesiredColumn = function() { - var cursor = this.getCursorPosition(); - this.$desiredColumn = this.doc.documentToScreenColumn(cursor.row, cursor.column); - }; this.navigateLeft = function() { if (!this.selection.isEmpty()) { @@ -944,7 +921,6 @@ var Editor =function(renderer, doc) { this.$tryReplace(range, replacement); if (range !== null) this.selection.setSelectionRange(range); - this.$updateDesiredColumn(); }, this.replaceAll = function(replacement, options) { @@ -963,7 +939,6 @@ var Editor =function(renderer, doc) { this.$tryReplace(ranges[i], replacement); if (ranges[0] !== null) this.selection.setSelectionRange(ranges[0]); - this.$updateDesiredColumn(); }, this.$tryReplace = function(range, replacement) { @@ -1016,7 +991,6 @@ var Editor =function(renderer, doc) { var range = this.$search.find(this.doc); if (range) { this.gotoLine(range.end.row+1, range.end.column); - this.$updateDesiredColumn(); this.selection.setSelectionRange(range); } }; diff --git a/lib/ace/selection.js b/lib/ace/selection.js index eb326c97..535b7151 100644 --- a/lib/ace/selection.js +++ b/lib/ace/selection.js @@ -158,11 +158,20 @@ var Selection = function(doc) { this.setSelectionRange = function(range, reverse) { if (reverse) { this.setSelectionAnchor(range.end.row, range.end.column); - this.selectTo(range.start.row, range.start.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(); + }; + + this.$updateDesiredColumn = function() { + var cursor = this.getCursor(); + if (cursor) { + this.$desiredColumn = this.doc.documentToScreenPosition(cursor.row, cursor.column).column; + console.log("selection.$updateDesiredColumn", this.$desiredColumn); + } }; this.$moveSelection = function(mover) { @@ -241,7 +250,7 @@ var Selection = function(doc) { var column = cursor.column; var range = this.doc.getWordRange(cursor.row, column); this.setSelectionRange(range); - + /*this.setSelectionAnchor(cursor.row, start); this.$moveSelection(function() { this.moveCursorTo(cursor.row, end); @@ -265,7 +274,7 @@ var Selection = function(doc) { this.moveCursorLeft = function() { if (this.selectionLead.column == 0) { - // cursor is a line start + // cursor is a line (start if (this.selectionLead.row > 0) { this.moveCursorTo(this.selectionLead.row - 1, this.doc .getLine(this.selectionLead.row - 1).length); @@ -309,7 +318,7 @@ var Selection = function(doc) { else if (leadingSpace[0].length >= column) this.moveCursorTo(row, 0); else - this.moveCursorTo(row, leadingSpace[0].length); + this.moveCursorTo(row, leadingSpace[0].length); }; this.moveCursorLineEnd = function() { @@ -380,7 +389,17 @@ var Selection = function(doc) { }; this.moveCursorBy = function(rows, chars) { - this.moveCursorTo(this.selectionLead.row + rows, this.selectionLead.column + chars); + if (this.doc.getUseWrapMode()) { + var pos = this.doc.documentToScreenPosition( + this.selectionLead.row, this.selectionLead.column); + pos = this.doc.screenToDocumentPosition( + pos.row + rows, (this.$desiredColumn || pos.column)); + this.moveCursorTo(pos.row, pos.column + chars, chars == 0); + } else { + this.moveCursorTo(this.selectionLead.row + rows, + (this.$desiredColumn || this.selectionLead.column) + chars, + chars == 0); + } }; @@ -388,20 +407,17 @@ var Selection = function(doc) { this.moveCursorTo(position.row, position.column); }; - this.moveCursorTo = function(row, column) { + this.moveCursorTo = function(row, column, preventUpdateDesiredColumn) { var cursor = this.$clipPositionToDocument(row, column); // only dispatch change if the cursor actually changed if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) { this.selectionLead = cursor; + !preventUpdateDesiredColumn && this.$updateDesiredColumn(column); this._dispatchEvent("changeCursor", { data: this.getCursor() }); } }; - this.moveCursorUp = function() { - this.moveCursorBy(-1, 0); - }; - this.$clipPositionToDocument = function(row, column) { var pos = {}; From a3ff06a9e308924059951dc48b9532443fd66841 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Sun, 9 Jan 2011 01:40:43 +0100 Subject: [PATCH 07/59] In wrapMode, document.screenWidth = doc.. Fix typo --- lib/ace/document.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index 197c7442..5610ac35 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -294,7 +294,7 @@ var Document = function(text, mode) { this.getScreenWidth = function() { this.$computeWidth(); - return this.screenWith; + return this.screenWidth; }; this.$computeWidth = function() { @@ -317,7 +317,12 @@ var Document = function(text, mode) { longestScreenLine = Math.max(longestScreenLine, len); } this.width = longestLine; - this.screenWith = longestScreenLine; + + if (this.$useWrapMode) { + this.screenWidth = this.$wrapLimit; + } else { + this.screenWidth = longestScreenLine; + } } }; From 8b6ba9f702bcf8b4ddd10a71f9ce0f2245db72c3 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Sun, 9 Jan 2011 11:18:03 +0100 Subject: [PATCH 08/59] Add LoreIpsum TextDocument in editor.html. Fix bug in Document.documentToScreenRow() and set Document.wrapLimit to 80. --- demo/demo_startup.js | 11 ++++++++++- editor.html | 45 ++++++++++++++++++++++++++++---------------- lib/ace/document.js | 7 ++----- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/demo/demo_startup.js b/demo/demo_startup.js index dcc9f42a..c754b1ad 100644 --- a/demo/demo_startup.js +++ b/demo/demo_startup.js @@ -57,8 +57,17 @@ exports.launch = function(env) { var docs = {}; + // Make the lorem ipsum text a little bit longer. + var loreIpsum = document.getElementById("plaintext").innerHTML; + for (var i = 0; i < 5; i++) { + loreIpsum += loreIpsum; + } + docs.plain = new Document(loreIpsum); + docs.plain.setUseWrapMode(true); + docs.plain.setMode(new TextMode()); + docs.plain.setUndoManager(new UndoManager()); + docs.js = new Document(document.getElementById("jstext").innerHTML); - docs.js.setUseWrapMode(true); docs.js.setMode(new JavaScriptMode()); docs.js.setUndoManager(new UndoManager()); diff --git a/editor.html b/editor.html index a6b28321..bf35fb44 100644 --- a/editor.html +++ b/editor.html @@ -6,14 +6,14 @@ Editor - +