Commits

Anonymous committed e36cff8

+ Support for Pygments-coloring of files.

Comments (0)

Files changed (3)

 [app:main]
 use = egg:Slipper
 
-# Specify a reStructuredText extension to use other than .rst (such as
-# .txt) by changing the following.
-slipper.DEFAULT.rst_extension = .rst
+# Specify a reStructuredText extension to use other than .txt (such as
+# .rst) by changing the 'rst_extension'.
+slipper.DEFAULT.rst_extension = .txt
 
 # Specify the cache directory to use.  (Leave commented out to use no cache)
 ## slipper.DEFAULT.cache_dir = %(here)s/cache
 # This is useful for browsing documentation locally.
 slipper.DEFAULT.index_path = /dev/tip+/doc/
 
+# If you want certain file extensions run through Pygments when browsing,
+# configure them here.  In this example, we want all '.py' files to be
+# rendered using the 'python' lexer when they are accessed.  The 
+# 'linenos' variant of the Pygments reStructuredText renderer causes line 
+# numbers to be shown.  
+# Additionally, we also want all '.txt' files to be rendered using the
+# 'rst' lexer when they are accessed using the '.txt-colorized' extension.
+slipper.DEFAULT.colorize = 
+  .py               .py     python  linenos,
+  .txt-colorized    .txt    rst
+
 # For each repository, choose a name, then specify both the location
 # of the repository on the local filesystem ('local_dir') and the base
 # URL of the hgweb or hgwebdir instance you'd like each page to link
 
 # You can also override the 'rst_extension' and 'cache_dir' if you
 # like:
-slipper.dev.rst_extension = .txt
+## slipper.dev.rst_extension = .rst
+
+# If you override 'colorize', it uses no values from DEFAULT, so be sure
+# to specify them again.
+## slipper.DEFAULT.colorize = 
+##   .py               .py     python  linenos,
+##   .rst-colorized    .rst    rst
             revision = 'tip'
         else:
             ctx = repo.changectx(revision)
+        colorize = config.colorize.colorize_info(file_path)
+        if colorize:
+            file_path = colorize['original_path']
         try:
             filectx = ctx[file_path]
         except LookupError:
         date = datestr(filectx.date())
         # XXX: HTTP experts: How do we short-circuit if the client's side is
         # up-to-date?
-        if splitext(file_path)[1] == config.rst_extension:
+        if colorize:
+            # Convert 'data' to reStructuredText.
+            delimiter = '=' * (len(file_path) + 2)
+            variant = colorize['variant']
+            if variant:
+                variant = u'    :%s:\n' % variant
+            else:
+                variant = u''
+            data = dedent(u"""\
+                %s
+                %s
+                %s
+                
+                .. sourcecode:: %s
+                %s
+                %s
+                """) % (
+                delimiter,
+                file_path,
+                delimiter,
+                colorize['lexer'],
+                variant,
+                u'\n'.join('    ' + line for line in data.splitlines()),
+                )
+        if colorize or splitext(file_path)[1] == config.rst_extension:
             if config.hgweb_url:
                 # Add a link to the source text.
-                data += dedent("""\
+                data += dedent(u"""\
 
                     .. admonition:: Page source
 
                         `<%s/file/%s/%s>`__.
-                    """ % (config.hgweb_url, revision, file_path))
+                    """) % (
+                    config.hgweb_url, revision, file_path
+                    )
+            # Look in cache first.
             hash = sha(data).hexdigest()
-            # Look in cache first.
             if config.cache_dir:
                 cache_filename = join(config.cache_dir, '%s.html' % hash)
             if config.cache_dir and exists(cache_filename):

slipper/config.py

     # Find default information.
     default = RepositoryInfo(
         cache_dir = config.pop('slipper.DEFAULT.cache_dir', None),
+        colorize = ColorizeInfo(config.pop('slipper.DEFAULT.colorize', '')),
         rst_extension = config.pop('slipper.DEFAULT.rst_extension', '.rst'),
         stylesheet_path = config.pop('slipper.DEFAULT.stylesheet_path', None),
         local_dir = None,
             continue
         _, repo_name, config_key = keyparts
         config = repo_map.setdefault(repo_name, default.copy())
+        if config_key == 'colorize':
+            value = ColorizeInfo(value)
         setattr(config, config_key, value)
     # Done.
     return repo_map
 
 
+class ColorizeInfo(object):
+    
+    def __init__(self, colorize_string):
+        # Split by comma.
+        parts = [part.strip() for part in colorize_string.split(',')]
+        # Remove blanks and split by spaces.
+        parts = [part.split() for part in parts if part]
+        # Turn into dictionary.
+        self.ext_info = dict((part[0], part[1:]) for part in parts)
+        
+    def colorize_info(self, path):
+        """Return a dictionary based on `path` that contains the following
+        keys, or `None` if the file should not be colorized.
+        
+        - `original_ext`: Original extension to use to find the file to
+          colorize.
+        - `original_path`: The path that should be accessed to retrieve the
+          file to colorize.
+        - `lexer`: The name of the Pygments lexer to use.
+        - `variant`: The name of the Pygments renderer variant to use, or 
+          None if not specified.
+        """
+        for extension in self.ext_info:
+            if path.endswith(extension):
+                parts = self.ext_info[extension]
+                info = dict(
+                    original_ext = parts[0],
+                    lexer = parts[1],
+                    )
+                if len(parts) == 3:
+                    info['variant'] = parts[2]
+                else:
+                    info['variant'] = None
+                path_without_ext = path[:len(path)-len(extension)]
+                info['original_path'] = (
+                    path_without_ext + info['original_ext'])
+                return info
+        return None
+        
+
 class RepositoryInfo(object):
 
     def __init__(self, **kw):