Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Feature/consoleactivity #1381

Merged
merged 6 commits into from

2 participants

@mattpardee

DO NOT MERGE. WIP FOR REVIEW ONLY. ALSO TOP SECRET. WHY ELSE WOULD I BE USING CAPS LOCK?

Feature to show the status of commands sent to the server via the CLI

@mattpardee mattpardee commented on the diff
client/ext/console/console.js
((5 lines not shown))
var css = require("text!ext/console/console.css");
var markup = require("text!ext/console/console.xml");
var theme = require("text!ext/console/themes/arthur.css");
+var InputHistory = require("ext/console/input_history");

lowercase this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@mattpardee mattpardee commented on the diff
client/ext/console/console.js
((70 lines not shown))
module.exports = ext.register("ext/console/console", {
name : "Console",
- dev : "Ajax.org",
+ dev : "Cloud9 IDE, Inc.",

Change this back to Ajax.org

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@javruben javruben merged commit 32ff859 into master
@javruben javruben commented on the diff
client/ext/console/console.js
@@ -1,11 +1,7 @@
/**
* Console for the Cloud9 IDE
*
- * The console plugin takes care of rendering a CLI at the bottom of the IDE and
- * of sending user input and parsing and outputting stdout in the
- * console.
- *
- * @copyright 2011, Ajax.org B.V.
+ * @copyright 2012, Cloud9 IDE, Inc.
@javruben Owner
javruben added a note

Change this back to Ajax.org

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 20, 2012
  1. @mattpardee
Commits on Apr 27, 2012
  1. @mattpardee

    Commit uno

    mattpardee authored
Commits on Apr 28, 2012
  1. @mattpardee

    Added "cancel" button state

    mattpardee authored
Commits on May 1, 2012
  1. @mattpardee

    node-start handling

    mattpardee authored
  2. @mattpardee

    Fixed merge

    mattpardee authored
  3. @mattpardee

    Minor fixes

    mattpardee authored
This page is out of date. Refresh to see the latest.
View
5 client/core/ext.js
@@ -258,7 +258,10 @@ module.exports = ext = {
return;
if (command.msg)
- c9console.write([command.msg]);
+ c9console.write([command.msg], data);
+ else
+ c9console.write('"' + cmd + '" command executed', data);
+ c9console.commandCompleted(data.tracer_id);
var res = commands.exec(cmd, null, data);
return res === undefined ? false : res;
View
2  client/core/settings.js
@@ -105,7 +105,7 @@ module.exports = {
$loadsettings : function(cb){
var _self = require('core/settings');
-
+
if (cloud9config.debug) {
cb({model : _self.model, ext : _self});
}
View
54 client/ext/console/console.css
@@ -4,10 +4,28 @@
.console_text div {
padding: 2px 10px;
}
+.console_text.feedback div {
+ padding-left: 31px;
+}
+.console_text.feedback .output_section {
+ padding: 10px 0 10px 2px;
+ border-bottom: 1px solid #444;
+ overflow: hidden;
+}
+
+.console_text.feedback .output_section.collapsed:hover,
+.console_text.feedback .output_section.collapsed.quit_proc:hover {
+ background: #38393a;
+}
+
+/** Deprecated **/
.cli_divider {
display: block;
border-top: 1px solid #444;
- margin: 6px 0 6px 0;
+ margin: 6px 5px 6px 30px;
+}
+.console_text.feedback div.prompt_spacer {
+ padding-top: 5px;
}
.console_text a:link, .console_text a:hover, .console_text a:active {
color: #86C2F6;
@@ -15,5 +33,39 @@
.console_text a:visited {
color: #909090;
}
+.console_text.feedback .prompt_spinner {
+ background: url(/static/ext/main/style/images/console_spinner_proc.gif) no-repeat 0 0;
+ display: inline;
+ width: 21px;
+ height: 14px;
+ padding: 4px 22px 4px 4px;
+ margin-left: 3px;
+}
+.console_text.feedback .output_section.quit_proc {
+ background-color: #372a2a;
+ box-shadow: inset 0px 0px 0px 1px #372a2a, inset 6px 0px 0px 0px #b0423f;
+}
+.console_text.feedback .output_section.loading.has_pid:hover .prompt_spinner {
+ background: url(/static/ext/main/style/images/console-action-cancel.png) no-repeat 0 0;
+}
+.console_text.feedback .output_section.loading.has_pid:hover .prompt_spinner:active {
+ background: url(/static/ext/main/style/images/console-action-cancel.png) no-repeat 0 -22px;
+}
+.console_text.feedback div.loaded .prompt_spinner {
+ background: url(/static/ext/main/style/images/cli-block-expand.png) no-repeat 1px 1px;
+}
+
+.console_text.feedback div.loaded .prompt_spinner:hover {
+ background: url(/static/ext/main/style/images/cli-block-expand.png) no-repeat -23px 1px;
+}
+
+.console_text.feedback div.loaded.collapsed .prompt_spinner {
+ background: url(/static/ext/main/style/images/cli-block-expand.png) no-repeat -48px 1px
+}
+
+.console_text.feedback div.loaded.collapsed .prompt_spinner:hover {
+ background: url(/static/ext/main/style/images/cli-block-expand.png) no-repeat -73px 1px
+}
+
.cmd_msg > span { float: left; }
.cmd_msg > span > span { margin:0 0 0 25px; }
View
451 client/ext/console/console.js
@@ -1,11 +1,7 @@
/**
* Console for the Cloud9 IDE
*
- * The console plugin takes care of rendering a CLI at the bottom of the IDE and
- * of sending user input and parsing and outputting stdout in the
- * console.
- *
- * @copyright 2011, Ajax.org B.V.
+ * @copyright 2012, Cloud9 IDE, Inc.
@javruben Owner
javruben added a note

Change this back to Ajax.org

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
* @license GPLv3 <http://www.gnu.org/licenses/gpl.txt>
* @contributor Sergi Mansilla <sergi AT c9 DOT io>
*/
@@ -19,83 +15,36 @@ var commands = require("ext/commands/commands");
var ext = require("core/ext");
var settings = require("core/settings");
var Logger = require("ext/console/logger");
+var code = require("ext/code/code");
var css = require("text!ext/console/console.css");
var markup = require("text!ext/console/console.xml");
var theme = require("text!ext/console/themes/arthur.css");
+var InputHistory = require("ext/console/input_history");

lowercase this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
// Some constants used throughout the plugin
var RE_band = /^\s*!/;
var KEY_TAB = 9, KEY_CR = 13, KEY_UP = 38, KEY_ESC = 27, KEY_DOWN = 40;
var actionCodes = [KEY_TAB, KEY_CR, KEY_UP, KEY_ESC, KEY_DOWN];
-// Executes a command (presumably coming from the CLI).
-var execAction = function(cmd, data) {
- ide.dispatchEvent("track_action", {
- type: "console",
- cmd: cmd,
- argv: data.argv
- });
-
- if (ext.execCommand(cmd, data) !== false) {
- var commandEvt = "consolecommand." + cmd;
- var consoleEvt = "consolecommand";
- var commandEvResult = ide.dispatchEvent(commandEvt, { data: data });
- var consoleEvResult = ide.dispatchEvent(consoleEvt, { data: data });
-
- if (commandEvResult !== false && consoleEvResult !== false) {
- if (!ide.onLine)
- module.exports.write("Cannot execute command. You are currently offline.");
- else
- ide.send(data);
- }
- else {
- // If any of the `consolecommand` events returns false, it means
- // that we don't want the console to show up.
- return false;
- }
- }
- return true;
-};
-
-// This object is a simple FIFO queue that keeps track of the list of commands
-// introduced by the user at any given time and allows the console to go back and forward.
-var cmdHistory = {
- _history: [""],
- _index: 0,
-
- push: function(cmd) {
- this._history.push(cmd);
- this._index = this.length();
- },
- length: function() {
- return this._history.length;
- },
- getNext: function() {
- this._index += 1;
- var cmd = this._history[this._index] || "";
- this._index = Math.min(this.length(), this._index);
-
- return cmd;
- },
- getPrev: function() {
- this._index = Math.max(0, this._index - 1);
- return this._history[this._index];
- }
-};
-
module.exports = ext.register("ext/console/console", {
name : "Console",
- dev : "Ajax.org",
+ dev : "Cloud9 IDE, Inc.",

Change this back to Ajax.org

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
type : ext.GENERAL,
alone : true,
markup : markup,
css : css + theme,
height : 200,
hidden : true,
+
+ inputHistory : new InputHistory(),
+
+ command_id_tracer : 1,
+ tracerToPidMap : {},
+ pidToTracerMap : {},
hiddenInput : true,
-
+
nodes : [],
-
+
minHeight : 150,
maxHeight: window.innerHeight - 70,
@@ -106,57 +55,57 @@ module.exports = ext.register("ext/console/console", {
excludeParent : true,
keyEvents: {},
- messages: {
- cd: function(message) {
+ onMessageMethods: {
+ cd: function(message, outputElDetails) {
var res = message.body;
if (res.cwd) {
this.$cwd = res.cwd.replace(ide.workspaceDir, "/workspace");
- this.write("Working directory changed.");
+ Logger.logNodeStream("Working directory changed", null, outputElDetails, ide);
}
},
- error: function(message) {
- Logger.log(message.body);
- Logger.log("", "divider");
+ error: function(message, outputElDetails) {
+ Logger.logNodeStream(message.body, null, outputElDetails, ide);
},
- /**
- * Info does the same as error in this case
- * but it's here for the future, we might want to distinguise these
- * on colors or something...
- */
- info: function (message) {
- Logger.log(message.body);
- Logger.log("", "divider");
+ info: function (message, outputElDetails) {
+ Logger.logNodeStream(message.body, null, outputElDetails, ide);
},
- __default__: function(message) {
+ __default__: function(message, outputElDetails) {
var res = message.body;
if (res) {
- res.out && Logger.logNodeStream(res.out, null, null, ide);
- res.err && Logger.logNodeStream(res.err, null, null, ide);
- res.code && Logger.log("", "divider"); // End of command
+ res.out && Logger.logNodeStream(res.out, null, outputElDetails, ide);
+ res.err && Logger.logNodeStream(res.err, null, outputElDetails, ide);
}
}
},
- help: function() {
+ getLogStreamOutObject : function(tracer_id, idIsPid) {
+ if (idIsPid)
+ tracer_id = this.pidToTracerMap[tracer_id];
+ var id = "section" + tracer_id;
+ return {
+ $ext : document.getElementById("console_" + id),
+ id : id
+ };
+ },
+
+ help: function(data) {
var words = Object.keys(commands.commands);
var tabs = "\t\t\t\t";
- var _self = this;
Logger.logNodeStream(
words.sort()
.map(function(w) { return w + tabs + commands.commands[w].hint; })
.join("\n"),
- null, null, ide
+ null, this.getLogStreamOutObject(data.tracer_id), ide
);
},
clear: function() {
- if (txtConsole) {
+ if (txtConsole)
txtConsole.clear();
- }
return false;
},
@@ -187,12 +136,14 @@ module.exports = ext.register("ext/console/console", {
return this.$cwd && this.$cwd.replace("/workspace", ide.workspaceDir);
},
- write: function(lines) {
+ write: function(lines, data) {
if (typeof lines === "string")
lines = lines.split("\n");
- lines.forEach(function(line) { Logger.log(line, "log"); });
- Logger.log("", "divider");
+ var lsOutObject = this.getLogStreamOutObject(data.tracer_id);
+ lines.forEach(function(line) {
+ Logger.logNodeStream(line, null, lsOutObject, ide);
+ });
},
keyupHandler: function(e) {
@@ -205,6 +156,22 @@ module.exports = ext.register("ext/console/console", {
return this.commandTextHandler(e);
},
+ outputLogSection: function(line) {
+ var spinnerBtn = ['<div class="prompt_spinner"', ' id="spinner',
+ this.command_id_tracer,
+ '" onclick="return require(\'ext/console/console\').handleCliBlockAction(event)"></div>']
+ .join("");
+
+ var outputId = "console_section" + this.command_id_tracer;
+ Logger.log(line, "prompt", spinnerBtn,
+ '<div class="prompt_spacer"></div>', null, outputId);
+
+ var outputEl = document.getElementById(outputId);
+ apf.setStyleClass(outputEl, "loading");
+
+ return this.command_id_tracer;
+ },
+
evalCmd: function(line) {
parseLine || (parseLine = require("ext/console/parser"));
var argv = parseLine(line);
@@ -213,17 +180,23 @@ module.exports = ext.register("ext/console/console", {
// Replace any quotes in the command
argv[0] = argv[0].replace(/["'`]/g, "");
- cmdHistory.push(line);
- Logger.log(this.getPrompt(line), "prompt");
+ this.inputHistory.push(line);
+
+ this.outputLogSection(this.getPrompt(line));
+
tabConsole.set("console");
var showConsole = true;
var cmd = argv[0];
- predefinedCmds || (predefinedCmds = require("ext/console/output"));
+ if (!predefinedCmds)
+ predefinedCmds = require("ext/console/output");
var defCmd = predefinedCmds.getPredefinedOutput(argv);
if (defCmd !== "") {
- this.write(defCmd);
+ this.commandCompleted(this.command_id_tracer);
+ Logger.logNodeStream(defCmd, null,
+ this.getLogStreamOutObject(this.command_id_tracer), ide);
+ this.command_id_tracer++;
}
else {
if (cmd.trim().charAt(0) === "!") {
@@ -240,15 +213,57 @@ module.exports = ext.register("ext/console/console", {
// the requireshandling flag indicates that this message cannot
// be silently ignored by the server.
// An error event should be thrown if no plugin handles this message.
- requireshandling: true
+ requireshandling: true,
+ tracer_id: this.command_id_tracer
};
if (cmd.trim() === "npm")
data.version = settings.model.queryValue("auto/node-version/@version") || "auto";
- showConsole = execAction(cmd, data);
+ showConsole = this.execAction(cmd, data);
}
- if (showConsole === true) this.show();
+
+ if (showConsole === true)
+ this.show();
+ },
+
+ // Executes a command (presumably coming from the CLI).
+ execAction : function(cmd, data) {
+ ide.dispatchEvent("track_action", {
+ type: "console",
+ cmd: cmd,
+ argv: data.argv
+ });
+
+ if (ext.execCommand(cmd, data) !== false) {
+ var commandEvt = "consolecommand." + cmd;
+ var consoleEvt = "consolecommand";
+ var commandEvResult = ide.dispatchEvent(commandEvt, { data: data });
+ var consoleEvResult = ide.dispatchEvent(consoleEvt, { data: data });
+
+ if (commandEvResult !== false && consoleEvResult !== false) {
+ if (!ide.onLine) {
+ this.write("Cannot execute command. You are currently offline.", {
+ tracer_id : this.command_id_tracer
+ });
+ }
+ else {
+ data.extra = {
+ command_id : this.command_id_tracer
+ };
+
+ ide.send(data);
+ }
+ }
+ else {
+ // If any of the `consolecommand` events returns false, it means
+ // that we don't want the console to show up.
+ return false;
+ }
+ }
+
+ this.command_id_tracer++;
+ return true;
},
commandTextHandler: function(e) {
@@ -257,31 +272,129 @@ module.exports = ext.register("ext/console/console", {
this.keyEvents[code](e.currentTarget);
},
+ commandCompleted: function(id, idIsPid) {
+ if (idIsPid)
+ id = this.pidToTracerMap[id];
+ var spinnerElement = document.getElementById("spinner" + id);
+ if (spinnerElement) {
+ var pNode = spinnerElement.parentNode;
+ if (pNode.className.indexOf("quitting") !== -1) {
+ apf.setStyleClass(pNode, "quit_proc", ["quitting_proc"]);
+ Logger.logNodeStream("Process successfully quit", null,
+ this.getLogStreamOutObject(id), ide);
+ }
+
+ Firmin.animate(spinnerElement, {
+ opacity : 0,
+ delay : 0.2 },
+ 0.3, function() {
+ spinnerElement.setAttribute("style", "");
+ apf.setStyleClass(spinnerElement.parentNode, "loaded", ["loading"]);
+ setTimeout(function() {
+ spinnerElement.style.opacity = "1";
+ }, 100);
+ });
+ }
+ },
+
onMessage: function(e) {
- var message = e.message;
- if (!message.type)
+ if (!e.message.type)
return;
- if (message.type === "node-data")
- return Logger.logNodeStream(message.data, message.stream, true, ide);
- if (message.type === "node-exit")
- return Logger.log("", "divider", null, null, true);
+ var message = e.message;
+ var extra = message.extra;
+ if (!extra && message.body)
+ extra = message.body.extra;
+
+ switch(message.type) {
+ case "node-start":
+ var command_id = this.outputLogSection("Running Node Process");
+ this.tracerToPidMap[command_id] = message.pid;
+ this.pidToTracerMap[message.pid] = command_id;
+
+ var containerEl = this.getLogStreamOutObject(command_id).$ext;
+ containerEl.setAttribute("rel", command_id);
+ apf.setStyleClass(containerEl, "has_pid");
+
+ if (window.cloud9config.hosted) {
+ var url = location.protocol + "//" +
+ ide.workspaceId.replace(/(\/)*user(\/)*/, '').split("/").reverse().join(".") +
+ "." + location.host;
+ Logger.logNodeStream("Tip: you can access long running processes, like a server, at '" + url +
+ "'.\nImportant: in your scripts, use 'process.env.PORT' as port and '0.0.0.0' as host.\n ",
+ null, this.getLogStreamOutObject(message.pid, true), ide);
+ }
- if (message.type.match(/-data$/))
- return Logger.logNodeStream(message.data, message.stream, false, ide);
+ this.command_id_tracer++;
+ return;
+ case "node-data":
+ Logger.logNodeStream(message.data, message.stream,
+ this.getLogStreamOutObject(message.pid, true), ide);
+ return;
+ case "node-exit":
+ this.commandCompleted(message.pid, true);
+ return;
+ case "kill":
+ if (message.err) {
+ Logger.logNodeStream(message.err, null,
+ this.getLogStreamOutObject(extra.command_id), ide);
+ }
+ break;
+ default:
+ if (message.type.match(/-start$/)) {
+ var command_id = extra.command_id;
+
+ this.tracerToPidMap[command_id] = message.pid;
+ this.pidToTracerMap[message.pid] = command_id;
+
+ var containerEl = this.getLogStreamOutObject(command_id).$ext;
+ containerEl.setAttribute("rel", command_id);
+ apf.setStyleClass(containerEl, "has_pid");
+ return;
+ }
- if (message.type.match(/-exit$/))
- return Logger.log("", "divider", false);
+ if (message.type.match(/-data$/)) {
+ var type = "tracer";
+ var id = extra.command_id;
+ if (!command_id) {
+ type = "pid";
+ id = message.pid;
+ }
+
+ Logger.logNodeStream(message.data, message.stream,
+ this.getLogStreamOutObject(id, type === "pid"), ide);
+ return;
+ }
+
+ if (message.type.match(/-exit$/)) {
+ if (extra.command_id)
+ this.commandCompleted(extra.command_id);
+ else
+ this.commandCompleted(message.pid, true);
+ return;
+ }
+ break;
+ }
+
+ // If we get to this point and `extra` is available, it's a process that
+ // sends all its stdout _after_ it has quit. Thus, we complete it here
+ if (extra)
+ this.commandCompleted(extra.command_id);
if (message.type !== "result")
return;
- if (this.messages[message.subtype])
- this.messages[message.subtype].call(this, message);
+ var outputElDetails;
+ if (extra)
+ outputElDetails = this.getLogStreamOutObject(extra.command_id);
+ if (this.onMessageMethods[message.subtype])
+ this.onMessageMethods[message.subtype].call(this, message, outputElDetails);
else
- this.messages.__default__.call(this, message);
+ this.onMessageMethods.__default__.call(this, message, outputElDetails);
- ide.dispatchEvent("consoleresult." + message.subtype, { data: message.body });
+ ide.dispatchEvent("consoleresult." + message.subtype, {
+ data: message.body
+ });
},
getPrompt: function(suffix) {
@@ -408,10 +521,9 @@ module.exports = ext.register("ext/console/console", {
});
},
- init: function(amlNode){
+ init: function(){
var _self = this;
-
- this.panel = tabConsole;
+
this.$cwd = "/workspace"; // code smell
apf.importCssString(this.css);
@@ -488,11 +600,11 @@ module.exports = ext.register("ext/console/console", {
);
this.keyEvents[KEY_UP] = function(input) {
- var newVal = cmdHistory.getPrev() || "";
+ var newVal = _self.inputHistory.getPrev() || "";
input.setValue(newVal);
};
this.keyEvents[KEY_DOWN] = function(input) {
- var newVal = cmdHistory.getNext() || "";
+ var newVal = _self.inputHistory.getNext() || "";
input.setValue(newVal);
};
this.keyEvents[KEY_CR] = function(input) {
@@ -507,8 +619,114 @@ module.exports = ext.register("ext/console/console", {
this.logged.forEach(function(text){
txtConsole.addValue(text);
});
+
+ // To be uncommented and fully implemented when merged with navbar
+ commands.addCommand({
+ name: "abortclicommand",
+ bindKey: {mac: "Ctrl-C", win: "Ctrl-C"},
+ isAvailable : function(){
+ if (apf.activeElement === txtConsoleInput) {
+ var selection = window.getSelection();
+ var range = selection.getRangeAt(0);
+ if (range.endOffset - range.startOffset === 0)
+ return true;
+ }
+ return false;
+ },
+ exec: function () {
+ _self.cancelCliAction();
+ }
+ });
+
+ // For now, until the local client gets upgraded
+ if (window.cloud9config.hosted)
+ apf.setStyleClass(txtConsole.$ext, "feedback");
},
-
+
+ handleCliBlockAction : function(e) {
+ var pNode = e.target.parentNode;
+
+ if (pNode.className.indexOf("loaded") !== -1) {
+ if (pNode.className.indexOf("collapsed") !== -1)
+ this.expandCliBlock(pNode);
+ else
+ this.collapseCliBlock(pNode);
+ }
+ else {
+ this.cancelCliAction(pNode);
+ }
+ },
+
+ /**
+ * Cancel a CLI command. If `pNode` is undefined, it will subtract 1 from
+ * `this.command_id_tracer`. `pNode` would be undefined if the user pressed
+ * ctrl-c in the input area
+ *
+ * @param DOMElement pNode The parent container block of the close button
+ */
+ cancelCliAction : function(pNode) {
+ var command_id;
+ if (typeof pNode === "undefined")
+ command_id = (this.command_id_tracer - 1)
+ else
+ command_id = parseInt(pNode.getAttribute("rel"), 10);
+
+ var pid = this.tracerToPidMap[command_id];
+ if (!pid)
+ return;
+
+ apf.setStyleClass(pNode, "quitting_proc");
+ Logger.logNodeStream("Killing this process...", null,
+ this.getLogStreamOutObject(command_id), ide);
+
+ ide.send({
+ command: "kill",
+ pid: pid
+ });
+ },
+
+ /**
+ * Expands a CLI block (prompt, stdin and stdout) from its collapsed state.
+ * This can happen from both clicking the expand arrow and also clicking on
+ * the collapsed block itself.
+ *
+ * @param DOMElement pNode The container block to be expanded
+ * @param Event e The click event
+ */
+ expandCliBlock : function(pNode, e) {
+ if (typeof e !== "undefined" && e.target.className.indexOf("prompt_spinner") !== -1)
+ return;
+
+ var height = parseInt(pNode.getAttribute("rel"), 10);
+ apf.setStyleClass(pNode, null, ["collapsed"]);
+ Firmin.animate(pNode, {
+ height : height + "px"
+ }, 0.2, function() {
+ apf.layout.forceResize(tabConsole.$ext);
+ });
+ },
+
+ /**
+ * Collapses a CLI block (prompt, stdin and stdout) down to just the prmompt
+ * and stdin line
+ *
+ * @param DOMElement pNode The container block to be collapsed
+ */
+ collapseCliBlock : function(pNode) {
+ // 20 = padding
+ var startingHeight = apf.getHtmlInnerHeight(pNode) - 20;
+ pNode.style.height = startingHeight + "px";
+ pNode.setAttribute("rel", startingHeight);
+ apf.setStyleClass(pNode, "collapsed");
+ Firmin.animate(pNode, {
+ height : "14px"
+ }, 0.2, function() {
+ apf.layout.forceResize(tabConsole.$ext);
+ });
+
+ pNode.setAttribute("onclick", 'require("ext/console/console").expandCliBlock(this, event)');
+ },
+
logged : [],
log : function(text){
if (this.inited)
@@ -675,6 +893,7 @@ module.exports = ext.register("ext/console/console", {
finish();
}
},
+
enable: function(){
this.nodes.each(function(item) { item.enable(); });
},
View
32 client/ext/console/console.xml
@@ -30,8 +30,8 @@
margin="1 0 0 1"
onclick="require('ext/console/console').hide()"/>
</a:hbox>
- <a:page id="pgConsole" caption="Console" name="console">
- <a:text id="txtConsole"
+ <a:page id="pgOutput" caption="Output" name="output">
+ <a:text id="txtOutput"
margin = "3 0 0 0"
anchors = "0 17 0 0"
flex = "1"
@@ -40,15 +40,15 @@
textselect = "true"
class = "console_text" />
<a:scrollbar
- for = "txtConsole"
- right = "0"
- top = "0"
- bottom = "0"
- skin = "console_scrollbar"
- width = "17" />
+ for = "txtOutput"
+ right = "0"
+ top = "0"
+ bottom = "0"
+ skin = "console_scrollbar"
+ width = "17" />
</a:page>
- <a:page id="pgOutput" caption="Output" name="output">
- <a:text id="txtOutput"
+ <a:page id="pgConsole" caption="Console" name="console">
+ <a:text id="txtConsole"
margin = "3 0 0 0"
anchors = "0 17 0 0"
flex = "1"
@@ -57,12 +57,12 @@
textselect = "true"
class = "console_text" />
<a:scrollbar
- for = "txtOutput"
- right = "0"
- top = "0"
- bottom = "0"
- skin = "console_scrollbar"
- width = "17" />
+ for = "txtConsole"
+ right = "0"
+ top = "0"
+ bottom = "0"
+ skin = "console_scrollbar"
+ width = "17" />
</a:page>
</a:tab>
View
41 client/ext/console/input_history.js
@@ -0,0 +1,41 @@
+/**
+ * Utility for pushing and retrieving input
+ *
+ * @license GPLv3 <http://www.gnu.org/licenses/gpl.txt>
+ */
+
+define(function(require, exports, module) {
+
+module.exports = (function() {
+ function InputHistory() {
+ this._history = [""];
+ this._index = 0;
+ }
+
+ InputHistory.prototype = {
+ push: function(cmd) {
+ this._history.push(cmd);
+ this._index = this.length();
+ },
+
+ length: function() {
+ return this._history.length;
+ },
+
+ getNext: function() {
+ this._index += 1;
+ var cmd = this._history[this._index] || "";
+ this._index = Math.min(this.length(), this._index);
+ return cmd;
+ },
+
+ getPrev: function() {
+ this._index = Math.max(0, this._index - 1);
+ return this._history[this._index];
+ }
+ };
+
+ return InputHistory;
+})();
+
+});
View
35 client/ext/console/logger.js
@@ -108,14 +108,16 @@ var createItem = module.exports.test.createItem = function(line, ide) {
ansiColor -= 2;
return "<span class=\"term_ansi" + ansiColor + "Color\">";
}
- else
+ else {
return "";
+ }
}
})
.replace(/(\u0007|\u001b)\[(K|2J)/g, "");
if (open > 0)
return line + (new Array(open + 1).join("</span>"));
+
return line;
};
@@ -128,6 +130,7 @@ var getOutputElement = function(choice) {
element: txtConsole.$ext,
id: "console"
};
+
if (!choice)
return ret;
@@ -158,15 +161,11 @@ module.exports.logNodeStream = function(data, stream, useOutput, ide) {
eventsAttached = true;
}
- if (!bufferInterval[outputId]) {
+ if (!bufferInterval[outputId])
setBufferInterval(parentEl, outputId);
- }
- // This is a bit cumbersome, but it solves the issue in which logging stuff
- // in the console at a high speed keeps the browser incredibly busy, and
- // sometimes it even crashes. An interval is created in which every 100ms
- // The lines stored in the document fragment are appended in the actual console
- // output.
+ // Interval console output so the browser doesn't crash from high-volume
+ // buffers
if (!childBuffer[outputId]) {
childBuffer[outputId] = document.createDocumentFragment();
childBufferInterval[outputId] = setInterval(function() {
@@ -185,6 +184,7 @@ module.exports.logNodeStream = function(data, stream, useOutput, ide) {
fragment.appendChild(div);
}
}
+
childBuffer[outputId].appendChild(fragment);
};
@@ -194,27 +194,28 @@ var messages = {
command: "<span style='color:#86c2f6'><span>&gt;&gt;&gt;</span><div>__MSG__</div></span>"
};
-module.exports.log = function(msg, type, pre, post, useOutput) {
+module.exports.log = function(msg, type, pre, post, useOutput, tracerId) {
msg = msg.toString().escapeHTML();
if (!type)
type = "log";
- if (messages[type]) {
+ if (messages[type])
msg = messages[type].replace("__MSG__", msg);
- }
var out = getOutputElement(useOutput);
var parentEl = out.element;
var outputId = out.id;
- if (!bufferInterval[outputId]) {
+ if (!bufferInterval[outputId])
setBufferInterval(parentEl, outputId);
- }
- parentEl.innerHTML +=
- "<div class='item console_" + type + "'>" +
- (pre || "") + msg + (post || "") +
- "</div>";
+ var containerOutput = ['<div'];
+ if (tracerId)
+ containerOutput.push(' id="', tracerId, '"');
+ containerOutput.push(" class='item output_section console_",
+ type, "'>", (pre || ""), msg, (post || ""), "</div>");
+
+ parentEl.innerHTML += containerOutput.join("");
};
});
View
23 client/ext/consolehints/consolehints.js
@@ -14,7 +14,7 @@ var ide = require("core/ide");
var ext = require("core/ext");
var markup = require("text!ext/consolehints/consolehints.xml");
var css = require("text!ext/consolehints/consolehints.css");
-var Console = require("ext/console/console");
+var c9console = require("ext/console/console");
var commands = require("ext/commands/commands");
var winHints, hintsContent, selectedHint, animControl, hintsTimer;
@@ -77,12 +77,11 @@ module.exports = ext.register("ext/consolehints/consolehints", {
alone : true,
markup : markup,
css : css,
- deps : [Console],
+ deps : [c9console],
hidden : true,
nodes : [],
autoOpen : true,
- excludeParent : true,
-
+
hook : function(){
var _self = this;
@@ -92,7 +91,7 @@ module.exports = ext.register("ext/consolehints/consolehints", {
var hideInput = e.ext.hideInput;
e.ext.hideInput = function(){
_self.hide();
- hideInput.apply(Console, arguments);
+ hideInput.apply(c9console, arguments);
}
});
},
@@ -112,12 +111,12 @@ module.exports = ext.register("ext/consolehints/consolehints", {
_self.hide();
});
- Console.messages.commandhints = function(message) {
+ c9console.onMessageMethods.commandhints = function(message) {
var cmds = message.body;
for (var cmd in cmds)
commands.commands[cmd] = cmds[cmd];
};
- Console.messages["internal-autocomplete"] = function(message) {
+ c9console.onMessageMethods["internal-autocomplete"] = function(message) {
var cmds = message.body;
_self.show(txtConsoleInput, "", cmds.matches, txtConsoleInput.getValue().length - 1);
};
@@ -127,7 +126,7 @@ module.exports = ext.register("ext/consolehints/consolehints", {
setTimeout(function() {
ide.send({
command: "commandhints",
- cwd: Console.getCwd()
+ cwd: c9console.getCwd()
});
}, 1000);
@@ -170,8 +169,8 @@ module.exports = ext.register("ext/consolehints/consolehints", {
};
Object.keys(redefinedKeys).forEach(function(keyCode) {
- var previousKey = Console.keyEvents[keyCode];
- Console.keyEvents[keyCode] = function(target) {
+ var previousKey = c9console.keyEvents[keyCode];
+ c9console.keyEvents[keyCode] = function(target) {
if (winHints.style.display === "none" && previousKey) {
previousKey(target);
}
@@ -187,7 +186,7 @@ module.exports = ext.register("ext/consolehints/consolehints", {
});
};
- if (Console && Console.messages) {
+ if (c9console && c9console.onMessageMethods) {
initConsoleDeps();
}
else {
@@ -301,7 +300,7 @@ module.exports = ext.register("ext/consolehints/consolehints", {
ide.send({
command: "internal-autocomplete",
argv: [cmd1, cmd2],
- cwd: Console.getCwd()
+ cwd: c9console.getCwd()
});
}
else {
View
3  client/ext/extmgr/extmgr.js
@@ -65,10 +65,11 @@ module.exports = ext.register("ext/extmgr/extmgr", {
init : function(amlNode){
// Save the manually-loaded extensions
+ var _self = this;
ide.addEventListener("settings.save", function(e){
if (!_self.loadedSettings)
return;
-
+
var eNode = e.model.data.selectSingleNode("auto/extensions");
if (eNode) {
eNode.parentNode.removeChild(eNode);
View
54 client/ext/help/help.js
@@ -37,16 +37,18 @@ define(function(require, exports, module) {
hook : function(){
var _self = this;
-
+
+ var mnuHelp = new apf.menu();
+
this.nodes.push(
- menus.addItemByPath("Help/", null, 100000)
+ menus.addItemByPath("Help/", mnuHelp, 100000)
);
var c = 0;
menus.addItemByPath("Help/About", new apf.item({ onclick : function(){ _self.showAbout(); }}), c += 100);
menus.addItemByPath("Help/~", new apf.divider(), c += 100);
menus.addItemByPath("Help/Documentation", new apf.item({ onclick : function(){ window.open('http://support.cloud9ide.com/forums') }}), c += 100);
- menus.addItemByPath("Help/Changelog", new apf.item({ onclick : function(){ window.open('http://c9.io/site/tag/changelog/') }}), c += 100);
+ var mnuChangelog = menus.addItemByPath("Help/Changelog", new apf.item({ onclick : function(){ window.open('http://c9.io/site/tag/changelog/') }}), c += 100);
menus.addItemByPath("Help/Quick Start", new apf.item({ onclick : function(){ quickstart.launchQS(); }}), c += 100);
menus.addItemByPath("Help/Take a Guided Tour", new apf.item({ onclick : function(){ guidedtour.launchGT(); }}), c += 100);
menus.addItemByPath("Help/~", new apf.divider(), c += 100);
@@ -72,27 +74,33 @@ define(function(require, exports, module) {
menus.addItemByPath("Help/Get in Touch/Twitter (for Cloud9 IDE support)", new apf.item({ onclick : function(){ window.open('https://twitter.com/#!/C9Support'); }}), c += 100);
menus.addItemByPath("Help/Get in Touch/Twitter (for general Cloud9 tweets)", new apf.item({ onclick : function(){ window.open('https://twitter.com/#!/cloud9ide'); }}), c += 100);
menus.addItemByPath("Help/Get in Touch/Facebook for Cloud9", new apf.item({ onclick : function(){ window.open('https://www.facebook.com/Cloud9IDE'); }}), c += 100);
-
- if (window.location.host.indexOf("c9.io") >= 0 || window.location.host.indexOf("stage.io") >= 0) {
- var blogURL = window.location.protocol + "//" + window.location.host + "/site/?json=get_tag_posts&tag_slug=changelog";
-
- var response = apf.ajax(blogURL, {
- method: "GET",
- contentType: "application/json",
- async: true,
- data: JSON.stringify({
- agent: navigator.userAgent,
- type: "C9 SERVER EXCEPTION"
- }),
- callback: function( data, state) {
- if (state == apf.SUCCESS) {
- if (data !== undefined) {
- var jsonBlog = JSON.parse(data);
- var latestDate = jsonBlog.posts[0].date;
-
- mnuChangelog.setAttribute("caption", mnuChangelog.caption + " (" + latestDate.split(" ")[0].replace(/-/g, ".") + ")");
+
+ if (window.cloud9config.hosted) {
+ mnuHelp.addEventListener("prop.visible", function(e) {
+ if (e.value) {
+ var blogURL = window.location.protocol + "//" + window.location.host + "/site/?json=get_tag_posts&tag_slug=changelog";
+
+ var response = apf.ajax(blogURL, {
+ method: "GET",
+ contentType: "application/json",
+ async: true,
+ data: JSON.stringify({
+ agent: navigator.userAgent,
+ type: "C9 SERVER EXCEPTION"
+ }),
+ callback: function( data, state) {
+ if (state == apf.SUCCESS) {
+ if (data !== undefined) {
+ var jsonBlog = JSON.parse(data);
+ var latestDate = jsonBlog.posts[0].date;
+
+ mnuChangelog.setAttribute("caption", mnuChangelog.caption + " (" + latestDate.split(" ")[0].replace(/-/g, ".") + ")");
+ }
+ }
}
- }
+ });
+
+ mnuHelp.removeEventListener("prop.visible", arguments.callee);
}
});
}
View
BIN  client/ext/main/style/images/cli-block-expand.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  client/ext/main/style/images/console-action-cancel.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  client/ext/main/style/images/console-expand-contract.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  client/ext/main/style/images/console_spinner_proc.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
2  server/cloud9/view/ide.tmpl.html
@@ -16,6 +16,7 @@
<script type="text/javascript">
//<![CDATA[
+ var baseUrl = window.location.host;
window.cloud9config = {
startdate: new Date(),
davPrefix: <%davPrefix%>,
@@ -29,6 +30,7 @@
version: <%version%>,
staticUrl: "[%staticUrl%]/",
socketIoUrl: <%socketIoUrl%>,
+ hosted: baseUrl.indexOf("c9.io") >= 0 || baseUrl.indexOf("stage.io") >= 0 || baseUrl.indexOf("c9.dev") >= 0,
settings: <%settingsXml%>
};
View
3  server/cloud9/workspace.js
@@ -57,7 +57,8 @@ var Workspace = module.exports = function(config) {
this.send({
type: "result",
subtype: "info",
- body: "Command '" + message.command + "' was not recognized"
+ body: "Command '" + message.command + "' was not recognized",
+ extra: message.extra
}, message);
}
};
Something went wrong with that request. Please try again.