diff --git a/demo/demo.js b/demo/demo.js index 67ee5c86..896518bf 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -149,7 +149,7 @@ exports.launch = function(env) { // BEGING TESTING var Range = require("ace/range").Range; - docs.js.addFold(new Range(1,0, 2, 999), "foo..."); + docs.js.addFold(new Range(1, 10, 2, 999), "foo..."); window.s = docs.js; window.e = env.editor; setTimeout(function() { diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 55d48473..7a2d0dbc 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1417,7 +1417,7 @@ var EditSession = function(text, mode) { * folded parts such that some parts of the line is still visible. **/ this.isRowFolded = function(docRow) { - return this.$foldData[docRow]; + return !!this.$foldData[docRow]; }; this.getRowLastFold = function(docRow) { diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index 50bf0f5c..68c350cc 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -270,6 +270,8 @@ var Text = function(parentEl) { // don't use setInnerHtml since we are working with an empty DIV lineEl.innerHTML = html.join(""); fragment.appendChild(lineEl); + + row = this.session.getRowFoldEnd(row); } return fragment; }; @@ -293,58 +295,61 @@ var Text = function(parentEl) { "lparen": true }; - this.$renderLine = function(stringBuilder, row, tokens) { - // Nothing to do if the entire line is folded. - // TODO: Remove this, once the folding feature is done. Only for - // developing stuff at the moment. - if (!this.session.isRowVisible(row)) { - throw "Calling renderLine on folded line doesn't make sense?"; + this.$renderToken = function(stringBuilder, screenColumn, token, value) { + var self = this; + var replaceReg = /\t|&|<|( +)|([\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000])|[\u1100-\u115F]|[\u11A3-\u11A7]|[\u11FA-\u11FF]|[\u2329-\u232A]|[\u2E80-\u2E99]|[\u2E9B-\u2EF3]|[\u2F00-\u2FD5]|[\u2FF0-\u2FFB]|[\u3000-\u303E]|[\u3041-\u3096]|[\u3099-\u30FF]|[\u3105-\u312D]|[\u3131-\u318E]|[\u3190-\u31BA]|[\u31C0-\u31E3]|[\u31F0-\u321E]|[\u3220-\u3247]|[\u3250-\u32FE]|[\u3300-\u4DBF]|[\u4E00-\uA48C]|[\uA490-\uA4C6]|[\uA960-\uA97C]|[\uAC00-\uD7A3]|[\uD7B0-\uD7C6]|[\uD7CB-\uD7FB]|[\uF900-\uFAFF]|[\uFE10-\uFE19]|[\uFE30-\uFE52]|[\uFE54-\uFE66]|[\uFE68-\uFE6B]|[\uFF01-\uFF60]|[\uFFE0-\uFFE6]/g; + var replaceFunc = function(c, a, b, tabIdx, idx4) { + if (c.charCodeAt(0) == 32) { + return new Array(c.length+1).join(" "); + } else if (c == "\t") { + var tabSize = self.session. + getScreenTabSize(screenColumn + tabIdx); + screenColumn += tabSize - 1; + return self.$tabStrings[tabSize]; + } else if (c == "&") { + return "&"; + } else if (c == "<") { + return "<"; + } else if (c.match(/[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/)) { + if (self.showInvisibles) { + var space = new Array(c.length+1).join(self.SPACE_CHAR); + return "" + space + ""; + } else { + return " "; + } + } else { + screenColumn += 1; + return "" + c + ""; + } } - var _self = this, + var output = value.replace(replaceReg, replaceFunc); + + if (!this.$textToken[token.type]) { + var classes = "ace_" + token.type.replace(/\./g, " ace_"); + stringBuilder.push("", output, ""); + } + else { + stringBuilder.push(output); + } + return value.length; + } + + this.$renderLineCore = function(stringBuilder, lastRow, tokens, splits) { + var chars = 0, + split = 0, + splitChars, characterWidth = this.config.characterWidth, - screenColumn = 0; + screenColumn = 0, + self = this; function addToken(token, value) { - var output = value - .replace(/\t|&|<|( +)|([\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000])|[\u1100-\u115F]|[\u11A3-\u11A7]|[\u11FA-\u11FF]|[\u2329-\u232A]|[\u2E80-\u2E99]|[\u2E9B-\u2EF3]|[\u2F00-\u2FD5]|[\u2FF0-\u2FFB]|[\u3000-\u303E]|[\u3041-\u3096]|[\u3099-\u30FF]|[\u3105-\u312D]|[\u3131-\u318E]|[\u3190-\u31BA]|[\u31C0-\u31E3]|[\u31F0-\u321E]|[\u3220-\u3247]|[\u3250-\u32FE]|[\u3300-\u4DBF]|[\u4E00-\uA48C]|[\uA490-\uA4C6]|[\uA960-\uA97C]|[\uAC00-\uD7A3]|[\uD7B0-\uD7C6]|[\uD7CB-\uD7FB]|[\uF900-\uFAFF]|[\uFE10-\uFE19]|[\uFE30-\uFE52]|[\uFE54-\uFE66]|[\uFE68-\uFE6B]|[\uFF01-\uFF60]|[\uFFE0-\uFFE6]/g, function(c, a, b, tabIdx, idx4) { - if (c.charCodeAt(0) == 32) { - return new Array(c.length+1).join(" "); - } else if (c == "\t") { - var tabSize = _self.session. - getScreenTabSize(screenColumn + tabIdx); - screenColumn += tabSize - 1; - return _self.$tabStrings[tabSize]; - } else if (c == "&") { - return "&"; - } else if (c == "<") { - return "<"; - } else if (c.match(/[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/)) { - if (this.showInvisibles) { - var space = new Array(c.length+1).join(self.SPACE_CHAR); - return "" + space + ""; - } else { - return " " - } - } else { - screenColumn += 1; - return "" + c + "" - } - }); - screenColumn += value.length; - - if (!_self.$textToken[token.type]) { - var classes = "ace_" + token.type.replace(/\./g, " ace_"); - stringBuilder.push("", output, ""); - } - else { - stringBuilder.push(output); - } + screenColumn += self.$renderToken( + stringBuilder, screenColumn, token, value); } - var splits = this.session.getRowSplitData(row); - var chars = 0, split = 0, splitChars; - if (!splits || splits.length == 0) { splitChars = Number.MAX_VALUE; } else { @@ -383,15 +388,42 @@ var Text = function(parentEl) { }; if (this.showInvisibles) { - if (row !== this.session.getLength() - 1) { + if (lastRow !== this.session.getLength() - 1) { stringBuilder.push("" + this.EOL_CHAR + ""); } else { stringBuilder.push("" + this.EOF_CHAR + ""); } } stringBuilder.push(""); + } + + this.$renderLine = function(stringBuilder, row, tokens) { + // Nothing to do if the entire line is folded. + // TODO: Remove this, once the folding feature is done. Only for + // developing stuff at the moment. + if (!this.session.isRowVisible(row)) { + throw "Calling renderLine on folded line doesn't make sense?"; + } + + // Check if the line to render is folded or not. If not, things are + // simple, otherwise, we need to fake some things... + if (!this.session.isRowFolded(row)) { + var splits = this.session.getRowSplitData(row); + this.$renderLineCore(stringBuilder, row, tokens, splits) + } else { + this.$renderFoldLine(stringBuilder, row, tokens, splits); + } }; + this.$renderFoldLine = function(stringBuilder, row, tokens) { + // TODO: Build a fake tokens array! + // TODO: Build a fake splits array! + var splits + var tokens; + var lastRow; + this.$renderLineCore(stringBuilder, lastRow, tokens, splits); + } + }).call(Text.prototype); exports.Text = Text;