summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Hatch <tim@timhatch.com>2014-04-14 17:18:09 -0400
committerTim Hatch <tim@timhatch.com>2014-04-14 17:18:09 -0400
commitd5fbe891177b85ada9d54239b1e86be059c63fc9 (patch)
tree5a25c483b54a330edb54940a98f5dfa36295d8d1
parent653fafe1d33ceb7c4c0771c113e77926157db192 (diff)
parentad810cad22484e52bacc1b065d187c67dd1220bb (diff)
downloadpygments-d5fbe891177b85ada9d54239b1e86be059c63fc9.tar.gz
Merged in tboyt/pygments-main (pull request #186)
Conflicts: pygments/lexers/_mapping.py pygments/lexers/templates.py
-rw-r--r--pygments/lexers/_mapping.py4
-rw-r--r--pygments/lexers/templates.py64
-rw-r--r--tests/examplefiles/demo.hbs12
-rw-r--r--tests/examplefiles/ember.handlebars33
4 files changed, 111 insertions, 2 deletions
diff --git a/pygments/lexers/_mapping.py b/pygments/lexers/_mapping.py
index 79da0b5f..88909fb4 100644
--- a/pygments/lexers/_mapping.py
+++ b/pygments/lexers/_mapping.py
@@ -137,6 +137,8 @@ LEXERS = {
'GroffLexer': ('pygments.lexers.text', 'Groff', ('groff', 'nroff', 'man'), ('*.[1234567]', '*.man'), ('application/x-troff', 'text/troff')),
'GroovyLexer': ('pygments.lexers.jvm', 'Groovy', ('groovy',), ('*.groovy',), ('text/x-groovy',)),
'HamlLexer': ('pygments.lexers.web', 'Haml', ('haml',), ('*.haml',), ('text/x-haml',)),
+ 'HandlebarsHtmlLexer': ('pygments.lexers.templates', 'HTML+Handlebars', ('html+handlebars',), ('*.handlebars', '*.hbs'), ('text/html+handlebars', 'text/x-handlebars-template')),
+ 'HandlebarsLexer': ('pygments.lexers.templates', 'Handlebars', ('handlebars',), (), ()),
'HaskellLexer': ('pygments.lexers.functional', 'Haskell', ('haskell', 'hs'), ('*.hs',), ('text/x-haskell',)),
'HaxeLexer': ('pygments.lexers.web', 'Haxe', ('hx', 'haxe', 'hxsl'), ('*.hx', '*.hxsl'), ('text/haxe', 'text/x-haxe', 'text/x-hx')),
'HtmlDjangoLexer': ('pygments.lexers.templates', 'HTML+Django/Jinja', ('html+django', 'html+jinja', 'htmldjango'), (), ('text/html+django', 'text/html+jinja')),
@@ -287,7 +289,7 @@ LEXERS = {
'RubyConsoleLexer': ('pygments.lexers.agile', 'Ruby irb session', ('rbcon', 'irb'), (), ('text/x-ruby-shellsession',)),
'RubyLexer': ('pygments.lexers.agile', 'Ruby', ('rb', 'ruby', 'duby'), ('*.rb', '*.rbw', 'Rakefile', '*.rake', '*.gemspec', '*.rbx', '*.duby'), ('text/x-ruby', 'application/x-ruby')),
'RustLexer': ('pygments.lexers.compiled', 'Rust', ('rust',), ('*.rs',), ('text/x-rustsrc',)),
- 'SLexer': ('pygments.lexers.math', 'S', ('splus', 's', 'r'), ('*.S', '*.R', '.Rhistory', '.Rprofile'), ('text/S-plus', 'text/S', 'text/x-r-source', 'text/x-r', 'text/x-R', 'text/x-r-history', 'text/x-r-profile')),
+ 'SLexer': ('pygments.lexers.math', 'S', ('splus', 's', 'r'), ('*.S', '*.R', '.Rhistory', '.Rprofile', '.Renviron'), ('text/S-plus', 'text/S', 'text/x-r-source', 'text/x-r', 'text/x-R', 'text/x-r-history', 'text/x-r-profile')),
'SMLLexer': ('pygments.lexers.functional', 'Standard ML', ('sml',), ('*.sml', '*.sig', '*.fun'), ('text/x-standardml', 'application/x-standardml')),
'SassLexer': ('pygments.lexers.web', 'Sass', ('sass',), ('*.sass',), ('text/x-sass',)),
'ScalaLexer': ('pygments.lexers.jvm', 'Scala', ('scala',), ('*.scala',), ('text/x-scala',)),
diff --git a/pygments/lexers/templates.py b/pygments/lexers/templates.py
index 72f81d63..a2de2f9c 100644
--- a/pygments/lexers/templates.py
+++ b/pygments/lexers/templates.py
@@ -39,7 +39,8 @@ __all__ = ['HtmlPhpLexer', 'XmlPhpLexer', 'CssPhpLexer',
'ColdfusionHtmlLexer', 'ColdfusionCFCLexer', 'VelocityLexer',
'VelocityHtmlLexer', 'VelocityXmlLexer', 'SspLexer',
'TeaTemplateLexer', 'LassoHtmlLexer', 'LassoXmlLexer',
- 'LassoCssLexer', 'LassoJavascriptLexer']
+ 'LassoCssLexer', 'LassoJavascriptLexer', 'HandlebarsLexer',
+ 'HandlebarsHtmlLexer']
class ErbLexer(Lexer):
@@ -1762,3 +1763,64 @@ class LassoJavascriptLexer(DelegatingLexer):
if 'function' in text:
rv += 0.2
return rv
+
+class HandlebarsLexer(RegexLexer):
+ """
+ Generic `handlebars <http://handlebarsjs.com/>` template lexer.
+
+ Highlights only the Handlebars template tags (stuff between `{{` and `}}`).
+ Everything else is left for a delegating lexer.
+ """
+
+ name = "Handlebars"
+ aliases = ['handlebars']
+
+ tokens = {
+ 'root': [
+ (r'[^{]+', Other),
+
+ (r'{{!.*}}', Comment),
+
+ (r'({{{)(\s*)', bygroups(Comment.Special, Text), 'tag'),
+ (r'({{)(\s*)', bygroups(Comment.Preproc, Text), 'tag'),
+ ],
+
+ 'tag': [
+ (r'\s+', Text),
+ (r'\}\}\}', Comment.Special, '#pop'),
+ (r'\}\}', Comment.Preproc, '#pop'),
+
+ # Handlebars
+ (r'([\#/]*)(each|if|unless|else|with|log|in)', bygroups(Keyword,
+ Keyword)),
+
+ # General {{#block}}
+ (r'([\#/])(\w+)', bygroups(Name.Function, Name.Function)),
+
+ # {{opt=something}}
+ (r'(\w+)(=)', bygroups(Name.Attribute, Operator)),
+
+ # borrowed from DjangoLexer
+ (r':?"(\\\\|\\"|[^"])*"', String.Double),
+ (r":?'(\\\\|\\'|[^'])*'", String.Single),
+ (r'[a-zA-Z][a-zA-Z0-9_-]*', Name.Variable),
+ (r'\.[a-zA-Z0-9_]+', Name.Variable),
+ (r"[0-9](\.[0-9]*)?(eE[+-][0-9])?[flFLdD]?|"
+ r"0[xX][0-9a-fA-F]+[Ll]?", Number),
+ ]
+ }
+
+
+class HandlebarsHtmlLexer(DelegatingLexer):
+ """
+ Subclass of the `HandlebarsLexer` that highlights unlexed data with the
+ `HtmlLexer`.
+ """
+
+ name = "HTML+Handlebars"
+ aliases = ["html+handlebars"]
+ filenames = ['*.handlebars', '*.hbs']
+ mimetypes = ['text/html+handlebars', 'text/x-handlebars-template']
+
+ def __init__(self, **options):
+ super(HandlebarsHtmlLexer, self).__init__(HtmlLexer, HandlebarsLexer, **options)
diff --git a/tests/examplefiles/demo.hbs b/tests/examplefiles/demo.hbs
new file mode 100644
index 00000000..1b9ed5a7
--- /dev/null
+++ b/tests/examplefiles/demo.hbs
@@ -0,0 +1,12 @@
+<!-- post.handlebars -->
+
+<div class='intro'>
+ {{intro}}
+</div>
+
+{{#if isExpanded}}
+ <div class='body'>{{body}}</div>
+ <button {{action contract}}>Contract</button>
+{{else}}
+ <button {{action expand}}>Show More...</button>
+{{/if}}
diff --git a/tests/examplefiles/ember.handlebars b/tests/examplefiles/ember.handlebars
new file mode 100644
index 00000000..515dffbd
--- /dev/null
+++ b/tests/examplefiles/ember.handlebars
@@ -0,0 +1,33 @@
+{{#view EmberFirebaseChat.ChatView class="chat-container"}}
+ <div class="chat-messages-container">
+ <ul class="chat-messages">
+ {{#each message in content}}
+ <li>
+ [{{formatTimestamp "message.timestamp" fmtString="h:mm:ss A"}}]
+ <strong>{{message.sender}}</strong>: {{message.content}}
+ </li>
+ {{/each}}
+ </ul>
+ </div>
+
+ {{! Comment }}
+ {{{unescaped value}}}
+
+ {{#view EmberFirebaseChat.InputView class="chat-input-container"}}
+ <form class="form-inline">
+ {{#if "auth.authed"}}
+ {{#if "auth.hasName"}}
+ <input type="text" id="message" placeholder="Message">
+ <button {{action "postMessage" target="view"}} class="btn">Send</button>
+ {{else}}
+ <input type="text" id="username" placeholder="Enter your username...">
+ <button {{action "pickName" target="view"}} class="btn">Send</button>
+ {{/if}}
+ {{else}}
+ <input type="text" placeholder="Log in with Persona to chat!" disabled="disabled">
+ <button {{action "login"}} class="btn">Login</button>
+ {{/if}}
+ </form>
+ {{/view}}
+{{/view}}
+