ace/src/Selection.js

394 lines
No EOL
10 KiB
JavaScript

ace.provide("ace.Selection");
ace.Selection = function(doc) {
this.doc = doc;
this.$initEvents();
this.clearSelection();
this.selectionLead = {
row: 0,
column: 0
};
};
(function() {
ace.implement(this, ace.MEventEmitter);
this.isEmpty = function() {
return (this.selectionAnchor == null);
};
this.isMultiLine = function() {
if (this.isEmpty()) {
return false;
}
var range = this.getRange();
return (range.start.row !== range.end.row);
};
this.getCursor = function() {
return this.selectionLead;
};
this.setSelectionAnchor = function(row, column) {
this.clearSelection();
this.selectionAnchor = this.$clipPositionToDocument(row, column);
};
this.getSelectionAnchor = function() {
if (this.selectionAnchor) {
return this.$clone(this.selectionAnchor);
} else {
return this.$clone(this.selectionLead);
}
};
this.getSelectionLead = function() {
return this.$clone(this.selectionLead);
};
this.shiftSelection = function(columns) {
if (this.isEmpty()) {
this.moveCursorTo(this.selectionLead.row, this.selectionLead.column + columns);
return;
};
var anchor = this.getSelectionAnchor();
var lead = this.getSelectionLead();
this.setSelectionAnchor(anchor.row, anchor.column + columns);
this.$moveSelection(function() {
this.moveCursorTo(lead.row, lead.column + columns);
});
};
this.getRange = function() {
var anchor = this.selectionAnchor || this.selectionLead;
var lead = this.selectionLead;
if (anchor.row > lead.row
|| (anchor.row == lead.row && anchor.column > lead.column)) {
return {
start : lead,
end : anchor
};
}
else {
return {
start : anchor,
end : lead
};
}
};
this.clearSelection = function() {
if (this.selectionAnchor) {
this.selectionAnchor = null;
this.$dispatchEvent("changeSelection", {});
}
};
this.selectAll = function() {
var lastRow = this.doc.getLength() - 1;
this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length);
this.$moveSelection(function() {
this.moveCursorTo(0, 0);
});
};
this.$moveSelection = function(mover) {
var changed = false;
if (!this.selectionAnchor) {
changed = true;
this.selectionAnchor = this.$clone(this.selectionLead);
}
var cursor = this.$clone(this.selectionLead);
mover.call(this);
if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) {
changed = true;
}
if (changed)
this.$dispatchEvent("changeSelection", {});
};
this.selectTo = function(row, column) {
this.$moveSelection(function() {
this.moveCursorTo(row, column);
});
};
this.selectToPosition = function(pos) {
this.$moveSelection(function() {
this.moveCursorToPosition(pos);
});
};
this.selectUp = function() {
this.$moveSelection(this.moveCursorUp);
};
this.selectDown = function() {
this.$moveSelection(this.moveCursorDown);
};
this.selectRight = function() {
this.$moveSelection(this.moveCursorRight);
};
this.selectLeft = function() {
this.$moveSelection(this.moveCursorLeft);
};
this.selectLineStart = function() {
this.$moveSelection(this.moveCursorLineStart);
};
this.selectLineEnd = function() {
this.$moveSelection(this.moveCursorLineEnd);
};
this.selectPageDown = function() {
var row = this.getPageDownRow() + Math.floor(this.getVisibleRowCount() / 2);
this.scrollPageDown();
this.$moveSelection(function() {
this.moveCursorTo(row, this.selectionLead.column);
});
};
this.selectPageUp = function() {
var visibleRows = this.getLastVisibleRow() - this.getFirstVisibleRow();
var row = this.getPageUpRow() + Math.round(visibleRows / 2);
this.scrollPageUp();
this.$moveSelection(function() {
this.moveCursorTo(row, this.selectionLead.column);
});
};
this.selectFileEnd = function() {
this.$moveSelection(this.moveCursorFileEnd);
};
this.selectFileStart = function() {
this.$moveSelection(this.moveCursorFileStart);
};
this.tokenRe = /^[\w\d]+/g;
this.nonTokenRe = /^[^\w\d]+/g;
this.selectWordRight = function() {
this.$moveSelection(this.moveCursorWordRight);
};
this.selectWordLeft = function() {
this.$moveSelection(this.moveCursorWordLeft);
};
this.selectWord = function() {
var cursor = this.selectionLead;
var line = this.doc.getLine(cursor.row);
var column = cursor.column;
var inToken = false;
if (column > 0) {
inToken = !!line.charAt(column - 1).match(this.tokenRe);
}
if (!inToken) {
inToken = !!line.charAt(column).match(this.tokenRe);
}
var re = inToken ? this.tokenRe : this.nonTokenRe;
var start = column;
if (start > 0) {
do {
start--;
}
while (start >= 0 && line.charAt(start).match(re));
start++;
}
var end = column;
while (end < line.length && line.charAt(end).match(re)) {
end++;
}
this.setSelectionAnchor(cursor.row, start);
this.$moveSelection(function() {
this.moveCursorTo(cursor.row, end);
});
};
this.selectLine = function() {
this.setSelectionAnchor(this.selectionLead.row, 0);
this.$moveSelection(function() {
this.moveCursorTo(this.selectionLead.row + 1, 0);
});
};
this.moveCursorUp = function() {
this.moveCursorBy(-1, 0);
};
this.moveCursorDown = function() {
this.moveCursorBy(1, 0);
};
this.moveCursorLeft = function() {
if (this.selectionLead.column == 0) {
if (this.selectionLead.row > 0) {
this.moveCursorTo(this.selectionLead.row - 1, this.doc
.getLine(this.selectionLead.row - 1).length);
}
}
else {
this.moveCursorBy(0, -1);
}
};
this.moveCursorRight = function() {
if (this.selectionLead.column == this.doc.getLine(this.selectionLead.row).length) {
if (this.selectionLead.row < this.doc.getLength() - 1) {
this.moveCursorTo(this.selectionLead.row + 1, 0);
}
}
else {
this.moveCursorBy(0, 1);
}
};
this.moveCursorLineStart = function() {
this.moveCursorTo(this.selectionLead.row, 0);
};
this.moveCursorLineEnd = function() {
this.moveCursorTo(this.selectionLead.row,
this.doc.getLine(this.selectionLead.row).length);
};
this.moveCursorFileEnd = function() {
var row = this.doc.getLength() - 1;
var column = this.doc.getLine(row).length;
this.moveCursorTo(row, column);
};
this.moveCursorFileStart = function() {
this.moveCursorTo(0, 0);
};
this.moveCursorWordRight = function() {
var row = this.selectionLead.row;
var column = this.selectionLead.column;
var line = this.doc.getLine(row);
var rightOfCursor = line.substring(column);
var match;
this.nonTokenRe.lastIndex = 0;
this.tokenRe.lastIndex = 0;
if (column == line.length) {
this.moveCursorRight();
return;
}
else if (match = this.nonTokenRe.exec(rightOfCursor)) {
column += this.nonTokenRe.lastIndex;
this.nonTokenRe.lastIndex = 0;
}
else if (match = this.tokenRe.exec(rightOfCursor)) {
column += this.tokenRe.lastIndex;
this.tokenRe.lastIndex = 0;
}
this.moveCursorTo(row, column);
};
this.moveCursorWordLeft = function() {
var row = this.selectionLead.row;
var column = this.selectionLead.column;
var line = this.doc.getLine(row);
var leftOfCursor = ace.stringReverse(line.substring(0, column));
var match;
this.nonTokenRe.lastIndex = 0;
this.tokenRe.lastIndex = 0;
if (column == 0) {
this.moveCursorLeft();
return;
}
else if (match = this.nonTokenRe.exec(leftOfCursor)) {
column -= this.nonTokenRe.lastIndex;
this.nonTokenRe.lastIndex = 0;
}
else if (match = this.tokenRe.exec(leftOfCursor)) {
column -= this.tokenRe.lastIndex;
this.tokenRe.lastIndex = 0;
}
this.moveCursorTo(row, column);
};
this.moveCursorBy = function(rows, chars) {
this.moveCursorTo(this.selectionLead.row + rows, this.selectionLead.column + chars);
};
this.moveCursorToPosition = function(position) {
this.moveCursorTo(position.row, position.column);
};
this.moveCursorTo = function(row, column) {
var cursor = this.$clipPositionToDocument(row, column);
if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) {
this.selectionLead = cursor;
this.$dispatchEvent("changeCursor", { data: this.getCursor() });
}
};
this.moveCursorUp = function() {
this.moveCursorBy(-1, 0);
};
this.$clipPositionToDocument = function(row, column) {
var pos = {};
if (row >= this.doc.getLength()) {
pos.row = this.doc.getLength() - 1;
pos.column = this.doc.getLine(pos.row).length;
}
else if (row < 0) {
pos.row = 0;
pos.column = 0;
}
else {
pos.row = row;
pos.column = Math.min(this.doc.getLine(pos.row).length,
Math.max(0, column));
}
return pos;
};
this.$clone = function(pos) {
return {
row: pos.row,
column: pos.column
};
};
}).call(ace.Selection.prototype);