|
|
ace.define("ace/ext/elastic_tabstops_lite",["require","exports","module","ace/editor","ace/config"], function(acequire, exports, module) { "use strict";
var ElasticTabstopsLite = function(editor) { this.$editor = editor; var self = this; var changedRows = []; var recordChanges = false; this.onAfterExec = function() { recordChanges = false; self.processRows(changedRows); changedRows = []; }; this.onExec = function() { recordChanges = true; }; this.onChange = function(delta) { if (recordChanges) { if (changedRows.indexOf(delta.start.row) == -1) changedRows.push(delta.start.row); if (delta.end.row != delta.start.row) changedRows.push(delta.end.row); } }; };
(function() { this.processRows = function(rows) { this.$inChange = true; var checkedRows = [];
for (var r = 0, rowCount = rows.length; r < rowCount; r++) { var row = rows[r];
if (checkedRows.indexOf(row) > -1) continue;
var cellWidthObj = this.$findCellWidthsForBlock(row); var cellWidths = this.$setBlockCellWidthsToMax(cellWidthObj.cellWidths); var rowIndex = cellWidthObj.firstRow;
for (var w = 0, l = cellWidths.length; w < l; w++) { var widths = cellWidths[w]; checkedRows.push(rowIndex); this.$adjustRow(rowIndex, widths); rowIndex++; } } this.$inChange = false; };
this.$findCellWidthsForBlock = function(row) { var cellWidths = [], widths; var rowIter = row; while (rowIter >= 0) { widths = this.$cellWidthsForRow(rowIter); if (widths.length == 0) break;
cellWidths.unshift(widths); rowIter--; } var firstRow = rowIter + 1; rowIter = row; var numRows = this.$editor.session.getLength();
while (rowIter < numRows - 1) { rowIter++;
widths = this.$cellWidthsForRow(rowIter); if (widths.length == 0) break;
cellWidths.push(widths); }
return { cellWidths: cellWidths, firstRow: firstRow }; };
this.$cellWidthsForRow = function(row) { var selectionColumns = this.$selectionColumnsForRow(row);
var tabs = [-1].concat(this.$tabsForRow(row)); var widths = tabs.map(function(el) { return 0; } ).slice(1); var line = this.$editor.session.getLine(row);
for (var i = 0, len = tabs.length - 1; i < len; i++) { var leftEdge = tabs[i]+1; var rightEdge = tabs[i+1];
var rightmostSelection = this.$rightmostSelectionInCell(selectionColumns, rightEdge); var cell = line.substring(leftEdge, rightEdge); widths[i] = Math.max(cell.replace(/\s+$/g,'').length, rightmostSelection - leftEdge); }
return widths; };
this.$selectionColumnsForRow = function(row) { var selections = [], cursor = this.$editor.getCursorPosition(); if (this.$editor.session.getSelection().isEmpty()) { if (row == cursor.row) selections.push(cursor.column); }
return selections; };
this.$setBlockCellWidthsToMax = function(cellWidths) { var startingNewBlock = true, blockStartRow, blockEndRow, maxWidth; var columnInfo = this.$izip_longest(cellWidths);
for (var c = 0, l = columnInfo.length; c < l; c++) { var column = columnInfo[c]; if (!column.push) { console.error(column); continue; } column.push(NaN);
for (var r = 0, s = column.length; r < s; r++) { var width = column[r]; if (startingNewBlock) { blockStartRow = r; maxWidth = 0; startingNewBlock = false; } if (isNaN(width)) { blockEndRow = r;
for (var j = blockStartRow; j < blockEndRow; j++) { cellWidths[j][c] = maxWidth; } startingNewBlock = true; }
maxWidth = Math.max(maxWidth, width); } }
return cellWidths; };
this.$rightmostSelectionInCell = function(selectionColumns, cellRightEdge) { var rightmost = 0;
if (selectionColumns.length) { var lengths = []; for (var s = 0, length = selectionColumns.length; s < length; s++) { if (selectionColumns[s] <= cellRightEdge) lengths.push(s); else lengths.push(0); } rightmost = Math.max.apply(Math, lengths); }
return rightmost; };
this.$tabsForRow = function(row) { var rowTabs = [], line = this.$editor.session.getLine(row), re = /\t/g, match;
while ((match = re.exec(line)) != null) { rowTabs.push(match.index); }
return rowTabs; };
this.$adjustRow = function(row, widths) { var rowTabs = this.$tabsForRow(row);
if (rowTabs.length == 0) return;
var bias = 0, location = -1; var expandedSet = this.$izip(widths, rowTabs);
for (var i = 0, l = expandedSet.length; i < l; i++) { var w = expandedSet[i][0], it = expandedSet[i][1]; location += 1 + w; it += bias; var difference = location - it;
if (difference == 0) continue;
var partialLine = this.$editor.session.getLine(row).substr(0, it ); var strippedPartialLine = partialLine.replace(/\s*$/g, ""); var ispaces = partialLine.length - strippedPartialLine.length;
if (difference > 0) { this.$editor.session.getDocument().insertInLine({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t"); this.$editor.session.getDocument().removeInLine(row, it, it + 1);
bias += difference; }
if (difference < 0 && ispaces >= -difference) { this.$editor.session.getDocument().removeInLine(row, it + difference, it); bias += difference; } } }; this.$izip_longest = function(iterables) { if (!iterables[0]) return []; var longest = iterables[0].length; var iterablesLength = iterables.length;
for (var i = 1; i < iterablesLength; i++) { var iLength = iterables[i].length; if (iLength > longest) longest = iLength; }
var expandedSet = [];
for (var l = 0; l < longest; l++) { var set = []; for (var i = 0; i < iterablesLength; i++) { if (iterables[i][l] === "") set.push(NaN); else set.push(iterables[i][l]); }
expandedSet.push(set); }
return expandedSet; }; this.$izip = function(widths, tabs) { var size = widths.length >= tabs.length ? tabs.length : widths.length;
var expandedSet = []; for (var i = 0; i < size; i++) { var set = [ widths[i], tabs[i] ]; expandedSet.push(set); } return expandedSet; };
}).call(ElasticTabstopsLite.prototype);
exports.ElasticTabstopsLite = ElasticTabstopsLite;
var Editor = acequire("../editor").Editor; acequire("../config").defineOptions(Editor.prototype, "editor", { useElasticTabstops: { set: function(val) { if (val) { if (!this.elasticTabstops) this.elasticTabstops = new ElasticTabstopsLite(this); this.commands.on("afterExec", this.elasticTabstops.onAfterExec); this.commands.on("exec", this.elasticTabstops.onExec); this.on("change", this.elasticTabstops.onChange); } else if (this.elasticTabstops) { this.commands.removeListener("afterExec", this.elasticTabstops.onAfterExec); this.commands.removeListener("exec", this.elasticTabstops.onExec); this.removeListener("change", this.elasticTabstops.onChange); } } } });
}); (function() { ace.acequire(["ace/ext/elastic_tabstops_lite"], function() {}); })();
|