1# -*- coding: utf-8 -*- 2r""" 3Template filter for rendering a string with syntax highlighting. 4It relies on Pygments to accomplish this. 5 6Some standard usage examples (from within Django templates). 7Coloring a string with the Python lexer: 8 9 {% load syntax_color %} 10 {{ code_string|colorize:"python" }} 11 12You may use any lexer in Pygments. The complete list of which 13can be found [on the Pygments website][1]. 14 15[1]: http://pygments.org/docs/lexers/ 16 17You may also have Pygments attempt to guess the correct lexer for 18a particular string. However, if may not be able to choose a lexer, 19in which case it will simply return the string unmodified. This is 20less efficient compared to specifying the lexer to use. 21 22 {{ code_string|colorize }} 23 24You may also render the syntax highlighed text with line numbers. 25 26 {% load syntax_color %} 27 {{ some_code|colorize_table:"html+django" }} 28 {{ let_pygments_pick_for_this_code|colorize_table }} 29 30Please note that before you can load the ``syntax_color`` template filters 31you will need to add the ``django_extensions.utils`` application to the 32``INSTALLED_APPS``setting in your project's ``settings.py`` file. 33""" 34import os 35 36from django import template 37from django.template.defaultfilters import stringfilter 38from django.utils.safestring import mark_safe 39 40try: 41 from pygments import highlight 42 from pygments.formatters import HtmlFormatter 43 from pygments.lexers import get_lexer_by_name, guess_lexer, ClassNotFound 44 HAS_PYGMENTS = True 45except ImportError: # pragma: no cover 46 HAS_PYGMENTS = False 47 48__author__ = 'Will Larson <lethain@gmail.com>' 49 50 51register = template.Library() 52 53 54def pygments_required(func): 55 """Raise ImportError if pygments is not installed.""" 56 def wrapper(*args, **kwargs): 57 if not HAS_PYGMENTS: # pragma: no cover 58 raise ImportError( 59 "Please install 'pygments' library to use syntax_color.") 60 rv = func(*args, **kwargs) 61 return rv 62 return wrapper 63 64 65@pygments_required 66@register.simple_tag 67def pygments_css(): 68 return HtmlFormatter().get_style_defs('.highlight') 69 70 71def generate_pygments_css(path=None): 72 path = os.path.join(path or os.getcwd(), 'pygments.css') 73 f = open(path, 'w') 74 f.write(pygments_css()) 75 f.close() 76 77 78def get_lexer(value, arg): 79 if arg is None: 80 return guess_lexer(value) 81 return get_lexer_by_name(arg) 82 83 84@pygments_required 85@register.filter(name='colorize') 86@stringfilter 87def colorize(value, arg=None): 88 try: 89 return mark_safe(highlight(value, get_lexer(value, arg), HtmlFormatter())) 90 except ClassNotFound: 91 return value 92 93 94@pygments_required 95@register.filter(name='colorize_table') 96@stringfilter 97def colorize_table(value, arg=None): 98 try: 99 return mark_safe(highlight(value, get_lexer(value, arg), HtmlFormatter(linenos='table'))) 100 except ClassNotFound: 101 return value 102 103 104@pygments_required 105@register.filter(name='colorize_noclasses') 106@stringfilter 107def colorize_noclasses(value, arg=None): 108 try: 109 return mark_safe(highlight(value, get_lexer(value, arg), HtmlFormatter(noclasses=True))) 110 except ClassNotFound: 111 return value 112