#!/usr/bin/bash
#
# asciidoctool -- Frontend for asciidoc
#
# Simplifies creation of HTML/PDF-files from plain text files.  Use
#     asciidoctool --help
# for usage information.
#
# Under Windows/Cygwin install MikTeX 2.8 (http://www.miktex.org/) and don't
# Cygwin's unsupported tetex. Make sure <.../miktex/bin> occurs before
# <C:\Cygwin\bin> in PATH.
#
# CSS/STYLESHEETS
#
#     $ asciidoc -a stylesdir=/path/to/adoc-themes/stylesheets-a theme=NAME source.txt
#
# RESOURCES
#
# http://tomayko.com/src/adoc-themes/[Asciidoc Themes]
# 
# http://francisshanahan.com/index.php/2010/setup-asciidoc-fop-pygment-on-windows/[How
# to Setup AsciiDoc, Pygment and FOP on Windows for Beautiful PDF and XHTML
# Documentation]
#
# http://www.stevestreeting.com/2010/03/07/building-a-new-technical-documentation-tool-chain/[Building
# a new technical documentation tool chain]
#
########
# $Compile: make -C ../.. install; asciidoctool -X sample/sample.text$

source libutils.sh                         # basename, dirname, namename, stack

script=$(basename $0) version='0.2.3'
scriptdir="$(dirname "$0")"

########################################################################
# Environment / Options
#

arguments="$*"
optall=0 optauto=0 optkeep=0 optclean=0 optlang=
optquiet=0 optverbose=0 optstyle='default'
cmds=() intermed=(NUL)
attribs="-a toc -a footer"

function ok    { set +x; quack "done"; exit 0; }
function die   { set +x; noise "$1"; exit -1; }
function noise { ((optquiet)) || ((!$#)) || echo "${PS4}${1}"; }
function quack { ((optverbose)) && noise "$@"; }

noise "$script $arguments"

while [ $# -gt 0 ]
do
    case "$1" in
        -l) shift; optlang="$1"; shift;;
        -m) attribs+=" -a asciimath"; shift;;
        -q|--quite) optverbose=1; shift;;
        -v|--verbose) optverbose=1; shift;;
        --keep) optkeep=1; shift;;
        --auto) optauto=1; shift;;
        -A|--all) optall=1; shift;;
        -H|--html)
            cmds=('do-html' "${cmds[@]}")
            shift;;
        -P|--pdf)
            cmds=('do-latex' 'do-pdf-using-pdflatex' 'do-simple-clean' "${cmds[@]}")
            shift;;
        -a)
            # E.g. "-a data-uri" bettet Binärdaten wie Bilder über
            # Base64-Kodierung in die Webseite ein (Data-URI,
            # <http://en.wikipedia.org/wiki/Data_URI_scheme>). So wächst die
            # Datenmenge zwar um ca. 30% an, dennoch kann die Seite insgesamt
            # oft schneller angezeigt werden da nur eine Datei geladen wird.
            shift
            attribs+=" -a $1"
            shift
            ;;
        --tpage)
            cmds=('do-tpage' "${cmds[@]}")
            shift
            ;;
        -X|--improve-xhtml11)
            optstyle=default
            cmds=('do-temp-css' 'do-tpage' "${cmds[@]}" 'do-html')
            noise "implying --tpage --html"
            shift
            ;;
        --clean)
            optclean=1
            cmds=('do-simple-clean' 'do-real-clean' "${cmds[@]}")
            shift
            ;;
        --verbose)
            attribs+=" --verbose"
            shift
            ;;
        --version)
            echo "$0 $version"
            exit 0
            ;;
        --)
            shift
            ;;
        -*)
            cat <<EOF 1>&2; die;;
USAGE
    $script [OPTION]... [TEXTFILE]

DESCRIPTION

Implements  toolchains for  creating HTML  and  PDF documents  from plain  text
files, with  indexes, headers, footers  and table of contents.

