package ActivePerl::DocTools::TOC; use strict; use warnings; use File::Basename; use File::Find; use Config; use Symbol; # get a default value for $dirbase ... can be overridden? our $dirbase; if (exists $Config{installhtmldir}) { $dirbase = $Config{installhtmldir}; } else { $dirbase = "$Config{installprefix}/html"; } my @corePodz = qw( perl perlfaq perltoc perlbook __ perlsyn perldata perlop perlsub perlfunc perlreftut perldsc perlrequick perlpod perlstyle perltrap __ perlrun perldiag perllexwarn perldebtut perldebug __ perlvar perllol perlopentut perlretut __ perlre perlref __ perlform __ perlboot perltoot perltootc perlobj perlbot perltie __ perlipc perlfork perlnumber perlthrtut __ perlport perllocale perlunicode perlebcdic __ perlsec __ perlmod perlmodlib perlmodinstall perlnewmod __ perlfaq1 perlfaq2 perlfaq3 perlfaq4 perlfaq5 perlfaq6 perlfaq7 perlfaq8 perlfaq9 __ perlcompile __ perlembed perldebguts perlxstut perlxs perlclib perlguts perlcall perlutil perlfilter perldbmfilter perlapi perlintern perlapio perltodo perlhack __ perlhist perldelta perl5005delta perl5004delta __ perlaix perlamiga perlbs2000 perlcygwin perldos perlepoc perlhpux perlmachten perlmacos perlmpeix perlos2 perlos390 perlsolaris perlvmesa perlvms perlvos perlwin32 ); # LIST OF METHODS TO OVERRIDE IN YOUR SUBCLASS { no strict "refs"; # trust me, I know what I'm doing for my $abstract_method (qw/ header before_pods pod_separator pod after_pods before_pragmas pragma after_pragmas before_libraries library library_indent_open library_indent_close library_indent_same library_container after_libraries footer/) { *$abstract_method = sub { die "The subroutine $abstract_method() must be overriden by the child class!" }; }; } sub new { my ($invocant, $options) = @_; my $class = ref($invocant) || $invocant; # object or class name. my $self; if (ref($options) eq 'HASH') { $self = $options; } else { $self = {}; } _BuildHashes($self); bless ($self, $class); return $self; } # generic structure for the website, HTML help, RDF sub TOC { # warn "entered Write"; my ($self) = @_; my $verbose = $self->{'verbose'}; my $output; my %filez = %{$self->{'filez'}}; my %pragmaz = %{$self->{'pragmaz'}}; my %podz = %{$self->{'podz'}}; # generic header stuff $output .= $self->boilerplate(); $output .= $self->header(); # core pods my %unused_podz = %podz; $output .= $self->before_pods(); foreach my $file (@corePodz) { if ($file eq '__') { $output .= $self->pod_separator(); } elsif ($podz{"Pod::$file"}) { $output .= $self->pod($file); delete $unused_podz{"Pod::$file"}; } else { warn "Couldn't find pod for $file" if $verbose; } } foreach my $file (sort keys %unused_podz) { warn "Unused Pod: $file" if $verbose; } $output .= $self->after_pods(); # pragmas (or pragmata to the pedantic :) $output .= $self->before_pragmas(); foreach my $file (sort keys %pragmaz) { $output .= $self->pragma($file) } $output .= $self->after_pragmas(); # libraries $output .= $self->before_libraries(); my $depth=0; foreach my $file (sort {uc($a) cmp uc($b)} keys %filez) { my $showfile=$file; my $file_depth=0; my $depthflag=0; # cuts $showfile down to its last part, i.e. Foo::Baz::Bar --> Bar # and counts the number of times, to get indent. --> 2 while ($showfile =~ s/.*?::(.*)/$1/) { $file_depth++ } # if the current file's depth is further out or in than last time, # add opening or closing tags. while ($file_depth != $depth) { if ($file_depth > $depth) { $output .= $self->library_indent_open(); $depth++; $depthflag=1; } elsif ($file_depth < $depth) { $output .= $self->library_indent_close(); $depth--; $depthflag=1; } } unless ($depthflag) { $output .= $self->library_indent_same(); } if ($filez{$file}) { $output .= $self->library($file, $showfile, $depth); } else { # assume this is a containing item like a folder or something $output .= $self->library_container($file, $showfile, $depth); } } $output .= $self->after_libraries(); $output .= $self->footer(); return $output; } sub _BuildHashes { my ($self) = shift; my $verbose = $self->{'verbose'}; unless (-d $dirbase) { die "htmldir not found at: $dirbase"; } #warn "entered buildhashes"; my @checkdirs = qw(lib site/lib); my (%filez, %pragmaz, %podz); my $Process = sub { return if -d; my $parsefile = $_; my ($filename,$dir,$suffix) = fileparse($parsefile,'\.html'); if ($suffix !~ m#\.html#) { return; } my $TOCdir = $dir; $filename =~ s/(.*)\..*/$1/; # print "$TOCdir"; $TOCdir =~ s#.*?lib/(.*)$#$1#; $TOCdir =~ s#/#::#g; # print " changed to: $TOCdir\n"; $dir =~ s#.*?/((site/)?lib.*)/$#$1#; #looks ugly to get around warning if ($filez{"$TOCdir/$filename.html"}) { warn "$parsefile: REPEATED!\n"; } $filez{"$TOCdir$filename"} = "$dir/$filename.html"; # print "adding $parsefile as " . $filez{"$TOCdir/$filename.html"} . "\n"; # print "\%filez{$TOCdir$filename.html}: " . $filez{"$TOCdir$filename.html"} . "\n"; return 1; }; foreach my $dir (@checkdirs) { find ( { wanted => $Process, no_chdir => 1 }, "$dirbase/$dir") if -d "$dirbase/$dir"; } foreach my $file (keys %filez) { if ($file =~ /^[a-z]/) { # pragmas in perl are denoted by all lowercase... if ($file ne 'perlfilter' and $file ne 'lwpcook') { # ... except these. sigh. Yes, Dave, it's their fault, but we ought to fix it anyway. $pragmaz{$file} = $filez{$file}; delete $filez{$file}; } } elsif ($file =~ /^Pod::perl/) { $podz{$file} = $filez{$file}; delete $filez{$file}; } elsif ($file eq 'Pod::PerlEz') { #this should be part of ActivePerl dox delete $filez{$file}; } } foreach my $file (sort {uc($b) cmp uc($a)} keys %filez) { my $prefix = $file; if (! ($prefix =~ s/(.*)?::(.*)/$1/)) { warn "$prefix from $file\n" if $verbose; } else { if (! defined ($filez{$prefix})) { $filez{$prefix} = ''; warn "Added topic: $prefix\n" if $verbose; } warn " $prefix from $file\n" if $verbose; } } $self->{'filez'} = \%filez; $self->{'podz'} = \%podz; $self->{'pragmaz'} = \%pragmaz; } sub text { my ($text) = join '', map { "$_\n" } @_; return sub { $text }; } 1; __END__ =head1 NAME ActivePerl::DocTools::TOC- base class for generating Perl documentation TOC =head1 SYNOPSIS use base ('ActivePerl::DocTools::TOC'); # override lots of methods here... see source for which ones =head1 DESCRIPTION Base class for generating TOC's from Perl html docs. =head2 EXPORTS $dirbase - where the html files are =head1 AUTHOR David Sparks, DaveS@ActiveState.com Neil Kandalgaonkar, NeilK@ActiveState.com =head1 SEE ALSO The amazing L. L L =cut