diff options
author | Steve Block <steveblock@google.com> | 2010-04-27 16:31:00 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2010-05-11 14:42:12 +0100 |
commit | dcc8cf2e65d1aa555cce12431a16547e66b469ee (patch) | |
tree | 92a8d65cd5383bca9749f5327fb5e440563926e6 /WebCore/inspector/front-end/TextEditorHighlighter.js | |
parent | ccac38a6b48843126402088a309597e682f40fe6 (diff) | |
download | external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.zip external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.gz external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.bz2 |
Merge webkit.org at r58033 : Initial merge by git
Change-Id: If006c38561af287c50cd578d251629b51e4d8cd1
Diffstat (limited to 'WebCore/inspector/front-end/TextEditorHighlighter.js')
-rw-r--r-- | WebCore/inspector/front-end/TextEditorHighlighter.js | 137 |
1 files changed, 50 insertions, 87 deletions
diff --git a/WebCore/inspector/front-end/TextEditorHighlighter.js b/WebCore/inspector/front-end/TextEditorHighlighter.js index cf0b590..4ac831e 100644 --- a/WebCore/inspector/front-end/TextEditorHighlighter.js +++ b/WebCore/inspector/front-end/TextEditorHighlighter.js @@ -34,24 +34,31 @@ WebInspector.TextEditorHighlighter = function(textModel, damageCallback) this._textModel = textModel; this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/html"); this._damageCallback = damageCallback; + this.reset(); } WebInspector.TextEditorHighlighter.prototype = { set mimeType(mimeType) { var tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType); - if (tokenizer) + if (tokenizer) { this._tokenizer = tokenizer; + this._tokenizerCondition = this._tokenizer.initialCondition; + } + }, + + reset: function() + { + this._lastHighlightedLine = 0; + this._lastHighlightedColumn = 0; + this._tokenizerCondition = this._tokenizer.initialCondition; }, highlight: function(endLine) { // First check if we have work to do. - var state = this._textModel.getAttribute(endLine - 1, "highlighter-state") - if (state && !state.outOfDate) { - // Last line is highlighted, just exit. + if (endLine <= this._lastHighlightedLine) return; - } this._requestedEndLine = endLine; @@ -60,110 +67,66 @@ WebInspector.TextEditorHighlighter.prototype = { return; } - // We will be highlighting. First rewind to the last highlighted line to gain proper highlighter context. - var startLine = endLine; - while (startLine > 0) { - var state = this._textModel.getAttribute(startLine - 1, "highlighter-state"); - if (state && !state.outOfDate) - break; - startLine--; - } - // Do small highlight synchronously. This will provide instant highlight on PageUp / PageDown, gentle scrolling. - var toLine = Math.min(startLine + 200, endLine); - this._highlightInChunks(startLine, toLine); + this._highlightInChunks(endLine); // Schedule tail highlight if necessary. - if (endLine > toLine) - this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, toLine, endLine), 100); + if (this._lastHighlightedLine < endLine) + this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, endLine), 100); }, - _highlightInChunks: function(startLine, endLine) + _highlightInChunks: function(endLine) { delete this._highlightTimer; // First we always check if we have work to do. Could be that user scrolled back and we can quit. - var state = this._textModel.getAttribute(this._requestedEndLine - 1, "highlighter-state"); - if (state && !state.outOfDate) + if (this._requestedEndLine <= this._lastHighlightedLine) return; if (this._requestedEndLine !== endLine) { // User keeps updating the job in between of our timer ticks. Just reschedule self, don't eat CPU (they must be scrolling). - this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, startLine, this._requestedEndLine), 100); + this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._requestedEndLine), 100); return; } - // Highlight 500 lines chunk. - var toLine = Math.min(startLine + 500, this._requestedEndLine); - this._highlightLines(startLine, toLine); + this._highlightLines(this._requestedEndLine); // Schedule tail highlight if necessary. - if (toLine < this._requestedEndLine) - this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, toLine, this._requestedEndLine), 10); + if (this._lastHighlightedLine < this._requestedEndLine) + this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._requestedEndLine), 10); }, - updateHighlight: function(startLine, endLine) + _highlightLines: function(endLine) { - // Start line was edited, we should highlight everything until endLine synchronously. - if (startLine) { - var state = this._textModel.getAttribute(startLine - 1, "highlighter-state"); - if (!state || state.outOfDate) { - // Highlighter did not reach this point yet, nothing to update. It will reach it on subsequent timer tick and do the job. - return; - } - } - - var restored = this._highlightLines(startLine, endLine); - - // Set invalidated flag to the subsequent lines. - 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) - { - // Restore highlighter context taken from previous line. - 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)) { - // Following lines are up to date, no need re-highlight. - this._damageCallback(startLine, i + 1); - return true; - } + // Tokenizer is stateless and reused accross viewers, restore its condition before highlight and save it after. + this._tokenizer.condition = this._tokenizerCondition; + var tokensCount = 0; + for (var lineNumber = this._lastHighlightedLine; lineNumber < endLine; ++lineNumber) { + var line = this._textModel.line(lineNumber); + this._tokenizer.line = line; + var attributes = this._textModel.getAttribute(lineNumber, "highlight") || {}; + + // Highlight line. + do { + var newColumn = this._tokenizer.nextToken(this._lastHighlightedColumn); + var tokenType = this._tokenizer.tokenType; + if (tokenType) + attributes[this._lastHighlightedColumn] = { length: newColumn - this._lastHighlightedColumn, tokenType: tokenType, subTokenizer: this._tokenizer.subTokenizer }; + this._lastHighlightedColumn = newColumn; + if (++tokensCount > 1000) + break; + } while (this._lastHighlightedColumn < line.length) + + this._textModel.setAttribute(lineNumber, "highlight", attributes); + if (this._lastHighlightedColumn < line.length) { + // Too much work for single chunk - exit. + break; + } else + this._lastHighlightedColumn = 0; } - 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, tokenType: tokenType }; - column = newColumn; - } while (column < line.length) + this._damageCallback(this._lastHighlightedLine, lineNumber); + this._tokenizerCondition = this._tokenizer.condition; + this._lastHighlightedLine = lineNumber; } } |