#!/usr/bin/perl

# converts vim documentation to simple html
# Sirtaj Singh Kang (taj@kde.org)
# Wed Oct  8 01:15:48 EST 1997

# Edited and extended by Dion Nicolaas <dion@nicolaas.net> 

# New in version 2.0:
# - Added Windows NT date command
# - fixed ARGV bug
# - Let Vim do the HTMLizing, just add links afterwards (this adds syntax 
#   highlighting)
# Wed 27-09-2000

# New in version 3.0:
# - Use Perl date
# - Use lowercase html tags to work with vim 6.0
# - Match every keyword that appears in the text
# Tue 25-09-01

use strict;

# Set this to your executable of Vim
my $vimcmd = "d:/bin/vim/vim60aw/gvim.exe";
# Set this to all words you don't want to match, in between **
my $nevermatch = "*is* *as* *end* *section* *various* *case* *put* *help* *starting* ";
# ======================================================================
# Nothing below this line should have to be changed.
# ======================================================================

my $date = gmtime;

my %url = ();

sub readTagFile
{
    my($tagfile) = @_;
    my($tag, $file);

    open(TAGS,"$tagfile") || die "can't read tags\n";

    while (<TAGS>) {
        s/</&lt;/g;
        s/>/&gt;/g;

        /^(.*)\t(.*)\t/;

        $tag = $1;
        ($file= $2) =~ s/.txt$/.html/g;

        $url{$tag} = "<A HREF=\"$file#$tag\">$tag</A>";
    }
    close(TAGS);
}

sub vim2html
{
    # viminfile is the original which will be munched by vim.
    my ($viminfile) = @_;
    my $infile;
    # execute
    # gvim $viminfile -c "so $VIMRUNTIME/syntax/2html.vim" -c "wq" -c "q"
    # to let vim do the HTMLizing
    my (@args) = ($vimcmd, $viminfile, "-c", "\"so \$VIMRUNTIME/syntax/2html.vim\"", "-c", "wq", "-c", "q");
    system(@args) == 0
        or die "system @args failed: $?";
                               
    $infile = "$viminfile.html";
    my $outfile;

    open(IN, "$infile") || die "Couldn't read from $infile.\n";

    ($outfile = $infile) =~ s/.*\///g;
    # infile is called .txt.html
    $outfile =~ s/\.txt\.html$//g;

    open(OUT, ">$outfile.html")
            || die "Couldn't write to $outfile.html.\n";

    my $dontmatch = "";     # tags not to match in this paragraph
    my $currentlabel = "";  # used to build $dontmatch
    # Replace applicable parts
    while (<IN>) {
        # Change the title and add an H1
        s/<title>.*<\/title>/<title>Vim documentation: $outfile<\/title>/g;
        s/<pre>/<h1>Vim documentation: $outfile<\/h1><hr><pre>/g;
        # Add bottom line
        s/<\/pre>/<\/pre><hr><p><i>Generated by vim2html 3.0 on $date<\/i><\/p>/g;
        # We don't want to link to the section we're reading, so we remember
        # where we are.
        if (m/\*[^ *]+\*/) {   # label in this line?
            # remember it
            $currentlabel .= $_;
            $dontmatch = $nevermatch . $currentlabel;
        } else {
            # first line of this section
            $currentlabel = "";
        }
        # replace all applicable words with a link
        chomp;
        my $out = "";   # we'll build the output in here.
    REPLACE:
        while (length $_ ) {
            # copy various pieces of line to $out, changing them into
            # links where appropriate. The order here is significant, as we
            # don't want to touch e.g. HTML tags.

            # copy leading spaces
            if (s/^(\s+)//) {
                $out .= $1;
                next REPLACE;
            }
            # copy html tags
            if (s/^(<[^>]+>)//)
            {
                $out .= $1;
                next REPLACE;
            }
            # copy keywords in **
            if (s/^(\*[^| ]+\*)//)
            {
                $out .= $1;
                next REPLACE;
            }

            # keywords in ""
            # Mostly appear in sentences like: 'the "/" command ...'
            # So we replace them almost always with a link.
            if (s/^\&quot;([^| ]+)\&quot;//) {
                my $tag = $1;
                # don't link when it appears in $dontmatch
                my $skip = ($dontmatch =~ m/\*\Q$tag\E\*/);
                if ($url{$tag} and not $skip) {
                    $out .= "\&quot;$url{$tag}\&quot;";
                }
                else {
                    $out .= "\&quot;$tag\&quot;";
                }
                next REPLACE;
            }    
            # keywords in ||
            # We always replace them with a link, if the link exists.
            if (s/^\|([^| ]+)\|//) {
                if ($url{$1}) {
                    $out .= "\|$url{$1}\|";
                }
                else {
                    $out .= "\|$1\|";
                }
                next REPLACE;
            }
            # plain word
            # We replace them if not in $dontmatch and longer than 1 char, to
            # prevent changing a and I and many others
            if (s/^([^ |<"]+)//) {
                my $tag = $1;
                my $skip = ($dontmatch =~ m/\*\Q$tag\E\*/);
                # no one char hits (includes &gt; and &lt;)
                if (length($tag) > 1 and
                        $tag ne "&lt;" and
                        $tag ne "&gt;"
                            and
                        $url{$tag}
                            and not $skip) {
                    $out .= "$url{$tag}";
                }
                else {
                    $out .= $tag;
                }
                next REPLACE;
            }
            # unmatched <"|, copy.
            if (s/^([|<"])//) {
                $out .= $1;
                next REPLACE;
            }

            # NOTREACHED
            die "Nothing matched? line = \"$_\"\n";
        }
        # *keyword* is only replaced now, to make skipping them earlier easier
        $out =~ s/\*([^ *]+)\*/\*<a name="$1">$1<\/a>\*/g;
        print OUT "$out\n";
    }
    # infile is intermediate, can now go
    unlink $infile;
}

sub usage
{
die<<EOF;
Vim2HTML 3.0 (Mon 25-09-2001)
vim2html.pl: converts vim documentation to HTML.
usage:
    vim2html.pl <tag file> <text files>
    
    <text files> should have the extension .txt
    The output files will have the extension .html
EOF
}

# main

if ($#ARGV < 1) {
    print "ERROR: too few arguments\n";
    usage();
}

print "Processing tags...\n";
readTagFile($ARGV[0]);

foreach my $file (1..$#ARGV) {
    print "Processing ".$ARGV[ $file ]."...\n";
    vim2html($ARGV[$file]);
}
