diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 3bdf1a08..97e78d36 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -50,8 +50,6 @@ var defaultCommands = require("./commands/default_commands").commands; var config = require("./config"); /** - * - * * The main entry point into the Ace functionality. * * The `Editor` manages the [[EditSession]] (which manages [[Document]]s), as well as the [[VirtualRenderer]], which draws everything to the screen. @@ -101,59 +99,40 @@ var Editor = function(renderer, session) { oop.implement(this, EventEmitter); this.$historyTracker = function(e) { + if (!this.$mergeUndoDeltas) + return; + var previous = this.previousCommand || {command:{}}; + var mergeableCommands = ["backspace", "del", "insertstring"]; if (e.command.name == "insertstring") { var text = e.args; - if (this.mergeNextCommand === undefined) { + 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; + var shouldMerge = e.command.name == previous.command.name // previous command was the same + && !this.cursorMoved // cursor was not moved since last command + && this.mergeNextCommand // previous command allows to coalesce with + && (!/\s/.test(text) || /\s/.test(previous.args)) // previous insertion was of same type + 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; + var shouldMerge = e.command.name == previous.command.name // previous command was the same + && mergeableCommands.indexOf(e.command.name) !== -1// the command is mergeable + && !this.cursorMoved // cursor was not moved since last command } + + if ( + this.$mergeUndoDeltas != "always" + && Date.now() - this.sequenceStartTime < 2000 + ) { + shouldMerge = false; // the sequence is too long + } + + if (shouldMerge) + this.session.mergeUndoDeltas = true; + else if (mergeableCommands.indexOf(e.command.name) !== -1) + this.sequenceStartTime = Date.now(); + this.cursorMoved = false; + this.previousCommand = e; }; /** @@ -2308,6 +2287,10 @@ config.defineOptions(Editor.prototype, "editor", { values: ["ace", "slim", "smooth", "wide"], initialValue: "ace" }, + mergeUndoDeltas: { + values: [false, true, "always"], + initialValue: false + }, behavioursEnabled: {initialValue: true}, wrapBehavioursEnabled: {initialValue: true},