Below is the file 'syntax.py' from this revision. You can also download the file.
# Copyright (C) 2005 Grahame Bowland <grahame@angrygoats.net> # # This program is made available under the GNU GPL version 2.0 or # greater. See the accompanying file COPYING for details. # # This program is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR # PURPOSE. #!/usr/bin/env python2.4 from common import set_nonblocking, terminate_popen3 from web import debug import config import popen2 import select import cgi mime_to_lang = { } def highlight(*args, **kwargs): # if we don't have a highlighter, let's just return the original # iterator if not hasattr(config, "highlight_command"): return __basic_highlight(*args, **kwargs) else: return __highlight(*args, **kwargs) def __basic_highlight(lines, language='py'): for line in lines: yield cgi.escape(line.rstrip('\n')) def __highlight(lines, language='py'): """A generator which will read lines from the given input stream, and yield them back in syntax highlighted, HTML format. """ # trickier than this initially looks; the syntax highlighter might not necessarily # have any more data for us, so it's necessary to use select() and write new data # as it wants it, and read it back (buffer and yield lines) as possible. # # this assumes the 'highlight' command, although shouldn't take much work to have this # happy with other highlighters. fromchild_buf, tochild_buf = '', '' to_run = [config.highlight_command, '--syntax', language, '-c', '/dev/null', '--quiet', '--xhtml', '--force', '--anchors', '--fragment'] process = popen2.Popen3(to_run, capturestderr=True) map (set_nonblocking, [ process.fromchild, process.tochild, process.childerr ]) while True: r_fds = [process.fromchild] w_fds = [] if not process.tochild.closed: w_fds.append(process.tochild) r_stdin, r_stdout, r_stderr = select.select(r_fds, w_fds, [], None) # debug ((r_stdin, r_stdout, r_stderr)) if not r_stdin and not r_stdout and not r_stderr: break if process.fromchild in r_stdin: data = process.fromchild.read() if data == "": break fromchild_buf += data if process.tochild in r_stdout: if tochild_buf == '': try: tochild_buf += lines.next() except StopIteration: tochild_buf = '' if tochild_buf == '': process.tochild.close() else: process.tochild.write(tochild_buf) tochild_buf = '' if fromchild_buf != '': while True: idx = fromchild_buf.find('\n') if idx == -1: break yield fromchild_buf[:idx] fromchild_buf = fromchild_buf[idx+1:] # anything left over (presumably without a newline) if fromchild_buf != '': yield fromchild_buf terminate_popen3(process) if __name__ == '__main__': def l(): fd = open('syntax.py') for line in fd: yield line for i in highlight(l()): print i ### ### vi:expandtab:sw=4:ts=4 ###