From f9bf9bfc9a385aa23963bd84ad388e5efb594966 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Tue, 26 Apr 2011 10:39:27 +0200 Subject: [PATCH] move background tokenizer from the editor to the edit session --- lib/ace/background_tokenizer.js | 5 +-- lib/ace/edit_session.js | 33 ++++++++++++++-- lib/ace/editor.js | 67 +++++++++++++-------------------- lib/ace/layer/text.js | 10 ++--- lib/ace/virtual_renderer.js | 8 +--- 5 files changed, 61 insertions(+), 62 deletions(-) diff --git a/lib/ace/background_tokenizer.js b/lib/ace/background_tokenizer.js index 6e2bf669..f845e3f1 100644 --- a/lib/ace/background_tokenizer.js +++ b/lib/ace/background_tokenizer.js @@ -56,7 +56,6 @@ var BackgroundTokenizer = function(tokenizer, editor) { var doc = self.doc; var processedLines = 0; - var lastVisibleRow = editor.getLastVisibleRow(); var len = doc.getLength(); while (self.currentLine < len) { @@ -67,9 +66,7 @@ var BackgroundTokenizer = function(tokenizer, editor) { 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); + self.running = setTimeout(self.$worker, 20); return; } } diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 83adf78b..a96e419a 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -46,6 +46,7 @@ var Selection = require("ace/selection").Selection; var TextMode = require("ace/mode/text").Mode; var Range = require("ace/range").Range; var Document = require("ace/document").Document; +var BackgroundTokenizer = require("ace/background_tokenizer").BackgroundTokenizer; var EditSession = function(text, mode) { this.$modified = true; @@ -64,6 +65,8 @@ var EditSession = function(text, mode) { this.selection = new Selection(this); if (mode) this.setMode(mode); + else + this.setMode(new TextMode()); }; @@ -92,6 +95,8 @@ var EditSession = function(text, mode) { } this.$updateWrapDataOnChange(e); + + this.bgTokenizer.start(delta.range.start.row); this._dispatchEvent("change", e); }; @@ -110,6 +115,14 @@ var EditSession = function(text, mode) { return this.selection; }; + this.getState = function(row) { + return this.bgTokenizer.getState(row); + }; + + this.getTokens = function(firstRow, lastRow) { + return this.bgTokenizer.getTokens(firstRow, lastRow); + }; + this.setUndoManager = function(undoManager) { this.$undoManager = undoManager; this.$deltas = []; @@ -371,19 +384,31 @@ var EditSession = function(text, mode) { if (this.$worker) this.$worker.terminate(); - if (this.$useWorker && window.Worker && !require.noWorker) + if (this.$useWorker && typeof Worker !== "undefined" && !require.noWorker) this.$worker = mode.createWorker(this); else this.$worker = null; + var tokenizer = mode.getTokenizer(); + + if (!this.bgTokenizer) { + this.bgTokenizer = new BackgroundTokenizer(tokenizer); + var _self = this; + this.bgTokenizer.addEventListener("update", function(e) { + _self._dispatchEvent("tokenizerUpdate", e); + }); + } else { + this.bgTokenizer.setTokenizer(tokenizer); + } + + this.bgTokenizer.setDocument(this.getDocument()); + this.bgTokenizer.start(0); + this.$mode = mode; this._dispatchEvent("changeMode"); }; this.getMode = function() { - if (!this.$mode) { - this.$mode = new TextMode(); - } return this.$mode; }; diff --git a/lib/ace/editor.js b/lib/ace/editor.js index b8fe95b7..01fe0bfd 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -52,7 +52,6 @@ var MouseHandler = require("ace/mouse_handler").MouseHandler; var KeyBinding = require("ace/keyboard/keybinding").KeyBinding; var EditSession = require("ace/edit_session").EditSession; var Search = require("ace/search").Search; -var BackgroundTokenizer = require("ace/background_tokenizer").BackgroundTokenizer; var Range = require("ace/range").Range; var EventEmitter = require("pilot/event_emitter").EventEmitter; @@ -122,6 +121,7 @@ var Editor =function(renderer, session) { var oldSession = this.session; this.session.removeEventListener("change", this.$onDocumentChange); this.session.removeEventListener("changeMode", this.$onChangeMode); + this.session.removeEventListener("tokenizerUpdate", this.$onTokenizerUpdate); this.session.removeEventListener("changeTabSize", this.$onChangeTabSize); this.session.removeEventListener("changeWrapLimit", this.$onChangeWrapLimit); this.session.removeEventListener("changeWrapMode", this.$onChangeWrapMode); @@ -147,6 +147,9 @@ var Editor =function(renderer, session) { this.$onChangeMode = this.onChangeMode.bind(this); session.addEventListener("changeMode", this.$onChangeMode); + this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this); + session.addEventListener("tokeizerupdate", this.$onTokenizerUpdate); + this.$onChangeTabSize = this.renderer.updateText.bind(this.renderer); session.addEventListener("changeTabSize", this.$onChangeTabSize); @@ -178,8 +181,6 @@ var Editor =function(renderer, session) { this.selection.addEventListener("changeSelection", this.$onSelectionChange); this.onChangeMode(); - this.bgTokenizer.setDocument(session.getDocument()); - this.bgTokenizer.start(0); this.onCursorChange(); this.onSelectionChange(); @@ -278,7 +279,6 @@ var Editor =function(renderer, session) { var delta = e.data; var range = delta.range; - this.bgTokenizer.start(range.start.row); if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines") var lastRow = range.end.row; else @@ -341,7 +341,7 @@ var Editor =function(renderer, session) { this.onCursorChange(e); if (this.$highlightSelectedWord) - this.mode.highlightSelection(this); + this.session.getMode().highlightSelection(this); }; this.onChangeFrontMarker = function() { @@ -361,22 +361,7 @@ var Editor =function(renderer, session) { }; this.onChangeMode = function() { - var mode = this.session.getMode(); - if (this.mode == mode) - return; - - this.mode = mode; - var tokenizer = mode.getTokenizer(); - - if (!this.bgTokenizer) { - var onUpdate = this.onTokenizerUpdate.bind(this); - this.bgTokenizer = new BackgroundTokenizer(tokenizer, this); - this.bgTokenizer.addEventListener("update", onUpdate); - } else { - this.bgTokenizer.setTokenizer(tokenizer); - } - - this.renderer.setTokenizer(this.bgTokenizer); + this.renderer.updateText() }; this.onChangeWrapLimit = function() { @@ -410,6 +395,9 @@ var Editor =function(renderer, session) { if (this.$readOnly) return; + var session = this.session; + var mode = session.getMode(); + var cursor = this.getCursorPosition(); text = text.replace("\t", this.session.getTabString()); @@ -426,28 +414,27 @@ var Editor =function(renderer, session) { this.clearSelection(); - var lineState = this.bgTokenizer.getState(cursor.row); - var shouldOutdent = this.mode.checkOutdent(lineState, this.session.getLine(cursor.row), text); - var line = this.session.getLine(cursor.row); - var lineIndent = this.mode.getNextLineIndent(lineState, line.slice(0, cursor.column), this.session.getTabString()); - var end = this.session.insert(cursor, text); + var lineState = session.getState(cursor.row); + var shouldOutdent = mode.checkOutdent(lineState, session.getLine(cursor.row), text); + var line = session.getLine(cursor.row); + var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString()); + var end = session.insert(cursor, text); - var lineState = this.bgTokenizer.getState(cursor.row); + var lineState = session.getState(cursor.row); // TODO disabled multiline auto indent // possibly doing the indent before inserting the text // if (cursor.row !== end.row) { - if (this.session.getDocument().isNewLine(text)) { + if (session.getDocument().isNewLine(text)) { this.moveCursorTo(cursor.row+1, 0); - var size = this.session.getTabSize(), - minIndent = Number.MAX_VALUE; + var size = session.getTabSize(); + var minIndent = Number.MAX_VALUE; - for (var row = cursor.row + 1; row <= end.row; ++row) { var indent = 0; - line = this.session.getLine(row); + line = session.getLine(row); for (var i = 0; i < line.length; ++i) if (line.charAt(i) == '\t') indent += size; @@ -462,18 +449,18 @@ var Editor =function(renderer, session) { for (var row = cursor.row + 1; row <= end.row; ++row) { var outdent = minIndent; - line = this.session.getLine(row); + line = session.getLine(row); for (var i = 0; i < line.length && outdent > 0; ++i) if (line.charAt(i) == '\t') outdent -= size; else if (line.charAt(i) == ' ') outdent -= 1; - this.session.remove(new Range(row, 0, row, i)); + session.remove(new Range(row, 0, row, i)); } - this.session.indentRows(cursor.row + 1, end.row, lineIndent); + session.indentRows(cursor.row + 1, end.row, lineIndent); } else { if (shouldOutdent) { - this.mode.autoOutdent(lineState, this.session, cursor.row); + mode.autoOutdent(lineState, session, cursor.row); } }; } @@ -538,9 +525,9 @@ var Editor =function(renderer, session) { this.$highlightSelectedWord = shouldHighlight; if (shouldHighlight) - this.mode.highlightSelection(this); + this.session.getMode().highlightSelection(this); else - this.mode.clearSelectionHighlight(this); + this.session.getMode().clearSelectionHighlight(this); }; this.getHighlightSelectedWord = function() { @@ -726,9 +713,9 @@ var Editor =function(renderer, session) { if (this.$readOnly) return; - var state = this.bgTokenizer.getState(this.getCursorPosition().row); + var state = this.session.getState(this.getCursorPosition().row); var rows = this.$getSelectedRows() - this.mode.toggleCommentLines(state, this.session, rows.first, rows.last); + this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last); }; this.removeLines = function() { diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index 833338c6..a4fdee3d 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -63,10 +63,6 @@ var Text = function(parentEl) { this.TAB_CHAR = "→"; this.SPACE_CHAR = "·"; - this.setTokenizer = function(tokenizer) { - this.tokenizer = tokenizer; - }; - this.getLineHeight = function() { return this.$characterSize.height || 1; }; @@ -191,7 +187,7 @@ var Text = function(parentEl) { var last = Math.min(lastRow, config.lastRow); var lineElements = this.element.childNodes; - var tokens = this.tokenizer.getTokens(first, last); + var tokens = this.session.getTokens(first, last); for (var i=first; i<=last; i++) { var lineElement = lineElements[i - config.firstRow]; if (!lineElement) @@ -242,7 +238,7 @@ var Text = function(parentEl) { this.$renderLinesFragment = function(config, firstRow, lastRow) { var fragment = document.createDocumentFragment(); - var tokens = this.tokenizer.getTokens(firstRow, lastRow); + var tokens = this.session.getTokens(firstRow, lastRow); for (var row=firstRow; row<=lastRow; row++) { var lineEl = dom.createElement("div"); lineEl.className = "ace_line"; @@ -265,7 +261,7 @@ var Text = function(parentEl) { this.config = config; var html = []; - var tokens = this.tokenizer.getTokens(config.firstRow, config.lastRow) + var tokens = this.session.getTokens(config.firstRow, config.lastRow) var fragment = this.$renderLinesFragment(config, config.firstRow, config.lastRow); // Clear the current content of the element and add the rendered fragment. diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 8ef081e0..6ab0f8f1 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -237,12 +237,6 @@ var VirtualRenderer = function(container, theme) { this.$loop.schedule(changes); }; - this.setTokenizer = function(tokenizer) { - this.$tokenizer = tokenizer; - this.$textLayer.setTokenizer(tokenizer); - this.$loop.schedule(this.CHANGE_TEXT); - }; - this.$onGutterClick = function(e) { var pageX = event.getDocumentX(e); var pageY = event.getDocumentY(e); @@ -395,7 +389,7 @@ var VirtualRenderer = function(container, theme) { }; this.$renderChanges = function(changes) { - if (!changes || !this.session || !this.$tokenizer) + if (!changes || !this.session) return; // text, scrolling and resize changes can cause the view port size to change