function shdoc { typeset version="3.1, 2008-05-28, Michael Wang ." typeset help doc file typeset tmpdir=/tmp/shdoc_$$_$RANDOM typeset base tmpf i flag eval help=y doc=pod "$@" [[ -n ${OPATH:-} ]] && typeset PATH=$OPATH set -- $(echo $help $doc | tr '[a-z]' '[A-Z]') help=$1 doc=$2 base=${file##*/} base=${base%.sh} base=${base%.ksh} base=${base%.c} base=${base%.pl} base=${base%.php} case ${doc} in (POD) mkdir -p ${tmpdir} && tmpf=${tmpdir}/${base}.pod ;; (MAN) mkdir -p ${tmpdir}/man/man1 && tmpf=${tmpdir}/man/man1/${base}.1 ;; esac while IFS= read -r i; do [[ $i = "## "* ]] && { [[ $i = "## ${doc}_START"* ]] && { flag=Y; continue; } [[ $i = "## ${doc}_STOP"* ]] && { flag=N; continue; } [[ ${doc} = POD && -z ${flag:-} ]] && flag=Y } if [[ $flag = "Y" ]]; then i=${i#"##"} i=${i#" "} printf "%s\n" "${i}" fi done < ${file} > ${tmpf} case $help in (Y) case ${doc} in (POD) perldoc ${tmpf} ;; (MAN) MANPATH=${tmpdir}/man man ${base} ;; esac ;; (PS|PDF) case ${doc} in (POD) pod2man ${tmpf} ;; (MAN) cat ${tmpf} ;; esac | groff -man | case ${help} in (PS) cat >${base}.ps ;; (PDF) ps2pdf - ${base}.pdf ;; esac ;; (POD) cp ${tmpf} ${base}.pod ;; (HTML) pod2html ${tmpf} > ${base}.html rm pod2htmd.tmp pod2htmi.tmp ;; esac rm -rf ${tmpdir} return 0 } ## POD_START ## ## =head1 NAME ## ## B - sh function for processing online man page ## ## =head1 SYNOPSIS ## ## [FPATH=/path/to/shdoc] ## ## B I [I] [I] ## ## =head1 DESCRIPTION ## ## Generally, large programs possess big documentation - with books, ## technical papers, MAN pages, etc. Examples include Solaris, ## Oracle, Perl, shells, etc. However, the shell scripts that we write ## every day usually aren't that big, and it's overhead to maintain ## separate documentation. In addition, shell programmers and administrators ## are notorious for not providing documentation. Why not simplify ## the task? ## ## Therefore, it's desirable to maintain online documentation within the ## code, and when code does change, documentation updates exist in only one ## place. This man page describes shdoc, a shell function ## which processes documentation embedded within a shell script. ## ## Perl programmers conveniently embed documentation in Perl scripts using the ## POD format, plain old documentation. The shdoc function uses the perldoc ## utility to process POD formatted documentation embeded in shell ## scripts. In addition, it the function can process embeded documentation ## already in MAN format. Besides viewing the man page online, it can also ## convert the documentation in Postscript or PDF format with groff and ## ps2pdf tools. ## ## =head1 POD / MAN FORMAT - sh STYLE ## ## The documentation is entered in scripts using the POD / MAN format, proceeding ## each line with "## ", where the space can be omitted for empty lines. The beginning ## and the ending of the documentation is marked by POD_START and POD_STOP, or ## MAN_START and MAN_STOP depending on the type of documentation. ## ## shdoc supports splitting documentation, so you can include ## comments and code in between sh style POD format. But usually the documentation ## is included at the end. ## ## Using "##", we differentiate sh style POD from normal shell ## comments, and, also, maintain 100% legal sh code since sh style POD ## are still comment lines. ## ## At run-time, anything after the exit command is not interpreted ## by the shell, so it is possible to include "bare" POD inside sh scripts. ## However, this approach confuses the shell parser. For example, ## the two-line script: ## ## exit 0 ## ) ## ## produces the following error when parsed with "ksh -n", which ## checks the syntax but does not execute: ## ## syntax error at line 2: `)' unexpected ## ## That is why we insist on 100% legal sh syntax. ## ## =head1 EXECUTING shdoc ## ## Execute the shdoc function either from a shell script or from the ## command-line: ## ## shdoc help=y|ps|pdf [doc=pod|man] [file=...] ## ## The default is "help=y", "doc=pod". "help=y" displays a ## man page, "help=ps" generates a Postscript document, and "help=pdf" ## generates a PDF document. ## ## =head1 EXECUTING FROM A SCRIPT ## ## This is a typical example of calling shdoc from a script. Executing: ## ## shdoctest.sh help=y ## ## outputs the man page converted from POD to standard output. ## ## The following lines from within the test script: ## ## my_getopts "$@" ## [[ $HELP = Y ]] && { shdoc file=$0; exit 0; } ## ## sets HELP="Y", calls the shdoc to process the POD, and exits the ## script. The my_getopts function which evaluates the command-line ## was a UnixReview.com Shell Corner subject. See ## ## http://www.unixreview.com/documents/s=1344/uni1042138723500/ ## ## The argument file=$0 instructs shdoc to search the present file ## for POD. Unfortunately, the argument is necessary since $0 inside ## a function in ksh93 is the function name, instead of the calling ## program name. Passing the program name works in most of shells. ## ## Executing: ## ## shdoctest.sh ## ## without "help=y" command-line argument, skip printing the documentation, and ## continue normal program flow. Of course, production scripts may have ## have other command-line arguments. ## ## You don't need to use my_getopts. Any command-line argument processing ## sensing that help should be printed can be used: ## ## [[ $1 = "-h" ]] && { shdoc file=$0; exit 0; } ## ## The above command executes shdoc if argument 1 equals "-h". ## ## So far, the examples have all displayed man pages. ## Sometimes you want to generate PS or ## PDF file for publishing. All you need is to tell the program what you ## want to do, pass it to shdoc function, and your wish be granted. ## ## Here is a one-line example: ## ## [[ $HELP = @(Y|PS|PDF) ]] && { shdoc file=$0 help=$HELP; exit 0; } ## ## =head1 UTILITIES USED AND PASSING THE PATH ## ## shdoc executes correctly only if the function can find the perldoc and ## pod2man utilities, and standard Unix commands. groff is needed for ## creating Postcript documents with "help=ps" option, and ps2pdf is needed ## for converting Postscript to PDF documents when specifying the "help=pdf" ## option. ## ## perldoc and pod2man are part of Perl package; groff is a GNU utility ## while ps2pdf is part of the Ghostcript package. ## ## The function does not set PATH. It is expected the proper PATH is set up ## in the calling program. ## ## =head1 REFERENCES ## ## Wall, Larry, Tom Christiansen, and Jon Orwant Programming Perl ## July 2000, Sebastopol, CA: O'Reilly & Associates, Inc. ## ## Bolsky, Morris, David Korn The New Kornshell Command and Programming ## Language 1995, Upper Saddle River, NJ: Prentice Hall PTR. ## ## =head1 SEE ALSO ## ## "my_getopts _help=y" on http://www.unixlabplus.com/. ## ## =head1 AUTHOR ## ## Michael Wang >, Ed Schaefer. ## ## This is free software. You may copy or redistribute it under the same ## terms as Perl. However, if you modify it, you are required to send the ## modification to the author via email. ## ## =head1 VERSION HISTORY ## ## =head2 version 3.0, 2007-01-26. ## ## =over 4 ## ## =item * ## ## A rewrite: added MAN format; make it portable (renamed from kshdoc to shdoc); ## simplified the code. ## ## =back ## ## =head2 version 2.1, 2003-01-27. ## ## =over 4 ## ## =item * ## ## Added "su bin -c ..." for root user. ## ## =back ## ## =head2 version 2.0, 2003-05-08. ## ## =over 4 ## ## =item * ## ## Use perldoc instead of pod2man - older version of pod2man does not ## support standard input. ## ## =item * ## ## Support file=command, file=function without full path, ## and lack of file= for shdoc itself. ## ## =item * ## ## Support split documentation. ## ## =item * ## ## "show=y" implies "help=n". ## ## =back ## ## =head2 version 1.0, 2002-08-22. ## ## POD_STOP