ANN: PySourceColor 1.7

M.E.Farmer mefjr75 at hotmail.com
Thu Oct 14 21:05:52 EDT 2004


Hello all,
    This version of PySourceColor supports decorators.
It looks like the syntax is there for a while, so I decided add them
in.
They parser code has also been extended to seperate all 12 types of
string.
I rewrote the _Null colorscheme to actually be null format.
Changed the old _Null to _Mono a black and white colorscheme for
printing.
Also added a few utility functions.
If you don't like the builtin colorschemes you should be able to write
a colorscheme that looks exactly like you want.
This is something that would be nice to have built into pydoc.
The links at the top-right of a pydoc page could point to a colorized
source and a plain text version :)
This program should run with Python 2.0 -> 2.4.
The code can be any version.
Just save to a file and run it.
It will parse itself into 6 diffrent webpages and show them.
    M.E.Farmer

######################################################################
# PySourceColor    
# A python source to colorized html converter.
# This does not create w3c valid html, but it works on every 
# browser i've tried so far.(I.E.,Mozilla/Firefox,Opera,wxHTML).
# After experimenting with diffrent html vs CSS + html
# I settled on plain old html because it works!
# Too bad CSS is not supported everywhere yet.
# Hacked by M.E.Farmer Jr. 2004
# Python license
######################################################################
# Currently it can seperate and colorize:
#   12 types of strings 
#    2 comment types
#      numbers
#      operators
#      class / name
#      def / name
#      decorator / name
#      keywords
#      text
# And can use any combination of 3 styles:
#      bold 
#      italic
#      underline    
######################################################################
# Recent changes:
#   October 09, 2004:
#      Added support for @decorators.
#         Tested on 2.2 and 2.4
#   Sepetember 25, 2004:
#      Extended string handling:
#         Unicode - single, singletriple, double, double triple
#         Raw     - single, singletriple, double, double triple
#         regular - single, singletriple, double, double triple
# 
######################################################################

import keyword, os, sys, traceback
import cgi, string, cStringIO
import token, tokenize, glob
import getopt, webbrowser, time
__title__ = 'PySourceColor'
__version__ = "1.7"
__date__ = '09 October 2004'
__author__ = "M.E.Farmer Jr."
__credits__ = '''This was originally submitted /written by 
Jürgen Hermann to ASPN python recipes.
I hacked the parser to give me more control over tokens.
Python license     M.E.Farmer 2004
'''
# Testing raw and unicode strings
# We do nothing with the value just look at colorizing
_ = (r'raw',r'''raw''',r"raw",r"""raw""")##Raw test
_ = (u'uni',u'''uni''',u"uni",u"""uni""")##Unicode test

# Do not edit
_DOUBLECOMMENT = token.NT_OFFSET + 1   
_CLASS = token.NT_OFFSET + 2
_DEF = token.NT_OFFSET + 3           
_TEXT = token.NT_OFFSET + 4           
_KEYWORD = token.NT_OFFSET + 5      
_SINGLEQUOTE = token.NT_OFFSET + 6
_SINGLEQUOTE_R = token.NT_OFFSET + 7 
_SINGLEQUOTE_U = token.NT_OFFSET + 8 
_DOUBLEQUOTE = token.NT_OFFSET + 9  
_DOUBLEQUOTE_R = token.NT_OFFSET + 10  
_DOUBLEQUOTE_U = token.NT_OFFSET + 11  
_TRIPLESINGLEQUOTE = token.NT_OFFSET + 12
_TRIPLESINGLEQUOTE_R = token.NT_OFFSET + 13
_TRIPLESINGLEQUOTE_U = token.NT_OFFSET + 14
_TRIPLEDOUBLEQUOTE = token.NT_OFFSET + 15
_TRIPLEDOUBLEQUOTE_R = token.NT_OFFSET + 16
_TRIPLEDOUBLEQUOTE_U = token.NT_OFFSET + 17
_BACKGROUND = token.NT_OFFSET + 18
_DECORATOR = token.NT_OFFSET + 19
_DECORATOR_DEF = token.NT_OFFSET + 20

