fix moving lines with folds
This commit is contained in:
parent
bf2015bf7e
commit
43854d7a35
2 changed files with 91 additions and 76 deletions
2
build
2
build
|
|
@ -1 +1 @@
|
|||
Subproject commit 75ba742f4f00cefadfef1ae451cfb2a4280ad367
|
||||
Subproject commit 1e3407af692eaf661800083897c73d46d0a4bc46
|
||||
|
|
@ -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
|
||||
|
|
@ -44,8 +44,8 @@ var SearchHighlight = require("./search_highlight").SearchHighlight;
|
|||
var config = require("./config");
|
||||
|
||||
/**
|
||||
* Stores all the data about [[Editor `Editor`]] state providing easy way to change editors state.
|
||||
*
|
||||
* Stores all the data about [[Editor `Editor`]] state providing easy way to change editors state.
|
||||
*
|
||||
* `EditSession` can be attached to only one [[Document `Document`]]. Same `Document` can be attached to several `EditSession`s.
|
||||
* @class EditSession
|
||||
**/
|
||||
|
|
@ -94,19 +94,19 @@ var config = require("./config");
|
|||
* @param {Object} e An object containing one property, `"data"`, that contains information about the changing rows
|
||||
*
|
||||
**/
|
||||
/**
|
||||
/**
|
||||
* Emitted when the current mode changes.
|
||||
*
|
||||
* @event changeMode
|
||||
*
|
||||
**/
|
||||
/**
|
||||
/**
|
||||
* Emitted when the wrap mode changes.
|
||||
*
|
||||
* @event changeWrapMode
|
||||
*
|
||||
**/
|
||||
/**
|
||||
/**
|
||||
* Emitted when the wrapping limit changes.
|
||||
*
|
||||
* @event changeWrapLimit
|
||||
|
|
@ -148,14 +148,14 @@ var EditSession = function(text, mode) {
|
|||
this.$backMarkers = {};
|
||||
this.$markerId = 1;
|
||||
this.$undoSelect = true;
|
||||
|
||||
|
||||
this.$foldData = [];
|
||||
this.$foldData.toString = function() {
|
||||
return this.join("\n");
|
||||
}
|
||||
this.on("changeFold", this.onChangeFold.bind(this));
|
||||
this.$onChange = this.onChange.bind(this);
|
||||
|
||||
|
||||
if (typeof text != "object" || !text.getLine)
|
||||
text = new Document(text);
|
||||
|
||||
|
|
@ -194,13 +194,13 @@ var EditSession = function(text, mode) {
|
|||
|
||||
/**
|
||||
* Returns the `Document` associated with this session.
|
||||
* @return {Document}
|
||||
* @return {Document}
|
||||
**/
|
||||
this.getDocument = function() {
|
||||
return this.doc;
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* @param {Number} row The row to work with
|
||||
*
|
||||
**/
|
||||
|
|
@ -293,19 +293,19 @@ var EditSession = function(text, mode) {
|
|||
this.getUndoManager().reset();
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the current [[Document `Document`]] as a string.
|
||||
* @method toString
|
||||
* @returns {String}
|
||||
* @alias EditSession.getValue
|
||||
* @alias EditSession.getValue
|
||||
*
|
||||
**/
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Returns the current [[Document `Document`]] as a string.
|
||||
* @method getValue
|
||||
* @returns {String}
|
||||
* @alias EditSession.toString
|
||||
* @alias EditSession.toString
|
||||
**/
|
||||
this.getValue =
|
||||
this.toString = function() {
|
||||
|
|
@ -319,7 +319,7 @@ var EditSession = function(text, mode) {
|
|||
return this.selection;
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* {:BackgroundTokenizer.getState}
|
||||
* @param {Number} row The row to start at
|
||||
*
|
||||
|
|
@ -329,7 +329,7 @@ var EditSession = function(text, mode) {
|
|||
return this.bgTokenizer.getState(row);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Starts tokenizing at the row indicated. Returns a list of objects of the tokenized rows.
|
||||
* @param {Number} row The row to start at
|
||||
*
|
||||
|
|
@ -483,7 +483,7 @@ var EditSession = function(text, mode) {
|
|||
|
||||
this.$overwrite = false;
|
||||
/**
|
||||
* Pass in `true` to enable overwrites in your session, or `false` to disable.
|
||||
* Pass in `true` to enable overwrites in your session, or `false` to disable.
|
||||
*
|
||||
* If overwrites is enabled, any text you enter will type over any text after it. If the value of `overwrite` changes, this function also emites the `changeOverwrite` event.
|
||||
*
|
||||
|
|
@ -537,7 +537,7 @@ var EditSession = function(text, mode) {
|
|||
this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, "");
|
||||
this._emit("changeBreakpoint", {});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of numbers, indicating which rows have breakpoints.
|
||||
* @returns {[Number]}
|
||||
|
|
@ -635,7 +635,7 @@ var EditSession = function(text, mode) {
|
|||
* @param {Object} marker object with update method
|
||||
* @param {Boolean} inFront Set to `true` to establish a front marker
|
||||
*
|
||||
*
|
||||
*
|
||||
* @return {Object} The added marker
|
||||
**/
|
||||
this.addDynamicMarker = function(marker, inFront) {
|
||||
|
|
@ -692,7 +692,7 @@ var EditSession = function(text, mode) {
|
|||
}
|
||||
this.$searchHighlight.setRegexp(re);
|
||||
}
|
||||
|
||||
|
||||
// experimental
|
||||
this.highlightLines = function(startRow, endRow, clazz, inFront) {
|
||||
if (typeof endRow != "number") {
|
||||
|
|
@ -701,12 +701,12 @@ var EditSession = function(text, mode) {
|
|||
}
|
||||
if (!clazz)
|
||||
clazz = "ace_step";
|
||||
|
||||
|
||||
var range = new Range(startRow, 0, endRow, Infinity);
|
||||
range.id = this.addMarker(range, clazz, "fullLine", inFront);
|
||||
return range;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Error:
|
||||
* {
|
||||
|
|
@ -741,7 +741,7 @@ var EditSession = function(text, mode) {
|
|||
this.setAnnotations([]);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* If `text` contains either the newline (`\n`) or carriage-return ('\r') characters, `$autoNewLine` stores that value.
|
||||
* @param {String} text A block of text
|
||||
*
|
||||
|
|
@ -772,7 +772,7 @@ var EditSession = function(text, mode) {
|
|||
|
||||
if (!inToken)
|
||||
inToken = !!line.charAt(column).match(this.tokenRe);
|
||||
|
||||
|
||||
if (inToken)
|
||||
var re = this.tokenRe;
|
||||
else if (/^\s+$/.test(line.slice(column-1, column+1)))
|
||||
|
|
@ -814,7 +814,7 @@ var EditSession = function(text, mode) {
|
|||
return wordRange;
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* {:Document.setNewLineMode.desc}
|
||||
* @param {String} newLineMode {:Document.setNewLineMode.param}
|
||||
*
|
||||
|
|
@ -825,7 +825,7 @@ var EditSession = function(text, mode) {
|
|||
this.doc.setNewLineMode(newLineMode);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
*
|
||||
* Returns the current new line mode.
|
||||
* @returns {String}
|
||||
|
|
@ -1061,7 +1061,7 @@ var EditSession = function(text, mode) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns a verbatim copy of the given line as it is in the document
|
||||
* @param {Number} row The row to retrieve from
|
||||
*
|
||||
|
|
@ -1073,7 +1073,7 @@ var EditSession = function(text, mode) {
|
|||
return this.doc.getLine(row);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns an array of strings of the rows between `firstRow` and `lastRow`. This function is inclusive of `lastRow`.
|
||||
* @param {Number} firstRow The first row index to retrieve
|
||||
* @param {Number} lastRow The final row index to retrieve
|
||||
|
|
@ -1085,7 +1085,7 @@ var EditSession = function(text, mode) {
|
|||
return this.doc.getLines(firstRow, lastRow);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the number of rows in the document.
|
||||
* @returns {Number}
|
||||
**/
|
||||
|
|
@ -1093,7 +1093,7 @@ var EditSession = function(text, mode) {
|
|||
return this.doc.getLength();
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* {:Document.getTextRange.desc}
|
||||
* @param {Range} range The range to work with
|
||||
*
|
||||
|
|
@ -1103,7 +1103,7 @@ var EditSession = function(text, mode) {
|
|||
return this.doc.getTextRange(range || this.selection.getRange());
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Inserts a block of `text` and the indicated `position`.
|
||||
* @param {Object} position The position {row, column} to start inserting at
|
||||
* @param {String} text A chunk of text to insert
|
||||
|
|
@ -1115,7 +1115,7 @@ var EditSession = function(text, mode) {
|
|||
return this.doc.insert(position, text);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Removes the `range` from the document.
|
||||
* @param {Range} range A specified Range to remove
|
||||
* @returns {Object} The new `start` property of the range, which contains `startRow` and `startColumn`. If `range` is empty, this function returns the unmodified value of `range.start`.
|
||||
|
|
@ -1132,7 +1132,7 @@ var EditSession = function(text, mode) {
|
|||
* @param {Array} deltas An array of previous changes
|
||||
* @param {Boolean} dontSelect [If `true`, doesn't select the range of where the change occured]{: #dontSelect}
|
||||
*
|
||||
*
|
||||
*
|
||||
* @returns {Range}
|
||||
**/
|
||||
this.undoChanges = function(deltas, dontSelect) {
|
||||
|
|
@ -1254,16 +1254,16 @@ var EditSession = function(text, mode) {
|
|||
return range;
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Replaces a range in the document with the new `text`.
|
||||
*
|
||||
* @param {Range} range A specified Range to replace
|
||||
* @param {String} text The new text to use as a replacement
|
||||
* @returns {Object} An object containing the final row and column, like this:
|
||||
* @returns {Object} An object containing the final row and column, like this:
|
||||
* ```
|
||||
* {row: endRow, column: 0}
|
||||
* ```
|
||||
* If the text and range are empty, this function returns an object containing the current `range.start` value.
|
||||
* ```
|
||||
* If the text and range are empty, this function returns an object containing the current `range.start` value.
|
||||
* If the text is the exact same as what currently exists, this function returns an object containing the current `range.end` value.
|
||||
*
|
||||
*
|
||||
|
|
@ -1364,7 +1364,39 @@ var EditSession = function(text, mode) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
this.$moveLines = function(firstRow, lastRow, dir) {
|
||||
var firstRow = this.getRowFoldStart(firstRow);
|
||||
var lastRow = this.getRowFoldEnd(lastRow);
|
||||
if (dir < 0) {
|
||||
var row = this.getRowFoldStart(firstRow + dir);
|
||||
if (row < 0) return 0;
|
||||
var diff = row-firstRow;
|
||||
} else if (dir > 0) {
|
||||
var row = this.getRowFoldEnd(lastRow + dir);
|
||||
if (row > this.doc.getLength()-1) return 0;
|
||||
var diff = row-lastRow;
|
||||
} else {
|
||||
firstRow = this.$clipRowToDocument(firstRow);
|
||||
lastRow = this.$clipRowToDocument(lastRow);
|
||||
var diff = lastRow - firstRow + 1;
|
||||
}
|
||||
|
||||
var range = new Range(firstRow, 0, lastRow, Number.MAX_VALUE);
|
||||
var folds = this.getFoldsInRange(range).map(function(x){
|
||||
x = x.clone();
|
||||
x.start.row += diff;
|
||||
x.end.row += diff;
|
||||
return x;
|
||||
});
|
||||
|
||||
var lines = dir == 0
|
||||
? this.doc.getLines(firstRow, lastRow)
|
||||
: this.doc.removeLines(firstRow, lastRow);
|
||||
this.doc.insertLines(firstRow+diff, lines);
|
||||
folds.length && this.addFolds(folds);
|
||||
return diff;
|
||||
};
|
||||
/**
|
||||
* Shifts all the lines in the document up one, starting from `firstRow` and ending at `lastRow`.
|
||||
* @param {Number} firstRow The starting row to move up
|
||||
* @param {Number} lastRow The final row to move up
|
||||
|
|
@ -1374,29 +1406,19 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
**/
|
||||
this.moveLinesUp = function(firstRow, lastRow) {
|
||||
if (firstRow <= 0) return 0;
|
||||
|
||||
var removed = this.doc.removeLines(firstRow, lastRow);
|
||||
this.doc.insertLines(firstRow - 1, removed);
|
||||
return -1;
|
||||
return this.$moveLines(firstRow, lastRow, -1);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Shifts all the lines in the document down one, starting from `firstRow` and ending at `lastRow`.
|
||||
* @param {Number} firstRow The starting row to move down
|
||||
* @param {Number} lastRow The final row to move down
|
||||
* @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @related Document.insertLines
|
||||
**/
|
||||
this.moveLinesDown = function(firstRow, lastRow) {
|
||||
if (lastRow >= this.doc.getLength()-1) return 0;
|
||||
|
||||
var removed = this.doc.removeLines(firstRow, lastRow);
|
||||
this.doc.insertLines(firstRow+1, removed);
|
||||
return 1;
|
||||
return this.$moveLines(firstRow, lastRow, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1408,14 +1430,7 @@ var EditSession = function(text, mode) {
|
|||
*
|
||||
**/
|
||||
this.duplicateLines = function(firstRow, lastRow) {
|
||||
var firstRow = this.$clipRowToDocument(firstRow);
|
||||
var lastRow = this.$clipRowToDocument(lastRow);
|
||||
|
||||
var lines = this.getLines(firstRow, lastRow);
|
||||
this.doc.insertLines(firstRow, lines);
|
||||
|
||||
var addedRows = lastRow - firstRow + 1;
|
||||
return addedRows;
|
||||
return this.$moveLines(firstRow, lastRow, 0);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1539,12 +1554,12 @@ var EditSession = function(text, mode) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* This should generally only be called by the renderer when a resize is detected.
|
||||
* @param {Number} desiredLimit The new wrap limit
|
||||
* @returns {Boolean}
|
||||
*
|
||||
*
|
||||
*
|
||||
* @private
|
||||
**/
|
||||
this.adjustWrapLimit = function(desiredLimit) {
|
||||
|
|
@ -1993,7 +2008,7 @@ var EditSession = function(text, mode) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the position (on screen) for the last character in the provided screen row.
|
||||
* @param {Number} screenRow The screen row to check
|
||||
* @returns {Number}
|
||||
|
|
@ -2005,21 +2020,21 @@ var EditSession = function(text, mode) {
|
|||
return this.documentToScreenColumn(pos.row, pos.column);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* For the given document row and column, this returns the column position of the last screen row.
|
||||
* @param {Number} docRow
|
||||
* @param {Number} docRow
|
||||
*
|
||||
* @param {Number} docColumn
|
||||
* @param {Number} docColumn
|
||||
**/
|
||||
this.getDocumentLastRowColumn = function(docRow, docColumn) {
|
||||
var screenRow = this.documentToScreenRow(docRow, docColumn);
|
||||
return this.getScreenLastRowColumn(screenRow);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* For the given document row and column, this returns the document position of the last row.
|
||||
* @param {Number} docRow
|
||||
* @param {Number} docColumn
|
||||
* @param {Number} docRow
|
||||
* @param {Number} docColumn
|
||||
*
|
||||
*
|
||||
**/
|
||||
|
|
@ -2028,7 +2043,7 @@ var EditSession = function(text, mode) {
|
|||
return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* For the given row, this returns the split data.
|
||||
* @returns {String}
|
||||
**/
|
||||
|
|
@ -2044,7 +2059,7 @@ var EditSession = function(text, mode) {
|
|||
* The distance to the next tab stop at the specified screen column.
|
||||
* @param {Number} screenColumn The screen column to check
|
||||
*
|
||||
*
|
||||
*
|
||||
* @returns {Number}
|
||||
**/
|
||||
this.getScreenTabSize = function(screenColumn) {
|
||||
|
|
@ -2061,7 +2076,7 @@ var EditSession = function(text, mode) {
|
|||
return this.screenToDocumentPosition(screenRow, screenColumn).column;
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Converts characters coordinates on the screen to characters coordinates within the document. [This takes into account code folding, word wrap, tab size, and any other visual modifications.]{: #conversionConsiderations}
|
||||
* @param {Number} screenRow The screen row to check
|
||||
* @param {Number} screenColumn The screen column to check
|
||||
|
|
@ -2110,7 +2125,7 @@ var EditSession = function(text, mode) {
|
|||
foldStart = foldLine ? foldLine.start.row : Infinity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (doCache) {
|
||||
this.$docRowCache.push(docRow);
|
||||
this.$screenRowCache.push(row);
|
||||
|
|
@ -2155,7 +2170,7 @@ var EditSession = function(text, mode) {
|
|||
return {row: docRow, column: docColumn};
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Converts document coordinates to screen coordinates. {:conversionConsiderations}
|
||||
* @param {Number} docRow The document row to check
|
||||
* @param {Number} docColumn The document column to check
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue