diff --git a/lib/ace/background_tokenizer.js b/lib/ace/background_tokenizer.js index 2fe9dceb..179c1d1b 100644 --- a/lib/ace/background_tokenizer.js +++ b/lib/ace/background_tokenizer.js @@ -222,10 +222,15 @@ var BackgroundTokenizer = function(tokenizer, editor) { * * @param {Number} row The row to get state at **/ - this.getState = function(row) { + this.getState = function(row, column) { if (this.currentLine == row) this.$tokenizeRow(row); - return this.states[row] || "start"; + if (typeof column != "number") + return this.states[row] || "start"; + + var line = this.doc.getLine(row); + var state = this.states[row - 1]; + return this.tokenizer.getStateAt(line, column, state, row); }; this.$tokenizeRow = function(row) { diff --git a/lib/ace/tokenizer.js b/lib/ace/tokenizer.js index b4ef627b..ecddd4ae 100644 --- a/lib/ace/tokenizer.js +++ b/lib/ace/tokenizer.js @@ -325,6 +325,72 @@ var Tokenizer = function(rules) { }; }; + this.getStateAt = function(line, column, startState) { + if (startState && typeof startState != "string") { + var stack = startState.slice(0); + startState = stack[0]; + } else + var stack = []; + + column = Math.min(column, line.length); + var tokenCount = MAX_TOKEN_COUNT; + + var currentState = startState || "start"; + var state = this.states[currentState]; + var mapping = this.matchMappings[currentState]; + var re = this.regExps[currentState]; + re.lastIndex = 0; + + var match, tokens = []; + var lastIndex = 0; + + while (match = re.exec(line)) { + var type = mapping.defaultToken; + var rule = null; + var value = match[0]; + var index = re.lastIndex; + + for (var i = 0; i < match.length-2; i++) { + if (match[i + 1] === undefined) + continue; + + rule = state[mapping[i]]; + + if (rule.onMatch) + rule.onMatch(value, currentState, stack); + + if (rule.next) { + if (typeof rule.next == "string") + currentState = rule.next; + else + currentState = rule.next(currentState, stack); + + state = this.states[currentState]; + if (!state) { + window.console && console.error && console.error(currentState, "doesn't exist"); + currentState = "start"; + state = this.states[currentState]; + } + mapping = this.matchMappings[currentState]; + lastIndex = index; + re = this.regExps[currentState]; + re.lastIndex = index; + } + break; + } + + if (lastIndex >= column) + break; + + lastIndex = index; + + if (!tokenCount--) { + break; + } + } + return stack.length ? stack : currentState; + }; + }).call(Tokenizer.prototype); exports.Tokenizer = Tokenizer;