Merge remote-tracking branch 'origin/master' into profile-001-1-create-project

Conflicts:
	configs/profile.js
	npm-shrinkwrap.json
	plugins/c9.styleguide/lib/flex.less
This commit is contained in:
Fabian Jakobs 2015-05-04 10:42:05 +00:00
commit 5e358a2840
55 changed files with 1837 additions and 778 deletions

View File

@ -56,7 +56,8 @@ return [
packagePath: "./c9.ide.auth/auth",
accessToken: "token",
ideBaseUrl: "",
apiUrl: APIURL
apiUrl: APIURL,
cli: true
// userId: process.env.C9_USER
},
{
@ -119,7 +120,8 @@ return [
local: true,
home: process.env.HOME,
setStatus: function(){},
location: ""
location: "",
platform: process.platform,
},
error_handler: {
log: function(){}

View File

@ -98,7 +98,7 @@ module.exports = function(options) {
packagePath: "plugins/c9.ide.plugins/debug"
},
{
packagePath: "plugins/c9.ide.plugins/market"
packagePath: "plugins/c9.ide.plugins/packages"
},
{
packagePath: "plugins/c9.ide.plugins/test",
@ -456,7 +456,7 @@ module.exports = function(options) {
{
packagePath: "plugins/c9.ide.layout.classic/preload",
themePrefix: options.themePrefix,
defaultTheme: "dark"
defaultTheme: options.defaultTheme || "dark"
},
{
packagePath: "plugins/c9.ide.tree/tree",
@ -618,7 +618,6 @@ module.exports = function(options) {
},
{
packagePath: "plugins/c9.cli.bridge/bridge",
port: 17123,
startBridge: options.startBridge
},
{

View File

@ -423,6 +423,12 @@ exports.commands = [{
exec: function() {},
passEvent: true,
readOnly: true
}, {
name: "copy",
exec: function(editor) {
// placeholder for replay macro
},
readOnly: true
},
// commands disabled in readOnly mode
@ -439,6 +445,12 @@ exports.commands = [{
},
scrollIntoView: "cursor",
multiSelectAction: "forEach"
}, {
name: "paste",
exec: function(editor, text) {
editor.$handlePaste(text);
},
scrollIntoView: "cursor"
}, {
name: "removeline",
bindKey: bindKey("Ctrl-D", "Command-D"),

View File

@ -132,7 +132,6 @@ var SearchHighlight = require("./search_highlight").SearchHighlight;
//}
/**
*
* Sets up a new `EditSession` and associates it with the given `Document` and `TextMode`.
* @param {Document | String} text [If `text` is a `Document`, it associates the `EditSession` with it. Otherwise, a new `Document` is created, with the initial text]{: #textParam}
* @param {TextMode} mode [The inital language mode to use for the document]{: #modeParam}
@ -149,9 +148,10 @@ var EditSession = function(text, mode) {
this.$undoSelect = true;
this.$foldData = [];
this.id = "session" + EditSession.$uid;
this.$foldData.toString = function() {
return this.join("\n");
}
};
this.on("changeFold", this.onChangeFold.bind(this));
this.$onChange = this.onChange.bind(this);
@ -167,6 +167,8 @@ var EditSession = function(text, mode) {
};
EditSession.$uid = 0;
(function() {
oop.implement(this, EventEmitter);
@ -255,15 +257,17 @@ var EditSession = function(text, mode) {
this.$resetRowCache(delta.start.row);
var removedFolds = this.$updateInternalDataOnChange(delta);
if (!this.$fromUndo && this.$undoManager && !delta.ignore) {
this.$deltasDoc.push(delta);
if (removedFolds && removedFolds.length != 0) {
this.$deltasFold.push({
if (!this.$fromUndo && this.$undoManager) {
if (removedFolds && removedFolds.length) {
this.$undoManager.add({
action: "removeFolds",
folds: removedFolds
});
}, this.mergeUndoDeltas);
this.mergeUndoDeltas = true;
}
this.$undoManager.add(delta, this.mergeUndoDeltas);
this.mergeUndoDeltas = true;
this.$informUndoManager.schedule();
}
@ -281,9 +285,6 @@ var EditSession = function(text, mode) {
this.selection.moveTo(0, 0);
this.$resetRowCache(0);
this.$deltas = [];
this.$deltasDoc = [];
this.$deltasFold = [];
this.setUndoManager(this.$undoManager);
this.getUndoManager().reset();
};
@ -364,53 +365,27 @@ var EditSession = function(text, mode) {
};
/**
* Sets the undo manager.
* @param {UndoManager} undoManager The new undo manager
*
*
**/
* Sets the undo manager.
* @param {UndoManager} undoManager The new undo manager
*
*
**/
this.setUndoManager = function(undoManager) {
this.$undoManager = undoManager;
this.$deltas = [];
this.$deltasDoc = [];
this.$deltasFold = [];
if (this.$informUndoManager)
this.$informUndoManager.cancel();
if (undoManager) {
var self = this;
undoManager.addSession(this);
this.$syncInformUndoManager = function() {
self.$informUndoManager.cancel();
if (self.$deltasFold.length) {
self.$deltas.push({
group: "fold",
deltas: self.$deltasFold
});
self.$deltasFold = [];
}
if (self.$deltasDoc.length) {
self.$deltas.push({
group: "doc",
deltas: self.$deltasDoc
});
self.$deltasDoc = [];
}
if (self.$deltas.length > 0) {
undoManager.execute({
action: "aceupdate",
args: [self.$deltas, self],
merge: self.mergeUndoDeltas
});
}
self.mergeUndoDeltas = false;
self.$deltas = [];
};
this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager);
} else {
this.$syncInformUndoManager = function() {};
}
};
@ -425,7 +400,11 @@ var EditSession = function(text, mode) {
this.$defaultUndoManager = {
undo: function() {},
redo: function() {},
reset: function() {}
reset: function() {},
add: function() {},
addSelection: function() {},
startNewGroup: function() {},
addSession: function() {},
};
/**
@ -1147,14 +1126,14 @@ var EditSession = function(text, mode) {
};
/**
* Removes a range of full lines. This method also triggers the `'change'` event.
* @param {Number} firstRow The first row to be removed
* @param {Number} lastRow The last row to be removed
* @returns {[String]} Returns all the removed lines.
*
* @related Document.removeFullLines
*
**/
* Removes a range of full lines. This method also triggers the `'change'` event.
* @param {Number} firstRow The first row to be removed
* @param {Number} lastRow The last row to be removed
* @returns {[String]} Returns all the removed lines.
*
* @related Document.removeFullLines
*
**/
this.removeFullLines = function(firstRow, lastRow){
return this.doc.removeFullLines(firstRow, lastRow);
};
@ -1163,34 +1142,30 @@ var EditSession = function(text, mode) {
* Reverts previous changes to your document.
* @param {Array} deltas An array of previous changes
* @param {Boolean} dontSelect [If `true`, doesn't select the range of where the change occured]{: #dontSelect}
*
*
* @returns {Range}
**/
**/
this.undoChanges = function(deltas, dontSelect) {
if (!deltas.length)
return;
this.$fromUndo = true;
var lastUndoRange = null;
for (var i = deltas.length - 1; i != -1; i--) {
var delta = deltas[i];
if (delta.group == "doc") {
this.doc.revertDeltas(delta.deltas);
lastUndoRange =
this.$getUndoSelection(delta.deltas, true, lastUndoRange);
} else {
delta.deltas.forEach(function(foldDelta) {
this.addFolds(foldDelta.folds);
}, this);
if (delta.action == "insert" || delta.action == "remove") {
this.doc.revertDelta(delta);
} else if (delta.folds) {
this.addFolds(delta.folds);
}
}
if (!dontSelect) {
// console.log(deltas.selectionBefore + "uuu")
if (deltas.selectionBefore)
this.selection.fromJSON(deltas.selectionBefore);
else
this.selection.setRange(this.$getUndoSelection(deltas, true));
}
this.$fromUndo = false;
lastUndoRange &&
this.$undoSelect &&
!dontSelect &&
this.selection.setSelectionRange(lastUndoRange);
return lastUndoRange;
};
/**
@ -1198,41 +1173,39 @@ var EditSession = function(text, mode) {
* @param {Array} deltas An array of previous changes
* @param {Boolean} dontSelect {:dontSelect}
*
*
* @returns {Range}
**/
**/
this.redoChanges = function(deltas, dontSelect) {
if (!deltas.length)
return;
this.$fromUndo = true;
var lastUndoRange = null;
for (var i = 0; i < deltas.length; i++) {
var delta = deltas[i];
if (delta.group == "doc") {
this.doc.applyDeltas(delta.deltas);
lastUndoRange =
this.$getUndoSelection(delta.deltas, false, lastUndoRange);
if (delta.action == "insert" || delta.action == "remove") {
this.doc.applyDelta(delta);
}
}
if (!dontSelect) {
if (deltas.selectionAfter)
this.selection.fromJSON(deltas.selectionAfter);
else
this.selection.setRange(this.$getUndoSelection(deltas, false));
}
this.$fromUndo = false;
lastUndoRange &&
this.$undoSelect &&
!dontSelect &&
this.selection.setSelectionRange(lastUndoRange);
return lastUndoRange;
};
/**
* Enables or disables highlighting of the range where an undo occured.
* @param {Boolean} enable If `true`, selects the range of the reinserted change
*
**/
*
**/
this.setUndoSelect = function(enable) {
this.$undoSelect = enable;
};
this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {
this.$getUndoSelection = function(deltas, isUndo) {
function isInsert(delta) {
return isUndo ? delta.action !== "insert" : delta.action === "insert";
}
@ -1268,60 +1241,36 @@ var EditSession = function(text, mode) {
lastDeltaIsInsert = false;
}
}
// Check if this range and the last undo range has something in common.
// If true, merge the ranges.
if (lastUndoRange != null) {
if (Range.comparePoints(lastUndoRange.start, range.start) === 0) {
lastUndoRange.start.column += range.end.column - range.start.column;
lastUndoRange.end.column += range.end.column - range.start.column;
}
var cmp = lastUndoRange.compareRange(range);
if (cmp == 1) {
range.setStart(lastUndoRange.start);
} else if (cmp == -1) {
range.setEnd(lastUndoRange.end);
}
}
return range;
};
/**
* Replaces a range in the document with the new `text`.
*
* @param {Range} range A specified Range to replace
* @param {String} text The new text to use as a replacement
* @returns {Object} An object containing the final row and column, like this:
* ```
* {row: endRow, column: 0}
* ```
* If the text and range are empty, this function returns an object containing the current `range.start` value.
* If the text is the exact same as what currently exists, this function returns an object containing the current `range.end` value.
*
*
*
* @related Document.replace
*
*
**/
* Replaces a range in the document with the new `text`.
*
* @param {Range} range A specified Range to replace
* @param {String} text The new text to use as a replacement
* @returns {Object} An object containing the final row and column, like this:
* ```
* {row: endRow, column: 0}
* ```
* If the text and range are empty, this function returns an object containing the current `range.start` value.
* If the text is the exact same as what currently exists, this function returns an object containing the current `range.end` value.
*
* @related Document.replace
**/
this.replace = function(range, text) {
return this.doc.replace(range, text);
};
/**
* Moves a range of text from the given range to the given position. `toPosition` is an object that looks like this:
* Moves a range of text from the given range to the given position. `toPosition` is an object that looks like this:
* ```json
* { row: newRowLocation, column: newColumnLocation }
* { row: newRowLocation, column: newColumnLocation }
* ```
* @param {Range} fromRange The range of text you want moved within the document
* @param {Object} toPosition The location (row and column) where you want to move the text to
* @returns {Range} The new range where the text was moved to.
*
*
*
**/
**/
this.moveText = function(fromRange, toPosition, copy) {
var text = this.getTextRange(fromRange);
var folds = this.getFoldsInRange(fromRange);
@ -1365,15 +1314,15 @@ var EditSession = function(text, mode) {
};
/**
* Indents all the rows, from `startRow` to `endRow` (inclusive), by prefixing each row with the token in `indentString`.
*
* If `indentString` contains the `'\t'` character, it's replaced by whatever is defined by [[EditSession.getTabString `getTabString()`]].
* @param {Number} startRow Starting row
* @param {Number} endRow Ending row
* @param {String} indentString The indent token
*
*
**/
* Indents all the rows, from `startRow` to `endRow` (inclusive), by prefixing each row with the token in `indentString`.
*
* If `indentString` contains the `'\t'` character, it's replaced by whatever is defined by [[EditSession.getTabString `getTabString()`]].
* @param {Number} startRow Starting row
* @param {Number} endRow Ending row
* @param {String} indentString The indent token
*
*
**/
this.indentRows = function(startRow, endRow, indentString) {
indentString = indentString.replace(/\t/g, this.getTabString());
for (var row=startRow; row<=endRow; row++)
@ -1381,11 +1330,10 @@ var EditSession = function(text, mode) {
};
/**
* Outdents all the rows defined by the `start` and `end` properties of `range`.
* @param {Range} range A range of rows
*
*
**/
* Outdents all the rows defined by the `start` and `end` properties of `range`.
* @param {Range} range A range of rows
*
**/
this.outdentRows = function (range) {
var rowRange = range.collapseRows();
var deleteRange = new Range(0, 0, 0, 0);
@ -1443,34 +1391,34 @@ var EditSession = function(text, mode) {
return diff;
};
/**
* Shifts all the lines in the document up one, starting from `firstRow` and ending at `lastRow`.
* @param {Number} firstRow The starting row to move up
* @param {Number} lastRow The final row to move up
* @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
*
**/
* Shifts all the lines in the document up one, starting from `firstRow` and ending at `lastRow`.
* @param {Number} firstRow The starting row to move up
* @param {Number} lastRow The final row to move up
* @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
*
**/
this.moveLinesUp = function(firstRow, lastRow) {
return this.$moveLines(firstRow, lastRow, -1);
};
/**
* Shifts all the lines in the document down one, starting from `firstRow` and ending at `lastRow`.
* @param {Number} firstRow The starting row to move down
* @param {Number} lastRow The final row to move down
* @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
**/
* Shifts all the lines in the document down one, starting from `firstRow` and ending at `lastRow`.
* @param {Number} firstRow The starting row to move down
* @param {Number} lastRow The final row to move down
* @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
**/
this.moveLinesDown = function(firstRow, lastRow) {
return this.$moveLines(firstRow, lastRow, 1);
};
/**
* Duplicates all the text between `firstRow` and `lastRow`.
* @param {Number} firstRow The starting row to duplicate
* @param {Number} lastRow The final row to duplicate
* @returns {Number} Returns the number of new rows added; in other words, `lastRow - firstRow + 1`.
*
*
**/
* Duplicates all the text between `firstRow` and `lastRow`.
* @param {Number} firstRow The starting row to duplicate
* @param {Number} lastRow The final row to duplicate
* @returns {Number} Returns the number of new rows added; in other words, `lastRow - firstRow + 1`.
*
*
**/
this.duplicateLines = function(firstRow, lastRow) {
return this.$moveLines(firstRow, lastRow, 0);
};
@ -1545,8 +1493,7 @@ var EditSession = function(text, mode) {
* Sets whether or not line wrapping is enabled. If `useWrapMode` is different than the current value, the `'changeWrapMode'` event is emitted.
* @param {Boolean} useWrapMode Enable (or disable) wrap mode
*
*
**/
**/
this.setUseWrapMode = function(useWrapMode) {
if (useWrapMode != this.$useWrapMode) {
this.$useWrapMode = useWrapMode;
@ -1565,9 +1512,9 @@ var EditSession = function(text, mode) {
};
/**
* Returns `true` if wrap mode is being used; `false` otherwise.
* @returns {Boolean}
**/
* Returns `true` if wrap mode is being used; `false` otherwise.
* @returns {Boolean}
**/
this.getUseWrapMode = function() {
return this.$useWrapMode;
};
@ -1581,8 +1528,7 @@ var EditSession = function(text, mode) {
* @param {Number} min The minimum wrap value (the left side wrap)
* @param {Number} max The maximum wrap value (the right side wrap)
*
*
**/
**/
this.setWrapLimitRange = function(min, max) {
if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) {
this.$wrapLimitRange = { min: min, max: max };
@ -1594,12 +1540,12 @@ var EditSession = function(text, mode) {
};
/**
* This should generally only be called by the renderer when a resize is detected.
* @param {Number} desiredLimit The new wrap limit
* @returns {Boolean}
*
* @private
**/
* This should generally only be called by the renderer when a resize is detected.
* @param {Number} desiredLimit The new wrap limit
* @returns {Boolean}
*
* @private
**/
this.adjustWrapLimit = function(desiredLimit, $printMargin) {
var limits = this.$wrapLimitRange;
if (limits.max < 0)

43
node_modules/ace/lib/ace/editor.js generated vendored
View File

@ -111,21 +111,25 @@ var Editor = function(renderer, session) {
oop.implement(this, EventEmitter);
this.$initOperationListeners = function() {
function last(a) {return a[a.length - 1]}
this.selections = [];
this.commands.on("exec", this.startOperation.bind(this), true);
this.commands.on("afterExec", this.endOperation.bind(this), true);
this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this));
// todo: add before change events?
this.on("change", function() {
this.curOp || this.startOperation();
if (!this.curOp) {
this.startOperation();
this.curOp.selectionBefore = this.$lastSel;
}
this.curOp.docChanged = true;
}.bind(this), true);
this.on("changeSelection", function() {
this.curOp || this.startOperation();
if (!this.curOp) {
this.startOperation();
this.curOp.selectionBefore = this.$lastSel;
}
this.curOp.selectionChanged = true;
}.bind(this), true);
};
@ -144,19 +148,18 @@ var Editor = function(renderer, session) {
}
this.$opResetTimer.schedule();
this.curOp = {
this.curOp = this.session.curOp = {
command: commadEvent.command || {},
args: commadEvent.args,
scrollTop: this.renderer.scrollTop
};
// this.selections.push(this.selection.toJSON());
this.curOp.selectionBefore = this.selection.toJSON();
};
this.endOperation = function(e) {
if (this.curOp) {
if (e && e.returnValue === false)
return this.curOp = null;
return (this.curOp = null);
this._signal("beforeEndOperation");
var command = this.curOp.command;
var scrollIntoView = command && command.scrollIntoView;
@ -185,7 +188,12 @@ var Editor = function(renderer, session) {
if (scrollIntoView == "animate")
this.renderer.animateScrolling(this.curOp.scrollTop);
}
var sel = this.selection.toJSON();
this.curOp.selectionAfter = sel;
this.$lastSel = this.selection.toJSON();
// console.log(this.$lastSel+" endOP")
this.session.getUndoManager().addSelection(sel);
this.prevOp = this.curOp;
this.curOp = null;
}
@ -903,10 +911,10 @@ var Editor = function(renderer, session) {
*
**/
this.onPaste = function(text) {
// todo this should change when paste becomes a command
if (this.$readOnly)
return;
this.commands.exec("paste", this, text);
};
this.$handlePaste = function(text) {
var e = {text: text};
this._signal("paste", e);
text = e.text;
@ -927,7 +935,6 @@ var Editor = function(renderer, session) {
this.session.insert(range.start, lines[i]);
}
}
this.renderer.scrollCursorIntoView();
};
this.execCommand = function(command, args) {
@ -2487,7 +2494,7 @@ var Editor = function(renderer, session) {
* @related UndoManager.undo
**/
this.undo = function() {
this.session.getUndoManager().undo();
this.session.getUndoManager().undo(this.session);
this.renderer.scrollCursorIntoView(null, 0.5);
};
@ -2496,7 +2503,7 @@ var Editor = function(renderer, session) {
* @related UndoManager.redo
**/
this.redo = function() {
this.session.getUndoManager().redo();
this.session.getUndoManager().redo(this.session);
this.renderer.scrollCursorIntoView(null, 0.5);
};

49
node_modules/ace/lib/ace/split.js generated vendored
View File

@ -42,8 +42,6 @@ var EditSession = require("./edit_session").EditSession;
/**
* @class Split
*
*
*
**/
@ -217,14 +215,7 @@ var Split = function(container, theme, splits) {
var s = new EditSession(session.getDocument(), session.getMode());
var undoManager = session.getUndoManager();
if (undoManager) {
var undoManagerProxy = new UndoManagerProxy(undoManager, s);
s.setUndoManager(undoManagerProxy);
}
// Overwrite the default $informUndoManager function such that new delas
// aren't added to the undo manager from the new and the old session.
s.$informUndoManager = lang.delayedCall(function() { s.$deltas = []; });
s.setUndoManager(undoManager);
// Copy over 'settings' from the session.
s.setTabSize(session.getTabSize());
@ -331,43 +322,5 @@ var Split = function(container, theme, splits) {
}).call(Split.prototype);
function UndoManagerProxy(undoManager, session) {
this.$u = undoManager;
this.$doc = session;
}
(function() {
this.execute = function(options) {
this.$u.execute(options);
};
this.undo = function() {
var selectionRange = this.$u.undo(true);
if (selectionRange) {
this.$doc.selection.setSelectionRange(selectionRange);
}
};
this.redo = function() {
var selectionRange = this.$u.redo(true);
if (selectionRange) {
this.$doc.selection.setSelectionRange(selectionRange);
}
};
this.reset = function() {
this.$u.reset();
};
this.hasUndo = function() {
return this.$u.hasUndo();
};
this.hasRedo = function() {
return this.$u.hasRedo();
};
}).call(UndoManagerProxy.prototype);
exports.Split = Split;
});

View File

@ -5,9 +5,9 @@ require("ace/lib/fixoldbrowsers");
var AsyncTest = require("asyncjs").test;
var async = require("asyncjs");
var passed = 0
var failed = 0
var log = document.getElementById("log")
var passed = 0;
var failed = 0;
var log = document.getElementById("log");
var testNames = [
"ace/anchor_test",
@ -55,6 +55,7 @@ var testNames = [
"ace/snippets_test",
"ace/token_iterator_test",
"ace/tokenizer_test",
"ace/undomanager_test",
"ace/virtual_renderer_test"
];
@ -64,13 +65,30 @@ for (var i in testNames) {
html.push("<a href='?", href, "'>", href.replace(/^ace\//, "") ,"</a><br>");
}
if (location.search.indexOf("show=1") != -1) {
var VirtualRenderer = require("ace/virtual_renderer").VirtualRenderer;
require("ace/test/mockrenderer").MockRenderer = function() {
var el = document.createElement("div");
el.style.position = "fixed";
el.style.left = "20px";
el.style.top = "30px";
el.style.width = "500px";
el.style.height = "300px";
document.body.appendChild(el);
return new VirtualRenderer(el);
};
}
var nav = document.createElement("div");
nav.innerHTML = html.join("");
nav.style.cssText = "position:absolute;right:0;top:0";
document.body.appendChild(nav);
if (location.search)
testNames = location.search.substr(1).split(",")
testNames = location.search.substr(1).split(",");
var filter = location.hash.substr(1);
@ -89,7 +107,7 @@ require(testNames, function() {
test[method] = undefined;
});
}
return AsyncTest.testcase(test)
return AsyncTest.testcase(test);
}, AsyncTest.TestGenerator)
.run()
.each(function(test, next) {
@ -102,16 +120,16 @@ require(testNames, function() {
var node = document.createElement("div");
node.className = test.passed ? "passed" : "failed";
var name = test.name
var name = test.name;
if (test.suiteName)
name = test.suiteName + ": " + test.name
name = test.suiteName + ": " + test.name;
var msg = "[" + test.count + "/" + test.index + "] " + name + " " + (test.passed ? "OK" : "FAIL")
var msg = "[" + test.count + "/" + test.index + "] " + name + " " + (test.passed ? "OK" : "FAIL");
if (!test.passed) {
if (test.err.stack)
var err = test.err.stack
var err = test.err.stack;
else
var err = test.err
var err = test.err;
console.error(msg);
console.error(err);
@ -123,13 +141,13 @@ require(testNames, function() {
node.innerHTML = msg;
log.appendChild(node);
next()
next();
})
.each(function(test) {
if (test.passed)
passed += 1
passed += 1;
else
failed += 1
failed += 1;
})
.end(function() {
log.innerHTML += [
@ -140,11 +158,11 @@ require(testNames, function() {
"Total number of tests: " + (passed + failed) + "<br>",
(passed ? "Passed tests: " + passed + "<br>" : ""),
(failed ? "Failed tests: " + failed + "<br>" : "")
].join("")
].join("");
console.log("Total number of tests: " + (passed + failed));
console.log("Passed tests: " + passed);
console.log("Failed tests: " + failed);
})
});
});
});

View File

@ -32,25 +32,26 @@ define(function(require, exports, module) {
"use strict";
/**
*
*
* This object maintains the undo stack for an [[EditSession `EditSession`]].
* @class UndoManager
**/
/**
*
*
* Resets the current undo state and creates a new `UndoManager`.
*
* @constructor
**/
var UndoManager = function() {
this.$maxRev = 0;
this.$fromUndo = false;
this.reset();
};
(function() {
this.addSession = function(session) {
this.$session = session;
};
/**
* Provides a means for implementing your own undo manager. `options` has one property, `args`, an [[Array `Array`]], with two elements:
*
@ -60,156 +61,523 @@ var UndoManager = function() {
* @param {Object} options Contains additional properties
*
**/
this.execute = function(options) {
// Normalize deltas for storage.
// var deltaSets = this.$serializeDeltas(options.args[0]);
var deltaSets = options.args[0];
// Add deltas to undo stack.
this.$doc = options.args[1];
if (options.merge && this.hasUndo()){
this.dirtyCounter--;
deltaSets = this.$undoStack.pop().concat(deltaSets);
this.add = function(delta, allowMerge, session) {
if (this.$fromUndo) return;
if (delta == this.$lastDelta) return;
if (allowMerge === false || !this.lastDeltas) {
this.lastDeltas = [];
this.$undoStack.push(this.lastDeltas);
delta.id = this.$rev = ++this.$maxRev;
}
this.$undoStack.push(deltaSets);
// Reset redo stack.
this.$redoStack = [];
if (this.dirtyCounter < 0) {
// The user has made a change after undoing past the last clean state.
// We can never get back to a clean state now until markClean() is called.
this.dirtyCounter = NaN;
}
this.dirtyCounter++;
if (delta.action == "remove" || delta.action == "insert")
this.$lastDelta = delta;
this.lastDeltas.push(delta);
};
this.addSelection = function(selection, rev) {
this.selections.push({
value: selection,
rev: rev || this.$rev
});
};
this.startNewGroup = function() {
this.lastDeltas = null;
return this.$rev;
};
this.markIgnored = function(from, to) {
if (to == null) to = this.$rev + 1;
var stack = this.$undoStack;
for (var i = stack.length; i--;) {
var delta = stack[i][0];
if (delta.id <= from)
break;
if (delta.id < to)
delta.ignore = true;
}
this.lastDeltas = null;
};
this.getSelection = function(rev, after) {
var stack = this.selections;
for (var i = stack.length; i--;) {
var selection = stack[i];
if (selection.rev < rev) {
if (after)
selection = stack[i + 1];
return selection;
}
}
};
this.getRevision = function() {
return this.$rev;
};
this.getDeltas = function(from, to) {
if (to == null) to = this.$rev + 1;
var stack = this.$undoStack;
var end = null, start = 0;
for (var i = stack.length; i--;) {
var delta = stack[i][0];
if (delta.id < to && !end)
end = i+1;
if (delta.id <= from) {
start = i + 1;
break;
}
}
return stack.slice(start, end);
};
this.getChangedRanges = function(from, to) {
if (to == null) to = this.$rev + 1;
};
this.getChangedLines = function(from, to) {
if (to == null) to = this.$rev + 1;
};
/**
* [Perform an undo operation on the document, reverting the last change.]{: #UndoManager.undo}
* @param {Boolean} dontSelect {:dontSelect}
*
*
* @returns {Range} The range of the undo.
**/
this.undo = function(dontSelect) {
var deltaSets = this.$undoStack.pop();
this.undo = function(session, dontSelect) {
this.lastDeltas = null;
var stack = this.$undoStack;
if (!rearrangeUndoStack(stack, stack.length))
return;
if (this.$redoStackBaseRev !== this.$rev && this.$redoStack.length)
this.$redoStack = [];
this.$fromUndo = true;
var deltaSet = stack.pop();
var undoSelectionRange = null;
if (deltaSets) {
undoSelectionRange = this.$doc.undoChanges(this.$deserializeDeltas(deltaSets), dontSelect);
this.$redoStack.push(deltaSets);
this.dirtyCounter--;
if (deltaSet && deltaSet.length) {
undoSelectionRange = session.undoChanges(deltaSet, dontSelect);
this.$redoStack.push(deltaSet);
this.$syncRev();
}
this.$fromUndo = false;
return undoSelectionRange;
};
/**
* [Perform a redo operation on the document, reimplementing the last change.]{: #UndoManager.redo}
* @param {Boolean} dontSelect {:dontSelect}
*
*
**/
this.redo = function(dontSelect) {
var deltaSets = this.$redoStack.pop();
var redoSelectionRange = null;
if (deltaSets) {
redoSelectionRange =
this.$doc.redoChanges(this.$deserializeDeltas(deltaSets), dontSelect);
this.$undoStack.push(deltaSets);
this.dirtyCounter++;
this.redo = function(session, dontSelect) {
this.lastDeltas = null;
this.$fromUndo = true;
if (this.$redoStackBaseRev != this.$rev) {
var diff = this.getDeltas(this.$redoStackBaseRev, this.$rev + 1);
rebaseRedoStack(this.$redoStack, diff);
this.$redoStackBaseRev = this.$rev;
this.$redoStack.forEach(function(x) {
x[0].id = ++this.$maxRev;
}, this);
}
var deltaSet = this.$redoStack.pop();
var redoSelectionRange = null;
if (deltaSet) {
redoSelectionRange = session.redoChanges(deltaSet, dontSelect);
this.$undoStack.push(deltaSet);
this.$syncRev();
}
this.$fromUndo = false;
return redoSelectionRange;
};
this.$syncRev = function() {
var stack = this.$undoStack;
var nextDelta = stack[stack.length - 1];
var id = nextDelta && nextDelta[0].id || 0;
this.$redoStackBaseRev = id;
this.$rev = id;
};
/**
*
* Destroys the stack of undo and redo redo operations.
**/
this.reset = function() {
this.lastDeltas = null;
this.$lastDelta = null;
this.$undoStack = [];
this.$redoStack = [];
this.dirtyCounter = 0;
this.$rev = 0;
this.mark = 0;
this.$redoStackBaseRev = this.$rev;
this.selections = [];
};
/**
*
* Returns `true` if there are undo operations left to perform.
* @returns {Boolean}
**/
this.hasUndo = function() {
this.canUndo = function() {
return this.$undoStack.length > 0;
};
/**
*
* Returns `true` if there are redo operations left to perform.
* @returns {Boolean}
**/
this.hasRedo = function() {
this.canRedo = function() {
return this.$redoStack.length > 0;
};
/**
*
* Marks the current status clean
**/
this.markClean = function() {
this.dirtyCounter = 0;
this.bookmark = function(rev) {
if (rev == undefined)
rev = this.$rev;
this.mark = rev;
};
/**
*
* Returns if the current status is clean
* @returns {Boolean}
**/
this.isClean = function() {
return this.dirtyCounter === 0;
this.isAtBookmark = function() {
return this.$rev === this.mark;
};
// Serializes deltaSets to reduce memory usage.
this.$serializeDeltas = function(deltaSets) {
return cloneDeltaSetsObj(deltaSets, $serializeDelta);
};
// Deserializes deltaSets to allow application to the document.
this.$deserializeDeltas = function(deltaSets) {
return cloneDeltaSetsObj(deltaSets, $deserializeDelta);
};
function $serializeDelta(delta){
return {
action: delta.action,
start: delta.start,
end: delta.end,
lines: delta.lines.length == 1 ? null : delta.lines,
text: delta.lines.length == 1 ? delta.lines[0] : null,
};
}
this.toJSON = function() {
function $deserializeDelta(delta) {
return {
action: delta.action,
start: delta.start,
end: delta.end,
lines: delta.lines || [delta.text]
};
}
};
function cloneDeltaSetsObj(deltaSets_old, fnGetModifiedDelta) {
var deltaSets_new = new Array(deltaSets_old.length);
for (var i = 0; i < deltaSets_old.length; i++) {
var deltaSet_old = deltaSets_old[i];
var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)};
for (var j = 0; j < deltaSet_old.deltas.length; j++) {
var delta_old = deltaSet_old.deltas[j];
deltaSet_new.deltas[j] = fnGetModifiedDelta(delta_old);
}
deltaSets_new[i] = deltaSet_new;
}
return deltaSets_new;
}
this.fromJSON = function() {
};
this.hasUndo = this.canUndo;
this.hasRedo = this.canRedo;
this.isClean = this.isAtBookmark;
this.markClean = this.bookmark;
}).call(UndoManager.prototype);
function rearrangeUndoStack(stack, pos) {
for (var i = pos; i--; ) {
var deltaSet = stack[i];
if (deltaSet && !deltaSet[0].ignore) {
while(i < pos - 1) {
var swapped = swapGroups(stack[i], stack[i + 1]);
stack[i] = swapped[0];
stack[i + 1] = swapped[1];
i++;
}
return true;
}
}
}
var Range = require("./range").Range;
var cmp = Range.comparePoints;
var comparePoints = Range.comparePoints;
function $updateMarkers(delta) {
var isInsert = delta.action == "insert";
var start = delta.start;
var end = delta.end;
var rowShift = (end.row - start.row) * (isInsert ? 1 : -1);
var colShift = (end.column - start.column) * (isInsert ? 1 : -1);
if (isInsert) end = start;
for (var i in this.marks) {
var point = this.marks[i];
var cmp = comparePoints(point, start);
if (cmp < 0) {
continue; // delta starts after the range
}
if (cmp === 0) {
if (isInsert) {
if (point.bias == 1) {
cmp = 1;
}
else {
point.bias == -1;
continue;
}
}
}
var cmp2 = isInsert ? cmp : comparePoints(point, end);
if (cmp2 > 0) {
point.row += rowShift;
point.column += point.row == end.row ? colShift : 0;
continue;
}
if (!isInsert && cmp2 <= 0) {
point.row = start.row;
point.column = start.column;
if (cmp2 === 0)
point.bias = 1;
}
}
}
function clonePos(pos) {
return {row: pos.row,column: pos.column};
}
function cloneDelta(d) {
return {
start: clonePos(d.start),
end: clonePos(d.end),
action: d.action,
lines: d.lines.slice()
};
}
function stringifyDelta(d) {
d = d || this;
if (Array.isArray(d)) {
return d.map(stringifyDelta).join("\n");
}
var type = "";
if (d.action) {
type = d.action == "insert" ? "+" : "-";
type += "[" + d.lines + "]";
} else if (d.value) {
if (Array.isArray(d.value)) {
type = d.value.map(stringifyRange).join("\n");
} else {
type = stringifyRange(d.value);
}
}
if (d.start) {
type += stringifyRange(d);
}
if (d.id || d.rev) {
type += "\t(" + (d.id || d.rev) + ")";
}
return type;
}
function stringifyRange(r) {
return r.start.row + ":" + r.start.column
+ "=>" + r.end.row + ":" + r.end.column;
}
/*
* i i d1 d2
* |/ |/ d2.s >= d1.e shift(d2, d1, -1)
* d2.s <= d1.s shift(d1, d2, +1)
* d1.s < d2.s < d1.e // can split
*
* i r d1 d2
* |/ |\ d2.s >= d1.e shift(d2, d1, -1)
* d2.e <= d1.s shift(d1, d2, -1)
* else // can't swap
*
* r i d1 d2
* |\ |/ d2.s >= d1.s shift(d2, d1, +1)
* d2.s <= d1.s shift(d1, d2, +1)
* // no else
*
* r r d1 d2
* |\ |\ d2.s >= d1.s shift(d2, d1, +1)
* d2.e <= d1.s shift(d1, d2, -1)
* d2.s < d1.s < d2.e // can split
*/
function swap(d1, d2) {
var i1 = d1.action == "insert";
var i2 = d2.action == "insert";
if (i1 && i2) {
if (cmp(d2.start, d1.end) >= 0) {
shift(d2, d1, -1);
} else if (cmp(d2.start, d1.start) <= 0) {
shift(d1, d2, +1);
} else {
return null;
}
} else if (i1 && !i2) {
if (cmp(d2.start, d1.end) >= 0) {
shift(d2, d1, -1);
} else if (cmp(d2.end, d1.start) <= 0) {
shift(d1, d2, -1);
} else {
return null;
}
} else if (!i1 && i2) {
if (cmp(d2.start, d1.start) >= 0) {
shift(d2, d1, +1);
} else if (cmp(d2.start, d1.start) <= 0) {
shift(d1, d2, +1);
} else {
return null;
}
} else if (!i1 && !i2) {
if (cmp(d2.start, d1.start) >= 0) {
shift(d2, d1, +1);
} else if (cmp(d2.end, d1.start) <= 0) {
shift(d1, d2, -1);
} else {
return null;
}
}
return [d2, d1];
}
function swapGroups(ds1, ds2) {
for (var i = ds1.length; i--; ) {
for (var j = 0; j < ds2.length; j++) {
if (!swap(ds1[i], ds2[j])) {
// rollback, we have to undo ds2 first
while (i < ds1.length) {
while (j--) {
swap(ds2[j], ds1[i]);
}
j = ds2.length;
i++;
}
return [ds1, ds2];
}
}
}
ds1.selectionBefore = ds2.selectionBefore =
ds1.selectionAfter = ds2.selectionAfter = null;
return [ds2, ds1];
}
/*
d2 xform(d1, c1) = [d2, c2]
o<---o xform(c1, d1) = [c2, d2]
c2 | | d1
o<---o
c1
*/
function xform(d1, c1) {
var i1 = d1.action == "insert";
var i2 = c1.action == "insert";
if (i1 && i2) {
if (cmp(d1.start, c1.start) < 0) {
shift(c1, d1, 1);
} else {
shift(d1, c1, 1);
}
} else if (i1 && !i2) {
if (cmp(d1.start, c1.end) >= 0) {
shift(d1, c1, -1);
} else if (cmp(d1.start, c1.start) <= 0) {
shift(c1, d1, +1);
} else {
shift(d1, Range.fromPoints(c1.start, d1.start), -1);
shift(c1, d1, +1);
}
} else if (!i1 && i2) {
if (cmp(c1.start, d1.end) >= 0) {
shift(c1, d1, -1);
} else if (cmp(c1.start, d1.start) <= 0) {
shift(d1, c1, +1);
} else {
shift(c1, Range.fromPoints(d1.start, c1.start), -1);
shift(d1, c1, +1);
}
} else if (!i1 && !i2) {
if (cmp(c1.start, d1.end) >= 0) {
shift(c1, d1, -1);
} else if (cmp(c1.end, d1.start) <= 0) {
shift(d1, c1, -1);
} else {
var before, after;
if (cmp(d1.start, c1.start) < 0) {
before = d1;
d1 = splitDelta(d1, c1.start);
}
if (cmp(d1.end, c1.end) > 0) {
after = splitDelta(d1, c1.end);
}
shiftPos(c1.end, d1.start, d1.end, -1);
if (after && !before) {
d1.lines = after.lines;
d1.start = after.start;
d1.end = after.end;
after = d1;
}
return [c1, before, after].filter(Boolean);
}
}
return [c1, d1];
}
function shift(d1, d2, dir) {
shiftPos(d1.start, d2.start, d2.end, dir);
shiftPos(d1.end, d2.start, d2.end, dir);
}
function shiftPos(pos, start, end, dir) {
if (pos.row == (dir == 1 ? start : end).row) {
pos.column += dir * (end.column - start.column);
}
pos.row += dir * (end.row - start.row);
}
function splitDelta(c, pos) {
var lines = c.lines;
var end = c.end;
c.end = clonePos(pos);
var rowsBefore = c.end.row - c.start.row;
var otherLines = lines.splice(rowsBefore, lines.length);
var col = rowsBefore ? pos.column : pos.column - c.start.column;
lines.push(otherLines[0].substring(0, col));
otherLines[0] = otherLines[0].substr(col) ;
var rest = {
start: clonePos(pos),
end: end,
lines: otherLines,
action: c.action
};
return rest;
}
function moveDeltasByOne(redoStack, d) {
d = cloneDelta(d);
for (var j = redoStack.length; j--;) {
var deltaSet = redoStack[j];
for (var i = deltaSet.length; i--> 0;) {
var x = deltaSet[i];
var xformed = xform(x, d);
d = xformed[0];
if (xformed.length != 2) {
if (xformed[2]) {
redoStack.splice(i + 1, 1, xformed[1], xformed[2]);
i++;
} else if (!xformed[1]) {
redoStack.splice(i, 1);
i--;
}
}
}
}
return redoStack;
}
function rebaseRedoStack(redoStack, deltaSets) {
for (var i = 0; i < deltaSets.length; i++) {
var deltas = deltaSets[i];
for (var j = 0; j < deltas.length; j++) {
moveDeltasByOne(redoStack, deltas[j]);
}
}
}
exports.UndoManager = UndoManager;
});

111
node_modules/ace/lib/ace/undomanager_test.js generated vendored Normal file
View File

@ -0,0 +1,111 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2010, Ajax.org B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Ajax.org B.V. nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***** END LICENSE BLOCK ***** */
if (typeof process !== "undefined") {
require("amd-loader");
require("./test/mockdom");
}
define(function(require, exports, module) {
"use strict";
require("./multi_select");
var assert = require("./test/assertions");
var Range = require("./range").Range;
var Editor = require("./editor").Editor;
var EditSession = require("./edit_session").EditSession;
var MockRenderer = require("./test/mockrenderer").MockRenderer;
var UndoManager = require("./undomanager").UndoManager;
var editor;
module.exports = {
name: "ACE undoManager.js",
"test: reabsing": function() {
var session = new EditSession("");
var editor = new Editor(new MockRenderer(), session);
var undoManager = new UndoManager();
session.setUndoManager(undoManager);
session.setValue("012345-012345-012345");
session.insert({row: 0, column: 0}, "xx");
session.markUndoGroup();
session.remove(new Range(0, 10, 0, 15));
session.markUndoGroup();
session.insert({row: 0, column: 5}, "yy");
session.markUndoGroup();
editor.undo();
editor.undo();
var rev = session.getUndoManager().startNewGroup();
session.insert({row: 0, column: 5}, "z\nz");
session.getUndoManager().markIgnored(rev);
// editor.undo()
editor.redo();
editor.redo();
var val1 = editor.getValue();
editor.undo();
editor.undo();
editor.undo();
editor.redo();
editor.redo();
editor.redo();
var val2 = editor.getValue();
assert.equal(val1, val2);
},
"test: conflicting deletes": function() {
var session = new EditSession("");
var editor = new Editor(new MockRenderer(), session);
var undoManager = new UndoManager();
session.setUndoManager(undoManager);
session.setValue("012345\nabcdefg\nxyz");
session.remove(new Range(0, 2, 0, 4));
assert.equal(session.getLine(0), "0145");
session.markUndoGroup();
editor.undo();
session.remove(new Range(0, 1, 0, 5));
assert.equal(session.getLine(0), "05");
session.markUndoGroup();
editor.redo();
assert.equal(session.getLine(0), "05");
editor.undo();
assert.equal(session.getLine(0), "012345");
}
};
});
if (typeof module !== "undefined" && module === require.main) {
require("asyncjs").test.testcase(module.exports).exec();
}

2
node_modules/vfs-child/parent.js generated vendored
View File

@ -15,7 +15,7 @@ function Parent(fsOptions) {
options.uid = fsOptions.uid;
delete fsOptions.uid;
}
options.customFds = [-1, -1, 2];
options.stdio = options.customFds = [-1, -1, 2];
var args = [require.resolve('./child.js'), JSON.stringify(fsOptions)];
var executablePath = process.execPath;
var child;

15
node_modules/vfs-local/localfs.js generated vendored
View File

@ -1828,8 +1828,13 @@ module.exports = function setup(fsOptions) {
if (options.idle)
options.command = "echo '[Idle]'";
if (options.terminal)
args.push("export ISOUTPUTPANE=0;" + BASH + " -l");
if (options.terminal) {
args.push("export ISOUTPUTPANE=0;"
+ (options.defaultEditor
? " export EDITOR='`which c9` open --wait'; "
: "")
+ BASH + " -l");
}
else if (options.command)
args.push((BASH + " -l -c '"
@ -2334,6 +2339,9 @@ module.exports = function setup(fsOptions) {
err.code = "EEXIST";
return callback(err, { api: apis[name] });
}
if (options.redefine && apis[name] && apis[name].destroy)
apis[name].destroy();
var fn;
@ -2394,6 +2402,9 @@ module.exports = function setup(fsOptions) {
}
function unextend(name, options, callback) {
if (apis[name] && apis[name].destroy)
apis[name].destroy();
delete apis[name];
callback(null, {});
}

15
node_modules/vfs-socket/worker.js generated vendored
View File

@ -162,6 +162,9 @@ function Worker(vfs) {
var nextStreamID = 1;
function storeStream(stream) {
if (stream.token)
return stream.token;
nextStreamID = (nextStreamID + 1) % 10000;
while (streams.hasOwnProperty(nextStreamID)) { nextStreamID = (nextStreamID + 1) % 10000; }
var id = nextStreamID;
@ -188,6 +191,7 @@ function Worker(vfs) {
remote.onClose(id);
});
var token = {id: id};
stream.token = token;
if (stream.hasOwnProperty("readable")) token.readable = stream.readable;
if (stream.hasOwnProperty("writable")) token.writable = stream.writable;
return token;
@ -195,6 +199,9 @@ function Worker(vfs) {
function storeProcess(process, onlyPid) {
var pid = process.pid;
if (processes.token)
return onlyPid ? process.pid : process.token;
processes[pid] = process;
process.on("exit", function (code, signal) {
delete processes[pid];
@ -215,11 +222,13 @@ function Worker(vfs) {
code: code
}, callback || function() {});
};
var token = {pid: pid};
process.token = token;
if (onlyPid)
return pid;
var token = {pid: pid};
token.stdin = storeStream(process.stdin);
token.stdout = storeStream(process.stdout);
token.stderr = storeStream(process.stderr);
@ -230,8 +239,8 @@ function Worker(vfs) {
if (!pty || processes[pty.pid] == pty) // Pty is returned twice
return pty && pty.token;
var pid = storeProcess(pty, true);
var token = storeStream(pty);
var pid = storeProcess(pty, true); delete pty.token;
var token = storeStream(pty); delete pty.token;
token.pid = pid;
pty.token = token;

View File

@ -60,12 +60,12 @@
"c9.ide.language.javascript.tern": "#7aab8b0b6a",
"c9.ide.language.javascript.infer": "#cfec494a3c",
"c9.ide.language.jsonalyzer": "#21b64e5820",
"c9.ide.collab": "#edef363853",
"c9.ide.collab": "#da4d09ae6a",
"c9.ide.local": "#2bfd7ff051",
"c9.ide.find": "#6cc6d3379d",
"c9.ide.find.infiles": "#72582de3cd",
"c9.ide.find.replace": "#e4daf722b8",
"c9.ide.run.debug": "#638e6b00b3",
"c9.ide.run.debug": "#23a188b91a",
"c9.automate": "#47e2c429c9",
"c9.ide.ace.emmet": "#e5f1a92ac3",
"c9.ide.ace.gotoline": "#4d1a93172c",
@ -81,9 +81,9 @@
"c9.ide.fontawesome": "#781602c5d8",
"c9.ide.format": "#f51451ac57",
"c9.ide.help.support": "#60e88f5680",
"c9.ide.imgeditor": "#08bbc53578",
"c9.ide.imgeditor": "#ed89162aa7",
"c9.ide.immediate": "#6845a93705",
"c9.ide.installer": "#a1e01c07a3",
"c9.ide.installer": "#9bfeb1f703",
"c9.ide.mount": "#32e79866ee",
"c9.ide.navigate": "#64156c7f4a",
"c9.ide.newresource": "#f1f0624768",
@ -99,7 +99,7 @@
"c9.ide.run": "#71c5562e42",
"c9.ide.run.build": "#ad45874c88",
"c9.ide.run.debug.xdebug": "#b91d23f48b",
"c9.ide.save": "#b876d87d55",
"c9.ide.save": "#3cb206c168",
"c9.ide.terminal.monitor": "#b0b4d03280",
"c9.ide.theme.flat": "#b1d65fa9bb",
"c9.ide.threewaymerge": "#229382aa0b",

View File

@ -5,7 +5,7 @@
*/
define(function(require, exports, module) {
main.consumes = ["c9", "Plugin", "net"];
main.provides = ["bridge-client"];
main.provides = ["bridge.client"];
return main;
function main(options, imports, register) {
@ -13,27 +13,61 @@ define(function(require, exports, module) {
var c9 = imports.c9;
var net = imports.net;
var JSONStream = require("./json-stream");
/***** Initialization *****/
var plugin = new Plugin("Ajax.org", main.consumes);
// var emit = plugin.getEmitter();
var PORT = options.port || 17123;
var counter = 0;
var SOCKET = c9.platform == "win32"
? "\\\\.\\pipe\\.c9\\bridge.socket"
: c9.home + "/.c9/bridge.socket";
/***** Methods *****/
function send(message, callback) {
net.connect(PORT, {}, function(err, stream) {
net.connect(SOCKET, {}, function(err, stream) {
if (err)
return callback(err);
stream.write(JSON.stringify(message));
stream.end();
var jstream = new JSONStream(stream);
var msgId = generateMessageId();
var done;
callback();
jstream.write({
id: msgId,
message: message
});
jstream.on("data", function(payload){
if (payload.id == msgId && !done) {
done = true;
callback(null, payload.message);
stream.end();
}
});
jstream.on("error", function(err){
if (done) return;
callback(err);
done = true;
});
jstream.on("close", function(){
if (done) return;
callback(new Error("No Response"));
done = true;
})
});
}
function generateMessageId(){
// Use vfs token
return Math.random() + "-" + ++counter;
}
/***** Lifecycle *****/
plugin.on("load", function(){
@ -55,7 +89,7 @@ define(function(require, exports, module) {
});
register(null, {
"bridge-client": plugin
"bridge.client": plugin
});
}
});

View File

@ -1,37 +1,128 @@
module.exports = function (vfs, options, register) {
var stream;
var net = require("net");
var Stream = require('stream');
var stream, server;
var SOCKET = process.platform == "win32"
? "\\\\.\\pipe\\.c9\\bridge.socket"
: process.env.HOME + "/.c9/bridge.socket";
function createListenClient(api){
var client = net.connect(SOCKET, function(data){
if (data) api.onData(data);
});
client.setEncoding("utf8");
client.unref();
client.on("data", function(data){
if (data) api.onData(data);
});
client.on("error", function(err){
if (err.code == "ECONNREFUSED") {
require("fs").unlink(SOCKET, function(){
createListenServer(api);
});
}
else if (err.code == "ENOENT") {
createListenServer(api);
}
else
api.onError(err);
});
client.on("end", function(){
createListenServer(api);
});
api.onConnect(client);
api.disconnect = function(){
client.end();
};
return client;
}
function createListenServer(api){
// var timeout = setTimeout(function(){
// unixServer.close();
// }, 500);
var unixServer = net.createServer(function(client) {
client.setEncoding("utf8");
client.on("data", function(data){
if (data) api.onData(data);
});
client.on("error", function(data){
// console.error("ERROR", api.id, data);
});
api.onConnect(client);
});
unixServer.listen(SOCKET);
unixServer.on("error", function(err){
if (err.code == "EADDRINUSE") {
createListenClient(api);
}
else
api.onError(err);
});
api.disconnect = function(){
unixServer.close();
};
}
register(null, {
connect: function (port, callback) {
connect: function (callback) {
if (stream) return callback(null, { stream: stream });
server = require('net').createServer(function(c) {
var buffer = "";
c.on("data", function(chunk) {
buffer += chunk;
});
c.on("end", function(){
stream.emit("data", buffer);
});
});
server.on("error", function(err) {
callback(err);
});
server.listen(port, process.env.OPENSHIFT_DIY_IP || "localhost", function(err) {
if (err) return callback(err);
callback(null, { stream: stream });
});
stream = new Stream();
stream.readable = true;
stream.writable = true;
var client;
var sent = false;
var api = this.api = {
id: Math.random(),
onConnect: function(c){
client = c;
if (sent) return;
callback(null, { stream: stream });
sent = true;
},
onData: function(data){
stream && stream.emit("data", data);
},
onError: function(err){
stream && stream.emit("error", err);
}
};
// createListenServer
createListenClient(api);
stream.write = function(data){
if (client) client.write(data);
};
},
disconnect: function(){
try { server && server.close(); }
try { this.api && this.api.disconnect(); }
catch (e) {}
stream = null;
server = null;
delete this.api;
},
destroy: function(){
this.disconnect();
}
});
};

View File

@ -1,4 +1,3 @@
define(function(require, exports, module) {
main.consumes = ["c9", "Plugin", "ext"];
main.provides = ["bridge"];
@ -8,6 +7,8 @@ define(function(require, exports, module) {
var Plugin = imports.Plugin;
var c9 = imports.c9;
var ext = imports.ext;
var JSONStream = require("./json-stream");
/***** Initialization *****/
@ -15,15 +16,10 @@ define(function(require, exports, module) {
var emit = plugin.getEmitter();
var ENABLED = options.startBridge !== false;
var PORT = options.port || 17123;
var stream, api;
var loaded = false;
function load(){
if (loaded) return;
loaded = true;
if (!ENABLED) return;
ext.loadRemotePlugin("bridge", {
@ -35,58 +31,62 @@ define(function(require, exports, module) {
api = remote;
api.connect(PORT, function(err, meta) {
if (err) {
loaded = false;
api.connect(function(err, meta) {
if (err)
return console.error(err); // this should never happen
if (err.code == "EADDRINUSE") {
console.warn("Another Application is using port "
+ PORT + ". CLI client interface disabled. Restart Cloud9 to retry connecting.");
}
else
console.error(err);
return;
}
stream = meta.stream;
stream.on("data", function(chunk) {
try { var message = JSON.parse(chunk); }
catch (e) {
setTimeout(function(){
loaded = false;
load();
}, 60000);
return;
}
emit("message", { message: message });
stream = new JSONStream(meta.stream);
stream.on("error", function(err) {
console.error(err);
});
stream.on("data", function(payload) {
emit("message", {
message: payload.message,
respond: function(err, message){
stream.write({
id: payload.id,
message: message,
error: err
});
}
});
});
stream.on("close", function(){
loaded = false;
load();
});
emit.sticky("ready");
});
});
window.addEventListener("unload", unload);
window.addEventListener("unload", function(){
api && api.disconnect();
});
}
function unload() {
api && api.disconnect();
api = stream = null;
loaded = false;
function write(json){
if (!stream) {
plugin.once("ready", function(){ write(json); });
return;
}
stream.write(json);
}
/***** Methods *****/
plugin.on("load", function(){
c9.on("connect", load, plugin);
c9.on("disconnect", unload, plugin);
});
plugin.on("unload", function(){
api && api.disconnect();
stream = null;
api = null;
});
/***** Register and define API *****/
@ -94,7 +94,12 @@ define(function(require, exports, module) {
/**
* Bridge To Communicate from CLI to IDE
**/
plugin.freezePublicAPI({ });
plugin.freezePublicAPI({
/**
*
*/
write: write
});
register(null, {
bridge: plugin

View File

@ -1,20 +1,25 @@
define(function(require, exports, module) {
main.consumes = [
"Plugin", "bridge", "tabManager", "panels",
"tree.favorites", "tree", "fs"
"Plugin", "bridge", "tabManager", "panels", "tree.favorites", "tree",
"fs", "preferences", "settings", "c9"
];
main.provides = ["bridge_commands"];
main.provides = ["bridge.commands"];
return main;
function main(options, imports, register) {
var Plugin = imports.Plugin;
var bridge = imports.bridge;
var tabs = imports.tabManager;
var tabManager = imports.tabManager;
var panels = imports.panels;
var tree = imports.tree;
var settings = imports.settings;
var favs = imports["tree.favorites"];
var fs = imports.fs;
var c9 = imports.c9;
var prefs = imports.preferences;
var async = require("async");
/***** Initialization *****/
@ -23,36 +28,62 @@ define(function(require, exports, module) {
var BASEPATH = options.basePath;
var loaded = false;
function load(){
if (loaded) return;
loaded = true;
bridge.on("message", function(e) {
var message = e.message;
switch (message.type) {
case "open":
open(message);
open(message, e.respond);
break;
case "ping":
e.respond(null, true);
break;
default:
console.error("Unknown Bridge Command: ", message.type);
break;
}
});
}, plugin);
settings.on("read", function(e) {
settings.setDefaults("user/terminal", [
["defaultEditor", "true"]
]);
}, plugin);
prefs.add({
"Editors" : {
"Terminal" : {
"Use Cloud9 as the Default Editor" : {
type: "checkbox",
path: "user/terminal/@defaultEditor",
position: 14000
}
}
}
}, plugin);
}
/***** Methods *****/
function open(message) {
message.paths.forEach(function(info, i) {
function open(message, callback) {
var i = -1;
var tabs = [];
BASEPATH = c9.toInternalPath(BASEPATH);
async.each(message.paths, function(info, next) {
var path = info.path;
i++;
path = c9.toInternalPath(path);
// Make sure file is inside workspace
if (path.substr(0, BASEPATH.length) !== BASEPATH)
return;
// Remove base path
path = path.substr(BASEPATH.length);
if (path.charAt(0) !== "~") {
if (path.substr(0, BASEPATH.length) !== BASEPATH)
return; // Dont' call callback. Perhaps another client will pick this up.
// Remove base path
path = path.substr(BASEPATH.length);
}
if (info.type == "directory") {
path = path.replace(/\/$/, "");
@ -61,26 +92,45 @@ define(function(require, exports, module) {
var node = favs.addFavorite(path);
tree.expand(path, function(err) {
tree.expand(path, function() {
tree.select(node); //path || "/");
tree.scrollToSelection();
next();
});
tree.focus();
}
else {
tabs.once("ready", function(){
tabManager.once("ready", function(){
fs.exists(path, function(existing) {
tabs.open({
var tab = tabManager.open({
path: path,
active: i === 0,
document:
existing
? undefined
: { meta : { newfile: true } }
}, function(){});
}, function(){
next();
});
if (message.wait) {
tab.on("close", function(){
tabs.splice(tabs.indexOf(tab), 1);
if (!tabs.length)
callback(null, true);
});
}
tabs.push(tab);
});
});
}
}, function(err){
if (err)
return callback(err);
if (!message.wait || !tabs.length)
callback(null, true);
});
}
@ -102,7 +152,7 @@ define(function(require, exports, module) {
plugin.freezePublicAPI({});
register(null, {
"bridge_commands": plugin
"bridge.commands": plugin
});
}
});

View File

@ -2,7 +2,7 @@
"use client";
require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai) {
require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "/vfs-home"], function (architect, chai, basePath, homePath) {
var expect = chai.expect;
var Assert = chai.assert;
@ -14,46 +14,70 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
debug: true,
hosted: true,
local: false,
davPrefix: "/"
davPrefix: "/",
home: homePath
},
"plugins/c9.core/ext",
"plugins/c9.core/http-xhr",
"plugins/c9.core/util",
"plugins/c9.ide.ui/lib_apf",
"plugins/c9.ide.ui/ui",
"plugins/c9.core/settings",
//"plugins/c9.ide.collab/collab",
"plugins/c9.vfs.client/vfs_client",
"plugins/c9.vfs.client/endpoint",
"plugins/c9.ide.auth/auth",
"plugins/c9.fs/fs",
"plugins/c9.fs/net",
{
packagePath: "plugins/c9.cli.bridge/bridge",
startBridge: true
},
{
packagePath: "plugins/c9.cli.bridge/bridge_commands",
basePath: basePath
},
"plugins/c9.cli.bridge/bridge-client",
// Mock plugins
{
consumes: ["ui"],
consumes: [],
provides: [
"preferences", "dialog.error"
"preferences", "ui"
],
setup: expect.html.mocked
},
{
consumes: ["collab"],
consumes: ["bridge", "bridge.client"],
provides: [],
setup: main
}
], architect);
function main(options, imports, register) {
var collab = imports.collab;
var bridge = imports.bridge;
var client = imports["bridge.client"];
describe('collab', function() {
this.timeout(10000);
describe('bridge', function() {
// this.timeout(10000);
describe("connect", function(){
it('should connect', function(done) {
collab.connect(null, function(err, stream) {
if (err) throw err.message;
});
before(function(done){
bridge.on("ready", function(){
done();
});
});
it('send and receive messages', function(done) {
bridge.on("message", function(e){
if (e.message.hello) {
e.respond(null, { "hi": true });
}
});
client.send({ "hello": true }, function(err, message){
if (err) throw err.message;
expect(message).property("hi").to.be.ok;
done();
});
});
});

View File

@ -0,0 +1,47 @@
define(function(require, exports, module) {
var EventEmitter = require("events").EventEmitter;
module.exports = function(stream) {
var emit = this.emit.bind(this);
var buffer = "";
stream.on("data", function(chunk) {
buffer += chunk;
var parts = buffer.split("\n");
while (parts.length) {
try {
var message = JSON.parse(parts[0]);
emit("data", message);
parts.shift();
}
catch (e) {
if (parts.length !== 1) {
emit("error", e);
parts.shift();
}
else {
break;
}
}
}
buffer = parts.join("\n");
});
stream.on("error", function(err){
emit("error", err);
});
stream.on("close", function(data){
emit("close", data);
});
this.write = function(data) {
stream.write(JSON.stringify(data) + "\n");
};
};
module.exports.prototype = new EventEmitter();
});

View File

@ -1,5 +1,5 @@
define(function(require, exports, module) {
main.consumes = ["Plugin", "cli_commands", "proc", "bridge-client"];
main.consumes = ["Plugin", "cli_commands", "proc", "bridge.client"];
main.provides = ["open"];
return main;
@ -7,7 +7,7 @@ define(function(require, exports, module) {
var Plugin = imports.Plugin;
var cmd = imports.cli_commands;
var proc = imports.proc;
var bridge = imports["bridge-client"];
var bridge = imports["bridge.client"];
var fs = require("fs");
var PATH = require("path");
@ -25,11 +25,12 @@ define(function(require, exports, module) {
cmd.addCommand({
name: "open",
info: " Opens a file or directory.",
usage: "<path>",
usage: "[--wait] <path>",
options: {
"path" : {
description: "Specify the path that will be opened",
default: false
"wait": {
description: "Wait until the file(s) are closed",
"default": false,
"boolean": true
}
},
check: function(argv) {
@ -39,6 +40,7 @@ define(function(require, exports, module) {
exec: function(argv) {
open(
argv._.slice(1), // Remove "open" from the paths
argv.wait,
function(){});
}
});
@ -46,12 +48,16 @@ define(function(require, exports, module) {
/***** Methods *****/
function open(paths, callback) {
function open(paths, wait, callback) {
try {
paths = paths.map(function(path) {
var isDir = fs.existsSync(path) && fs.statSync(path).isDirectory();
path = PATH.resolve(path);
if (path.substr(0, process.env.HOME.length) == process.env.HOME)
path = "~" + path.substr(process.env.HOME.length);
return {
path: "/" + PATH.resolve(path),
path: path,
type: isDir ? "directory" : "file"
};
});
@ -65,6 +71,7 @@ define(function(require, exports, module) {
paths.forEach(function(info) {
var path = info.type == "directory"
? info.path : PATH.dirname(info.path);
if (!last) {
last = path;
}
@ -86,11 +93,12 @@ define(function(require, exports, module) {
var message = {
type: "open",
workspace: "local",
wait: wait,
// cwd : cwd,
paths: paths
};
bridge.send(message, function cb(err) {
bridge.send(message, function cb(err, response) {
if (err) {
if (err.code == "ECONNREFUSED") {
// Seems Cloud9 is not running, lets start it up
@ -111,6 +119,9 @@ define(function(require, exports, module) {
console.log(err.message);
}
if (response !== true)
console.log("Could not open ", paths);
process.exit(); // I don't get why this is needed
});
}
@ -129,13 +140,16 @@ define(function(require, exports, module) {
var timed = Date.now();
(function retry(){
bridge.send({ type: "ping" }, function(err) {
bridge.send({ type: "ping" }, function(err, message) {
if (!err)
return callback(true);
if (Date.now() - timed > 10000)
return callback(false);
if (message !== true)
return callback(false);
setTimeout(retry, 100);
});
})();

View File

@ -77,10 +77,6 @@ define(function(require, exports, module) {
"default": false,
"boolean": true
},
"package" : {
description: "",
"default": false
},
"verbose" : {
"description": "Output more information",
"alias": "v",
@ -131,7 +127,7 @@ define(function(require, exports, module) {
process.exit(1);
}
else {
console.log("Succesfully installed", name + (argv.debug ? "" : "@" + data.version));
console.log("Successfully installed", name + (argv.debug ? "" : "@" + data.version));
process.exit(0);
}
});
@ -140,6 +136,7 @@ define(function(require, exports, module) {
cmd.addCommand({
name: "remove",
alias: "uninstall",
info: " Removes a cloud9 package.",
usage: "[--verbose] [--global] [--local] <package>", // @TODO --global
options: {
@ -153,9 +150,6 @@ define(function(require, exports, module) {
"default": false,
"boolean": true
},
"package" : {
description: ""
},
"verbose" : {
"description": "Output more information",
"alias": "v",
@ -186,7 +180,7 @@ define(function(require, exports, module) {
process.exit(1);
}
else {
console.log("Succesfully removed", name);
console.log("Successfully removed", name);
process.exit(0);
}
});
@ -387,8 +381,8 @@ define(function(require, exports, module) {
if (verbose)
console.log("Installing debug version of package");
if (!options.test)
return callback(new Error("Dry run is not supported for debug installations"));
if (options.test)
return callback(new Error("Test is not supported for debug installations"));
prepareDirectory(function(err, packagePath){
if (err) return callback(err);

View File

@ -88,8 +88,7 @@ define(function(require, exports, module) {
}
},
check: function(argv) {
// if (argv._.length < 2 && !argv["newversion"] && !argv["dry-run"])
// throw new Error("Missing version");
},
exec: function(argv) {
verbose = argv["verbose"];
@ -438,9 +437,9 @@ define(function(require, exports, module) {
var path = join(cwd, json.installer);
var installerCode = fs.readFileSync(path, "utf8");
var m = installerCode.match(/\.version\s*=\s*(\d+)/g);
var m = installerCode.match(/\.version\s*=\s*(\d+)/);
var installerVersion = m && m[0];
var installerVersion = m && m[1];
if (!installerVersion)
return callback(new Error("ERROR: missing installer version in " + json.installer));
extraCode.push({
@ -724,7 +723,7 @@ define(function(require, exports, module) {
request.on('response', function(res) {
// TODO better handle version exists error
if (res.statusCode == 412 && !version)
if (res.statusCode == 412)
console.error("ERROR: most likely version " + json.version + " already exisits, try increasing version");
if (res.statusCode != 200)
return callback(new Error("ERROR: Unknown Error:" + res.statusCode));

View File

@ -66,7 +66,6 @@ define(function(require, exports, module) {
}, function(err, token) {
if (err) return callback(err);
fs.writeFile(AUTHPATH, token, function(err){
if (err) return callback(err);
callback(null, lastToken = token);

View File

@ -7,6 +7,9 @@ define(function(require, exports, module) {
var Plugin = imports.Plugin;
var cmd = imports.cli_commands;
var fs = require("fs");
var resolve = require("path").resolve;
var optimist;
/***** Initialization *****/
@ -21,7 +24,7 @@ define(function(require, exports, module) {
var module;
var argv;
process.argv.slice(2).some(function(n){
process.argv.slice(2).some(function(n) {
if (!n.match(/^[-\/]/) && n != "node") {
module = n;
return true;
@ -29,6 +32,18 @@ define(function(require, exports, module) {
return false;
});
if (!commands[module] && process.argv.length > 2) {
for (var i = 2; i < process.argv.length; i++) {
if (process.argv[i].charAt(0) == "-") continue;
var path = resolve(process.argv[i]);
if (fs.existsSync(path)) {
process.argv.splice(2, 0, "open");
module = "open";
}
break;
}
}
optimist = require('optimist');
if (!module || !commands[module]) {
@ -62,6 +77,12 @@ define(function(require, exports, module) {
argv = optimist
.usage("The Cloud9 CLI.\nUsage: c9 " + module + " [--help] " + def.usage)
.options(def.options);
if (argv.argv.help)
argv = argv.check(function(){
if (argv.help)
throw new Error("Help Requested");
});
if (def.check)
argv = argv.check(def.check);
argv = argv.argv;

View File

@ -55,7 +55,7 @@ define(function(require, exports, module) {
loaded = true;
if (options.cli)
plugin.on("error", function(e){ console.error(e.error); });
plugin.on("error", function(e){ }); // Prevent exception
}
function wrap(name, fn) {

View File

@ -40,13 +40,14 @@ define(function(require, exports, module) {
var lang = require("ace/lib/lang");
var Range = require("ace/range").Range;
var config = require("ace/config");
var AceEditor = require("ace/editor").Editor;
var Document = require("ace/document").Document;
var AceEditor = require("ace/editor").Editor;
var EditSession = require("ace/edit_session").EditSession;
var UndoManager = require("ace/undomanager").UndoManager;
var whitespaceUtil = require("ace/ext/whitespace");
var defaultCommands = require("ace/commands/default_commands").commands;
var VirtualRenderer = require("ace/virtual_renderer").VirtualRenderer;
var multiSelectCommands = require("ace/multi_select").commands;
var whitespaceUtil = require("ace/ext/whitespace");
// enable multiselect
require("ace/multi_select");
@ -281,100 +282,169 @@ define(function(require, exports, module) {
/***** Undo Manager *****/
function AceUndoManager(undoManager, session) {
var state = undoManager.getState();
this.$session = session;
this.$undo = undoManager;
var _self = this;
var Item = this.Item;
this.$undo.on("itemFind", function(e) {
return Item(_self, e.state);
});
this.$aceUndo = new UndoManager();
this.$aceUndo.c9UndoProxy = undoManager;
undoManager.$aceUndo = this.$aceUndo;
undoManager.add = this.add;
undoManager.addSelection = this.addSelection;
undoManager.undo = this.undo;
undoManager.redo = this.redo;
undoManager.reset = this.reset;
undoManager.canUndo = this.canUndo;
undoManager.canRedo = this.canRedo;
undoManager.getState = this.getState;
undoManager.setState = this.setState;
undoManager.bookmark = this.bookmarkPosition;
undoManager.isAtBookmark = this.isAtBookmark;
undoManager.__defineGetter__("position", this.getPosition);
undoManager.__defineGetter__("length", this.getLength);
undoManager._emit = this._emit = undoManager.getEmitter();
this.deleyedEmit = lang.delayedCall(this._emit.bind(null, "change"))
.schedule.bind(null, 0);
this.setState(state, true);
}
function updateDeltas(deltas) {
if (deltas[0] && deltas[0].deltas) {
var oldDeltas = deltas.slice();
deltas.length = 0;
oldDeltas.forEach(function(x) {
deltas.push.apply(deltas, x.deltas);
});
}
return deltas;
}
AceUndoManager.prototype = {
Item: function(_self, deltas) {
return {
undo: function(){
_self.$session.session.undoChanges(deltas, _self.dontSelect);
},
redo: function(){
_self.$session.session.redoChanges(deltas, _self.dontSelect);
},
getState: function(){
return deltas.filter(function (d) {
return d.group != "fold";
});
}
};
add: function(delta, doc) {
this.$aceUndo.add(delta, doc);
this._emit("change");
},
execute: function(options) {
if (options.merge && this.lastDeltas) {
this.lastDeltas.push.apply(this.lastDeltas, options.args[0]);
} else {
this.lastDeltas = options.args[0];
this.$undo.add(this.Item(this, this.lastDeltas));
}
addSelection: function(range, rev) {
this.$aceUndo.addSelection(range, rev);
},
undo: function(dontSelect) {
this.dontSelect = dontSelect;
this.$undo.undo();
this.$aceUndo.undo(dontSelect);
this._emit("change");
},
redo: function(dontSelect) {
this.dontSelect = dontSelect;
this.$undo.redo();
this.$aceUndo.redo(dontSelect);
this._emit("change");
},
reset: function(){
this.$undo.reset();
this.$aceUndo.reset();
this._emit("change");
},
hasUndo: function() {
return this.$undo.length > this.$undo.position + 1;
canUndo: function() {
return this.$aceUndo.canUndo();
},
hasRedo: function() {
return this.$undo.length <= this.$undo.position + 1;
canRedo: function() {
return this.$aceUndo.canRedo();
},
get $undoStack() {
return this.$undo.stack.slice(0, this.$undo.position + 1)
.map(function(e){ return e.getState ? e.getState() : e });
clearUndo: function() {
this.$aceUndo.$undoStack = [];
this._emit("change");
},
clearRedo: function() {
this.$aceUndo.$redoStack = [];
this._emit("change");
},
startNewGroup: function() {
return this.$aceUndo.startNewGroup();
},
markIgnored: function(from, to) {
return this.$aceUndo.markIgnored(from, to);
},
getState: function() {
var aceUndo = this.$aceUndo;
var mark = -1;
var aceMark = aceUndo.mark;
var stack = [];
function transform(deltaSet) {
var newDelta = deltaSet.filter(function (d) {
if (d.id == aceMark) mark = stack.length;
return d.action == "insert" || d.action == "remove";
});
stack.push(newDelta);
}
aceUndo.$undoStack.forEach(transform);
if (aceUndo.$redoStackBaseRev == aceUndo.$rev)
aceUndo.$redoStack.forEach(transform);
return {
stack: stack,
mark: mark,
position: aceUndo.$undoStack.length - 1
};
},
setState: function(e, silent) {
var aceUndo = this.$aceUndo;
var stack = e.stack || [];
var marked = stack[e.mark] && stack[e.mark][0];
var pos = e.position + 1;
var undo = stack.slice(0, pos);
var redo = stack.slice(pos);
aceUndo.$undoStack = undo.filter(function(x) {
return x.length;
}).map(updateDeltas);
aceUndo.$redoStack = redo.filter(function(x) {
return x.length;
}).map(updateDeltas);
stack = aceUndo.$undoStack;
var lastDeltaGroup = stack[stack.length - 1];
var lastRev = lastDeltaGroup && lastDeltaGroup[0].id || 0;
aceUndo.$rev = lastRev;
aceUndo.$redoStackBaseRev = aceUndo.$rev;
aceUndo.$maxRev = Math.max(aceUndo.$maxRev, lastRev);
var markedRev = marked && marked.id;
if (markedRev != null)
this.$aceUndo.bookmark(markedRev);
else if (e.mark == e.position)
this.$aceUndo.bookmark();
else
this.$aceUndo.bookmark(-1);
silent || this._emit("change");
},
isAtBookmark: function() {
return this.$aceUndo.isAtBookmark();
},
bookmark: function(rev) {
this.$aceUndo.bookmark(rev);
this._emit("change");
},
bookmarkPosition: function(index) {
if (index > -1) {
var stack = this.$aceUndo.$undoStack;
if (index >= stack.length) {
index -= stack.length;
stack = this.$aceUndo.$redoStack;
index = stack.length - index;
}
var deltaSet = stack[index];
var rev = deltaSet && deltaSet[0] && deltaSet[0].id;
if (rev == null) rev = -1;
this.$aceUndo.bookmark(rev);
} else if (index == -1) {
this.$aceUndo.bookmark(0);
} else {
this.$aceUndo.bookmark(index);
}
this._emit("change");
},
addSession: function(session) {
this.$aceUndo.addSession(session);
},
getPosition: function() {
var aceUndo = this.$aceUndo;
return aceUndo.$undoStack.length - 1;
},
getLength: function() {
var aceUndo = this.$aceUndo;
return aceUndo.$undoStack.length + aceUndo.$redoStack.length;
}
};
function UndoManagerProxy(undoManager, session) {
this.$u = undoManager;
this.$doc = session;
}
(function() {
this.execute = function(options) {
this.$u.execute(options);
};
this.undo = function() {
var selectionRange = this.$u.undo(true);
if (selectionRange) {
this.$doc.selection.setSelectionRange(selectionRange);
}
};
this.redo = function() {
var selectionRange = this.$u.redo(true);
if (selectionRange) {
this.$doc.selection.setSelectionRange(selectionRange);
}
};
this.reset = function() {
this.$u.reset();
};
this.hasUndo = function() {
return this.$u.hasUndo();
};
this.hasRedo = function() {
return this.$u.hasRedo();
};
}).call(UndoManagerProxy.prototype);
/***** Generic Load *****/
handle.on("load", function(){
@ -1370,8 +1440,7 @@ define(function(require, exports, module) {
if (!undoManager)
undoManager = session.getUndoManager();
if (undoManager) {
var undoManagerProxy = new UndoManagerProxy(undoManager, s);
s.setUndoManager(undoManagerProxy);
s.setUndoManager(undoManager);
}
// Overwrite the default $informUndoManager function such that new deltas
@ -2172,9 +2241,9 @@ define(function(require, exports, module) {
var c9Session = doc.getSession();
// if load starts from another editor type
// tabmanager will show as instantly
// tabmanager will show us instantly
// so we need to show progress bar instantly
progress.noFadeIn = !currentDocument;
progress.noFadeIn = !currentDocument || !currentDocument.tab.active;
// Value Retrieval
doc.on("getValue", function get(e) {

View File

@ -80,7 +80,10 @@ define(function(require, exports, module) {
request(apiUrl + "/user", function(err, user) {
if (err || !user) {
console.warn("LOGIN: API /user err", err);
if (options.cli)
console.warn("Invalid username or password. Please try again.");
else
console.warn("LOGIN: API /user err", err);
return setTimeout(login, 1000);
}

View File

@ -1,11 +1,12 @@
define(function(require, module, exports) {
main.consumes = ["Dialog", "util", "dialog.alert"];
main.consumes = ["Dialog", "util", "dialog.alert", "metrics"];
main.provides = ["dialog.alert_internal"];
return main;
function main(options, imports, register) {
var Dialog = imports.Dialog;
var util = imports.util;
var metrics = imports.metrics;
var alertWrapper = imports["dialog.alert"];
/***** Initialization *****/
@ -25,6 +26,8 @@ define(function(require, module, exports) {
/***** Methods *****/
function show(title, header, msg, onhide, options) {
metrics.increment("dialog.error");
return plugin.queue(function(){
if (header === undefined) {
plugin.title = "Notice";

View File

@ -1,13 +1,14 @@
define(function(require, exports, module) {
"use strict";
main.consumes = ["Plugin", "ui"];
main.consumes = ["Plugin", "ui", "metrics"];
main.provides = ["dialog.error"];
return main;
function main(options, imports, register) {
var Plugin = imports.Plugin;
var ui = imports.ui;
var metrics = imports.metrics;
/***** Initialization *****/
@ -84,6 +85,8 @@ define(function(require, exports, module) {
}
function show(message, timeout) {
metrics.increment("dialog.error");
// Error message container
if (!error) {
error = document.body.appendChild(document.createElement("div"));

View File

@ -43,7 +43,7 @@ define(function(require, module, exports) {
function initUndo(){
undoManager.on("change", function(e) {
var c = !undoManager.isAtBookmark();
if (changed !== c || undoManager.position == -1) {
if (changed !== c) {
changed = c;
emit("changed", { changed: c });
}
@ -60,26 +60,24 @@ define(function(require, module, exports) {
}
var state = getState();
undoManager.once("change", function(){
// Bookmark the undo manager
undoManager.bookmark();
// Update state
delete state.changed;
delete state.value;
delete state.meta;
state.undoManager = undoManager.getState();
if (cleansed && editor && state[editor.type])
state[editor.type].cleansed = true;
// Set new state (preserving original state)
if (emit("mergeState") !== false)
setState(state);
});
// Record value (which should add an undo stack item)
plugin.value = value;
// Bookmark the undo manager
undoManager.bookmark();
// Update state
delete state.changed;
delete state.value;
delete state.meta;
state.undoManager = undoManager.getState();
if (cleansed && editor && state[editor.type])
state[editor.type].cleansed = true;
// Set new state (preserving original state)
if (emit("mergeState") !== false)
setState(state);
}
function getState(filter) {

View File

@ -10,7 +10,7 @@ define(function(require, module, exports) {
var plugin = new Plugin("Ajax.org", main.consumes);
var emit = plugin.getEmitter();
var position = -1, mark = null, stack = [];
var position = -1, mark = -2, stack = [];
if (options)
setState(options);
@ -55,7 +55,7 @@ define(function(require, module, exports) {
position = 0;
if (mark < position)
mark = -1;
mark = -2;
emit("change");
}
@ -64,7 +64,7 @@ define(function(require, module, exports) {
stack = stack.slice(0, position + 1);
if (mark > position)
mark = -1;
mark = -2;
if (!noEvent)
emit("change");
@ -91,7 +91,7 @@ define(function(require, module, exports) {
position--;
if (mark == idx)
mark = -1;
mark = -2;
else if (mark > idx)
mark--;
@ -105,8 +105,7 @@ define(function(require, module, exports) {
}
function isAtBookmark(){
return mark !== null && mark == position
|| mark === null && position == -1;
return mark == position;
}
function item(idx) {
@ -133,7 +132,7 @@ define(function(require, module, exports) {
return; // guard against broken stack
stack = state.stack;
emit("change"); //If you remove this again, change the test
emit("change"); // If you remove this again, change the test
}
function findItem(compressedItem) {
@ -146,11 +145,13 @@ define(function(require, module, exports) {
position = -1;
stack = [];
mark = null;
mark = -1;
emit("change");
}
plugin.freezePublicAPI.baseclass();
/**
* The Undo Manager class of Cloud9. Each {@link Document}
* has a single instance of the undo manager that
@ -213,10 +214,6 @@ define(function(require, module, exports) {
*
**/
plugin.freezePublicAPI({
/**
* @ignore
*/
get stack() { return stack; },
/**
* The number of items on the stack. This number will stay the
* same when using {@link UndoManager#undo} and

View File

@ -133,7 +133,7 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
expect(undo.position).to.equal(4);
undo.undo(); check++;
undo.setState({ position : -1, stack : stack, mark : null }); check++;
undo.setState({ position : -1, stack : stack, mark : -1 }); check++;
expect(undo.isAtBookmark()).to.equal(true);
expect(data).to.deep.equal(["a", "q"]);
checkCount();

View File

@ -8,7 +8,7 @@ define(function(require, exports, module) {
"use strict";
main.consumes = [
"Plugin", "info"
"Plugin", "info", "metrics"
];
main.provides = ["error_handler"];
return main;
@ -16,6 +16,7 @@ define(function(require, exports, module) {
function main(options, imports, register) {
var Plugin = imports.Plugin;
var info = imports.info;
var metrics = imports.metrics;
/***** Initialization *****/
@ -57,7 +58,8 @@ define(function(require, exports, module) {
Raygun.setVersion(version + ".0");
}
function reportError(exception, customData, tags) {
function log(exception, customData, tags) {
metrics.increment("errorhandler.log");
if (typeof exception === "string")
exception = new Error(exception);
if (!exception)
@ -78,8 +80,8 @@ define(function(require, exports, module) {
plugin.freezePublicAPI({
/** @deprecated Use log() instead. */
reportError: reportError,
log: reportError
reportError: log,
log: log
});
register(null, { "error_handler" : plugin });

View File

@ -1,6 +1,6 @@
define(function(require, exports, module) {
main.consumes = [
"Plugin", "proc", "c9", "pubsub", "auth", "util"
"Plugin", "proc", "c9", "pubsub", "auth", "util", "installer"
];
main.provides = ["plugin.installer"];
return main;
@ -12,6 +12,9 @@ define(function(require, exports, module) {
var proc = imports.proc;
var auth = imports.auth;
var pubsub = imports.pubsub;
var installer = imports.installer;
var async = require("async");
var escapeShell = util.escapeShell;
var updates = options.updates;
@ -20,11 +23,10 @@ define(function(require, exports, module) {
/***** Initialization *****/
var plugin = new Plugin("Ajax.org", main.consumes);
// var emit = plugin.getEmitter();
var emit = plugin.getEmitter();
var HASSDK = c9.location.indexOf("sdk=0") === -1;
var queue = [];
var installing;
var loaded = false;
@ -69,87 +71,66 @@ define(function(require, exports, module) {
// return;
// }
if (!config.length) return;
if (!config.length)
return callback && callback();
var found = {};
config.forEach(function(item){
if (!found[item.packageName])
found[item.packageName] = true;
else return;
queue.push({ name: item.packageName, version: item.version });
if (installing)
installing.push(item);
});
if (installing) return;
installing = config;
var i = 0;
function next(err){
if (err) console.log(err);
if (!queue[i]) {
installing = false; queue = [];
architect.loadAdditionalPlugins(config, callback);
return;
}
installPlugin(queue[i].name, queue[i].version, next);
i++;
// Only run one installer at a time
if (installing) {
return plugin.once("finished", function(){
installPlugins(config, callback);
});
}
next();
installing = true;
var found = {}, packages = [];
config.forEach(function(item){
if (!found[item.name])
found[item.name] = true;
else return;
packages.push({ name: item.name, version: item.version });
});
async.eachSeries(packages, function(pkg, next){
installPlugin(pkg.name, pkg.version, next);
}, function(err){
installing = false;
emit("finished");
if (err) {
console.error(err.message);
return callback && callback(err);
}
architect.loadAdditionalPlugins(config, callback);
});
}
function installPlugin(name, version, callback){
proc.spawn("bash", {
args: ["-c", ["c9", "install", "--local", "--force", "--accessToken=" + auth.accessToken, escapeShell(name) + "@" + escapeShell(version)].join(" ")]
}, function(err, process){
if (err) return callback(err);
process.stdout.on("data", function(c){
console.log(c);
});
process.stderr.on("data", function(c){
console.error(c);
// Headless installation of the plugin
installer.createSession(name, version, function(session, options){
session.install({
"bash": "c9 install --local --force --accessToken=" + auth.accessToken
+ " " + escapeShell(name) + "@" + escapeShell(version)
});
process.on("exit", function(code){
if (code) {
var error = new Error(err);
error.code = code;
return callback(error);
}
callback();
});
});
// Force to start immediately
session.start(callback, true);
}, function(){}, 2); // Force to not be administered
}
function uninstallPlugin(name, callback){
proc.spawn("c9", {
args: ["remove", "--local", "--force", "--accessToken=" + auth.accessToken, escapeShell(name)]
}, function(err, process){
if (err) return callback(err);
var res = null;
process.stdout.on("data", function(c){
res = c.toString("utf8");
});
process.stderr.on("data", function(c){
err = c.toString("utf8");
// Headless uninstallation of the plugin
installer.createSession(name, -1, function(session, options){
session.install({
"bash": "c9 remove --local --force --accessToken=" + auth.accessToken
+ " " + escapeShell(name)
});
process.on("exit", function(code){
if (code) {
var error = new Error(err);
error.code = code;
return callback(error);
}
callback(null, res);
});
});
// Force to start immediately
session.start(callback, true);
}, function(){}, 2); // Force to not be administered
}
/***** Lifecycle *****/
@ -160,7 +141,6 @@ define(function(require, exports, module) {
plugin.on("unload", function() {
loaded = false;
installing = false;
queue = [];
});
/***** Register and define API *****/
@ -180,6 +160,11 @@ define(function(require, exports, module) {
*/
installPlugins: installPlugins,
/**
*
*/
installPlugin: installPlugin,
/**
*
*/

View File

@ -85,7 +85,9 @@ define(function(require, exports, module) {
};
var TEMPLATES = {
"plugin.simple": "Empty Plugin",
"plugin.default": "Full Plugin"
"plugin.default": "Full Plugin",
"plugin.installer": "Installer Plugin",
"plugin.bundle": "Cloud9 Bundle"
};
// @TODO add sorting
@ -102,7 +104,6 @@ define(function(require, exports, module) {
// var emit = plugin.getEmitter();
var HASSDK = c9.location.indexOf("sdk=0") === -1;
var ENABLED = c9.location.indexOf("sdk=1") > -1;
var model, datagrid, filterbox;
var btnUninstall, btnReport, btnReadme, btnCloud9, btnReload;
@ -125,20 +126,18 @@ define(function(require, exports, module) {
// updateCommandsFromSettings();
// }, plugin);
if (ENABLED) {
menus.addItemByPath("File/New Plugin", null, 210, plugin);
Object.keys(TEMPLATES).forEach(function(name){
menus.addItemByPath("File/New Plugin/" + TEMPLATES[name], new ui.item({
onclick: function(){
createNewPlugin(name);
}
}), 210, plugin);
});
ext.on("register", function(){
setTimeout(reloadModel);
});
}
menus.addItemByPath("File/New Plugin", null, 210, plugin);
Object.keys(TEMPLATES).forEach(function(name){
menus.addItemByPath("File/New Plugin/" + TEMPLATES[name], new ui.item({
onclick: function(){
createNewPlugin(name);
}
}), 210, plugin);
});
ext.on("register", function(){
setTimeout(reloadModel);
});
}
var drawn;

View File

@ -0,0 +1 @@
<div class="helloworld">Hello World</div>

View File

@ -0,0 +1,155 @@
define(function(require, exports, module) {
main.consumes = [
"Plugin", "ui", "commands", "menus", "preferences", "settings"
];
main.provides = ["myplugin"];
return main;
function main(options, imports, register) {
var Plugin = imports.Plugin;
var ui = imports.ui;
var menus = imports.menus;
var commands = imports.commands;
var settings = imports.settings;
var prefs = imports.preferences;
/***** Initialization *****/
var plugin = new Plugin("Ajax.org", main.consumes);
var emit = plugin.getEmitter();
var showing;
function load() {
commands.addCommand({
name: "mycommand",
bindKey: { mac: "Command-I", win: "Ctrl-I" },
isAvailable: function(){ return true; },
exec: function() {
showing ? hide() : show();
}
}, plugin);
menus.addItemByPath("Tools/My Menu Item", new ui.item({
command: "mycommand"
}), 300, plugin);
settings.on("read", function(e){
settings.setDefaults("user/my-plugin", [
["first", "1"],
["second", "all"]
]);
});
prefs.add({
"Example" : {
position: 450,
"My Plugin" : {
position: 100,
"First Setting": {
type: "checkbox",
path: "user/my-plugin/@first",
position: 100
},
"Second Setting": {
type: "dropdown",
path: "user/my-plugin/@second",
width: "185",
position: 200,
items: [
{ value: "you", caption: "You" },
{ value: "me", caption: "Me" },
{ value: "all", caption: "All" }
]
}
}
}
}, plugin);
}
var drawn = false;
function draw() {
if (drawn) return;
drawn = true;
// Insert HTML
var markup = require("text!./plugin.html");
ui.insertHtml(document.body, markup, plugin);
// Insert CSS
ui.insertCss(require("text!./style.css"), options.staticPrefix, plugin);
emit("draw");
}
/***** Methods *****/
function show() {
draw();
var div = document.querySelector(".helloworld");
div.style.display = "block";
div.innerHTML = settings.get("user/my-plugin/@second");
emit("show");
showing = true;
}
function hide() {
if (!drawn) return;
document.querySelector(".helloworld").style.display = "none";
emit("hide");
showing = false;
}
/***** Lifecycle *****/
plugin.on("load", function() {
load();
});
plugin.on("unload", function() {
drawn = false;
showing = false;
});
/***** Register and define API *****/
/**
* This is an example of an implementation of a plugin.
* @singleton
*/
plugin.freezePublicAPI({
/**
* @property showing whether this plugin is being shown
*/
get showing(){ return showing; },
_events: [
/**
* @event show The plugin is shown
*/
"show",
/**
* @event hide The plugin is hidden
*/
"hide"
],
/**
* Show the plugin
*/
show: show,
/**
* Hide the plugin
*/
hide: hide,
});
register(null, {
"myplugin": plugin
});
}
});

View File

@ -0,0 +1,41 @@
"use client";
"use mocha";
define(function(require, exports, module) {
main.consumes = ["plugin.test", "myplugin"];
main.provides = [];
return main;
function main(options, imports, register) {
var test = imports["plugin.test"];
var myplugin = imports.myplugin;
var describe = test.describe;
var it = test.it;
var before = test.before;
var after = test.after;
var beforeEach = test.beforeEach;
var afterEach = test.afterEach;
var assert = test.assert;
var expect = test.expect;
/***** Initialization *****/
describe(myplugin.name, function(){
this.timeout(2000);
it("shows a helloworld div", function() {
myplugin.show();
expect(document.querySelector(".helloworld")).to.ok;
expect(document.querySelector(".helloworld").innerText).to.equal("all");
});
it("hides the div", function() {
myplugin.hide();
expect(document.querySelector(".helloworld").offsetHeight).to.not.ok;
});
});
register(null, {});
}
});

View File

@ -3,7 +3,7 @@ define(function(require, exports, module) {
"Editor", "editors", "ui", "commands", "menus", "layout",
"tabManager", "util", "settings", "api", "c9"
];
main.provides = ["plugin.market"];
main.provides = ["plugin.packages"];
return main;
function main(options, imports, register) {
@ -24,17 +24,17 @@ define(function(require, exports, module) {
var extensions = [];
var packages = {};
var handle = editors.register("plugin.market", "Market Place",
MarketPlace, extensions);
var handle = editors.register("plugin.packages", "Package Browser",
PackageBrowser, extensions);
var emit = handle.getEmitter();
emit.setMaxListeners(1000);
var HASSDK = c9.location.indexOf("sdk=1") > -1;
var HASSDK = c9.location.indexOf("sdk=0") === -1;
function focusOpenMarket(){
function focusOpenPackages(){
var pages = tabs.getTabs();
for (var i = 0, tab = pages[i]; tab; tab = pages[i++]) {
if (tab.editorType == "plugin.market") {
if (tab.editorType == "plugin.packages") {
tabs.focusTab(tab);
return true;
}
@ -49,29 +49,30 @@ define(function(require, exports, module) {
});
commands.addCommand({
name: "openmarketplace",
hint: "open the market place",
name: "openpackagebrowser",
hint: "open the package browser",
group: "General",
// bindKey: { mac: "Command-,", win: "Ctrl-," },
exec: function () {
var tab = tabs.focussedTab;
if (tab && tab.editor.type == "plugin.market") {
if (tab && tab.editor.type == "plugin.packages") {
tab.close();
return;
}
if (focusOpenMarket())
if (focusOpenPackages())
return;
tabs.open({
editorType: "plugin.market",
editorType: "plugin.packages",
active: true
}, function(){});
}
}, handle);
menus.addItemByPath("Cloud9/Plugin Store", new ui.item({
command: "openmarketplace"
}), 301, handle);
menus.addItemByPath("Cloud9/~", new ui.divider(), 1000, handle);
menus.addItemByPath("Cloud9/Package Browser", new ui.item({
command: "openpackagebrowser"
}), 1100, handle);
});
/***** Methods *****/
@ -123,10 +124,10 @@ define(function(require, exports, module) {
/***** Editor *****/
function MarketPlace(){
function PackageBrowser(){
var plugin = new Editor("Ajax.org", main.consumes, extensions);
//var emit = plugin.getEmitter();
var tab;
var tab, iframe;
plugin.on("resize", function(e) {
emit("resize", e);
@ -136,33 +137,15 @@ define(function(require, exports, module) {
tab = e.tab;
var htmlNode = e.htmlNode;
api.packages.get("", function(err, list){
if (c9.standalone) {
err = null;
list = [{ name: "example", apikey:"0000000000000000000000000000=", packagePath: "plugins/c9.example/example" }];
}
if (err) return;
var sHtml = "";
list.forEach(function(plugin){ // @todo use react instead in an iframe
packages[plugin.name] = plugin;
sHtml += "<div>"
+ "<span>" + plugin.name + "</span> | "
+ "<a href='javascript:void(0)' plugin-name='" + plugin.name + "' target='project'>Install In Workspace</a> | "
+ "<a href='javascript:void(0)' plugin-name='" + plugin.name + "' target='user'>Install To User</a>"
+ "</div>";
});
htmlNode.innerHTML = sHtml;
htmlNode.addEventListener("click", function(e){
if (e.target.tagName == "A") {
installPlugin(e.target.getAttribute("plugin-name"),
e.target.getAttribute("target"), function(){});
}
});
});
htmlNode.style.paddingTop = 0;
iframe = htmlNode.appendChild(document.createElement("iframe"));
iframe.style.width = "100%";
iframe.style.height = "100%";
iframe.style.border = 0;
iframe.style.backgroundColor = "#fbfbfb";
iframe.src = location.origin.replace("ide.", "") + "/profile/packages?nobar=1&pid=" + c9.projectId;
});
plugin.on("getState", function(e) {
@ -174,12 +157,11 @@ define(function(require, exports, module) {
plugin.on("documentLoad", function(e) {
var doc = e.doc;
doc.title = "Plugin Store";
doc.title = "Package Browser";
function setTheme(){
// var bg = ui.getStyleRule(".bar-preferences .container .header", "backgroundColor") || "#F0F0F0";
var bg = "#FFF";
doc.tab.backgroundColor = bg; //"#2d2d2d";
var bg = "#fbfbfb";
doc.tab.backgroundColor = bg;
if (util.shadeColor(bg, 1).isLight)
doc.tab.classList.remove("dark");
@ -192,14 +174,7 @@ define(function(require, exports, module) {
});
plugin.on("documentActivate", function(e) {
e.doc.tab.on("unload", function(){
if (parent.parentNode == tab)
tab.removeChild(parent);
});
tab.appendChild(parent);
emit("show");
});
/***** Register and define API *****/
@ -212,13 +187,13 @@ define(function(require, exports, module) {
});
plugin.load(null, "plugin.market");
plugin.load(null, "plugin.packages");
return plugin;
}
register(null, {
"plugin.market": handle
"plugin.packages": handle
});
}
});

View File

@ -0,0 +1 @@
This is the Cloud9 bundle example

View File

@ -0,0 +1,21 @@
{
"name": "",
"description": "",
"version": "0.0.1",
"author": "",
"contributors": [
{
"name": "",
"email": ""
}
],
"repository": {
"type": "git",
"url": ""
},
"plugins": {},
"categories": [
"misc"
],
"licenses": []
}

View File

@ -1,3 +1 @@
# c9.ide.example
This is the Cloud9 default plugin example

View File

@ -1,5 +1,5 @@
{
"name": "c9.ide.default",
"name": "",
"description": "",
"version": "0.0.1",
"author": "",

View File

@ -0,0 +1 @@
This is the Cloud9 installer plugin example

View File

@ -0,0 +1,57 @@
define(function(require, exports, module) {
module.exports = function(session, options){
// Dependencies for the collaboration features of Cloud9
session.install({
"name": "SQLite",
"description": "SQLite Database and NPM module",
"cwd": "~/.c9",
"optional": true
}, [
{
"npm": ["sqlite3@3.0.5"]
},
{
"tar.gz": {
"url": "https://raw.githubusercontent.com/c9/install/master/packages/sqlite3/linux/sqlite3.tar.gz",
"target": "~/.c9/lib/sqlite3",
"dir": "sqlite3"
}
},
{
"symlink": {
"source": "~/.c9/lib/sqlite3/sqlite3",
"target": "~/.c9/bin/sqlite3"
}
}
]);
session.install({
"name": "Sequalize",
"description": "Sequalize NPM module",
"cwd": "~/.c9",
"optional": true
}, {
"npm": ["sequelize@2.0.0-beta.0"]
});
session.install({
"name": "Collab Server",
"description": "A small Node.js collaboration server",
"cwd": "~/.c9",
"optional": true
}, {
"tar.gz": {
"url": "https://raw.githubusercontent.com/c9/install/master/packages/extend/c9-vfs-extend.tar.gz",
"target": "~/.c9"
}
});
// Show the installation screen
session.start();
};
module.exports.version = 1;
});

View File

@ -0,0 +1,22 @@
{
"name": "",
"description": "",
"version": "0.0.1",
"author": "",
"contributors": [
{
"name": "",
"email": ""
}
],
"repository": {
"type": "git",
"url": ""
},
"plugins": {},
"installer": "install.js",
"categories": [
"misc"
],
"licenses": []
}

View File

@ -1,3 +1 @@
# c9.ide.simple
This is the Cloud9 simple plugin example

View File

@ -1,5 +1,5 @@
{
"name": "c9.ide.simple",
"name": "",
"description": "",
"version": "0.0.1",
"author": "",

View File

@ -750,6 +750,9 @@ define(function(require, exports, module) {
session.__defineGetter__("tab", function(){ return doc.tab });
session.__defineGetter__("doc", function(){ return doc });
session.__defineGetter__("defaultEditor", function(){
return settings.getBool("user/terminal/@defaultEditor");
});
session.attach = function(){
if (session.aceSession && aceterm) {

View File

@ -157,6 +157,7 @@ module.exports = function(c9, proc, installPath, shell) {
options.output = false;
options.terminal = true;
options.detachOthers = !session.hasConnected;
options.defaultEditor = session.defaultEditor;
}
// Connect to backend and start tmux session

View File

@ -309,11 +309,8 @@ define(function(require, exports, module) {
doc.meta.$mergeRoot = data;
// If the value on disk is the same as in the document, set the bookmark
if (mergedValue == data) {
doc.undoManager.once("change", function(){
doc.undoManager.bookmark();
});
}
if (mergedValue == data)
doc.undoManager.bookmark();
return true;
}

View File

@ -146,7 +146,7 @@ EventEmitter.prototype.addListener = function(type, listener, plugin) {
if (m && m > 0 && eventList.length > m) {
eventList.warned = true;
console.error('(node) warning: possible EventEmitter memory '
console.error('warning: possible EventEmitter memory '
+ 'leak detected. " + eventList.length + " listeners of type "' + type + '" added. '
+ 'Use emitter.setMaxListeners() to increase limit.'
);

View File

@ -156,6 +156,14 @@ function plugin(options, imports, register) {
res.end("define(function(require, exports, module) { return '"
+ options.workspaceDir + "'; });");
});
api.get("/vfs-home", function(req, res, next) {
if (!options.options.testing)
return next();
res.writeHead(200, {"Content-Type": "application/javascript"});
res.end("define(function(require, exports, module) { return '"
+ process.env.HOME + "'; });");
});
api.get("/update", function(req, res, next) {
res.writeHead(200, {

View File

@ -195,6 +195,7 @@ require([
})(),
log: {},
http: {},
ui: {},
api: {
stats: {
post: function(type, message, cb) {
@ -414,8 +415,13 @@ require([
"metrics": {
getLastPing: function() { throw Error("Not implemented"); },
getLastest: function() { throw Error("Not implemented"); },
log: function() {},
increment: function() {}
},
error_handler: {
log: function() {},
reportError: function(){}
},
error_handler: {reportError: function(){}},
proc: {
execFile: function() {},
spawn: function() {}

View File

@ -28,6 +28,7 @@ module.exports = function(manifest, installPath) {
var config = {
standalone: true,
startBridge: true,
manifest: manifest,
workspaceDir: workspaceDir,
projectName: path.basename(workspaceDir),