diff --git a/lib/ace/clipboard.js b/lib/ace/clipboard.js new file mode 100644 index 00000000000..b1a7635427b --- /dev/null +++ b/lib/ace/clipboard.js @@ -0,0 +1,36 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2012, 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 ***** */ + +define(function(require, exports, module) { +"use strict"; + +module.exports = { lineMode: false }; + +}); diff --git a/lib/ace/commands/default_commands.js b/lib/ace/commands/default_commands.js index e5c94392d11..b346e279106 100644 --- a/lib/ace/commands/default_commands.js +++ b/lib/ace/commands/default_commands.js @@ -435,13 +435,13 @@ exports.commands = [{ { name: "cut", exec: function(editor) { - var range = editor.getSelectionRange(); + var cutLine = editor.$copyWithEmptySelection && editor.selection.isEmpty(); + var range = cutLine ? editor.selection.getLineRange() : editor.selection.getRange(); editor._emit("cut", range); - if (!editor.selection.isEmpty()) { + if (!range.isEmpty()) editor.session.remove(range); - editor.clearSelection(); - } + editor.clearSelection(); }, scrollIntoView: "cursor", multiSelectAction: "forEach" diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 7a329fb8e0d..6e4f6e69146 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -50,6 +50,8 @@ var defaultCommands = require("./commands/default_commands").commands; var config = require("./config"); var TokenIterator = require("./token_iterator").TokenIterator; +var clipboard = require("./clipboard"); + /** * The main entry point into the Ace functionality. * @@ -889,12 +891,25 @@ Editor.$uid = 0; /** * Returns the string of text currently highlighted. * @returns {String} - * @deprecated Use getSelectedText instead. **/ this.getCopyText = function() { var text = this.getSelectedText(); - this._signal("copy", text); - return text; + var nl = this.session.doc.getNewLineCharacter(); + var copyLine= false; + if (!text && this.$copyWithEmptySelection) { + copyLine = true; + var ranges = this.selection.getAllRanges(); + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + if (i && ranges[i - 1].start.row == range.start.row) + continue; + text += this.session.getLine(range.start.row) + nl; + } + } + var e = {text: text}; + this._signal("copy", e); + clipboard.lineMode = copyLine ? e.text : ""; + return e.text; }; /** @@ -934,8 +949,18 @@ Editor.$uid = 0; e = {text: e}; this._signal("paste", e); var text = e.text; + + var lineMode = text == clipboard.lineMode; + var session = this.session; if (!this.inMultiSelectMode || this.inVirtualSelectionMode) { - this.insert(text); + if (lineMode) + session.insert({ row: this.selection.lead.row, column: 0 }, text); + else + this.insert(text); + } else if (lineMode) { + this.selection.rangeList.ranges.forEach(function(range) { + session.insert({ row: range.start.row, column: 0 }, text); + }); } else { var lines = text.split(/\r\n|\r|\n/); var ranges = this.selection.rangeList.ranges; @@ -946,9 +971,9 @@ Editor.$uid = 0; for (var i = ranges.length; i--;) { var range = ranges[i]; if (!range.isEmpty()) - this.session.remove(range); + session.remove(range); - this.session.insert(range.start, lines[i]); + session.insert(range.start, lines[i]); } } }; @@ -2642,6 +2667,12 @@ config.defineOptions(Editor.prototype, "editor", { }, initialValue: false }, + copyWithEmptySelection: { + set: function(value) { + this.textInput.setCopyWithEmptySelection(value); + }, + initialValue: false + }, cursorStyle: { set: function(val) { this.$resetCursorStyle(); }, values: ["ace", "slim", "smooth", "wide"], diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index 3a55afc337e..81811e96073 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -61,6 +61,7 @@ var TextInput = function(parentNode, host) { var inComposition = false; var tempStyle = ''; var isSelectionEmpty = true; + var copyWithEmptySelection = false; // FOCUS // ie9 throws error if document.activeElement is accessed too soon @@ -106,6 +107,7 @@ var TextInput = function(parentNode, host) { }); function resetSelection(isEmpty) { + isEmpty = copyWithEmptySelection ? false : isEmpty; if (inComposition) return; @@ -410,6 +412,10 @@ var TextInput = function(parentNode, host) { text.readOnly = readOnly; }; + this.setCopyWithEmptySelection = function(value) { + copyWithEmptySelection = value; + }; + this.onContextMenu = function(e) { afterContextMenu = true; resetSelection(host.selection.isEmpty());