view examples/trac/trac/mimeview/php.py @ 39:93b4dcbafd7b trunk

Copy Trac to main branch.
author cmlenz
date Mon, 03 Jul 2006 18:53:27 +0000
parents
children
line wrap: on
line source
# -*- coding: utf-8 -*-
#
# Copyright (C) 2005 Edgewall Software
# Copyright (C) 2005 Christian Boos <cboos@bct-technology.com>
# Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de>
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://trac.edgewall.com/license.html.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://projects.edgewall.com/trac/.
#
# Author: Christian Boos <cboos@bct-technology.com>
#         Christopher Lenz <cmlenz@gmx.de>

import re

from trac.core import *
from trac.config import Option
from trac.mimeview.api import IHTMLPreviewRenderer, content_to_unicode
from trac.util import NaivePopen
from trac.util.markup import Deuglifier

__all__ = ['PHPRenderer']

php_types = ('text/x-php', 'application/x-httpd-php',
             'application/x-httpd-php4', 'application/x-httpd-php1')


class PhpDeuglifier(Deuglifier):

    def format(self, indata):
        # The PHP highlighter produces the end-span tags on the next line
        # instead of the line they actually apply to, which causes
        # Trac to produce lots of (useless) open-and-immediately-close
        # spans beginning each line.  This tries to curtail by bubbling
        # the first span after a set of 1+ "<br />" to before them.
        r_fixeol = re.compile(r"((?:<br />)+)(</(?:font|span)>)")
        indata = r_fixeol.sub(lambda m: m.group(2) + m.group(1), indata)
        
        # Now call superclass implementation that handles the dirty work
        # of applying css classes.
        return Deuglifier.format(self, indata)

    def rules(cls):
        colors = dict(comment='FF8000', lang='0000BB', keyword='007700',
                      string='DD0000')
        # rules check for <font> for PHP 4 or <span> for PHP 5
        color_rules = [
            r'(?P<%s><(?:font color="|span style="color: )#%s">)' % c
            for c in colors.items()
            ]
        return color_rules + [ r'(?P<font><font.*?>)', r'(?P<endfont></font>)' ]
    rules = classmethod(rules)

class PHPRenderer(Component):
    """
    Syntax highlighting using the PHP executable if available.
    """

    implements(IHTMLPreviewRenderer)

    path = Option('mimeviewer', 'php_path', 'php',
        """Path to the PHP executable (''since 0.9'').""")

    # IHTMLPreviewRenderer methods

    def get_quality_ratio(self, mimetype):
        if mimetype in php_types:
            return 4
        return 0

    def render(self, req, mimetype, content, filename=None, rev=None):
        cmdline = self.config.get('mimeviewer', 'php_path')
        # -n to ignore php.ini so we're using default colors
        cmdline += ' -sn'
        self.env.log.debug("PHP command line: %s" % cmdline)
        
        content = content_to_unicode(self.env, content, mimetype)
        content = content.encode('utf-8')
        np = NaivePopen(cmdline, content, capturestderr=1)
        if np.errorlevel or np.err:
            err = 'Running (%s) failed: %s, %s.' % (cmdline, np.errorlevel,
                                                    np.err)
            raise Exception, err
        odata = ''.join(np.out.splitlines()[1:-2])
        if odata.startswith('X-Powered-By'):
            raise TracError, 'You appear to be using the PHP CGI binary.  ' \
                             'Trac requires the CLI version for syntax ' \
                             'highlighting.'

        html = PhpDeuglifier().format(odata.decode('utf-8'))
        for line in html.split('<br />'):
            # PHP generates _way_ too many non-breaking spaces...
            # We don't need them anyway, so replace them by normal spaces
            yield line.replace('&nbsp;', ' ')
Copyright (C) 2012-2017 Edgewall Software