# coding=utf-8
"""
Similar to syntax_color.py but this is intended more for being able to
copy+paste actual code into your Django templates without needing to
escape or anything crazy.

http://lobstertech.com/2008/aug/30/django_syntax_highlight_template_tag/

Example:

 {% load highlighting %}

 <style>
 @import url("http://lobstertech.com/media/css/highlight.css");
 .highlight { background: #f8f8f8; }
 .highlight { font-size: 11px; margin: 1em; border: 1px solid #ccc;
              border-left: 3px solid #F90; padding: 0; }
 .highlight pre { padding: 1em; overflow: auto; line-height: 120%; margin: 0; }
 .predesc { margin: 1.5em 1.5em -2.5em 1em; text-align: right;
            font: bold 12px Tahoma, Arial, sans-serif;
            letter-spacing: 1px; color: #333; }
 </style>

 <h2>check out this code</h2>

 {% highlight 'python' 'Excerpt: blah.py' %}
 def need_food(self):
     print("Love is <colder> than &death&")
 {% endhighlight %}

"""

import django
from django import template
from django.template import (
    Context, Node, Template, TemplateSyntaxError, Variable,
)
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe

try:
    from pygments import highlight as pyghighlight
    from pygments.lexers import get_lexer_by_name
    from pygments.formatters import HtmlFormatter
    HAS_PYGMENTS = True
except ImportError:
    HAS_PYGMENTS = False

register = template.Library()


@stringfilter
def parse_template(value):
    return mark_safe(Template(value).render(Context()))
parse_template.is_safe = True

if django.get_version() >= "1.4":
    register.filter(parse_template, is_safe=True)
else:
    parse_template.is_safe = True
    register.filter(parse_template)


class CodeNode(Node):
    def __init__(self, language, nodelist, name=''):
        self.language = Variable(language)
        self.nodelist = nodelist
        if name:
            self.name = Variable(name)
        else:
            self.name = None

    def render(self, context):
        code = self.nodelist.render(context).strip()
        lexer = get_lexer_by_name(self.language.resolve(context))
        formatter = HtmlFormatter(linenos=False)
        html = ""
        if self.name:
            name = self.name.resolve(context)
            html = '<div class="predesc"><span>%s</span></div>' % name
        return html + pyghighlight(code, lexer, formatter)


@register.tag
def highlight(parser, token):
    """
    Allows you to put a highlighted source code <pre> block in your code.
    This takes two arguments, the language and a little explaination message
    that will be generated before the code.  The second argument is optional.

    Your code will be fed through pygments so you can use any language it
    supports.

    Usage::

      {% load highlighting %}
      {% highlight 'python' 'Excerpt: blah.py' %}
      def need_food(self):
          print("Love is colder than death")
      {% endhighlight %}

    """
    if not HAS_PYGMENTS:
        raise ImportError("Please install 'pygments' library to use highlighting.")
    nodelist = parser.parse(('endhighlight',))
    parser.delete_first_token()
    bits = token.split_contents()[1:]
    if len(bits) < 1:
        raise TemplateSyntaxError("'highlight' statement requires an argument")
    return CodeNode(bits[0], nodelist, *bits[1:])
