aas@boeygen.nr.no (Gisle Aas) (03/01/90)
This posting includes a perl script which produces a "map" of the
directory tree in PostScript. Pipe the output from this script to
your favourite PostScript printer (or previewer). Enjoy!
------Cut here-------
#!/usr/bin/perl -P
;# NAME
;# pstree(1) - produce directory map in PostScript
;#
;# SYNOPSIS
;# pstree [-f] [dirname]
;#
;# DESCRIPTION
;# The output from this program is a PostScript program that will
;# produce a "map" of the directory tree from the current directory
;# and down. If a dirname is given the directory map from the given
;# directory and down is produced. The page size is assumed to be A4.
;#
;# OPTIONS
;# -f Include ordinary files in the map. Without this flag only
;# the overall directory structure is shown.
;#
;# SEE ALSO
;# ls(1), perl(1), postscript(7)
;#
;# AUTHOR
;# Gisle Aas, Norwegian Computing Centre, 1990
;#
;# BUGS
;# Pstree truncates all directory names to 14 characters.
;#
;# NOTES
;# PostScript is a trademark of Adobe Systems, Incorporated.
;# Perl is written by Larry Wall and is distributed under the
;# terms of the GNU General Public License.
;#
;# CHANGES
;# Jan 22 1990, Gisle Aas, NCC
;# The right way to get rid of "." and ".." from directories is
;# now used. Proper handling of symbolic links: tree doesn't
;# follow symbolic links to directories any more.
;# Jan 23 1990, Gisle Aas, NCC
;# Added the '-f' option to include ordinary files in dir map.
;#
#define A4_TOP 841
#define A4_RIGHT_EDGE 595
#define TB_MARGIN 40
#define LEFT_MARGIN 60
#define FONT "AvantGarde-Book"
#define FONT_SIZE 10
#define DIR_LEVEL_INDENT 90
$y = A4_TOP - TB_MARGIN;
$prev_level = 0;
open(tmp,"+>/tmp/tree$$") || die "Can't create temporary file";
unlink("/tmp/tree$$");
select(tmp);
print "/s {show} bind def\n";
print "/m {moveto} bind def\n";
printf "/%s findfont %d scalefont setfont\n",FONT,FONT_SIZE;
print "0.1 setlinewidth\n";
push(@ARGV,'.');
if ($ARGV[0] =~ /^-/) {
$_ = shift;
last if (/^--$/);
if (/f/) {
$list_files = 1;
}
else {
print STDERR "Usage: tree [-f] [dirname]\n";
exit(1);
}
}
&list_dir($ARGV[0],0);
print "showpage\n";
seek(tmp,0,0); # rewind the temporary file
select(STDOUT);
print "%!\n";
if ($y < TB_MARGIN) {
$page_size = (A4_TOP - 2*TB_MARGIN);
$scale_factor = (A4_TOP - 2*TB_MARGIN)/((A4_TOP - TB_MARGIN ) - $y);
printf "%.1f %.3f translate\n", LEFT_MARGIN,
(-$y)*$scale_factor + TB_MARGIN;
printf "%.5f dup scale\n", $scale_factor;
} else {
printf "%.1f 0 translate\n", LEFT_MARGIN;
};
;# copy temporary file to standard out
while (<tmp>) {
print;
}
exit;
sub list_dir
{
local($dirname) = shift;
local($level) = shift;
local(@content);
opendir(d,$dirname);
@content = sort(grep(!/^\.\.?$/,readdir(d)));
closedir(d);
while ($file = shift(@content)) {
$file = "$dirname/$file";
if (-d $file) {
if (-l $file) { # symbolic link; do not follow these
&emitt(substr($file,rindex($file,'/')+1,14) . " -> " .
readlink($file), $level + 1);
}
else {
&list_dir($file,$level+1);
}
}
elsif ($list_files) {
&emitt(substr($file,rindex($file,'/')+1,14), $level+1);
}
}
&emitt(substr($dirname,rindex($dirname,'/')+1,14), $level);
}
;# Uses the following global variables:
;# $y : current vertical position (initial value = 'top of page')
;# $prev_level : the level reportet last time on emit (init value = 0)
;# @top : current top position at different levels
;# @bottom : current bottom position at different levels
;# @pos : string of positions at different levels
sub emitt
{
local($text) = shift;
local($level) = shift;
;# Do some substitutions on the $text so that it can be used as a
;# PostScript string constant.
$text =~ s/\\/\\134/g;
$text =~ s/\(/\\050/g;
$text =~ s/\)/\\051/g;
if ($level == $prev_level) {
&write($level,$y,$text);
$pos[$level] .= " $y";
$bottom[$level] = $y;
$y -= FONT_SIZE;
}
elsif ($level > $prev_level) {
&write($level,$y,$text);
local($i);
for ($i=$prev_level+1;$i<$level;$i++) {
$pos[$i] = '';
}
$pos[$level] = "$y";
$top[$level] = $y;
$bottom[$level] = $y;
$y -= FONT_SIZE;
}
elsif ($level == ($prev_level - 1)) {
local($ypos) = ($top[$level+1] - $bottom[$level+1]) / 2 +
$bottom[$level+1];
&write($level,$ypos,$text);
&lines($level,$ypos,$pos[$level+1],$text);
if ($pos[$level]) {
$pos[$level] .= " $ypos";
$bottom[$level] = $ypos;
}
else {
$pos[$level] = "$ypos";
$top[$level] = $ypos;
$bottom[$level] = $ypos;
}
}
else {
die "Humm..., jump from level $prev_level to level $level";
}
$prev_level = $level;
}
sub write
{
local($x,$y,$text) = @_;
$x = $x * DIR_LEVEL_INDENT;
printf "%.f %.f m(%s)s\n", $x, $y, $text;
}
sub lines
{
local($x,$y,$to,$text) = @_;
local(@to) = split(/ /,$to);
$x = $x * DIR_LEVEL_INDENT;
$y += FONT_SIZE/3;
printf "($text) stringwidth pop %.1f add %.1f m\n",$x+1,$y;
printf "[";
for (@to) { printf " %.1f", $_ + FONT_SIZE/3; }
printf "]\n";
printf "{gsave %.1f exch lineto stroke grestore} forall\n",
$x+DIR_LEVEL_INDENT-4;
}
------Cut here-------
--
-----------------------+------------------------------------------------
Gisle Aas ! email: Gisle.Aas@nr.uninett
Norsk Regnesentral ! arpa: Gisle.Aas%nr.uninett@tor.nta.no
Tlf: (02)453561 ! snail: Postboks 114 Blindern, N-0314 OSLO 3
-----------------------+------------------------------------------------