From 98b0026207ce0de253a4bedfdbf9b4c489e3fbf2 Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Thu, 13 Sep 2012 16:52:53 -0700 Subject: [PATCH 1/4] Start work on lua fodmode --- lib/ace/mode/folding/lua.js | 75 +++++++++++++++++++++++++++++++++++++ lib/ace/mode/lua.js | 2 + 2 files changed, 77 insertions(+) create mode 100644 lib/ace/mode/folding/lua.js diff --git a/lib/ace/mode/folding/lua.js b/lib/ace/mode/folding/lua.js new file mode 100644 index 00000000..c01f1e9f --- /dev/null +++ b/lib/ace/mode/folding/lua.js @@ -0,0 +1,75 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2012, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var BaseFoldMode = require("./fold_mode").FoldMode; +var Range = require("../../range").Range; + +var FoldMode = exports.FoldMode = function() {}; + +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + this.foldingStartMarker = /\b(function|local\s+function|then|do|repeat)\b|{[ \t]*$|\[\[/; + this.foldingStopMarker = /\bend\b|^\s*}|\]\]/; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var lines = session.doc.getAllLines(row); + var line = lines[row]; + + var re = this.foldingStartMarker.test(line) ? this.foldingStartMarker : this.foldingStopMarker; + + if (this.foldingStartMarker.test(line)) { + for (var i = row + 1, l = session.getLength(); i < l; i++) { + if (re.test(lines[i])) + break; + } + + return new Range(row, line.length, i, 0); + } + + if (this.foldingStopMarker.test(line)) { + for (var i = row - 1; i >= 0; i--) { + line = lines[i]; + if (re.test(line)) + break; + } + + return new Range(i, line.length, row, 0); + } + }; + +}).call(FoldMode.prototype); + +}); diff --git a/lib/ace/mode/lua.js b/lib/ace/mode/lua.js index efb3ffd1..e1a6143a 100644 --- a/lib/ace/mode/lua.js +++ b/lib/ace/mode/lua.js @@ -35,10 +35,12 @@ var oop = require("../lib/oop"); var TextMode = require("./text").Mode; var Tokenizer = require("../tokenizer").Tokenizer; var LuaHighlightRules = require("./lua_highlight_rules").LuaHighlightRules; +var LuaFoldMode = require("./folding/lua").FoldMode; var Range = require("../range").Range; var Mode = function() { this.$tokenizer = new Tokenizer(new LuaHighlightRules().getRules()); + this.foldingRules = new LuaFoldMode(); }; oop.inherits(Mode, TextMode); From 704eae50c1ef78c901053d405263f3acf8d9036a Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 13 Oct 2012 14:53:49 +0400 Subject: [PATCH 2/4] lua folding: do not show foldwidgets for keywords in comments --- lib/ace/mode/folding/lua.js | 39 ++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/lib/ace/mode/folding/lua.js b/lib/ace/mode/folding/lua.js index c01f1e9f..73a6a37c 100644 --- a/lib/ace/mode/folding/lua.js +++ b/lib/ace/mode/folding/lua.js @@ -41,9 +41,42 @@ oop.inherits(FoldMode, BaseFoldMode); (function() { - this.foldingStartMarker = /\b(function|local\s+function|then|do|repeat)\b|{[ \t]*$|\[\[/; - this.foldingStopMarker = /\bend\b|^\s*}|\]\]/; - + this.foldingStartMarker = /\b(function|then|do|repeat)\b|{\s*$|(\[=*\[)/; + this.foldingStopMarker = /\bend\b|^\s*}|\]=*\]/; + + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + var isStart = this.foldingStartMarker.test(line); + var isEnd = this.foldingStopMarker.test(line); + + if (isStart && !isEnd) { + var match = line.match(this.foldingStartMarker); + if (match[1]) { + if (session.getTokenAt(row, match.index + 1).type == "keyword") + return "start"; + } else if (match[2]) { + var type = session.getTokenAt(row + 1, 0).type + if (type == "comment" || type == "string") + return "start"; + } else { + return "start"; + } + } + if (foldStyle != "markbeginend" || !isEnd || isStart && isEnd) + return ""; + + var match = line.match(this.foldingStopMarker); + if (match[0] == "end") { + if (session.getTokenAt(row, match.index + 1).type == "keyword") + return "end"; + } else if (match[0][0] == "]") { + var type = session.getTokenAt(row - 1, 0).type + if (type == "comment" || type == "string") + return "end"; + } else + return "end"; + }; + this.getFoldWidgetRange = function(session, foldStyle, row) { var lines = session.doc.getAllLines(row); var line = lines[row]; From db499d06a9c81a826fcea93182864e7e4ee1c889 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 17 Oct 2012 00:47:41 +0400 Subject: [PATCH 3/4] finish lua folding --- lib/ace/mode/folding/lua.js | 121 ++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 27 deletions(-) diff --git a/lib/ace/mode/folding/lua.js b/lib/ace/mode/folding/lua.js index 73a6a37c..369eed9e 100644 --- a/lib/ace/mode/folding/lua.js +++ b/lib/ace/mode/folding/lua.js @@ -3,7 +3,7 @@ * * Copyright (c) 2012, Ajax.org B.V. * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright @@ -14,7 +14,7 @@ * * Neither the name of Ajax.org B.V. nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -34,6 +34,8 @@ define(function(require, exports, module) { var oop = require("../../lib/oop"); var BaseFoldMode = require("./fold_mode").FoldMode; var Range = require("../../range").Range; +var TokenIterator = require("ace/token_iterator").TokenIterator; + var FoldMode = exports.FoldMode = function() {}; @@ -52,11 +54,11 @@ oop.inherits(FoldMode, BaseFoldMode); if (isStart && !isEnd) { var match = line.match(this.foldingStartMarker); if (match[1]) { - if (session.getTokenAt(row, match.index + 1).type == "keyword") + if (session.getTokenAt(row, match.index + 1).type === "keyword") return "start"; } else if (match[2]) { - var type = session.getTokenAt(row + 1, 0).type - if (type == "comment" || type == "string") + var type = session.bgTokenizer.getState(row) || ""; + if (type.indexOf("comment") != -1 || type.indexOf("string") != -1) return "start"; } else { return "start"; @@ -66,43 +68,108 @@ oop.inherits(FoldMode, BaseFoldMode); return ""; var match = line.match(this.foldingStopMarker); - if (match[0] == "end") { - if (session.getTokenAt(row, match.index + 1).type == "keyword") + if (match[0] === "end") { + if (session.getTokenAt(row, match.index + 1).type === "keyword") return "end"; - } else if (match[0][0] == "]") { - var type = session.getTokenAt(row - 1, 0).type - if (type == "comment" || type == "string") + } else if (match[0][0] === "]") { + var type = session.bgTokenizer.getState(row - 1) || ""; + if (type.indexOf("comment") != -1 || type.indexOf("string") != -1) return "end"; } else return "end"; }; this.getFoldWidgetRange = function(session, foldStyle, row) { - var lines = session.doc.getAllLines(row); - var line = lines[row]; - - var re = this.foldingStartMarker.test(line) ? this.foldingStartMarker : this.foldingStopMarker; + var line = session.doc.getLine(row); + var match = this.foldingStartMarker.exec(line); + if (match) { + if (match[1]) + return this.luaBlock(session, row, match.index + 1); - if (this.foldingStartMarker.test(line)) { - for (var i = row + 1, l = session.getLength(); i < l; i++) { - if (re.test(lines[i])) - break; - } + if (match[2]) + return session.getCommentFoldRange(row, match.index + 1); - return new Range(row, line.length, i, 0); + return this.openingBracketBlock(session, "{", row, match.index); } - if (this.foldingStopMarker.test(line)) { - for (var i = row - 1; i >= 0; i--) { - line = lines[i]; - if (re.test(line)) - break; + var match = this.foldingStopMarker.exec(line); + if (match) { + if (match[0] === "end") { + if (session.getTokenAt(row, match.index + 1).type === "keyword") + return this.luaBlock(session, row, match.index + 1); } - return new Range(i, line.length, row, 0); + if (match[0][0] === "]") + return session.getCommentFoldRange(row, match.index + 1); + + return this.closingBracketBlock(session, "}", row, match.index + match[0].length); } }; - + + this.luaBlock = function(session, row, column) { + var stream = new TokenIterator(session, row, column); + var indentKeywords = { + "function": 1, + "do": 1, + "then": 1, + "elseif": -1, + "else": 0, + "end": -1, + "repeat": 1, + "until": -1, + }; + var voidKeywords = { + "elseif": 1, + "if": 1, + "for": 1 + }; + + var token = stream.getCurrentToken(); + if (!token || token.type != "keyword") + return; + + var val = token.value; + var stack = [val]; + var dir; + if (voidKeywords[val]) { + stack = []; + dir = 1; + } else if (val === "else") { + dir = 1; + } else { + dir = indentKeywords[val]; + } + + if (!dir) + return; + + var startColumn = dir === -1 ? stream.getCurrentTokenColumn() : session.getLine(row).length; + var startRow = row; + + stream.step = dir === -1 ? stream.stepBackward : stream.stepForward; + while(token = stream.step()) { + if (token.type !== "keyword") + continue; + var level = dir * indentKeywords[token.value]; + + if (level > 0) { + stack.unshift(token.value); + } else if (level <= 0) { + stack.shift(); + if (!stack.length) + break; + if (level === 0) + stack.unshift(token.value); + } + } + + var row = stream.getCurrentTokenRow(); + if (dir === -1) + return new Range(row, session.getLine(row).length, startRow, startColumn); + else + return new Range(startRow, startColumn, row, stream.getCurrentTokenColumn()); + }; + }).call(FoldMode.prototype); }); From 5ab20469c0260bbed3f9e0f1920258f4206c7a8f Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 3 Nov 2012 21:52:41 +0400 Subject: [PATCH 4/4] simplify lua folding --- lib/ace/mode/folding/lua.js | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/lib/ace/mode/folding/lua.js b/lib/ace/mode/folding/lua.js index 369eed9e..2aa7d562 100644 --- a/lib/ace/mode/folding/lua.js +++ b/lib/ace/mode/folding/lua.js @@ -53,6 +53,8 @@ oop.inherits(FoldMode, BaseFoldMode); if (isStart && !isEnd) { var match = line.match(this.foldingStartMarker); + if (match[1] == "then" && /\belseif\b/.test(line)) + return; if (match[1]) { if (session.getTokenAt(row, match.index + 1).type === "keyword") return "start"; @@ -113,16 +115,10 @@ oop.inherits(FoldMode, BaseFoldMode); "do": 1, "then": 1, "elseif": -1, - "else": 0, "end": -1, "repeat": 1, "until": -1, }; - var voidKeywords = { - "elseif": 1, - "if": 1, - "for": 1 - }; var token = stream.getCurrentToken(); if (!token || token.type != "keyword") @@ -130,15 +126,7 @@ oop.inherits(FoldMode, BaseFoldMode); var val = token.value; var stack = [val]; - var dir; - if (voidKeywords[val]) { - stack = []; - dir = 1; - } else if (val === "else") { - dir = 1; - } else { - dir = indentKeywords[val]; - } + var dir = indentKeywords[val]; if (!dir) return; @@ -156,7 +144,7 @@ oop.inherits(FoldMode, BaseFoldMode); stack.unshift(token.value); } else if (level <= 0) { stack.shift(); - if (!stack.length) + if (!stack.length && token.value != "elseif") break; if (level === 0) stack.unshift(token.value);