#!/usr/bin/perl #vim:et:ts=4: # 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 # (version 2.0, 3.0, 3.1, 3.3, 3.3.1) # Made into a CGI by Thorsten Maerz # (version 3.2) # 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 # # New in version 3.1: # - Option for HTML level # - Do replace < and > when no HTML # Thu 27-09-01 # New in version 3.2: # - works as cgi script # Thu 27-09-01 # New in version 3.3: # - More nevermatch words # - Remove modelines from files # - improved Perl HTMLising # Fri 28-09-01 # New in version 3.3.1: # - use vims colorschemes (quickndirty) use strict; # set $isCGI to 1 to run as a cgi-script my $isCGI = 1; # Set this to your executable of Vim #my $vimcmd = "d:/bin/vim/vim60/gvim.exe"; my $vimcmd = "vim"; # Set this to all words you don't want to match, in between ** my $nevermatch = "*is* *as* *end* *section* *various* *case* *put* *help* *starting* *go*"; # ====================================================================== # Nothing below this line should have to be changed. # ====================================================================== my %syn; my $CGIfilename; my $CGIsearch; my $CGIbasename; if ($isCGI) { use Fcntl; use POSIX qw(tmpnam); use CGI qw/:standard/; ($CGIbasename = $0) =~ s#.*/([^/]+)#$1#; } my $date = gmtime; my %url = (); my %file = (); my $opt_htmlising = 2; my $progID = "vim2html.pl 3.2"; sub readTagFile { my($tagfile) = @_; my($tag, $file); open(TAGS,"$tagfile") || die "can't read tags\n"; while () { s//>/g; /^(.*)\t(.*)\t/; $tag = $1; if ($isCGI) { $file{$tag}= $2; # $url{$tag} = "$tag"; $url{$tag} = "$tag"; } else { ($file{$tag}= $2) =~ s/.txt$/.html/g; $url{$tag} = "$tag"; } } close(TAGS); } sub vim2html { # viminfile is the original which will be munched by vim. my ($viminfile) = @_; my $infile; $infile = "$viminfile.html"; if ($opt_htmlising < 2) { open (IN, "$viminfile") or die "Can't read input file $viminfile: $?"; if ($isCGI) { # try new temporary filenames until we get one that didn't already # exist; the check should be unnecessary, but you can't be too careful do { $infile = tmpnam() } until sysopen(INTER, $infile, O_RDWR|O_CREAT|O_EXCL); } else { open(INTER, ">$infile") or die "Can't write intermediate file $infile: $?"; } if ($opt_htmlising == 1) { # write header print INTER "
";
        }
        my ($example, $examplecount) = 0;
        my $curly = 0;
        # Create a "safe" file
        while () {
            # Replace tabs with spaces (ts=8)
            my $pos;
            while (($pos = index($_, "\t")) != -1) {
                $pos %= 8;
                if ($pos == 8) { $pos = 0; }
                my $padding = substr("        ", 0, 8 - $pos);
                s/\t/$padding/;
            }
            s//>/g;
            if ($opt_htmlising == 1 || $isCGI) {
		# bugs
		# intro.txt:*CTRL-{char}* 
		
                # do syntax highlighting in Perl
                s/^\<$//;                                                    # only <
                s/^\<(\s)/ $1/;                                              # leading <
                s/\>$//      unless /\</;                                 # trailing >

                s/(.*)~$/$syn{'Header'}$1$syn{'end'}/;                          # trailing ~

                s/^[-=]+$/$syn{'SectionDelim'}$&$syn{'end'}/g;                  # ===== or ----
                # dont highlight ^*word* : wouldnt be recognized as jump target later
                s/ \*[^ *]*\*/$syn{'HyperTextEntry'}$&$syn{'end'}/g;            # *Entry*
                s/(?
                s/(?$&<\/b>/g;                  # bold "word"

            }
            print  INTER $_;
        }
        if ($opt_htmlising == 1) {
            # write footer 
            print INTER "
"; } close(INTER); } else { # execute # gvim $viminfile -c "so $VIMRUNTIME/syntax/2html.vim" -c "wq" -c "q" # to let vim do the HTMLizing my $socmd; if ($ENV{'OSTYPE'} =~ /linux/i) { $socmd = "so \$VIMRUNTIME/syntax/2html.vim" } else { $socmd = "\"so \$VIMRUNTIME/syntax/2html.vim\"" } my (@args) = ($vimcmd, $viminfile, "-c", $socmd, "-c", "wq", "-c", "q"); print @args; system(@args) == 0 or die "system @args failed: $?"; } 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; if ($isCGI) { open(OUT, ">-"); } else { 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 () { # Change the title and add an H1 s/.*<\/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 <tt>$progID<\/tt> on $date<\/i><\/p>/g; # Remove modeline s/ vim:.*:\s*$//; # Links # 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/^\"([^| ]+)\"//) { 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 .= "\"$url{$tag}\""; } else { $out .= "\"$tag\""; } 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 > and <) if (length($tag) > 1 and $tag ne "<" and $tag ne ">" 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; $progID (Thu 27-09-2001) Converts vim documentation to HTML. usage: vim2html.pl [-v{0|1|2}] <tag file> <text files> -v0 means no HTMLising (apart from links) -v1 means basic HTML -v2 means let Vim do the HTMLising. Default is -v2. <text files> should have the extension .txt The output files will have the extension .html EOF } # CGI / HTML header and footer sub CGIStartHTML { my $color=param('cs'); print <<EOF; Content-type: text/html <HTML> <HEAD><TITLE>Vim online doc: $CGIfilename

VimDoc: $CGIfilename

FAQ
select color
help
manual
PS / PDF
single file
VimOnline
Vim.org
search
VimDoc

EOF
}

sub CGIEndHTML
{
$CGIsearch=param('search') || '';
my $color=param('cs');
print <

Main help    Table Of Contents

Automatically generated by $progID on $date

EOF } sub searchTag { my( $file, $name ); my $CGIsearch = shift; my $count; foreach (keys(%url)) { if (/$CGIsearch/i) { $count++; print "$file{$_} : $url{$_}\n"; } } $count = $count || 'no'; print "\n
$count hits"; } # main if ($isCGI) { my $pipecmd='cvs -z9 -d:pserver:anonymous@cvs1:/cvsroot/vim co -p vim/runtime/doc/'; $opt_htmlising=0; $CGIfilename=param('page') || 'help.txt'; $CGIfilename = 'search "'.param('search').'"' if param('search'); if (param('cs') eq 'blue') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#000088" text="#f8fcf8" ' .'LINK="#b8bcb8" ' .'VLINK="#888c88" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'elflord') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#000000" text="#00fcf8" ' .'LINK="#40fcf8" ' .'VLINK="#30aca8" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'evening') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#303030" text="#f8fcf8" ' .'LINK="#40fcf8" ' .'VLINK="#30aca8" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'koehler') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#000000" text="#f8fcf8" ' .'LINK="#40fcf8" ' .'VLINK="#30aca8" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'morning') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#e0e4e0" text="#000000" ' .'LINK="#008888" ' .'VLINK="#006868" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'murphy') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#000000" text="#90ec90" ' .'LINK="#00fcf8" ' .'VLINK="#00aca8" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'pablo') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#000000" text="#f8fcf8" ' .'LINK="#00c0c0" ' .'VLINK="#008080" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'peachpuff') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#f8d8b8" text="#000000" ' .'LINK="#008888" ' .'VLINK="#006868" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'printman') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#f8fcf8" text="#000000" ' .'LINK="#000000" ' .'VLINK="#a8aca8" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'ron') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#000000" text="#00fcf8" ' .'LINK="#00fcf8" ' .'VLINK="#00aca8" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'shine') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#f8fcf8" text="#000000" ' .'LINK="#008888" ' .'VLINK="#006868" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'torte') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#000000" text="#c8ccc8" ' .'LINK="#00fc00" ' .'VLINK="#00ac00" ' ; $syn{'end'} = ''; } elsif (param('cs') eq 'zellner') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#f8fcf8" text="#000000" ' .'LINK="#0000f8" ' .'VLINK="#0000a8" ' ; $syn{'end'} = ''; } else { # (param('cs') eq 'default') { $syn{'Header'} = ''; $syn{'SectionDelim'} = ''; $syn{'Example'} = ''; $syn{'HyperTextJump'} = ''; $syn{'HyperTextEntry'} = ''; $syn{'Option'} = ''; $syn{'Special'} = ''; $syn{'color'} = 'bgcolor="#ffffff" text="#000000" ' .'LINK="#008888" ' .'VLINK="#006868" ' ; $syn{'end'} = ''; } CGIStartHTML(); readTagFile($pipecmd.'tags|'); if (param('search')) { searchTag(param('search')); } else { vim2html($pipecmd.$CGIfilename.'|'); print "

"; } CGIEndHTML(); } else { if ($#ARGV < 1) { print "ERROR: too few arguments\n"; usage(); } my $nextarg = 0; my $more = 0; do { print "$ARGV[$nextarg]\n"; $more = 0; if ($ARGV[$nextarg] eq "-h0") { $opt_htmlising = 0; # no html $nextarg++; $more = 1; } elsif ($ARGV[$nextarg] eq "-h1") { $opt_htmlising = 1; # basic html $nextarg++; $more = 1; } elsif ($ARGV[$nextarg] eq "-h2") { $opt_htmlising = 2; # Vim html $nextarg++; $more = 1; } } while ($more); print "Processing tags...\n"; readTagFile($ARGV[$nextarg]); $nextarg++; foreach my $file ($nextarg..$#ARGV) { print "Processing ".$ARGV[ $file ]."...\n"; vim2html($ARGV[$file]); } }