davew@ux.acs.umn.edu (David B. Walters) (01/24/91)
I am looking for a program that will take a general tree structure and output a postscript graph of the tree. /--------------------------------------------------------------------\ |David B. Walters Alias: Arastin | |University of Minnesota Internet: davew@ux.acs.umn.edu | |Mathematics Computer Lab (the Zoo) Office #: (612) 625-0801 | |4 Vincent Hall; 206 Church Street.S.E., | |Minneapolis, MN 55455 UUCP: rutgers!umn-cs!ux.acss.umn.edu!davew | \--------------------------------------------------------------------/
aas@aase.nr.no (Gisle Aas) (01/25/91)
In article <3105@ux.acs.umn.edu> davew@ux.acs.umn.edu (David B. Walters) writes: > I am looking for a program that will take a general > tree structure and output a postscript graph of the tree. You should be able to adjust this "unix-file-hierarchy-tree" program to your needs. It is written in the perl language, which ought to be present at any decent computer installation. The file is also suitable input to nroff/troff for manual page formatting. ----- cut here -------------------------------------- #!/usr/local/bin/perl 'di'; 'ig00'; # pstree(1) - produce directory map in PostScript. # $Id: pstree,v 1.1 90/11/21 12:22:15 aas Exp $ sub PAGE_TOP { 842; } # A4 height = 842, letter height = 792 #sub PAGE_RIGHT_EDGE { 595; } sub TB_MARGIN { 50; } sub LEFT_MARGIN { 60; } sub FONT { "Helvetica"; } sub FONT_SIZE { 20; } sub DIR_LEVEL_INDENT { &FONT_SIZE * 9; } $y = &PAGE_TOP - &TB_MARGIN; $prev_level = 0; $average_char_width = &FONT_SIZE / 2; $max_x_pos = 0; # keep track of it in order produce bounding box 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: $0 [-f] [dirname]\n"; exit(1); } } &list_dir($ARGV[0],0); print "showpage\n"; seek(tmp,0,0); # rewind the temporary file select(STDOUT); print "%!PS-Adobe-2.0 EPSF-2.0\n"; print "%%Title: (Directory map of $ARGV[0])\n"; print "%%Creator: pstree, (C) 1990 Gisle Aas, NR\n"; printf "%%%%DocumentFonts: %s\n", &FONT; if ($y < &TB_MARGIN) { $page_size = (&PAGE_TOP - 2 * &TB_MARGIN); $scale_factor = ($page_size)/((&PAGE_TOP - &TB_MARGIN ) - $y); printf "%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", &LEFT_MARGIN, &TB_MARGIN + &FONT_SIZE * $scale_factor, &LEFT_MARGIN + $max_x_pos * $scale_factor, &PAGE_TOP - &TB_MARGIN + &FONT_SIZE * $scale_factor; printf "%.1f %.3f translate\n", &LEFT_MARGIN, (-$y)*$scale_factor + &TB_MARGIN; printf "%.5f dup scale\n", $scale_factor; } else { printf "%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", &LEFT_MARGIN, $y + &FONT_SIZE, &LEFT_MARGIN + $max_x_pos, &PAGE_TOP - &TB_MARGIN + &FONT_SIZE; 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/[\\\(\)]/\\$&/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; $x += length($text) * $average_char_width; $max_x_pos = $x if ($x > $max_x_pos); } 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; } ########################################################################### # These next few lines are legal in both Perl and nroff. .00; # finish .ig 'di \" finish diversion--previous line must be blank .nr nl 0-1 \" fake up transition to first page again .nr % 0 \" start at page 1 ';<<'.ex'; #__END__ #### From here on it's a standard manual page ######### .TH PSTREE 1 "November 1990" .SH NAME pstree \- produce directory map in PostScript .SH SYNOPSIS .B pstree [ .B \-f ] [ .I dirname ] .SH 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 .I dirname is given the directory map from the given directory and down is produced. The output conforms to Adobe's document structuring conventions (version 2.1), and the EPSF specification version 2.0. .SH OPTIONS .TP 5 .B \-f Include ordinary files in the map. Without this flag only the overall directory structure is shown. .SH SEE ALSO .BR find (1), .BR ls (1), .BR perl(1), .BR postscript(7) .SH BUGS Pstree truncates all directory names to 14 characters. The image is not scaled down if it overflows the right edge of the page. .SH AUTHOR (C) Gisle Aas, Norwegian Computing Centre (NR), 1990. <Gisle.Aas@nr.no> .SH 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. .ex -- Gisle Aas | snail: Boks 114 Blindern, N-0314 Oslo, Norway Norsk Regnesentral | X.400: G=Gisle;S=Aas;O=nr;P=uninett;C=no voice: +47-2-453561 | inet: Gisle.Aas@nr.no