1
|
ace.define("ace/ext/elastic_tabstops_lite",["require","exports","module","ace/editor","ace/config"], function(require, exports, module) {
|
2
|
"use strict";
|
3
|
|
4
|
var ElasticTabstopsLite = function(editor) {
|
5
|
this.$editor = editor;
|
6
|
var self = this;
|
7
|
var changedRows = [];
|
8
|
var recordChanges = false;
|
9
|
this.onAfterExec = function() {
|
10
|
recordChanges = false;
|
11
|
self.processRows(changedRows);
|
12
|
changedRows = [];
|
13
|
};
|
14
|
this.onExec = function() {
|
15
|
recordChanges = true;
|
16
|
};
|
17
|
this.onChange = function(delta) {
|
18
|
if (recordChanges) {
|
19
|
if (changedRows.indexOf(delta.start.row) == -1)
|
20
|
changedRows.push(delta.start.row);
|
21
|
if (delta.end.row != delta.start.row)
|
22
|
changedRows.push(delta.end.row);
|
23
|
}
|
24
|
};
|
25
|
};
|
26
|
|
27
|
(function() {
|
28
|
this.processRows = function(rows) {
|
29
|
this.$inChange = true;
|
30
|
var checkedRows = [];
|
31
|
|
32
|
for (var r = 0, rowCount = rows.length; r < rowCount; r++) {
|
33
|
var row = rows[r];
|
34
|
|
35
|
if (checkedRows.indexOf(row) > -1)
|
36
|
continue;
|
37
|
|
38
|
var cellWidthObj = this.$findCellWidthsForBlock(row);
|
39
|
var cellWidths = this.$setBlockCellWidthsToMax(cellWidthObj.cellWidths);
|
40
|
var rowIndex = cellWidthObj.firstRow;
|
41
|
|
42
|
for (var w = 0, l = cellWidths.length; w < l; w++) {
|
43
|
var widths = cellWidths[w];
|
44
|
checkedRows.push(rowIndex);
|
45
|
this.$adjustRow(rowIndex, widths);
|
46
|
rowIndex++;
|
47
|
}
|
48
|
}
|
49
|
this.$inChange = false;
|
50
|
};
|
51
|
|
52
|
this.$findCellWidthsForBlock = function(row) {
|
53
|
var cellWidths = [], widths;
|
54
|
var rowIter = row;
|
55
|
while (rowIter >= 0) {
|
56
|
widths = this.$cellWidthsForRow(rowIter);
|
57
|
if (widths.length == 0)
|
58
|
break;
|
59
|
|
60
|
cellWidths.unshift(widths);
|
61
|
rowIter--;
|
62
|
}
|
63
|
var firstRow = rowIter + 1;
|
64
|
rowIter = row;
|
65
|
var numRows = this.$editor.session.getLength();
|
66
|
|
67
|
while (rowIter < numRows - 1) {
|
68
|
rowIter++;
|
69
|
|
70
|
widths = this.$cellWidthsForRow(rowIter);
|
71
|
if (widths.length == 0)
|
72
|
break;
|
73
|
|
74
|
cellWidths.push(widths);
|
75
|
}
|
76
|
|
77
|
return { cellWidths: cellWidths, firstRow: firstRow };
|
78
|
};
|
79
|
|
80
|
this.$cellWidthsForRow = function(row) {
|
81
|
var selectionColumns = this.$selectionColumnsForRow(row);
|
82
|
|
83
|
var tabs = [-1].concat(this.$tabsForRow(row));
|
84
|
var widths = tabs.map(function(el) { return 0; } ).slice(1);
|
85
|
var line = this.$editor.session.getLine(row);
|
86
|
|
87
|
for (var i = 0, len = tabs.length - 1; i < len; i++) {
|
88
|
var leftEdge = tabs[i]+1;
|
89
|
var rightEdge = tabs[i+1];
|
90
|
|
91
|
var rightmostSelection = this.$rightmostSelectionInCell(selectionColumns, rightEdge);
|
92
|
var cell = line.substring(leftEdge, rightEdge);
|
93
|
widths[i] = Math.max(cell.replace(/\s+$/g,'').length, rightmostSelection - leftEdge);
|
94
|
}
|
95
|
|
96
|
return widths;
|
97
|
};
|
98
|
|
99
|
this.$selectionColumnsForRow = function(row) {
|
100
|
var selections = [], cursor = this.$editor.getCursorPosition();
|
101
|
if (this.$editor.session.getSelection().isEmpty()) {
|
102
|
if (row == cursor.row)
|
103
|
selections.push(cursor.column);
|
104
|
}
|
105
|
|
106
|
return selections;
|
107
|
};
|
108
|
|
109
|
this.$setBlockCellWidthsToMax = function(cellWidths) {
|
110
|
var startingNewBlock = true, blockStartRow, blockEndRow, maxWidth;
|
111
|
var columnInfo = this.$izip_longest(cellWidths);
|
112
|
|
113
|
for (var c = 0, l = columnInfo.length; c < l; c++) {
|
114
|
var column = columnInfo[c];
|
115
|
if (!column.push) {
|
116
|
console.error(column);
|
117
|
continue;
|
118
|
}
|
119
|
column.push(NaN);
|
120
|
|
121
|
for (var r = 0, s = column.length; r < s; r++) {
|
122
|
var width = column[r];
|
123
|
if (startingNewBlock) {
|
124
|
blockStartRow = r;
|
125
|
maxWidth = 0;
|
126
|
startingNewBlock = false;
|
127
|
}
|
128
|
if (isNaN(width)) {
|
129
|
blockEndRow = r;
|
130
|
|
131
|
for (var j = blockStartRow; j < blockEndRow; j++) {
|
132
|
cellWidths[j][c] = maxWidth;
|
133
|
}
|
134
|
startingNewBlock = true;
|
135
|
}
|
136
|
|
137
|
maxWidth = Math.max(maxWidth, width);
|
138
|
}
|
139
|
}
|
140
|
|
141
|
return cellWidths;
|
142
|
};
|
143
|
|
144
|
this.$rightmostSelectionInCell = function(selectionColumns, cellRightEdge) {
|
145
|
var rightmost = 0;
|
146
|
|
147
|
if (selectionColumns.length) {
|
148
|
var lengths = [];
|
149
|
for (var s = 0, length = selectionColumns.length; s < length; s++) {
|
150
|
if (selectionColumns[s] <= cellRightEdge)
|
151
|
lengths.push(s);
|
152
|
else
|
153
|
lengths.push(0);
|
154
|
}
|
155
|
rightmost = Math.max.apply(Math, lengths);
|
156
|
}
|
157
|
|
158
|
return rightmost;
|
159
|
};
|
160
|
|
161
|
this.$tabsForRow = function(row) {
|
162
|
var rowTabs = [], line = this.$editor.session.getLine(row),
|
163
|
re = /\t/g, match;
|
164
|
|
165
|
while ((match = re.exec(line)) != null) {
|
166
|
rowTabs.push(match.index);
|
167
|
}
|
168
|
|
169
|
return rowTabs;
|
170
|
};
|
171
|
|
172
|
this.$adjustRow = function(row, widths) {
|
173
|
var rowTabs = this.$tabsForRow(row);
|
174
|
|
175
|
if (rowTabs.length == 0)
|
176
|
return;
|
177
|
|
178
|
var bias = 0, location = -1;
|
179
|
var expandedSet = this.$izip(widths, rowTabs);
|
180
|
|
181
|
for (var i = 0, l = expandedSet.length; i < l; i++) {
|
182
|
var w = expandedSet[i][0], it = expandedSet[i][1];
|
183
|
location += 1 + w;
|
184
|
it += bias;
|
185
|
var difference = location - it;
|
186
|
|
187
|
if (difference == 0)
|
188
|
continue;
|
189
|
|
190
|
var partialLine = this.$editor.session.getLine(row).substr(0, it );
|
191
|
var strippedPartialLine = partialLine.replace(/\s*$/g, "");
|
192
|
var ispaces = partialLine.length - strippedPartialLine.length;
|
193
|
|
194
|
if (difference > 0) {
|
195
|
this.$editor.session.getDocument().insertInLine({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t");
|
196
|
this.$editor.session.getDocument().removeInLine(row, it, it + 1);
|
197
|
|
198
|
bias += difference;
|
199
|
}
|
200
|
|
201
|
if (difference < 0 && ispaces >= -difference) {
|
202
|
this.$editor.session.getDocument().removeInLine(row, it + difference, it);
|
203
|
bias += difference;
|
204
|
}
|
205
|
}
|
206
|
};
|
207
|
this.$izip_longest = function(iterables) {
|
208
|
if (!iterables[0])
|
209
|
return [];
|
210
|
var longest = iterables[0].length;
|
211
|
var iterablesLength = iterables.length;
|
212
|
|
213
|
for (var i = 1; i < iterablesLength; i++) {
|
214
|
var iLength = iterables[i].length;
|
215
|
if (iLength > longest)
|
216
|
longest = iLength;
|
217
|
}
|
218
|
|
219
|
var expandedSet = [];
|
220
|
|
221
|
for (var l = 0; l < longest; l++) {
|
222
|
var set = [];
|
223
|
for (var i = 0; i < iterablesLength; i++) {
|
224
|
if (iterables[i][l] === "")
|
225
|
set.push(NaN);
|
226
|
else
|
227
|
set.push(iterables[i][l]);
|
228
|
}
|
229
|
|
230
|
expandedSet.push(set);
|
231
|
}
|
232
|
|
233
|
|
234
|
return expandedSet;
|
235
|
};
|
236
|
this.$izip = function(widths, tabs) {
|
237
|
var size = widths.length >= tabs.length ? tabs.length : widths.length;
|
238
|
|
239
|
var expandedSet = [];
|
240
|
for (var i = 0; i < size; i++) {
|
241
|
var set = [ widths[i], tabs[i] ];
|
242
|
expandedSet.push(set);
|
243
|
}
|
244
|
return expandedSet;
|
245
|
};
|
246
|
|
247
|
}).call(ElasticTabstopsLite.prototype);
|
248
|
|
249
|
exports.ElasticTabstopsLite = ElasticTabstopsLite;
|
250
|
|
251
|
var Editor = require("../editor").Editor;
|
252
|
require("../config").defineOptions(Editor.prototype, "editor", {
|
253
|
useElasticTabstops: {
|
254
|
set: function(val) {
|
255
|
if (val) {
|
256
|
if (!this.elasticTabstops)
|
257
|
this.elasticTabstops = new ElasticTabstopsLite(this);
|
258
|
this.commands.on("afterExec", this.elasticTabstops.onAfterExec);
|
259
|
this.commands.on("exec", this.elasticTabstops.onExec);
|
260
|
this.on("change", this.elasticTabstops.onChange);
|
261
|
} else if (this.elasticTabstops) {
|
262
|
this.commands.removeListener("afterExec", this.elasticTabstops.onAfterExec);
|
263
|
this.commands.removeListener("exec", this.elasticTabstops.onExec);
|
264
|
this.removeListener("change", this.elasticTabstops.onChange);
|
265
|
}
|
266
|
}
|
267
|
}
|
268
|
});
|
269
|
|
270
|
}); (function() {
|
271
|
ace.require(["ace/ext/elastic_tabstops_lite"], function(m) {
|
272
|
if (typeof module == "object" && typeof exports == "object" && module) {
|
273
|
module.exports = m;
|
274
|
}
|
275
|
});
|
276
|
})();
|
277
|
|