#!/usr/bin/env python # convert CLAWPACK source code, data files, READMEs, etc. into html. # for example, # clawcode2html filename.f # generates # filename.f.html # If filename.f.html already exists, you will be prompted before # overwriting unless the -f or --force flag is used, e.g. # clawcode2html --force filename.f # # Based on mathcode2html.py from # http://www.amath.washington.edu/~rjl/mathcode2html # with some modifications for CLAWPACK. # # The environment variable CLAW must be properly set to the root # of the claw directory before using this script. # # Most of code is put into
 environment.
# Any comments enclosed by begin_html and end_html are taken out 
# of the 
 environment and indented properly (using a table) 
# to match the surrounding code.

# By default, the html comments are offset in blue font, except if the 
# input file has extension .txt or no extension, in which case it's 
# left as black.  The default_color can be changed below.
# Also, the begin_html line may contain [color: red] for example,
# to determine the color of this comment.

# You may modify the recognized extensions and comment characters below.

# Allows many latex commands in comments if jsMath is used on webpage.
# In this case make sure the variable jsMathScript is properly set below.
# If you don't want to include a call to the jsMath script on the html
# page, invoke mathcode2html with the --nojsmath option.


#---------------------------------------------------------------------------
# Copyright (C) 2008   Randall J. LeVeque 
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.  
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details,
#     http://www.gnu.org/licenses/
#---------------------------------------------------------------------------


import sys,os,glob
import string,re
import time
from optparse import OptionParser

# parse command line arguments:
parser = OptionParser()
parser.add_option("-f", "--force",
                  action="store_true", dest="forced", default=False,
                  help="force action even if it overwrites html file")
parser.add_option("--nojsmath",
                  action="store_false", dest="usejsMath", default=True,
                  help="don't include call to jsMath script in html")
parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose", default=True,
                  help="don't print status messages to stdout")
parser.add_option("--noheader",
                  action="store_false", dest="header", default=True,
                  help="suppress printing header at top of html page")

(options, infiles) = parser.parse_args()

forced = options.forced
usejsMath = options.usejsMath
verbose = options.verbose
header = options.header


# CLAWPACK environment variables:

try:
    clawdir = os.getenv('CLAW')  # assumes environment variable set properly
except:
    print "CLAW environment variable not set"
    print "You need to run setenv.py before setup.py"
    sys.exit(1)

if clawdir == None:
    print "CLAW environment variable not set"
    print "You need to run setenv.py before setup.py"
    sys.exit(1)


# Create addresses for links on html pages.
# change the lines below if you want to point to a webpage home instead
# of the local file system  (e.g.  clawaddr = "http://www.mywebpage/claw")


clawaddr = 'file://%s' % os.getcwd()


# Set comment characters for different programming languages:
# Augment or modify as desired.
commentchar = { '.f'  : ['!', '#'], \
                '.m'  : '%', \
                '.py' : '#', \
                '.data' : ['#','=:'], \
                '.txt': None, \
                ''    : None}

firstfort = ['c','*','C','!']   # valid fortran comment char's in col. 1

leadingindent = ''    # additional indentation for webpage, if desired

default_color = 'blue'

try:
    infiles.remove('clawcode2html.py')  # can't apply this code to itself!
except:
    pass

