add alignCursors command (ctrl+alt+a)
This commit is contained in:
parent
86750fbadb
commit
4e12d1c9b9
2 changed files with 139 additions and 19 deletions
|
|
@ -74,11 +74,15 @@ exports.defaultCommands = [{
|
|||
}, {
|
||||
name: "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
|
||||
}, {
|
||||
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 = [{
|
||||
name: "singleSelection",
|
||||
bindKey: "esc",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -35,6 +35,7 @@ var Range = require("./range").Range;
|
|||
var Selection = require("./selection").Selection;
|
||||
var onMouseDown = require("./mouse/multi_select_handler").onMouseDown;
|
||||
var event = require("./lib/event");
|
||||
var lang = require("./lib/lang");
|
||||
var commands = require("./commands/multi_select_commands");
|
||||
exports.commands = commands.defaultCommands.concat(commands.multiSelectCommands);
|
||||
|
||||
|
|
@ -66,7 +67,7 @@ var EditSession = require("./edit_session").EditSession;
|
|||
this.rangeList = null;
|
||||
|
||||
/** extension
|
||||
* Selection.addRange(range, $blockChangeEvents)
|
||||
* Selection.addRange(range, $blockChangeEvents)
|
||||
* - range (Range): The new range to add
|
||||
* - $blockChangeEvents (Boolean): Whether or not to block changing events
|
||||
*
|
||||
|
|
@ -113,7 +114,7 @@ var EditSession = require("./edit_session").EditSession;
|
|||
|
||||
range && this.fromOrientedRange(range);
|
||||
};
|
||||
|
||||
|
||||
/** extension
|
||||
* Selection.substractPoint(pos) -> Range
|
||||
* - pos (Range): The position to remove, as a `{row, column}` object
|
||||
|
|
@ -129,7 +130,7 @@ var EditSession = require("./edit_session").EditSession;
|
|||
};
|
||||
|
||||
/** extension
|
||||
* Selection.mergeOverlappingRanges()
|
||||
* Selection.mergeOverlappingRanges()
|
||||
*
|
||||
* Merges overlapping ranges ensuring consistency after changes
|
||||
**/
|
||||
|
|
@ -241,7 +242,7 @@ var EditSession = require("./edit_session").EditSession;
|
|||
* - screenCursor (Cursor): The cursor to use
|
||||
* - screenAnchor (Anchor): The anchor to use
|
||||
* - includeEmptyLines (Boolean): If true, this includes ranges inside the block which are empty due to clipping
|
||||
*
|
||||
*
|
||||
* Gets list of ranges composing rectangular block on the screen
|
||||
*
|
||||
**/
|
||||
|
|
@ -313,9 +314,9 @@ var EditSession = require("./edit_session").EditSession;
|
|||
// extend Editor
|
||||
var Editor = require("./editor").Editor;
|
||||
(function() {
|
||||
|
||||
|
||||
/** extension
|
||||
* Editor.updateSelectionMarkers()
|
||||
* Editor.updateSelectionMarkers()
|
||||
*
|
||||
* Updates the cursor and marker layers.
|
||||
**/
|
||||
|
|
@ -343,7 +344,7 @@ var Editor = require("./editor").Editor;
|
|||
};
|
||||
|
||||
/** extension
|
||||
* Editor.removeSelectionMarker(range)
|
||||
* Editor.removeSelectionMarker(range)
|
||||
* - range (Range): The selection range added with [[Editor.addSelectionMarker `addSelectionMarker()`]].
|
||||
*
|
||||
* Removes the selection marker.
|
||||
|
|
@ -431,7 +432,7 @@ var Editor = require("./editor").Editor;
|
|||
};
|
||||
|
||||
/** extension
|
||||
* Editor.forEachSelection(cmd, args)
|
||||
* Editor.forEachSelection(cmd, args)
|
||||
* - cmd (String): The command to execute
|
||||
* - args (String): Any arguments for the command
|
||||
*
|
||||
|
|
@ -496,7 +497,7 @@ var Editor = require("./editor").Editor;
|
|||
|
||||
// todo this should change when paste becomes a command
|
||||
this.onPaste = function(text) {
|
||||
if (this.$readOnly)
|
||||
if (this.$readOnly)
|
||||
return;
|
||||
|
||||
this._emit("paste", text);
|
||||
|
|
@ -551,7 +552,7 @@ var Editor = require("./editor").Editor;
|
|||
|
||||
// commands
|
||||
/** extension
|
||||
* Editor.selectMoreLines(dir, skip)
|
||||
* Editor.selectMoreLines(dir, skip)
|
||||
* - dir (Number): The direction of lines to select: -1 for up, 1 for down
|
||||
* - skip (Boolean): If `true`, removes the active selection range
|
||||
*
|
||||
|
|
@ -596,10 +597,10 @@ var Editor = require("./editor").Editor;
|
|||
};
|
||||
|
||||
/** extension
|
||||
* Editor.transposeSelections(dir)
|
||||
* Editor.transposeSelections(dir)
|
||||
* - dir (Number): The direction to rotate selections
|
||||
*
|
||||
* Transposes the selected ranges.
|
||||
* Transposes the selected ranges.
|
||||
**/
|
||||
this.transposeSelections = function(dir) {
|
||||
var session = this.session;
|
||||
|
|
@ -639,13 +640,13 @@ var Editor = require("./editor").Editor;
|
|||
}
|
||||
|
||||
/** extension
|
||||
* Editor.selectMore(dir, skip)
|
||||
* Editor.selectMore(dir, skip)
|
||||
* - dir (Number): The direction of lines to select: -1 for up, 1 for down
|
||||
* - skip (Boolean): If `true`, removes the active selection range
|
||||
*
|
||||
* 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 sel = session.multiSelect;
|
||||
|
||||
|
|
@ -665,6 +666,121 @@ var Editor = require("./editor").Editor;
|
|||
if (skip)
|
||||
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);
|
||||
|
||||
|
||||
|
|
@ -710,7 +826,7 @@ exports.onSessionChange = function(e) {
|
|||
}
|
||||
};
|
||||
|
||||
// MultiSelect(editor)
|
||||
// MultiSelect(editor)
|
||||
// adds multiple selection support to the editor
|
||||
// (note: should be called only once for each editor instance)
|
||||
function MultiSelect(editor) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue