diff --git a/node_modules/ace/lib/ace/edit_session.js b/node_modules/ace/lib/ace/edit_session.js index e385647a..30a8749d 100644 --- a/node_modules/ace/lib/ace/edit_session.js +++ b/node_modules/ace/lib/ace/edit_session.js @@ -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); @@ -376,7 +378,7 @@ var EditSession = function(text, mode) { if (undoManager) { var self = this; - undoManager.setSession(this); + undoManager.addSession(this); this.$syncInformUndoManager = function() { self.$informUndoManager.cancel(); self.mergeUndoDeltas = false; @@ -402,7 +404,7 @@ var EditSession = function(text, mode) { add: function() {}, addSelection: function() {}, startNewGroup: function() {}, - setSession: function() {}, + addSession: function() {}, }; /** diff --git a/node_modules/ace/lib/ace/editor.js b/node_modules/ace/lib/ace/editor.js index ce099e62..8d816cbd 100644 --- a/node_modules/ace/lib/ace/editor.js +++ b/node_modules/ace/lib/ace/editor.js @@ -2496,7 +2496,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); }; @@ -2505,7 +2505,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); }; diff --git a/node_modules/ace/lib/ace/split.js b/node_modules/ace/lib/ace/split.js index 878b0dc3..e960c128 100644 --- a/node_modules/ace/lib/ace/split.js +++ b/node_modules/ace/lib/ace/split.js @@ -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; }); diff --git a/node_modules/ace/lib/ace/test/all_browser.js b/node_modules/ace/lib/ace/test/all_browser.js index 7ac5092e..71e96e2f 100644 --- a/node_modules/ace/lib/ace/test/all_browser.js +++ b/node_modules/ace/lib/ace/test/all_browser.js @@ -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("", href.replace(/^ace\//, "") ,"
"); } + +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) + "
", (passed ? "Passed tests: " + passed + "
" : ""), (failed ? "Failed tests: " + failed + "
" : "") - ].join("") + ].join(""); console.log("Total number of tests: " + (passed + failed)); console.log("Passed tests: " + passed); console.log("Failed tests: " + failed); - }) + }); }); }); diff --git a/node_modules/ace/lib/ace/undomanager.js b/node_modules/ace/lib/ace/undomanager.js index 3bf6b5bc..c23eb4f9 100644 --- a/node_modules/ace/lib/ace/undomanager.js +++ b/node_modules/ace/lib/ace/undomanager.js @@ -49,7 +49,7 @@ var UndoManager = function() { (function() { - this.setSession = function(session) { + this.addSession = function(session) { this.$session = session; }; /** @@ -61,13 +61,16 @@ var UndoManager = function() { * @param {Object} options Contains additional properties * **/ - this.add = function(delta, allowMerge) { + 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; } + if (delta.action == "remove" || delta.action == "insert") + this.$lastDelta = delta; this.lastDeltas.push(delta); }; @@ -144,7 +147,7 @@ var UndoManager = function() { * * @returns {Range} The range of the undo. **/ - this.undo = function(dontSelect) { + this.undo = function(session, dontSelect) { this.lastDeltas = null; var stack = this.$undoStack; @@ -159,7 +162,7 @@ var UndoManager = function() { var deltaSet = stack.pop(); var undoSelectionRange = null; if (deltaSet && deltaSet.length) { - undoSelectionRange = this.$session.undoChanges(deltaSet, dontSelect); + undoSelectionRange = session.undoChanges(deltaSet, dontSelect); this.$redoStack.push(deltaSet); this.$syncRev(); } @@ -174,7 +177,7 @@ var UndoManager = function() { * @param {Boolean} dontSelect {:dontSelect} * **/ - this.redo = function(dontSelect) { + this.redo = function(session, dontSelect) { this.lastDeltas = null; this.$fromUndo = true; @@ -190,7 +193,7 @@ var UndoManager = function() { var redoSelectionRange = null; if (deltaSet) { - redoSelectionRange = this.$session.redoChanges(deltaSet, dontSelect); + redoSelectionRange = session.redoChanges(deltaSet, dontSelect); this.$undoStack.push(deltaSet); this.$syncRev(); } @@ -212,6 +215,7 @@ var UndoManager = function() { **/ this.reset = function() { this.lastDeltas = null; + this.$lastDelta = null; this.$undoStack = []; this.$redoStack = []; this.$rev = 0; diff --git a/node_modules/ace/lib/ace/undomanager_test.js b/node_modules/ace/lib/ace/undomanager_test.js new file mode 100644 index 00000000..6d0dbf58 --- /dev/null +++ b/node_modules/ace/lib/ace/undomanager_test.js @@ -0,0 +1,92 @@ +/* ***** 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({start: {row: 0, column: 10}, end: {row: 0, column: 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); + } +}; + +}); + +if (typeof module !== "undefined" && module === require.main) { + require("asyncjs").test.testcase(module.exports).exec(); +} diff --git a/plugins/c9.ide.ace/ace.js b/plugins/c9.ide.ace/ace.js index 1affd8b2..d453afc0 100644 --- a/plugins/c9.ide.ace/ace.js +++ b/plugins/c9.ide.ace/ace.js @@ -352,6 +352,12 @@ define(function(require, exports, module) { this.$aceUndo.$redoStack = []; this._emit("changeSync"); }, + startNewGroup: function() { + return this.$aceUndo.startNewGroup(); + }, + markIgnored: function(from, to) { + return this.$aceUndo.markIgnored(from, to); + }, getState: function() { console.log("getState()"); var aceUndo = this.$aceUndo; @@ -371,9 +377,9 @@ define(function(require, exports, module) { var aceUndo = this.$aceUndo; aceUndo.$undoStack = (e.stack || []).filter(function(x) { return x.length; - }); + }).map(updateDeltas); var stack = aceUndo.$undoStack; - var lastDeltaGroup = stack[stack.length] - 1; + var lastDeltaGroup = stack[stack.length - 1]; var lastRev = lastDeltaGroup && lastDeltaGroup[0].id || 0; aceUndo.$rev = lastRev; aceUndo.$maxRev = Math.max(aceUndo.$maxRev, lastRev); @@ -404,70 +410,19 @@ define(function(require, exports, module) { } this._emit("changeSync"); }, - setSession: function(session) { - this.$aceUndo.setSession(session); + addSession: function(session) { + this.$aceUndo.addSession(session); }, getPosition: function() { var aceUndo = this.$aceUndo; return aceUndo.$undoStack.length - 1; }, - getMark: 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.add = function(delta, doc) { - this.$u.add(delta, doc); - }; - - Object.defineProperty(this, "", { - configurable: true, - get: function() { - return this.$u.lastDeltas; - }, - set: function(v) { - this.$u.lastDeltas = v; - } - }); - - 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(){ @@ -1463,8 +1418,7 @@ define(function(require, exports, module) { if (!undoManager) undoManager = session.getUndoManager(); if (undoManager) { - var undoManagerProxy = new UndoManagerProxy(undoManager, s); - s.setUndoManager(undoManagerProxy.$aceUndo); + s.setUndoManager(undoManager); } // Overwrite the default $informUndoManager function such that new deltas diff --git a/plugins/c9.ide.editors/document.js b/plugins/c9.ide.editors/document.js index ec70358e..6c7174c5 100644 --- a/plugins/c9.ide.editors/document.js +++ b/plugins/c9.ide.editors/document.js @@ -40,15 +40,16 @@ define(function(require, module, exports) { // Listen to changes and detect when the value of the editor // is different from what is on disk - function updateStatus(e) { - var c = !undoManager.isAtBookmark(); - if (changed !== c) { - changed = c; - emit("changed", { changed: c }); - } + function initUndo(){ + undoManager.on("change", function(e) { + var c = !undoManager.isAtBookmark(); + if (changed !== c) { + changed = c; + emit("changed", { changed: c }); + } + }); } - undoManager.on("change", updateStatus); - undoManager.on("changeSync", updateStatus); + initUndo(); /***** Methods *****/