TextEditorHighlighter.js [plain text]
WebInspector.TextEditorHighlighter = function(textModel, damageCallback)
{
this._textModel = textModel;
this._styles = [];
this._styles["css-comment"] = "rgb(0, 116, 0)";
this._styles["css-params"] = "rgb(7, 144, 154)";
this._styles["css-string"] = "rgb(7, 144, 154)";
this._styles["css-keyword"] = "rgb(7, 144, 154)";
this._styles["css-number"] = "rgb(50, 0, 255)";
this._styles["css-property"] = "rgb(200, 0, 0)";
this._styles["css-at-rule"] = "rgb(200, 0, 0)";
this._styles["css-selector"] = "rgb(0, 0, 0)";
this._styles["css-important"] = "rgb(200, 0, 180)";
this._styles["html-tag"] = "rgb(136, 18, 128)";
this._styles["html-attr-name"] = "rgb(153, 69, 0)";
this._styles["html-attr-value"] = "rgb(26, 26, 166)";
this._styles["html-comment"] = "rgb(35, 110, 37)";
this._styles["html-doctype"] = "rgb(192, 192, 192)";
this._styles["javascript-comment"] = "rgb(0, 116, 0)";
this._styles["javascript-string"] = "rgb(196, 26, 22)";
this._styles["javascript-regexp"] = "rgb(196, 26, 22)";
this._styles["javascript-keyword"] = "rgb(170, 13, 145)";
this._styles["javascript-number"] = "rgb(28, 0, 207)";
this.mimeType = "text/html";
this._damageCallback = damageCallback;
}
WebInspector.TextEditorHighlighter.prototype = {
set mimeType(mimeType)
{
var tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType);
if (tokenizer)
this._tokenizer = tokenizer;
},
highlight: function(endLine)
{
var state = this._textModel.getAttribute(endLine - 1, "highlighter-state")
if (state && !state.outOfDate) {
return;
}
this._requestedEndLine = endLine;
if (this._highlightTimer) {
return;
}
var startLine = endLine;
while (startLine > 0) {
var state = this._textModel.getAttribute(startLine - 1, "highlighter-state");
if (state && !state.outOfDate)
break;
startLine--;
}
var toLine = Math.min(startLine + 200, endLine);
this._highlightInChunks(startLine, toLine);
if (endLine > toLine)
this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, toLine, endLine), 100);
},
_highlightInChunks: function(startLine, endLine)
{
delete this._highlightTimer;
var state = this._textModel.getAttribute(this._requestedEndLine - 1, "highlighter-state");
if (state && !state.outOfDate)
return;
if (this._requestedEndLine !== endLine) {
this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, startLine, this._requestedEndLine), 100);
return;
}
var toLine = Math.min(startLine + 500, this._requestedEndLine);
this._highlightLines(startLine, toLine);
if (toLine < this._requestedEndLine)
this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, toLine, this._requestedEndLine), 10);
},
updateHighlight: function(startLine, endLine)
{
if (startLine) {
var state = this._textModel.getAttribute(startLine - 1, "highlighter-state");
if (!state || state.outOfDate) {
return;
}
}
var restored = this._highlightLines(startLine, endLine);
for (var i = endLine; i < this._textModel.linesCount; ++i) {
var highlighterState = this._textModel.getAttribute(i, "highlighter-state");
if (highlighterState)
highlighterState.outOfDate = !restored;
else
return;
}
},
_highlightLines: function(startLine, endLine)
{
var state = this._textModel.getAttribute(startLine - 1, "highlighter-state");
if (state)
this._tokenizer.condition = state.postCondition;
else
this._tokenizer.condition = this._tokenizer.initialCondition;
for (var i = startLine; i < endLine; ++i) {
state = {};
state.preCondition = this._tokenizer.condition;
state.attributes = {};
this._lex(this._textModel.line(i), i, state.attributes);
state.postCondition = this._tokenizer.condition;
this._textModel.setAttribute(i, "highlighter-state", state);
var nextLineState = this._textModel.getAttribute(i + 1, "highlighter-state");
if (nextLineState && this._tokenizer.hasCondition(nextLineState.preCondition)) {
this._damageCallback(startLine, i + 1);
return true;
}
}
this._damageCallback(startLine, endLine);
return false;
},
_lex: function(line, lineNumber, attributes) {
this._tokenizer.line = line;
var column = 0;
do {
var newColumn = this._tokenizer.nextToken(column);
var tokenType = this._tokenizer.tokenType;
if (tokenType)
attributes[column] = { length: newColumn - column, style: this._styles[tokenType] };
column = newColumn;
} while (column < line.length)
}
}