for infilename in infiles:

    # check if this is a code file of a recognized language.
    ext = os.path.splitext(infilename)[1]
    
    if not commentchar.has_key(ext):
        print "  "
        print "  Warning: Unrecognized extension, will proceed"
        print "           with no replacement of comment characters"
        commentchar[ext] = None 
    
    
    # open input and output files:
    #-----------------------------
    
    try:
        ifile = open(infilename,'r')
    except:
        print "File not found:", infilename
        sys.exit(1)
    
    
    outfilename = infilename + '.html'
    if (glob.glob(outfilename) != []) & (not forced):
        sys.stdout.write('  OK to overwrite %s?  '  %  outfilename)
        answer = raw_input()
        if answer not in ['y','Y','yes']:
            print '  Aborting!'
            sys.exit(1)
    
    ofile = open(outfilename,'w')
    
    
    # start creating html file:
    #--------------------------
    
    if verbose:
        print '  Converting ', infilename, ' to ', outfilename

    
    ofile.write('\n  %s \n'  % outfilename)

    
    # determine time and reformat:
    time1 = time.asctime()
    year = time1[-5:]
    day = time1[:-14]
    hour = time1[-13:-5]
    creationtime = day + year + ' at ' + hour

    # put full file name with path into a comment for future reference:
    fullinfilename = os.path.join(os.getcwd(),infilename)
    ofile.write('\n\n'  % fullinfilename)
    ofile.write('\n\n'  % creationtime)
    
    if header:
        ofile.write(
           """
           
           
           """)
    
        #ofile.write('
\n') ofile.write('\n' % outfilename) ofile.write('
\n') ofile.write('  %s clawcode2html\n'\ % clawaddr) ofile.write('  
\n') ofile.write(' Source file:   %s \n' \ % (infilename,infilename)) ofile.write('
\n') ofile.write(' Directory:   %s \n' % os.getcwd()) ofile.write('
\n') ofile.write(' Converted:   %s \n' % creationtime) ofile.write('
\n') ofile.write('  This documentation file will \n') ofile.write('not reflect any later changes in the source file. \n') ofile.write('
\n') ofile.write('

