bzr branch
http://gegoxaren.bato24.eu/bzr/lenasys/trunk
15.1.1
by galaxyAbstractor
Started implementation of a new codeviewer using Ace |
1 |
/* ***** BEGIN LICENSE BLOCK *****
|
2 |
* Distributed under the BSD license:
|
|
3 |
*
|
|
4 |
* Copyright (c) 2012, Ajax.org B.V.
|
|
5 |
* All rights reserved.
|
|
6 |
*
|
|
7 |
* Redistribution and use in source and binary forms, with or without
|
|
8 |
* modification, are permitted provided that the following conditions are met:
|
|
9 |
* * Redistributions of source code must retain the above copyright
|
|
10 |
* notice, this list of conditions and the following disclaimer.
|
|
11 |
* * Redistributions in binary form must reproduce the above copyright
|
|
12 |
* notice, this list of conditions and the following disclaimer in the
|
|
13 |
* documentation and/or other materials provided with the distribution.
|
|
14 |
* * Neither the name of Ajax.org B.V. nor the
|
|
15 |
* names of its contributors may be used to endorse or promote products
|
|
16 |
* derived from this software without specific prior written permission.
|
|
17 |
*
|
|
18 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
19 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
20 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
21 |
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
|
22 |
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
23 |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
24 |
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
25 |
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
26 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
27 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
28 |
*
|
|
29 |
* ***** END LICENSE BLOCK ***** */
|
|
30 |
||
31 |
define('ace/ext/elastic_tabstops_lite', ['require', 'exports', 'module' , 'ace/editor', 'ace/config'], function(require, exports, module) { |
|
32 |
||
33 |
||
34 |
var ElasticTabstopsLite = function(editor) { |
|
35 |
this.$editor = editor; |
|
36 |
var self = this; |
|
37 |
var changedRows = []; |
|
38 |
var recordChanges = false; |
|
39 |
this.onAfterExec = function() { |
|
40 |
recordChanges = false; |
|
41 |
self.processRows(changedRows); |
|
42 |
changedRows = []; |
|
43 |
}; |
|
44 |
this.onExec = function() { |
|
45 |
recordChanges = true; |
|
46 |
}; |
|
47 |
this.onChange = function(e) { |
|
48 |
var range = e.data.range |
|
49 |
if (recordChanges) { |
|
50 |
if (changedRows.indexOf(range.start.row) == -1) |
|
51 |
changedRows.push(range.start.row); |
|
52 |
if (range.end.row != range.start.row) |
|
53 |
changedRows.push(range.end.row); |
|
54 |
} |
|
55 |
}; |
|
56 |
};
|
|
57 |
||
58 |
(function() { |
|
59 |
this.processRows = function(rows) { |
|
60 |
this.$inChange = true; |
|
61 |
var checkedRows = []; |
|
62 |
||
63 |
for (var r = 0, rowCount = rows.length; r < rowCount; r++) { |
|
64 |
var row = rows[r]; |
|
65 |
||
66 |
if (checkedRows.indexOf(row) > -1) |
|
67 |
continue; |
|
68 |
||
69 |
var cellWidthObj = this.$findCellWidthsForBlock(row); |
|
70 |
var cellWidths = this.$setBlockCellWidthsToMax(cellWidthObj.cellWidths); |
|
71 |
var rowIndex = cellWidthObj.firstRow; |
|
72 |
||
73 |
for (var w = 0, l = cellWidths.length; w < l; w++) { |
|
74 |
var widths = cellWidths[w]; |
|
75 |
checkedRows.push(rowIndex); |
|
76 |
this.$adjustRow(rowIndex, widths); |
|
77 |
rowIndex++; |
|
78 |
} |
|
79 |
} |
|
80 |
this.$inChange = false; |
|
81 |
}; |
|
82 |
||
83 |
this.$findCellWidthsForBlock = function(row) { |
|
84 |
var cellWidths = [], widths; |
|
85 |
var rowIter = row; |
|
86 |
while (rowIter >= 0) { |
|
87 |
widths = this.$cellWidthsForRow(rowIter); |
|
88 |
if (widths.length == 0) |
|
89 |
break; |
|
90 |
||
91 |
cellWidths.unshift(widths); |
|
92 |
rowIter--; |
|
93 |
} |
|
94 |
var firstRow = rowIter + 1; |
|
95 |
rowIter = row; |
|
96 |
var numRows = this.$editor.session.getLength(); |
|
97 |
||
98 |
while (rowIter < numRows - 1) { |
|
99 |
rowIter++; |
|
100 |
||
101 |
widths = this.$cellWidthsForRow(rowIter); |
|
102 |
if (widths.length == 0) |
|
103 |
break; |
|
104 |
||
105 |
cellWidths.push(widths); |
|
106 |
} |
|
107 |
||
108 |
return { cellWidths: cellWidths, firstRow: firstRow }; |
|
109 |
}; |
|
110 |
||
111 |
this.$cellWidthsForRow = function(row) { |
|
112 |
var selectionColumns = this.$selectionColumnsForRow(row); |
|
113 |
||
114 |
var tabs = [-1].concat(this.$tabsForRow(row)); |
|
115 |
var widths = tabs.map(function (el) { return 0; } ).slice(1); |
|
116 |
var line = this.$editor.session.getLine(row); |
|
117 |
||
118 |
for (var i = 0, len = tabs.length - 1; i < len; i++) { |
|
119 |
var leftEdge = tabs[i]+1; |
|
120 |
var rightEdge = tabs[i+1]; |
|
121 |
||
122 |
var rightmostSelection = this.$rightmostSelectionInCell(selectionColumns, rightEdge); |
|
123 |
var cell = line.substring(leftEdge, rightEdge); |
|
124 |
widths[i] = Math.max(cell.replace(/\s+$/g,'').length, rightmostSelection - leftEdge); |
|
125 |
} |
|
126 |
|
|
127 |
return widths; |
|
128 |
}; |
|
129 |
||
130 |
this.$selectionColumnsForRow = function(row) { |
|
131 |
var selections = [], cursor = this.$editor.getCursorPosition(); |
|
132 |
if (this.$editor.session.getSelection().isEmpty()) { |
|
133 |
if (row == cursor.row) |
|
134 |
selections.push(cursor.column); |
|
135 |
} |
|
136 |
||
137 |
return selections; |
|
138 |
}; |
|
139 |
||
140 |
this.$setBlockCellWidthsToMax = function(cellWidths) { |
|
141 |
var startingNewBlock = true, blockStartRow, blockEndRow, maxWidth; |
|
142 |
var columnInfo = this.$izip_longest(cellWidths); |
|
143 |
||
144 |
for (var c = 0, l = columnInfo.length; c < l; c++) { |
|
145 |
var column = columnInfo[c]; |
|
146 |
if (!column.push) { |
|
147 |
console.error(column); |
|
148 |
continue; |
|
149 |
} |
|
150 |
column.push(NaN); |
|
151 |
||
152 |
for (var r = 0, s = column.length; r < s; r++) { |
|
153 |
var width = column[r]; |
|
154 |
if (startingNewBlock) { |
|
155 |
blockStartRow = r; |
|
156 |
maxWidth = 0; |
|
157 |
startingNewBlock = false; |
|
158 |
} |
|
159 |
if (isNaN(width)) { |
|
160 |
blockEndRow = r; |
|
161 |
||
162 |
for (var j = blockStartRow; j < blockEndRow; j++) { |
|
163 |
cellWidths[j][c] = maxWidth; |
|
164 |
} |
|
165 |
startingNewBlock = true; |
|
166 |
} |
|
167 |
||
168 |
maxWidth = Math.max(maxWidth, width); |
|
169 |
} |
|
170 |
} |
|
171 |
||
172 |
return cellWidths; |
|
173 |
}; |
|
174 |
||
175 |
this.$rightmostSelectionInCell = function(selectionColumns, cellRightEdge) { |
|
176 |
var rightmost = 0; |
|
177 |
||
178 |
if (selectionColumns.length) { |
|
179 |
var lengths = []; |
|
180 |
for (var s = 0, length = selectionColumns.length; s < length; s++) { |
|
181 |
if (selectionColumns[s] <= cellRightEdge) |
|
182 |
lengths.push(s); |
|
183 |
else |
|
184 |
lengths.push(0); |
|
185 |
} |
|
186 |
rightmost = Math.max.apply(Math, lengths); |
|
187 |
} |
|
188 |
||
189 |
return rightmost; |
|
190 |
}; |
|
191 |
||
192 |
this.$tabsForRow = function(row) { |
|
193 |
var rowTabs = [], line = this.$editor.session.getLine(row), |
|
194 |
re = /\t/g, match; |
|
195 |
||
196 |
while ((match = re.exec(line)) != null) { |
|
197 |
rowTabs.push(match.index); |
|
198 |
} |
|
199 |
||
200 |
return rowTabs; |
|
201 |
}; |
|
202 |
||
203 |
this.$adjustRow = function(row, widths) { |
|
204 |
var rowTabs = this.$tabsForRow(row); |
|
205 |
||
206 |
if (rowTabs.length == 0) |
|
207 |
return; |
|
208 |
|
|
209 |
var bias = 0, location = -1; |
|
210 |
var expandedSet = this.$izip(widths, rowTabs); |
|
211 |
||
212 |
for (var i = 0, l = expandedSet.length; i < l; i++) { |
|
213 |
var w = expandedSet[i][0], it = expandedSet[i][1]; |
|
214 |
location += 1 + w; |
|
215 |
it += bias; |
|
216 |
var difference = location - it; |
|
217 |
||
218 |
if (difference == 0) |
|
219 |
continue; |
|
220 |
||
221 |
var partialLine = this.$editor.session.getLine(row).substr(0, it ); |
|
222 |
var strippedPartialLine = partialLine.replace(/\s*$/g, ""); |
|
223 |
var ispaces = partialLine.length - strippedPartialLine.length; |
|
224 |
||
225 |
if (difference > 0) { |
|
226 |
this.$editor.session.getDocument().insertInLine({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t"); |
|
227 |
this.$editor.session.getDocument().removeInLine(row, it, it + 1); |
|
228 |
||
229 |
bias += difference; |
|
230 |
} |
|
231 |
||
232 |
if (difference < 0 && ispaces >= -difference) { |
|
233 |
this.$editor.session.getDocument().removeInLine(row, it + difference, it); |
|
234 |
bias += difference; |
|
235 |
} |
|
236 |
} |
|
237 |
}; |
|
238 |
this.$izip_longest = function(iterables) { |
|
239 |
if (!iterables[0]) |
|
240 |
return []; |
|
241 |
var longest = iterables[0].length; |
|
242 |
var iterablesLength = iterables.length; |
|
243 |
||
244 |
for (var i = 1; i < iterablesLength; i++) { |
|
245 |
var iLength = iterables[i].length; |
|
246 |
if (iLength > longest) |
|
247 |
longest = iLength; |
|
248 |
} |
|
249 |
|
|
250 |
var expandedSet = []; |
|
251 |
||
252 |
for (var l = 0; l < longest; l++) { |
|
253 |
var set = []; |
|
254 |
for (var i = 0; i < iterablesLength; i++) { |
|
255 |
if (iterables[i][l] === "") |
|
256 |
set.push(NaN); |
|
257 |
else |
|
258 |
set.push(iterables[i][l]); |
|
259 |
} |
|
260 |
||
261 |
expandedSet.push(set); |
|
262 |
} |
|
263 |
|
|
264 |
||
265 |
return expandedSet; |
|
266 |
}; |
|
267 |
this.$izip = function(widths, tabs) { |
|
268 |
var size = widths.length >= tabs.length ? tabs.length : widths.length; |
|
269 |
|
|
270 |
var expandedSet = []; |
|
271 |
for (var i = 0; i < size; i++) { |
|
272 |
var set = [ widths[i], tabs[i] ]; |
|
273 |
expandedSet.push(set); |
|
274 |
} |
|
275 |
return expandedSet; |
|
276 |
}; |
|
277 |
||
278 |
}).call(ElasticTabstopsLite.prototype); |
|
279 |
||
280 |
exports.ElasticTabstopsLite = ElasticTabstopsLite; |
|
281 |
||
282 |
var Editor = require("../editor").Editor; |
|
283 |
require("../config").defineOptions(Editor.prototype, "editor", { |
|
284 |
useElasticTabstops: { |
|
285 |
set: function(val) { |
|
286 |
if (val) { |
|
287 |
if (!this.elasticTabstops) |
|
288 |
this.elasticTabstops = new ElasticTabstopsLite(this); |
|
289 |
this.commands.on("afterExec", this.elasticTabstops.onAfterExec); |
|
290 |
this.commands.on("exec", this.elasticTabstops.onExec); |
|
291 |
this.on("change", this.elasticTabstops.onChange); |
|
292 |
} else if (this.elasticTabstops) { |
|
293 |
this.commands.removeListener("afterExec", this.elasticTabstops.onAfterExec); |
|
294 |
this.commands.removeListener("exec", this.elasticTabstops.onExec); |
|
295 |
this.removeListener("change", this.elasticTabstops.onChange); |
|
296 |
} |
|
297 |
} |
|
298 |
} |
|
299 |
});
|
|
300 |
||
301 |
});
|