From ef2e2cdd1164ffd28adfac0a7511f4fb7621e034 Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 17 Jun 2013 01:30:22 +0400 Subject: [PATCH] move undo delta merging to the editor --- lib/ace/edit_session.js | 4 +-- lib/ace/editor.js | 63 ++++++++++++++++++++++++++++++++-- lib/ace/keyboard/keybinding.js | 52 +--------------------------- 3 files changed, 64 insertions(+), 55 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index facc4e4e..cc34ce6f 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -407,10 +407,10 @@ var EditSession = function(text, mode) { undoManager.execute({ action: "aceupdate", args: [self.$deltas, self], - merge: self.coalesceDeltas + merge: self.mergeUndoDeltas }); } - self.coalesceDeltas = false; + self.mergeUndoDeltas = false; self.$deltas = []; } this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager); diff --git a/lib/ace/editor.js b/lib/ace/editor.js index e1403414..3bdf1a08 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -88,6 +88,9 @@ var Editor = function(renderer, session) { wrap: true }); + this.$historyTracker = this.$historyTracker.bind(this); + this.commands.on("exec", this.$historyTracker); + this.setSession(session || new EditSession("")); config.resetOptions(this); config._emit("editor", this); @@ -96,6 +99,62 @@ var Editor = function(renderer, session) { (function(){ oop.implement(this, EventEmitter); + + this.$historyTracker = function(e) { + if (e.command.name == "insertstring") { + var text = e.args; + if (this.mergeNextCommand === undefined) { + this.mergeNextCommand = true; + } + var previousCommand = this.previousCommand || {}; + if ( + // previous command was the same + "insertstring" == previousCommand.name + // cursor was not moved since last command + && !this.cursorMoved + // previous command allows to coalesce with + && this.mergeNextCommand + // previous insertion was not a new line or a whitespace + // or this is a sequence of a new line or a whitespace insertions + && (!/ |\r\n|\r|\n/.test(text) || / |\r\n|\r|\n/.test(previousCommand.text)) + // the sequence is not too long + && (new Date()) - this.sequenceStartTime < 2000 + ) + this.session.mergeUndoDeltas = true; + else + this.sequenceStartTime = new Date().getTime(); + + this.previousCommand = { + name: "insertstring", + text: text + } + this.cursorMoved = false; + this.mergeNextCommand = true; + } else { + var mergeableCommands = ["backspace", "del"]; + var previousCommand = this.previousCommand || {}; + if ( + // previous command was the same + e.command.name == previousCommand.name + // the command is mergeable + && mergeableCommands.indexOf(e.command.name) !== -1 + // cursor was not moved since last command + && !this.cursorMoved + // the sequence is not too long + && (new Date()) - this.sequenceStartTime < 2000 + ) + this.session.mergeUndoDeltas = true + else + if (mergeableCommands.indexOf(e.command.name) !== -1) + this.sequenceStartTime = new Date().getTime(); + + this.previousCommand = { + name: e.command.name, + text: e.command.text + } + this.cursorMoved = false; + } + }; /** * Sets a new key handler, such as "vim" or "windows". @@ -703,8 +762,8 @@ var Editor = function(renderer, session) { var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text); if (transform) { if (text !== transform.text) { - this.session.coalesceDeltas = false; - this.coalesceNextCommand = false; + this.session.mergeUndoDeltas = false; + this.$mergeNextCommand = false; } text = transform.text; diff --git a/lib/ace/keyboard/keybinding.js b/lib/ace/keyboard/keybinding.js index a02a6346..9c54a947 100644 --- a/lib/ace/keyboard/keybinding.js +++ b/lib/ace/keyboard/keybinding.js @@ -105,28 +105,6 @@ var KeyBinding = function(editor) { if (toExecute.command == "null") { success = true; } else { - var mergeableCommands = ["backspace", "del"]; - var previousCommand = this.$editor.previousCommand || {}; - if ( - // previous command was the same - toExecute.command.name == previousCommand.name - // the command is mergeable - && mergeableCommands.indexOf(toExecute.command.name) !== -1 - // cursor was not moved since last command - && !this.$editor.cursorMoved - // the sequence is not too long - && (new Date()) - this.$editor.sequenceStartTime < 2000 - ) - this.$editor.session.coalesceDeltas = true - else - if (mergeableCommands.indexOf(toExecute.command.name) !== -1) - this.$editor.sequenceStartTime = new Date().getTime(); - - this.$editor.previousCommand = { - name: toExecute.command.name, - text: toExecute.command.text - } - this.$editor.cursorMoved = false; success = commands.exec(toExecute.command, this.$editor, toExecute.args, e); } // do not stop input events to not break repeating @@ -145,36 +123,8 @@ var KeyBinding = function(editor) { this.onTextInput = function(text) { var success = this.$callKeyboardHandlers(-1, text); - if (!success) { - if (this.$editor.coalesceNextCommand === undefined) { - this.$editor.coalesceNextCommand = true; - } - var previousCommand = this.$editor.previousCommand || {}; - if ( - // previous command was the same - "insertstring" == previousCommand.name - // cursor was not moved since last command - && !this.$editor.cursorMoved - // previous command allows to coalesce with - && this.$editor.coalesceNextCommand - // previous insertion was not a new line or a whitespace - // or this is a sequence of a new line or a whitespace insertions - && (!/ |\r\n|\r|\n/.test(text) || / |\r\n|\r|\n/.test(previousCommand.text)) - // the sequence is not too long - && (new Date()) - this.$editor.sequenceStartTime < 2000 - ) - this.$editor.session.coalesceDeltas = true; - else - this.$editor.sequenceStartTime = new Date().getTime(); - - this.$editor.previousCommand = { - name: "insertstring", - text: text - } - this.$editor.cursorMoved = false; - this.$editor.coalesceNextCommand = true; + if (!success) this.$editor.commands.exec("insertstring", this.$editor, text); - } }; }).call(KeyBinding.prototype);