132 lines
3.6 KiB
JavaScript
132 lines
3.6 KiB
JavaScript
/**
|
|
* Ajax.org Code Editor (ACE)
|
|
*
|
|
* @copyright 2010, Ajax.org Services B.V.
|
|
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
|
|
* @author Fabian Jakobs <fabian AT ajax DOT org>
|
|
*/
|
|
require.def("ace/BackgroundTokenizer", ["ace/lib/oop", "ace/MEventEmitter"], function(oop, MEventEmitter) {
|
|
|
|
var BackgroundTokenizer = function(tokenizer, editor) {
|
|
this.running = false;
|
|
this.textLines = [];
|
|
this.lines = [];
|
|
this.currentLine = 0;
|
|
this.tokenizer = tokenizer;
|
|
|
|
var self = this;
|
|
|
|
this.$worker = function() {
|
|
if (!self.running) { return; }
|
|
|
|
var workerStart = new Date();
|
|
var startLine = self.currentLine;
|
|
var textLines = self.textLines;
|
|
|
|
var processedLines = 0;
|
|
var lastVisibleRow = editor.getLastVisibleRow();
|
|
|
|
while (self.currentLine < textLines.length) {
|
|
self.lines[self.currentLine] = self.$tokenizeRows(self.currentLine, self.currentLine)[0];
|
|
self.currentLine++;
|
|
|
|
// only check every 5 lines
|
|
processedLines += 1;
|
|
if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) {
|
|
self.fireUpdateEvent(startLine, self.currentLine-1);
|
|
|
|
var timeout = self.currentLine < lastVisibleRow ? 20 : 100;
|
|
self.running = setTimeout(self.$worker, timeout);
|
|
return;
|
|
}
|
|
}
|
|
|
|
self.running = false;
|
|
|
|
self.fireUpdateEvent(startLine, textLines.length - 1);
|
|
};
|
|
};
|
|
|
|
(function(){
|
|
|
|
oop.implement(this, MEventEmitter);
|
|
|
|
this.setTokenizer = function(tokenizer) {
|
|
this.tokenizer = tokenizer;
|
|
this.lines = [];
|
|
|
|
this.start(0);
|
|
};
|
|
|
|
this.setLines = function(textLines) {
|
|
this.textLines = textLines;
|
|
this.lines = [];
|
|
|
|
this.stop();
|
|
};
|
|
|
|
this.fireUpdateEvent = function(firstRow, lastRow) {
|
|
var data = {
|
|
first: firstRow,
|
|
last: lastRow
|
|
};
|
|
this.$dispatchEvent("update", {data: data});
|
|
};
|
|
|
|
this.start = function(startRow) {
|
|
this.currentLine = Math.min(startRow || 0, this.currentLine,
|
|
this.textLines.length);
|
|
|
|
// remove all cached items below this line
|
|
this.lines.splice(this.currentLine, this.lines.length);
|
|
|
|
this.stop();
|
|
// pretty long delay to prevent the tokenizer from interfering with the user
|
|
this.running = setTimeout(this.$worker, 700);
|
|
};
|
|
|
|
this.stop = function() {
|
|
if (this.running)
|
|
clearTimeout(this.running);
|
|
this.running = false;
|
|
};
|
|
|
|
this.getTokens = function(firstRow, lastRow, callback) {
|
|
callback(this.$tokenizeRows(firstRow, lastRow));
|
|
};
|
|
|
|
this.getState = function(row, callback) {
|
|
callback(this.$tokenizeRows(row, row)[0].state);
|
|
};
|
|
|
|
this.$tokenizeRows = function(firstRow, lastRow) {
|
|
var rows = [];
|
|
|
|
// determine start state
|
|
var state = "start";
|
|
var doCache = false;
|
|
if (firstRow > 0 && this.lines[firstRow - 1]) {
|
|
state = this.lines[firstRow - 1].state;
|
|
doCache = true;
|
|
}
|
|
|
|
for (var row=firstRow; row<=lastRow; row++) {
|
|
if (!this.lines[row]) {
|
|
var tokens = this.tokenizer.getLineTokens(this.textLines[row] || "", state);
|
|
var state = tokens.state;
|
|
rows.push(tokens);
|
|
|
|
if (doCache) {
|
|
this.lines[row] = tokens;
|
|
}
|
|
}
|
|
else
|
|
rows.push(this.lines[row]);
|
|
}
|
|
return rows;
|
|
};
|
|
|
|
}).call(BackgroundTokenizer.prototype);
|
|
|
|
return BackgroundTokenizer;
|
|
});
|