This commit is contained in:
Joe Walker 2011-01-04 15:10:14 +00:00
commit 8cf2c04047
55 changed files with 79 additions and 8292 deletions

3
.gitmodules vendored
View file

@ -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

View file

@ -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);
});
});
});

View file

@ -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;
}
</style>
</head>
@ -177,31 +191,10 @@ echo $output;
?></script>
<input id="cockpitInput" type="text"/>
<input id="cockpitInput" type="text"/>
<script>
require = {
//urlArgs: "bust=" + (new Date()).getTime()
};
</script>
<script src="demo/require.js" type="text/javascript" charset="utf-8"></script>
<script src="demo/boot.js" type="text/javascript"></script>
<script>
setupPlugins({
pluginDirs: {
"../demo": {
singleFiles: ["demo_startup"]
}
}
}, 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);
});
});
</script>
<script src="demo/require.js" type="text/javascript" charset="utf-8"></script>
<script src="demo/boot.js" type="text/javascript"></script>
</body>
</html>
</html>

File diff suppressed because it is too large Load diff

View file

@ -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);
}
});
};
*/
});

View file

@ -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;
});

View file

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

View file

@ -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) {
});

View file

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

View file

@ -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 = '<span class="cptPrompt">&gt;</span> ';
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 += ' &nbsp;&#x21E5; ' + (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 += '<span class=' + scores[i].toString() + '>';
lastStatus = scores[i];
}
completion += this.element.value[i];
i++;
if (i === this.element.value.length) {
completion += '</span>';
break;
}
if (lastStatus !== scores[i]) {
completion += '</span>';
}
}
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;
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 669 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View file

@ -1,39 +0,0 @@
.cptRowIn {
display: box; display: -moz-box; display: -webkit-box;
box-orient: horizontal; -moz-box-orient: horizontal; -webkit-box-orient: horizontal;
box-align: center; -moz-box-align: center; -webkit-box-align: center;
color: #333;
background-color: #EEE;
width: 100%;
font-family: consolas, courier, monospace;
}
.cptRowIn > * { padding-left: 2px; padding-right: 2px; }
.cptRowIn > img { cursor: pointer; }
.cptHover { display: none; }
.cptRowIn:hover > .cptHover { display: block; }
.cptRowIn:hover > .cptHover.cptHidden { display: none; }
.cptOutTyped {
box-flex: 1; -moz-box-flex: 1; -webkit-box-flex: 1;
font-weight: bold; color: #000; font-size: 120%;
}
.cptRowOutput { padding-left: 10px; line-height: 1.2em; }
.cptRowOutput strong,
.cptRowOutput b,
.cptRowOutput th,
.cptRowOutput h1,
.cptRowOutput h2,
.cptRowOutput h3 { color: #000; }
.cptRowOutput a { font-weight: bold; color: #666; text-decoration: none; }
.cptRowOutput a: hover { text-decoration: underline; cursor: pointer; }
.cptRowOutput input[type=password],
.cptRowOutput input[type=text],
.cptRowOutput textarea {
color: #000; font-size: 120%;
background: transparent; padding: 3px;
border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;
}
.cptRowOutput table,
.cptRowOutput td,
.cptRowOutput th { border: 0; padding: 0 2px; }
.cptRowOutput .right { text-align: right; }

View file

@ -1,28 +0,0 @@
<div class=cptRow>
<!-- The div for the input (i.e. what was typed) -->
<div class="cptRowIn" save="${rowin}"
onclick="${copyToInput}"
ondblclick="${executeRequest}">
<!-- What the user actually typed -->
<div class="cptGt">&gt; </div>
<div class="cptOutTyped">${request.typed}</div>
<!-- The extra details that appear on hover -->
<div class=cptHover save="${duration}"></div>
<img class=cptHover onclick="${hideOutput}" save="${hide}"
alt="Hide command output" _src="${imagePath}/minus.png"/>
<img class="cptHover cptHidden" onclick="${showOutput}" save="${show}"
alt="Show command output" _src="${imagePath}/plus.png"/>
<img class=cptHover onclick="${remove}"
alt="Remove this command from the history" _src="${imagePath}/closer.png"/>
</div>
<!-- The div for the command output -->
<div class="cptRowOut" save="${rowout}">
<div class="cptRowOutput" save="${output}"></div>
<img _src="${imagePath}/throbber.gif" save="${throb}"/>
</div>
</div>

View file

@ -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;
});