OPTIONS

    -l LANG
        Set language attribute. Default is to determine character encoding of
        TEXTFILE and set LANG accordingly.

    -m
        Set "-a asciimath".

    -H, --html
        Create XHTML 1.1 (default).

    -a ATTR
        Set asciidoc attribute, e.g. "-a data-uri", "-a numbered".

    -P, --pdf
        Create (La)TeX and PDF.

    -A, --all
        All output formats (alias "--html --pdf").

    --tpage
        Filter TEXTFILE by "tpage" program (Perl Template Toolkit).

    -X, --improve-xhtml11
        Create a temporary css-file in the directory of TEXTFILE that carefully
        overloads some stlyes from asciidoc's "xhtml11.css". You must place the
        following into the document header, before the first heading, to apply
        the temporary css-file created by $script:
            [% BLOCK preamble %]
            PREAMBLE.  Your abstract...
            [% END %]
            [% PROCESS asciidoctool.css %]
        The code will be placed into the body-section of the HTML-file.
        Implies --tpage, --html.

    --auto
        Find and process "*.text" and "*.txt" files in the current directory.

    --keep
        Keep some of the intermediate files (e.g. ".tex").

    --clean
        Remove all target files (intermediate and HTML+PDF).

    --version
        Print version.

REQUIREMENTS

    asciidoc, a2x, pdflatex, tpage, libutils.sh

ABOUT

Maintained at <http://www.visualco.de>.

EOF

        *)
            [[ -z "$textfile" ]] || die "Only one file argument allowed."
            textfile="$1"
            shift;;
    esac
done

