ShowCode

This (somewhat lengthy) document will go through most of the detail of building a particular application using ant. It will also explain the purpose of that application, and a bit about its coding.

the purpose

Often we need to show various sourcecode files or scripts, and would like to have them arranged so we can jump back and forth while perusing them. We may also want some explanation other than just possible comments in the code.

ShowCode produces html files which contain content files arranged so that it is easy to jump back and forth between the listings. The listings themselves are wrapped for display within HTML (it would be "easy" to colorize the listings, but that has not yet been done). There is a table of contents toward the top of the HTML page which allows you to click to go to a particular listing, and a tag with each listing that allows you to go back to the table of contents.

There is also provision for a link to a zip file containing whatever you wish: the ShowCode program does not create the zip file (although that would not be difficult to provide if desired).

This file is in fact produced itself by ShowCode.

This link gives you showcode.jar which you should put in a library somewhere, and this link gives you showcode, which is a shell script you can run that should be edited to point to the jar file.

Using the program

My build file has a distjar task which produces an "executable jar" file which is then run by the script


java -jar /home/doug/lib/showcode.jar $*

To create a file such as the one you are reading you might use a command such as:


showcode -t ShowCode -h ShowCode -w index.html -p preface ShowCode.java build.showcode.xml showcode-bin-manifest.mf