View file

@ -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);
};
});

View file

@ -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.
* <p>Future requirements could include:
* <ul>
* <li>Multiple command lines
* <li>The ability to recall key presses (i.e. requests with no output) which
* will likely be needed for macro recording or similar
* <li>The ability to store the command history either on the server or in the
* browser local storage.
* </ul>
* <p>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):
* <pre>
* var request = new Request({
* command: command,
* args: args,
* typed: typed
* });
* </pre>
* @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:
* <pre>request.error = true; request.done(output);</pre>
*/
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;
});

View file

@ -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);
};
});

View file

@ -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('<h2>Welcome to Skywriter - Code in the Cloud</h2><ul>' +
'<li><a href="http://labs.mozilla.com/projects/skywriter" target="_blank">Home Page</a></li>' +
'<li><a href="https://wiki.mozilla.org/Labs/Skywriter" target="_blank">Wiki</a></li>' +
'<li><a href="https://wiki.mozilla.org/Labs/Skywriter/UserGuide" target="_blank">User Guide</a></li>' +
'<li><a href="https://wiki.mozilla.org/Labs/Skywriter/Tips" target="_blank">Tips and Tricks</a></li>' +
'<li><a href="https://wiki.mozilla.org/Labs/Skywriter/FAQ" target="_blank">FAQ</a></li>' +
'<li><a href="https://wiki.mozilla.org/Labs/Skywriter/DeveloperGuide" target="_blank">Developers Guide</a></li>' +
'</ul>');
}
if (command) {
// We must be looking at sub-commands
output.push('<h2>Sub-Commands of ' + command.name + '</h2>');
output.push('<p>' + command.description + '</p>');
}
else if (args.search) {
if (args.search == 'hidden') { // sneaky, sneaky.
args.search = '';
showHidden = true;
}
output.push('<h2>Commands starting with \'' + args.search + '\':</h2>');
}
else {
output.push('<h2>Available Commands:</h2>');
}
var commandNames = canon.getCommandNames();
commandNames.sort();
output.push('<table>');
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('<tr>');
output.push('<th class="right">' + command.name + '</th>');
output.push('<td>' + command.description + '</td>');
output.push('</tr>');
}
output.push('</table>');
if (!args.search) {
output.push('For more information, see the <a href="https://wiki.mozilla.org/Labs/Skywriter">Skywriter Wiki</a>.');
}
}
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 = '<b>Error: ' + e.message + '</b>';
}
var msg = '';
var type = '';
var x;
if (checks.isFunction(result)) {
// converts the function to a well formated string
msg = (result + '').replace(/\n/g, '<br>').replace(/ /g, '&#160');
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 += '<b>' + items[x].name + '</b>: ' + items[x].value + '<br>';
}
} else {
msg = result;
type = typeof result;
}
request.done('Result for eval <b>\'' + javascript + '\'</b>' +
' (type: '+ type+'): <br><br>'+ 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);
};
});

View file

@ -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('<table>');
var count = 1;
history.requests.forEach(function(request) {
output.push('<tr>');
output.push('<th>' + count + '</th>');
output.push('<td>' + request.typed + '</td>');
output.push('</tr>');
count++;
});
output.push('</table>');
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;
};
});

View file

@ -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 += '<a class="setting" href="' + url +
'" title="View external documentation on setting: ' +
setting.name +
'" target="_blank">' +
setting.name +
'</a> = ' +
setting.value +
'<br/>';
});
} else {
// set with only a setting, shows the value for that setting
if (args.value === undefined) {
html = '<strong>' + setting.name + '</strong> = ' +
setting.get();
} else {
// Actually change the setting
args.setting.set(args.value);
html = 'Setting: <strong>' + args.setting.name + '</strong> = ' +
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 <strong>' +
args.setting + '</strong>.');
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);
};
});

View file

@ -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;
}
});
}
});

View file

@ -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 <fabian AT ajax DOT org>
*
* 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 <tt>include</tt>
*/
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;
};
});

View file

