From f29e12c78f3e8712a2f12b12e5a46691403076c2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 28 Jul 2012 16:40:09 +0400 Subject: [PATCH 1/9] fix highlighting of multiline clojure strings --- lib/ace/mode/clojure_highlight_rules.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/ace/mode/clojure_highlight_rules.js b/lib/ace/mode/clojure_highlight_rules.js index 0a42e0dc..3ac380c3 100644 --- a/lib/ace/mode/clojure_highlight_rules.js +++ b/lib/ace/mode/clojure_highlight_rules.js @@ -190,10 +190,7 @@ var ClojureHighlightRules = function() { regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b" }, { token : "string", // single line - regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' - }, { - token : "string", // multi line - regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?$', + regex : '"', next: "string" }, { token : "string", // symbol @@ -217,12 +214,16 @@ var ClojureHighlightRules = function() { ], "string" : [ { - token : "string", + token : "constant.language.escape", merge : true, - regex : "\\\\." + regex : "\\\\.|\\\\$" }, { token : "string", - regex : '[^"\\\\]*?"', + merge : true, + regex : '[^"\\\\]+' + }, { + token : "string", + regex : '"', next : "start" } ] From cd6ebd846719812941a62f71ea99485c28f16135 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 28 Jul 2012 16:16:10 +0400 Subject: [PATCH 2/9] improve performance of search result folding --- lib/ace/mode/folding/c9search.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/ace/mode/folding/c9search.js b/lib/ace/mode/folding/c9search.js index 2c9828de..7b8253c7 100644 --- a/lib/ace/mode/folding/c9search.js +++ b/lib/ace/mode/folding/c9search.js @@ -48,18 +48,19 @@ oop.inherits(FoldMode, BaseFoldMode); (function() { - this.foldingStartMarker = /^(\w.*\:|Searching for.*)$/; + this.foldingStartMarker = /^(\S.*\:|Searching for.*)$/; this.foldingStopMarker = /^(\s+|Found.*)$/; this.getFoldWidgetRange = function(session, foldStyle, row) { - var line = session.getLine(row); + var lines = session.doc.getAllLines(row); + var line = lines[row]; var level1 = /^(Found.*|Searching for.*)$/; - var level2 = /^(\w.*\:|\s*)$/; + var level2 = /^(\S.*\:|\s*)$/; var re = level1.test(line) ? level1 : level2; if (this.foldingStartMarker.test(line)) { for (var i = row + 1, l = session.getLength(); i < l; i++) { - if (re.test(session.getLine(i))) + if (re.test(lines[i])) break; } @@ -68,7 +69,7 @@ oop.inherits(FoldMode, BaseFoldMode); if (this.foldingStopMarker.test(line)) { for (var i = row - 1; i >= 0; i--) { - line = session.getLine(i); + line = lines[i]; if (re.test(line)) break; } From 54c0a563087381d5b837bdd5dcc4cfd419653e19 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 28 Jul 2012 20:24:27 +0400 Subject: [PATCH 3/9] cleanup search.js --- lib/ace/search.js | 77 ++++++++++++++++++++---------------------- lib/ace/search_test.js | 18 ++++++++++ 2 files changed, 54 insertions(+), 41 deletions(-) diff --git a/lib/ace/search.js b/lib/ace/search.js index c03391e2..ad3249b8 100644 --- a/lib/ace/search.js +++ b/lib/ace/search.js @@ -137,23 +137,24 @@ var Search = function() { return []; this.$assembleRegExp(options); - if (options.range) { - var range = options.range; - var lines = session.getLines(range.start.row, range.end.row); - } else - var lines = session.doc.getAllLines(); + var range = options.range; + var lines = range + ? session.getLines(range.start.row, range.end.row) + : session.doc.getAllLines(); var ranges = []; var re = options.re; if (options.$isMultiLine) { var len = re.length; var maxRow = lines.length - len; - for (var row = re.offset || 0; row < maxRow; row++) { - for (var j = 0; j < re.length; j++) + for (var row = re.offset || 0; row <= maxRow; row++) { + for (var j = 0; j < len; j++) if (lines[row + j].search(re[j]) == -1) break; - - var startIndex = lines[row + j].match(re[0])[0].length; + + var startLine = lines[row]; + var line = lines[row + len - 1]; + var startIndex = startLine.match(re[0])[0].length; var endIndex = line.match(re[len - 1])[0].length; ranges.push(new Range( @@ -167,11 +168,11 @@ var Search = function() { for (var j = 0; j < matches.length; j++) { var match = matches[j]; ranges.push(new Range(i, match.offset, i, match.offset + match.length)); - }; + } } } - if (options.range) { + if (range) { var startColumn = range.start.column; var endColumn = range.start.column; var i = 0, j = ranges.length - 1; @@ -210,7 +211,7 @@ var Search = function() { if (!match || match[0].length != input.length) return null; - replacement = input.replace(re, replacement) + replacement = input.replace(re, replacement); if (options.preserveCase) { replacement = replacement.split(""); for (var i = Math.min(input.length, input.length); i--; ) { @@ -261,21 +262,21 @@ var Search = function() { if (callback(range)) return true; - } + }; } else if (backwards) { var matchIterator = function(line, row, startIndex) { var matches = lang.getMatchOffsets(line, re); for (var i = matches.length-1; i >= 0; i--) if (callback(matches[i], row, startIndex)) return true; - } + }; } else { var matchIterator = function(line, row, startIndex) { var matches = lang.getMatchOffsets(line, re); for (var i = 0; i < matches.length; i++) if (callback(matches[i], row, startIndex)) return true; - } + }; } return { @@ -310,7 +311,7 @@ var Search = function() { try { var re = new RegExp(needle, modifier); } catch(e) { - var re = false; + re = false; } return options.re = re; }; @@ -333,7 +334,6 @@ var Search = function() { }; this.$lineIterator = function(session, options) { - var range = options.range; var backwards = options.backwards == true; var skipCurrent = options.skipCurrent != false; @@ -346,30 +346,9 @@ var Search = function() { start = start[skipCurrent != backwards ? "end" : "start"]; var firstRow = range ? range.start.row : 0; - var firstColumn = range ? range.start.column : 0; var lastRow = range ? range.end.row : session.getLength() - 1; - if (!backwards) { - var forEach = function(callback) { - var row = start.row; - - var line = session.getLine(row).substr(start.column); - if (callback(line, row, start.column)) - return; - - for (row = row+1; row <= lastRow; row++) - if (callback(session.getLine(row), row)) - return; - - if (options.wrap == false) - return; - - for (row = firstRow, lastRow = start.row; row <= lastRow; row++) - if (callback(session.getLine(row), row)) - return; - } - } else { - var forEach = function(callback) { + var forEach = backwards ? function(callback) { var row = start.row; var line = session.getLine(row).substring(0, start.column); @@ -386,9 +365,25 @@ var Search = function() { for (row = lastRow, firstRow = start.row; row >= firstRow; row--) if (callback(session.getLine(row), row)) return; - } - } + } : function(callback) { + var row = start.row; + var line = session.getLine(row).substr(start.column); + if (callback(line, row, start.column)) + return; + + for (row = row+1; row <= lastRow; row++) + if (callback(session.getLine(row), row)) + return; + + if (options.wrap == false) + return; + + for (row = firstRow, lastRow = start.row; row <= lastRow; row++) + if (callback(session.getLine(row), row)) + return; + }; + return {forEach: forEach}; }; diff --git a/lib/ace/search_test.js b/lib/ace/search_test.js index 7a28d89c..c098e905 100644 --- a/lib/ace/search_test.js +++ b/lib/ace/search_test.js @@ -339,6 +339,24 @@ module.exports = { assert.position(ranges[1].start, 2, 1); assert.position(ranges[1].end, 2, 3); }, + + + "test: find all multiline matches" : function() { + var session = new EditSession(["juhu", "juhu", "juhu", "juhu"]); + + var search = new Search().set({ + needle: "hu\nju", + wrap: true + }); + + var ranges = search.findAll(session); + + assert.equal(ranges.length, 3); + assert.position(ranges[0].start, 0, 2); + assert.position(ranges[0].end, 1, 2); + assert.position(ranges[1].start, 1, 2); + assert.position(ranges[1].end, 2, 2); + }, "test: replace() should return the replacement if the input matches the needle" : function() { var search = new Search().set({ From 22ee0d0bc88a82a9e42c9b8244012591242c55e0 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 28 Jul 2012 16:42:12 +0400 Subject: [PATCH 4/9] fix typos --- lib/ace/commands/default_commands.js | 2 ++ lib/ace/lib/net.js | 2 +- lib/ace/mouse/fold_handler.js | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/ace/commands/default_commands.js b/lib/ace/commands/default_commands.js index 415fc2e9..c2140289 100644 --- a/lib/ace/commands/default_commands.js +++ b/lib/ace/commands/default_commands.js @@ -117,11 +117,13 @@ exports.commands = [{ name: "selecttostart", bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Up"), exec: function(editor) { editor.getSelection().selectFileStart(); }, + multiSelectAction: "forEach", readOnly: true }, { name: "gotostart", bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"), exec: function(editor) { editor.navigateFileStart(); }, + multiSelectAction: "forEach", readOnly: true }, { name: "selectup", diff --git a/lib/ace/lib/net.js b/lib/ace/lib/net.js index 438a26a2..bdb01ab6 100644 --- a/lib/ace/lib/net.js +++ b/lib/ace/lib/net.js @@ -8,7 +8,7 @@ define(function(require, exports, module) { "use strict"; -var useragent = require("ace/lib/useragent"); +var useragent = require("./useragent"); exports.get = function (url, callback) { var xhr = exports.createXhr(); diff --git a/lib/ace/mouse/fold_handler.js b/lib/ace/mouse/fold_handler.js index 2064660e..d7b6470e 100644 --- a/lib/ace/mouse/fold_handler.js +++ b/lib/ace/mouse/fold_handler.js @@ -62,7 +62,8 @@ function FoldHandler(editor) { if (gutterRegion == "foldWidgets") { var row = e.getDocumentPosition().row; - if (editor.session.foldWidgets[row]) + var session = editor.session; + if (session.foldWidgets && session.foldWidgets[row]) editor.session.onFoldWidgetClick(row, e); e.stop(); } From 0e5b77763f6433137837d328c6edf38c6403bb56 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 28 Jul 2012 16:53:56 +0400 Subject: [PATCH 5/9] revert acc3faf42ce69d004656d3b32b1be79b95954c87 since it was not working with folding enabled --- lib/ace/css/editor.css | 6 +++++ lib/ace/virtual_renderer.js | 49 ++++++++++++++----------------------- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/lib/ace/css/editor.css b/lib/ace/css/editor.css index 2b9967a7..f0d31f10 100644 --- a/lib/ace/css/editor.css +++ b/lib/ace/css/editor.css @@ -27,6 +27,12 @@ z-index: 4; } +.ace_gutter_active_line { + position: absolute; + left: 0; + right: 0; +} + .ace_scroller.horscroll { box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset; } diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index d9a0c241..b9abc187 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -102,6 +102,7 @@ var VirtualRenderer = function(container, theme) { this.content.className = "ace_content"; this.scroller.appendChild(this.content); + this.setHighlightGutterLine(true); this.$gutterLayer = new GutterLayer(this.$gutter); this.$gutterLayer.on("changeGutterWidth", this.onResize.bind(this, true)); this.setFadeFoldWidgets(true); @@ -468,38 +469,30 @@ var VirtualRenderer = function(container, theme) { dom.removeCssClass(this.$gutter, "ace_fade-fold-widgets"); }; - this.$highlightGutterLine = true; + this.$highlightGutterLine = false; this.setHighlightGutterLine = function(shouldHighlight) { if (this.$highlightGutterLine == shouldHighlight) return; this.$highlightGutterLine = shouldHighlight; - this.$loop.schedule(this.CHANGE_GUTTER); + if (!this.$gutterLineHighlight) { + this.$gutterLineHighlight = dom.createElement("div"); + this.$gutterLineHighlight.className = "ace_gutter_active_line"; + this.$gutter.appendChild(this.$gutterLineHighlight); + return; + } + + this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none"; + this.$updateGutterLineHighlight(); }; this.getHighlightGutterLine = function() { return this.$highlightGutterLine; }; - this.$updateGutterLineHighlight = function(gutterReady) { - var i = this.session.selection.lead.row; - if (i == this.$gutterLineHighlight) - return; - - if (!gutterReady) { - var lineEl, ch = this.$gutterLayer.element.children; - var index = this.$gutterLineHighlight - this.layerConfig.firstRow; - if (index >= 0 && (lineEl = ch[index])) - dom.removeCssClass(lineEl, "ace_gutter_active_line"); - - index = i - this.layerConfig.firstRow; - if (index >= 0 && (lineEl = ch[index])) - dom.addCssClass(lineEl, "ace_gutter_active_line"); - } - - this.$gutterLayer.removeGutterDecoration(this.$gutterLineHighlight, "ace_gutter_active_line"); - this.$gutterLayer.addGutterDecoration(i, "ace_gutter_active_line"); - this.$gutterLineHighlight = i; + this.$updateGutterLineHighlight = function() { + this.$gutterLineHighlight.style.top = this.$cursorLayer.$pixelPos.top - this.layerConfig.offset + "px"; + this.$gutterLineHighlight.style.height = this.layerConfig.lineHeight + "px"; }; this.$updatePrintMargin = function() { @@ -693,15 +686,13 @@ var VirtualRenderer = function(container, theme) { // update scrollbar first to not lose scroll position when gutter calls resize this.$updateScrollBar(); this.$textLayer.update(this.layerConfig); - if (this.showGutter) { - if (this.$highlightGutterLine) - this.$updateGutterLineHighlight(true); + if (this.showGutter) this.$gutterLayer.update(this.layerConfig); - } this.$markerBack.update(this.layerConfig); this.$markerFront.update(this.layerConfig); this.$cursorLayer.update(this.layerConfig); this.$moveTextAreaToCursor(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); return; } @@ -713,15 +704,13 @@ var VirtualRenderer = function(container, theme) { else this.$textLayer.scrollLines(this.layerConfig); - if (this.showGutter) { - if (this.$highlightGutterLine) - this.$updateGutterLineHighlight(true); + if (this.showGutter) this.$gutterLayer.update(this.layerConfig); - } this.$markerBack.update(this.layerConfig); this.$markerFront.update(this.layerConfig); this.$cursorLayer.update(this.layerConfig); this.$moveTextAreaToCursor(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); return; } @@ -744,7 +733,7 @@ var VirtualRenderer = function(container, theme) { if (changes & this.CHANGE_CURSOR) { this.$cursorLayer.update(this.layerConfig); this.$moveTextAreaToCursor(); - this.$highlightGutterLine && this.$updateGutterLineHighlight(false); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); } if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) { From 2d0b6fc49f4cffc3e895c9bb8690f88d89fc68af Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 27 Jul 2012 01:27:48 +0400 Subject: [PATCH 6/9] fix starting selection from inside selection --- lib/ace/mouse/default_handlers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/mouse/default_handlers.js b/lib/ace/mouse/default_handlers.js index 21ca5e84..8a9b2585 100644 --- a/lib/ace/mouse/default_handlers.js +++ b/lib/ace/mouse/default_handlers.js @@ -225,7 +225,7 @@ function DefaultHandlers(mouseHandler) { var editor = this.editor; if (distance > DRAG_OFFSET) { - this.startSelect(); + this.startSelect(this.mousedownEvent.getDocumentPosition()); } else if (time - this.mousedownEvent.time > editor.getDragDelay()) { this.startDrag(); } From f97666315006ee30f9e773ae7c6072b64b563ac5 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 29 Jul 2012 15:04:40 +0400 Subject: [PATCH 7/9] remove redundant getRowHeight method --- lib/ace/edit_session.js | 14 +------------- lib/ace/layer/gutter.js | 2 +- lib/ace/test/mockrenderer.js | 4 ++-- lib/ace/virtual_renderer.js | 10 +++++----- 4 files changed, 9 insertions(+), 21 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index b903356a..144f2aff 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -2029,7 +2029,7 @@ var EditSession = function(text, mode) { * - row (Number): The row number to check * * - * Returns the length of the indicated row. + * Returns number of screenrows in a wrapped line. **/ this.getRowLength = function(row) { if (!this.$useWrapMode || !this.$wrapData[row]) { @@ -2039,18 +2039,6 @@ var EditSession = function(text, mode) { } }; - /** - * EditSession.getRowHeight(config, row) -> Number - * - config (Object): An object containing a parameter indicating the `lineHeight`. - * - row (Number): The row number to check - * - * Returns the height of the indicated row. This is mostly relevant for situations where wrapping occurs, and a single line spans across multiple rows. - * - **/ - this.getRowHeight = function(config, row) { - return this.getRowLength(row) * config.lineHeight; - }; - /** internal, hide, related to: EditSession.documentToScreenColumn * EditSession.getScreenLastRowColumn(screenRow) -> Number * - screenRow (Number): The screen row to check diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index d30c4ba3..2bf3bc53 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -129,7 +129,7 @@ var Gutter = function(parentEl) { breakpoints[i] ? " ace_breakpoint " : " ", annotation.className, "' title='", annotation.text.join("\n"), - "' style='height:", this.session.getRowLength(i) * config.lineHeight, "px;'>", (i+1)); + "' style='height:", this.session.getRowLength(i) * config.lineHeight, "px;'>", (i)); if (foldWidgets) { var c = foldWidgets[i]; diff --git a/lib/ace/test/mockrenderer.js b/lib/ace/test/mockrenderer.js index 4e5c515d..91b1c1ad 100644 --- a/lib/ace/test/mockrenderer.js +++ b/lib/ace/test/mockrenderer.js @@ -115,10 +115,10 @@ MockRenderer.prototype.scrollToX = function(scrollTop) {}; MockRenderer.prototype.scrollToY = function(scrollLeft) {}; MockRenderer.prototype.scrollToLine = function(line, center) { - var lineHeight = { lineHeight: 16 }; + var lineHeight = 16; var row = 0; for (var l = 1; l < line; l++) { - row += this.session.getRowHeight(lineHeight, l-1) / lineHeight.lineHeight; + row += this.session.getRowLength(l-1); } if (center) { diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index b9abc187..6a6dae4b 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -775,7 +775,7 @@ var VirtualRenderer = function(container, theme) { // Map lines on the screen to lines in the document. var firstRowScreen, firstRowHeight; - var lineHeight = { lineHeight: this.lineHeight }; + var lineHeight = this.lineHeight; firstRow = session.screenToDocumentRow(firstRow, 0); // Check if firstRow is inside of a foldLine. If true, then use the first @@ -786,13 +786,13 @@ var VirtualRenderer = function(container, theme) { } firstRowScreen = session.documentToScreenRow(firstRow, 0); - firstRowHeight = session.getRowHeight(lineHeight, firstRow); + firstRowHeight = session.getRowLength(firstRow) * lineHeight; lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1); - minHeight = this.$size.scrollerHeight + session.getRowHeight(lineHeight, lastRow)+ + minHeight = this.$size.scrollerHeight + session.getRowLength(lastRow) * lineHeight + firstRowHeight; - offset = this.scrollTop - firstRowScreen * this.lineHeight; + offset = this.scrollTop - firstRowScreen * lineHeight; this.layerConfig = { width : longestLine, @@ -800,7 +800,7 @@ var VirtualRenderer = function(container, theme) { firstRow : firstRow, firstRowScreen: firstRowScreen, lastRow : lastRow, - lineHeight : this.lineHeight, + lineHeight : lineHeight, characterWidth : this.characterWidth, minHeight : minHeight, maxHeight : maxHeight, From abcf0d4771ff06cbee3e1a6c5003de3933872eb4 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 31 Jul 2012 20:37:33 +0400 Subject: [PATCH 8/9] fix #855 do not stop mousemove events on old browsers --- lib/ace/lib/event.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/ace/lib/event.js b/lib/ace/lib/event.js index 87da2cb2..9d03f868 100644 --- a/lib/ace/lib/event.js +++ b/lib/ace/lib/event.js @@ -108,11 +108,6 @@ exports.getButton = function(e) { if (document.documentElement.setCapture) { exports.capture = function(el, eventHandler, releaseCaptureHandler) { - function onMouseMove(e) { - eventHandler(e); - return exports.stopPropagation(e); - } - var called = false; function onReleaseCapture(e) { eventHandler(e); @@ -137,22 +132,17 @@ if (document.documentElement.setCapture) { } else { exports.capture = function(el, eventHandler, releaseCaptureHandler) { - function onMouseMove(e) { - eventHandler(e); - e.stopPropagation(); - } - function onMouseUp(e) { eventHandler && eventHandler(e); releaseCaptureHandler && releaseCaptureHandler(e); - document.removeEventListener("mousemove", onMouseMove, true); + document.removeEventListener("mousemove", eventHandler, true); document.removeEventListener("mouseup", onMouseUp, true); e.stopPropagation(); } - document.addEventListener("mousemove", onMouseMove, true); + document.addEventListener("mousemove", eventHandler, true); document.addEventListener("mouseup", onMouseUp, true); }; } From a9caa1144706c011421f587f6798ad428a1492ff Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 3 Aug 2012 18:27:32 +0400 Subject: [PATCH 9/9] fix pasting in readOnly mode --- lib/ace/editor.js | 3 +++ lib/ace/multi_select.js | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 5b387f98..4cf4ef80 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -694,6 +694,9 @@ var Editor = function(renderer, session) { * called whenever a text "paste" happens. **/ this.onPaste = function(text) { + // todo this should change when paste becomes a command + if (this.$readOnly) + return; this._emit("paste", text); this.insert(text); }; diff --git a/lib/ace/multi_select.js b/lib/ace/multi_select.js index 9cbc5417..eeae8039 100644 --- a/lib/ace/multi_select.js +++ b/lib/ace/multi_select.js @@ -502,7 +502,11 @@ var Editor = require("./editor").Editor; return text; }; + // todo this should change when paste becomes a command this.onPaste = function(text) { + if (this.$readOnly) + return; + this._emit("paste", text); if (!this.inMultiSelectMode) return this.insert(text);