This says make me a file "index.html" (or whatever the -w argument says) with HTML title "ShowCode" (or whatever the -t argument says) and with header "Showcode" (or whatever the -h tag says) beginning with the contents of the file "preface" (or whatever the -p tag says) [which should be HTML markup which can go inside a body tag showing the contents of the remaining parameters on the line.

This is actually done using the class net.dougharris.utility.P which is "The Programmer's Partner" and has facilities for handling command line arguments and other things.

The default for the -w property is in fact "index.html", and the default for -h is the value of the -t property.

ShowCode uses the Java regexp package to wrap the codefiles for HTML inclusion.

Code links

ShowCode.java
build.showcode.xml
showcode-bin-manifest.mf

Listings

ShowCode.java
package net.dougharris.utility;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class ShowCode{
  static StringBuffer b = new StringBuffer();
  static Pattern pamp=Pattern.compile("\\&");
  static Pattern plt=Pattern.compile("\\<");
  static Pattern pgt=Pattern.compile("\\>");
  static P cmdArgs;

  public static void main(String[] args) throws IOException {
    String options = "h_t_p_w_z_";
    String usage = 
      "ShowCode -t Title -h Header -z ZipFile -w HtmlFile codeFile...";
    cmdArgs = P.arseArgs(options, args);

    String htmlTitle        =  cmdArgs.getProperty("-t", "Title");
    String htmlHeader       =  cmdArgs.getProperty("-h", htmlTitle);
    String htmlFileName     = cmdArgs.getProperty("-w", "index.html");
    String zipFileName      =  cmdArgs.getProperty("-z");
    String prefaceFileName  =  cmdArgs.getProperty("-p", "");

    FileWriter o = new FileWriter(htmlFileName);
    args = cmdArgs.getParams();
    // The args is just a list of files,
    // in the order in which they are to be shown.
    // There will be a <dl> and then for each file
    // a <dt> elements with the fileName
    // followed by a dd element which contains the file contents
    // properly wrapped encapsulated within  <pre><code> tags.
    b.append("<html>\n");
    b.append("<head>\n");
    b.append("<title>");
    b.append(htmlTitle);
    b.append(", by doug@mscs.mu.edu");
    b.append("</title>\n");
    b.append
      ("<link type=\"text/css\"
        rel=\"stylesheet\" href=\"/style.css\">");
    b.append("</head>\n");
    b.append("<body>\n");
    b.append("<h3 align=\"center\">");
    b.append(htmlHeader);
    b.append("</h3>\n");
    b.append("<table align=\"center\" width=\"600\">\n");
    if (!prefaceFileName.equals("")){
      b.append("<tr>\n");
      b.append("<td>\n");
      BufferedReader i = new BufferedReader(new FileReader(prefaceFileName));
      String line;
      while(null!=(line=i.readLine())){
        b.append(line);
        b.append("\n");
      }
      b.append("</td>\n");
      b.append("</tr>\n");
    }
    if (!zipFileName.equals("")){
      b.append("<tr>\n");
      b.append("<td>\n");
      b.append("<a href=\""+zipFileName+".zip\">zipped source code</a>");
      b.append("</td>\n");
      b.append("</tr>\n");
    }
    b.append("<tr>\n");
    b.append("<td>\n");
    b.append("<h4><a name=\"top\">Code links</a></h4>\n");
    b.append("<dl>\n");
    for (int j = 0;j<args.length;j++){
      makeFileNameElement(args[j]);
    }
    b.append("</dl>\n");
    b.append("<h4>Listings</h4>");
    b.append("<dl>\n");
    for (int j = 0;j<args.length;j++){
      makeFileCodeElement(args[j]);
    }
    b.append("</dl>\n");
    b.append("</td>\n");
    b.append("</tr>\n");
    b.append("</table>\n");
    b.append("</body>\n");
    b.append("</html>");
    o.write(b.toString());
    o.close();
  }

  public static void makeFileNameElement(String s){
    b.append("<dt><a href=\"#");
    b.append(s);
    b.append("\">");
    b.append(s);
    b.append("</a></dt>\n");
  }

  public static void makeFileCodeElement(String s){
    b.append("<dt><a href=\"#top\" name=\"");
    b.append(s);
    b.append("\">^&nbsp;</a>");
    b.append(s);
    b.append("</dt>\n");
    b.append("<dd>\n");
    b.append("<pre><code>");
    makeFileListing(s);
    b.append("\n</code></pre>\n");
    b.append("</dd>\n");
  }

  public static void makeFileListing(String s){
    try{
      File f = new File(s);
      char[] a = new char[(int)f.length()];
      FileReader i = new FileReader(f);
      i.read(a);
      b.append(editFileListing(new String(a)));
    } catch(FileNotFoundException x){
      System.err.println(x.getClass().getName()+" says "+x.getMessage());
      System.exit(1);
    } catch(IOException x){
      System.err.println(x.getClass().getName()+" says "+x.getMessage());
      System.exit(2);
    }
  }

  public static String editFileListing(String s){
    s = (pamp.matcher(s)).replaceAll("\\&amp;");
    s = (plt.matcher(s)).replaceAll("\\&lt;");
    s = (pgt.matcher(s)).replaceAll("\\&gt;");
    return s;
  }
}

build.showcode.xml
<project name="showcode" basedir = "/home/doug" default="compile">
  <property name = "app.name" value="showcode" />
  <property name = "projectdir" value = "${basedir}/softwarekeptsimple" />
  <property name = "srcdir" value = "${projectdir}/src" />
  <property name = "builddir" value = "${projectdir}/build-${app.name}" />
  <property name = "builddirlib" value = "${builddir}/lib" />
  <property name = "docdir" value = "${builddir}/docs" />
  <property name = "classdir" value = "${builddir}/classes" />
  <property name = "build.compiler" value = "modern" />

  <target name = "init">
    <mkdir dir = "${builddir}" />
    <mkdir dir = "${builddirlib}" />
    <mkdir dir = "${docdir}" />
    <mkdir dir = "${classdir}" />
    <tstamp/>
  </target>

  <target name = "compile" depends = "init">
    <javac destdir = "${classdir}" includeAntRuntime="false">
      <src path="${srcdir}"/>
      <include name="net/dougharris/utility/ShowCode.java"/>
      <include name="net/dougharris/utility/P.java"/>
    </javac>
  </target>

  <target name="clean">
    <delete dir="${builddir}"/>
  </target>

  <target name="docs" depends="compile">
    <mkdir dir="${docdir}/api"/>
      <javadoc
         packagenames="net.dougharris.utility"
	        sourcepath="${srcdir}"
	        destdir="${docdir}/api"
         author="true"
         version="true"
         use="true"
         doctitle="ShowCode"
         windowtitle="ShowCode"
         bottom = "Copyright &#169;
	   2002 Keep It Simple Advice. All Rights Reserved"
      />
   </target>
  <target name="distjar" depends="init,compile">
    <jar jarfile="${builddirlib}/${app.name}.jar"
       manifest="${srcdir}/buildFiles/showcode-bin-manifest.mf"
       basedir="${classdir}"
    />
  </target>

  <target name="srcjar" depends="init,compile">
    <jar jarfile="${builddirlib}/${app.name}.src.jar">
    <fileset dir="${srcdir}">
      <patternset id="sources">
      <include name="net/dougharris/utility/jock.java"/>
      <include name="net/dougharris/utility/P.java"/>
      </patternset>
    </fileset>
    </jar>
  </target>
</project>

showcode-bin-manifest.mf
Manifest-Version: 1.0
Main-Class: net.dougharris.utility.ShowCode