Automating POD previewing
I find it difficult to review documentation written in a markup language. I need to see that final pretty rendition of it as a manual page, PDF file or HTML web page before I can get a feeling if the thing makes sense. I also like to see that final rendition while I'm writing the document, and switching between the editor and the command line to render the documentation is painful.
Luckily most modern OS's provide a means of monitoring filesystems for changes. I've put together a rather simple bash script which uses Linux's inotify system and App::Pod2CpanHtml to generate HTML output whenever I save a .pod
or .pm
file. I use Firefox with the Auto Reload plugin to view the files. For grins the script also has an option to pop up a desktop notification when things change, so I know something has happened.
The shell script follows. This could easily be rewritten in Perl using the File::ChangeNotify module to make it more cross-platform.
#!/bin/bash
trap 'cleanup' EXIT
usage () {
local exitval=$1
cat <<EOF
$0 [options]
Automatically regenerate HTML from .pod or .pm files.
-c remove output directory upon exit
-C don't remove output directory upon exit
-d DIR directory to monitor. [$MONITORDIR]
-n send a desktop notification when a file changes
-o DIR the output directory. required. ${OUTPUTDIR:+[$OUTPUTDIR]}
-v be verbose
EOF
test -n "$exitval" && exit $exitval
}
cleanup () {
test ${clean:-0} -eq 1 \
&& test -n "$OUTPUTDIR" \
&& rm -rf "$OUTPUTDIR'"
}
wait_for_change () {
inotifywait \
-r \
-q \
-m \
-e close_write \
--format '%w %f' $1
}
loop () {
local output_dir
shopt -s extglob
wait_for_change $MONITORDIR | while read dir file
do
[[ "$file" = @(*.pm|*.pod) ]] || continue
output_dir=$OUTPUTDIR/$dir
test -d "$output_dir" || mkdir -p "$output_dir"
pod2cpanhtml \
--no-index "$dir/$file" \
"$output_dir/${file%.*}.html"
test $notify -eq 1 \
&& notify-send "$dir/$file"
test $verbose -eq 1 \
&& echo "$dir/$file"
done
}
OUTPUTDIR=
clean=
notify=0
verbose=0
MONITORDIR=lib
while getopts cCd:hno:v arg
do
case "$arg" in
c ) clean=1
;;
C ) clean=0
;;
d ) MONITORDIR=$OPTARG
;;
h ) usage 0
;;
n) notify=1
;;
o ) OUTPUTDIR=$OPTARG
;;
v ) verbose=1
;;
?) exit 1
;;
esac
done
if [ -z "$OUTPUTDIR" ]; then
echo >&2 "$0: missing -o option"
exit 1
fi
if [ $notify -eq 1 ] ; then
if ! command -v notify-send >& /dev/null; then
echo >&2 "can't notify; unable to find notify-send"
exit 1
fi
fi
loop
I usually use Tk::Pod for this when I write a module. It also gives me warnings if the POD is incorrect.
And I use Pod::Server (when it's working, which is not right now), and if not fall back to the very simple but reliable
Pod::Webserver.