kopia lustrzana https://github.com/c9/core
Merge remote-tracking branch 'origin/master' into codeintel-paths
Conflicts: plugins/c9.ide.language.codeintel/worker/codeintel_worker.jspull/309/head
commit
2f418ce0f4
|
@ -80,6 +80,10 @@ return [
|
|||
packagePath: "./c9.cli.open/open",
|
||||
platform: process.platform
|
||||
},
|
||||
{
|
||||
packagePath: "./c9.cli.exec/exec",
|
||||
platform: process.platform
|
||||
},
|
||||
{
|
||||
packagePath: "./c9.cli.open/restart",
|
||||
platform: process.platform
|
||||
|
|
|
@ -317,7 +317,10 @@ module.exports = function(options) {
|
|||
"plugins/c9.ide.language/tooltip",
|
||||
"plugins/c9.ide.language/jumptodef",
|
||||
"plugins/c9.ide.language/worker_util_helper",
|
||||
"plugins/c9.ide.language.generic/generic",
|
||||
{
|
||||
packagePath: "plugins/c9.ide.language.generic/generic",
|
||||
mode_completer: options.ssh,
|
||||
},
|
||||
"plugins/c9.ide.language.css/css",
|
||||
"plugins/c9.ide.language.html/html",
|
||||
"plugins/c9.ide.language.javascript/javascript",
|
||||
|
@ -694,14 +697,15 @@ module.exports = function(options) {
|
|||
no_newsletter: options.user.no_newsletter,
|
||||
subscription_on_signup: options.user.subscription_on_signup,
|
||||
premium: options.user.premium,
|
||||
region: options.user.region
|
||||
region: options.user.region,
|
||||
},
|
||||
project: {
|
||||
id: options.project.id,
|
||||
name: options.project.name,
|
||||
contents: options.project.contents,
|
||||
descr: options.project.descr,
|
||||
remote: options.project.remote
|
||||
remote: options.project.remote,
|
||||
premium: options.project.premium,
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -719,12 +723,6 @@ module.exports = function(options) {
|
|||
packagePath: "plugins/c9.cli.bridge/bridge_commands",
|
||||
basePath: workspaceDir
|
||||
},
|
||||
{
|
||||
packagePath: "plugins/c9.ide.help.support/support",
|
||||
baseurl: options.ideBaseUrl,
|
||||
userSnapApiKey: options.support.userSnapApiKey,
|
||||
screenshotSupport: true
|
||||
},
|
||||
{
|
||||
packagePath: "plugins/c9.ide.help/help",
|
||||
staticPrefix: staticPrefix + "/plugins/c9.ide.help"
|
||||
|
@ -811,13 +809,28 @@ module.exports = function(options) {
|
|||
|
||||
"plugins/c9.ide.test.mocha/mocha",
|
||||
|
||||
// git integration v2
|
||||
// {
|
||||
// packagePath: "plugins/c9.ide.scm/scm.commit",
|
||||
// staticPrefix: staticPrefix + "/plugins/c9.ide.scm"
|
||||
// },
|
||||
// "plugins/c9.ide.scm/scm",
|
||||
// "plugins/c9.ide.scm/scm.branches",
|
||||
// "plugins/c9.ide.scm/dialog.localchanges",
|
||||
// "plugins/c9.ide.scm/scm.log",
|
||||
// "plugins/c9.ide.scm/git",
|
||||
// "plugins/c9.ide.scm/diff.split",
|
||||
// "plugins/c9.ide.scm/diff.unified",
|
||||
|
||||
// // git integration v1
|
||||
"plugins/c9.ide.scm/v1/scm",
|
||||
"plugins/c9.ide.scm/v1/scmpanel",
|
||||
"plugins/c9.ide.scm/v1/detail",
|
||||
"plugins/c9.ide.scm/v1/log",
|
||||
"plugins/c9.ide.scm/v1/git",
|
||||
"plugins/c9.ide.scm/v1/editor",
|
||||
|
||||
// git integration
|
||||
"plugins/c9.ide.scm/scm",
|
||||
"plugins/c9.ide.scm/scmpanel",
|
||||
"plugins/c9.ide.scm/detail",
|
||||
"plugins/c9.ide.scm/log",
|
||||
"plugins/c9.ide.scm/git",
|
||||
"plugins/c9.ide.scm/editor",
|
||||
"plugins/c9.ide.scm/mergetool"
|
||||
];
|
||||
|
||||
|
|
|
@ -695,6 +695,31 @@ API Documentation
|
|||
|
||||
All classes and public API should be documented using [JSDuck annotations](https://github.com/senchalabs/jsduck).
|
||||
|
||||
Commit messages
|
||||
---------------
|
||||
|
||||
We try to adhere to https://github.com/blog/926-shiny-new-commit-styles and to a lesser extent http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html.
|
||||
Don't write `I fixed a bug` or `Fixed bug`, or even `Added a cool fix for bug`. Just write `Fix bug in wrop wraffles` or `Add feature flip floppers`, present tense.
|
||||
|
||||
Branch Naming
|
||||
-------------
|
||||
|
||||
We follow the uni-repo approach so our source code is in one place. To work around some of the issues - for example looking at all PRs affecting a certain service - we prefix branches with the name of the service(s) the branch affects.
|
||||
|
||||
PR branch names, e.g.
|
||||
|
||||
“api-”, “ide-”, “multi-ide-vfs-sapi-”
|
||||
|
||||
Checking for branch naming consistency is part of the review process and the teams responsibility.
|
||||
|
||||
Use “all-” in case of doubt. E.g., https://github.com/c9/newclient/pull/12962/files affects redis schema code.
|
||||
|
||||
Generally, releasing changes affecting several services is a smell so this can help you identify possible issues.
|
||||
|
||||
You can now look for all PRs which made it in like so (api in this case):
|
||||
|
||||
git log --oneline --first-parent SHA..origin/master | grep -v bump | grep api-
|
||||
|
||||
Other Resources
|
||||
===============
|
||||
|
||||
|
|
|
@ -772,7 +772,7 @@ function Folding() {
|
|||
this.removeFold(fold);
|
||||
else
|
||||
this.expandFold(fold);
|
||||
return;
|
||||
return fold;
|
||||
}
|
||||
|
||||
var range = this.getFoldWidgetRange(row, true);
|
||||
|
@ -781,7 +781,7 @@ function Folding() {
|
|||
fold = this.getFoldAt(range.start.row, range.start.column, 1);
|
||||
if (fold && range.isEqual(fold.range)) {
|
||||
this.removeFold(fold);
|
||||
return;
|
||||
return fold;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,10 +127,20 @@ exports.trimTrailingSpace = function(session, options) {
|
|||
var lines = doc.getAllLines();
|
||||
|
||||
var min = options && options.trimEmpty ? -1 : 0;
|
||||
var cursors = session.selection.rangeCount
|
||||
? session.selection.ranges.map(function(x) { return x.cursor; })
|
||||
: [session.selection.getCursor()];
|
||||
var ci = options && options.keepCursorPosition ? 0 : -1;
|
||||
var cursors = [], ci = -1;
|
||||
if (options && options.keepCursorPosition) {
|
||||
if (session.selection.rangeCount) {
|
||||
session.selection.rangeList.ranges.forEach(function(x, i, ranges) {
|
||||
var next = ranges[i + 1];
|
||||
if (next && next.cursor.row == x.cursor.row)
|
||||
return;
|
||||
cursors.push(x.cursor);
|
||||
});
|
||||
} else {
|
||||
cursors.push(session.selection.getCursor());
|
||||
}
|
||||
ci = 0;
|
||||
}
|
||||
var cursorRow = cursors[ci] && cursors[ci].row;
|
||||
|
||||
for (var i = 0, l=lines.length; i < l; i++) {
|
||||
|
@ -138,8 +148,8 @@ exports.trimTrailingSpace = function(session, options) {
|
|||
var index = line.search(/\s+$/);
|
||||
|
||||
if (i == cursorRow) {
|
||||
if (index < cursors[ci].column)
|
||||
index = min;
|
||||
if (index < cursors[ci].column && index > min)
|
||||
index = cursors[ci].column;
|
||||
ci++;
|
||||
cursorRow = cursors[ci] ? cursors[ci].row : -1;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
if (typeof process !== "undefined") {
|
||||
require("amd-loader");
|
||||
require("../test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
require("../multi_select");
|
||||
var assert = require("assert");
|
||||
var EditSession = require("../edit_session").EditSession;
|
||||
var UndoManager = require("../undomanager").UndoManager;
|
||||
var whitespace = require("./whitespace");
|
||||
|
||||
// Execution ORDER: test.setUpSuite, setUp, testFn, tearDown, test.tearDownSuite
|
||||
|
@ -111,8 +112,90 @@ module.exports = {
|
|||
assert.equal(indent.length, 1);
|
||||
|
||||
next();
|
||||
}
|
||||
},
|
||||
|
||||
"test trimTrailingSpace": function(next) {
|
||||
var session = new EditSession([
|
||||
"a",
|
||||
"\t b \t",
|
||||
" ",
|
||||
"\t",
|
||||
"\t\tx\t\t",
|
||||
" ",
|
||||
" "
|
||||
]);
|
||||
session.setUndoManager(new UndoManager());
|
||||
|
||||
function testOne(value, options) {
|
||||
console.log(JSON.stringify(session.getValue()))
|
||||
|
||||
whitespace.trimTrailingSpace(session, options);
|
||||
assert.equal(value, session.getValue());
|
||||
session.markUndoGroup();
|
||||
session.getUndoManager().undo();
|
||||
}
|
||||
|
||||
testOne("a\n\t b\n \n\t\n\t\tx\n \n ")
|
||||
|
||||
testOne("a\n\t b\n\n\n\t\tx\n\n", {
|
||||
trimEmpty: true
|
||||
});
|
||||
|
||||
session.selection.fromJSON([{
|
||||
start: {row:2,column:3},
|
||||
end: {row:4,column:4}
|
||||
}]);
|
||||
testOne("a\n\t b\n\n\n\t\tx\t\n\n", {
|
||||
keepCursorPosition: true,
|
||||
trimEmpty: true
|
||||
});
|
||||
|
||||
session.selection.fromJSON([{
|
||||
start: {row:2,column:3},
|
||||
end: {row:4,column:4},
|
||||
isBackwards: true
|
||||
}]);
|
||||
testOne("a\n\t b\n \n\n\t\tx\n\n", {
|
||||
keepCursorPosition: true,
|
||||
trimEmpty: true
|
||||
});
|
||||
|
||||
session.selection.$initRangeList();
|
||||
session.selection.fromJSON([{
|
||||
start: {row:2, column:3},
|
||||
end: {row:2,column:3}
|
||||
}, {
|
||||
start: {row:1, column:1},
|
||||
end: {row:1, column:1}
|
||||
}, {
|
||||
start: {row:2,column:2},
|
||||
end: {row:2,column:2}
|
||||
}, {
|
||||
start: {row:0,column:5},
|
||||
end: {row:0,column:5},
|
||||
isBackwards:false
|
||||
}, {
|
||||
start: {row:6,column:1},
|
||||
end: {row:6,column:1},
|
||||
isBackwards:false
|
||||
}]);
|
||||
testOne("a\n\t b\n \n\n\t\tx\n\n ", {
|
||||
trimEmpty: true,
|
||||
keepCursorPosition: true
|
||||
});
|
||||
|
||||
session.setValue("some text");
|
||||
session.selection.fromJSON([{
|
||||
start: {row:0,column:4},
|
||||
end: {row:0,column:4}
|
||||
}]);
|
||||
testOne("some text", {
|
||||
keepCursorPosition: true,
|
||||
trimEmpty: true
|
||||
});
|
||||
|
||||
next();
|
||||
},
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
@ -214,7 +214,7 @@ function LineWidgets(session) {
|
|||
if (!w.coverGutter) {
|
||||
w.el.style.zIndex = 3;
|
||||
}
|
||||
if (!w.pixelHeight) {
|
||||
if (w.pixelHeight == null) {
|
||||
w.pixelHeight = w.el.offsetHeight;
|
||||
}
|
||||
if (w.rowCount == null) {
|
||||
|
|
|
@ -38,7 +38,7 @@ var FoldMode = require("./folding/diff").FoldMode;
|
|||
|
||||
var Mode = function() {
|
||||
this.HighlightRules = HighlightRules;
|
||||
this.foldingRules = new FoldMode(["diff", "index", "\\+{3}", "@@|\\*{5}"], "i");
|
||||
this.foldingRules = new FoldMode(["diff", "@@|\\*{5}"], "i");
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ oop.inherits(FoldMode, BaseFoldMode);
|
|||
}
|
||||
if (row == start.row + 1)
|
||||
return;
|
||||
return Range.fromPoints(start, {row: row - 1, column: line.length});
|
||||
return new Range(start.row, start.column, row - 1, line.length);
|
||||
};
|
||||
|
||||
}).call(FoldMode.prototype);
|
||||
|
|
|
@ -200,7 +200,7 @@ window.onmessage = function(e) {
|
|||
sender._signal(msg.event, msg.data);
|
||||
}
|
||||
else if (msg.command) {
|
||||
if (main[msg.command])
|
||||
if (main && main[msg.command])
|
||||
main[msg.command].apply(main, msg.args);
|
||||
else if (window[msg.command])
|
||||
window[msg.command].apply(window, msg.args);
|
||||
|
|
|
@ -36,7 +36,7 @@ var net = require("../lib/net");
|
|||
var EventEmitter = require("../lib/event_emitter").EventEmitter;
|
||||
var config = require("../config");
|
||||
|
||||
var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) {
|
||||
var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl, importScripts) {
|
||||
this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this);
|
||||
this.changeListener = this.changeListener.bind(this);
|
||||
this.onMessage = this.onMessage.bind(this);
|
||||
|
@ -75,6 +75,9 @@ var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) {
|
|||
throw e;
|
||||
}
|
||||
}
|
||||
if (importScripts) {
|
||||
this.send("importScripts", importScripts);
|
||||
}
|
||||
this.$worker.postMessage({
|
||||
init : true,
|
||||
tlns : tlns,
|
||||
|
@ -94,7 +97,7 @@ var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) {
|
|||
|
||||
this.onMessage = function(e) {
|
||||
var msg = e.data;
|
||||
switch(msg.type) {
|
||||
switch (msg.type) {
|
||||
case "event":
|
||||
this._signal(msg.name, {data: msg.data});
|
||||
break;
|
||||
|
@ -157,7 +160,7 @@ var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) {
|
|||
};
|
||||
|
||||
this.attachToDocument = function(doc) {
|
||||
if(this.$doc)
|
||||
if (this.$doc)
|
||||
this.terminate();
|
||||
|
||||
this.$doc = doc;
|
||||
|
|
|
@ -49,7 +49,7 @@ var DataProvider = function(root) {
|
|||
};
|
||||
|
||||
this.open =
|
||||
this.expand = function(node, deep, silent, justLoaded) {
|
||||
this.expand = function(node, deep, silent) {
|
||||
if (typeof deep != "number")
|
||||
deep = deep ? 100 : 0;
|
||||
if (!node)
|
||||
|
@ -69,7 +69,7 @@ var DataProvider = function(root) {
|
|||
this.collapse(node, null, true);
|
||||
node.status = "loaded";
|
||||
if (!err)
|
||||
this.expand(node, null, false, true);
|
||||
this.expand(node, null, false);
|
||||
}.bind(this));
|
||||
this.setOpen(node, true);
|
||||
return;
|
||||
|
@ -95,9 +95,6 @@ var DataProvider = function(root) {
|
|||
}
|
||||
}
|
||||
|
||||
if (justLoaded)
|
||||
node.justLoaded = true;
|
||||
|
||||
this.rows = items.length;
|
||||
silent || this._signal("expand", node);
|
||||
};
|
||||
|
@ -417,7 +414,7 @@ DataProvider.variableHeightRowMixin = function() {
|
|||
var items = this.visibleItems;
|
||||
var top = 0, index = 0, l = items.length;
|
||||
while (index < l) {
|
||||
var height = this.getItemHeight(items[index].height, index);
|
||||
var height = this.getItemHeight(items[index], index);
|
||||
top += height;
|
||||
index++;
|
||||
if (top >= offset) {
|
||||
|
@ -445,7 +442,7 @@ DataProvider.variableHeightRowMixin = function() {
|
|||
var items = this.visibleItems;
|
||||
var startH = 0, index = 0, l = items.length;
|
||||
while (index < l) {
|
||||
var height = this.getItemHeight(items[index].height, index);
|
||||
var height = this.getItemHeight(items[index], index);
|
||||
startH += height;
|
||||
index++;
|
||||
if (startH >= top) {
|
||||
|
|
|
@ -157,11 +157,12 @@ var EditableTree = function(tree) {
|
|||
this.ace.commands.bindKeys({
|
||||
"Esc": function(ace) {
|
||||
ace.treeEditor.endRename(true);
|
||||
ace.treeEditor.tree.focus();
|
||||
},
|
||||
"Enter": function(ace) {
|
||||
ace.treeEditor.endRename();
|
||||
ace.treeEditor.tree.focus();
|
||||
},
|
||||
"ctrl-s|cmd-s": function(ace) {
|
||||
ace.treeEditor.endRename();
|
||||
},
|
||||
"Tab": function(ace) {
|
||||
ace.treeEditor.editNext(1);
|
||||
|
@ -249,17 +250,26 @@ var EditableTree = function(tree) {
|
|||
this._destroyEditor = function() {
|
||||
if (this.lastDomNode) {
|
||||
this.lastDomNode.style.color = "";
|
||||
this.lastDomNode
|
||||
this.lastDomNode;
|
||||
}
|
||||
this.ace.off("blur", this._onBlur);
|
||||
|
||||
this.tree.renderer.off("afterRender", this._onAfterRender);
|
||||
this.ace.blur();
|
||||
|
||||
this.ace.destroy();
|
||||
if (this.ace.wrapper.parentNode)
|
||||
this.ace.wrapper.parentNode.removeChild(this.ace.wrapper);
|
||||
var ace = this.ace;
|
||||
this.ace = null;
|
||||
this.$lastAce = ace;
|
||||
ace.renderer.freeze();
|
||||
setTimeout(function() {
|
||||
// doing this after timeout to allow rename event focus something else
|
||||
var wasFocused = ace.isFocused();
|
||||
ace.destroy();
|
||||
if (ace.wrapper.parentNode)
|
||||
ace.wrapper.parentNode.removeChild(ace.wrapper);
|
||||
if (wasFocused)
|
||||
this.tree.focus();
|
||||
this.$lastAce = null;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
this.findNextEditPoint = function(dir, node, col, keepColumn) {
|
||||
|
@ -384,6 +394,7 @@ var EditableTree = function(tree) {
|
|||
this.tree._emit("rename", {
|
||||
node: node,
|
||||
value: val,
|
||||
oldValue: this.origVal,
|
||||
column: this.column
|
||||
});
|
||||
this.tree.provider._signal("change");
|
||||
|
|
|
@ -51,7 +51,7 @@ var Cells = function(parentEl) {
|
|||
this.$renderRow(html, datarow, vsize, hsize, row);
|
||||
}
|
||||
|
||||
if (firstRow === 0 && lastRow === 0) {
|
||||
if (firstRow <= 0 && lastRow <= 0) {
|
||||
this.renderPlaceHolder(provider, html, config);
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ var Cells = function(parentEl) {
|
|||
provider.renderRow(row, html, config);
|
||||
}
|
||||
|
||||
if (firstRow === 0 && lastRow === 0) {
|
||||
if (firstRow <= 0 && lastRow <= 0) {
|
||||
this.renderPlaceHolder(provider, html, config);
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ var Cells = function(parentEl) {
|
|||
} else if (provider.getEmptyMessage) {
|
||||
html.push(
|
||||
"<div class='message empty'>",
|
||||
provider.getEmptyMessage(),
|
||||
escapeHTML(provider.getEmptyMessage()),
|
||||
"</div>"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ function ColumnHeader(parentEl, renderer) {
|
|||
}
|
||||
col.pixelWidth = 0;
|
||||
}, this);
|
||||
columns.fixedWidth = fixedWidth;
|
||||
columns.$fixedWidth = fixedWidth + "px";
|
||||
columns.width = null;
|
||||
provider.columns = columns;
|
||||
|
|
|
@ -427,7 +427,7 @@ var host = location.protocol + "//" + location.hostname + (location.port ? ":" +
|
|||
var loadScript = function(path, id, callback) {
|
||||
if (!config.useCache)
|
||||
return loadScriptWithTag(path, id, callback);
|
||||
if (!/https?:/.test(path))
|
||||
if (!/^https?:/.test(path))
|
||||
path = host + path;
|
||||
var cb = function(e, val, deps) {
|
||||
if (e) return processLoadQueue({ id: id, path: path });
|
||||
|
@ -498,10 +498,12 @@ function checkCache() {
|
|||
}).then(function(keys) {
|
||||
baseUrl = host + config.baseUrl;
|
||||
var val = keys.map(function(r) {
|
||||
var url = r.url;
|
||||
if (url.startsWith(baseUrl))
|
||||
url = url.slice(baseUrl.length);
|
||||
return r.headers.get("etag") + " " + url;
|
||||
var url = r.url;
|
||||
if (url.startsWith(baseUrl))
|
||||
url = url.slice(baseUrl.length);
|
||||
else if (/^\w+:/.test(url))
|
||||
return "";
|
||||
return r.headers.get("etag") + " " + url;
|
||||
}).join("\n") + "\n";
|
||||
if (val.length == 1) {
|
||||
ideCachePromiss = null;
|
||||
|
@ -510,7 +512,7 @@ function checkCache() {
|
|||
return new Promise(function(resolve) {
|
||||
var checked = 0;
|
||||
var buffer = "";
|
||||
var toDelete = []
|
||||
var toDelete = [];
|
||||
post("/static/__check__", val, function(t) {
|
||||
var e = t.slice(checked);
|
||||
checked = t.length;
|
||||
|
@ -539,6 +541,22 @@ function checkCache() {
|
|||
return ideCachePromiss;
|
||||
}
|
||||
|
||||
require.clearCache = function(callback) {
|
||||
ideCachePromiss = window.caches.open("ide").then(function(ideCache_) {
|
||||
ideCache = ideCache_;
|
||||
return ideCache.keys();
|
||||
}).then(function(keys) {
|
||||
var toDelete = keys.map(function(i) {
|
||||
ideCache.delete(i);
|
||||
});
|
||||
Promise.all(toDelete).then(function() {
|
||||
callback && callback();
|
||||
}, function(e) {
|
||||
callback && callback(e);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function post(path, val, progress, cb) {
|
||||
var xhr = new window.XMLHttpRequest();
|
||||
xhr.open("POST", path, true);
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
var patchTemplate = ";(" +function() {
|
||||
// automatically generated by architect-build
|
||||
// bundle all dependencies in the main package
|
||||
var Module = require("module");
|
||||
var path = require("path");
|
||||
var _resolveFilename_orig = Module._resolveFilename
|
||||
var root = path.join(__dirname, "{root}");
|
||||
Module._resolveFilename = function(id, parent) {
|
||||
if (parent && parent.paths && parent.paths[0] && parent.paths[0].indexOf(root) == 0) {
|
||||
parent.paths = parent.paths.map(function(p) {
|
||||
if (p.indexOf(root) != 0) return
|
||||
p = p.slice(root.length);
|
||||
return root + p.replace(/([\\\/]|^)node_modules([\\\/]|$)/g, "$1n_m$2");
|
||||
}).filter(Boolean);
|
||||
}
|
||||
return _resolveFilename_orig.call(Module, id, parent);
|
||||
};
|
||||
} + ")();";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var fs = require("fs");
|
||||
var copy = require("architect-build/copy");
|
||||
var pathLib = require("path");
|
||||
|
||||
function freeze(path, mode) {
|
||||
path = copy.convertPath(path);
|
||||
var pkgs = {};
|
||||
function freezePkg(path) {
|
||||
if (!pkgs[path]) {
|
||||
pkgs[path] = JSON.parse(fs.readFileSync(path + "/package.json"))
|
||||
Object.keys(pkgs[path]).forEach(function(k) {
|
||||
if (/Dependencies/i.test(k)) delete pkgs[path][k];
|
||||
})
|
||||
}
|
||||
pkgs[path].dependencies = {};
|
||||
var deps = fs.existsSync(path + "/node_modules") ? fs.readdirSync(path + "/node_modules") : [];
|
||||
deps.forEach(function(n) {
|
||||
if (n == ".bin") return;
|
||||
var depPath = path + "/node_modules/" + n;
|
||||
freezePkg(depPath);
|
||||
pkgs[path].dependencies[n] = pkgs[depPath].version;
|
||||
});
|
||||
if (mode == "rename") {
|
||||
if (deps.length) {
|
||||
fs.renameSync(path + "/node_modules/", path + "/n_m")
|
||||
delete pkgs[path].dependencies
|
||||
if (pkgs[path].files)
|
||||
pkgs[path].files.push("n_m")
|
||||
}
|
||||
} else {
|
||||
pkgs[path].bundledDependencies = Object.keys(pkgs[path].dependencies);
|
||||
}
|
||||
fs.writeFileSync(path + "/package.json", JSON.stringify(pkgs[path], null, "\t"), "utf8");
|
||||
}
|
||||
freezePkg(path);
|
||||
var bin = pkgs[path].bin;
|
||||
Object.keys(bin).forEach(function(key) {
|
||||
var p = bin[key];
|
||||
var root = pathLib.relative(pathLib.dirname(p), "").replace(/[\\]/g, "/");
|
||||
var src = fs.readFileSync(path + "/" + p, "utf8");
|
||||
src = src.replace(/^(#.*|"use strict";?|\s)*/, function(a) {
|
||||
return a.trim() + "\n\n" + patchTemplate.replace(/{root}/g, root) + "\n\n";
|
||||
});
|
||||
fs.writeFileSync(path + "/" + p, src, "utf8");
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = freeze;
|
|
@ -23,7 +23,9 @@ define(function(require, exports, module) {
|
|||
name: user.fullname || user.name,
|
||||
pricingPlan: user.premium ? "Premium" : "Free",
|
||||
referredBy: user.referrer,
|
||||
region: user.region
|
||||
region: user.region,
|
||||
usertype: user.usertype,
|
||||
purpose: user.purpose,
|
||||
};
|
||||
|
||||
return traits;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
|
||||
module.exports = function isNotFound(err) {
|
||||
if (err && err.code === 404) return true;
|
||||
return false;
|
||||
};
|
|
@ -36,7 +36,7 @@ function RestClient(host, port, config) {
|
|||
var headers = _.extend({
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"Content-Length": payload.length
|
||||
"Content-Length": Buffer.byteLength(payload)
|
||||
}, config.headers || {});
|
||||
|
||||
var options = {
|
||||
|
@ -44,7 +44,11 @@ function RestClient(host, port, config) {
|
|||
port: port,
|
||||
path: path,
|
||||
method: method,
|
||||
headers: headers
|
||||
headers: headers,
|
||||
timeout: config.timeout || 60 * 1000,
|
||||
pool: config.pool || {
|
||||
maxSockets: 100000,
|
||||
},
|
||||
};
|
||||
if (config.username)
|
||||
options.auth = config.username + ":" + config.password;
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/*global describe it before after beforeEach afterEach */
|
||||
"use strict";
|
||||
|
||||
"use server";
|
||||
"use mocha";
|
||||
|
||||
require("c9/inline-mocha")(module);
|
||||
require("amd-loader");
|
||||
|
||||
var assert = require("assert");
|
||||
var http = require("http");
|
||||
var findFreePort = require("netutil").findFreePort;
|
||||
var RestClient = require("./rest_client");
|
||||
|
||||
describe(__filename, function() {
|
||||
|
||||
var port;
|
||||
var MIN_API_PORT = 18500;
|
||||
var MAX_API_PORT = MIN_API_PORT + 1000;
|
||||
|
||||
beforeEach(function(next) {
|
||||
findFreePort(MIN_API_PORT, MAX_API_PORT, 'localhost', function(err, _port) {
|
||||
port = _port;
|
||||
next(err);
|
||||
});
|
||||
});
|
||||
|
||||
it("should send correct content length", function(next) {
|
||||
var server = http.createServer(function(req, res) {
|
||||
var body = "";
|
||||
req.on("data", function(d) {
|
||||
body += d;
|
||||
});
|
||||
|
||||
req.on("end", function() {
|
||||
JSON.parse(body);
|
||||
res.end("OK");
|
||||
});
|
||||
|
||||
});
|
||||
server.listen(port, function() {
|
||||
var client = new RestClient("localhost", port, {});
|
||||
|
||||
// send body with "strange" unicode character
|
||||
var body = {"cloneFromScm":"https://github.com/saasbook/ruby-calisthenics"};
|
||||
client.request("POST", "/", body, function(err, res) {
|
||||
assert(!err, err);
|
||||
assert.equal(res, "OK");
|
||||
server.close(next);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -200,7 +200,9 @@ module.exports = function setup(fsOptions) {
|
|||
// Extending the API
|
||||
extend: extend,
|
||||
unextend: unextend,
|
||||
use: use
|
||||
use: use,
|
||||
|
||||
workspaceDir: fsOptions.projectDir
|
||||
});
|
||||
|
||||
function wrapDomain(api) {
|
||||
|
@ -1030,7 +1032,16 @@ module.exports = function setup(fsOptions) {
|
|||
if (!exists || options.overwrite || isSamePath) {
|
||||
// Rename the file
|
||||
fs.rename(frompath, topath, function (err) {
|
||||
if (err) return callback(err);
|
||||
if (err) {
|
||||
if (err.code == 'ENOENT' && options.mkdirP != false) {
|
||||
options.mkdirP = false;
|
||||
return mkdirP(dir, {}, function(err) {
|
||||
if (err) return callback(err);
|
||||
rename(path, options, callback);
|
||||
});
|
||||
}
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// Rename metadata
|
||||
if (options.metadata !== false) {
|
||||
|
@ -1551,7 +1562,7 @@ module.exports = function setup(fsOptions) {
|
|||
// todo add resize event
|
||||
proc.emit("data", {rows: rows, cols: cols});
|
||||
|
||||
if (!tmuxWarned) {
|
||||
if (!tmuxWarned && !isWin) {
|
||||
if (/v0\.([123456789]\..*|10\.(0|1|2[0-7]))/.test(process.version)) {
|
||||
proc.emit("data", {
|
||||
message: "Wrong Node.js version: " + process.version,
|
||||
|
@ -1827,9 +1838,11 @@ module.exports = function setup(fsOptions) {
|
|||
}
|
||||
else if (options.command) {
|
||||
args.push(BASH + " -l -c '"
|
||||
+ options.command.replace(/'/g, "'\\''")
|
||||
+ '; printf "\\e[01;30m\\n\\nProcess exited with code: $?\\e[0m\\n"'
|
||||
+ "; sleep 0.1;'");
|
||||
+ (
|
||||
'trap \'printf "\\e[01;30m\\n\\nProcess exited with code: $?\\e[0m\\n"\' EXIT\n'
|
||||
+ options.command
|
||||
).replace(/'/g, "'\\''")
|
||||
+ "'");
|
||||
}
|
||||
|
||||
args.push(
|
||||
|
@ -1995,15 +2008,20 @@ module.exports = function setup(fsOptions) {
|
|||
};
|
||||
|
||||
this.destroy = function(){
|
||||
pty.destroy.apply(pty, arguments);
|
||||
return pty.destroy.apply(pty, arguments);
|
||||
};
|
||||
|
||||
this.end = function(){
|
||||
pty.end.apply(pty, arguments);
|
||||
return pty.end.apply(pty, arguments);
|
||||
};
|
||||
|
||||
this.write = function() {
|
||||
pty.write.apply(pty, arguments);
|
||||
return pty.write.apply(pty, arguments);
|
||||
};
|
||||
|
||||
this.resize = function() {
|
||||
if (!exited)
|
||||
return pty.resize.apply(pty, arguments);
|
||||
};
|
||||
|
||||
// this.acknowledgeWrite = function(callback) {
|
||||
|
|
|
@ -437,6 +437,8 @@ function Worker(vfs) {
|
|||
var keys = Object.keys(meta || {});
|
||||
for (var i = 0, l = keys.length; i < l; i++) {
|
||||
var key = keys[i];
|
||||
if (meta[key] == undefined)
|
||||
continue;
|
||||
switch (key) {
|
||||
case "stream": token.stream = storeStream(meta.stream); break;
|
||||
case "process": token.process = storeProcess(meta.process); break;
|
||||
|
|
46
package.json
46
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "c9",
|
||||
"description": "New Cloud9 Client",
|
||||
"version": "3.1.1776",
|
||||
"version": "3.1.2074",
|
||||
"author": "Ajax.org B.V. <info@ajax.org>",
|
||||
"private": true,
|
||||
"main": "bin/c9",
|
||||
|
@ -26,7 +26,7 @@
|
|||
"mkdirp": "~0.3.5",
|
||||
"msgpack-js": "~0.1.1",
|
||||
"msgpack-js-browser": "~0.1.4",
|
||||
"nak": "git://github.com/cloud9ide/nak.git#719f2188ec1d8e4ce553286e80737d7e6434d777",
|
||||
"nak": "git://github.com/cloud9ide/nak.git#6deef931594",
|
||||
"netutil": "~0.0.2",
|
||||
"optimist": "~0.6.0",
|
||||
"qs": "0.6.6",
|
||||
|
@ -55,24 +55,24 @@
|
|||
"c9"
|
||||
],
|
||||
"c9plugins": {
|
||||
"c9.ide.language": "#b392f03a6c",
|
||||
"c9.ide.language": "#e058ff301f",
|
||||
"c9.ide.language.css": "#be07d72209",
|
||||
"c9.ide.language.generic": "#92210f5a48",
|
||||
"c9.ide.language.generic": "#3949510863",
|
||||
"c9.ide.language.html": "#22fdc74869",
|
||||
"c9.ide.language.html.diff": "#24f3608d26",
|
||||
"c9.ide.language.javascript": "#d1a479805c",
|
||||
"c9.ide.language.javascript": "#e626169643",
|
||||
"c9.ide.language.javascript.immediate": "#c8b1e5767a",
|
||||
"c9.ide.language.javascript.eslint": "#3c57ed1720",
|
||||
"c9.ide.language.javascript.eslint": "#4de5457db1",
|
||||
"c9.ide.language.javascript.tern": "#64ab01f271",
|
||||
"c9.ide.language.javascript.infer": "#18acb93a3a",
|
||||
"c9.ide.language.jsonalyzer": "#4b329741b1",
|
||||
"c9.ide.language.codeintel": "#72157892e4",
|
||||
"c9.ide.collab": "#11a0d3c5ce",
|
||||
"c9.ide.language.codeintel": "#44b7cb3565",
|
||||
"c9.ide.collab": "#728ad2bde2",
|
||||
"c9.ide.local": "#10eb45842a",
|
||||
"c9.ide.find": "#e33fbaed2f",
|
||||
"c9.ide.find.infiles": "#c0a13737ef",
|
||||
"c9.ide.find.replace": "#8cbce45290",
|
||||
"c9.ide.run.debug": "#286975f644",
|
||||
"c9.ide.find.replace": "#810ebf8bfb",
|
||||
"c9.ide.run.debug": "#ef40edcc3f",
|
||||
"c9.automate": "#47e2c429c9",
|
||||
"c9.ide.ace.emmet": "#6dc4585e02",
|
||||
"c9.ide.ace.gotoline": "#a8ff07c8f4",
|
||||
|
@ -80,24 +80,24 @@
|
|||
"c9.ide.ace.repl": "#4b88a85b7b",
|
||||
"c9.ide.ace.split": "#0ae0151c78",
|
||||
"c9.ide.ace.statusbar": "#3aab0b67e0",
|
||||
"c9.ide.ace.stripws": "#8885016b9e",
|
||||
"c9.ide.ace.stripws": "#042a9936e3",
|
||||
"c9.ide.behaviors": "#db32109ebc",
|
||||
"c9.ide.closeconfirmation": "#cee4674141",
|
||||
"c9.ide.configuration": "#528234d97d",
|
||||
"c9.ide.configuration": "#a936df26bb",
|
||||
"c9.ide.dialog.wizard": "#7667ec79a8",
|
||||
"c9.ide.fontawesome": "#781602c5d8",
|
||||
"c9.ide.format": "#5ec97fb083",
|
||||
"c9.ide.help.support": "#af5c4055b2",
|
||||
"c9.ide.help.support": "#932fbb3743",
|
||||
"c9.ide.imgeditor": "#612e75ef4f",
|
||||
"c9.ide.immediate": "#19758abe08",
|
||||
"c9.ide.installer": "#0fde9f0067",
|
||||
"c9.ide.installer": "#1232d4e179",
|
||||
"c9.ide.language.python": "#701bd2630a",
|
||||
"c9.ide.language.go": "#6ce1c7a7ef",
|
||||
"c9.ide.mount": "#4c39359b87",
|
||||
"c9.ide.navigate": "#1fbb7cd53b",
|
||||
"c9.ide.navigate": "#0b7ec7936c",
|
||||
"c9.ide.newresource": "#981a408a7b",
|
||||
"c9.ide.openfiles": "#2ae85a9e33",
|
||||
"c9.ide.preview": "#70bd68740c",
|
||||
"c9.ide.preview": "#5f5fff0185",
|
||||
"c9.ide.preview.browser": "#897177be7f",
|
||||
"c9.ide.preview.markdown": "#c3174d86e0",
|
||||
"c9.ide.pubsub": "#a85fb27eca",
|
||||
|
@ -105,19 +105,19 @@
|
|||
"c9.ide.recentfiles": "#7c099abf40",
|
||||
"c9.ide.remote": "#301d2ab519",
|
||||
"c9.ide.processlist": "#2b12cd1bdd",
|
||||
"c9.ide.run": "#4f0257bc0b",
|
||||
"c9.ide.run": "#6bd4996a4e",
|
||||
"c9.ide.run.build": "#0598fff697",
|
||||
"c9.ide.run.debug.xdebug": "#9956689819",
|
||||
"c9.ide.save": "#86f0f38160",
|
||||
"c9.ide.scm": "#f1d190fa51",
|
||||
"c9.ide.terminal.monitor": "#1a4092ede2",
|
||||
"c9.ide.test": "#a282ec1619",
|
||||
"c9.ide.save": "#4cda35bfdb",
|
||||
"c9.ide.scm": "#637a68cd04",
|
||||
"c9.ide.terminal.monitor": "#affa33572f",
|
||||
"c9.ide.test": "#102942ae4e",
|
||||
"c9.ide.test.mocha": "#fc053b23d2",
|
||||
"c9.ide.theme.flat": "#81dadeee55",
|
||||
"c9.ide.threewaymerge": "#229382aa0b",
|
||||
"c9.ide.undo": "#b028bcb4d5",
|
||||
"c9.ide.upload": "#0bd010d3dc",
|
||||
"c9.ide.upload": "#a3da59803d",
|
||||
"c9.ide.welcome": "#5b86c44e92",
|
||||
"c9.ide.guide": "#16537f57cf"
|
||||
"c9.ide.guide": "#8ab966f344"
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ define(function(require, exports, module) {
|
|||
if (done) return;
|
||||
callback(new Error("No Response"));
|
||||
done = true;
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
define(function(require, exports, module) {
|
||||
main.consumes = [
|
||||
"Plugin", "bridge", "tabManager", "panels", "tree.favorites", "tree",
|
||||
"fs", "preferences", "settings", "c9"
|
||||
"fs", "preferences", "settings", "c9", "commands"
|
||||
];
|
||||
main.provides = ["bridge.commands"];
|
||||
return main;
|
||||
|
@ -18,6 +18,7 @@ define(function(require, exports, module) {
|
|||
var fs = imports.fs;
|
||||
var c9 = imports.c9;
|
||||
var prefs = imports.preferences;
|
||||
var commands = imports.commands;
|
||||
|
||||
var async = require("async");
|
||||
|
||||
|
@ -36,6 +37,15 @@ define(function(require, exports, module) {
|
|||
case "open":
|
||||
open(message, e.respond);
|
||||
break;
|
||||
case "exec":
|
||||
exec(message, e.respond);
|
||||
break;
|
||||
case "pipe":
|
||||
createPipe(message, e.respond);
|
||||
break;
|
||||
case "pipeData":
|
||||
updatePipe(message, e.respond);
|
||||
break;
|
||||
case "ping":
|
||||
e.respond(null, true);
|
||||
break;
|
||||
|
@ -66,6 +76,30 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
/***** Methods *****/
|
||||
function createPipe(message, callback) {
|
||||
tabManager.once("ready", function(){
|
||||
tabManager.open({
|
||||
focus: true,
|
||||
editorType: "ace",
|
||||
path: message.path && c9.toInternalPath(message.path),
|
||||
document: { meta : { newfile: true } }
|
||||
}, function(err, tab) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
callback(null, tab.path || tab.name);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function updatePipe(message, callback) {
|
||||
tabManager.once("ready", function() {
|
||||
var tab = tabManager.findTab(message.tab);
|
||||
var c9Session = tab && tab.document.getSession();
|
||||
if (c9Session && c9Session.session)
|
||||
c9Session.session.insert({row: Number.MAX_VALUE, column: Number.MAX_VALUE} , message.data);
|
||||
callback(null, true);
|
||||
});
|
||||
}
|
||||
|
||||
function open(message, callback) {
|
||||
var i = -1;
|
||||
|
@ -102,12 +136,22 @@ define(function(require, exports, module) {
|
|||
}
|
||||
else {
|
||||
tabManager.once("ready", function(){
|
||||
var m = /:(\d*)(?::(\d*))?$/.exec(path);
|
||||
var jump = {};
|
||||
if (m) {
|
||||
if (m[1])
|
||||
jump.row = parseInt(m[1], 10) - 1;
|
||||
if (m[2])
|
||||
jump.column = parseInt(m[2], 10);
|
||||
path = path.slice(0, m.index);
|
||||
}
|
||||
|
||||
fs.exists(path, function(existing) {
|
||||
var tab = tabManager.open({
|
||||
path: path,
|
||||
focus: i === 0,
|
||||
document: existing
|
||||
? undefined
|
||||
? { ace: { jump: jump } }
|
||||
: { meta : { newfile: true } }
|
||||
}, function(){
|
||||
next();
|
||||
|
@ -133,6 +177,12 @@ define(function(require, exports, module) {
|
|||
callback(null, true);
|
||||
});
|
||||
}
|
||||
|
||||
function exec(message, callback) {
|
||||
var result = commands.exec(message.command, message.args);
|
||||
var err = result ? null : "command failed";
|
||||
callback(err, result);
|
||||
}
|
||||
|
||||
/***** Lifecycle *****/
|
||||
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
define(function(require, exports, module) {
|
||||
main.consumes = ["Plugin", "cli_commands", "bridge.client"];
|
||||
main.provides = ["exec"];
|
||||
return main;
|
||||
|
||||
function main(options, imports, register) {
|
||||
var Plugin = imports.Plugin;
|
||||
var cmd = imports.cli_commands;
|
||||
var bridge = imports["bridge.client"];
|
||||
|
||||
/***** Initialization *****/
|
||||
|
||||
var plugin = new Plugin("Ajax.org", main.consumes);
|
||||
// var emit = plugin.getEmitter();
|
||||
|
||||
var loaded;
|
||||
function load(){
|
||||
if (loaded) return;
|
||||
loaded = true;
|
||||
|
||||
cmd.addCommand({
|
||||
name: "exec",
|
||||
info: " Executes remote c9 commands.",
|
||||
usage: "<command> [argument 1] [argument 2] ... [argument n]",
|
||||
check: function(argv) {
|
||||
if (argv._.length < 2)
|
||||
throw new Error("Missing command");
|
||||
},
|
||||
options: {},
|
||||
exec: function(argv) {
|
||||
exec(
|
||||
argv._[1],
|
||||
argv._.slice(2),
|
||||
function(){});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/***** Methods *****/
|
||||
|
||||
function exec(command, args, callback) {
|
||||
args.unshift(process.cwd());
|
||||
var message = {
|
||||
type: "exec",
|
||||
command: command,
|
||||
args: args
|
||||
};
|
||||
|
||||
bridge.send(message, function cb(err, response) {
|
||||
if (err) {
|
||||
console.log(err.message);
|
||||
}
|
||||
|
||||
if (response !== true)
|
||||
console.log("Could not execute", command);
|
||||
|
||||
process.exit(); // I don't get why this is needed
|
||||
});
|
||||
}
|
||||
|
||||
/***** Lifecycle *****/
|
||||
|
||||
plugin.on("load", function(){
|
||||
load();
|
||||
});
|
||||
plugin.on("enable", function(){
|
||||
|
||||
});
|
||||
plugin.on("disable", function(){
|
||||
|
||||
});
|
||||
plugin.on("unload", function(){
|
||||
loaded = false;
|
||||
});
|
||||
|
||||
/***** Register and define API *****/
|
||||
|
||||
/**
|
||||
* Finds or lists files and/or lines based on their filename or contents
|
||||
**/
|
||||
plugin.freezePublicAPI({
|
||||
/**
|
||||
*
|
||||
*/
|
||||
exec: exec
|
||||
});
|
||||
|
||||
register(null, {
|
||||
exec: plugin
|
||||
});
|
||||
}
|
||||
});
|
|
@ -25,19 +25,28 @@ define(function(require, exports, module) {
|
|||
cmd.addCommand({
|
||||
name: "open",
|
||||
info: " Opens a file or directory.",
|
||||
usage: "[--wait] <path>",
|
||||
usage: "[--wait] [--pipe] <path>",
|
||||
options: {
|
||||
"wait": {
|
||||
description: "Wait until the file(s) are closed",
|
||||
"default": false,
|
||||
"boolean": true
|
||||
},
|
||||
"pipe": {
|
||||
description: "Pipe data from a command into c9",
|
||||
"default": false,
|
||||
"boolean": true
|
||||
}
|
||||
},
|
||||
check: function(argv) {
|
||||
if (argv._.length < 2 && !argv["path"])
|
||||
if (argv._.length < 2 && !argv["path"] && !argv.pipe)
|
||||
throw new Error("Missing path");
|
||||
},
|
||||
exec: function(argv) {
|
||||
if (argv.pipe) {
|
||||
openWithPipe(function(){});
|
||||
return;
|
||||
}
|
||||
open(
|
||||
argv._.slice(1), // Remove "open" from the paths
|
||||
argv.wait,
|
||||
|
@ -126,6 +135,60 @@ define(function(require, exports, module) {
|
|||
});
|
||||
}
|
||||
|
||||
function openWithPipe(callback) {
|
||||
bridge.send({
|
||||
type: "pipe",
|
||||
path: process.cwd() + "/" + "Pipe " + (new Date()).toLocaleString().replace(/:/g, "."),
|
||||
}, function cb(err, response) {
|
||||
if (err) {
|
||||
if (err.code == "ECONNREFUSED") {
|
||||
// Seems Cloud9 is not running, lets start it up
|
||||
startCloud9Local({}, function(success) {
|
||||
if (success)
|
||||
bridge.send({ type: "pipe" }, cb);
|
||||
else {
|
||||
console.log("Could not start Cloud9. "
|
||||
+ "Please check your configuration.");
|
||||
callback(err);
|
||||
|
||||
process.exit(40); // This appears to be needed; let's return something useful
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
else {
|
||||
console.log(err.message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var stdin = process.openStdin();
|
||||
stdin.setEncoding("utf8");
|
||||
var finished = 0;
|
||||
stdin.on("data", function(chunk) {
|
||||
finished++;
|
||||
bridge.send({
|
||||
type: "pipeData",
|
||||
data: chunk,
|
||||
tab: response
|
||||
}, function(err, message) {
|
||||
// Dunno why, but this always returns No Response...
|
||||
// Escaping that error so end users aren't confused...
|
||||
if (err && err.message !== "No Response")
|
||||
console.log(err.message);
|
||||
finished--;
|
||||
});
|
||||
});
|
||||
stdin.on("end", function() {
|
||||
(function retry() {
|
||||
if (finished === 0)
|
||||
process.exit();
|
||||
setTimeout(retry, 100);
|
||||
})();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function startCloud9Local(opts, callback) {
|
||||
if (options.platform == "darwin") {
|
||||
proc.spawn("open", {
|
||||
|
|
|
@ -653,6 +653,10 @@ define(function(require, exports, module) {
|
|||
p = "/" + normalizePath(Path.relative(cwd, p));
|
||||
excludeMap[p] = 1;
|
||||
});
|
||||
// keep installer in both packed and unpacked form
|
||||
if (json.installer)
|
||||
excludeMap["/" + normalizePath(Path.relative(cwd, json.installer))] = 0;
|
||||
|
||||
copy(cwd, cwd + "/.c9/.build", {
|
||||
exclude: function(name, parent) {
|
||||
if (excludeRe.test(name))
|
||||
|
|
|
@ -577,7 +577,7 @@ define(function(require, exports, module) {
|
|||
|
||||
function setAPIKey(apikey){
|
||||
// Validate Key
|
||||
if (!apikey || !apikey.match(/[\w+]{27}=/))
|
||||
if (!apikey || !apikey.match(/^.{27}=$/))
|
||||
throw new Error("Invalid API key");
|
||||
|
||||
return {
|
||||
|
|
|
@ -115,6 +115,7 @@ function plugin(options, imports, register) {
|
|||
var accept = req.headers.accept || '';
|
||||
|
||||
if (statusCode == 500) {
|
||||
console.error(err && err.stack);
|
||||
emitter.emit("internalServerError", {
|
||||
err: err,
|
||||
req: req
|
||||
|
|
|
@ -90,6 +90,7 @@ function plugin(options, imports, register) {
|
|||
var customData = _.clone(raygun.customData || {});
|
||||
if (req.user) {
|
||||
customData.user = {
|
||||
augment: err.augment,
|
||||
id: req.user.id,
|
||||
name: req.user.name,
|
||||
email: req.user.email
|
||||
|
|
|
@ -25,8 +25,8 @@ function plugin(options, imports, register) {
|
|||
};
|
||||
|
||||
var clients = {
|
||||
error: new raygun.Client().init({ apiKey: options.keys.error }),
|
||||
warning: new raygun.Client().init({ apiKey: options.keys.warning })
|
||||
error: new raygun.Client().init({ apiKey: options.keys.error, useHumanStringForObject: false }),
|
||||
warning: new raygun.Client().init({ apiKey: options.keys.warning, useHumanStringForObject: false })
|
||||
};
|
||||
|
||||
var customClients = options.customClients || {};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<title><%=error%></title>
|
||||
<title>503 - Service Unavailable</title>
|
||||
<link rel="stylesheet" type="text/css" href="<%=staticPrefix%>/error_handler/style.css" />
|
||||
</head>
|
||||
<body class="error503 light">
|
||||
|
|
|
@ -82,6 +82,9 @@ define(function(require, exports, module) {
|
|||
node.status = "pending";
|
||||
return;
|
||||
}
|
||||
var parentPath = e.path;
|
||||
if (!parentPath.endsWith("/"))
|
||||
parentPath += "/";
|
||||
// update cache
|
||||
if (!node) {
|
||||
if (!showHidden && isFileHidden(e.path))
|
||||
|
@ -92,97 +95,116 @@ define(function(require, exports, module) {
|
|||
orphans[e.path] = node;
|
||||
orphan = true;
|
||||
}
|
||||
node.$lastReadT = Date.now();
|
||||
|
||||
// Indicate this directory has been fully read
|
||||
model.setAttribute(node, "status", "loaded");
|
||||
|
||||
var wasOpen = startUpdate(node);
|
||||
node.children = null;
|
||||
var existing = node.map || {};
|
||||
node.map = {};
|
||||
|
||||
// Fill Parent
|
||||
var ondisk = {}, toAppend = [];
|
||||
var ondisk = Object.create(null);
|
||||
var toRemove = [];
|
||||
var toCreate = [];
|
||||
var orphanAppand = [];
|
||||
var existing = node.map || (node.map = Object.create(null));
|
||||
e.result[1].forEach(function(stat) {
|
||||
if (!stat.name || !showHidden && isFileHidden(stat.name))
|
||||
return;
|
||||
|
||||
var name = stat.name;
|
||||
var path = (e.path + "/" + name).replace("//", "/");
|
||||
var path = parentPath + name;
|
||||
|
||||
ondisk[name] = 1;
|
||||
// if (existing[name]) return;
|
||||
|
||||
if (orphans[path]) {
|
||||
toAppend.push(path);
|
||||
if (existing[name])
|
||||
delete orphans[path];
|
||||
orphanAppand.push(path);
|
||||
}
|
||||
createNode(path, stat, existing[name], true);
|
||||
|
||||
if (existing[name])
|
||||
updateNodeStat(path, stat, existing[name]);
|
||||
else
|
||||
toCreate.push(stat);
|
||||
});
|
||||
|
||||
for (var name in existing) {
|
||||
if (!ondisk[name]) {
|
||||
// onreaddir can be called before copied nodes are written to disk
|
||||
// in this case we don't want to lose "predicted" state
|
||||
if (existing[name] && existing[name].status === "predicted")
|
||||
node.map[name] = existing[name];
|
||||
else {
|
||||
delete existing[name];
|
||||
|
||||
emit("remove", {
|
||||
path: e.path + "/" + name,
|
||||
node: existing[name],
|
||||
parent: node
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Object.keys(existing).forEach(function(name) {
|
||||
// onreaddir can be called before copied nodes are written to disk
|
||||
// in this case we don't want to lose "predicted" state
|
||||
if (existing[name] && existing[name].status === "predicted")
|
||||
ondisk[name] = 1;
|
||||
if (!ondisk[name])
|
||||
toRemove.push(name);
|
||||
});
|
||||
|
||||
if (!toCreate.length && !toRemove.length && !orphanAppand.length)
|
||||
return;
|
||||
|
||||
var wasOpen = startUpdate(node);
|
||||
node.children = null;
|
||||
|
||||
// Fill Parent
|
||||
toCreate.forEach(function(stat) {
|
||||
createNode(parentPath + stat.name, stat, null, true);
|
||||
});
|
||||
|
||||
toRemove.forEach(function(name) {
|
||||
var currentNode = existing[name];
|
||||
delete existing[name];
|
||||
emit("remove", {
|
||||
path: parentPath + name,
|
||||
node: currentNode,
|
||||
parent: node
|
||||
});
|
||||
});
|
||||
|
||||
emit("readdir", { path : e.path, parent : node, orphan: orphan });
|
||||
|
||||
endUpdate(node, wasOpen);
|
||||
|
||||
toAppend.forEach(function(path) {
|
||||
orphanAppand.forEach(function(path) {
|
||||
emit("orphan-append", {path: path});
|
||||
});
|
||||
}
|
||||
fs.on("afterReaddir", onreaddir, plugin);
|
||||
|
||||
function onstat(e) {
|
||||
var stat;
|
||||
if (e.error) return;
|
||||
|
||||
if (!e.error) {
|
||||
// update cache
|
||||
var there = true;
|
||||
var node = findNode(e.path);
|
||||
var parent = findNode(dirname(e.path));
|
||||
|
||||
if (!showHidden && isFileHidden(e.path))
|
||||
return;
|
||||
// update cache
|
||||
var stat = e.result[1];
|
||||
|
||||
var there = true;
|
||||
var node = findNode(e.path);
|
||||
var parent = findNode(dirname(e.path));
|
||||
|
||||
if (!showHidden && isFileHidden(e.path))
|
||||
return;
|
||||
|
||||
if (!node) {
|
||||
if (!parent)
|
||||
return;
|
||||
there = false;
|
||||
if (!node) {
|
||||
if (!parent)
|
||||
return;
|
||||
there = false;
|
||||
}
|
||||
|
||||
if (there != !!stat) {
|
||||
if (there) {
|
||||
if (!node.link)
|
||||
deleteNode(node);
|
||||
}
|
||||
|
||||
if (there != !!e.result[1]) {
|
||||
if (there) {
|
||||
if (!node.link)
|
||||
deleteNode(node);
|
||||
}
|
||||
else {
|
||||
stat = e.result[1];
|
||||
if (typeof stat != "object")
|
||||
stat = null;
|
||||
createNode(e.path, stat);
|
||||
}
|
||||
}
|
||||
else if (there) {
|
||||
stat = e.result[1];
|
||||
else {
|
||||
if (typeof stat != "object")
|
||||
stat = null;
|
||||
createNode(e.path, stat, node);
|
||||
createNode(e.path, stat);
|
||||
}
|
||||
}
|
||||
else if (there) {
|
||||
if (typeof stat != "object")
|
||||
stat = null;
|
||||
if (!stat && node)
|
||||
return;
|
||||
if (stat && node)
|
||||
updateNodeStat(e.path, stat, node);
|
||||
else
|
||||
createNode(e.path, stat, node);
|
||||
}
|
||||
}
|
||||
fs.on("afterStat", onstat, plugin);
|
||||
fs.on("afterReadFile", function(e) {
|
||||
|
@ -295,14 +317,15 @@ define(function(require, exports, module) {
|
|||
// Validation
|
||||
var toNode = findNode(newPath);
|
||||
|
||||
deleteNode(node, true);
|
||||
if (toNode)
|
||||
deleteNode(toNode, true);
|
||||
|
||||
createNode(newPath, null, node); // Move node
|
||||
recurPathUpdate(node, oldPath, newPath);
|
||||
if (!toNode) {
|
||||
deleteNode(node, true);
|
||||
createNode(newPath, null, node); // Move node
|
||||
recurPathUpdate(node, oldPath, newPath);
|
||||
}
|
||||
|
||||
e.undo = function(){
|
||||
if (toNode)
|
||||
return;
|
||||
if (!parent) {
|
||||
var tmpParent = node;
|
||||
while (node.parent && tmpParent.parent.status == "pending")
|
||||
|
@ -318,6 +341,12 @@ define(function(require, exports, module) {
|
|||
recurPathUpdate(node, newPath, oldPath);
|
||||
};
|
||||
e.confirm = function() {
|
||||
if (toNode) {
|
||||
deleteNode(toNode, true);
|
||||
createNode(newPath, null, node); // Move node
|
||||
recurPathUpdate(node, oldPath, newPath);
|
||||
}
|
||||
|
||||
if (node.status === "predicted")
|
||||
node.status = "loaded";
|
||||
};
|
||||
|
@ -511,14 +540,8 @@ define(function(require, exports, module) {
|
|||
updateNode = orphans[path];
|
||||
delete orphans[path];
|
||||
}
|
||||
var original_stat;
|
||||
if (stat && stat.link) {
|
||||
original_stat = stat;
|
||||
stat = stat.linkStat;
|
||||
}
|
||||
|
||||
var parts = path.split("/");
|
||||
var name = parts[parts.length - 1];
|
||||
var node = model.root.map[parts[0] == "~" ? "~" : ""];
|
||||
if (!node) {
|
||||
node = orphans[parts[0]];
|
||||
|
@ -537,7 +560,7 @@ define(function(require, exports, module) {
|
|||
|
||||
var map = node.map;
|
||||
if (!map) {
|
||||
map = node.map = {};
|
||||
map = node.map = Object.create(null);
|
||||
}
|
||||
parent = node;
|
||||
node = map[p];
|
||||
|
@ -545,6 +568,11 @@ define(function(require, exports, module) {
|
|||
modified.push(parent);
|
||||
if (i !== parts.length - 1) {
|
||||
node = {label: p, path: subPath, status: "pending", isFolder: true};
|
||||
// TODO filter hidden files in getChildren instead.
|
||||
if (!showHidden && isFileHidden(p)) {
|
||||
orphans[node.path] = path;
|
||||
return;
|
||||
}
|
||||
} else if (updateNode) {
|
||||
deleteNode(updateNode, true);
|
||||
node = updateNode;
|
||||
|
@ -564,8 +592,32 @@ define(function(require, exports, module) {
|
|||
node = {label: parts[parts.length - 1], path: path};
|
||||
orphans[path] = node;
|
||||
}
|
||||
|
||||
updateNodeStat(path, stat, node);
|
||||
|
||||
node.children = null;
|
||||
|
||||
if (!updating) {
|
||||
if (!modified.length)
|
||||
modified.push(parent);
|
||||
var wasOpen = startUpdate(modified[0]);
|
||||
modified.forEach(function(n) {
|
||||
if (n != model.root)
|
||||
n.children = null;
|
||||
});
|
||||
endUpdate(modified[0], wasOpen);
|
||||
}
|
||||
model._signal("createNode", node);
|
||||
return node;
|
||||
}
|
||||
|
||||
function updateNodeStat(path, stat, node) {
|
||||
node.path = path;
|
||||
|
||||
var original_stat;
|
||||
if (stat && stat.link) {
|
||||
original_stat = stat;
|
||||
stat = stat.linkStat;
|
||||
}
|
||||
if (stat) {
|
||||
var isFolder = stat && /(directory|folder)$/.test(stat.mime);
|
||||
if (isFolder) {
|
||||
|
@ -589,25 +641,13 @@ define(function(require, exports, module) {
|
|||
delete node.isFolder;
|
||||
}
|
||||
|
||||
if (node.isFolder && !node.map)
|
||||
node.map = {};
|
||||
else if (!node.isFolder && node.map)
|
||||
if (node.isFolder && !node.map) {
|
||||
node.map = Object.create(null);
|
||||
node.children = null;
|
||||
} else if (!node.isFolder && node.map) {
|
||||
delete node.map;
|
||||
|
||||
node.children = null;
|
||||
|
||||
if (!updating) {
|
||||
if (!modified.length)
|
||||
modified.push(parent);
|
||||
var wasOpen = startUpdate(modified[0]);
|
||||
modified.forEach(function(n) {
|
||||
if (n != model.root)
|
||||
n.children = null;
|
||||
});
|
||||
endUpdate(modified[0], wasOpen);
|
||||
node.children = null;
|
||||
}
|
||||
model._signal("createNode", node);
|
||||
return node;
|
||||
}
|
||||
|
||||
function deleteNode(node, silent) {
|
||||
|
@ -670,7 +710,7 @@ define(function(require, exports, module) {
|
|||
map: {}
|
||||
};
|
||||
var root = {};
|
||||
root.map = {};
|
||||
root.map = Object.create(null);
|
||||
root.map[""] = model.projectDir;
|
||||
model.setRoot(root);
|
||||
// fs.readdir("/", function(){});
|
||||
|
@ -894,7 +934,12 @@ define(function(require, exports, module) {
|
|||
* @param {Function} progress
|
||||
* @param {Function} done
|
||||
*/
|
||||
loadNodes: loadNodes
|
||||
loadNodes: loadNodes,
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
isFileHidden: isFileHidden
|
||||
});
|
||||
|
||||
register(null, {
|
||||
|
|
|
@ -37,7 +37,7 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
|
|||
|
||||
describe('proc', function() {
|
||||
describe('spawn()', function() {
|
||||
this.timeout(4000);
|
||||
this.timeout(10000);
|
||||
|
||||
it("should spawn a child process", function(done) {
|
||||
var args = ["-e", "process.stdin.pipe(process.stdout);try{process.stdin.resume()}catch(e) {};"];
|
||||
|
@ -66,8 +66,8 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
|
|||
});
|
||||
});
|
||||
|
||||
//should test the kill() method - which is broken now
|
||||
//Another test - see that cwd defaults to the root vfs dir when resolve is set to true
|
||||
// should test the kill() method - which is broken now
|
||||
// Another test - see that cwd defaults to the root vfs dir when resolve is set to true
|
||||
});
|
||||
describe('execFile()', function() {
|
||||
this.timeout(10000);
|
||||
|
@ -101,8 +101,19 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
|
|||
});
|
||||
});
|
||||
|
||||
//should test the kill() method - which is broken now
|
||||
//Another test - see that cwd defaults to the root vfs dir when resolve is set to true
|
||||
it('should pass stdout and stderr', function(done) {
|
||||
proc.execFile("node", {
|
||||
args: ["-v"]
|
||||
}, function(e, stdout, stderr) {
|
||||
expect(stdout[0]).to.equal("v");
|
||||
expect(stderr).to.equal("");
|
||||
expect(e).to.not.ok;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// should test the kill() method - which is broken now
|
||||
// Another test - see that cwd defaults to the root vfs dir when resolve is set to true
|
||||
});
|
||||
describe('pty()', function() {
|
||||
this.timeout(30000);
|
||||
|
|
|
@ -1444,7 +1444,7 @@ define(function(require, exports, module) {
|
|||
else if (/^{/.test(firstLine)) {
|
||||
syntax = "json";
|
||||
}
|
||||
else if (/\.(bashrc|inputrc)$/.test(path)) {
|
||||
else if (/\.(bash|inputrc|profile|zsh)/.test(path)) {
|
||||
syntax = "sh";
|
||||
}
|
||||
else if (/\.(git(attributes|config|ignore)|npmrc)$/.test(path)) {
|
||||
|
|
|
@ -26,6 +26,8 @@ define(function(require, module, exports) {
|
|||
/***** Methods *****/
|
||||
|
||||
function show(title, header, msg, onhide, options) {
|
||||
options = options || {};
|
||||
|
||||
metrics.increment("dialog.error");
|
||||
|
||||
return plugin.queue(function(){
|
||||
|
@ -37,13 +39,15 @@ define(function(require, module, exports) {
|
|||
else {
|
||||
plugin.title = title;
|
||||
}
|
||||
plugin.heading = options && options.isHTML ? header : util.escapeXml(header);
|
||||
plugin.body = options && options.isHTML ? msg : (util.escapeXml(msg) || "")
|
||||
plugin.heading = options.isHTML ? header : util.escapeXml(header);
|
||||
plugin.body = options.isHTML ? msg : (util.escapeXml(msg) || "")
|
||||
.replace(/\n/g, "<br />")
|
||||
.replace(/(https?:\/\/[^\s]*\b)/g, "<a href='$1' target='_blank'>$1</a>");
|
||||
|
||||
plugin.getElement("ok").setCaption(options.yes || "OK");
|
||||
|
||||
plugin.update([
|
||||
{ id: "dontshow", visible: options && options.showDontShow }
|
||||
{ id: "dontshow", visible: options.showDontShow }
|
||||
]);
|
||||
|
||||
plugin.once("hide", function(){
|
||||
|
|
|
@ -54,7 +54,7 @@ define(function(require, module, exports) {
|
|||
|
||||
var gotYesNo = false;
|
||||
plugin.once("hide", function(){
|
||||
!gotYesNo && cancel && onNo(false, true, metadata);
|
||||
!gotYesNo && cancel && onNo && onNo(false, true, metadata);
|
||||
});
|
||||
|
||||
plugin.update([
|
||||
|
@ -63,22 +63,22 @@ define(function(require, module, exports) {
|
|||
{ id: "yestoall", visible: all, onclick: function(){
|
||||
gotYesNo = true;
|
||||
plugin.hide();
|
||||
onYes(true, metadata);
|
||||
onYes && onYes(true, metadata);
|
||||
}},
|
||||
{ id: "notoall", visible: all, onclick: function(){
|
||||
gotYesNo = true;
|
||||
plugin.hide();
|
||||
onNo(true, false, metadata);
|
||||
onNo && onNo(true, false, metadata);
|
||||
}},
|
||||
{ id: "yes", onclick: function(){
|
||||
gotYesNo = true;
|
||||
plugin.hide();
|
||||
onYes(false, metadata);
|
||||
onYes && onYes(false, metadata);
|
||||
}},
|
||||
{ id: "no", onclick: function(){
|
||||
gotYesNo = true;
|
||||
plugin.hide();
|
||||
onNo(false, false, metadata);
|
||||
onNo && onNo(false, false, metadata);
|
||||
}}
|
||||
]);
|
||||
}, options.queue === false);
|
||||
|
|
|
@ -27,14 +27,14 @@ define(function(require, module, exports) {
|
|||
options = {isHTML: true};
|
||||
|
||||
return plugin.queue(function(){
|
||||
var all = options.all;
|
||||
var cancel = options.cancel;
|
||||
var showDontAsk = options.showDontAsk;
|
||||
var metadata = options.metadata;
|
||||
|
||||
title = title || "This is a Premium feature";
|
||||
header = header || "Get Premium Support Now!";
|
||||
msg = msg || 'Help is just a few clicks away. Check out our <a href="https://c9.io/pricing" target="_blank">amazing premium plans</a>.'
|
||||
header = header || "Upgrade to Premium Now!";
|
||||
onYes = onYes || function() {};
|
||||
onNo = onNo || function() {};
|
||||
msg = msg || 'A better, faster, more versatile Cloud9 is just a click away. Check out our <a href="https://c9.io/pricing" target="_blank">amazing premium plans</a>.';
|
||||
|
||||
plugin.title = title;
|
||||
plugin.heading = options && options.isHTML ? header : util.escapeXml(header);
|
||||
|
@ -73,7 +73,12 @@ define(function(require, module, exports) {
|
|||
plugin.freezePublicAPI({
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Function} onYes Callback for when user clicks the 'yes' button
|
||||
* @param {Function} onNo Callback for when the user clicks the 'no' button
|
||||
* @param {String} [title] Title for the dialog
|
||||
* @param {String} [header] Header for the dialog body
|
||||
* @param {String} [msg] Message to show the user.
|
||||
* @param {Object} [options] Miscellaneous options
|
||||
*/
|
||||
show: show
|
||||
});
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<a:textbox
|
||||
id = "txtFilename"
|
||||
flex = "7"
|
||||
class = "ace_searchbox tb_textbox searchbox searchTxt tb_console tb_textboxInitial"
|
||||
class = "ace_searchbox tb_textbox searchbox searchTxt tb_console"
|
||||
focusselect = "true" />
|
||||
</a:hsplitbox>
|
||||
</div>
|
||||
|
@ -46,7 +46,7 @@
|
|||
<a:textbox
|
||||
id = "txtDirectory"
|
||||
flex = "7"
|
||||
class = "directory ace_searchbox tb_textbox searchbox searchTxt tb_console tb_textboxInitial"
|
||||
class = "directory ace_searchbox tb_textbox searchbox searchTxt tb_console"
|
||||
focusselect = "true" />
|
||||
</a:hbox>
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<a:textbox
|
||||
id = "txtUsername"
|
||||
flex = "7"
|
||||
class = "ace_searchbox tb_textbox searchbox searchTxt tb_console tb_textboxInitial"
|
||||
class = "ace_searchbox tb_textbox searchbox searchTxt tb_console"
|
||||
focusselect = "true" />
|
||||
</a:hbox>
|
||||
</div>
|
||||
|
@ -41,7 +41,7 @@
|
|||
<a:secret
|
||||
id = "txtPassword"
|
||||
flex = "7"
|
||||
class = "ace_searchbox tb_textbox searchbox searchTxt tb_console tb_textboxInitial"
|
||||
class = "ace_searchbox tb_textbox searchbox searchTxt tb_console"
|
||||
focusselect = "true" />
|
||||
</a:hbox>
|
||||
</div>
|
||||
|
|
|
@ -245,14 +245,16 @@ define(function(require, module, exports) {
|
|||
dropdown.setAttribute("value", item.value);
|
||||
break;
|
||||
default:
|
||||
if ("value" in item)
|
||||
el.setAttribute('value', item.value);
|
||||
if ("onclick" in item)
|
||||
el.onclick = item.onclick;
|
||||
if ("visible" in item)
|
||||
el.setAttribute("visible", item.visible);
|
||||
if ("zindex" in item)
|
||||
el.setAttribute("zindex", item.zindex);
|
||||
// supported attributes
|
||||
var validAttributes = /^(value|visible|zindex|disabled|caption|tooltip|command|class|icon|src|submenu)$/;
|
||||
Object.keys(item).forEach(function(key) {
|
||||
// Check for onclick explictly
|
||||
if (key === "onclick")
|
||||
return el.onclick = item.onclick;
|
||||
// Check for attributes we know exist and will directly set
|
||||
if (validAttributes.test(key))
|
||||
return el.setAttribute(key, item[key]);
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -291,9 +291,9 @@ define(function(require, module, exports) {
|
|||
load();
|
||||
});
|
||||
|
||||
plugin.on("beforeUnload", function(){
|
||||
plugin.on("beforeUnload", function(e){
|
||||
if (!plugin.meta.$closing) {
|
||||
if (close())
|
||||
if (close(e && e.animate === false))
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1283,7 +1283,7 @@ define(function(require, module, exports) {
|
|||
|
||||
// Or keep tab until the new one is loaded
|
||||
else {
|
||||
previewTab.unload();
|
||||
previewTab.unload({ animate: false });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,12 +74,15 @@ define(function(require, exports, module) {
|
|||
plugin.freezePublicAPI({
|
||||
/**
|
||||
* Returns the logged in user.
|
||||
*
|
||||
* @param [callback]
|
||||
* @return {Object} The currently user
|
||||
*/
|
||||
getUser: getUser,
|
||||
|
||||
/**
|
||||
* Return the active workspace.
|
||||
*
|
||||
* @return {Object} The currently active workspace
|
||||
*/
|
||||
getWorkspace: getWorkspace,
|
||||
|
|
|
@ -96,9 +96,18 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
function getHotkey(command) {
|
||||
if (!commands[command] || !commands[command].bindKey)
|
||||
return "";
|
||||
return commands[command].bindKey[platform];
|
||||
}
|
||||
|
||||
function getPrettyHotkey(command) {
|
||||
var key = getHotkey(command);
|
||||
if (platform == "mac")
|
||||
key = apf.hotkeys.toMacNotation(key);
|
||||
return key;
|
||||
}
|
||||
|
||||
var markDirty = lang.delayedCall(function(){
|
||||
emit("update");
|
||||
}, 500);
|
||||
|
@ -557,6 +566,14 @@ define(function(require, exports, module) {
|
|||
*/
|
||||
getHotkey: getHotkey,
|
||||
|
||||
/**
|
||||
* returns result of getHotkey formatted for displaying in menus
|
||||
*
|
||||
* @param {String} name the name of the command.
|
||||
* @return {String}
|
||||
*/
|
||||
getPrettyHotkey: getPrettyHotkey,
|
||||
|
||||
/**
|
||||
* Executes the action tied to a command. This method will call
|
||||
* the `isAvailable` method for a command and will not execute if
|
||||
|
|
|
@ -79,6 +79,9 @@ define(function(require, exports, module) {
|
|||
// @TODO this is probably not sufficient
|
||||
layout.on("resize", function(){ tree.resize() }, plugin);
|
||||
|
||||
var key = commands.getPrettyHotkey("commands");
|
||||
txtFilter.setAttribute("initial-message", key);
|
||||
|
||||
tree.textInput = txtFilter.ace.textInput;
|
||||
|
||||
txtFilter.ace.commands.addCommands([
|
||||
|
|
|
@ -214,7 +214,7 @@ define(function(require, exports, module) {
|
|||
}
|
||||
}
|
||||
|
||||
function proposeLayoutChange(kind, force, type, reset) {
|
||||
function proposeLayoutChange(kind, force, type) {
|
||||
if (!force && settings.getBool("user/general/@propose"))
|
||||
return;
|
||||
|
||||
|
@ -225,7 +225,7 @@ define(function(require, exports, module) {
|
|||
ignoreTheme = true;
|
||||
var theme = {"dark": "flat-dark", "light": "flat-light"}[kind];
|
||||
settings.set("user/general/@skin", theme);
|
||||
updateTheme(!!reset, type);
|
||||
updateTheme(false, type);
|
||||
ignoreTheme = false;
|
||||
settings.set("user/general/@propose", question.dontAsk);
|
||||
},
|
||||
|
@ -333,15 +333,6 @@ define(function(require, exports, module) {
|
|||
amlNode.$ext.className += " c9btn";
|
||||
|
||||
menus.addItemByPath("File/~", new apf.divider(), 1000000, plugin);
|
||||
|
||||
if (!c9.local) {
|
||||
menus.addItemByPath("Cloud9/~", new apf.divider(), 2000000, plugin);
|
||||
menus.addItemByPath("Cloud9/Quit Cloud9", new apf.item({
|
||||
onclick: function(){
|
||||
location.href = "http://c9.io";
|
||||
}
|
||||
}), 2000100, plugin);
|
||||
}
|
||||
|
||||
menus.addItemByPath("View/~", new apf.divider(), 9999, plugin);
|
||||
|
||||
|
@ -357,6 +348,14 @@ define(function(require, exports, module) {
|
|||
}), 300, plugin);
|
||||
}
|
||||
|
||||
function resetTheme(theme, type) {
|
||||
ignoreTheme = true;
|
||||
settings.set("user/general/@skin", theme);
|
||||
updateTheme(true);
|
||||
emit("themeDefaults", {theme: theme, type: type});
|
||||
ignoreTheme = false;
|
||||
}
|
||||
|
||||
function resize(){
|
||||
if (c9console && tabManager) {
|
||||
var tRect = tabManager.container.$ext.getBoundingClientRect();
|
||||
|
@ -597,7 +596,7 @@ define(function(require, exports, module) {
|
|||
get theme(){
|
||||
return theme;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns an AMLElement that can server as a parent.
|
||||
* @param {Plugin} plugin The plugin for which to find the parent.
|
||||
|
@ -613,6 +612,13 @@ define(function(require, exports, module) {
|
|||
*/
|
||||
initMenus: initMenus,
|
||||
|
||||
/**
|
||||
* Resets theme (without questioning user).
|
||||
* @param {String} theme Theme to use.
|
||||
* @param {String} type Type of editor to use.
|
||||
*/
|
||||
resetTheme: resetTheme,
|
||||
|
||||
/**
|
||||
* Sets the layout in one of two default modes:
|
||||
* @param {"default"|"minimal"} type
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
.btn-switcher {
|
||||
.user-select(none);
|
||||
-webkit-display: flex;
|
||||
display: flex;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
cursor: default;
|
||||
font-size: @preview-chooser-font-size;
|
||||
font-weight: @preview-chooser-font-weight;
|
||||
color: ;
|
||||
font-family: @preview-chooser-font-family;
|
||||
-webkit-font-smoothing: auto;
|
||||
-moz-osx-font-smoothing: auto;
|
||||
background: @preview-chooser-background;
|
||||
border-radius: 0 2px 2px 0;
|
||||
box-shadow: @preview-chooser-box-shadow;
|
||||
cursor: pointer;
|
||||
border: 1px solid @textbox-border-color;
|
||||
border-left : 0;
|
||||
border-radius: 0 3px 3px 0;
|
||||
position : relative;
|
||||
|
||||
padding: 4px 17px 4px 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.btn-switcherOver{
|
||||
background: @preview-chooser-over-background;
|
||||
}
|
||||
.btn-switcherDown{
|
||||
background: @preview-chooser-active-background;
|
||||
}
|
||||
.btn-switcher svg{
|
||||
vertical-align: middle;
|
||||
margin: -2px 4px 0 0;
|
||||
}
|
||||
|
||||
.btn-switcher span{
|
||||
display : block;
|
||||
position : absolute;
|
||||
right : 6px;
|
||||
top : 11px;
|
||||
width : 5px;
|
||||
height : 5px;
|
||||
background: url("@{image-path}/@{preview-chooser-arrow}") no-repeat;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.btn-switcherIcon {
|
||||
background-repeat: no-repeat;
|
||||
padding-left: 25px;
|
||||
background-position: 5px 50%
|
||||
}
|
|
@ -18,6 +18,9 @@
|
|||
color : @textbox-disabled-color;
|
||||
background: @textbox-disabled-background;
|
||||
}
|
||||
.has_apf .searchTxt.tb_console.ace_searchboxDisabled .sbtb_middle .input {
|
||||
color : @textbox-disabled-color;
|
||||
}
|
||||
.ace_one-line .ace_scroller.ace_scroll-left {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
@ -40,10 +43,6 @@
|
|||
outline : none;
|
||||
text-overflow : ellipsis;
|
||||
}
|
||||
.tb_consoleFocus .sbtb_middle,
|
||||
.tb_consoleOver .sbtb_middle,
|
||||
.tb_console .sbtb_middle:hover {
|
||||
}
|
||||
|
||||
.topborder .sbtb_middle{
|
||||
border-width : 1px 0 0 0;
|
||||
|
@ -63,15 +62,13 @@
|
|||
padding : 0;
|
||||
}
|
||||
|
||||
.tb_console.tb_textboxInitial .sbtb_middle {
|
||||
padding-right : 0 !important;
|
||||
|
||||
.ace_editor .tb_textboxInitialMsg {
|
||||
text-indent: 5px;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.tb_console.tb_textboxInitial .input {
|
||||
font-size : 10px;
|
||||
}
|
||||
|
||||
.tb_console.tb_textboxInitial .ace_cursor{
|
||||
.ace_initialMsg:not(.ace_focus) .ace_cursor {
|
||||
display : none;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ BODY.noInput *{
|
|||
@import "less/button.less";
|
||||
@import "less/btn_console.less";
|
||||
@import "less/btn_console_open.less";
|
||||
@import "less/btn-switcher.less";
|
||||
@import "less/c9-divider-double.less";
|
||||
@import "less/c9-divider-hor.less";
|
||||
@import "less/c9-divider.less";
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
height: auto;
|
||||
position: relative;
|
||||
}
|
||||
.searchTxt.tb_textboxInitial .sbtb_middle .input {
|
||||
.searchTxt.tb_textboxInitial .sbtb_middle .input, .tb_textboxInitialMsg {
|
||||
color: @textbox-initial-color !important;
|
||||
text-shadow: @textbox-initial-text-shadow;
|
||||
font-family: @find-textbox-font-family;
|
||||
|
|
|
@ -859,4 +859,16 @@
|
|||
</a:main>
|
||||
</a:presentation>
|
||||
</a:button>
|
||||
<a:button name="btn-switcher">
|
||||
<a:presentation>
|
||||
<a:main
|
||||
caption = "text()"
|
||||
background = "."
|
||||
icon = ".">
|
||||
<div class="btn-switcher">
|
||||
-<span> </span>
|
||||
</div>
|
||||
</a:main>
|
||||
</a:presentation>
|
||||
</a:button>
|
||||
</a:skin>
|
|
@ -1711,7 +1711,7 @@
|
|||
@form-bar-border-bottom: 1px solid black;
|
||||
@form-bar-box-shadow: 0 1px @border-highlight;
|
||||
|
||||
@panel-settings-changes-top: 46px;
|
||||
@panel-settings-changes-top: 53px;
|
||||
|
||||
/*******/
|
||||
|
||||
|
|
|
@ -1066,8 +1066,8 @@
|
|||
@textbox-border-color: darken(#dedede, @darken-chrome);
|
||||
@textbox-initial-color: darken(#A5A5A5, @darken-chrome);
|
||||
@textbox-initial-text-shadow: 0 1px 0 darken(#FFFFFF, @darken-chrome);
|
||||
@textbox-disabled-color: gray;
|
||||
@textbox-disabled-background: darken(rgb(216, 216, 216), @darken-chrome);
|
||||
@textbox-disabled-color: #C5C5C5;
|
||||
@textbox-disabled-background: #F1F1F1;
|
||||
|
||||
// Textbox - Simple
|
||||
@tbsimple-border: 1px solid #DEDEDE;
|
||||
|
@ -1706,9 +1706,9 @@
|
|||
@diff-toolbar-buttons-background: #F9F9F9;
|
||||
@diff-toolbar-buttons-border: 1px solid @border-highlight-dark;
|
||||
|
||||
@form-bar-padding: 10px 50px 10px 10px;
|
||||
@form-bar-padding: 10px 10px 0 10px;
|
||||
@form-bar-background: @menu-button-active-background;
|
||||
@form-bar-border-bottom: 1px solid black;
|
||||
@form-bar-border-bottom: 1px solid #DEDEDE;
|
||||
@form-bar-box-shadow: 0 1px @border-highlight;
|
||||
|
||||
@panel-settings-changes-top: 46px;
|
||||
@panel-settings-changes-top: 53px;
|
|
@ -470,6 +470,9 @@ body .runner-form-header{
|
|||
.cbblack.cbcontainerDisabled.cbcontainerChecked .checkbox{
|
||||
background-position: 0 -142px;
|
||||
}
|
||||
.cbblack.cbcontainerDisabled.cbcontainerDisabled .checkbox{
|
||||
background-position: 0 0;
|
||||
}
|
||||
.session_btn .tab_middle:before {
|
||||
background-position : 0 -126px;
|
||||
-webkit-mask-position : 0 -95px;
|
||||
|
|
|
@ -40,6 +40,15 @@ define(function(require, exports, module) {
|
|||
});
|
||||
|
||||
auth.on("relogin", onReLogin);
|
||||
|
||||
if (!c9.local) {
|
||||
menus.addItemByPath("Cloud9/~", new apf.divider(), 2000000, plugin);
|
||||
menus.addItemByPath("Cloud9/Quit Cloud9", new apf.item({
|
||||
onclick: function(){
|
||||
signout();
|
||||
}
|
||||
}), 2000100, plugin);
|
||||
}
|
||||
}
|
||||
|
||||
/***** Methods *****/
|
||||
|
|
|
@ -147,6 +147,14 @@ define(function(require, module, exports) {
|
|||
|
||||
mnuItem.setAttribute("hotkey",
|
||||
"{commands.commandManager." + options.name + "}");
|
||||
|
||||
|
||||
if (button && button.setAttribute) {
|
||||
var key = commands.getPrettyHotkey(options.name);
|
||||
button.setAttribute("tooltip", options.name
|
||||
+ (key ? " (" + key + ")" : ""));
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
|
@ -382,6 +390,11 @@ define(function(require, module, exports) {
|
|||
*/
|
||||
get button(){ return button; },
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get active(){ return panels.isActive(plugin.name); },
|
||||
|
||||
_events: [
|
||||
/**
|
||||
* Fires when the panel is drawn.
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
<div id="mocha"></div>
|
||||
<div id='jserror' width='100%' height='20px' style='font: 10px \"courier new\"; color: red; display: none;'></div>
|
||||
|
||||
<script src="/static/require.js"></script>
|
||||
<script src="/static/lib/mocha/mocha.js"></script>
|
||||
<script src="/static/require.js" crossorigin="true"></script>
|
||||
<script src="/static/lib/mocha/mocha.js" crossorigin="true"></script>
|
||||
<script>
|
||||
/*global mocha*/
|
||||
mocha.setup('bdd');
|
||||
|
@ -57,4 +57,4 @@
|
|||
});
|
||||
//--></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -43,7 +43,9 @@
|
|||
"Press Option-Tab to go to the next IDE tab.",
|
||||
"Press Option-Shift-T to reopen a tab you closed.",
|
||||
"Press Option-T to open a new terminal at any time.",
|
||||
"Press Cmd-E to search for a file by name."
|
||||
"Press Cmd-E to search for a file by name.",
|
||||
"Press Cmd-Shift-E to search for a function by name.",
|
||||
"Press Option-S to switch between a terminal and an editor.",
|
||||
];
|
||||
|
||||
var win_keybindings = [
|
||||
|
@ -54,7 +56,9 @@
|
|||
"Press Ctrl-D to delete the current line of code",
|
||||
"Press Alt-Shift-T to reopen a tab you closed.",
|
||||
"Press Alt-T to open a new terminal at any time.",
|
||||
"Press Ctrl-E to search for a file by name."
|
||||
"Press Ctrl-E to search for a file by name.",
|
||||
"Press Ctrl-Shift-E to search for a function by name.",
|
||||
"Press Alt-S to switch between a terminal and an editor.",
|
||||
];
|
||||
|
||||
var isMac = (navigator.platform == "MacIntel" || navigator.platform == "Macintosh" || navigator.platform == "MacPPC");
|
||||
|
|
|
@ -221,7 +221,7 @@ define(function(require, exports, module) {
|
|||
}]);
|
||||
|
||||
ace.onPaste = function(text) {
|
||||
this.send(text.replace(/\r\n/g, "\n"));
|
||||
this.send(text.replace(/\r\n?|\n/g, this.session.term.convertEol ? "\n" : "\r"));
|
||||
};
|
||||
|
||||
ace.setKeyboardHandler(this);
|
||||
|
|
|
@ -470,7 +470,7 @@ Terminal.prototype.writeInternal = function(data) {//TODO optimize lines
|
|||
if (!this.insertMode)
|
||||
line[this.x] = [this.curAttr, ch];
|
||||
else
|
||||
line[insertY].splice(this.x, 0, [this.curAttr, ch]);
|
||||
line.splice(this.x, 0, [this.curAttr, ch]);
|
||||
break;
|
||||
case 0:
|
||||
if (this.x > 0) this.x--;
|
||||
|
@ -481,7 +481,7 @@ Terminal.prototype.writeInternal = function(data) {//TODO optimize lines
|
|||
line[this.x] = [this.curAttr, ch];
|
||||
line[this.x + 1] = [this.curAttr, "\x00"];
|
||||
} else {
|
||||
line[insertY].splice(this.x, 0, [this.curAttr, ch], [this.curAttr, ""]);
|
||||
line.splice(this.x, 0, [this.curAttr, ch], [this.curAttr, ""]);
|
||||
}
|
||||
this.x++;
|
||||
break;
|
||||
|
|
|
@ -3,7 +3,7 @@ define(function(require, exports, module) {
|
|||
"Panel", "c9", "util", "fs", "settings", "ui", "menus",
|
||||
"panels", "commands", "tabManager", "fs.cache", "watcher",
|
||||
"preferences", "clipboard", "dialog.alert", "dialog.fileremove",
|
||||
"dialog.fileoverwrite", "dialog.error", "layout"
|
||||
"dialog.fileoverwrite", "dialog.error", "layout", "dialog.question"
|
||||
];
|
||||
main.provides = ["tree"];
|
||||
return main;
|
||||
|
@ -24,6 +24,7 @@ define(function(require, exports, module) {
|
|||
var watcher = imports.watcher;
|
||||
var prefs = imports.preferences;
|
||||
var alert = imports["dialog.alert"].show;
|
||||
var question = imports["dialog.question"].show;
|
||||
var fsCache = imports["fs.cache"];
|
||||
var confirmRemove = imports["dialog.fileremove"].show;
|
||||
var confirmRename = imports["dialog.fileoverwrite"].show;
|
||||
|
@ -34,7 +35,7 @@ define(function(require, exports, module) {
|
|||
var TreeEditor = require("ace_tree/edit");
|
||||
var markup = require("text!./tree.xml");
|
||||
|
||||
var basename = require("path").basename;
|
||||
var join = require("path").join;
|
||||
var dirname = require("path").dirname;
|
||||
|
||||
var staticPrefix = options.staticPrefix;
|
||||
|
@ -52,7 +53,7 @@ define(function(require, exports, module) {
|
|||
});
|
||||
var emit = plugin.getEmitter();
|
||||
|
||||
var container, winFilesViewer; //UI elements
|
||||
var container, winFilesViewer; // UI elements
|
||||
var showHideScrollPos, scrollTimer;
|
||||
var tree;
|
||||
|
||||
|
@ -404,15 +405,10 @@ define(function(require, exports, module) {
|
|||
|
||||
emit("expand", { path: id });
|
||||
|
||||
if (node.justLoaded) {
|
||||
delete node.justLoaded;
|
||||
return;
|
||||
}
|
||||
|
||||
// Only save if we are not loading the tree
|
||||
if (!refreshing || loadedSettings != -1) {
|
||||
if (!node.isRoot) {
|
||||
var refresh = !refreshing && node.status == "loaded";
|
||||
var refresh = !refreshing && node.status == "loaded" && Date.now() - node.$lastReadT > 500;
|
||||
watcher.watch(id, refresh);
|
||||
|
||||
// watch children
|
||||
|
@ -424,8 +420,10 @@ define(function(require, exports, module) {
|
|||
});
|
||||
}
|
||||
|
||||
changed = true;
|
||||
settings.save();
|
||||
if (!updateSingleDirectoryChain(true, node)) {
|
||||
changed = true;
|
||||
settings.save();
|
||||
}
|
||||
}
|
||||
}, plugin);
|
||||
|
||||
|
@ -451,13 +449,29 @@ define(function(require, exports, module) {
|
|||
});
|
||||
}
|
||||
|
||||
changed = true;
|
||||
settings.save();
|
||||
if (!updateSingleDirectoryChain(false, node)) {
|
||||
changed = true;
|
||||
settings.save();
|
||||
}
|
||||
}, plugin);
|
||||
|
||||
function abortNoStorage() {
|
||||
if (!c9.has(c9.STORAGE))
|
||||
return false;
|
||||
|
||||
function updateSingleDirectoryChain(isExpand, node) {
|
||||
if (!node.children || node.children.length !== 1)
|
||||
return;
|
||||
var child = node.children[0];
|
||||
if (!child || !child.isFolder || child.$depth > 0xff)
|
||||
return;
|
||||
if (fsCache.isFileHidden(child.path))
|
||||
return;
|
||||
if (isExpand && !child.isOpen) {
|
||||
expandNode(child);
|
||||
return true;
|
||||
}
|
||||
else if (!isExpand && child.isOpen) {
|
||||
updateSingleDirectoryChain(false, child);
|
||||
delete expandedList[child.path];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Rename
|
||||
|
@ -479,34 +493,58 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
var node = e.node;
|
||||
var name = e.value;
|
||||
var name = e.value.trim();
|
||||
|
||||
// check for a path with the same name, which is not allowed to rename to:
|
||||
var path = node.path;
|
||||
var newpath = path.replace(/[^\/]+$/, name);
|
||||
var newpath = join(path, "..", name);
|
||||
|
||||
// No point in renaming when the name is the same
|
||||
if (basename(path) == name)
|
||||
if (path == newpath)
|
||||
return;
|
||||
|
||||
// Returning false from this function will cancel the rename. We do this
|
||||
// when the name to which the file is to be renamed contains invalid
|
||||
// characters
|
||||
if (/[\\\/\n\r]/.test(name)) {
|
||||
// todo is this still needed?
|
||||
|
||||
var m = /([\0\\\n\r])/.exec(name) || c9.platform == "win32" && /([\\:*?"<>|])/.exec(name);
|
||||
if (m) {
|
||||
showError(
|
||||
"Could not rename to '" + ui.htmlentities(name)
|
||||
+ "'. Names can only contain alfanumeric characters, space, . (dot)"
|
||||
+ ", - and _ (underscore). Use the terminal to rename to other names."
|
||||
"Invalid character '" + m[0] + "' in '" + name + "'"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
fs.rename(path, newpath, {}, function(err, success) { });
|
||||
// renaming to hidden file can be confusing if one doesn't know about hidden files
|
||||
if (fsCache.isFileHidden(newpath) && !settings.getBool("user/projecttree/@showhidden")) {
|
||||
settings.set("user/projecttree/@showhidden", true);
|
||||
changed = true;
|
||||
fsCache.showHidden = true;
|
||||
refresh(true, function(){});
|
||||
}
|
||||
|
||||
emit("rename", { path: newpath, oldpath: path });
|
||||
if (dirname(newpath) != dirname(path)) {
|
||||
tree.edit.$lastAce && tree.edit.$lastAce.blur(); // TODO this shouldn't be needed when apf focus works
|
||||
question(
|
||||
"Confirm move to a new folder",
|
||||
"move '" + e.oldValue + "' to \n" +
|
||||
"'" + dirname(newpath) + "'?",
|
||||
"",
|
||||
doRename
|
||||
);
|
||||
} else {
|
||||
doRename();
|
||||
}
|
||||
|
||||
return false;
|
||||
function doRename() {
|
||||
fs.rename(path, newpath, {}, function(err, success) {
|
||||
if (err) {
|
||||
var message = err.message;
|
||||
if (err.code == "EEXIST")
|
||||
message = "File " + path + " already exists.";
|
||||
return showError(message);
|
||||
}
|
||||
if (dirname(newpath) != dirname(path))
|
||||
expandAndSelect(newpath);
|
||||
});
|
||||
emit("rename", { path: newpath, oldpath: path });
|
||||
}
|
||||
}, plugin);
|
||||
|
||||
// Context Menu
|
||||
|
@ -977,7 +1015,7 @@ define(function(require, exports, module) {
|
|||
}
|
||||
else {
|
||||
var node = fsCache.findNode(path);
|
||||
if (node) //Otherwise orphan-append will pick it up
|
||||
if (node) // Otherwise orphan-append will pick it up
|
||||
expandNode(node);
|
||||
}
|
||||
|
||||
|
@ -1045,14 +1083,14 @@ define(function(require, exports, module) {
|
|||
if (typeof node == "string")
|
||||
node = fsCache.findNode(node, "refresh");
|
||||
|
||||
if (node && !node.isFolder)
|
||||
node = node.parent;
|
||||
if (node && node.status === "loaded") {
|
||||
tree.provider.setAttribute(node, "status", "pending");
|
||||
node.children = null;
|
||||
}
|
||||
});
|
||||
|
||||
//c9.dispatchEvent("track_action", { type: "reloadtree" });
|
||||
|
||||
loadProjectTree(false, function(err) {
|
||||
var expandedNodes = Object.keys(expandedList);
|
||||
expandedList = {};
|
||||
|
@ -1067,7 +1105,7 @@ define(function(require, exports, module) {
|
|||
callback(err);
|
||||
tree.provider.on("changeScrollTop", scrollHandler);
|
||||
|
||||
emit("refreshComplete")
|
||||
emit("refreshComplete");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1100,6 +1138,7 @@ define(function(require, exports, module) {
|
|||
function expandAndSelect(path_or_node) {
|
||||
var node = findNode(path_or_node);
|
||||
expand(node, function(){
|
||||
refreshing = false;
|
||||
tree.select(node);
|
||||
scrollToSelection();
|
||||
});
|
||||
|
@ -1212,10 +1251,12 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
function select(path_or_node) {
|
||||
refreshing = false;
|
||||
tree.select(findNode(path_or_node));
|
||||
}
|
||||
|
||||
function selectList(list) {
|
||||
refreshing = false;
|
||||
tree.selection.setSelection(list.map(function(n) {
|
||||
return findNode(n);
|
||||
}));
|
||||
|
@ -1293,6 +1334,9 @@ define(function(require, exports, module) {
|
|||
|
||||
callback(err, data);
|
||||
});
|
||||
var node = fsCache.findNode(newpath, "expand");
|
||||
if (node)
|
||||
expandAndSelect(node);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ apf.codebox = function(struct, tagName) {
|
|||
this.value = "";
|
||||
|
||||
this.$draw = function(){
|
||||
//Build Main Skin
|
||||
// Build Main Skin
|
||||
this.$ext = this.$getExternal();
|
||||
this.$input = this.$getLayoutNode("main", "input", this.$ext);
|
||||
this.$button = this.$getLayoutNode("main", "button", this.$ext);
|
||||
|
@ -87,28 +87,28 @@ apf.codebox = function(struct, tagName) {
|
|||
this.$editor = this.ace = ace;
|
||||
ace.renderer.setPadding(2);
|
||||
this.ace.codebox = this;
|
||||
|
||||
ace.on("focus", function() {
|
||||
dom.removeCssClass(ace.codebox.$ext, "tb_textboxInitial");
|
||||
|
||||
if (ace.renderer.initialMessageNode) {
|
||||
|
||||
var checkInitial = function() {
|
||||
var value = ace.getValue();
|
||||
if (value && ace.renderer.initialMessageNode) {
|
||||
dom.removeCssClass(ace.container, "ace_initialMsg");
|
||||
ace.renderer.scroller.removeChild(ace.renderer.initialMessageNode);
|
||||
ace.renderer.initialMessageNode = null;
|
||||
}
|
||||
});
|
||||
else if (!value && !ace.renderer.initialMessageNode) {
|
||||
dom.addCssClass(ace.container, "ace_initialMsg");
|
||||
var el = document.createElement("div");
|
||||
el.className = "tb_textboxInitialMsg";
|
||||
el.textContent = ace.codebox["initial-message"] || "";
|
||||
ace.renderer.initialMessageNode = el;
|
||||
ace.renderer.scroller.appendChild(ace.renderer.initialMessageNode);
|
||||
}
|
||||
|
||||
};
|
||||
ace.on("input", checkInitial);
|
||||
|
||||
function onBlur() {
|
||||
if (ace.$isFocused || ace.session.getValue())
|
||||
return;
|
||||
dom.addCssClass(ace.codebox.$ext, "tb_textboxInitial");
|
||||
|
||||
if (ace.renderer.initialMessageNode)
|
||||
return;
|
||||
ace.renderer.initialMessageNode = document.createTextNode(ace.codebox["initial-message"] || "");
|
||||
ace.renderer.scroller.appendChild(ace.renderer.initialMessageNode);
|
||||
}
|
||||
ace.on("blur", onBlur);
|
||||
setTimeout(onBlur, 100);
|
||||
setTimeout(checkInitial, 100);
|
||||
|
||||
// todo should we do this here?
|
||||
// ace.on("resize", function(){apf.layout.forceResize();});
|
||||
|
||||
|
@ -181,6 +181,7 @@ apf.codebox = function(struct, tagName) {
|
|||
new MultiSelect(editor);
|
||||
editor.session.setUndoManager(new UndoManager());
|
||||
|
||||
editor.setOption("indentedSoftWrap", false);
|
||||
editor.setHighlightActiveLine(false);
|
||||
editor.setShowPrintMargin(false);
|
||||
editor.renderer.setShowGutter(false);
|
||||
|
|
|
@ -481,14 +481,16 @@ define(function(require, exports, module) {
|
|||
}
|
||||
break;
|
||||
default:
|
||||
if ("value" in item)
|
||||
el.lastChild.setAttribute('value', item.value);
|
||||
if ("onclick" in item)
|
||||
el.lastChild.onclick = item.onclick;
|
||||
if ("visible" in item)
|
||||
el.lastChild.setAttribute("visible", item.visible)
|
||||
if ("zindex" in item)
|
||||
el.lastChild.setAttribute("zindex", item.zindex)
|
||||
// supported attributes
|
||||
var validAttributes = /^(value|visible|zindex|disabled|caption|tooltip|command|class|icon|src|submenu)$/;
|
||||
Object.keys(item).forEach(function(key) {
|
||||
// Check for onclick explictly
|
||||
if (key === "onclick")
|
||||
return el.onclick = item.onclick;
|
||||
// Check for attributes we know exist and will directly set
|
||||
if (validAttributes.test(key))
|
||||
return el.setAttribute(key, item[key]);
|
||||
});
|
||||
break;
|
||||
}
|
||||
})
|
||||
|
|
|
@ -947,8 +947,10 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
function show(x, y, type) {
|
||||
if (type == "context")
|
||||
y++;
|
||||
if (type == "context") {
|
||||
x += 2;
|
||||
y += 2;
|
||||
}
|
||||
lastCoords = { x : x, y : y };
|
||||
aml.display(x, y);
|
||||
}
|
||||
|
@ -967,7 +969,7 @@ define(function(require, exports, module) {
|
|||
checkItems.call(this, e);
|
||||
},
|
||||
"onitemclick" : function(e) {
|
||||
emit("itemclick", { value : e.value });
|
||||
emit("itemclick", { value : e.value, item: e.relatedNode });
|
||||
}
|
||||
});
|
||||
aml.cloud9menu = plugin;
|
||||
|
|
|
@ -124,7 +124,7 @@ define(function(require, module, exports) {
|
|||
"list", "tab", "textbox", "textarea", "radiobutton", "checkbox", "page",
|
||||
"splitter", "hsplitbox", "vsplitbox", "group", "img", "label", "spinner",
|
||||
"dropdown", "BindingColumnRule", "datagrid", "hbox", "vbox", "colorbox",
|
||||
"frame", "password", "modalwindow", "filler", "splitbutton"].forEach(function(tag) {
|
||||
"frame", "password", "modalwindow", "filler", "splitbutton", "codebox"].forEach(function(tag) {
|
||||
plugin[tag] = function(struct) {
|
||||
return new apf[tag](struct);
|
||||
};
|
||||
|
|
|
@ -34,7 +34,7 @@ define(function(require, exports, module) {
|
|||
var acetree;
|
||||
var model;
|
||||
var redirectEvents;
|
||||
var filterRoot;
|
||||
var fRoot;
|
||||
var meta = {};
|
||||
var dataType = options.model ? "object" : options.dataType;
|
||||
var excludedEvents = {
|
||||
|
@ -251,6 +251,16 @@ define(function(require, exports, module) {
|
|||
*/
|
||||
get enableDragdrop(){ return acetree.getOption("enableDragDrop"); },
|
||||
set enableDragdrop(value){ acetree.setOption("enableDragDrop", value); },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get enableVariableHeight(){ return model.getItemHeight; },
|
||||
set enableVariableHeight(value){
|
||||
if (!value) throw new Error("Unable to remove variable height");
|
||||
|
||||
var variableHeightRowMixin = model.constructor.variableHeightRowMixin;
|
||||
variableHeightRowMixin.apply(model);
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -296,18 +306,20 @@ define(function(require, exports, module) {
|
|||
set filterKeyword(value){
|
||||
model.keyword = value;
|
||||
if (!model.keyword) {
|
||||
filterRoot = null;
|
||||
fRoot = null;
|
||||
model.reKeyword = null;
|
||||
model.setRoot(model.cachedRoot);
|
||||
}
|
||||
else {
|
||||
model.reKeyword = new RegExp("("
|
||||
+ util.escapeRegExp(model.keyword) + ")", 'i');
|
||||
filterRoot = search.treeSearch(
|
||||
model.cachedRoot.items || model.cachedRoot,
|
||||
fRoot = search.treeSearch(
|
||||
model.filterRoot
|
||||
? model.filterRoot.items || model.filterRoot
|
||||
: model.cachedRoot.items || model.cachedRoot,
|
||||
model.keyword, model.filterCaseInsensitive,
|
||||
null, null, model.indexProperty);
|
||||
model.setRoot(filterRoot);
|
||||
null, null, model.filterProperty);
|
||||
model.setRoot(fRoot);
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
@ -320,6 +332,11 @@ define(function(require, exports, module) {
|
|||
*/
|
||||
get filterProperty(){ return model.filterProperty; },
|
||||
set filterProperty(value){ model.filterProperty = value; },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get filterRoot(){ return model.filterRoot; },
|
||||
set filterRoot(value){ model.filterRoot = value; },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -394,11 +411,21 @@ define(function(require, exports, module) {
|
|||
*/
|
||||
get getClassName(){ return model.getClassName; },
|
||||
set getClassName(fn){ model.getClassName = fn; },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get getTooltipText(){ return model.getTooltipText; },
|
||||
set getTooltipText(fn){ model.getTooltipText = fn; },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get getIndex(){ return model.getIndex; },
|
||||
set getIndex(fn){ model.getIndex = fn; },
|
||||
/**
|
||||
*
|
||||
*/
|
||||
get getItemHeight(){ return model.getItemHeight; },
|
||||
set getItemHeight(fn){ model.getItemHeight = fn; },
|
||||
|
||||
// Events
|
||||
_events: [
|
||||
|
@ -494,7 +521,10 @@ define(function(require, exports, module) {
|
|||
*/
|
||||
setRoot: function(root){
|
||||
model.cachedRoot = root;
|
||||
return model.setRoot(root);
|
||||
if (model.keyword)
|
||||
plugin.filterKeyword = model.keyword;
|
||||
else
|
||||
return model.setRoot(root);
|
||||
},
|
||||
/**
|
||||
*
|
||||
|
@ -538,8 +568,8 @@ define(function(require, exports, module) {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
scrollIntoView: function(anchor, lead, offset){
|
||||
return acetree.renderer.scrollCaretIntoView(anchor, lead, offset);
|
||||
scrollIntoView: function(anchor, offset){
|
||||
return acetree.renderer.scrollCaretIntoView(anchor, offset);
|
||||
},
|
||||
/**
|
||||
*
|
||||
|
@ -585,7 +615,10 @@ define(function(require, exports, module) {
|
|||
*
|
||||
*/
|
||||
refresh: function(){
|
||||
model.setRoot(filterRoot || plugin.root);
|
||||
if (model.keyword)
|
||||
plugin.filterKeyword = model.keyword;
|
||||
else
|
||||
model.setRoot(plugin.root);
|
||||
},
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
define(function(require, exports, module) {
|
||||
|
||||
function timeago(timestamp) {
|
||||
if (timestamp instanceof Date) {
|
||||
return inWords(timestamp);
|
||||
} else if (typeof timestamp === "string") {
|
||||
return inWords(parse(timestamp));
|
||||
} else if (typeof timestamp === "number") {
|
||||
return inWords(new Date(timestamp));
|
||||
} else {
|
||||
return timeagoElement(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
var settings = {
|
||||
refreshMillis: 60000,
|
||||
allowFuture: false,
|
||||
strings: {
|
||||
prefixAgo: null,
|
||||
prefixFromNow: null,
|
||||
suffixAgo: "ago",
|
||||
suffixFromNow: "from now",
|
||||
seconds: "less than a minute",
|
||||
minute: "about a minute",
|
||||
minutes: "%d minutes",
|
||||
hour: "about an hour",
|
||||
hours: "about %d hours",
|
||||
day: "a day",
|
||||
days: "%d days",
|
||||
month: "about a month",
|
||||
months: "%d months",
|
||||
year: "about a year",
|
||||
years: "%d years",
|
||||
wordSeparator: " ",
|
||||
numbers: []
|
||||
}
|
||||
};
|
||||
function distanceInWords(distanceMillis) {
|
||||
var $l = settings.strings;
|
||||
var prefix = $l.prefixAgo;
|
||||
var suffix = $l.suffixAgo;
|
||||
if (settings.allowFuture) {
|
||||
if (distanceMillis < 0) {
|
||||
prefix = $l.prefixFromNow;
|
||||
suffix = $l.suffixFromNow;
|
||||
}
|
||||
}
|
||||
|
||||
var seconds = Math.abs(distanceMillis) / 1000;
|
||||
var minutes = seconds / 60;
|
||||
var hours = minutes / 60;
|
||||
var days = hours / 24;
|
||||
var years = days / 365;
|
||||
|
||||
function substitute(stringOrFunction, number) {
|
||||
var string = typeof stringOrFunction === "function" ? stringOrFunction(number, distanceMillis) : stringOrFunction;
|
||||
var value = ($l.numbers && $l.numbers[number]) || number;
|
||||
return string.replace(/%d/i, value);
|
||||
}
|
||||
|
||||
var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
|
||||
seconds < 90 && substitute($l.minute, 1) ||
|
||||
minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
|
||||
minutes < 90 && substitute($l.hour, 1) ||
|
||||
hours < 24 && substitute($l.hours, Math.round(hours)) ||
|
||||
hours < 42 && substitute($l.day, 1) ||
|
||||
days < 30 && substitute($l.days, Math.round(days)) ||
|
||||
days < 45 && substitute($l.month, 1) ||
|
||||
days < 365 && substitute($l.months, Math.round(days / 30)) ||
|
||||
years < 1.5 && substitute($l.year, 1) ||
|
||||
substitute($l.years, Math.round(years));
|
||||
|
||||
var separator = $l.wordSeparator || "";
|
||||
if ($l.wordSeparator === undefined) { separator = " "; }
|
||||
return [prefix, words, suffix].filter(function(s) { return s; })
|
||||
.map(function(s){ return s.trim(); })
|
||||
.join(separator);
|
||||
}
|
||||
function parse(iso8601) {
|
||||
var s = iso8601.trim();
|
||||
s = s.replace(/\.\d+/,""); // remove milliseconds
|
||||
s = s.replace(/-/,"/").replace(/-/,"/");
|
||||
s = s.replace(/T/," ").replace(/Z/," UTC");
|
||||
s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
|
||||
return new Date(s);
|
||||
}
|
||||
function datetime(elem) {
|
||||
var iso8601 = isTime(elem) ? elem.getAttribute("datetime") : elem.getAttribute("title");
|
||||
return parse(iso8601);
|
||||
}
|
||||
function isTime(elem) {
|
||||
return elem.tagName.toLowerCase() === "time";
|
||||
}
|
||||
|
||||
function timeagoElement(elem) {
|
||||
refresh(elem);
|
||||
if (settings.refreshMillis > 0)
|
||||
setInterval(refresh.bind(null, elem), settings.refreshMillis);
|
||||
}
|
||||
|
||||
function refresh(elem) {
|
||||
var datetime = prepareDateTime(elem);
|
||||
if (!isNaN(datetime))
|
||||
elem.textContent = inWords(datetime);
|
||||
}
|
||||
|
||||
function prepareDateTime(elem) {
|
||||
var timeagoAttr = elem.getAttribute("timeago");
|
||||
if (timeagoAttr)
|
||||
return new Date(timeagoAttr);
|
||||
var data = datetime(elem);
|
||||
elem.setAttribute("timeago", data);
|
||||
var text = elem.textContent.trim();
|
||||
if (text.length > 0 && !(isTime(elem) && elem.title))
|
||||
elem.title = text;
|
||||
return data;
|
||||
}
|
||||
|
||||
function inWords(date) {
|
||||
return distanceInWords(distance(date));
|
||||
}
|
||||
|
||||
function distance(date) {
|
||||
return (new Date().getTime() - date.getTime());
|
||||
}
|
||||
|
||||
// fix for IE6 suckage
|
||||
document.createElement("abbr");
|
||||
document.createElement("time");
|
||||
|
||||
module.exports = timeago;
|
||||
});
|
|
@ -254,6 +254,7 @@ function main(options, imports, register) {
|
|||
"plugins/c9.ide.language/worker",
|
||||
"plugins/c9.ide.language.generic/local_completer",
|
||||
"plugins/c9.ide.language.generic/snippet_completer",
|
||||
"plugins/c9.ide.language.generic/mode_completer",
|
||||
"plugins/c9.ide.language.generic/open_files_local_completer",
|
||||
"plugins/c9.ide.language.generic/simple/make",
|
||||
"plugins/c9.ide.language.generic/simple/shell",
|
||||
|
|
|
@ -76,6 +76,8 @@ function main(options, imports, register) {
|
|||
var parts = e.split(" ");
|
||||
var id = parts[1];
|
||||
var etag = parts[0];
|
||||
if (!id || /^https?:\/\//.test(id))
|
||||
return q.oneDone();
|
||||
var path = resolveModulePath(id, req.pathConfig.pathMap);
|
||||
|
||||
if (path == id && !/^(\/|\w:)/.test(path)) {
|
||||
|
|
|
@ -225,6 +225,10 @@ define(function(require, exports, module) {
|
|||
callback(fatalError(res.error.message, "dashboard"));
|
||||
return;
|
||||
}
|
||||
else if (err.code == 404) {
|
||||
callback(fatalError("This workspace no longer appears to exist or failed to be created.", "dashboard"));
|
||||
return;
|
||||
}
|
||||
else if (err.code === 428 && res.error) {
|
||||
emit("restore", {
|
||||
projectState: res.error.projectState,
|
||||
|
@ -251,6 +255,13 @@ define(function(require, exports, module) {
|
|||
}, 10000);
|
||||
return;
|
||||
}
|
||||
else if (err.code == 503) {
|
||||
// service unavailable
|
||||
setTimeout(function() {
|
||||
tryNext(i);
|
||||
}, res.error.retryIn || 15000);
|
||||
return;
|
||||
}
|
||||
else if (err.code === 500 && res && res.error && res.error.cause) {
|
||||
return callback(res.error.cause.message);
|
||||
}
|
||||
|
|
|
@ -253,7 +253,7 @@ define(function(require, exports, module) {
|
|||
err.message = "SSH permission denied. Please review your workspace configuration.";
|
||||
return showAlert("Workspace Error", "Unable to access your workspace", err.message, function() {
|
||||
window.location = dashboardUrl;
|
||||
});
|
||||
}, { yes: "Return to dashboard" });
|
||||
case "reload":
|
||||
lastError = showError(err.message + ". Please reload this window.", -1);
|
||||
setTimeout(function() {
|
||||
|
|
|
@ -199,6 +199,8 @@ require([
|
|||
c.exec = function(name) {
|
||||
commands[name].exec();
|
||||
};
|
||||
c.getPrettyHotkey = function(name) { return "" };
|
||||
c.getHotkey = function(name) { return "" };
|
||||
c.getExceptionList = function(){ return []; };
|
||||
|
||||
return c;
|
||||
|
|
|
@ -96,7 +96,7 @@ updateNodeModules() {
|
|||
echo "${magenta}--- Running npm install --------------------------------------------${resetColor}"
|
||||
safeInstall(){
|
||||
deps=(`"$NODE" -e 'console.log(Object.keys(require("./package.json").dependencies).join(" "))'`)
|
||||
for m in $deps; do echo $m;
|
||||
for m in ${deps[@]}; do echo $m;
|
||||
"$NPM" install --loglevel warn $m || true
|
||||
done
|
||||
}
|
||||
|
|
|
@ -85,7 +85,8 @@ function main(config, settings, options, callback) {
|
|||
findAllAndPurge: function(maxVfsAge, callback) {
|
||||
callback(null, [{}]);
|
||||
}
|
||||
}
|
||||
},
|
||||
"User": {}
|
||||
},
|
||||
"redis": {},
|
||||
"health": {
|
||||
|
|
Ładowanie…
Reference in New Issue