\n') if usejsMath: # jsMath stuff: (delete if you don't want jsMath for latex commands) # Set jsMathScript to the file or URL of the java script load.js. jsMathScript = "%s/doc/load.js" % clawaddr ofile.write(" \n") ofile.write(" \n" % jsMathScript) ofile.write(""" $\phantom{******** If you see this on the webpage then the browser could not locate *********}$
$\phantom{******** jsMath/easy/load.js or the variable root is set wrong in this file *********}$
\n""") # define any latex macros that you want to use in jsMath: ofile.write(""" $\\newcommand{\\vector}[1]{\\left[\\begin{array}{c} #1 \\end{array}\\right]}$ $\\newenvironment{matrix}{\\left[\\begin{array}{cccccccccc}} {\\end{array}\\right]}$ $\\newcommand{\\A}{{\\cal A}}$ $\\newcommand{\\W}{{\\cal W}}$ \n""") # # end of jsMath stuff #---------------------------------------------------------------------- # start writing input file to output file... # code is in pre-formatted environment: ofile.write('

\n')
    
    insidehtml = 0;   # set to 1 when we're processing html comments
    lineno = 0;       # line number counter for error message
    
    for line in ifile:
    
        lineno += 1
    
        if string.count(line,"begin_html"):
            regexp = re.compile(r"\[color:(?P[^\]]*)\]")
            result = regexp.search(line)
	    if result:
	        font_color = result.group('color')
	    else:
	        font_color = default_color
    
            if insidehtml:
                print '  Error at line ', lineno, '\n'
                print '  Unexpected begin_html  when already in html mode\n'
                print '  Missing end_html? \n'
                sys.exit(1)
    
            # switch out of pre-formatted mode and create table to indent
            ofile.write('
\n\n') # the next column of the table has the comment itself: ofile.write('
\n') # The first column of the table is spaces for indentation # to match surrounding source code. # Count how many spaces there are before the begin_html # or to the first comment character preceeding that string: regexp = re.compile(r"(?P[ ]*)(#|!|%|begin)") result = regexp.search(line) if result: numindent = len(leadingindent) + len(result.group('spaces')) numindent = numindent ofile.write('
')
                for i in range(numindent):
                    ofile.write(' ')
                ofile.write('
') else: print ' Strange error in clawcode2html - should not be here' print ' at line number ', lineno ofile.write('\n
\n') if ext not in ('.txt', ''): # use colored font for comments except for text files. ofile.write('\n' % font_color) insidehtml = 1; elif string.count(line,"end_html"): # switch back to pre-formatted environment ofile.write('
\n') ofile.write('
\n')
            insidehtml = 0;
    
        else:
            if insidehtml:
    
                # replace blank line in html comment by new paragraph 

: blankline = (string.split(line) == []) if not blankline: firstchar = string.split(line)[0][0] if ((ext == '.f') & (firstchar not in firstfort)): if firstchar not in commentchar[ext]: print ' Error... in line ', lineno,'\n' \ ' In html but not in a comment.'\ ' Forgotten "end_html" ?' sys.exit(1) if ext == '.f': # fortran comments may have comment symbol in column 1 # strip lines inside an html comment of leading symbol: if line[0] in firstfort: line = ' ' + line[1:] # replace any comment character by ' ' if commentchar[ext]: for char in commentchar[ext]: line = string.replace(line,char,' ') blankline = (string.split(line) == []) if blankline: line = ('

\n') # Allow wiki formatting of links: # replace links of the form [code: target] # by html links to both target and target.html regexp = re.compile(r"\[code:(?P[^\]]*)\]") result = regexp.search(line) while result: targetname = result.group('target') oldpat = result.group() newpat = '' + \ targetname + ' ' + \ '' + \ '[.html]' line = line.replace(oldpat,newpat) result = regexp.search(line) # replace links of the form [link: target text] # by an html link from text to the target page. regexp = re.compile(r"\[link:[ ]?(?P[^ ]*)" + \ r"([ ]*)(?P[^\]]*)\]") result = regexp.search(line) while result: targetname = result.group('target') text = result.group('text') oldpat = result.group() if text=='': text = targetname newpat = '' + \ text + ' ' line = line.replace(oldpat,newpat) result = regexp.search(line) # replace links of the form [http:etc text] # by an html link from text to the http page. regexp = re.compile(r"\[http:(?P[^ ]*)" + \ r"([ ]*)(?P[^\]]*)\]") result = regexp.search(line) while result: targetname = result.group('target') text = result.group('text') oldpat = result.group() if text=='': text = targetname[2:] newpat = '' + \ text + ' ' line = line.replace(oldpat,newpat) result = regexp.search(line) # replace links of the form [www.etc text] # by an html link from text to the http://www.etc page. regexp = re.compile(r"\[www.(?P[^ ]*)" + \ r"([ ]*)(?P[^\]]*)\]") result = regexp.search(line) while result: targetname = result.group('target') text = result.group('text') oldpat = result.group() if text=='': text = 'www.' + targetname newpat = '' + \ text + ' ' line = line.replace(oldpat,newpat) result = regexp.search(line) # special things for CLAWPACK: # replace links of the form [clawcode:clawpack/1d/lib/step1.f] # for example by links relative to clawaddr, # along with a link to the .html version. regexp = re.compile(r"\[clawcode:(?P[^\]]*)\]") result = regexp.search(line) while result: targetname = result.group('target').lstrip() oldpat = result.group() newpat = '' + 'claw/' + targetname + ' ' + \ '' + '[.html]' line = line.replace(oldpat,newpat) result = regexp.search(line) # replace links of the form [claw:clawpack/1d/lib] # for example by links relative to clawaddr, # with no .html version. regexp = re.compile(r"\[claw:(?P[^\]]*)\]") result = regexp.search(line) while result: targetname = result.group('target') oldpat = result.group() newpat = '' + 'claw/' + targetname + ' ' line = line.replace(oldpat,newpat) result = regexp.search(line) else: # not insidehtml - make regular comments default_color. # Determine if this line contains a comment and if so, # what column the comment starts in: startcomment = 1000 if (ext == '.f') & (line[0] in firstfort): startcomment = 0 else: if commentchar[ext]: for c in commentchar[ext]: commentcol = string.find(line,c) if (commentcol>-1)&(commentcol' % default_color + \ line[startcomment:-1] + '\n' # output the (possibly modified) line to the output file: ofile.write('%s' % leadingindent+line) # Done with all lines. Add closing stuff at bottom of html file: ofile.write('

\n') ifile.close() ofile.close()