diff --git a/plugins/pilot/lib/commands/basic.js b/plugins/pilot/lib/commands/basic.js
new file mode 100644
index 00000000..ae2bc01c
--- /dev/null
+++ b/plugins/pilot/lib/commands/basic.js
@@ -0,0 +1,269 @@
+/* ***** 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 util = require('pilot/util');
+
+/**
+ * '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 = catalog.getExtensionByKey('command', args.search);
+ if (command && command.pointer) {
+ // caught a real command
+ output.push(command.description);
+ } else {
+ var showHidden = false;
+
+ if (!args.search) {
+ output.push('
Welcome to Skywriter - Code in the Cloud
");
+ }
+
+ if (command) {
+ // We must be looking at sub-commands
+ output.push('Sub-Commands of ' + command.name + '
');
+ output.push('' + command.description + '
');
+ } else if (args.search) {
+ if (args.search == 'hidden') { // sneaky, sneaky.
+ args.search = '';
+ showHidden = true;
+ }
+ output.push('Commands starting with \'' + args.search + '\':
');
+ } else {
+ output.push('Available Commands:
');
+ }
+
+ var toBeSorted = [];
+ catalog.getExtensions('command').forEach(function(command) {
+ toBeSorted.push(command.name);
+ });
+
+ var sorted = toBeSorted.sort();
+
+ output.push('');
+ for (var i = 0; i < sorted.length; i++) {
+ command = catalog.getExtensionByKey('command', sorted[i]);
+ if (!command) {
+ console.error('Huh? command ', command.name, ' cannot be looked up by name');
+ continue;
+ }
+
+ if (!showHidden && command.hidden) {
+ continue;
+ }
+ if (command.description === undefined) {
+ // Ignore editor actions
+ continue;
+ }
+ if (args.search && command.name.indexOf(args.search) !== 0) {
+ // Filtered out by the user
+ continue;
+ }
+ if (!args.search && command.name.indexOf(' ') != -1) {
+ // sub command
+ continue;
+ }
+ if (command && command.name == args.search) {
+ // sub command, and we've already given that help
+ continue;
+ }
+
+ // todo add back a column with parameter information, perhaps?
+
+ output.push('');
+ output.push('| ' + command.name + ' | ');
+ output.push('' + command.description + ' | ');
+ output.push('
');
+ }
+ output.push('
');
+
+ if (!args.search) {
+ output.push("For more information, see the Skywriter Wiki.");
+ }
+ }
+
+ request.done(output.join(''));
+ }
+};
+
+/**
+ * 'eval' command
+ */
+var evalCommandSpec = {
+ name: "eval",
+ params: [
+ {
+ name: "javascript",
+ type: "text",
+ description: "The JavaScript to evaluate"
+ }
+ ],
+ description: "evals given js code and show the result",
+ hidden: true,
+ exec: function(env, args, request) {
+ var result;
+ var javascript = args.javascript;
+ try {
+ result = eval(javascript);
+ } catch (e) {
+ result = 'Error: ' + e.message + '';
+ }
+
+ var msg = '';
+ var type = '';
+ var x;
+
+ if (util.isFunction(result)) {
+ // converts the function to a well formated string
+ msg = (result + '').replace(/\n/g, '
').replace(/ /g, ' ');
+ type = 'function';
+ } else if (util.isObject(result)) {
+ if (Array.isArray(result)) {
+ type = 'array';
+ } else {
+ type = 'object';
+ }
+
+ var items = [];
+ var value;
+
+ for (x in result) {
+ if (result.hasOwnProperty(x)) {
+ if (util.isFunction(result[x])) {
+ value = '[function]';
+ } else if (util.isObject(result[x])) {
+ value = '[object]';
+ } else {
+ value = result[x];
+ }
+
+ items.push({name: x, value: value});
+ }
+ }
+
+ items.sort(function(a,b) {
+ return (a.name.toLowerCase() < b.name.toLowerCase()) ? -1 : 1;
+ });
+
+ for (x = 0; x < items.length; x++) {
+ msg += '' + items[x].name + ': ' + items[x].value + '
';
+ }
+
+ } else {
+ msg = result;
+ type = typeof result;
+ }
+
+ request.done('Result for eval "' + javascript + '"' +
+ ' (type: '+ type+'):
'+ msg);
+ }
+};
+
+/**
+ * 'version' command
+ */
+var versionCommandSpec = {
+ name: "version",
+ description: "show the Skywriter version",
+ hidden: true,
+ exec: function(env, args, request) {
+ var version = 'Skywriter ' + skywriter.versionNumber + ' (' +
+ skywriter.versionCodename + ')';
+ request.done(version);
+ }
+};
+
+/**
+ * 'skywriter' command
+ */
+var skywriterCommandSpec = {
+ name: "skywriter",
+ description: "has",
+ hidden: true,
+ exec: function(env, args, request) {
+ var index = Math.floor(Math.random() * messages.length);
+ request.done('Skywriter ' + messages[index]);
+ }
+};
+var messages = [
+ 'really wants you to trick it out in some way.',
+ 'is your Web editor.',
+ 'would love to be like Emacs on the Web.',
+ 'is written on the Web platform, so you can tweak it.'
+];
+
+
+var canon = require('pilot/canon');
+
+exports.startup = function(data, reason) {
+ canon.addCommand(helpCommandSpec);
+ canon.addCommand(evalCommandSpec);
+ // canon.addCommand(versionCommandSpec);
+ canon.addCommand(skywriterCommandSpec);
+};
+
+exports.shutdown = function(data, reason) {
+ canon.removeCommand(helpCommandSpec);
+ canon.removeCommand(evalCommandSpec);
+ // canon.removeCommand(versionCommandSpec);
+ canon.removeCommand(skywriterCommandSpec);
+};
+
+
+});
diff --git a/plugins/pilot/lib/commands/history.js b/plugins/pilot/lib/commands/history.js
new file mode 100644
index 00000000..39f99b3d
--- /dev/null
+++ b/plugins/pilot/lib/commands/history.js
@@ -0,0 +1,117 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Skywriter.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Skywriter Team (skywriter@mozilla.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define(function(require, exports, module) {
+
+
+/**
+ * CLI 'up'
+ * Decrement the 'current entry' pointer
+ */
+var historyPreviousCommandSpec = {
+ name: "historyPrevious",
+ predicates: { isCommandLine: true, isKeyUp: true },
+ key: "up",
+ exec: function(args, request) {
+ if (pointer > 0) {
+ pointer--;
+ }
+
+ var display = history.requests[pointer].typed;
+ env.commandLine.setInput(display);
+ }
+};
+
+/**
+ * CLI 'down'
+ * Increment the 'current entry' pointer
+ */
+var historyNextCommandSpec = {
+ name: "historyNext",
+ predicates: { isCommandLine: true, isKeyUp: true },
+ key: "down",
+ exec: function(args, request) {
+ if (pointer < history.requests.length) {
+ pointer++;
+ }
+
+ var display = (pointer === history.requests.length)
+ ? ''
+ : history.requests[pointer].typed;
+
+ env.commandLine.setInput(display);
+ }
+};
+
+/**
+ * 'history' command
+ */
+var historyCommandSpec = {
+ name: "history",
+ description: "Show history of the commands",
+ exec: function(args, request) {
+ var output = [];
+ output.push('');
+ var count = 1;
+
+ history.requests.forEach(function(request) {
+ output.push('');
+ output.push('| ' + count + ' | ');
+ output.push('' + request.typed + ' | ');
+ output.push('
');
+ count++;
+ });
+ output.push('
');
+
+ 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;
+};
+
+
+});