Skip to content

Commit

Permalink
Add support for Go templates.
Browse files Browse the repository at this point in the history
These are exposed as go-text-template and go-html-template.

Fixes #105.
  • Loading branch information
alecthomas committed Mar 18, 2018
1 parent db6920e commit f315512
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 4 deletions.
53 changes: 52 additions & 1 deletion lexers/g/go.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"strings"

. "github.com/alecthomas/chroma" // nolint
"github.com/alecthomas/chroma/lexers/h"
"github.com/alecthomas/chroma/lexers/internal"
)

Expand Down Expand Up @@ -38,7 +39,7 @@ var Go = internal.Register(MustNewLexer(
{`0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil},
{`(0|[1-9][0-9]*)`, LiteralNumberInteger, nil},
{`'(\\['"\\abfnrtv]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|[^\\])'`, LiteralStringChar, nil},
{"`[^`]*`", LiteralString, nil},
{"(`)([^`]*)(`)", ByGroups(LiteralString, Using(TypeRemappingLexer(GoTextTemplate, TypeMapping{{Other, LiteralString, nil}})), LiteralString), nil},
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
{`(<<=|>>=|<<|>>|<=|>=|&\^=|&\^|\+=|-=|\*=|/=|%=|&=|\|=|&&|\|\||<-|\+\+|--|==|!=|:=|\.\.\.|[+\-*/%&])`, Operator, nil},
{`[|^<>=!()\[\]{}.,;:]`, Punctuation, nil},
Expand All @@ -54,3 +55,53 @@ var Go = internal.Register(MustNewLexer(
}
return 0.0
}))

var goTemplateRules = Rules{
"root": {
{`{{[-]?`, CommentPreproc, Push("template")},
{`[^{]+`, Other, nil},
{`{`, Other, nil},
},
"template": {
{`[-]?}}`, CommentPreproc, Pop(1)},
{`\s+`, Whitespace, nil},
{`/\*.*?\*/`, Comment, nil},
{`(?=}})`, CommentPreproc, Pop(1)}, // Terminate the pipeline
{`\(`, Operator, Push("subexpression")},
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
Include("expression"),
},
"subexpression": {
{`\)`, Operator, Pop(1)},
Include("expression"),
},
"expression": {
{`\(`, Operator, Push("subexpression")},
{`(if|while|with|template|end|true|false|nil|and|call|html|index|js|len|not|or|print|printf|println|urlquery|eq|ne|lt|le|gt|ge)\b`, Keyword, nil},
{`\|`, Operator, nil},
{`[^\W\d]\w*`, NameOther, nil},
{`\.(?:[^\W\d]\w*)?`, NameAttribute, nil},
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
{`\d+i`, LiteralNumber, nil},
{`\d+\.\d*([Ee][-+]\d+)?i`, LiteralNumber, nil},
{`\.\d+([Ee][-+]\d+)?i`, LiteralNumber, nil},
{`\d+[Ee][-+]\d+i`, LiteralNumber, nil},
{`\d+(\.\d+[eE][+\-]?\d+|\.\d*|[eE][+\-]?\d+)`, LiteralNumberFloat, nil},
{`\.\d+([eE][+\-]?\d+)?`, LiteralNumberFloat, nil},
{`0[0-7]+`, LiteralNumberOct, nil},
{`0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil},
{`(0|[1-9][0-9]*)`, LiteralNumberInteger, nil},
{`'(\\['"\\abfnrtv]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|[^\\])'`, LiteralStringChar, nil},
{"`[^`]*`", LiteralString, nil},
},
}

var GoHTMLTemplate = internal.Register(DelegatingLexer(h.HTML, MustNewLexer(
&Config{Name: "go-html-template"},
goTemplateRules,
)))

var GoTextTemplate = internal.Register(MustNewLexer(
&Config{Name: "go-text-template"},
goTemplateRules,
))
6 changes: 5 additions & 1 deletion regexp.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,11 @@ func (l *LexerState) Iterator() *Token {
if l.Lexer.trace {
fmt.Fprintf(os.Stderr, "%s: pos=%d, text=%q\n", l.State, l.Pos, string(l.Text[l.Pos:]))
}
ruleIndex, rule, groups := matchRules(l.Text[l.Pos:], l.Rules[l.State])
selectedRule, ok := l.Rules[l.State]
if !ok {
panic("unknown state " + l.State)
}
ruleIndex, rule, groups := matchRules(l.Text[l.Pos:], selectedRule)
// No match.
if groups == nil {
l.Pos++
Expand Down
10 changes: 8 additions & 2 deletions remap.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,21 @@ func TypeRemappingLexer(lexer Lexer, mapping TypeMapping) Lexer {
km = map[string]TokenType{}
lut[rt.From] = km
}
for _, k := range rt.Words {
km[k] = rt.To
if len(rt.Words) == 0 {
km[""] = rt.To
} else {
for _, k := range rt.Words {
km[k] = rt.To
}
}

}
return RemappingLexer(lexer, func(t *Token) []*Token {
if k, ok := lut[t.Type]; ok {
if tt, ok := k[t.Value]; ok {
t.Type = tt
} else if tt, ok := k[""]; ok {
t.Type = tt
}
}
return []*Token{t}
Expand Down

0 comments on commit f315512

Please sign in to comment.