BITESIZED: How do I pretty print source code?

Page last modified Tue Oct 5 15:15:02 2004

Background

I've often run in situations where I'd like to print some source code, and found that just piping the file to lpr leaves you with same output that our forefathers enjoyed ... hardly fitting for modern PostScript laser printers (likely simulated through GhostScript). Thus began my quest to find a way to "pretty-print" source code files.

The tool to use is called enscript, which is designed to convert text files into PostScript. Among it's many options (the man page is 25 pages long!) are a few that will be absolutely perfect for pretty-print source code:

Whoah, that last one almost snuck by and it was a doozie! By calling the states program, enscript can syntax highlight (by default) Ada95, ASM, AWK, C, ChangeLog files, C++, diffs, Delphi, elisp, Fortran, Haskell, HTML, idl, Java, JavaScript, email (!), Makefiles, nroff, ObjC, Pascal, Perl, PostScript, Python, Scheme, shell scripts, SQL, Synopsys, TCL, Verilog, vhdl, Visual Basic, and you can even add syntax recognition rules for virtually any type of file yourself! It's even smart enough to figure out what type of file it is on it's own, which simplifies our job by a big chunk.

In order to create our source code pretty-printer, then, we'll need to create a small script that calls enscript and passes it all the options that we want to use. Let's call it pr2src for "print (in 2 columns) some source code". We'll also need to create a custom header file (a .hdr file, for enscript) that will print the file name (with full path), date and time it was printed, and a page count at the top of every page.

Two pr2src scripts are presented, and a sample .hdr file, called tillman.hdr, is also demonstrated. The output is rather pretty looking, although you might want to tweak the darkness of the gray highlights to match your printer, since my tends to print somewhat lightly.

pr2src (generally goes in /usr/local/bin)

This is the original Perl script to perform the pretty-printing. It calls on enscript to do the actual work.

#!/usr/bin/perl
# Copyright 1999 Tillman Hodgson
# Based on a similar script by Mike MacNeill
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.  If not, write to
# the Free Software Foundation, 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
IN: {
        $fn = shift;
        if (-e "$fn") {
                &PrintMe;
        } else {
                print "You want me to print WHAT? \n";
                exit(1);
        }
}
sub PrintMe {
        system( "/usr/bin/nenscript -E -C -2r -H4 -T4
			--fancy-header=tillman
			--highlight-bar-gray=0.87
			--mark-wrapped-lines=arrow
			-fCourier6.6 -P lp0 $fn" );
}

pr2src (alternate version, thanks to Scott Wunsch)

This alternate version of the pr2src script was developed by Scott Wunsch, fearless leader of the LOSURS. He took a different angle of attack at the problem; while it still calls enscript to do the dirty work, he used a shell script to put things together. One advantage of his approach is that you can pipe the output of a command to this script and it will attempt to print it, rather than having to use the command with a file name as a parameter explicitly.

#!/bin/sh
#   
# Passes documents through nenscript to produce nicely formatted
# PostScript output on the printer.  If no filename is given, it
# reads standard input. It is expected that you want to print to
# the "lp0" queue.  If invoked as "pr2me", it will print two
# pages on one.
#   
# Written by Scott Wunsch, 29 February 2000
# Based on original prme and pr2me scripts by Tillman Hodgson
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.  If not, write to
# the Free Software Foundation, 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
SWITCHES="-E -C -2r -H4 -T4 --fancy-header=tillman \
	--highlight-bar-gray=0.87 \
	--mark-wrapped-lines=arrow-fCourier6.6 -P lp0"
[ `basename $0` = pr2me ] && SWITCHES="$SWITCHES -2r"
if [ -n "$1" ]; then
  if [ -e "$1" ]; then
    SWITCHES="$SWITCHES $1"
  else
    echo "What's a $1?"
    exit
  fi
fi
nenscript $SWITCHES

tillman.hdr (generally goes in /usr/share/enscript)

 % Tillman Hodgson Source Code header
 % Copyright  2000 Tillman Hodgson
 % Author: Tillman Hodgson - tillman@hodgsonhouse.com
 % =-=-=-=-=-=-=-=-=-=-
 % This program is free software; you can redistribute it and/or
 % modify it under the terms of the GNU General Public License as
 % published by the Free Software Foundation; either version 2,
 % or (at your option) any later version.
 % =-=-=-=-=-=-=-=-=-=-
 % This program is distributed in the hope that it will be useful,
 % but WITHOUT ANY WARRANTY; without even the implied warranty of
 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 % GNU General Public License for more details.
 % =-=-=-=-=-=-=-=-=-=-
 % You should have received a copy of the GNU General Public
 % License along with this program; see the file COPYING.  If not,
 % write to the Free Software Foundation, 59 Temple Place - Suite
 % 330, Boston, MA 02111-1307, USA.
 % =-=-=-=-=-=-=-=-=-=-
 % Format: datestr        Printed on %D{%a %b %d, %Y at %l:%M%p}
 % Format: pagestr        $%
 % Format: pagestr2       /$=
 % HeaderHeight: 48
 % Fonts.
/Helvetica-BoldOblique /helvetica-encoded MF
/SmallFont /helvetica-encoded findfont 12 scalefont def
/BigFont /helvetica-encoded findfont 18 scalefont def

/RBox {         % x y w h r -> -
  /r exch def
  /h exch def
  /w exch def
  /y exch def
  /x exch def
  
  x y r add moveto
  x y h add x w add y h add r arcto 4 {pop} repeat
  x w add y h add x w add y r arcto 4 {pop} repeat
  x w add y x y r arcto 4 {pop} repeat
  x y x y h add r arcto 4 {pop} repeat
  closepath
} def

/radius 8 def

/do_header {    % print mp header
  gsave
    .5 setlinewidth

    % header
    d_header_x d_header_y 8 add d_header_w 65 sub 40 radius RBox
    gsave
      .83 setgray fill
    grestore
    stroke
    SmallFont setfont

    datestr dup stringwidth pop d_header_x d_header_w 75 sub add exch sub
    d_header_y 22 add moveto show
    d_header_x 10 add d_header_y 22 add moveto (File: ) show
    fname show

    d_header_x d_header_w add 60 sub d_header_y 8 add 60 40 radius RBox
    stroke

    SmallFont setfont
    (Page) dup stringwidth pop 60 exch sub 2 div 
    d_header_x d_header_w add 60 sub add d_header_y 33 add moveto show
    BigFont setfont
    pagestr dup stringwidth pop 60 exch sub 2 div
    d_header_x d_header_w add 75 sub add d_header_y 13 add moveto show
    SmallFont setfont
    pagestr2 dup stringwidth pop 60 exch sub 2 div 
    d_header_x d_header_w add 40 sub add d_header_y 13 add moveto show

  grestore
} def


Title Image - left

Recent blog entries

Categories:

General (13)
Hardware (2)
MetaNetwork (9)
Organizations (4)
Security (3)
SeekingFire Meta (10)
Unix (2)

Subscribe: RSS/Atom

© 2002-2005 Tillman Hodgson, security consultant.
(Copyright Details)

Hacker glider emblem