######################################################################
# Edit colors and styles to taste
# Create your own scheme, just copy one below , rename and edit.
# Color is rgb hex and must be specified. #RRGGBB
# Styles are optional: b=bold, i=italic, u=underline
# Colorscheme names must start with an underscore: _MyColor
# Underscore will not be used on command line (--color= Pythonwin)
######################################################################
_Null = {
        token.ERRORTOKEN:     '#FF8080',# no edit
        token.STRING:         '#000000',# no edit 
        _TEXT:                '#000000',# no edit
        _DECORATOR_DEF:       '#000000',# Decorators
        _DECORATOR:           '#000000',# @
        token.NAME:           '#000000',# All Text
        token.NUMBER:         '#000000',# 0->10
        token.OP:             '#000000',# ()<>=!.:;^>%, etc...
        tokenize.COMMENT:     '#000000',# There are 2 types of comment
        _DOUBLECOMMENT:       '#000000',## Like this 
        _CLASS:               '#000000',# Class name
        _DEF:                 '#000000',# Def name
        _KEYWORD:             '#000000',# Python keywords
        _SINGLEQUOTE:         '#000000',# 'SINGLEQUOTE'
        _SINGLEQUOTE_R:       '#000000',# r'SINGLEQUOTE'
        _SINGLEQUOTE_U:       '#000000',# u'SINGLEQUOTE'
        _DOUBLEQUOTE:         '#000000',# "DOUBLEQUOTE"
        _DOUBLEQUOTE_R:       '#000000',# r"DOUBLEQUOTE"
        _DOUBLEQUOTE_U:       '#000000',# u"DOUBLEQUOTE"
        _TRIPLESINGLEQUOTE:   '#000000',# '''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_R: '#000000',# r'''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_U: '#000000',# u'''TRIPLESINGLEQUOTE'''
        _TRIPLEDOUBLEQUOTE:   '#000000',# """TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_R: '#000000',# r"""TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_U: '#000000',# u"""TRIPLEDOUBLEQUOTE"""
        _BACKGROUND:          '#FFFFFF',# Page background color
        }

_Mono = {
        token.ERRORTOKEN:     '#FF8080',# no edit
        token.STRING:         '#000000',# no edit 
        _TEXT:                '#000000',# no edit
        _DECORATOR_DEF:     'bu#000000',# Decorators
        _DECORATOR:          'b#000000',# @
        token.NAME:           '#000000',# All Text
        token.NUMBER:        'b#000000',# 0->10
        token.OP:            'b#000000',# ()<>=!.:;^>%, etc...
        tokenize.COMMENT:    'i#000000',# There are 2 types of comment
        _DOUBLECOMMENT:       '#000000',## Like this 
        _CLASS:             'bu#000000',# Class name
        _DEF:                'b#000000',# Def name
        _KEYWORD:            'b#000000',# Python keywords
        _SINGLEQUOTE:         '#000000',# 'SINGLEQUOTE'
        _SINGLEQUOTE_R:       '#000000',# r'SINGLEQUOTE'
        _SINGLEQUOTE_U:       '#000000',# u'SINGLEQUOTE'
        _DOUBLEQUOTE:         '#000000',# "DOUBLEQUOTE"
        _DOUBLEQUOTE_R:       '#000000',# r"DOUBLEQUOTE"
        _DOUBLEQUOTE_U:       '#000000',# u"DOUBLEQUOTE"
        _TRIPLESINGLEQUOTE:   '#000000',# '''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_R: '#000000',# r'''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_U: '#000000',# u'''TRIPLESINGLEQUOTE'''
        _TRIPLEDOUBLEQUOTE:  'i#000000',# """TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_R:'i#000000',# r"""TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_U:'i#000000',# u"""TRIPLEDOUBLEQUOTE"""
        _BACKGROUND:          '#FFFFFF',# Page background color
        }
    
