diff --git a/lib/PyFontify.py b/lib/PyFontify.py index 1b956416..104ce2f6 100644 --- a/lib/PyFontify.py +++ b/lib/PyFontify.py @@ -1,152 +1,173 @@ """Module to analyze Python source code; for syntax coloring tools. Interface: - tags = fontify(pytext, searchfrom, searchto) -The 'pytext' argument is a string containing Python source code. -The (optional) arguments 'searchfrom' and 'searchto' may contain a slice in pytext. + tags = fontify(pytext, searchfrom, searchto) + +The PYTEXT argument is a string containing Python source code. The +(optional) arguments SEARCHFROM and SEARCHTO may contain a slice in +PYTEXT. + The returned value is a list of tuples, formatted like this: - [('keyword', 0, 6, None), ('keyword', 11, 17, None), ('comment', 23, 53, None), etc. ] + + [('keyword', 0, 6, None), + ('keyword', 11, 17, None), + ('comment', 23, 53, None), + ... + ] + The tuple contents are always like this: - (tag, startindex, endindex, sublist) -tag is one of 'keyword', 'string', 'comment' or 'identifier' -sublist is not used, hence always None. + + (tag, startindex, endindex, sublist) + +TAG is one of 'keyword', 'string', 'comment' or 'identifier' +SUBLIST is not used, hence always None. """ # Based on FontText.py by Mitchell S. Chapman, # which was modified by Zachary Roadhouse, # then un-Tk'd by Just van Rossum. # Many thanks for regular expression debugging & authoring are due to: -# Tim (the-incredib-ly y'rs) Peters and Cristian Tismer +# Tim (the-incredib-ly y'rs) Peters and Cristian Tismer # So, who owns the copyright? ;-) How about this: # Copyright 1996-1997: -# Mitchell S. Chapman, -# Zachary Roadhouse, -# Tim Peters, -# Just van Rossum +# Mitchell S. Chapman, +# Zachary Roadhouse, +# Tim Peters, +# Just van Rossum __version__ = "0.3.1" import string, re -# First a little helper, since I don't like to repeat things. (Tismer speaking) -def replace(where, what, with): - return string.join(string.split(where, what), with) # This list of keywords is taken from ref/node13.html of the # Python 1.3 HTML documentation. ("access" is intentionally omitted.) -keywordsList = [ - "del", "from", "lambda", "return", - "and", "elif", "global", "not", "try", - "break", "else", "if", "or", "while", - "class", "except", "import", "pass", - "continue", "finally", "in", "print", - "def", "for", "is", "raise"] -# Build up a regular expression which will match anything -# interesting, including multi-line triple-quoted strings. +keywordsList = ["and", "assert", "break", "class", "continue", "def", + "del", "elif", "else", "except", "exec", "finally", + "for", "from", "global", "if", "import", "in", "is", + "lambda", "not", "or", "pass", "print", "raise", + "return", "try", "while", + ] + +# First a little helper, since I don't like to repeat things. (Tismer speaking) +def replace(where, what, with): + return string.join(string.split(where, what), with) + +# A regexp for matching Python comments. commentPat = "#.*" -pat = "q[^\q\n]*\(\\\\[\000-\377][^\q\n]*\)*q" -quotePat = replace(pat, "q", "'") + "\|" + replace(pat, 'q', '"') +# A regexp for matching simple quoted strings. +pat = "q[^q\\n]*(\\[\000-\377][^q\\n]*)*q" +quotePat = replace(pat, "q", "'") + "|" + replace(pat, 'q', '"') -# Way to go, Tim! +# A regexp for matching multi-line tripled-quoted strings. (Way to go, Tim!) pat = """ - qqq - [^\\q]* - \( - \( \\\\[\000-\377] - \| q - \( \\\\[\000-\377] - \| [^\\q] - \| q - \( \\\\[\000-\377] - \| [^\\q] - \) - \) - \) - [^\\q]* - \)* - qqq + qqq + [^q]* + ( + ( \\[\000-\377] + | q + ( \\[\000-\377] + | [^q] + | q + ( \\[\000-\377] + | [^q] + ) + ) + ) + [^q]* + )* + qqq """ -pat = string.join(string.split(pat), '') # get rid of whitespace -tripleQuotePat = replace(pat, "q", "'") + "\|" + replace(pat, 'q', '"') +pat = string.join(string.split(pat), '') # get rid of whitespace +tripleQuotePat = replace(pat, "q", "'") + "|" + replace(pat, 'q', '"') -# Build up a regular expression which matches all and only -# Python keywords. This will let us skip the uninteresting -# identifier references. -# nonKeyPat identifies characters which may legally precede -# a keyword pattern. -nonKeyPat = "\(^\|[^a-zA-Z0-9_.\"']\)" +# A regexp which matches all and only Python keywords. This will let +# us skip the uninteresting identifier references. +nonKeyPat = "(^|[^a-zA-Z0-9_.\"'])" # legal keyword-preceding characters +keyPat = nonKeyPat + "(" + string.join(keywordsList, "|") + ")" + nonKeyPat -keyPat = nonKeyPat + "\(" -for keyword in keywordsList: - keyPat = keyPat + keyword + "\|" -keyPat = keyPat[:-2] + "\)" + nonKeyPat +# Our final syntax-matching regexp is the concatation of the regexp's we +# constructed above. +syntaxPat = keyPat + \ + "|" + commentPat + \ + "|" + tripleQuotePat + \ + "|" + quotePat +syntaxRE = re.compile(syntaxPat) -matchPat = keyPat + "\|" + commentPat + "\|" + tripleQuotePat + "\|" + quotePat -matchRE = re.compile(matchPat) - -idKeyPat = "[ \t]*[A-Za-z_][A-Za-z_0-9.]*" # Ident w. leading whitespace. +# Finally, we construct a regexp for matching indentifiers (with +# optional leading whitespace). +idKeyPat = "[ \t]*[A-Za-z_][A-Za-z_0-9.]*" idRE = re.compile(idKeyPat) -def fontify(pytext, searchfrom = 0, searchto = None): - if searchto is None: - searchto = len(pytext) - # Cache a few attributes for quicker reference. - search = matchRE.search - group = matchRE.group - idSearch = idRE.search - idGroup = idRE.group - - tags = [] - tags_append = tags.append - commentTag = 'comment' - stringTag = 'string' - keywordTag = 'keyword' - identifierTag = 'identifier' - - start = 0 - end = searchfrom - while 1: - start = search(pytext, end) - if start < 0 or start >= searchto: - break # EXIT LOOP - match = group(0) - end = start + len(match) - c = match[0] - if c not in "#'\"": - # Must have matched a keyword. - if start <> searchfrom: - # there's still a redundant char before and after it, strip! - match = match[1:-1] - start = start + 1 - else: - # this is the first keyword in the text. - # Only a space at the end. - match = match[:-1] - end = end - 1 - tags_append((keywordTag, start, end, None)) - # If this was a defining keyword, look ahead to the - # following identifier. - if match in ["def", "class"]: - start = idSearch(pytext, end) - if start == end: - match = idGroup(0) - end = start + len(match) - tags_append((identifierTag, start, end, None)) - elif c == "#": - tags_append((commentTag, start, end, None)) - else: - tags_append((stringTag, start, end, None)) - return tags +def fontify(pytext, searchfrom=0, searchto=None): + if searchto is None: + searchto = len(pytext) + tags = [] + commentTag = 'comment' + stringTag = 'string' + keywordTag = 'keyword' + identifierTag = 'identifier' + + start = 0 + end = searchfrom + while 1: + # Look for some syntax token we're interested in. If find + # nothing, we're done. + matchobj = syntaxRE.search(pytext, end) + if not matchobj: + break + + # If we found something outside our search area, it doesn't + # count (and we're done). + start = matchobj.start() + if start >= searchto: + break + + match = matchobj.group(0) + end = start + len(match) + c = match[0] + if c == '#': + # We matched a comment. + tags.append((commentTag, start, end, None)) + elif c == '"' or c == '\'': + # We matched a string. + tags.append((stringTag, start, end, None)) + else: + # We matched a keyword. + if start != searchfrom: + # there's still a redundant char before and after it, strip! + match = match[1:-1] + start = start + 1 + else: + # This is the first keyword in the text. + # Only a space at the end. + match = match[:-1] + end = end - 1 + tags.append((keywordTag, start, end, None)) + # If this was a defining keyword, look ahead to the + # following identifier. + if match in ["def", "class"]: + matchobj = idRE.search(pytext, end) + if matchobj: + start = matchobj.start() + if start == end and start < searchto: + end = start + len(matchobj.group(0)) + tags.append((identifierTag, start, end, None)) + return tags def test(path): - f = open(path) - text = f.read() - f.close() - tags = fontify(text) - for tag, start, end, sublist in tags: - print tag, `text[start:end]` + f = open(path) + text = f.read() + f.close() + tags = fontify(text) + for tag, start, end, sublist in tags: + print tag, `text[start:end]` + +if __name__ == "__main__": + import sys + test(sys.argv[0]) diff --git a/lib/py2html.py b/lib/py2html.py index f86d780e..3c8c9912 100755 --- a/lib/py2html.py +++ b/lib/py2html.py @@ -1,6 +1,6 @@ -#!/usr/local/bin/python -u +#!/usr/bin/python -u -""" Python Highlighter for HTML Version: 0.5 +""" Python Highlighter Version: 0.8 py2html.py [options] files... @@ -10,8 +10,8 @@ -stdout read from files, write to stdout -files read from files, write to filename+'.html' (default) -format: - html output HTML page (default) - rawhtml output pure HTML (without headers, titles, etc.) + html output XHTML page (default) + rawhtml output pure XHTML (without headers, titles, etc.) -mode: color output in color (default) mono output b/w (for printing) @@ -21,11 +21,11 @@ -footer:file use contents of file as footer -URL replace all occurances of 'URL: link' with 'link'; this is always enabled - in CGI mode + in CGI mode -v verbose Takes the input, assuming it is Python code and formats it into - colored HTML. When called without parameters the script tries to + colored XHTML. When called without parameters the script tries to work in CGI mode. It looks for a field 'script=URL' and tries to use that URL as input file. If it can't find this field, the path info (the part of the URL following the CGI script name) is @@ -34,47 +34,43 @@ * Uses Just van Rossum's PyFontify version 0.3 to tag Python scripts. You can get it via his homepage on starship: - URL: http://starship.skyport.net/crew/just + URL: http://starship.python.net/crew/just """ __comments__ = """ The following snippet is a small shell script I use for viewing - Python scripts per less on Unix: + Python scripts via less on Unix: + +pyless: #!/bin/sh # Browse pretty printed Python code using ANSI codes for highlighting -py2html -stdout -format:ansi -mode:mono $* | less -r +py2html -stdout -format:ansi -mode:color $* | less -r History: - + + 0.8: Added patch by Patrick Lynch to have py2html.py use style + sheets for markup + 0.7: Added patch by Ville Skyttä to make py2html.py output + valid XHTML. + 0.6: Fixed a bug in .escape_html(); thanks to Vespe Savikko for + finding this one. 0.5: Added a few suggestions by Kevin Ng to make the CGI version a little more robust. """ -__copyright__ = """ ------------------------------------------------------------------------------ -(c) Copyright by Marc-Andre Lemburg, 1998 (mailto:mal@lemburg.com) - - Permission to use, copy, modify, and distribute this software and its - documentation for any purpose and without fee or royalty is hereby granted, - provided that the above copyright notice appear in all copies and that - both that copyright notice and this permission notice appear in - supporting documentation or portions thereof, including modifications, - that you make. - - THE AUTHOR MARC-ANDRE LEMBURG DISCLAIMS ALL WARRANTIES WITH REGARD TO - THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, - INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING - FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - WITH THE USE OR PERFORMANCE OF THIS SOFTWARE ! +__copyright__ = """\ + Copyright (c) 1998-2000, Marc-Andre Lemburg; mailto:mal@lemburg.com + Copyright (c) 2000-2002, eGenix.com Software GmbH; mailto:info@egenix.com + Distributed under the terms and conditions of the eGenix.com Public + License. See http://www.egenix.com/files/python/mxLicense.html for + details, or contact the author. All Rights Reserved.\ """ -__version__ = '0.5' +__version__ = '0.8' __cgifooter__ = ('\n
# code highlighted using py2html.py '
-		 'version %s
\n' % __version__) + '"http://www.lemburg.com/files/python/">py2html.py ' + 'version %s\n' % __version__) import sys,string,re @@ -86,21 +82,25 @@ sys.path.append('.') # URL of the input form the user is redirected to in case no script=xxx # form field is given. The URL *must* be absolute. Leave blank to # have the script issue an error instead. -INPUT_FORM = 'http://starship.skyport.net/~lemburg/SoftwareDescriptions.html#py2html.py' +INPUT_FORM = 'http://www.lemburg.com/files/python/SoftwareDescriptions.html#py2html.py' + +# HTML DOCTYPE and XML namespace +HTML_DOCTYPE = '' +HTML_XMLNS = ' xmlns="http://www.w3.org/1999/xhtml"' ### Helpers def fileio(file, mode='rb', data=None, close=0): if type(file) == type(''): - f = open(file,mode) - close = 1 + f = open(file,mode) + close = 1 else: - f = file + f = file if data: - f.write(data) + f.write(data) else: - data = f.read() + data = f.read() if close: f.close() return data @@ -112,35 +112,36 @@ class PrettyPrint: * supports tagging Python scripts in the following ways: - # format/mode | color mono - # -------------------------- - # rawhtml | x x (HTML without headers, etc.) - # html | x x (a HTML page with HEAD&BODY:) - # ansi | x (with Ansi-escape sequences) + # format/mode | color mono + # -------------------------- + # rawhtml | x x (HTML without headers, etc.) + # html | x x (a HTML page with HEAD&BODY:) + # ansi | x x (with Ansi-escape sequences) - * interfaces: + * interfaces: - file_filter -- takes two files: input & output (may be stdin/stdout) - filter -- takes a string and returns the highlighted version - - * to create an instance use: + file_filter -- takes two files: input & output (may be stdin/stdout) + filter -- takes a string and returns the highlighted version - c = PrettyPrint(tagfct,format,mode) + * to create an instance use: - where format and mode must be strings according to the - above table if you plan to use PyFontify.fontify as - tagfct + c = PrettyPrint(tagfct,format,mode) + + where format and mode must be strings according to the + above table if you plan to use PyFontify.fontify as + tagfct * the tagfct has to take one argument, text, and return a taglist - (format: [(id,left,right,sublist),...], where id is the - "name" given to the slice left:right in text and sublist is a - taglist for tags inside the slice or None) + (format: [(id,left,right,sublist),...], where id is the + "name" given to the slice left:right in text and sublist is a + taglist for tags inside the slice or None) """ # misc settings title = '' bgcolor = '#FFFFFF' + css = '' header = '' footer = '' replace_URLs = 0 @@ -149,19 +150,19 @@ class PrettyPrint: def __init__(self,tagfct=None,format='html',mode='color'): - self.tag = tagfct - self.set_mode = getattr(self,'set_mode_'+format+'_'+mode) - self.filter = getattr(self,'filter_'+format) - self.set_mode() + self.tag = tagfct + self.set_mode = getattr(self,'set_mode_%s_%s' % (format, mode)) + self.filter = getattr(self,'filter_%s' % format) def file_filter(self,infile,outfile): - text = fileio(infile,'r') - if type(infile) == type('') and self.title == '': - self.title = infile - fileio(outfile,'w',self.filter(text)) + self.set_mode() + text = fileio(infile,'r') + if type(infile) == type('') and self.title == '': + self.title = infile + fileio(outfile,'w',self.filter(text)) - ### set pre- and postfixes for formats & modes + ### Set pre- and postfixes for formats & modes # # These methods must set self.formats to a dictionary having # an entry for every tag returned by the tagging function. @@ -175,134 +176,185 @@ class PrettyPrint: def set_mode_html_color(self): - self.formats = { - 'all':('
','
'), - 'comment':('',''), - 'keyword':('',''), - 'parameter':('' % (strip(x)), - ''), - 'string':('','') - } + self.css = """ + """ % self.bgcolor + + self.formats = { + 'all':('
','
'), + 'comment':('',''), + 'keyword':('',''), + 'parameter':('',''), + 'identifier':( lambda x,strip=string.strip: + '' % (strip(x)), + ''), + 'string':('','') + } set_mode_rawhtml_color = set_mode_html_color def set_mode_html_mono(self): - self.formats = { - 'all':('
','
'), - 'comment':('',''), - 'keyword':( '',''), - 'parameter':('',''), - 'identifier':( lambda x,strip=string.strip: - '' % (strip(x)), - ''), - 'string':('','') - } + self.css = """ + """ % self.bgcolor + + self.formats = { + 'all':('
','
'), + 'comment':('',''), + 'keyword':( '',''), + 'parameter':('',''), + 'identifier':( lambda x,strip=string.strip: + '
' % (strip(x)), + ''), + 'string':('','') + } set_mode_rawhtml_mono = set_mode_html_mono def set_mode_ansi_mono(self): - self.formats = { - 'all':('',''), - 'comment':('\033[2m','\033[m'), - 'keyword':('\033[4m','\033[m'), - 'parameter':('',''), - 'identifier':('\033[1m','\033[m'), - 'string':('','') - } + self.formats = { + 'all':('',''), + 'comment':('\033[2m','\033[m'), + 'keyword':('\033[4m','\033[m'), + 'parameter':('',''), + 'identifier':('\033[1m','\033[m'), + 'string':('','') + } - ### filter for Python scripts given as string + def set_mode_ansi_color(self): + + self.formats = { + 'all':('',''), + 'comment':('\033[34;2m','\033[m'), + 'keyword':('\033[1;34m','\033[m'), + 'parameter':('',''), + 'identifier':('\033[1;31m','\033[m'), + 'string':('\033[32;2m','\033[m') + } + + ### Filters for Python scripts given as string def escape_html(self,text): - t = (('<','<'),('>','>')) - for x,y in t: - text = string.join(string.split(text,x),y) - return text + t = (('&','&'),('<','<'),('>','>')) + for x,y in t: + text = string.join(string.split(text,x),y) + return text def filter_html(self,text): - output = self.fontify(self.escape_html(text)) - if self.replace_URLs: - output = re.sub('URL:([ \t]+)([^ \n\r<]+)', - 'URL:\\1\\2',output) - html = """%s - - %s - %s - %s - \n"""%(self.title,self.bgcolor,self.header,output,self.footer) - return html + output = self.fontify(self.escape_html(text)) + if self.replace_URLs: + output = re.sub('URL:([ \t]+)([^ \n\r<]+)', + 'URL:\\1\\2',output) + html = """%s + + %s + + %s + + + + %s + + %s + + %s + \n"""%(HTML_DOCTYPE, + HTML_XMLNS, + self.title, + self.css, + self.header, + output, + self.footer) + return html def filter_rawhtml(self,text): - output = self.fontify(self.escape_html(text)) - if self.replace_URLs: - output = re.sub('URL:([ \t]+)([^ \n\r<]+)', - 'URL:\\1\\2',output) - return self.header+output+self.footer + output = self.fontify(self.escape_html(text)) + if self.replace_URLs: + output = re.sub('URL:([ \t]+)([^ \n\r<]+)', + 'URL:\\1\\2',output) + return self.header + output + self.footer def filter_ansi(self,text): - output = self.fontify(text) - return self.header+output+self.footer + output = self.fontify(text) + return self.header + output + self.footer - ### fontify engine + ### Fontify engine def fontify(self,pytext): - # parse - taglist = self.tag(pytext) + # parse + taglist = self.tag(pytext) - # prepend special 'all' tag: - taglist[:0] = [('all',0,len(pytext),None)] + # prepend special 'all' tag: + taglist[:0] = [('all',0,len(pytext),None)] - # prepare splitting - splits = [] - addsplits(splits,pytext,self.formats,taglist) + # prepare splitting + splits = [] + addsplits(splits,pytext,self.formats,taglist) - # do splitting & inserting - splits.sort() - l = [] - li = 0 - for ri,dummy,insert in splits: - if ri > li: l.append(pytext[li:ri]) - l.append(insert) - li = ri - if li < len(pytext): l.append(pytext[li:]) - - return string.join(l,'') + # do splitting & inserting + splits.sort() + l = [] + li = 0 + for ri,dummy,insert in splits: + if ri > li: l.append(pytext[li:ri]) + l.append(insert) + li = ri + if li < len(pytext): l.append(pytext[li:]) + + return string.join(l,'') def addsplits(splits,text,formats,taglist): - # helper for fontify() + + """ Helper for .fontify() + """ for id,left,right,sublist in taglist: - try: - pre,post = formats[id] - except KeyError: - # sys.stderr.write('Warning: no format for %s specified\n'%repr(id)) - pre,post = '','' - if type(pre) != type(''): - pre = pre(text[left:right]) - if type(post) != type(''): - post = post(text[left:right]) - # len(splits) is a dummy used to make sorting stable - splits.append((left,len(splits),pre)) - if sublist: - addsplits(splits,text,formats,sublist) - splits.append((right,len(splits),post)) + try: + pre,post = formats[id] + except KeyError: + # sys.stderr.write('Warning: no format for %s specified\n'%repr(id)) + pre,post = '','' + if type(pre) != type(''): + pre = pre(text[left:right]) + if type(post) != type(''): + post = post(text[left:right]) + # len(splits) is a dummy used to make sorting stable + splits.append((left,len(splits),pre)) + if sublist: + addsplits(splits,text,formats,sublist) + splits.append((right,len(splits),post)) def write_html_error(titel,text): print """\ -html>%s +%s%s

%s

%s -""" % (titel,titel,text) +""" % (HTML_DOCTYPE,HTML_XMLNS,titel,titel,text) def redirect_to(url): @@ -310,13 +362,13 @@ def redirect_to(url): sys.stdout.write('Status: 302\r\n') sys.stdout.write('Location: %s\r\n\r\n' % url) print """ - +%s 302 Moved Temporarily

302 Moved Temporarily

-

The document has moved to %s.

+The document has moved to %s.

-""" % (url,url) +""" % (HTML_DOCTYPE,HTML_XMLNS,url,url) def main(cmdline): @@ -326,162 +378,162 @@ def main(cmdline): options = [] optvalues = {} for o in cmdline[1:]: - if o[0] == '-': - if ':' in o: - k,v = tuple(string.split(o,':')) - optvalues[k] = v - options.append(k) - else: - options.append(o) - else: - break + if o[0] == '-': + if ':' in o: + k,v = tuple(string.split(o,':')) + optvalues[k] = v + options.append(k) + else: + options.append(o) + else: + break files = cmdline[len(options)+1:] - # create converting object + ### create converting object # load fontifier if '-marcs' in options: - # use mxTextTool's tagging engine - from mxTextTools import tag - from mxTextTools.Examples.Python import python_script - tagfct = lambda text,tag=tag,pytable=python_script: \ - tag(text,pytable)[1] - print "Py2HTML: using Marc's tagging engine" + # use mxTextTool's tagging engine as fontifier + from mx.TextTools import tag + from mx.TextTools.Examples.Python import python_script + tagfct = lambda text,tag=tag,pytable=python_script: \ + tag(text,pytable)[1] + print "Py2HTML: using Marc's tagging engine" else: - # load Just's - try: - import PyFontify - if PyFontify.__version__ < '0.3': raise ValueError - tagfct = PyFontify.fontify - except: - print """ + # load Just's fontifier + try: + import PyFontify + if PyFontify.__version__ < '0.3': raise ValueError + tagfct = PyFontify.fontify + except: + print """ Sorry, but this script needs the PyFontify.py module version 0.3; You can download it from Just's homepage at - URL: http://starship.skyport.net/crew/just + URL: http://starship.python.net/crew/just """ - sys.exit() - + sys.exit() + if '-format' in options: - format = optvalues['-format'] + format = optvalues['-format'] else: - # use default - format = 'html' + # use default + format = 'html' if '-mode' in options: - mode = optvalues['-mode'] + mode = optvalues['-mode'] else: - # use default - mode = 'color' + # use default + mode = 'color' c = PrettyPrint(tagfct,format,mode) convert = c.file_filter - # start working + ### start working if '-title' in options: - c.title = optvalues['-title'] + c.title = optvalues['-title'] if '-bgcolor' in options: - c.bgcolor = optvalues['-bgcolor'] + c.bgcolor = optvalues['-bgcolor'] if '-header' in options: - try: - f = open(optvalues['-header']) - c.header = f.read() - f.close() - except IOError: - if verbose: print 'IOError: header file not found' - + try: + f = open(optvalues['-header']) + c.header = f.read() + f.close() + except IOError: + if verbose: print 'IOError: header file not found' + if '-footer' in options: - try: - f = open(optvalues['-footer']) - c.footer = f.read() - f.close() - except IOError: - if verbose: print 'IOError: footer file not found' + try: + f = open(optvalues['-footer']) + c.footer = f.read() + f.close() + except IOError: + if verbose: print 'IOError: footer file not found' if '-URL' in options: - c.replace_URLs = 1 + c.replace_URLs = 1 if '-' in options: - convert(sys.stdin,sys.stdout) - sys.exit() + convert(sys.stdin,sys.stdout) + sys.exit() if '-h' in options: - print __doc__ - sys.exit() + print __doc__ + sys.exit() if len(files) == 0: - # Turn URL processing on - c.replace_URLs = 1 - # Try CGI processing... - import cgi,urllib,urlparse,os - form = cgi.FieldStorage() - if not form.has_key('script'): - # Ok, then try pathinfo - if not os.environ.has_key('PATH_INFO'): - if INPUT_FORM: - redirect_to(INPUT_FORM) - else: - sys.stdout.write('Content-Type: text/html\r\n\r\n') - write_html_error('Missing Parameter', - 'Missing script=URL field in request') - sys.exit(1) - url = os.environ['PATH_INFO'][1:] # skip the leading slash - else: - url = form['script'].value - sys.stdout.write('Content-Type: text/html\r\n\r\n') - scheme, host, path, params, query, frag = urlparse.urlparse(url) - if not host: - scheme = 'http' - if os.environ.has_key('HTTP_HOST'): - host = os.environ['HTTP_HOST'] - else: - host = 'localhost' - url = urlparse.urlunparse((scheme, host, path, params, query, frag)) - #print url; sys.exit() - network = urllib.URLopener() - try: - tempfile,headers = network.retrieve(url) - except IOError,reason: - write_html_error('Error opening "%s"' % url, - 'The given URL could not be opened. Reason: %s' %\ - str(reason)) - sys.exit(1) - f = open(tempfile,'rb') - c.title = url - c.footer = __cgifooter__ - convert(f,sys.stdout) - f.close() - network.close() - sys.exit() + # Turn URL processing on + c.replace_URLs = 1 + # Try CGI processing... + import cgi,urllib,urlparse,os + form = cgi.FieldStorage() + if not form.has_key('script'): + # Ok, then try pathinfo + if not os.environ.has_key('PATH_INFO'): + if INPUT_FORM: + redirect_to(INPUT_FORM) + else: + sys.stdout.write('Content-Type: text/html\r\n\r\n') + write_html_error('Missing Parameter', + 'Missing script=URL field in request') + sys.exit(1) + url = os.environ['PATH_INFO'][1:] # skip the leading slash + else: + url = form['script'].value + sys.stdout.write('Content-Type: text/html\r\n\r\n') + scheme, host, path, params, query, frag = urlparse.urlparse(url) + if not host: + scheme = 'http' + if os.environ.has_key('HTTP_HOST'): + host = os.environ['HTTP_HOST'] + else: + host = 'localhost' + url = urlparse.urlunparse((scheme, host, path, params, query, frag)) + #print url; sys.exit() + network = urllib.URLopener() + try: + tempfile,headers = network.retrieve(url) + except IOError,reason: + write_html_error('Error opening "%s"' % url, + 'The given URL could not be opened. Reason: %s' %\ + str(reason)) + sys.exit(1) + f = open(tempfile,'rb') + c.title = url + c.footer = __cgifooter__ + convert(f,sys.stdout) + f.close() + network.close() + sys.exit() if '-stdout' in options: - filebreak = '-'*72 - for f in files: - try: - if len(files) > 1: - print filebreak - print 'File:',f - print filebreak - convert(f,sys.stdout) - except IOError: - pass + filebreak = '-'*72 + for f in files: + try: + if len(files) > 1: + print filebreak + print 'File:',f + print filebreak + convert(f,sys.stdout) + except IOError: + pass else: - verbose = ('-v' in options) - if verbose: - print 'Py2HTML: working on', - for f in files: - try: - if verbose: print f, - convert(f,f+'.html') - except IOError: - if verbose: print '(IOError!)', - if verbose: - print - print 'Done.' + verbose = ('-v' in options) + if verbose: + print 'Py2HTML: working on', + for f in files: + try: + if verbose: print f, + convert(f,f+'.html') + except IOError: + if verbose: print '(IOError!)', + if verbose: + print + print 'Done.' if __name__=='__main__': main(sys.argv) diff --git a/lib/viewcvs.py b/lib/viewcvs.py index b75ff14b..93730ca0 100644 --- a/lib/viewcvs.py +++ b/lib/viewcvs.py @@ -1282,6 +1282,7 @@ def markup_stream_python(fp, cfg): ### mailtos as well as we do. html = cgi.escape(fp.read()) pp = py2html.PrettyPrint(PyFontify.fontify, "rawhtml", "color") + pp.set_mode_rawhtml_color() html = pp.fontify(html) html = re.sub(_re_rewrite_url, r'\1', html) html = re.sub(_re_rewrite_email, r'\1', html) diff --git a/templates/docroot/styles.css b/templates/docroot/styles.css index 7bfa5cc3..98484222 100644 --- a/templates/docroot/styles.css +++ b/templates/docroot/styles.css @@ -67,22 +67,26 @@ form { margin: 0; } background-color: #eeeeee; } - /*** Highlight Markup Styles ***/ -#vc_markup .num { color:#000000; } -#vc_markup .esc { color:#bd8d8b; } -#vc_markup .str { color:#bd8d8b; } -#vc_markup .dstr { color:#bd8d8b; } -#vc_markup .slc { color:#ac2020; font-style:italic; } -#vc_markup .com { color:#ac2020; font-style:italic; } -#vc_markup .dir { color:#000000; } -#vc_markup .sym { color:#000000; } -#vc_markup .line { color:#555555; } -#vc_markup .kwa { color:#9c20ee; font-weight:bold; } -#vc_markup .kwb { color:#208920; } -#vc_markup .kwc { color:#0000ff; } -#vc_markup .kwd { color:#000000; } +#vc_markup .num { color: #000000; } +#vc_markup .esc { color: #bd8d8b; } +#vc_markup .str { color: #bd8d8b; } +#vc_markup .dstr { color: #bd8d8b; } +#vc_markup .slc { color: #ac2020; font-style: italic; } +#vc_markup .com { color: #ac2020; font-style: italic; } +#vc_markup .dir { color: #000000; } +#vc_markup .sym { color: #000000; } +#vc_markup .line { color: #555555; } +#vc_markup .kwa { color: #9c20ee; font-weight: bold; } +#vc_markup .kwb { color: #208920; } +#vc_markup .kwc { color: #0000ff; } +#vc_markup .kwd { color: #404040; } +/*** Py2html Markup Styles ***/ +#vc_markup .PY_STRING { color: #bd8d8b; } +#vc_markup .PY_COMMENT { color: #ac2020; font-style: italic; } +#vc_markup .PY_KEYWORD { color: #9c20ee; font-weight: bold; } +#vc_markup .PY_IDENTIFIER { color: #404040; } /*** Line numbers outputted by highlight colorizer ***/ .line {