summaryrefslogtreecommitdiff
path: root/pygments/lexers/templates.py
diff options
context:
space:
mode:
Diffstat (limited to 'pygments/lexers/templates.py')
-rw-r--r--pygments/lexers/templates.py323
1 files changed, 323 insertions, 0 deletions
diff --git a/pygments/lexers/templates.py b/pygments/lexers/templates.py
new file mode 100644
index 00000000..3a735d15
--- /dev/null
+++ b/pygments/lexers/templates.py
@@ -0,0 +1,323 @@
+# -*- coding: utf-8 -*-
+"""
+ pygments.lexers.templates
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Lexers for various template engines.
+
+ :copyright: 2006 by Armin Ronacher, Georg Brandl.
+ :license: GNU LGPL, see LICENSE for more details.
+"""
+
+import re
+try:
+ set
+except NameError:
+ from sets import Set as set
+
+from pygments.lexers.web import \
+ PhpLexer, HtmlLexer, XmlLexer, JavascriptLexer, CssLexer
+from pygments.lexer import \
+ Lexer, DelegatingLexer, RegexLexer, do_insertions, bygroups, include, using
+from pygments.token import \
+ Text, Comment, Operator, Keyword, Name, String, Number, Other
+
+__all__ = ['HtmlPhpLexer', 'XmlPhpLexer', 'CssPhpLexer',
+ 'JavascriptPhpLexer', 'ErbLexer', 'RhtmlLexer',
+ 'XmlErbLexer', 'CssErbLexer', 'JavascriptErbLexer',
+ 'SmartyLexer', 'HtmlSmartyLexer', 'XmlSmartyLexer',
+ 'CssSmartyLexer', 'JavascriptSmartyLexer', 'DjangoLexer',
+ 'HtmlDjangoLexer', 'CssDjangoLexer', 'XmlDjangoLexer',
+ 'JavascriptDjangoLexer']
+
+
+class ErbLexer(Lexer):
+ name = 'ERB'
+ aliases = ['erb']
+
+ _block_re = re.compile(r'(<%%|%%>|<%=|<%#|<%-|<%|-%>|%>|^%[^%].*?$)', re.M)
+
+ def __init__(self, **options):
+ from pygments.lexers.agile import RubyLexer
+ self.ruby_lexer = RubyLexer(**options)
+ Lexer.__init__(self, **options)
+
+ def get_tokens_unprocessed(self, text):
+ """
+ Since ERB doesn't allow "<%" and other tags inside of ruby
+ blocks we have to use a split approach here that fails for
+ that too.
+ """
+ tokens = self._block_re.split(text)
+ tokens.reverse()
+ state = idx = 0
+ try:
+ while True:
+ # text
+ if state == 0:
+ val = tokens.pop()
+ yield idx, Other, val
+ idx += len(val)
+ state = 1
+ # block starts
+ elif state == 1:
+ tag = tokens.pop()
+ # literals
+ if tag in ('<%%', '%%>'):
+ yield idx, Other, tag
+ idx += 3
+ state = 0
+ # comment
+ elif tag == '<%#':
+ yield idx, Comment.Preproc, tag
+ val = tokens.pop()
+ yield idx + 3, Comment, val
+ idx += 3 + len(val)
+ state = 2
+ # blocks or output
+ elif tag in ('<%', '<%=', '<%-'):
+ yield idx, Comment.Preproc, tag
+ idx += len(tag)
+ data = tokens.pop()
+ r_idx = 0
+ for r_idx, r_token, r_value in \
+ self.ruby_lexer.get_tokens_unprocessed(data):
+ yield r_idx + idx, r_token, r_value
+ idx += len(data)
+ state = 2
+ elif tag in ('%>', '-%>'):
+ yield idx, Error, tag
+ idx += len(tag)
+ state = 0
+ # % raw ruby statements
+ else:
+ yield idx, Comment.Preproc, tag[0]
+ r_idx = 0
+ for r_idx, r_token, r_value in \
+ self.ruby_lexer.get_tokens_unprocessed(tag[1:]):
+ yield idx + 1 + r_idx, r_token, r_value
+ idx += len(tag)
+ state = 0
+ # block ends
+ elif state == 2:
+ tag = tokens.pop()
+ if tag not in ('%>', '-%>'):
+ yield idx, Other, tag
+ else:
+ yield idx, Comment.Preproc, tag
+ idx += len(tag)
+ state = 0
+ except IndexError:
+ return
+
+
+class SmartyLexer(RegexLexer):
+ name = 'Smarty'
+ aliases = ['smarty']
+
+ flags = re.MULTILINE | re.DOTALL
+
+ tokens = {
+ # XXX: make marty delimiters customizable somehow
+ 'root': [
+ (r'[^{]+', Other),
+ (r'(\{)(\*.*?\*)(\})',
+ bygroups(Comment.Preproc, Comment, Comment.Preproc)),
+ (r'(\{php\})(.*?)(\{/php\})',
+ bygroups(Comment.Preproc, using(PhpLexer, startinline=True),
+ Comment.Preproc)),
+ (r'(\{)(/?[a-zA-Z_][a-zA-Z0-9_]*)(\s*)',
+ bygroups(Comment.Preproc, Name.Function, Text), 'smarty'),
+ (r'\{', Comment.Preproc, 'smarty')
+ ],
+ 'smarty': [
+ (r'\s+', Text),
+ (r'\}', Comment.Preproc, '#pop'),
+ (r'#[a-zA-Z_][a-zA-Z0-9_]*#', Name.Variable),
+ (r'\$[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z0-9_]+)*', Name.Variable),
+ (r'[~!%^&*()+=|\[\]:;,.<>/?{}@-]', Operator),
+ ('(true|false|null)\b', Keyword.Constant),
+ (r"[0-9](\.[0-9]*)?(eE[+-][0-9])?[flFLdD]?|"
+ r"0[xX][0-9a-fA-F]+[Ll]?", Number),
+ (r'"(\\\\|\\"|[^"])*"', String.Double),
+ (r"'(\\\\|\\'|[^'])*'", String.Single),
+ (r'[a-zA-Z_][a-zA-Z0-9_]*', Name.Attribute)
+ ]
+ }
+
+
+class DjangoLexer(RegexLexer):
+ name = 'django template'
+ aliases = ['django']
+
+ tokens = {
+ 'root': [
+ (r'[^\{]+', Other),
+ (r'\{\{', Comment.Preproc, 'var'),
+ (r'(\{\%)(\s*)(comment)(\s*)(\%\})(.*?)'
+ r'(\{\%)(\s*)(endcomment)(\s*)(\%\})',
+ bygroups(Comment.Preproc, Text, Keyword, Text, Comment.Preproc,
+ Comment, Comment.Preproc, Text, Keyword, Text,
+ Comment.Preproc)),
+ (r'(\{\%)(\s*)([a-zA-Z_][a-zA-Z0-9_]*)',
+ bygroups(Comment.Preproc, Text, Keyword), 'block'),
+ (r'\{', Other)
+ ],
+ 'varnames': [
+ (r'[a-zA-Z][a-zA-Z0-9_]*(\.[a-zA-Z][a-zA-Z0-9_]*)*', Name.Variable),
+ (r"(\|)([a-zA-Z_][a-zA-Z0-9_]*)(:'(\\\\|\\'|[^'])*')",
+ bygroups(Operator, Name.Function, String.Single)),
+ (r'(\|)([a-zA-Z_][a-zA-Z0-9_]*)(:"(\\\\|\\"|[^"])*")',
+ bygroups(Operator, Name.Function, String.Double)),
+ (r'(\|)([a-zA-Z_][a-zA-Z0-9_]*)',
+ bygroups(Operator, Name.Function))
+ ],
+ 'var': [
+ (r'\s+', Text),
+ include('varnames'),
+ (r'\}\}', Comment.Preproc, '#pop')
+ ],
+ 'block': [
+ (r'\s+', Text),
+ (r'(in|as|reversed|not|count|and|or|with)\b', Keyword),
+ (r'"(\\\\|\\"|[^"])*"', String.Double),
+ (r"'(\\\\|\\'|[^'])*'", String.Single),
+ include('varnames'),
+ (r'\%\}', Comment.Preproc, '#pop'),
+ (r'.', Text)
+ ]
+ }
+
+
+class RhtmlLexer(DelegatingLexer):
+ name = 'RHTML'
+ aliases = ['rhtml', 'html+erb', 'html+ruby']
+ filenames = ['*.rhtml']
+
+ def __init__(self, **options):
+ super(RhtmlLexer, self).__init__(HtmlLexer, ErbLexer, **options)
+
+
+class XmlErbLexer(DelegatingLexer):
+ name = 'XML+Ruby'
+ aliases = ['xml+erb', 'xml+ruby']
+
+ def __init__(self, **options):
+ super(XmlErbLexer, self).__init__(XmlLexer, ErbLexer, **options)
+
+
+class CssErbLexer(DelegatingLexer):
+ name = 'CSS+Ruby'
+ aliases = ['css+erb', 'css+ruby']
+
+ def __init__(self, **options):
+ super(CssErbLexer, self).__init__(CssLexer, ErbLexer, **options)
+
+
+class JavascriptErbLexer(DelegatingLexer):
+ name = 'JavaScript+Ruby'
+ aliases = ['js+erb', 'javascript+erb', 'js+ruby', 'javascript+ruby']
+
+ def __init__(self, **options):
+ super(JavascriptErbLexer, self).__init__(JavascriptLexer, ErbLexer,
+ **options)
+
+
+class HtmlPhpLexer(DelegatingLexer):
+ name = 'HTML+PHP'
+ aliases = ['html+php']
+ filenames = ['*.phtml']
+
+ def __init__(self, **options):
+ super(HtmlPhpLexer, self).__init__(HtmlLexer, PhpLexer, **options)
+
+
+class XmlPhpLexer(DelegatingLexer):
+ name = 'XML+PHP'
+ aliases = ['xml+php']
+
+ def __init__(self, **options):
+ super(XmlPhpLexer, self).__init__(XmlLexer, PhpLexer, **options)
+
+
+class CssPhpLexer(DelegatingLexer):
+ name = 'CSS+PHP'
+ aliases = ['css+php']
+
+ def __init__(self, **options):
+ super(CssPhpLexer, self).__init__(CssLexer, PhpLexer, **options)
+
+
+class JavascriptPhpLexer(DelegatingLexer):
+ name = 'JavaScript+PHP'
+ aliases = ['js+php', 'javascript+php']
+
+ def __init__(self, **options):
+ super(JavascriptPhpLexer, self).__init__(JavascriptLexer, PhpLexer,
+ **options)
+
+
+class HtmlSmartyLexer(DelegatingLexer):
+ name = 'HTML+Smarty'
+ aliases = ['html+smarty']
+
+ def __init__(self, **options):
+ super(HtmlSmartyLexer, self).__init__(HtmlLexer, SmartyLexer, **options)
+
+
+class XmlSmartyLexer(DelegatingLexer):
+ name = 'XML+Smarty'
+ aliases = ['xml+smarty']
+
+ def __init__(self, **options):
+ super(XmlSmartyLexer, self).__init__(XmlLexer, SmartyLexer, **options)
+
+
+class CssSmartyLexer(DelegatingLexer):
+ name = 'CSS+Smarty'
+ aliases = ['css+smarty']
+
+ def __init__(self, **options):
+ super(CssSmartyLexer, self).__init__(CssLexer, SmartyLexer, **options)
+
+
+class JavascriptSmartyLexer(DelegatingLexer):
+ name = 'JavaScript+Smarty'
+ aliases = ['js+smarty', 'javascript+smarty']
+
+ def __init__(self, **options):
+ super(JavascriptSmartyLexer, self).__init__(JavascriptLexer, SmartyLexer,
+ **options)
+
+
+class HtmlDjangoLexer(DelegatingLexer):
+ name = 'HTML+Django'
+ aliases = ['html+django']
+
+ def __init__(self, **options):
+ super(HtmlDjangoLexer, self).__init__(HtmlLexer, DjangoLexer, **options)
+
+
+class XmlDjangoLexer(DelegatingLexer):
+ name = 'XML+Django'
+ aliases = ['xml+django']
+
+ def __init__(self, **options):
+ super(XmlDjangoLexer, self).__init__(XmlLexer, DjangoLexer, **options)
+
+
+class CssDjangoLexer(DelegatingLexer):
+ name = 'CSS+Django'
+ aliases = ['css+django']
+
+ def __init__(self, **options):
+ super(CssDjangoLexer, self).__init__(CssLexer, DjangoLexer, **options)
+
+
+class JavascriptDjangoLexer(DelegatingLexer):
+ name = 'JavaScript+Django'
+ aliases = ['js+django', 'javascript+django']
+
+ def __init__(self, **options):
+ super(JavascriptDjangoLexer, self).__init__(JavascriptLexer, DjangoLexer,
+ **options)