_Dark = {
        token.ERRORTOKEN:     '#FF8080',# no edit
        token.STRING:         '#FFFFFF',# no edit 
        _TEXT:                '#000000',# no edit
        _DECORATOR_DEF:      'b#FFBBAA',# Decorators
        _DECORATOR:          'b#CC5511',# @    
        token.NAME:           '#ffffff',# All Text
        token.NUMBER:         '#FF0000',# 0->10
        token.OP:            'b#FAF785',# Operators ()<>=!.:;^>%,
etc...
        tokenize.COMMENT:    'i#45FCA0',# There are 2 types of comment
        _DOUBLECOMMENT:       '#A7C7A9',## Like this 
        _CLASS:              'b#B599FD',# Class name
        _DEF:                'b#EBAE5C',# Def name
        _KEYWORD:            'b#8680FF',# Python keywords
        _SINGLEQUOTE:         '#F8BAFE',# 'SINGLEQUOTE'
        _SINGLEQUOTE_R:       '#F8BAFE',# r'SINGLEQUOTE'
        _SINGLEQUOTE_U:       '#F8BAFE',# u'SINGLEQUOTE'
        _DOUBLEQUOTE:         '#FF80C0',# "DOUBLEQUOTE"
        _DOUBLEQUOTE_R:       '#FF80C0',# r"DOUBLEQUOTE"
        _DOUBLEQUOTE_U:       '#FF80C0',# u"DOUBLEQUOTE"
        _TRIPLESINGLEQUOTE:   '#FF9595',# '''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_R: '#FF9595',# r'''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_U: '#FF9595',# u'''TRIPLESINGLEQUOTE'''
        _TRIPLEDOUBLEQUOTE:   '#B3FFFF',# """TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_R: '#B3FFFF',# r"""TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_U: '#B3FFFF',# u"""TRIPLEDOUBLEQUOTE"""
        _BACKGROUND:          '#000000',# Page background color
        }
    
     
_Lite = {
        token.ERRORTOKEN:     '#FF8080',# no edit
        token.STRING:         '#000000',# no edit 
        _TEXT:                '#000000',# no edit
        _DECORATOR_DEF:      'b#BB4422',# Decorators
        _DECORATOR:          'b#3333af',# @   
        token.NAME:           '#000000',# All Text
        token.NUMBER:         '#FF2200',# 0->10
        token.OP:            'b#303000',# Operators ()<>=!.:;^>%,
etc...
        tokenize.COMMENT:     '#007F00',# There are 2 types of comment
        _DOUBLECOMMENT:       '#606060',## Like this 
        _CLASS:               '#0000FF',# Class name
        _DEF:                'b#9C7A00',# Def name
        _KEYWORD:            'b#0000AF',# Python keywords
        _SINGLEQUOTE:         '#600080',# 'SINGLEQUOTE'
        _SINGLEQUOTE_R:       '#600080',# r'SINGLEQUOTE'
        _SINGLEQUOTE_U:       '#600080',# u'SINGLEQUOTE'
        _DOUBLEQUOTE:         '#A0008A',# "DOUBLEQUOTE"
        _DOUBLEQUOTE_R:       '#A0008A',# r"DOUBLEQUOTE"
        _DOUBLEQUOTE_U:       '#A0008A',# u"DOUBLEQUOTE"
        _TRIPLESINGLEQUOTE:   '#4488BB',# '''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_R: '#4488BB',# r'''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_U: '#4488BB',# u'''TRIPLESINGLEQUOTE'''
        _TRIPLEDOUBLEQUOTE:   '#2299BB',# """TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_R: '#2299BB',# r"""TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_U: '#2299BB',# u"""TRIPLEDOUBLEQUOTE"""
        _BACKGROUND:          '#FFFFFF',# Page background color
        }

_Idle = {
        token.ERRORTOKEN:     '#FF8080',# no edit
        token.STRING:         '#000000',# no edit 
        _TEXT:                '#000000',# no edit
        _DECORATOR_DEF:       '#900090',# Decorators
        _DECORATOR:           '#000000',# @   
        token.NAME:           '#000000',# All Text
        token.NUMBER:         '#000000',# 0->10
        token.OP:             '#000000',# Operators ()<>=!.:;^>%,
etc...
        tokenize.COMMENT:     '#DD0000',# There are 2 types of comment
        _DOUBLECOMMENT:       '#DD0000',## Like this 
        _CLASS:               '#0000FF',# Class name
        _DEF:                 '#0000FF',# Def name
        _KEYWORD:             '#FF7700',# Python keywords
        _SINGLEQUOTE:         '#00AA00',# 'SINGLEQUOTE'
        _SINGLEQUOTE_R:       '#00AA00',# r'SINGLEQUOTE'
        _SINGLEQUOTE_U:       '#00AA00',# u'SINGLEQUOTE'
        _DOUBLEQUOTE:         '#00AA00',# "DOUBLEQUOTE"
        _DOUBLEQUOTE_R:       '#00AA00',# r"DOUBLEQUOTE"
        _DOUBLEQUOTE_U:       '#00AA00',# u"DOUBLEQUOTE"
        _TRIPLESINGLEQUOTE:   '#00AA00',# '''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_R: '#00AA00',# r'''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_U: '#00AA00',# u'''TRIPLESINGLEQUOTE'''
        _TRIPLEDOUBLEQUOTE:   '#00AA00',# """TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_R: '#00AA00',# r"""TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_U: '#00AA00',# u"""TRIPLEDOUBLEQUOTE"""
        _BACKGROUND:          '#FFFFFF',# Page background color
        }
    
