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

2 Comments

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.

Leave a comment

About Diab Jerius

user-pic I blog about Perl.