Content of Pretty.java extracted from pretty.jar
/* Program pretty: used to reformat a java program in order to look better 05-11-2005 Version 0.1: initial release 05-11-2006 Version 0.2: minor changes 10-11-2007 Version 0.3: conversion to html now supported Usage: java Pretty [-notabs] [-nocomment] [-strings] [-html] [-help] <filename> [<outfile>] -notabs use blanks instead of tabs -nocomment remove every comment -strings print-out strings -html convert java source to html, colorize java source -help print this help message Requires Java 1.5 javalc6 */ import java.io.*; import parser.*; import java.util.ArrayList; enum State { SOURCE, STRING, COMMENT, SHORT_COMMENT, CHAR } interface callback { void print(String s, State state); void println(String s, State state); } public class Pretty { boolean notabs, nocomment, strings, html; PrintWriter out = null; boolean newline; int column; final String blanks = new blanks().generate(1000); String color; // used only for html final boolean testmode = false; // testmode, normally false private class blanks { String generate(int num) { String result =""; for (int i = 0; i < num; i++) result += " "; return (result); } }; private class HandleSource implements callback { public void print(String s, State state) { StringBuffer str = new StringBuffer(); if (s.length() == 0) return; if ((state == State.SOURCE) && newline) { // source in newline String ss = removeLeadingChars(s); if ((ss.length() > 0) && (ss.charAt(0) == '}')) column--; if (notabs) str.append(blanks.substring(0,column*4)); else for (int i =0; i < column; i++) { str.append("\t"); } str.append(ss); for (int i = 0; i < ss.length(); i++) { if (ss.charAt(i) == '{') column++; if ((i > 0)&&(ss.charAt(i) == '}')) column--; } } else { if (!nocomment) str.append(s); else if (state != State.COMMENT) // comment str.append(s); if (state == State.SOURCE) // source for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '{') column++; if (s.charAt(i) == '}') column--; } } if (html) printHTML(str, state); else out.print(str); newline = false; } public void println(String s, State state) { print(s, state); out.println(); newline = true; } } Pretty (String [] files, boolean notabs, boolean nocomment, boolean strings, boolean html) { this.notabs = notabs; this.nocomment = nocomment; this.strings = strings; this.html = html; java.util.Arrays.sort(Java.keywords); newline = true; column = 0; try { String result; if (files.length == 2) result = files[1]; else if (html) result = files[0]+".html"; else result = files[0]+".new"; LineNumberReader in = new LineNumberReader(new FileReader(files[0])); long zz = System.currentTimeMillis(); out = open(result, files[0]); syntax(in, new HandleSource()); close(out); if (testmode) { System.out.println("Result: "+lazyCompare(new File(files[0]), new File(result))+" Elapsed time (ms): "+(System.currentTimeMillis() - zz)); } else System.out.println("Elapsed time (ms): "+(System.currentTimeMillis() - zz)); } catch (IOException ex) { System.err.println(ex.toString()); if (out != null) out.close(); } } void syntax (LineNumberReader in, callback cb) throws IOException { String s; State state = State.SOURCE; while ((s = in.readLine()) != null) { int marker = 0; main: // for each char in string for (int i = 0; i < s.length(); i++) { switch (state) { case SOURCE : // source if (s.startsWith("//", i)) { cb.print(s.substring(marker, i), state); // source marker = i; state = State.SHORT_COMMENT; // short_comment break main; } if (s.startsWith("/*", i)) { cb.print(s.substring(marker, i), state); // source marker = i; state = State.COMMENT; // comment break; } if (s.charAt(i) == '\"') { cb.print(s.substring(marker, i), state); // source marker = i; state = State.STRING; // string break; } if (s.charAt(i) == '\'') { cb.print(s.substring(marker, i), state); // source marker = i; state = State.CHAR; // char break; } break; case STRING: // string if (s.charAt(i) == '\"') { cb.print(s.substring(marker, i), state); // string if (strings) System.out.println(s.substring(marker, i+1)); marker = i; state = State.SOURCE; // source } if (s.charAt(i) == '\\') i++; // escape, skip break; case COMMENT: // comment if (s.startsWith("*/", i)) { cb.print(s.substring(marker, i+2), state); // comment marker = i+2; state = State.SOURCE; // source } // else if (s.indexOf("*/", i) == -1) break main; break; case SHORT_COMMENT: // short_comment throw new RuntimeException("Assert failed"); case CHAR: // char if (s.charAt(i) == '\'') { cb.print(s.substring(marker, i), State.STRING); // string ??? marker = i; state = State.SOURCE; // source } if (s.charAt(i) == '\\') i++; // escape, skip break; } } // all chars in the current line were analysed switch (state) { case SOURCE : // source cb.println(s.substring(marker), state); // source break; case STRING: // string throw new IOException("Wrong syntax: string not terminated correctly at line "+in.getLineNumber()); case COMMENT: // comment cb.println(s.substring(marker), state); // comment break; case SHORT_COMMENT: // short_comment cb.println(s.substring(marker), State.COMMENT); // comment (even if it is short...) state = State.SOURCE; // source break; case CHAR: // char throw new IOException("Wrong syntax: char not terminated correctly at line "+in.getLineNumber()); } // main while } in.close(); } String removeLeadingChars(String line) { int i=0; while ((i < line.length())&&((line.charAt(i) == ' ')||(line.charAt(i) == '\t'))) i++; return (line.substring(i)); } PrintWriter open(String filename, String source) throws IOException { PrintWriter out = new PrintWriter(new FileWriter(new File(filename))); if (html) { out.println(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<html>"); out.println("<head>"); out.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1252\">"); out.println("<meta name=\"description\" content=\"Programmi Java\">"); out.println("<title>"+encodeHTML(new StringBuffer(source))+"</title>"); out.println("</head>"); out.println("<body><pre><font color=\"#000000\">"); color = "#000000"; // used only for html } return out; } void close(PrintWriter out) { if (html) { out.println("</font></pre></body>"); out.println("</html>"); } out.close(); } boolean testAlfa(char ch) { return ((ch >= 'a')&&(ch <= 'z'))||((ch >= 'A')&&(ch <= 'Z')); } boolean testDigit(char ch) { return ((ch >= '0')&&(ch <= '9')); } void printHTML(StringBuffer str, State state) { String oldcolor = color; switch (state) { case SOURCE : color = "#000000"; break; case COMMENT : color = "#339966"; break; default: color = "#0033CC"; } if (!color.equals(oldcolor)) { out.print("</font><font color=\""+color+"\">"); } if (state == State.SOURCE) { int i = 0; while (i < str.length()) { // skips blank and tabs char ch = str.charAt(i); if (testAlfa(ch)||(ch == '_')||(ch == '$')) { StringBuffer id = new StringBuffer(); do { id.append(ch); i++; if (i >= str.length()) break; ch = str.charAt(i); } while (testAlfa(ch)||(ch == '_')||(ch == '$') || testDigit(ch)); if (java.util.Arrays.binarySearch(Java.keywords, id.toString()) >= 0) out.print("<b>"+encodeHTML(id)+"</b>"); else out.print(encodeHTML(id)); } if (i >= str.length()) break; out.print(encodeHTML(new StringBuffer(str.substring(i,i+1)))); i++; } } else out.print(encodeHTML(str)); } public StringBuffer encodeHTML(StringBuffer s) { StringBuffer out = new StringBuffer(); for(int i=0; i<s.length(); i++) { char c = s.charAt(i); if(c > 127 || c=='"' || c=='<' || c=='>') { out.append("&#"+(int)c+";"); } else if (c=='"') out.append("""); else if (c=='<') out.append("<"); else if (c=='>') out.append(">"); else if (c=='&') out.append("&"); else { out.append(c); } } return out; } public static boolean lazyCompare(File file1, File file2) throws IOException { InputStream bufferedInput1 = new BufferedInputStream(new java.io.FileInputStream(file1)); InputStream bufferedInput2 = new BufferedInputStream(new java.io.FileInputStream(file2)); int ch = bufferedInput1.read(); int ch2 = bufferedInput2.read(); while(true) { while ((-1 != ch)&&(" \t\n\r".indexOf(ch) != -1)) { ch = bufferedInput1.read(); } while ((-1 != ch2)&&(" \t\n\r".indexOf(ch2) != -1)) { ch2 = bufferedInput2.read(); } if (ch == -1) return -1 == ch2; // System.err.println(ch+"<->"+ch2); if( ch != ch2 ) return false; ch = bufferedInput1.read(); ch2 = bufferedInput2.read(); } } //main public static void main(String[] args) throws ParserException { Parser cli = new Parser(); Option notabs = cli.addOption("-notabs", false, null,"use blanks instead of tabs"); Option nocomment = cli.addOption("-nocomment", false, null,"remove every comment"); Option strings = cli.addOption("-strings", false, null,"print-out strings"); Option html = cli.addOption("-html", false, null,"convert java to html"); cli.addOption("-help", false, null,"print this help message"); String [] result = cli.parse(args); if ((result.length > 0)&&(result.length < 3)) { if (new File(result[0]).isDirectory()) System.err.println("Error: "+result[0]+" is a directory!"); else new Pretty(result, cli.hasOption(notabs), cli.hasOption(nocomment), cli.hasOption(strings), cli.hasOption(html)); } else System.err.println("Usage: java Pretty"+cli.getUsage("<filename> [<outfile>]")); } }