_PythonWin = {
        token.ERRORTOKEN:     '#FF8080',# no edit
        token.STRING:         '#000000',# no edit
        _TEXT:                '#000000',# no edit
        _DECORATOR_DEF:      'b#303030',# Decorators
        _DECORATOR:          'b#DD0080',# @  
        token.NAME:           '#303030',# All Text
        token.NUMBER:         '#008080',# 0->10
        token.OP:             '#000000',# ()<>=!.:;^>%, etc...
        tokenize.COMMENT:     '#007F00',# There are 2 types of comment
        _DOUBLECOMMENT:       '#7F7F7F',## Like this 
        _CLASS:              'b#0000FF',# Class name
        _DEF:                'b#007F7F',# Def name
        _KEYWORD:            'b#000080',# Python keywords
        _SINGLEQUOTE:         '#808000',# 'SINGLEQUOTE'
        _SINGLEQUOTE_R:       '#808000',# r'SINGLEQUOTE'
        _SINGLEQUOTE_U:       '#808000',# u'SINGLEQUOTE'
        _DOUBLEQUOTE:         '#808000',# "DOUBLEQUOTE"
        _DOUBLEQUOTE_R:       '#808000',# r"DOUBLEQUOTE"
        _DOUBLEQUOTE_U:       '#808000',# u"DOUBLEQUOTE"
        _TRIPLESINGLEQUOTE:   '#808000',# '''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_R: '#808000',# r'''TRIPLESINGLEQUOTE'''
        _TRIPLESINGLEQUOTE_U: '#808000',# u'''TRIPLESINGLEQUOTE'''
        _TRIPLEDOUBLEQUOTE:   '#808000',# """TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_R: '#808000',# r"""TRIPLEDOUBLEQUOTE"""
        _TRIPLEDOUBLEQUOTE_U: '#808000',# u"""TRIPLEDOUBLEQUOTE"""
        _BACKGROUND:          '#FFFFFF',# Page background color
        }
DefaultColorScheme= _Dark 
##################################################################################

def Usage():
   """
_______________________________________________________________________________
Example usage:
  # To colorize all .py,.pyw files in cwdir you can also use: . or _
 python PySourceColor.py -i .
  # Using long options w/ =
 python PySourceColor.py --in=c:/myDir/my.py --out=c:/myDir
--color=Lite --show
  # Using short options w/out =
 python PySourceColor.py -i c:/myDir/  -c Idle
  # Using any mix 
 python PySourceColor.py --in _ -o=c:/myDir --show
-------------------------------------------------------------------------------
This module is designed to colorize python source code.
It is a hacked version of MoinMoin python parser recipe.
    -h or --help
        Display this help message.
    -i or --in 
        Input file or dir. (Use any of these for the cwdir . , _ ,
this)
    -o or --out
        Optional, output dir for the colorized source
            default: output dir is input dir.
    -c or --color
        Optional. Null, Dark, Lite, Idle, Pythonwin, create your own!
            default: Dark
    -s or --show
        Optional, Show webpage after creation.
            default: no show
_______________________________________________________________________________
"""
   print Usage.__doc__