((${#cmds})) || {
    cmds=('do-html')
    noise "implying --html"
}
(( optkeep)) || cmds=("${cmds[@]}" 'do-simple-clean')
((optverbose)) && rm="rm -v" || rm=rm

if ((optall)); then
    "$0" --html "$textfile" &&
    "$0" --pdf "$textfile" &&
    ok || die
fi

#########################
# Get textfile or, if "--auto" specified, find/process all text files in the
# working directory.
#
# Unless "-l" is given on the commandline autodetect language (encoding) using
# the "file" utility, which is a pretty accurate method. Note that you cannot
# determine the character encoding, only deduce it. That's because there's
# considerable overlap on most code pages, so the only way to figure out if a
# specific encoding was used is to find a usage that only makes sense for that
# encoding.
#
# WARNING: Asciidoc requires the encoding-attribute to be set before the
#          document title, or it uses UTF-8.

function gettextfile
{
    [ -z "$1" ] || textfile="$1"
    textdir=$(dirname "$textfile")
    #textfile=$textdir/$(basename "$textfile")            # full name + ext
    textname=$textdir/$(namename "$textfile")
    textsuffix=$(extensionname "$textfile")
    textbase=$(basename "$textfile" $textsuffix)
    if [ -z "$optlang" ]; then
        file -ki "$textfile" | grep -qi 'ISO-8859-1' && optlang=de
    fi
    [[ $textsuffix = '.' ]] && textsuffix=
    quack "using text file '$textname$textsuffix' ($optlang)"
}

if [ -z "$textfile" ]; then
    # No input file. With --auto or --clean recurse on known file names and
    # types.
    ((optclean)) && optauto=1
    if ((optauto)); then
        for pattern in '*.text' '*.txt' README MOTIVATION; do
            while IFS= read -r -u3 -d $'\0' textfile; do
                if [[ -n $textfile ]]; then
                    noise found "'${textfile}'"
                    set -x
                    "$0" ${arguments:--A} "$textfile"
                    set +x
                fi
            done 3< <(find . -maxdepth 1 -type f -name "$pattern" -print0)
        done
        exit 0
    else
        cat <<EOF >&2
Missing input file ($script $version).
Try '--auto' or '--help'
EOF
        exit 1
    fi
else
    gettextfile
fi

if [ -n "$optlang" ]; then
    case $optlang in
        de)
            attribs+=" -a encoding=ISO-8859-1";;
    esac
    attribs+=" -a lang=$optlang"
fi

########################################################################
# Program
#
# Loop over all output format tokens and run the toolchains.
#

GREP_OPTIONS=
exec > >(grep -v 'set .x' | tee "$0.log") 2>&1
{
    while [ ${#cmds[*]} -gt 0 ]
    do
        quack "${cmds[0]}"
        export PS4="    ${PS4}"
        case "${cmds[0]}" in
            ####################################
            # asciidoctool.css
            #
            do-temp-css)
                tempcss="${textdir}/asciidoctool.css"
                noise "created temporary file '$tempcss'"
                case "$optstyle" in
                    default)
                        cat <<-EOF > "$tempcss"
                    [%# -*-template-*- %]

                    [% BLOCK before_preamble %]
                    ifdef::basebackend-html[]
                    ++++++++++++++++++++++++++++++++++++++
                    <style type="text/css">
                      body { font-size:100%; font-family: Verdana, sans-serif; }
                      h1 { letter-spacing:2pt; }
                      h2 { letter-spacing:1pt; }
                      h3, h4 { letter-spacing:0.5pt; }
                      h5 { letter-spacing:0.5pt; font-weight:normal; font-size: 100%; }
                      em { color:darkslateblue;; }
                      tt { color:darkblue; }
                      div#toc {
                        margin:2em 2.5em 1.5em 2.5em;
                        padding:1em 2em 1.5em 2em;
                        border:2px solid silver; width:70%;
                      }
                      div#header { text-align:center; }
                      span#author { font-weight:normal; font-size:100%; }
                      div#toctitle {
                        padding:0; margin:0; line-height:2;
                        letter-spacing: 3pt;
                      }
                      div.toclevel1 {
                        font-weight:bold;
                        text-align:left; line-height:2;
                        margin-top: 0.5em;
                      }
                      div.toclevel2, div.toclevel3, div.toclevel4 {
                        text-align:left; line-height:1.3;
                      }
                      div.paragraph {
                        text-align:justify; color:black;
                      }
                      div.paragraph, div.dlist, div.olist, div.literalblock {
                        line-height:1.5;
                        margin-left:1.5em;
                      }
                      div.sidebar-content > div.paragraph {
                        padding:1em 1.5em 1em 1.5em;
                        font-size:100%; line-height:1.2; width:100%;
                      }
                      div.quoteblock > div.paragraph {
                        margin-left:5em;
                      }
                      div.quoteblock-content > div.paragraph {
                        width:70%; line-height:1.2;
                      }
                      div.literalblock {
                        margin-top:0.7em;
                        margin-bottom:0.7em;
                        width:90%;
                      }
                      div.literalblock > div.content {
                        padding:0.5em 1.5em 0.5em 1.5em;
                        background-color:lavender; line-height:1;
                      }
                      div.listingblock > div.content {
                        border-top:1px dashed silver;
                        border-right:2px solid darkgray;
                        border-bottom:2px solid darkgray;
                        border-left:1px dashed silver;
                        padding:0.5em 1.5em 0.5em 1.5em; width:100%;
                      }
                    </style>
                    <div style="margin:2em 12% 3em 12%; line-height:2; letter-spacing:1pt;">
                    ++++++++++++++++++++++++++++++++++++++
                    endif::basebackend-html[]
                    [% END %]

                    [% BLOCK after_preamble %]
                    ifdef::basebackend-html[]
                    pass::[</div>]
                    endif::basebackend-html[]
                    [% END %]

                    [% PROCESS before_preamble %]
                    [% PROCESS preamble %]
                    [% PROCESS after_preamble %]

                    EOF
                        ;;
                esac
                intermed=("$temptextfile" "$tempcss" "${intermed[@]}")
                ;;

            ####################################
            # ${textfile} | tpage > ${textname}.tmp = new ${textfile}
            #
            do-tpage)
                temptextfile="${textdir}/${textbase}.tmp"
                set -x
                tpage --include_path="$textdir" --include_path="$scriptdir" "$textfile" > "$temptextfile" || die
                set +x
                #intermed=("$temptextfile" "${intermed[@]}")
                gettextfile "$temptextfile"
                quack "ok"
                ;;

            ####################################
            # ${textfile} | asciidoc > ${textname}.html (XHTML 1.1)
            #
            do-html)
                set -x
                asciidoc $attribs -a badges "${textname}${textsuffix}" || die
                set +x
                noise "$(ls -la "${textname}.html")"
                quack "ok"
                ;;

            ####################################
            # ${textname}.txt  | asciidoc > ${textname}.tex
            # ${textname}.text | tpage | asciidoc > ${textname}.tex
            #
            # WARNING: the latex backend is experimental in asciidoc.
            #
            # asciidoc 8.5.3 prints errors
            #     asciidoc: WARNING: missing template section: [abstractblock]
            #     asciidoc: FAILED: [tabledef-default] missing section: [tabletags-header]
            #
            # As a quick solution add to /etc/asciidoc/latex.conf: between
            # [abstract] and [dedication]:
            #     [abstractblock]
            # between [tabletags-asciidoc] and [tabletags-default]:
            #     [tabledef-default]
            #     [tabletags-header]
            #
            do-latex)
                set -x
                asciidoc $attribs --unsafe --backend=latex "$textname$textsuffix"
                set +x
                # Heal bugs (http://www.methods.co.nz/asciidoc/latex-bugs.html).
                sed -i 's/SPURIOUS TEXT//g' "${textname}.tex"
                noise "$(ls -la "${textname}.tex")"
                quack "ok"
                ;;

            ####################################
            # ${textname}.tex | pdflatex > ${textname}.pdf
            #
            # Tested with MikTeX do-pdf-using-pdflatex.
            #
            do-pdf-using-pdflatex)
                set -x
                pdflatex -c-style-errors --interaction=batchmode "${textname}.tex" || die
                set +x
                intermed=("${textbase}.tex" "texput.log" "${intermed[@]}")
                noise "$(ls -la "${textname}.pdf")"
                quack "ok"
                ;;

            ####################################
            # ${textname}.txt | asciidoc > ${textname}.xml | a2x > ${textname}.pdf
            #
            # Requirements:
            #
            #     asciidoc 8.5.x xmllint xsltproc dblatex
            #
            # AsciiDoc's a2x does the grunt work. It will generate XHTML
            # (chunked and unchunked), PDF, man page, HTML Help and text file
            # outputs from an AsciiDoc text file. a2x deploys CSS and icons.
            #
            # http://xpt.sourceforge.net/techdocs/nix/tool/asciidoc-usg/ascu04-UsingDocBooktoolchain/
            #
            do-pdf-using-a2x)
                a2x --version
                set -x
                a2x -f pdf $textname$textsuffix || die
                set +x
                noise "$(ls -la "${textname}.pdf")"
                quack "ok"
                ;;

            ####################################
            # Remove intermediate files and XHTML/PDF target files.
            #
            do-simple-clean)
                $rm -vf "${intermed[@]}"
                find -regextype posix-egrep -type f -regex \
                    ".*/${textbase}\\.(aux|idx|log|out)$" -exec $rm "{}" \;
                ;;

            do-real-clean)
                find -regextype posix-egrep -type f -regex \
                    ".*/${textbase}\\.(tex|pdf|html)$" -exec $rm "{}" \;
                ;;

            *)
                noise "ERROR: unknown format '${cmds[0]}'"
                exit -1
                ;;
        esac
        cmds=(${cmds[@]:1})
    done
}

rm -f NUL
ok

# Local Variables:
# coding: iso-8859-1-unix
# fill-column: 79
# End:

# asciidoctool ends here