# HG changeset patch # User thomas_-_s # Date 1235912006 0 # Node ID b2e7bd0b3996c95ccf5fbb83ba9a8ee429e4cd33 # Parent 0ab5eff393407982e7fa3f5005f35552955f042c Updated to version 1.1.0 of JsDecoder. git-svn-id: svn://svn.code.sf.net/p/universalindent/code/trunk@944 59b1889a-e5ac-428c-b0c7-476e01d41282 diff -r 0ab5eff39340 -r b2e7bd0b3996 indenters/JsDecoder.js --- a/indenters/JsDecoder.js Tue Feb 17 08:43:05 2009 +0000 +++ b/indenters/JsDecoder.js Sun Mar 01 12:53:26 2009 +0000 @@ -2,172 +2,615 @@ * DO NOT REMOVE THIS NOTICE * * PROJECT: JsDecoder - * VERSION: 1.0.2 - * COPYRIGHT: (c) 2004-2006 Cezary Tomczak + * VERSION: 1.1.0 + * COPYRIGHT: (c) 2004-2008 Cezary Tomczak * LINK: http://code.gosu.pl * LICENSE: GPL */ -function JsDecoder() { - this.s = ""; /* encoded string */ +function JsDecoder() +{ + this.s = ''; + this.len = 0; + this.i = 0; - this.len = 0; - - this.code = [""]; + this.lvl = 0; /* indent level */ + this.code = ['']; this.row = 0; - - this.lvl = 0; /* block level */ - - this.lastWord = ""; - this.nextChar = ""; - this.prevChar = ""; - - this.switches = []; /* searching on each { and } */ - - /* DECODE */ - this.decode = function() { - - this.s = this.s.replace(/(\r\n|\r|\n)/g, "\n"); - - this.len = this.s.length; - while (this.i < this.len) { - - var c = this.s.charAt(this.i); - - if (this.len - 1 == this.i) { - this.nextChar = ""; - } else { - this.nextChar = this.s.charAt(this.i + 1); - } - - switch (c) { - - case "\n": this.linefeed(); break; - - case " ": - case "\t": - this.space(); - break; - - case "{": this.blockBracketOn(); break; - case "}": this.blockBracketOff(); break; - - case ":": this.colon(); break; - case ";": this.semicolon(); break; + this.switches = []; - case "(": this.bracketOn(); break; - case ")": this.bracketOff(); break; - case "[": this.squareBracketOn(); break; - case "]": this.squareBracketOff(); break; - - case '"': - case "'": - this.quotation(c); - break; - - case "/": - if ("/" == this.nextChar) { - this.lineComment(); - } else if ("*" == this.nextChar) { - this.comment(); - } else { - this.slash(); - } - break; - - case ",": this.comma(); break; - case ".": this.dot(); break; + this.lastWord = ''; + this.nextChar = ''; + this.prevChar = ''; + this.isAssign = false; - case "~": - case "^": - this.symbol1(c); - break; - - case "-": case "+": case "*": case "%": - case "<": case "=": case ">": case "?": - case ":": case "&": case "|": case "/": - this.symbol2(c); - break; - - case "!": - if ("=" == this.nextChar) { - this.symbol2(c); - } else { - this.symbol1(c); - } - break; - - default: - if (/\w/.test(c)) { this.alphanumeric(c); } - else { this.unknown(c); } - break; - } - if (!/\w/.test(c)) { - if (c != " " && c != "\t") { - this.lastWord = ""; - } - } - this.prevChar = c; + this.decode = function () + { + this.s = this.s.replace(/[\r\n\f]+/g, "\n"); + this.len = this.s.length; + while (this.i < this.len) + { + var c = this.s.charAt(this.i); + this.charInit(); + this.switch_c(c); this.i++; } return this.code.join("\n"); - } + }; + this.switch_c = function(c) + { + switch (c) + { + case "\n": + this.linefeed(); + break; + + case ' ': + case "\t": + this.space(); + break; + + case '{': this.blockBracketOn(); break; + case '}': this.blockBracketOff(); break; + + case ':': this.colon(); break; + case ';': this.semicolon(); break; + + case '(': this.bracketOn(); break; + case ')': this.bracketOff(); break; + case '[': this.squareBracketOn(); break; + case ']': this.squareBracketOff(); break; + + case '"': + case "'": + this.quotation(c); + break; + + case '/': + if ('/' == this.nextChar) { + this.lineComment(); + } else if ('*' == this.nextChar) { + this.comment(); + } else { + this.slash(); + } + break; + + case ',': this.comma(); break; + case '.': this.dot(); break; + + case '~': + case '^': + this.symbol1(c); + break; + + case '-': case '+': case '*': case '%': + case '<': case '=': case '>': case '?': + case ':': case '&': case '|': case '/': + this.symbol2(c); + break; + + case '!': + if ('=' == this.nextChar) { + this.symbol2(c); + } else { + this.symbol1(c); + } + break; - /* WRITE */ - this.write = function(s) { - if (0 == this.code[this.row].length) { - var lvl = ("}" == s ? this.lvl - 1 : this.lvl); - for (var i = 0; i < lvl; i++) { - this.code[this.row] += " "; + default: + if (/\w/.test(c)) { this.alphanumeric(c); } + else { this.unknown(c); } + break; + } + c = this.s.charAt(this.i); + if (!/\w/.test(c)) { + this.lastWord = ''; + } + }; + this.blockBracketOn = function () + { + this.isAssign = false; + var nextNW = this.nextNonWhite(this.i); + if ('}' == nextNW) { + var ss = (this.prevChar == ')' ? ' ' : ''); + this.write(ss+'{'); + this.lvl++; + return; + + } + if (/^\s*switch\s/.test(this.getCurrentLine())) { + this.switches.push(this.lvl); + } + var line = this.getCurrentLine(); + var line_row = this.row; + var re = /(,)\s*(\w+\s*:\s*function\s*\([^\)]*\)\s*)$/; + if (re.test(line)) { + this.replaceLine(this.code[line_row].replace(re, '$1')); + this.writeLine(); + var match = re.exec(line); + this.write(match[2]); + } + + /* example: return { + title: 'Jack Slocum', + iconCls: 'user'} + After return bracket cannot be on another line + */ + if (/^\s*return\s*/.test(this.code[this.row])) { + if (/^\s*return\s+\w+/.test(this.code[this.row])) { + this.writeLine(); + } else if (this.prevChar != ' ') { + this.write(' '); } - this.code[this.row] += s; + this.write('{'); + this.writeLine(); + this.lvl++; + return; + } + + if (/function\s*/.test(this.code[this.row]) || this.isBlockBig()) { + this.writeLine(); } else { - this.code[this.row] += s; + if (this.prevChar != ' ' && this.prevChar != "\n" && this.prevChar != '(') { + /* && this.prevChar != '(' && this.prevChar != '[' */ + this.write(' '); + } + } + this.write('{'); + this.lvl++; + if ('{' != nextNW) { + this.writeLine(); } - } - this.removePrevChar = function() + }; + this.isBlockBig = function() + { + var i = this.i + 1; + var count = 0; + var opened = 0; + var closed = 0; + while (i < this.len - 1) + { + i++; + var c = this.s.charAt(i); + if (/\s/.test(c)) { + continue; + } + if ('}' == c && opened == closed) { + break; + } + if ('{' == c) { opened++; } + if ('}' == c) { closed++; } + count++; + if (count > 80) { + return true; + } + } + return (count > 80); + }; + this.blockBracketOff = function () { - if (this.code[this.row].length) { - this.code[this.row].length = this.code[this.row].length-1; + var nextNW = this.nextNonWhite(this.i); + var prevNW = this.prevNonWhite(this.i); + var line = this.getCurrentLine(); + + if (prevNW != '{') + { + if (line.length && nextNW != ';' && nextNW != '}' && nextNW != ')' && nextNW != ',') { + //this.semicolon(); + this.writeLine(); + } else if (line.length && prevNW != ';' && nextNW == '}' && this.isAssign) { + this.semicolon(); + } else if (line.length && this.isAssign && prevNW != ';') { + this.semicolon(); + } else if (line.length && prevNW != ';') { + if (/^\s*(else)?\s*return[\s(]+/i.test(line)) { + this.semicolon(); + } else { + this.writeLine(); + } + } + } + this.write('}'); + + if (',' == nextNW) { + this.write(','); + this.goNextNonWhite(); + } + var next3 = this.nextManyNW(3); + if (next3 == '(),') { + this.write('(),'); + this.goNextManyNW('(),'); + this.writeLine(); } - } + else if (next3 == '();') { + this.write('();'); + this.goNextManyNW('();'); + this.writeLine(); + } + else if (next3 == '():') { + this.write('()'); + this.goNextManyNW('()'); + this.write(' : '); + this.goNextNonWhite(); + } + else + { + if ('{' == prevNW) { + if (',' == nextNW && this.getCurrentLine().length < 80) { + this.write(' '); + } else { + if (this.nextWord() || '}' == nextNW) { + this.writeLine(); + } + } + } else { + if (')' != nextNW && ']' != nextNW) { + if (',' == nextNW && /^[\s\w,]+\)/.test(this.s.substr(this.i, 20))) { + this.write(' '); + } else { + this.writeLine(); + } + } + } + } + this.lvl--; - /* WRITELINE */ - this.writeLine = function() { - this.code.push(""); - this.row++; - } + if (this.switches.length && this.switches[this.switches.length - 1] == this.lvl) + { + var row = this.row - 1; + var spaces1 = str_repeat(' ', this.lvl * 4); + var spaces2 = str_repeat(' ', (this.lvl + 1) * 4); + var sw1 = new RegExp('^'+spaces1+'(switch\\s|{)'); + var sw2 = new RegExp('^'+spaces2+'(case|default)[\\s:]'); + var sw3 = new RegExp('^'+spaces2+'[^\\s]'); + while (row > 0) { + row--; + if (sw1.test(this.code[row])) { + break; + } + if (sw2.test(this.code[row])) { + continue; + } + this.replaceLine(' ' + this.code[row], row); + /* + if (sw3.test(this.code[row])) { + this.replaceLine(' ' + this.code[row], row); + } + */ + } + this.switches.pop(); + } + + // fix missing brackets for sub blocks + + if (this.sub) { + return; + } + + var re1 = /^(\s*else\s*if)\s*\(/; + var re2 = /^(\s*else)\s+[^{]+/; - /* WRITETAB */ - this.writeTab = function() { - this.write(" "); - } + var part = this.s.substr(this.i+1, 100); + + if (re1.test(part)) { + this.i += re1.exec(part)[1].length; + this.write('else if'); + this.lastWord = 'if'; + //debug(this.getCurrentLine(), 're1'); + this.fixSub('else if'); + //debug(this.getCurrentLine(), 're1 after'); + } else if (re2.test(part)) { + this.i += re2.exec(part)[1].length; + this.write('else'); + this.lastWord = 'else'; + //debug(this.getCurrentLine(), 're2'); + this.fixSub('else'); + //debug(this.getCurrentLine(), 're2 after'); + } + }; + this.bracketOn = function () + { + if (this.isKeyword() && this.prevChar != ' ' && this.prevChar != "\n") { + this.write(' ('); + } else { + this.write('('); + } + }; + this.bracketOff = function () + { + this.write(')'); + /* + if (/\w/.test(this.nextNonWhite(this.i))) { + this.semicolon(); + } + */ + if (this.sub) { + return; + } + var re = new RegExp('^\\s*(if|for|while|do)\\s*\\([^{}]+\\)$', 'i'); + var line = this.getCurrentLine(); + if (re.test(line)) { + var c = this.nextNonWhite(this.i); + if ('{' != c && ';' != c && ')' != c) { + var opened = 0; + var closed = 0; + var foundFirst = false; + var semicolon = false; + var fix = false; + for (var k = 0; k < line.length; k++) { + if (line.charAt(k) == '(') { + foundFirst = true; + opened++; + } + if (line.charAt(k) == ')') { + closed++; + if (foundFirst && opened == closed) { + if (k == line.length - 1) { + fix = true; + } else { + break; + } + } + } + } + if (fix) { + //alert(this.s.substr(this.i)); + //throw 'asdas'; + //alert(line); + this.fixSub(re.exec(line)[1]); + /* + this.writeLine(); + this.lvl2++; + var indent = ''; + for (var j = 0; j < this.lvl2; j++) { + indent += ' '; + } + this.write(indent); + */ + } + } + } + }; + this.sub = false; + + this.orig_i = null; + this.orig_lvl = null; + this.orig_code = null; + this.orig_row = null; + this.orig_switches = null; - /* GETCURRENTLINE */ - this.getCurrentLine = function() { - return this.code[this.row]; - } + this.restoreOrig = function (omit_i) + { + this.sub = false; + + if (!omit_i) { this.i = this.orig_i; } + this.lvl = this.orig_lvl; + this.code = this.orig_code; + this.row = this.orig_row; + this.switches = this.orig_switches; + + this.prevCharInit(); + + this.lastWord = ''; + this.charInit(); + this.isAssign = false; + }; + this.combineSub = function () + { + //debug(this.orig_code, 'orig_code'); + for (i = 0; i < this.code.length; i++) { + var line = this.orig_code[this.orig_row]; + if (0 == i && line.length) { + if (line.substr(line.length-1, 1) != ' ') { + this.orig_code[this.orig_row] += ' '; + } + this.orig_code[this.orig_row] += this.code[i].trim(); + } else { + this.orig_code[this.orig_row+i] = this.code[i]; + } + } + //debug(this.code, 'sub_code'); + //debug(this.orig_code, 'code'); + }; + this.fixSub = function (keyword) + { + // repair missing {}: for, if, while, do, else, else if + + if (this.sub) { + return; + } + + if ('{' == this.nextNonWhite(this.i)) { + return; + } + + var firstWord = this.nextWord(); + + //debug(this.code, 'fixSub('+keyword+') start'); + + this.orig_i = this.i; + this.orig_lvl = this.lvl; + this.orig_code = this.code; + this.orig_row = this.row; + this.orig_switches = this.switches; + + this.sub = true; + this.code = ['']; + this.prevChar = ''; + this.row = 0; + this.switches = []; + this.isAssign = false; + + this.i++; + + var b1 = 0; + var b2 = 0; + var b3 = 0; - /* ISKEYWORD - * Check if this.lastWord is a keyword */ - this.isKeyword = function() { - return this.lastWord && this.keywords.indexOf(this.lastWord) != -1; - } + if ('else if' == keyword) { + var first_b2_closed = false; + } + + var found = false; + + /* + try catch + switch + while do + if else else else... - /* LINEFEED */ - this.linefeed = function() { - } + todo: nestings + if () + if () + if () + for () + if () asd(); + else + asd(); + else + if () + try { + } catch {} + else + if () + */ + var b1_lastWord = false; + var b2_lastWord = false; - /* SPACE - * Example: "var asd" (2 spaces) does not change - * Example: for (var a in b) {} - * Example: return new test(); */ - this.space = function() { + while (!found && this.i < this.len) + { + var c = this.s.charAt(this.i); + this.charInit(); + switch (c) + { + case '{': b1++; break; + case '}': + b1--; + // case: for(){if (!c.m(g))c.g(f, n[t] + g + ';')} + if (0 == b1 && 0 == b2 && 0 == b3 && this.lvl-1 == this.orig_lvl) + { + var nextWord = this.nextWord(); + if ('switch' == firstWord) { + found = true; + break; + } + if ('try' == firstWord && 'catch' == b1_lastWord) { + found = true; + break; + } + if ('while' == firstWord && 'do' == b1_lastWord) { + found = true; + break; + } + if ('if' == firstWord) { + // todo + } + if ('if' == keyword && 'else' == nextWord && 'if' != firstWord) { + found = true; + break; + } + b1_lastWord = nextWord; + } + break; + case '(': b2++; break; + case ')': + b2--; + if ('else if' == keyword && 0 == b2 && !first_b2_closed) { + if (this.nextNonWhite(this.i) == '{') { + this.write(c); + this.combineSub(); + this.restoreOrig(true); + //debug(this.code, 'fixSub('+keyword+') b2 return'); + //debug(this.s.charAt(this.i), ' b2 current char'); + return; + } + // do not restore orig i + this.write(c); + this.combineSub(); + this.restoreOrig(true); + this.fixSub('if'); + //debug(this.code, 'fixSub('+keyword+') b2 return'); + return; + } + break; + case '[': b3++; break; + case ']': b3--; break; + case ';': + //debug(this.getCurrentLine(), 'semicolon'); + //debug([b1, b2, b3]); + if (0 == b1 && 0 == b2 && 0 == b3 && this.lvl == this.orig_lvl && 'if' != firstWord) { + found = true; + } + break; + } + if (-1 == b1 && b2 == 0 && b3 == 0 && this.prevNonWhite(this.i) != '}') { + this.write(';'); + this.i--; + found = true; + } else if (b1 < 0 || b2 < 0 || b3 < 0) { + found = false; + break; + } else { + this.switch_c(c); + } + this.i++; + } + this.i--; + + if (found) + { + /* + var re = /^\s*(else\s+[\s\S]*)$/; + if ('if' == keyword && re.test(this.getCurrentLine())) { + this.i = this.i - re.exec(this.getCurrentLine())[1].length; + this.code[this.row] = ''; + } + */ + this.s = this.s.substr(0, this.orig_i+1) + '{' + this.code.join("\n") + '}' + this.s.substr(this.i+1); + this.len = this.s.length; + } + + //debug("{\n" + this.code.join("\n") + '}', 'fixSub('+keyword+') result'); + //debug(found, 'found'); + + this.restoreOrig(false); + }; + this.squareBracketOn = function () + { + this.checkKeyword(); + this.write('['); + }; + this.squareBracketOff = function () + { + this.write(']'); + }; + this.isKeyword = function () + { + // Check if this.lastWord is a keyword + return this.lastWord.length && this.keywords.indexOf(this.lastWord) != -1; + }; + this.linefeed = function () {}; + this.space = function () + { + if (!this.prevChar.length) { + return; + } + if (' ' == this.prevChar || "\n" == this.prevChar) { + return; + } + if ('}' == this.prevChar && ']' == this.nextChar) { + //return; + } + this.write(' '); + return; + + /* if (this.isKeyword()) { - this.write(" "); - this.lastWord = ""; + this.write(' '); + this.lastWord = ''; } else { - var multi = ["in", "new"]; + var multi = ['in', 'new']; for (var i = 0; i < multi.length; i++) { var isKeywordNext = true; for (var j = 0; j < multi[i].length; j++) { @@ -177,141 +620,177 @@ } } if (isKeywordNext) { - this.write(" "); - this.lastWord = ""; + this.write(' '); + this.lastWord = ''; + break; + } + } + } + */ + }; + this.checkKeyword = function () + { + if (this.isKeyword() && this.prevChar != ' ' && this.prevChar != "\n") { + this.write(' '); + } + }; + this.nextWord = function () + { + var i = this.i; + var word = ''; + while (i < this.len - 1) + { + i++; + var c = this.s.charAt(i); + if (word.length) { + if (/\s/.test(c)) { + break; + } else if (/\w/.test(c)) { + word += c; + } else { + break; + } + } else { + if (/\s/.test(c)) { + continue; + } else if (/\w/.test(c)) { + word += c; + } else { break; } } } - } - - /* BLOCKBRACKETON - * search for switch */ - this.blockBracketOn = function() { - if (/^\s*switch\s/.test(this.getCurrentLine())) { - this.switches.push(this.lvl); + if (word.length) { + return word; } - var currentLine = this.getCurrentLine(); - if (currentLine.length) { - var lastChar = currentLine[currentLine.length - 1]; - if (lastChar != " " && lastChar != "\t") { - this.write(" {"); - } else { - this.write("{"); - } - } else { - this.write("{"); - } - this.writeLine(); - this.lvl++; - } - this.lastChar = function() + return false; + }; + this.nextManyNW = function(many) { - var line = this.getCurrentLine(); - if (line.length) return line[line-1]; - else return "notfound"; - } - - /* BLOCKBRACKETOFF - * search for switch */ - this.blockBracketOff = function() - { - if (this.getCurrentLine().length && this.lastChar != ';') { - this.semicolon(); + var ret = ''; + var i = this.i; + while (i < this.len - 1) + { + i++; + var c = this.s.charAt(i); + if (!/^\s+$/.test(c)) { + ret += c; + if (ret.length == many) { + return ret; + } + } } - this.write("}"); - this.writeLine(); - this.lvl--; - if (this.switches.length && this.switches[this.switches.length - 1] == this.lvl) { - var row = this.row - 1; - var spaces = (this.lvl + 1) * 4; - var caseRegexp = new RegExp("^\\s{"+spaces+"}case\\s"); - while (row > 0) { - row--; - if (/^\s*switch\s/.test(this.code[row])) { - break; + return false; + } + this.goNextManyNW = function (cc) + { + var ret = ''; + var i = this.i; + while (i < this.len - 1) + { + i++; + var c = this.s.charAt(i); + if (!/^\s+$/.test(c)) { + ret += c; + if (ret == cc) { + this.i = i; + this.charInit(); + return true; } - if (!caseRegexp.test(this.code[row])) { - this.code[row] = " " + this.code[row]; + if (ret.length >= cc.length) { + return false; } } - this.switches.pop(); + } + return false; + }; + this.nextNonWhite = function (i) + { + while (i < this.len - 1) + { + i++; + var c = this.s.charAt(i); + if (!/^\s+$/.test(c)) { + return c; + } + } + return false; + }; + this.prevNonWhite = function (i) + { + while (i > 0) + { + i--; + var c = this.s.charAt(i); + if (!/^\s+$/.test(c)) { + return c; + } } - } - - /* COLON - * case 6: - * expr ? stat : stat */ - this.colon = function() { - if (/^\s*case\s/.test(this.getCurrentLine())) { - this.write(":"); + return false; + }; + this.goNextNonWhite = function () + { + // you need to write() this nonWhite char when calling this func + var i = this.i; + while (i < this.len - 1) + { + i++; + var c = this.s.charAt(i); + if (!/^\s+$/.test(c)) { + this.i = i; + this.charInit(); + return true; + } + } + return false; + }; + this.colon = function () + { + //alert(this.getCurrentLine()); + /* case 6: expr ? stat : stat */ + var line = this.getCurrentLine(); + if (/^\s*case\s/.test(line) || /^\s*default$/.test(line)) { + this.write(':'); this.writeLine(); } else { - this.symbol2(":"); + this.symbol2(':'); } - } - - this.isStart = function() + }; + this.isStart = function () { - return this.getCurrentLine().length == 0; - } - this.backLine = function() + return this.getCurrentLine().length === 0; + }; + this.backLine = function () { if (!this.isStart) { - throw "backLine() may be called only at the start of the line"; - return; + throw 'backLine() may be called only at the start of the line'; } this.code.length = this.code.length-1; this.row--; - } - - /* SEMICOLON - * for statement: for (i = 1; i < len; i++) */ - this.semicolon = function() + }; + this.semicolon = function () { + /* for statement: for (i = 1; i < len; i++) */ + this.isAssign = false; if (this.isStart()) { this.backLine(); } - this.write(";"); + this.write(';'); if (/^\s*for\s/.test(this.getCurrentLine())) { - this.write(" "); + this.write(' '); } else { this.writeLine(); } - } - - /* BRACKETON */ - this.bracketOn = function() { - if (this.isKeyword() && this.prevChar != " " && this.prevChar != "\t") { - this.write(" ("); - } else { - this.write("("); - } - } - - /* BRACKETOFF */ - this.bracketOff = function() { - this.write(")"); - } - - /* SQUAREBRACKETON */ - this.squareBracketOn = function() { - this.write("["); - } - - /* SQUARE BRACKETOFF */ - this.squareBracketOff = function() { - this.write("]"); - } - - /* QUOTATION */ - this.quotation = function(quotation) { + }; + this.quotation = function (quotation) + { + this.checkKeyword(); var escaped = false; this.write(quotation); while (this.i < this.len - 1) { this.i++; var c = this.s.charAt(this.i); - if ("\\" == c) { + if ('\\' == c) { escaped = (escaped ? false : true); } this.write(c); @@ -320,15 +799,16 @@ break; } } - if ("\\" != c) { + if ('\\' != c) { escaped = false; } } - } - - /* LINECOMMENT */ - this.lineComment = function() { - this.write("//"); + //debug(this.getCurrentLine(), 'quotation'); + //debug(this.s.charAt(this.i), 'char'); + }; + this.lineComment = function () + { + this.write('//'); this.i++; while (this.i < this.len - 1) { this.i++; @@ -339,163 +819,280 @@ } this.write(c); } - } - - /* COMMENT - * multilines */ - this.comment = function() { - this.write("/*"); + }; + this.comment = function () + { + this.write('/*'); this.i++; - var c = ""; - var prevC = ""; - while (this.i < this.len - 1) { + var c = ''; + var prevC = ''; + while (this.i < this.len - 1) + { this.i++; prevC = c; c = this.s.charAt(this.i); - if (" " == c || "\t" == c || "\n" == c) { - if (" " == c) { - if (this.getCurrentLine()) { - this.write(" "); + if (' ' == c || "\t" == c || "\n" == c) { + if (' ' == c) { + if (this.getCurrentLine().length > 100) { + this.writeLine(); + } else { + this.write(' ', true); } } else if ("\t" == c) { - if (this.getCurrentLine()) { - this.writeTab(); - } + this.write(' ', true); } else if ("\n" == c) { this.writeLine(); } } else { - this.write(c); + this.write(c, true); } - if ("/" == c && "*" == prevC) { + if ('/' == c && '*' == prevC) { break; } } this.writeLine(); - } - - /* SLASH - * divisor /= or *\/ (4/5 , a/5) - * regexp /\w/ (//.test() , var asd = /some/;) */ - this.slash = function() + }; + this.slash = function () { - var a = (this.lastWord); - var b = ("*" == this.prevChar); + /* + divisor /= or *\/ (4/5 , a/5) + regexp /\w/ (//.test() , var asd = /some/;) + asd /= 5; + bbb = * / (4/5) + asd =( a/5); + regexp = /\w/; + /a/.test(); + var asd = /some/; + obj = { sasd : /pattern/ig } + */ + var a_i = this.i - 1; + var a_c = this.s.charAt(a_i); + for (a_i = this.i - 1; a_i >= 0; a_i--) { + var c2 = this.s.charAt(a_i); + if (' ' == c2 || '\t' == c2) { + continue; + } + a_c = this.s.charAt(a_i); + break; + } + var a = /^\w+$/.test(a_c) || ']' == a_c || ')' == a_c; + var b = ('*' == this.prevChar); if (a || b) { if (a) { - if ("=" == this.nextChar) { - this.write(" /"); + if ('=' == this.nextChar) { + var ss = this.prevChar == ' ' ? '' : ' '; + this.write(ss+'/'); } else { - this.write(" / "); + this.write(' / '); } } else if (b) { - this.write("/ "); + this.write('/ '); } } else if (')' == this.prevChar) { this.write(' / '); } else { - if ("=" == this.prevChar) { - this.write(" /"); + var ret = ''; + if ('=' == this.prevChar || ':' == this.prevChar) { + ret += ' /'; } else { - this.write("/"); + ret += '/'; } var escaped = false; while (this.i < this.len - 1) { this.i++; var c = this.s.charAt(this.i); - if ("\\" == c) { + if ('\\' == c) { escaped = (escaped ? false : true); } - this.write(c); - if ("/" == c) { + ret += c; + if ('/' == c) { if (!escaped) { break; } } - if ("\\" != c) { + if ('\\' != c) { escaped = false; } } + this.write(ret); } - } - - /* COMMA - * function arguments seperator - * array values seperator - * object values seperator - * todo: col > 80 this.writeLine() ? */ - this.comma = function() { - this.write(", "); - } - - /* DOT - * method calling */ - this.dot = function() { - this.write("."); - } - - /* SYMBOL 1 - * See: this.symbols1 */ - this.symbol1 = function(c) { - this.write(c); - } - - /* SYMBOL 2 - * ++ , -- - * See: this.symbols2 */ - this.symbol2 = function(c) { - if ("+" == c || "-" == c) { + }; + this.comma = function () + { + /* + * function arguments seperator + * array values seperator + * object values seperator + */ + this.write(', '); + var line = this.getCurrentLine(); + if (line.replace(' ', '').length > 100) { + this.writeLine(); + } + }; + this.dot = function () + { + this.write('.'); + }; + this.symbol1 = function (c) + { + if ('=' == this.prevChar && '!' == c) { + this.write(' '+c); + } else { + this.write(c); + } + }; + this.symbol2 = function (c) + { + // && !p + // === + if ('+' == c || '-' == c) { if (c == this.nextChar || c == this.prevChar) { this.write(c); return; } } + var ss = (this.prevChar == ' ' ? '' : ' '); + var ss2 = ' '; + if ('(' == this.prevChar) { + ss = ''; + ss2 = ''; + } + if ('-' == c && ('>' == this.prevChar || '>' == this.prevChar)) { + this.write(' '+c); + return; + } if (this.symbols2.indexOf(this.prevChar) != -1) { if (this.symbols2.indexOf(this.nextChar) != -1) { - this.write(c); + this.write(c + (this.nextChar == '!' ? ' ' : '')); } else { - this.write(c + " "); + this.write(c + ss2); } } else { if (this.symbols2.indexOf(this.nextChar) != -1) { - this.write(" " + c); + this.write(ss + c); } else { - this.write(" " + c + " "); + this.write(ss + c + ss2); } } - } - - /* ALPHANUMERIC - * /[a-zA-Z0-9_]/ == /\w/ */ - this.alphanumeric = function(c) { + if ('=' == c && /^[\w\]]$/.test(this.prevNonWhite(this.i)) && /^[\w\'\"\[]$/.test(this.nextNonWhite(this.i))) { + this.isAssign = true; + } + }; + this.alphanumeric = function (c) + { + /* /[a-zA-Z0-9_]/ == /\w/ */ if (this.lastWord) { this.lastWord += c; } else { this.lastWord = c; } + if (')' == this.prevChar) { + c = ' '+c; + } this.write(c); - } - - /* UNKNOWN */ - this.unknown = function(c) { - //throw "Unknown char: '"+c+"' , this.i = " + this.i; + }; + this.unknown = function (c) + { + //throw 'Unknown char: "'+c+'" , this.i = ' + this.i; this.write(c); - } + }; - this.symbols1 = "~!^"; - this.symbols2 = "-+*%<=>?:&|/!"; + this.charInit = function () + { + /* + if (this.i > 0) { + //this.prevChar = this.s.charAt(this.i - 1); + var line = this.code[this.row]; + if (line.length) { + this.prevChar = line.substr(line.length-1, 1); + } else { + this.prevChar = ''; + } + } else { + this.prevChar = ''; + } + */ + if (this.len - 1 === this.i) { + this.nextChar = ''; + } else { + this.nextChar = this.s.charAt(this.i + 1); + } + }; + this.write = function (s, isComment) + { + if (isComment) { + if (!/\s/.test(s)) { + if (this.code[this.row].length < this.lvl * 4) { + this.code[this.row] += str_repeat(' ', this.lvl * 4 - this.code[this.row].length); + } + } + this.code[this.row] += s; + } else { + if (0 === this.code[this.row].length) { + var lvl = ('}' == s ? this.lvl - 1 : this.lvl); + for (var i = 0; i < lvl; i++) { + this.code[this.row] += ' '; + } + this.code[this.row] += s; + } else { + this.code[this.row] += s; + } + } + this.prevCharInit(); + }; + this.writeLine = function () + { + this.code.push(''); + this.row++; + this.prevChar = "\n"; + }; + this.replaceLine = function (line, row) + { + if ('undefined' == typeof row) { + row = false; + } + if (row !== false) { + if (!/^\d+$/.test(row) || row < 0 || row > this.row) { + throw 'replaceLine() failed: invalid row='+row; + } + } + if (row !== false) { + this.code[row] = line; + } else { + this.code[this.row] = line; + } + if (row === false || row == this.row) { + this.prevCharInit(); + } + }; + this.prevCharInit = function () + { + this.prevChar = this.code[this.row].charAt(this.code[this.row].length - 1); + }; + this.writeTab = function () + { + this.write(' '); + this.prevChar = ' '; + }; + this.getCurrentLine = function () + { + return this.code[this.row]; + }; - this.keywords = ["abstract", "boolean", "break", "byte", "case", "catch", "char", "class", - "const", "continue", "default", "delete", "do", "double", "else", "extends", "false", - "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", - "in", "instanceof", "int", "interface", "long", "native", "new", "null", "package", - "private", "protected", "public", "return", "short", "static", "super", "switch", - "synchronized", "this", "throw", "throws", "transient", "true", "try", "typeof", "var", - "void", "while", "with"]; + this.symbols1 = '~!^'; + this.symbols2 = '-+*%<=>?:&|/!'; + this.keywords = ['abstract', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class', + 'const', 'continue', 'default', 'delete', 'do', 'double', 'else', 'extends', 'false', + 'final', 'finally', 'float', 'for', 'function', 'goto', 'if', 'implements', 'import', + 'in', 'instanceof', 'int', 'interface', 'long', 'native', 'new', 'null', 'package', + 'private', 'protected', 'public', 'return', 'short', 'static', 'super', 'switch', + 'synchronized', 'this', 'throw', 'throws', 'transient', 'true', 'try', 'typeof', 'var', + 'void', 'while', 'with']; } -/* Finds the index of the first occurrence of item in the array, or -1 if not found */ -if (typeof Array.prototype.indexOf == "undefined") { +if (typeof Array.prototype.indexOf == 'undefined') { + /* Finds the index of the first occurence of item in the array, or -1 if not found */ Array.prototype.indexOf = function(item) { for (var i = 0; i < this.length; i++) { if ((typeof this[i] == typeof item) && (this[i] == item)) { @@ -503,9 +1100,74 @@ } } return -1; + }; +} +if (!String.prototype.trim) { + String.prototype.trim = function() { + return this.replace(/^\s*|\s*$/g, ''); + }; +} + +function str_repeat(str, repeat) +{ + ret = ''; + for (var i = 0; i < repeat; i++) { + ret += str; } + return ret; } +var debug_w; +function debug (arr, name) +{ + if (!debug_w) + { + var width = 600; + var height = 600; + var x = (screen.width/2-width/2); + var y = (screen.height/2-height/2); + debug_w = window.open('', '', 'scrollbars=yes,resizable=yes,width='+width+',height='+height+',screenX='+(x)+',screenY='+y+',left='+x+',top='+y); + debug_w.document.open(); + debug_w.document.write('