def Main():
    '''Gathers the command line arguments 
       and try to do something reasonable with them.
    '''
    try:
        # try to get command line args 
        opts, args = getopt.getopt(sys.argv[1:],
                     "hsi:o:c:", ["help", "show", "input=", "out=",
"color="])
    except getopt.GetoptError:
        # on error print help information and exit:
        Usage()
        sys.exit(2)
    # init some names
    input = None
    output = None
    scheme = None
    show = 0
    # if we have args then process them
    for o, a in opts:
        if o in ("-h", "--help"):
            Usage()
            sys.exit()
        if o in ("-o", "--out"):
            output = a
        if o in ("-i", "--input"):
            input = a
            if input in('.','_', 'this'):
                input = os.getcwd()
        if o  in ("-s", "--show"):
            show = 1
        if o in ("-c", "--color"):
            try:
               #Fix this if you see a weakness
               scheme = eval('_%s'%a)
            except:
               traceback.print_exc()

    if input == None:
        # if there was no input specified then we try to
        # parse ourselves and do it in diffrent flavors.
        fi = sys.argv[0]
        Path2File(fi, '/MyDir/null', _Null, 1)
        Path2File(fi, '/MyDir/mono', _Mono, 1)
        Path2File(fi, '/MyDir/lite', _Lite, 1)
        Path2File(fi, '/MyDir/dark', _Dark, 1)
        Path2File(fi, '/MyDir/idle', _Idle, 1)
        Path2File(fi, '/MyDir/pythonwin', _PythonWin, 1)
    else:
        # if there was at least an input given we can proceed
        Convert(input, output, scheme, show)
import os

def Str2Html(sourcestring, title='', form=None, colors=None):
    '''Converts a code(string) to colorized HTML 
       and prints to sys.stdout
       form='pre','code',or'snip' for "<pre>yourcode</pre>" only
       colors=_Null,_Mono,_Lite,_Dark,_Idle,or _PythonWin
       example:
Str2Html("""x, y = os.path.split(myPath)
if os.path.isdir(y):
    print'No file' """,form='snip',colors=_Lite)
    '''
    Parser(sourcestring, colors, title).format(form)

def Path2Html(sourcepath, form=None, colors=None):
    '''Converts code(file) to colorized HTML 
       and prints to sys.stdout
       form='pre','code',or'snip' for "<pre>yourcode</pre>" only
       colors=_Null,_Mono,_Lite,_Dark,_Idle,or _PythonWin
    '''
    source = open(sourcepath).read()
    Parser(source, colors, sourcepath).format(form)

def Convert(sourcePath, outdir=None, colors=None, show=0):
    ''' Converts all python source in the given directory to html
file/s.
    '''
    c=0
     # If it is a filename then Path2File
    if not os.path.isdir(sourcePath):
        if os.path.isfile(sourcePath):
            c+=1
            Path2File(sourcePath, outdir, colors, show)
    # If we pass in a dir we need to walkdir for files.
    # Then we need to colorize them with Path2File
    else:
        fileList = WalkDir(sourcePath)
        if fileList != None:
            for i in fileList:
                c+=1
                Path2File(i, outdir, colors, show)
            print'Completed colorizing %s source files.'% str(c)
        else:
            print"No files to convert in dir."

def Path2File(sourcePath, outdir=None, colors=None, show=0):
    ''' Converts python source to html file.
    '''
    print" Converting %s into HTML" % sourcePath
    # If no outdir is given we use the sourcePath
    if outdir == None:
        htmlPath = sourcePath + '.html'
    else:
        # If we do give an outdir, and it does
        # not exist , it will be created.
        if not os.path.isdir(outdir):
            os.makedirs(outdir)
        sourceName = os.path.basename(sourcePath)
        htmlPath = os.path.join(outdir,sourceName)+'.html'
        print "  Output to %s"%htmlPath
    # Open the text and do the parsing.
    source = open(sourcePath).read()
    Parser(source, colors, sourcePath, open(htmlPath, 'wt')).format()
    if show:
        # load HTML page into the default web browser.
        # slower than os.startfile or os.system, but more universal
        try:
            webbrowser.open_new(htmlPath)
        except:
            traceback.print_exc()
    return htmlPath

def WalkDir(dir):
    '''Return a list of .py and .pyw files from a given directory.
       This function can be written as a generator Python 2.3, or a
genexp
       in Python 2.4. But 2.2 and 2.1 would be left out....
    '''
    # Get a list of files that match *.py*
    GLOB_PATTERN = os.path.join(dir, "*.[p][y]*")
    pathlist = glob.glob(GLOB_PATTERN)
    # Now filter out all but py and pyw
    filterlist = [x for x in pathlist 
                        if x.endswith('.py')
                        or x.endswith('.pyw')]
    if filterlist != []:
        # if we have a list send it
        return filterlist
    else:
        return None

