Merge pull request #881 from ajaxorg/align_cursors

add command to align cursors
This commit is contained in:
Mostafa Eweda 2012-09-11 12:40:48 -07:00
commit 7966efc0df
2 changed files with 149 additions and 20 deletions

View file

@ -74,11 +74,15 @@ exports.defaultCommands = [{
}, { }, {
name: "splitIntoLines", name: "splitIntoLines",
exec: function(editor) { editor.multiSelect.splitIntoLines(); }, exec: function(editor) { editor.multiSelect.splitIntoLines(); },
bindKey: {win: "Ctrl-Shift-L", mac: "Ctrl-Shift-L"}, bindKey: {win: "Ctrl-Alt-L", mac: "Ctrl-Alt-L"},
readonly: true readonly: true
}, {
name: "alignCursors",
exec: function(editor) { editor.alignCursors(); },
bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"}
}]; }];
// commands active in multiselect mode // commands active only in multiselect mode
exports.multiSelectCommands = [{ exports.multiSelectCommands = [{
name: "singleSelection", name: "singleSelection",
bindKey: "esc", bindKey: "esc",

View file

@ -35,6 +35,7 @@ var Range = require("./range").Range;
var Selection = require("./selection").Selection; var Selection = require("./selection").Selection;
var onMouseDown = require("./mouse/multi_select_handler").onMouseDown; var onMouseDown = require("./mouse/multi_select_handler").onMouseDown;
var event = require("./lib/event"); var event = require("./lib/event");
var lang = require("./lib/lang");
var commands = require("./commands/multi_select_commands"); var commands = require("./commands/multi_select_commands");
exports.commands = commands.defaultCommands.concat(commands.multiSelectCommands); exports.commands = commands.defaultCommands.concat(commands.multiSelectCommands);
@ -198,10 +199,19 @@ var EditSession = require("./edit_session").EditSession;
this.setSelectionRange(range, lastRange.cursor == lastRange.start); this.setSelectionRange(range, lastRange.cursor == lastRange.start);
} else { } else {
var range = this.getRange(); var range = this.getRange();
var isBackwards = this.isBackwards();
var startRow = range.start.row; var startRow = range.start.row;
var endRow = range.end.row; var endRow = range.end.row;
if (startRow == endRow) if (startRow == endRow) {
if (isBackwards)
var start = range.end, end = range.start;
else
var start = range.start, end = range.end;
this.addRange(Range.fromPoints(end, end));
this.addRange(Range.fromPoints(start, start));
return; return;
}
var rectSel = []; var rectSel = [];
var r = this.getLineRange(startRow, true); var r = this.getLineRange(startRow, true);
@ -645,7 +655,7 @@ var Editor = require("./editor").Editor;
* *
* Finds the next occurence of text in an active selection and adds it to the selections. * Finds the next occurence of text in an active selection and adds it to the selections.
**/ **/
this.selectMore = function (dir, skip) { this.selectMore = function(dir, skip) {
var session = this.session; var session = this.session;
var sel = session.multiSelect; var sel = session.multiSelect;
@ -665,6 +675,121 @@ var Editor = require("./editor").Editor;
if (skip) if (skip)
this.multiSelect.substractPoint(range.cursor); this.multiSelect.substractPoint(range.cursor);
}; };
/** extension
* Editor.alignCursors()
*
* aligns cursors or selected text
**/
this.alignCursors = function() {
var session = this.session;
var sel = session.multiSelect;
var ranges = sel.ranges;
if (!ranges.length) {
var range = this.selection.getRange();
var fr = range.start.row, lr = range.end.row;
var lines = this.session.doc.removeLines(fr, lr);
lines = this.$reAlignText(lines);
this.session.doc.insertLines(fr, lines);
range.start.column = 0;
range.end.column = lines[lines.length - 1].length;
this.selection.setRange(range);
} else {
// filter out ranges on same row
var row = -1;
var sameRowRanges = ranges.filter(function(r) {
if (r.cursor.row == row)
return true;
row = r.cursor.row;
});
sel.$onRemoveRange(sameRowRanges);
var maxCol = 0;
var minSpace = Infinity;
var spaceOffsets = ranges.map(function(r) {
var p = r.cursor;
var line = session.getLine(p.row);
var spaceOffset = line.substr(p.column).search(/\S/g);
if (spaceOffset == -1)
spaceOffset = 0;
if (p.column > maxCol)
maxCol = p.column;
if (spaceOffset < minSpace)
minSpace = spaceOffset;
return spaceOffset;
});
ranges.forEach(function(r, i) {
var p = r.cursor;
var l = maxCol - p.column;
var d = spaceOffsets[i] - minSpace;
if (l > d)
session.insert(p, lang.stringRepeat(" ", l - d));
else
session.remove(new Range(p.row, p.column, p.row, p.column - l + d));
r.start.column = r.end.column = maxCol;
r.start.row = r.end.row = p.row;
r.cursor = r.end;
});
sel.fromOrientedRange(ranges[0]);
this.renderer.updateCursor();
this.renderer.updateBackMarkers();
}
};
this.$reAlignText = function(lines) {
var isLeftAligned = true, isRightAligned = true;
var startW, textW, endW;
return lines.map(function(line) {
var m = line.match(/(\s*)(.*?)(\s*)([=:].*)/);
if (!m)
return [line];
if (startW == null) {
startW = m[1].length;
textW = m[2].length;
endW = m[3].length;
return m;
}
if (startW + textW + endW != m[1].length + m[2].length + m[3].length)
isRightAligned = false;
if (startW != m[1].length)
isLeftAligned = false;
if (startW > m[1].length)
startW = m[1].length;
if (textW < m[2].length)
textW = m[2].length;
if (endW > m[3].length)
endW = m[3].length;
return m;
}).map(isLeftAligned ? isRightAligned ? alignRight : alignLeft : unAlign);
function strRepeat(n, ch) {
return Array(n + 1).join(ch)
}
function alignLeft(m) {
return !m[2] ? m[0] : strRepeat(startW, " ") + m[2]
+ strRepeat(textW - m[2].length + endW, " ")
+ m[4].replace(/^([=:])\s+/, "$1 ")
}
function alignRight(m) {
return !m[2] ? m[0] : strRepeat(startW + textW - m[2].length, " ") + m[2]
+ strRepeat(endW, " ")
+ m[4].replace(/^([=:])\s+/, "$1 ")
}
function unAlign(m) {
return !m[2] ? m[0] : strRepeat(startW, " ") + m[2]
+ strRepeat(endW, " ")
+ m[4].replace(/^([=:])\s+/, "$1 ")
}
}
}).call(Editor.prototype); }).call(Editor.prototype);