diff --git a/lib/ace/multi_select_test.js b/lib/ace/multi_select_test.js index b1c9f397..45ab4965 100644 --- a/lib/ace/multi_select_test.js +++ b/lib/ace/multi_select_test.js @@ -171,6 +171,30 @@ module.exports = { selection.addRange(range2); editor.execCommand('insertfoo'); assert.equal('l1foo\nl2foo', editor.getValue()); + }, + + "test multiselect fromJSON/toJSON": function() { + var doc = new EditSession(["l1", "l2"]); + editor = new Editor(new MockRenderer(), doc); + MultiSelect(editor); + var selection = editor.selection; + + var before = selection.toJSON(); + + var range1 = new Range(0,2,0,2); + var range2 = new Range(1,2,1,2); + selection.fromOrientedRange(range1) + selection.addRange(range2); + + var after = selection.toJSON(); + + selection.fromJSON(before); + assert.ok(!selection.isEqual(after)); + assert.ok(selection.isEqual(before)); + + selection.fromJSON(after); + assert.ok(!selection.isEqual(before)); + assert.ok(selection.isEqual(after)); } }; diff --git a/lib/ace/selection.js b/lib/ace/selection.js index dd5435f1..68a22a5c 100644 --- a/lib/ace/selection.js +++ b/lib/ace/selection.js @@ -3,7 +3,7 @@ * * 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 @@ -14,7 +14,7 @@ * * 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 @@ -37,7 +37,7 @@ var EventEmitter = require("./lib/event_emitter").EventEmitter; var Range = require("./range").Range; /** - * + * * Contains the cursor position and the text selection of an edit session. * * The row/columns used in the selection are in document coordinates representing ths coordinates as thez appear in the document before applying soft wrap and folding. @@ -49,22 +49,22 @@ var Range = require("./range").Range; * Emitted when the cursor position changes. * @event changeCursor * - * + * * **/ /** * Emitted when the cursor selection changes. * @event changeSelection * - * + * * **/ /** * Creates a new `Selection` object. * @param {EditSession} session The session to use * - * - * + * + * * @constructor **/ var Selection = function(session) { @@ -95,7 +95,7 @@ var Selection = function(session) { oop.implement(this, EventEmitter); /** - * + * * Returns `true` if the selection is empty. * @returns {Boolean} **/ @@ -106,7 +106,7 @@ var Selection = function(session) { )); }; - /** + /** * Returns `true` if the selection is a multi-line. * @returns {Boolean} **/ @@ -118,7 +118,7 @@ var Selection = function(session) { return this.getRange().isMultiLine(); }; - /** + /** * Gets the current position of the cursor. * @returns {Number} **/ @@ -131,7 +131,7 @@ var Selection = function(session) { * @param {Number} row The new row * @param {Number} column The new column * - * + * **/ this.setSelectionAnchor = function(row, column) { this.anchor.setPosition(row, column); @@ -156,7 +156,7 @@ var Selection = function(session) { }; /** - * + * * Returns an object containing the `row` and `column` of the calling selection lead. * @returns {Object} **/ @@ -168,7 +168,7 @@ var Selection = function(session) { * Shifts the selection up (or down, if [[Selection.isBackwards `isBackwards()`]] is true) the given number of columns. * @param {Number} columns The number of columns to shift by * - * + * * **/ this.shiftSelection = function(columns) { @@ -245,7 +245,7 @@ var Selection = function(session) { * @param {Range} range The range of text to select * @param {Boolean} reverse Indicates if the range should go backwards (`true`) or not * - * + * * @method setSelectionRange * @alias setRange **/ @@ -274,7 +274,7 @@ var Selection = function(session) { * @param {Number} row The row to select to * @param {Number} column The column to select to * - * + * * **/ this.selectTo = function(row, column) { @@ -287,7 +287,7 @@ var Selection = function(session) { * Moves the selection cursor to the row and column indicated by `pos`. * @param {Object} pos An object containing the row and column * - * + * * **/ this.selectToPosition = function(pos) { @@ -297,7 +297,7 @@ var Selection = function(session) { }; /** - * + * * Moves the selection up one row. **/ this.selectUp = function() { @@ -305,7 +305,7 @@ var Selection = function(session) { }; /** - * + * * Moves the selection down one row. **/ this.selectDown = function() { @@ -313,7 +313,7 @@ var Selection = function(session) { }; /** - * + * * * Moves the selection right one column. **/ @@ -322,7 +322,7 @@ var Selection = function(session) { }; /** - * + * * Moves the selection left one column. **/ this.selectLeft = function() { @@ -330,7 +330,7 @@ var Selection = function(session) { }; /** - * + * * Moves the selection to the beginning of the current line. **/ this.selectLineStart = function() { @@ -338,7 +338,7 @@ var Selection = function(session) { }; /** - * + * * Moves the selection to the end of the current line. **/ this.selectLineEnd = function() { @@ -346,7 +346,7 @@ var Selection = function(session) { }; /** - * + * * Moves the selection to the end of the file. **/ this.selectFileEnd = function() { @@ -354,7 +354,7 @@ var Selection = function(session) { }; /** - * + * * Moves the selection to the start of the file. **/ this.selectFileStart = function() { @@ -362,7 +362,7 @@ var Selection = function(session) { }; /** - * + * * Moves the selection to the first word on the right. **/ this.selectWordRight = function() { @@ -370,14 +370,14 @@ var Selection = function(session) { }; /** - * + * * Moves the selection to the first word on the left. **/ this.selectWordLeft = function() { this.$moveSelection(this.moveCursorWordLeft); }; - /** + /** * Moves the selection to highlight the entire word. * @related EditSession.getWordRange **/ @@ -389,16 +389,16 @@ var Selection = function(session) { } return this.session.getWordRange(row, column); }; - + /** - * + * * Selects an entire word boundary. **/ this.selectWord = function() { this.setSelectionRange(this.getWordRange()); }; - /** + /** * Selects a word, including its right whitespace. * @related EditSession.getAWordRange **/ @@ -433,7 +433,7 @@ var Selection = function(session) { }; /** - * + * * Moves the cursor up one row. **/ this.moveCursorUp = function() { @@ -441,7 +441,7 @@ var Selection = function(session) { }; /** - * + * * Moves the cursor down one row. **/ this.moveCursorDown = function() { @@ -449,7 +449,7 @@ var Selection = function(session) { }; /** - * + * * Moves the cursor left one column. **/ this.moveCursorLeft = function() { @@ -474,7 +474,7 @@ var Selection = function(session) { }; /** - * + * * Moves the cursor right one column. **/ this.moveCursorRight = function() { @@ -499,7 +499,7 @@ var Selection = function(session) { }; /** - * + * * Moves the cursor to the start of the line. **/ this.moveCursorLineStart = function() { @@ -524,7 +524,7 @@ var Selection = function(session) { }; /** - * + * * Moves the cursor to the end of the line. **/ this.moveCursorLineEnd = function() { @@ -543,7 +543,7 @@ var Selection = function(session) { }; /** - * + * * Moves the cursor to the end of the file. **/ this.moveCursorFileEnd = function() { @@ -553,7 +553,7 @@ var Selection = function(session) { }; /** - * + * * Moves the cursor to the start of the file. **/ this.moveCursorFileStart = function() { @@ -561,7 +561,7 @@ var Selection = function(session) { }; /** - * + * * Moves the cursor to the word on the right. **/ this.moveCursorLongWordRight = function() { @@ -607,7 +607,7 @@ var Selection = function(session) { }; /** - * + * * Moves the cursor to the word on the left. **/ this.moveCursorLongWordLeft = function() { @@ -704,11 +704,11 @@ var Selection = function(session) { if (column == line.length) { var l = this.doc.getLength(); - do { + do { row++; rightOfCursor = this.doc.getLine(row) } while (row < l && /^\s*$/.test(rightOfCursor)) - + if (!/^\s+/.test(rightOfCursor)) rightOfCursor = "" column = 0; @@ -729,11 +729,11 @@ var Selection = function(session) { var line = this.session.getLine(row).substring(0, column); if (column == 0) { - do { + do { row--; line = this.doc.getLine(row); } while (row > 0 && /^\s*$/.test(line)) - + column = line.length; if (!/\s+$/.test(line)) line = "" @@ -760,11 +760,11 @@ var Selection = function(session) { }; /** - * Moves the cursor to position indicated by the parameters. Negative numbers move the cursor backwards in the document. + * Moves the cursor to position indicated by the parameters. Negative numbers move the cursor backwards in the document. * @param {Number} rows The number of rows to move by * @param {Number} chars The number of characters to move by * - * + * * @related EditSession.documentToScreenPosition **/ this.moveCursorBy = function(rows, chars) { @@ -790,7 +790,7 @@ var Selection = function(session) { * Moves the selection to the position indicated by its `row` and `column`. * @param {Object} position The position to move to * - * + * **/ this.moveCursorToPosition = function(position) { this.moveCursorTo(position.row, position.column); @@ -802,7 +802,7 @@ var Selection = function(session) { * @param {Number} column The column to move to * @param {Boolean} keepDesiredColumn [If `true`, the cursor move does not respect the previous column]{: #preventUpdateBool} * - * + * **/ this.moveCursorTo = function(row, column, keepDesiredColumn) { // Ensure the row/column is not inside of a fold. @@ -826,7 +826,7 @@ var Selection = function(session) { * @param {Number} column The column to move to * @param {Boolean} keepDesiredColumn {:preventUpdateBool} * - * + * **/ this.moveCursorToScreen = function(row, column, keepDesiredColumn) { var pos = this.session.screenToDocumentPosition(row, column); @@ -861,6 +861,52 @@ var Selection = function(session) { return range; } + this.toJSON = function() { + if (this.rangeCount) { + var data = this.ranges.map(function(r) { + var r1 = r.clone(); + r1.isBackwards = r.cursor == r.start; + return r1; + }); + } else { + var data = this.getRange(); + data.isBackwards = this.isBackwards(); + } + return data; + }; + + this.fromJSON = function(data) { + if (data.start == undefined) { + if (this.toSingleRange) { + this.toSingleRange(data[0]); + for (var i = data.length; i--; ) { + var r = Range.fromPoints(data[i].start, data[i].end); + if (data.isBackwards) + r.cursor = r.start; + this.addRange(r, true); + } + return; + } else + data = data[0]; + } + if (this.toSingleRange) + this.toSingleRange(data); + this.setSelectionRange(data, data.isBackwards); + }; + + this.isEqual = function(data) { + if ((data.length || this.rangeCount) && data.length != this.rangeCount) + return false; + if (!data.length || !this.ranges) + return this.getRange().isEqual(data); + + for (var i = this.ranges.length; i--; ) { + if (!this.ranges[i].isEqual(data[i])) + return false + } + return true; + } + }).call(Selection.prototype); exports.Selection = Selection; diff --git a/lib/ace/selection_test.js b/lib/ace/selection_test.js index b69fd6dd..e1a67669 100644 --- a/lib/ace/selection_test.js +++ b/lib/ace/selection_test.js @@ -434,9 +434,7 @@ module.exports = { }, "test (keyboard navigation) when curLine is not EOL and targetLine is all whitespace new column should be current column": function() { - var session = new EditSession("function (a) {\n\ - \n\ -}"); + var session = new EditSession("function (a) {\n \n}"); var selection = session.getSelection(); selection.moveCursorTo(2, 0); @@ -445,16 +443,33 @@ module.exports = { assert.position(selection.getCursor(), 1, 0); }, - "test (keyboard navigation) when curLine is EOL and targetLine is shorter dan current column, new column should be targetLine's EOL": function() { - var session = new EditSession("function (a) {\n\ - \n\ -}"); + "test (keyboard navigation) when curLine is EOL and targetLine is shorter than current column, new column should be targetLine's EOL": function() { + var session = new EditSession("function (a) {\n \n}"); var selection = session.getSelection(); selection.moveCursorTo(0, 14); selection.moveCursorDown(); assert.position(selection.getCursor(), 1, 4); + }, + + "test fromJSON/toJSON": function() { + var session = new EditSession("function (a) {\n \n}"); + var selection = session.getSelection(); + + selection.moveCursorTo(0, 14); + selection.moveCursorDown(); + assert.position(selection.getCursor(), 1, 4); + var data = selection.toJSON(); + data = JSON.parse(JSON.stringify(data)) + selection.moveCursorDown(); + assert.position(selection.getCursor(), 2, 1); + + assert.ok(!selection.isEqual(data)); + + selection.fromJSON(data); + assert.position(selection.getCursor(), 1, 4); + assert.ok(selection.isEqual(data)); } };