class Parser:
    """ MoinMoin python parser heavily chopped :)
    """
    def __init__(self, raw, colors=None, title='', out=sys.stdout):
        ''' Store the source text & set some flags.
        '''
        if colors == None:
            colors = DefaultColorScheme
        self.raw = string.strip(string.expandtabs(raw))
        self.out = out
        self.title = os.path.basename(title)
        self.ClassFlag = 0
        self.DefFlag = 0
        self.Decorator = 0
        self.colors = colors
        # Name: Date stamp top
        self.header = 0
        # Name: Date stamp bottom
        self.footer = 0

    def format(self, form=None, filler=None):
        ''' Parse and send the colored source.
        '''
        if form in ['snip','pre','code']:
            self.addEnds = 0
        else:
            self.addEnds = 1
        # Store line offsets in self.lines
        self.lines = [0, 0]
        pos = 0

        # Gather lines
        while 1:
            pos = string.find(self.raw, '\n', pos) + 1
            if not pos: break
            self.lines.append(pos)
        self.lines.append(len(self.raw))

        # Wrap text in a filelike object
        self.pos = 0
        text = cStringIO.StringIO(self.raw)

        # Html start
        if self.addEnds:
            self._doPageStart()
        else:
            self._doSnippetStart()

        # Parse the source.
        ## Tokenize calls the __call__ 
        ## function for each token till done.
        try:
            tokenize.tokenize(text.readline, self)
        except tokenize.TokenError, ex:
            msg = ex[0]
            line = ex[1][0]
            self.out.write("<h3>ERROR: %s</h3>%s\n" % (
                msg, self.raw[self.lines[line]:]))
            traceback.print_exc()

        # Html end
        if self.addEnds:
            self._doPageEnd()
        else:
            self._doSnippetEnd()   

    def __call__(self, toktype, toktext, (srow,scol), (erow,ecol),
line):
        ''' Token handler. Order of evaluation is important do not
rearrange.
        '''
        style = ''
        # calculate new positions
        oldpos = self.pos
        newpos = self.lines[srow] + scol
        self.pos = newpos + len(toktext)

        # handle newlines
        if toktype in [token.NEWLINE, tokenize.NL]:
            self.out.write('\n')
            return

        # send the original whitespace, if needed
        if newpos > oldpos:
            self.out.write(self.raw[oldpos:newpos])

        # skip indenting tokens
        if toktype in [token.INDENT, token.DEDENT]:
            self.pos = newpos
            return

        if self.ClassFlag or self.DefFlag:
            # maps the color if it was a class or def name
            if self.ClassFlag:
                toktype = _CLASS
                self.ClassFlag = 0 
            elif self.DefFlag:
                toktype = _DEF
                self.DefFlag = 0
        else:
            # Sets a flag if it was a class, def
            # next token will be colored.
            if toktext =='class':
                self.ClassFlag = 1
            elif toktext == 'def':
                self.DefFlag = 1
            #The last token was a @ so we must be a deco name
            elif self.Decorator:
                toktype = _DECORATOR_DEF
                # reset the flag
                self.Decorator = 0

        # map token type to a color group
        if token.LPAR <= toktype and toktype <= token.OP:
            # trap decorators py2.4>
            if toktext == '@':
                toktype = _DECORATOR
                #Colorize next token (decorator name)
                self.Decorator = 1
            else:
                toktype = token.OP
        elif toktype == token.NAME and keyword.iskeyword(toktext):
            toktype = _KEYWORD

        # Extended to seperate the diffrent string types..
        # Plus raw and unicode types. (12 string types)
        # Order of evaluation is important do not change.
        if toktype == token.STRING:
            # TRIPLE DOUBLE QUOTE's
            if (toktext[:3].lower() == '"""'):
                toktype = _TRIPLEDOUBLEQUOTE
            elif (toktext[:4].lower() == 'r"""'):
                toktype = _TRIPLEDOUBLEQUOTE_R
            elif (toktext[:4].lower() == 'u"""'):
                toktype = _TRIPLEDOUBLEQUOTE_U
            # DOUBLE QUOTE's
            elif (toktext[:1].lower() == '"'):
                toktype = _DOUBLEQUOTE
            elif (toktext[:2].lower() == 'r"'):
                toktype = _DOUBLEQUOTE_R
            elif (toktext[:2].lower() == 'u"'): 
                toktype = _DOUBLEQUOTE_U
            # TRIPLE SINGLE QUOTE's
            elif (toktext[:3].lower() == "'''"):
                toktype = _TRIPLESINGLEQUOTE
            elif (toktext[:4].lower() == "r'''"):
                toktype = _TRIPLESINGLEQUOTE_R
            elif (toktext[:4].lower() == "u'''"):
                toktype = _TRIPLESINGLEQUOTE_U
            # SINGLE QUOTE's
            elif (toktext[:1].lower() == "'"):
                toktype = _SINGLEQUOTE
            elif (toktext[:2].lower() == "r'"):
                toktype = _SINGLEQUOTE_R
            elif (toktext[:2].lower() == "u'"):
                toktype = _SINGLEQUOTE_U

        # Exetended to seperate the diffrent comment types
        elif toktype == tokenize.COMMENT:
            if toktext[:2] == "##":
                toktype = _DOUBLECOMMENT

        # Extended errors to seperate decorators
        elif toktype == token.ERRORTOKEN:
            # trap decorators...<py2.3
            if toktext == '@':
                toktype = _DECORATOR
                self.Decorator = 1
            else:
                # Error tokenizing ..red boxes
                style = ' style="border: solid 1.5pt #FF0000;"'
                
        # Get the colors from the dictionary for the standard tokens
        color = self.colors.get(toktype, self.colors[_TEXT])
        otherstart = ''
        otherend = ''
        splitpoint = color.find('#')
        tags = color[:splitpoint].lower()
        color = color[splitpoint:]
        
        # Check for styles and set them if needed.
        if 'b' in tags:#Bold
            otherstart += '<b>'
            otherend += '</b>'
        if 'i' in tags:#Italics
            otherstart += '<i>'
            otherend += '</i>'
        if 'u' in tags:#Underline
            otherstart += '<u>'
            otherend += '</u>'

        # send text
        self.out.write('<font color="%s"%s>%s' % (color, style,
otherstart))
        self.out.write(cgi.escape(toktext))
        self.out.write('%s</font>'% (otherend,))
        return

    def _doSnippetStart(self):
        self.out.write('<pre><font face="Lucida Console, Courier
New">\n')

    def _doSnippetEnd(self):
        self.out.write('</pre>\n')

    def _doPageStart(self):
        self.out.write(
                 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2
Final//EN">\n')
        self.out.write('<html><head><title>%s</title>\n'%
(self.title))
        self.out.write('<!--This document created by %s %s on:
%s-->\n'%
                                       
(__title__,__version__,time.ctime()))
        self.out.write('<meta http-equiv="Content-Type" \
                         content="text/html;charset=iso-8859-1" />\n')
        # Get background color and check for styles and ignore all but
b,i,u
        color = self.colors.get(_BACKGROUND, self.colors[_TEXT])
        color = color[color.find('#'):]
        if color[:1] != '#': 
            self.out.write('</head><body bgcolor="#000000">\n')
        else:
            self.out.write('</head><body bgcolor="%s">\n'% color)
        # Write a little info at the top.
        if self.header:
            self._doPageHeader()
        self.out.write('<pre><font face="Lucida Console, Courier
New">\n')

    def _doPageHeader(self):
        color = self.colors.get(token.NAME, self.colors[_TEXT])
        color = color[color.find('#'):]
        self.out.write(' <b><u><font color="%s">%s   
%s</font></u></b>\n'%
                                   (color, self.title, time.ctime()))
    def _doPageFooter(self):
        color = self.colors.get(token.NAME, self.colors[_TEXT])
        color = color[color.find('#'):]
        self.out.write(' <b><u><font color="%s">%s   
%s</font></u></b>\n'%
                                   (color, self.title,time.ctime()))
    def _doPageEnd(self):
        self.out.write('</pre>\n')
        # Write a little info at the bottom
        if self.footer:
            self._doPageFooter()
        # Write a little info in the web page source
        self.out.write('<!--This document created by %s ver.%s on:
%s-->\n'%
                                  
(__title__,__version__,time.ctime()))
        self.out.write('</body></html>\n')

if __name__ == '__main__':
    Main()
# End of code



More information about the Python-list mailing list