Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
I wrote for myself a little documenatry tool because of a larger project with a lot of modules
- hmm - I am now not sure what to do with this idea.
It could by that others find this very usefull too and therefore I want to ask here if this idea is that good that it would be worth to 'make it official' as an additional tool to document perl programs and modules.
The (big) advantage of this idea is that you as programmer really don't have much add. work for this DocTool.pl.
'Single-Line-Descriptions' for the package, the subs and the the required, optional and returned variables is needed, with only 2 tags: #: and ##:This you will write anyway in your program.
As an example you find the code of a ChatServer (serch for this topic) and the prgram DocTool.pl itself as well, just start DocTool so that it can read the chatServer and than hopefully you'll like the result.
Of course a lot can and has to done to make that real nice. For example the presentation in frames simulöar to a real prog. IDE, but I have no idea about the frames and no time to dig into that.
If you are interested put DocTool.pl and the ChatServer.pl into the same folder and there start ./DocTool.pl.
Then open the created
DocTool.html with a Browser. Maybe you like what you see - but all is still in progress ..
(Please excuse the prg.style but this damn nested html table and list stuff took a lot of time.)
Thanks,
Carl
#! /usr/bin/perl #t: make a Documentation of Functions, Methods and Objects. #t: Read Section VI for detailed information # those vars can be given by the commandline use warnings; use strict; my $verbose = ("@ARGV" =~ /\-v/) ? 1 : 0; #: verbose mode if ("@ARGV" +=~ /\-v/) my @F = getFiles( @ARGV ); #: (mixed) list of Files or Dirs, default: +local dir (/.) my $fHTML = 'DocTool.html'; # HTML-File to create my $isa = ''; # is set to '' in the package detet. section my $tp = '<a href="#top">^ top</a>'; # goto Top tag my $pack = "\n\n<p><a name=\"DetPac\"></a>\n". "<b><font size=+1>V The Detailed Packages and P +rograms</font></b>\n"; my $li = ''; # line ident my $top = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> <html> <head> <title>add. Perl Documentary Tool (an idea of C.A. Schreiber)</title +> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859 +-1"> <meta name="GENERATOR" content="DocTool.pl"> </head> <body><a name="top"></a> Sections in this Web-page:<table> <tr><td> I </td><td><a href="#Progra +ms">Programs</a></td><td></td></tr> <tr><td> II </td><td><a href="#PacDe +scr">Package-Overview</a></td><td></td></tr> <tr><td> III </td><td><a href="#PacS +ubs">Packages with their Subs</a></td><td></td></tr> <tr><td> IV </td><td><a href="#SubsS +ubs">All Subs with their Descriptions</a></td><td></td></tr> <tr><td> V </td><td><a href="#DetPac +">The Detailed Packages and Programs</a></td><td></td></tr> <tr><td> VI </td><td><a href="#Help" +>How to Use this Program: DocTool.pl</a></td><td></td></tr> </table>'."<p>\n\n<a name=\"Programs\"></a>\n"; # <font face="courier" +> my %CT = (); # the content is put here for later: foreach (sort keys % +CT) # 1st Part: only if it is a Program-File (.pl) and not a Packege-File +(.pm) my $prgTop = ''; # 2st Part: only Packages + description (sorted); kind of content my $contSort = "<p>\n\n<!--\$contSort--> <a name=\"PacDescr\"></a><tab +le>\n$tp<br>\n<b><font size=+1>II Package-Overview (with D +escriptions)</font></b>\n"; # start with '.' # 3nd Part: (sorted) Packages with their (sorted) subs my $pacSort = "<p>\n\n<!--\$pacSort-->\n$tp<br>\n<a name=\"PacSubs\">< +/a><b><font size=+1>III Packages with their Subs</font></b +>\n<ul>"; # start with ':' # 4rd Part: all Subs sorted alphabetically and description my $subSort = "<p>\n\n<!--\$subSort--><a name=\"SubsSubs\"></a>\n<tabl +e valign =\"top\">\n$tp<br>\n<b><font size=+1>IV All Subs +with Descriptions</font></b>\n"; # 5th Part: (sorted) Packages with their (sorted) subs and their req. + or opt. Variables and what they return my @ret = (); my $totalNoPack = 0; # 6th Part: Help (How to read this page) #$helpHelp = &help(); foreach my $fPL (@F) { # Perl-File print "\n\n#############\n#############\n\n\t<=\t$fPL\n" if $verbo +se; my $PerlProgramTop = ($fPL =~ /\.pl$|\.cgi$/) ? 1 : 0; my $_prgTop = "<table valign =\"top\"><b><a href=\"#$fPL\">$fPL </ +a></b><a href=\"$fPL\"> (File)</a>\n<tr><td> & +nbsp; </td>\n\t<td>\n" if ($PerlProgramTop); my $is_prgTopText = 0; # for DocTool Text at the begin of the pl-f +ile #read Perl-File open F, "< $fPL" or die "Can'T open to read $fPL: $!\n\n"; my @L = <F>; close(F); next if ("@L" =~ /NoDocTool/ && $fPL !~ /DocTool\.pl/); # not fast + but save my $LC = 0; # Line Counter my $isPOD = 0; # to skip the lines between =pod .. =cut my %expSubs = (); # exported subs to def. color my @tmp = (); # to be pushed into @ret after the file my $isDocTool = 0; # is this firle setup for DocTool? my $NoPack = 0; my $sub = 0; my $StopDocTool = 0; my $packName = $fPL; # is replaced in the package-section, used if + a script with subs, but no packages!! for my $l (@L) { # go through all lines $LC++; if ($l =~ /#.+?StopDocTool/ && $l !~ /\s*last\sif\s\(/) { # 2. + question: to make it self-analysable $StopDocTool = 1; # must be menat to be documtented last; } # not to read nromal comment ines but those if spec. varibles +are meant for DocTool.pl # but not used in that way but by Perls sys.-Vars: @_ or $_[0] +.. next if ($l =~ /\s*#\s/ && $l !~ /#\s(my|our)\s+.+?#:/); $isPOD = 1 if ($l =~ /^=pod$/); $isPOD = 0 if ($l =~ /^=cut$/ && $isPOD); next if ($isPOD); # detect different tags for the documentation: # Commentaries => print this line if ($l =~ /#t\:\s*(\S.+?)\s*$/) { # just print this line print "#t\t$1\n" if $verbose; my $t = $1; if ($PerlProgramTop) { if ( $is_prgTopText == 0 ) { $_prgTop .= "\t\t<i> $t </i>\n"; $is_prgTopText = 1; } else { $_prgTop .= "\t\t<i> $t </i>\n"; } } else { push @tmp, "$isa <br><i>$t</i>$li"; } $isa = ''; $isDocTool = 1; next; } if ($l =~ /\@EXPORT[\s\=\(]+(.+)\);/) { my $s = $1; $s =~ s/\'//g; push @tmp, "<table><tr><td align=\"left\" valign=\"top\">< +font color=\"red\"><b>exported subs: <b></font></td><td>$s$li</td></t +r></table>\n"; %expSubs = map { $_ => 1 } split /\,\s*/, $s; } # is A: @ISA = qw(AI); if ($l =~ /\@ISA[\s\=qw]+\((.+?)\)/) { # isa link # $me->{'eD'} = DBar::new($me->{'SYM'}, $me->{'toSave'}, +$max); #HasA: text my $v = "Is a: <b><a href=\"#$1\"> $1</a></b>", +; print $l ,"\t\t1:$1; v:$v;\n" if $verbose; if ($v !~ /Exporter/i) { push @tmp, " <br>$v$li"; $isa = "<br> <br>\n"; } next; } # Returns if ($l =~ /\#\#\:\s*([A-Za-z\$\%\&\(\'\-].+)/) { # return valu +e print $l if $verbose; push @tmp, " <b>returns: </b> $1 $li"; $isDocTool = 1; next; } # Has another Object if ($l =~ /[\smy]+([\$\@\%\&\'\-].+?)[\s\=].*?\s([A-Za-z\_]+)\ +:\:.+?\s*\#\:\s*(\S.+)\s/) { # Has an Object # incl our: if ($l =~ /[mo][uyr\s]+([\$\@\%\&\'\-].+?)[\s\=]. +*?\s([A-Za-z\_]+)\:\:.+?\#\:\s*(\S.+)\s/) { # Has an Object my ($v,$o,$t) = (sprintf("<b>%-16s</b>",$1) ,sprintf("has +a: <b><a href=\"#%s\">%s</a></b>",$2,$2),$3); print $l ,"\t1:$1; 2:$2; 3:$3; v:$v; o:$o\n" if $verbose; $t = (($t=~/^[A-Z]/) ? "<b>$t</b>" : $t); push @tmp, " <li>$v$o: $t</li>$li"; next; } # SUBS if ($l =~ /^\s*sub\s+(\w.+?)\s*\{\s*\#\:\s*(\S.+)/) { # sub new { #: create new Stat analysing tool print "sub\t$1\n\t$2\n\t$packName\t*\t$1\n" if $verbose; if ( $is_prgTopText == 1 ) { $is_prgTopText = 0; $_prgTop .= "</td></tr>\n"; } $PerlProgramTop = 0; # not anymore top of prg. my $color = (exists $expSubs{$1}) ? '"red"' : '"blue"'; unless ($NoPack) { push @tmp, "$pack<table>$tp\n<tr><td align=\"left\" va +lign=\"top\"><font size=\"+2\"><b><a name=\"$fPL\"><a href=\"$fPL\">$ +fPL </a></a></b></td></tr></table>"; $NoPack--; } if ($sub) { $li = "\n "; push @tmp, "</ol><br><li>$li<table><tr><td align=\"lef +t\" valign=\"top\"><a name=\"$packName*$1\"><font color=$color><b> $1 + </b></font></a> (l:$LC) </td><td><i>$2</i></td></tr></table><ol>$li" +; } else { push @tmp, "$isa<ul><li><table><tr><td align=\"left\" +valign=\"top\"><a name=\"$packName*$1\"><font color=$color><b>$1</b>< +/font></a> (l:$LC) </td><td><i> $2</i></td></tr></table><ol>$li"; $sub = 1; $isa = ''; } $CT{":$packName*$1"} = " <li><a href=\"#$packName*$1\"> +$1 </a> $2 </li>\n" if ($NoPack>0); $CT{";$1*$packName"} = " <tr><td> </td><td><a href=\" +#$packName*$1\"> $1 </a></td><td> $packName </td><td><a href=\"$fPL\" +> (File) </a></td><td> $2</td></tr>\n";# if ($NoPack>0); $isDocTool = 1; next; } # Variables if ($l =~ /(our\s+|my\s+)([\$\@\%\&\'\-].+?)[\s\=]+.+?\#\:\s*( +\S.+?)\s*$/) { # variables # $me->{'INF'} = (@_) ? shift : '-/-'; #: Inf. to take and + to print print $l ,"\t\t1:$2; 2:$3\n" if $verbose; my ($v,$t) = ($2,$3); if ($PerlProgramTop) { if ( $is_prgTopText ) { $is_prgTopText = 0; $_prgTop .= "\t</td>\n"; } $_prgTop .= "</tr>\n<!--vars-->\n<tr>" unless ($_prgTo +p =~ /<!--vars-->/); $_prgTop .= "\n\t\t<tr><td>". (($t =~ /^[A-Z]/) ? "<b> + $v </b></td><td> = $t " : " $v</td><td> = <em> $t </em>" ) ."</td></ +tr>$li"; } else { push @tmp, "$isa <li>". (($t =~ /^[A-Z]/) ? "<b> $v </ +b> = $t " : " $v = <em> $t </em>" ) ."</li>$li"; } $isa = ''; $isDocTool = 1; next; } #PACKAGES if ($l =~ /package\s(.+);.*?\#\:\s*(\S.+)/) { # new pa +ckage print "pack\t$1\n\t$2\n\t$packName\t-\t$fPL\n" if $verbose +; $NoPack++; $totalNoPack++; $PerlProgramTop = 0; # not anymore top of prg. if ( $is_prgTopText ) { $is_prgTopText = 0; $_prgTop .= "</td></tr>\n"; } $sub = 0; # to start new ul for subs my $pN = sprintf("%-6s",$1); $li = "\n "; push @tmp, "$pack<table>$tp\n<tr><td align=\"left\" valign +=\"top\"><font size=\"+2\"><b><a name=\"$1\"><a href=\"$fPL\">$pN </a +></a></b></td><td></font><font size=\"+1\"><b><i> $2 </i></b></t +d></font></tr></table>"; $packName = $1; $li .= ' '; $CT{".$2"} = "<tr><td><li><a href=\"#$1\"><b> $1 </b></a>< +/li></td><td><a href=\"$fPL\"> (File)</a>: </td><td> $2</td></tr>\n"; $CT{":$1"} = "\n<li><a href=\"#$1\"> $1 </a> <a href=\"$fP +L\"> (File) </a> <i> $2 <i><ul>\n"; $pack = "</ol>\n </ul>\n</p> <br> <br>\n\n<p>\n" +; $isa = ''; next; } } # foreach line of a file #if ($_prgTop) { if ($_prgTop) { #$_prgTop .= "</ol>\n" if ( $_prgTop =~ /\<ol\>/); print $_prgTop if $verbose; $prgTop = "\n<p>\n<b><font size=+1>I Programs</font +></b>\n" unless ($prgTop); $prgTop .= "$_prgTop\n</table>\n<p>\n" if ($_prgTop =~ /\<\/tr +\>/ or $StopDocTool); } push @ret, @tmp if ($isDocTool); } # foreach file my $go = 0; foreach my $i (sort keys %CT) { $i =~ /^(.)/; if ($1 eq ':') { $pacSort .= " </ul>\n </li><br>" if ($go && $CT{$i} =~ / +<li>.+?<ul>/); $pacSort .= $CT{$i}; $go++; } $subSort .= $CT{$i} if ($1 eq ';'); $contSort .= $CT{$i} if ($1 eq '.'); } # write the end of the Parts; #$prgTop .= "\n</table>\n" if ($prgTop); $pacSort .= " </ul>\n </li>\n</ul>\n<p>\n"; $subSort .= '</table><br>'; $contSort .= '</table><p>'; # open HTML File to write the html-file open (F, "> $fHTML") or die "\nCan't open to write $fHTML: $!\n\n"; print F $top, $prgTop, (($totalNoPack) ? ($contSort , $pacSort) : '<!-- no Packag +es -->'), $subSort, "<p>\n\n<!-- \@ret -->\n", @ret, "</ol>\n</ul>$pack\n", &help(), "\n$tp\n</body></html>"; close(F); # that's it ###### subs ###### sub getFiles { #: creates a list of Perl-files to go through # my @f = @_; #: list of file- or dir-names if omitted local dir ( +/.) is read. my @ret; if (@_) { foreach (@_) { push @ret, $_ if (-f $_); push @ret, _rdDir($_) if (-d $_); # '-v' is skipped here: no file, no dir!! } } else { push @ret, _rdDir('.'); } print map { "\t$_\n" } @ret if $verbose; return @ret; ##: Perl-file list } sub _rdDir { #: read all files in $dir that end with .pm, .pl, .cgi. my $dir = shift; #: Dir to read if ( opendir(DIR, $dir) ) { my @d = map { "$dir/$_" } grep { -f "$dir/$_" && /.+\.p[ml]$/ +} readdir(DIR); closedir DIR; # print map { "\t$_\n" } @d; return @d; ##: list of file-names or an empty list } else { warn "can't opendir $dir: $!"; return (); } } sub help { #: this is needed, because the examples to use DocTool.pl c +onfuse DocTool.pl if it anayses itself. my $n = 1; return ##: the help-text as html-formated string # StopDocTool "<p>\n\n<!--\$helpHelp--><a name=\"Help\"></a>\n<table valign + =\"top\" cellspacing=20>\n$tp<br>\n<b><font size=+1>VI Ho +w to Use this Program: DocTool.pl</font></b>\n" ."<tr><td> ${\($n++)})</td><td>Basic Intention< +/td>" ."<td> The main intentions for this is: to get easily and + quick the information needed to (re-)use packages, methods, subs and + scripts. Larger projects leed to a lot of modules and metho +ds, and by the time it can become difficult to retain everything in mind that has been programmed. So it + might be usefull to have a quick way to get the information about: how is a method call +ed, what variables are required or optional, what would be the defaul +t value and what is returned. Beside that it might be nice + to look into that method just with one klick. And finally it might be usefull in some cases to f +ind a method not only by knowing its module. <br><br>It is not meant to replace good program-do +cumentation!. <br>Due to intention for this program the examples + ChatServer.pl and DocTool.pl itself should not be documented as they + are! Only the 1st section 'I Scripts' are necessary to +(re-)use them. All functions packages and methods are internally used + and there is no need to document them. If you want to follow this idea, just eliminate th +e tags of DocTool.pl, but on the other hand you can use this tool as +a sturtup for your program documentation. </td>" ."<tr><td> ${\($n++)})</td><td>Red and Blue Met +hod Names</td>" ."<td> Methods are presented in the 5th section as lexica +lly sorted list within the module they are defined. Red method names indicates that the method is expo +rted (see below the package name where you find all exp +orted methods).<br> Blue method names indicate that the method is not +exported. </td>" ."<tr><td> ${\($n++)})</td><td>Line Numbers</td +>" ."<td> After the method - in brackets - you find the line + number, where the method start. <br>(Maybe this can be replaced by a direct link t +o that line later on) </td>" ."<tr><td> ${\($n++)})</td><td>Normal and Bold +Variable Names</td>" ."<td> Due to the convention of DocTool.pl a capital lett +er after the tag <b> #: </b> indicates required variables. In this case the variable name is printed in bold +letters. If the variable is optional its name is printed no +rmally and a default value (if not given) for this variable should be + mentioned. The varibales ar presented as ordered list, so tha +t the number indicates the place where the variable put calling this +method. <br>(By the way, the variable-tag for DocTool.pl i +s not only '#:' but a <b>my</b> or an <b>our</b> before the valiable. +) </td>" ."<tr><td> ${\($n++)})</td><td>Tags of DocTool. +pl</td>" ."<td><table valign=\"top\"> DocTool.pl uses only 3 + 2 tags: <tr><td><b>#t:</b></td> <td> Comment to be printed for additional i +nformation. Mainly for executable Perl-Scripts to +get what they are meant for or what it is doing. </td></tr> <tr><td><b>#:</b></td> <td> This is used for packages, methods sub +s and variables. In the <i>same</i> line with either <b>package, sub, my, our</b> you can d +escribe in this line what they are meant for or what it is doing. examples: <li><b>package Reader; #: detached pro +cess to receive the Client's Input</b> <br> prints: Reader detached proces +s to receive the Client's Input (see above).</li> <li><b>sub run { #: runs until the soc +ket of this object brokes, ..</b> <br>prints: run (l:78) runs until the +socket of this object brokes, .. (s.a.)</li> <li><b>my \$ID = shift; #: The ID for +this module</b> <br>prints: <b>\$ID</b> = The ID for t +his module</li> <li><b>C</b>apital-letter(s) right aft +er the tag indicates that this variable is required.</li> <li>non capital-letters: a-z.0-9,(,[,{ +, .. indicates optional values/variables, please use default:0 to exp +lain what happens if omitted.</li> <li><b>commeted variables</b><br> If you want to use the Perl-Vars \@_ o +f \$_[0], \$_[1], .. you can comment-out the description (used in s2T + in Writer): <br><b># my \$dur = shift #: Duration +in sec. transfrmd into Days hh:mm:ss</b> <br> prints: <b>\$dur</b> = Duration i +n sec. transfrmd into Days hh:mm:ss </td></tr> <tr><td><b>##:</b></td> <td> is used for the returnd value(s): <br>return \@l; ##: list of file-na +mes or an empty list <br>prints: <b>returns: </b> list o +f file-names or an empty list <br>(remark: 'returns' is not needed t +o write again) </td> </tr> <tr><td><b>StopDocTool</b></td> <td> This is used by DocToll to stop analys +ing the lines hereafter. </td> </tr> <tr><td><b>NoDocTool</b></td> <td> The file is not analyzed if this is wr +itten somewhere in the file. </td> </tr> </table> </td>" ."<tr><td> ${\($n++)})</td><td>Hide and/or Show +</td>" ."<td> As this is meant for (re-)using packages, methods +and so on you can hide all what is not needed to know using the packa +ge, method,.. So, here all packages and subs should be hided, bu +t to demonstrate how this works they are prepared to be presented in +this web-page. That means that only what has been written to sect +ion 'I Programs' should be seen. But of course, you can use it as you + like it. </td>" ."<tr><td> ${\($n++)})</td><td></td>" ."<td> </td>" ."<tr><td> ${\($n++)})</td><td></td>" ."<td> </td>" ."<tr><td> ${\($n++)})</td><td></td>" ."<td> </td>" .'</tr> </table>'; }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: DocTool.pl: additional Perl Documentation?
by Aristotle (Chancellor) on Jan 07, 2004 at 16:58 UTC | |
by Anonymous Monk on Jan 08, 2004 at 11:49 UTC | |
|
Re: DocTool.pl: additional Perl Documentation?
by Roger (Parson) on Jan 08, 2004 at 04:30 UTC | |
by Anonymous Monk on Jan 08, 2004 at 11:58 UTC |