@ -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 <x if="${...}">
* @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 <x foreach="param in ${array}"> and the special case of
* <loop foreach="param in ${array}">
* @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 <loop> 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:
* <ul>
* <li>property('a.b', { a: { b: 99 }}); // returns 99
* <li>property('a', { a: { b: 99 }}); // returns { b: 99 }
* <li>property('a', { a: { b: 99 }}, 42); // returns 99 and alters the
* input data to be { a: { b: 42 }}
* </ul>
* @param path An array of strings indicating the path through the data, or
* a string to be cut into an array using <tt>split('.')</tt>
* @param data An object to look in for the <tt>path</tt> 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 <tt>path</tt> before any
* <tt>newValue</tt> 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 <tt>env</tt> 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;
});

View file

@ -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 <fabian AT ajax DOT org>
*
* 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;
}
});
}
};
});

View file

@ -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 <fabian AT ajax DOT org>
*
* 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<listeners.length; i++) {
listeners[i](e);
}
};
EventEmitter.on =
EventEmitter.addEventListener = function(eventName, callback) {
this._eventRegistry = this._eventRegistry || {};
var listeners = this._eventRegistry[eventName];
if (!listeners) {
var listeners = this._eventRegistry[eventName] = [];
}
if (listeners.indexOf(callback) == -1) {
listeners.push(callback);
}
};
EventEmitter.removeEventListener = function(eventName, callback) {
this._eventRegistry = this._eventRegistry || {};
var listeners = this._eventRegistry[eventName];
if (!listeners) {
return;
}
var index = listeners.indexOf(callback);
if (index !== -1) {
listeners.splice(index, 1);
}
};
exports.EventEmitter = EventEmitter;
});

View file

@ -1,164 +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) {
/**
* Array detector.
* Firefox 3.5 and Safari 4 have this already. Chrome 4 however ...
* Note to Dojo - your isArray is still broken: instanceof doesn't work with
* Arrays taken from a different frame/window.
*/
if (!Array.isArray) {
Array.isArray = function(data) {
return data && Object.prototype.toString.call(data) === "[object Array]";
};
}
// from MDC
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(searchElement /*, fromIndex */)
{
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 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;
});

View file

@ -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);
}
});
};
*/
});

View file

@ -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();
});

View file

@ -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_)<number>
// 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);
};
});

View file

@ -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');
};
});

View file

@ -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 <fabian AT ajax DOT org>
*
* 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<arr.length; i++) {
map[arr[i]] = 1;
}
return map;
};
/**
* splice out of 'array' anything that === 'value'
*/
exports.arrayRemove = function(array, value) {
for (var i = 0; i <= array.length; i++) {
if (value === array[i]) {
array.splice(i, 1);
}
}
};
exports.escapeRegExp = function(str) {
return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
};
exports.deferredCall = function(fcn) {
var timer = null;
var callback = function() {
timer = null;
fcn();
};
return {
schedule: function() {
if (!timer) {
timer = setTimeout(callback, 0);
}
},
call: function() {
this.cancel();
fcn();
},
cancel: function() {
clearTimeout(timer);
timer = null;
}
};
};
});

View file

@ -1,58 +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 <fabian AT ajax DOT org>
*
* 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);
};
});

View file

@ -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();
});

View file

@ -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 <tt>this</tt> 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;
});

View file

@ -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);
}
};
});

View file

@ -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));
};
});

View file

@ -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 <code>key</code> 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.
* <p>Usage:
* <pre>
* // 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');
* </pre>
* @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.
* <p>Example usage:
* <pre>
* 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
* });
* </pre>
* @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;
});

View file

@ -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);
};
});

View file

@ -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 <loic@dachary.org> (2008)
// Johan Euphrosine <proppy@aminche.com> (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.
* <strike>Feature</strike> 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.<anonymous>\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++;
}
}
};
});

View file

@ -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 ]');
};
});

View file

@ -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]";
};
});

View file

@ -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 <tt>value</tt> 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 <tt>str</tt> 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.
* <p>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);
};
});

View file

@ -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.
*
* <p>In addition to these types, Jetpack also accepts range, member, password
* that we are thinking of adding.
*
* <p>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);
};
});

View file

@ -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);
};
});

View file

@ -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);
};
});

View file

@ -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 <fabian AT ajax DOT org>
*
* 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'];
}
};
});

1
support/cockpit Submodule

@ -0,0 +1 @@
Subproject commit 47df3c340244b15c272ed87b17cd87659f4bcd0c