394 lines
No EOL
10 KiB
JavaScript
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); |