Debug

'); + debug_w.document.close(); + } + var ret = ''; + if ('undefined' !== typeof name && name.length) { + ret = '

'+name+'

'+"\n"; + } + if ('object' === typeof arr) { + for (var i = 0; i < arr.length; i++) { + ret += '['+i+'] => '+arr[i]+"\n"; + } + } else if ('string' == typeof arr) { + ret += arr; + } else { + try { ret += arr.toString(); } catch (e) {} + ret += ' ('+typeof arr+')'; + } + debug_w.document.body.innerHTML += '
'+ret+'
'; +} + + + +/* ******************************************************* + The following code lines are added to be able + to use JsDecoder with UniversalIndentGUI. + + For each new JsDecoder version they need to be added! + ******************************************************* */ +if (typeof String.prototype.substr == 'undefined') { + /* The substr() method extracts a specified number of characters in a string, from a start index. */ + String.prototype.substr = function(start,length) { + if (typeof length == 'undefined') + length = this.length - start; + + if ( start < 0 ) + return this.substring(this.length+start, this.length); + else + return this.substring(start, start + length); + }; +} var jsdecoder = new JsDecoder(); var formattedCode; diff -r 0ab5eff39340 -r b2e7bd0b3996 indenters/uigui_jsdecoder.ini --- a/indenters/uigui_jsdecoder.ini Tue Feb 17 08:43:05 2009 +0000 +++ b/indenters/uigui_jsdecoder.ini Sun Mar 01 12:53:26 2009 +0000 @@ -14,4 +14,4 @@ showHelpParameter= stringparaminquotes= useCfgFileParameter= -version=1.0.2 +version=1.1.0