From 4276f1544df07a91f579812baa16770f38c60db6 Mon Sep 17 00:00:00 2001 From: James Allen Date: Thu, 6 Jul 2017 11:56:20 +0100 Subject: [PATCH] Update ace latex worker to include context reporting --- .../web/public/js/ace-1.2.5/mode-latex.js | 2 +- .../web/public/js/ace-1.2.5/worker-latex.js | 480 +++++++++++------- 2 files changed, 291 insertions(+), 191 deletions(-) diff --git a/services/web/public/js/ace-1.2.5/mode-latex.js b/services/web/public/js/ace-1.2.5/mode-latex.js index 8e7bbe4802..7c5f426713 100644 --- a/services/web/public/js/ace-1.2.5/mode-latex.js +++ b/services/web/public/js/ace-1.2.5/mode-latex.js @@ -330,7 +330,7 @@ var createLatexWorker = function (session) { }; worker.on("lint", function(results) { if(docChangePending) { docChangePending = false; }; - hints = results.data; + hints = results.data.errors; if (hints.length > 100) { hints = hints.slice(0, 100); // limit to 100 errors }; diff --git a/services/web/public/js/ace-1.2.5/worker-latex.js b/services/web/public/js/ace-1.2.5/worker-latex.js index ccd7e2da9b..dfb4e69e56 100644 --- a/services/web/public/js/ace-1.2.5/worker-latex.js +++ b/services/web/public/js/ace-1.2.5/worker-latex.js @@ -1419,6 +1419,33 @@ var LatexWorker = exports.LatexWorker = function(sender) { oop.inherits(LatexWorker, Mirror); +(function() { + var disabled = false; + this.onUpdate = function() { + if (disabled) { return ; }; + + var value = this.doc.getValue(); + var errors = []; + var contexts = []; + try { + if (value) { + var result = Parse(value); + errors = result.errors; + contexts = result.contexts; + } + } catch (e) { + console.log(e); + disabled = true; + errors = []; + } + this.sender.emit("lint", { + errors: errors, + contexts: contexts + }); + }; + +}).call(LatexWorker.prototype); + var Tokenise = function (text) { var Tokens = []; var Comments = []; @@ -1503,22 +1530,8 @@ var Tokenise = function (text) { } idx = SPECIAL.lastIndex = nextSpecialPos; } - } else if (code === "{") { // open group - Tokens.push([lineNumber, code, pos]); - } else if (code === "}") { // close group - Tokens.push([lineNumber, code, pos]); - } else if (code === "$") { // math mode - Tokens.push([lineNumber, code, pos]); - } else if (code === "&") { // tabalign - Tokens.push([lineNumber, code, pos]); - } else if (code === "#") { // macro parameter - Tokens.push([lineNumber, code, pos]); - } else if (code === "^") { // superscript - Tokens.push([lineNumber, code, pos]); - } else if (code === "_") { // subscript - Tokens.push([lineNumber, code, pos]); - } else if (code === "~") { // active character (space) - Tokens.push([lineNumber, code, pos]); + } else if (["{", "}", "$", "&", "#", "^", "_", "~"].indexOf(code) > -1) { // special characters + Tokens.push([lineNumber, code, pos, pos+1]); } else { throw "unrecognised character " + code; } @@ -1539,15 +1552,15 @@ var read1arg = function (TokeniseResult, k, options) { }; var open = Tokens[k+1]; - var env = Tokens[k+2]; + var delimiter = Tokens[k+2]; var close = Tokens[k+3]; - var envName; + var delimiterName; if(open && open[1] === "\\") { - envName = open[4]; // array element 4 is command sequence + delimiterName = open[4]; // array element 4 is command sequence return k + 1; - } else if(open && open[1] === "{" && env && env[1] === "\\" && close && close[1] === "}") { - envName = env[4]; // NOTE: if we were actually using this, keep track of * above + } else if(open && open[1] === "{" && delimiter && delimiter[1] === "\\" && close && close[1] === "}") { + delimiterName = delimiter[4]; // NOTE: if we were actually using this, keep track of * above return k + 3; // array element 4 is command sequence } else { return null; @@ -1579,21 +1592,21 @@ var read1name = function (TokeniseResult, k) { var text = TokeniseResult.text; var open = Tokens[k+1]; - var env = Tokens[k+2]; + var delimiter = Tokens[k+2]; var close = Tokens[k+3]; - if(open && open[1] === "{" && env && env[1] === "Text" && close && close[1] === "}") { - var envName = text.substring(env[2], env[3]); + if(open && open[1] === "{" && delimiter && delimiter[1] === "Text" && close && close[1] === "}") { + var delimiterName = text.substring(delimiter[2], delimiter[3]); return k + 3; - } else if (open && open[1] === "{" && env && env[1] === "Text") { - envName = ""; + } else if (open && open[1] === "{" && delimiter && delimiter[1] === "Text") { + delimiterName = ""; for (var j = k + 2, tok; (tok = Tokens[j]); j++) { if (tok[1] === "Text") { var str = text.substring(tok[2], tok[3]); if (!str.match(/^\S*$/)) { break; } - envName = envName + str; + delimiterName = delimiterName + str; } else if (tok[1] === "_") { - envName = envName + "_"; + delimiterName = delimiterName + "_"; } else { break; } @@ -1788,7 +1801,7 @@ var InterpretTokens = function (TokeniseResult, ErrorReporter) { var TokenErrorFromTo = ErrorReporter.TokenErrorFromTo; var TokenError = ErrorReporter.TokenError; - var Environments = new EnvHandler(ErrorReporter); + var Environments = new EnvHandler(TokeniseResult, ErrorReporter); var nextGroupMathMode = null; // if the next group should have var nextGroupMathModeStack = [] ; // tracking all nextGroupMathModes @@ -1815,28 +1828,28 @@ var InterpretTokens = function (TokeniseResult, ErrorReporter) { if (type === "\\") { if (seq === "begin" || seq === "end") { var open = Tokens[i+1]; - var env = Tokens[i+2]; + var delimiter = Tokens[i+2]; var close = Tokens[i+3]; - if(open && open[1] === "{" && env && env[1] === "Text" && close && close[1] === "}") { - var envName = text.substring(env[2], env[3]); - Environments.push({command: seq, name: envName, token: token, closeToken: close}); + if(open && open[1] === "{" && delimiter && delimiter[1] === "Text" && close && close[1] === "}") { + var delimiterName = text.substring(delimiter[2], delimiter[3]); + Environments.push({command: seq, name: delimiterName, token: token, closeToken: close}); i = i + 3; // advance past these tokens } else { - if (open && open[1] === "{" && env && env[1] === "Text") { - envName = ""; + if (open && open[1] === "{" && delimiter && delimiter[1] === "Text") { + delimiterName = ""; for (var j = i + 2, tok; (tok = Tokens[j]); j++) { if (tok[1] === "Text") { var str = text.substring(tok[2], tok[3]); if (!str.match(/^\S*$/)) { break; } - envName = envName + str; + delimiterName = delimiterName + str; } else if (tok[1] === "_") { - envName = envName + "_"; + delimiterName = delimiterName + "_"; } else { break; } } if (tok && tok[1] === "}") { - Environments.push({command: seq, name: envName, token: token, closeToken: close}); + Environments.push({command: seq, name: delimiterName, token: token, closeToken: close}); i = j; // advance past these tokens continue; } @@ -1844,8 +1857,8 @@ var InterpretTokens = function (TokeniseResult, ErrorReporter) { var endToken = null; if (open && open[1] === "{") { endToken = open; // we've got a { - if (env && env[1] === "Text") { - endToken = env.slice(); // we've got some text following the { + if (delimiter && delimiter[1] === "Text") { + endToken = delimiter.slice(); // we've got some text following the { start = endToken[2]; end = endToken[3]; for (j = start; j < end; j++) { var char = text[j]; @@ -1978,7 +1991,12 @@ var InterpretTokens = function (TokeniseResult, ErrorReporter) { var nextIsDollar = lookAhead && lookAhead[1] === "$"; currentMathMode = Environments.getMathMode() ; // returns null / $(inline) / $$(display) if (nextIsDollar && (!currentMathMode || currentMathMode.command == "$$")) { - Environments.push({command:"$$", token:token}); + if (currentMathMode && currentMathMode.command == "$$") { + var delimiterToken = lookAhead; + } else { + var delimiterToken = token; + } + Environments.push({command:"$$", token:delimiterToken}); i = i + 1; } else { Environments.push({command:"$", token:token}); @@ -1999,74 +2017,174 @@ var InterpretTokens = function (TokeniseResult, ErrorReporter) { return Environments; }; -var EnvHandler = function (ErrorReporter) { +var DocumentTree = function(TokeniseResult) { + var tree = { + children: [] + }; + var stack = [tree]; + + this.openEnv = function(startDelimiter) { + var currentNode = this.getCurrentNode(); + var newNode = { + startDelimiter: startDelimiter, + children: [] + }; + currentNode.children.push(newNode); + stack.push(newNode); + }; + + this.closeEnv = function(endDelimiter) { + if (stack.length == 1) { + return null + } + var currentNode = stack.pop(); + currentNode.endDelimiter = endDelimiter; + return currentNode.startDelimiter; + }; + + this.getNthPreviousNode = function(n) { + var offset = stack.length - n - 1; + if (offset < 0) + return null; + return stack[offset]; + } + + this.getCurrentNode = function() { + return this.getNthPreviousNode(0); + } + + this.getCurrentDelimiter = function() { + return this.getCurrentNode().startDelimiter; + }; + + this.getPreviousDelimiter = function() { + var node = this.getNthPreviousNode(1); + if (!node) + return null + return node.startDelimiter; + } + + this.getDepth = function() { + return (stack.length - 1) // Root node doesn't count + } + + this.getContexts = function() { + var linePosition = TokeniseResult.linePosition; + + function tokenToRange(token) { + var line = token[0], start = token[2], end = token[3]; + var start_col = start - linePosition[line]; + if (!end) { end = start + 1; } ; + var end_col = end - linePosition[line]; + return { + start: { + row: line, + column: start_col + }, + end: { + row: line, + column: end_col + } + } + }; + + function getContextsFromNode(node) { + if (node.startDelimiter && node.startDelimiter.mathMode) { + var context = { + type: "math", + range: { + start: tokenToRange(node.startDelimiter.token).start + } + }; + if (node.endDelimiter) { + var closeToken = node.endDelimiter.closeToken || node.endDelimiter.token; + context.range.end = tokenToRange(closeToken).end; + }; + return [context]; + } else { + var contexts = []; + for (var i = 0; i < node.children.length; i++) { + var child = node.children[i]; + contexts = contexts.concat(getContextsFromNode(child)); + } + return contexts; + } + }; + + return getContextsFromNode(tree); + } +} + +var EnvHandler = function (TokeniseResult, ErrorReporter) { var ErrorTo = ErrorReporter.EnvErrorTo; var ErrorFromTo = ErrorReporter.EnvErrorFromTo; var ErrorFrom = ErrorReporter.EnvErrorFrom; - var envs = []; + var delimiters = []; - var state = []; + var document = new DocumentTree(TokeniseResult); var documentClosed = null; var inVerbatim = false; var verbatimRanges = []; - - this.Environments = envs; - - this.push = function (newEnv) { - this.setEnvProps(newEnv); - this.checkAndUpdateState(newEnv); - envs.push(newEnv); + + this.getDocument = function() { + return document; }; - this._endVerbatim = function (thisEnv) { - var lastEnv = state.pop(); - if (lastEnv && lastEnv.name === thisEnv.name) { + this.push = function (newDelimiter) { + this.setDelimiterProps(newDelimiter); + this.checkAndUpdateState(newDelimiter); + delimiters.push(newDelimiter); + }; + + this._endVerbatim = function (thisDelimiter) { + var lastDelimiter = document.getCurrentDelimiter(); + if (lastDelimiter && lastDelimiter.name === thisDelimiter.name) { inVerbatim = false; - verbatimRanges.push({start: lastEnv.token[2], end: thisEnv.token[2]}); - } else { - if(lastEnv) { state.push(lastEnv); } ; + document.closeEnv(thisDelimiter); + verbatimRanges.push({start: lastDelimiter.token[2], end: thisDelimiter.token[2]}); } }; var invalidEnvs = []; - this._end = function (thisEnv) { + this._end = function (thisDelimiter) { do { - var lastEnv = state.pop(); + var lastDelimiter = document.getCurrentDelimiter(); var retry = false; var i; - if (closedBy(lastEnv, thisEnv)) { - if (thisEnv.command === "end" && thisEnv.name === "document" && !documentClosed) { - documentClosed = thisEnv; + if (closedBy(lastDelimiter, thisDelimiter)) { + document.closeEnv(thisDelimiter); + if (thisDelimiter.command === "end" && thisDelimiter.name === "document" && !documentClosed) { + documentClosed = thisDelimiter; }; return; - } else if (!lastEnv) { + } else if (!lastDelimiter) { if (documentClosed) { - ErrorFromTo(documentClosed, thisEnv, "\\end{" + documentClosed.name + "} is followed by unexpected content",{errorAtStart: true, type: "info"}); + ErrorFromTo(documentClosed, thisDelimiter, "\\end{" + documentClosed.name + "} is followed by unexpected content",{errorAtStart: true, type: "info"}); } else { - ErrorTo(thisEnv, "unexpected " + getName(thisEnv)); + ErrorTo(thisDelimiter, "unexpected " + getName(thisDelimiter)); } - } else if (invalidEnvs.length > 0 && (i = indexOfClosingEnvInArray(invalidEnvs, thisEnv) > -1)) { + } else if (invalidEnvs.length > 0 && (i = indexOfClosingEnvInArray(invalidEnvs, thisDelimiter) > -1)) { invalidEnvs.splice(i, 1); - if (lastEnv) { state.push(lastEnv); } ; return; } else { - var status = reportError(lastEnv, thisEnv); - if (envPrecedence(lastEnv) < envPrecedence(thisEnv)) { - invalidEnvs.push(lastEnv); + var status = reportError(lastDelimiter, thisDelimiter); + if (delimiterPrecedence(lastDelimiter) < delimiterPrecedence(thisDelimiter)) { + document.closeEnv(); + invalidEnvs.push(lastDelimiter); retry = true; } else { - var prevLastEnv = state.pop(); - if(prevLastEnv) { - if (thisEnv.name === prevLastEnv.name) { + var prevDelimiter = document.getPreviousDelimiter(); + if(prevDelimiter) { + if (thisDelimiter.name === prevDelimiter.name) { + document.closeEnv() // Close current env + document.closeEnv(thisDelimiter) // Close previous env return; - } else { - state.push(prevLastEnv); } } - invalidEnvs.push(lastEnv); + invalidEnvs.push(lastDelimiter); } } @@ -2082,28 +2200,28 @@ var EnvHandler = function (ErrorReporter) { "$$": "$$" }; - var closedBy = function (lastEnv, thisEnv) { - if (!lastEnv) { + var closedBy = function (lastDelimiter, thisDelimiter) { + if (!lastDelimiter) { return false ; - } else if (thisEnv.command === "end") { - return lastEnv.command === "begin" && lastEnv.name === thisEnv.name; - } else if (thisEnv.command === CLOSING_DELIMITER[lastEnv.command]) { + } else if (thisDelimiter.command === "end") { + return lastDelimiter.command === "begin" && lastDelimiter.name === thisDelimiter.name; + } else if (thisDelimiter.command === CLOSING_DELIMITER[lastDelimiter.command]) { return true; } else { return false; } }; - var indexOfClosingEnvInArray = function (envs, thisEnv) { - for (var i = 0, n = envs.length; i < n ; i++) { - if (closedBy(envs[i], thisEnv)) { + var indexOfClosingEnvInArray = function (delimiters, thisDelimiter) { + for (var i = 0, n = delimiters.length; i < n ; i++) { + if (closedBy(delimiters[i], thisDelimiter)) { return i; } } return -1; }; - var envPrecedence = function (env) { + var delimiterPrecedence = function (delimiter) { var openScore = { "{" : 1, "left" : 2, @@ -2118,14 +2236,14 @@ var EnvHandler = function (ErrorReporter) { "$$" : 5, "end": 4 }; - if (env.command) { - return openScore[env.command] || closeScore[env.command]; + if (delimiter.command) { + return openScore[delimiter.command] || closeScore[delimiter.command]; } else { return 0; } }; - var getName = function(env) { + var getName = function(delimiter) { var description = { "{" : "open group {", "}" : "close group }", @@ -2138,12 +2256,12 @@ var EnvHandler = function (ErrorReporter) { "left" : "\\left", "right" : "\\right" }; - if (env.command === "begin" || env.command === "end") { - return "\\" + env.command + "{" + env.name + "}"; - } else if (env.command in description) { - return description[env.command]; + if (delimiter.command === "begin" || delimiter.command === "end") { + return "\\" + delimiter.command + "{" + delimiter.name + "}"; + } else if (delimiter.command in description) { + return description[delimiter.command]; } else { - return env.command; + return delimiter.command; } }; @@ -2151,81 +2269,81 @@ var EnvHandler = function (ErrorReporter) { var UNCLOSED_GROUP = 2; var UNCLOSED_ENV = 3; - var reportError = function(lastEnv, thisEnv) { - if (!lastEnv) { // unexpected close, nothing was open! + var reportError = function(lastDelimiter, thisDelimiter) { + if (!lastDelimiter) { // unexpected close, nothing was open! if (documentClosed) { - ErrorFromTo(documentClosed, thisEnv, "\\end{" + documentClosed.name + "} is followed by unexpected end group }",{errorAtStart: true, type: "info"}); + ErrorFromTo(documentClosed, thisDelimiter, "\\end{" + documentClosed.name + "} is followed by unexpected end group }",{errorAtStart: true, type: "info"}); } else { - ErrorTo(thisEnv, "unexpected " + getName(thisEnv)); + ErrorTo(thisDelimiter, "unexpected " + getName(thisDelimiter)); }; return EXTRA_CLOSE; - } else if (lastEnv.command === "{" && thisEnv.command === "end") { - ErrorFromTo(lastEnv, thisEnv, "unclosed " + getName(lastEnv) + " found at " + getName(thisEnv), + } else if (lastDelimiter.command === "{" && thisDelimiter.command === "end") { + ErrorFromTo(lastDelimiter, thisDelimiter, "unclosed " + getName(lastDelimiter) + " found at " + getName(thisDelimiter), {suppressIfEditing:true, errorAtStart: true, type:"warning"}); return UNCLOSED_GROUP; } else { - var pLast = envPrecedence(lastEnv); - var pThis = envPrecedence(thisEnv); + var pLast = delimiterPrecedence(lastDelimiter); + var pThis = delimiterPrecedence(thisDelimiter); if (pThis > pLast) { - ErrorFromTo(lastEnv, thisEnv, "unclosed " + getName(lastEnv) + " found at " + getName(thisEnv), + ErrorFromTo(lastDelimiter, thisDelimiter, "unclosed " + getName(lastDelimiter) + " found at " + getName(thisDelimiter), {suppressIfEditing:true, errorAtStart: true}); } else { - ErrorFromTo(lastEnv, thisEnv, "unexpected " + getName(thisEnv) + " after " + getName(lastEnv)); + ErrorFromTo(lastDelimiter, thisDelimiter, "unexpected " + getName(thisDelimiter) + " after " + getName(lastDelimiter)); } return UNCLOSED_ENV; }; }; - this._beginMathMode = function (thisEnv) { + this._beginMathMode = function (thisDelimiter) { var currentMathMode = this.getMathMode(); // undefined, null, $, $$, name of mathmode env if (currentMathMode) { - ErrorFrom(thisEnv, getName(thisEnv) + " used inside existing math mode " + getName(currentMathMode), + ErrorFrom(thisDelimiter, getName(thisDelimiter) + " used inside existing math mode " + getName(currentMathMode), {suppressIfEditing:true, errorAtStart: true, mathMode:true}); }; - thisEnv.mathMode = thisEnv; - state.push(thisEnv); + thisDelimiter.mathMode = thisDelimiter; + document.openEnv(thisDelimiter); }; - this._toggleMathMode = function (thisEnv) { - var lastEnv = state.pop(); - if (closedBy(lastEnv, thisEnv)) { + this._toggleMathMode = function (thisDelimiter) { + var lastDelimiter = document.getCurrentDelimiter(); + if (closedBy(lastDelimiter, thisDelimiter)) { + document.closeEnv(thisDelimiter) return; } else { - if (lastEnv) {state.push(lastEnv);} - if (lastEnv && lastEnv.mathMode) { - this._end(thisEnv); + if (lastDelimiter && lastDelimiter.mathMode) { + this._end(thisDelimiter); } else { - thisEnv.mathMode = thisEnv; - state.push(thisEnv); + thisDelimiter.mathMode = thisDelimiter; + document.openEnv(thisDelimiter); } }; }; this.getMathMode = function () { - var n = state.length; - if (n > 0) { - return state[n-1].mathMode; + var currentDelimiter = document.getCurrentDelimiter(); + if (currentDelimiter) { + return currentDelimiter.mathMode; } else { return null; } }; this.insideGroup = function () { - var n = state.length; - if (n > 0) { - return (state[n-1].command === "{"); + var currentDelimiter = document.getCurrentDelimiter(); + if (currentDelimiter) { + return (currentDelimiter.command === "{"); } else { return null; } }; var resetMathMode = function () { - var n = state.length; - if (n > 0) { - var lastMathMode = state[n-1].mathMode; + var currentDelimiter = document.getCurrentDelimiter(); + if (currentDelimiter) { + var lastMathMode = currentDelimiter.mathMode; do { - var lastEnv = state.pop(); - } while (lastEnv && lastEnv !== lastMathMode); + var lastDelimiter = document.closeEnv(); + } while (lastDelimiter && lastDelimiter !== lastMathMode); } else { return; } @@ -2233,42 +2351,42 @@ var EnvHandler = function (ErrorReporter) { this.resetMathMode = resetMathMode; - var getNewMathMode = function (currentMathMode, thisEnv) { + var getNewMathMode = function (currentMathMode, thisDelimiter) { var newMathMode = null; - if (thisEnv.command === "{") { - if (thisEnv.mathMode !== null) { - newMathMode = thisEnv.mathMode; + if (thisDelimiter.command === "{") { + if (thisDelimiter.mathMode !== null) { + newMathMode = thisDelimiter.mathMode; } else { newMathMode = currentMathMode; } - } else if (thisEnv.command === "left") { + } else if (thisDelimiter.command === "left") { if (currentMathMode === null) { - ErrorFrom(thisEnv, "\\left can only be used in math mode", {mathMode: true}); + ErrorFrom(thisDelimiter, "\\left can only be used in math mode", {mathMode: true}); }; newMathMode = currentMathMode; - } else if (thisEnv.command === "begin") { - var name = thisEnv.name; + } else if (thisDelimiter.command === "begin") { + var name = thisDelimiter.name; if (name) { if (name.match(/^(document|figure|center|enumerate|itemize|table|abstract|proof|lemma|theorem|definition|proposition|corollary|remark|notation|thebibliography)$/)) { if (currentMathMode) { - ErrorFromTo(currentMathMode, thisEnv, thisEnv.name + " used inside " + getName(currentMathMode), + ErrorFromTo(currentMathMode, thisDelimiter, thisDelimiter.name + " used inside " + getName(currentMathMode), {suppressIfEditing:true, errorAtStart: true, mathMode: true}); resetMathMode(); }; newMathMode = null; } else if (name.match(/^(array|gathered|split|aligned|alignedat)\*?$/)) { if (currentMathMode === null) { - ErrorFrom(thisEnv, thisEnv.name + " not inside math mode", {mathMode: true}); + ErrorFrom(thisDelimiter, thisDelimiter.name + " not inside math mode", {mathMode: true}); }; newMathMode = currentMathMode; } else if (name.match(/^(math|displaymath|equation|eqnarray|multline|align|gather|flalign|alignat)\*?$/)) { if (currentMathMode) { - ErrorFromTo(currentMathMode, thisEnv, thisEnv.name + " used inside " + getName(currentMathMode), + ErrorFromTo(currentMathMode, thisDelimiter, thisDelimiter.name + " used inside " + getName(currentMathMode), {suppressIfEditing:true, errorAtStart: true, mathMode: true}); resetMathMode(); }; - newMathMode = thisEnv; + newMathMode = thisDelimiter; } else { newMathMode = undefined; // undefined means we don't know if we are in math mode or not } @@ -2277,41 +2395,41 @@ var EnvHandler = function (ErrorReporter) { return newMathMode; }; - this.checkAndUpdateState = function (thisEnv) { + this.checkAndUpdateState = function (thisDelimiter) { if (inVerbatim) { - if (thisEnv.command === "end") { - this._endVerbatim(thisEnv); + if (thisDelimiter.command === "end") { + this._endVerbatim(thisDelimiter); } else { return; // ignore anything in verbatim environments } - } else if(thisEnv.command === "begin" || thisEnv.command === "{" || thisEnv.command === "left") { - if (thisEnv.verbatim) {inVerbatim = true;}; + } else if(thisDelimiter.command === "begin" || thisDelimiter.command === "{" || thisDelimiter.command === "left") { + if (thisDelimiter.verbatim) {inVerbatim = true;}; var currentMathMode = this.getMathMode(); // undefined, null, $, $$, name of mathmode env - var newMathMode = getNewMathMode(currentMathMode, thisEnv); - thisEnv.mathMode = newMathMode; - state.push(thisEnv); - } else if (thisEnv.command === "end") { - this._end(thisEnv); - } else if (thisEnv.command === "(" || thisEnv.command === "[") { - this._beginMathMode(thisEnv); - } else if (thisEnv.command === ")" || thisEnv.command === "]") { - this._end(thisEnv); - } else if (thisEnv.command === "}") { - this._end(thisEnv); - } else if (thisEnv.command === "right") { - this._end(thisEnv); - } else if (thisEnv.command === "$" || thisEnv.command === "$$") { - this._toggleMathMode(thisEnv); + var newMathMode = getNewMathMode(currentMathMode, thisDelimiter); + thisDelimiter.mathMode = newMathMode; + document.openEnv(thisDelimiter); + } else if (thisDelimiter.command === "end") { + this._end(thisDelimiter); + } else if (thisDelimiter.command === "(" || thisDelimiter.command === "[") { + this._beginMathMode(thisDelimiter); + } else if (thisDelimiter.command === ")" || thisDelimiter.command === "]") { + this._end(thisDelimiter); + } else if (thisDelimiter.command === "}") { + this._end(thisDelimiter); + } else if (thisDelimiter.command === "right") { + this._end(thisDelimiter); + } else if (thisDelimiter.command === "$" || thisDelimiter.command === "$$") { + this._toggleMathMode(thisDelimiter); } }; this.close = function () { - while (state.length > 0) { - var thisEnv = state.pop(); - if (thisEnv.command === "{") { - ErrorFrom(thisEnv, "unclosed group {", {type:"warning"}); + while (document.getDepth() > 0) { + var thisDelimiter = document.closeEnv(); + if (thisDelimiter.command === "{") { + ErrorFrom(thisDelimiter, "unclosed group {", {type:"warning"}); } else { - ErrorFrom(thisEnv, "unclosed " + getName(thisEnv)); + ErrorFrom(thisDelimiter, "unclosed " + getName(thisDelimiter)); } } var vlen = verbatimRanges.length; @@ -2331,10 +2449,10 @@ var EnvHandler = function (ErrorReporter) { } }; - this.setEnvProps = function (env) { - var name = env.name ; + this.setDelimiterProps = function (delimiter) { + var name = delimiter.name ; if (name && name.match(/^(verbatim|boxedverbatim|lstlisting|minted|Verbatim)$/)) { - env.verbatim = true; + delimiter.verbatim = true; } }; }; @@ -2458,9 +2576,9 @@ var ErrorReporter = function (TokeniseResult) { errors.push(err); }; - this.EnvErrorFrom = function (env, message, options) { + this.EnvErrorFrom = function (delimiter, message, options) { if(!options) { options = {} ; }; - var token = env.token; + var token = delimiter.token; var line = token[0], type = token[1], start = token[2], end = token[3]; var start_col = start - linePosition[line]; var end_col = Infinity; @@ -2481,29 +2599,11 @@ var Parse = function (text) { var Reporter = new ErrorReporter(TokeniseResult); var Environments = InterpretTokens(TokeniseResult, Reporter); Environments.close(); - return Reporter.getErrors(); + return { + errors: Reporter.getErrors(), + contexts: Environments.getDocument().getContexts() + } }; - -(function() { - var disabled = false; - - this.onUpdate = function() { - if (disabled) { return ; }; - - var value = this.doc.getValue(); - var errors = []; - try { - if (value) - errors = Parse(value); - } catch (e) { - disabled = true; - errors = []; - } - this.sender.emit("lint", errors); - }; - -}).call(LatexWorker.prototype); - }); ace.define("ace/lib/es5-shim",["require","exports","module"], function(require, exports, module) {