Repository: alecthomas/chroma
Pull request #401 (2020-09-22 12:08:04)

Improved support for Go templates
Improved support for Go templates:

* Multiline comments
* Negative numbers
* Simple assignment of variables

alecthomas: Nice!

Patch:
diff --git a/lexers/g/go.go b/lexers/g/go.go
index 33077e0..ef400b7 100644
--- a/lexers/g/go.go
+++ b/lexers/g/go.go
@@ -60,13 +60,13 @@ var Go = internal.Register(MustNewLexer(
 
 var goTemplateRules = Rules{
 	"root": {
+		{`{{(- )?/\*(.|\n)*?\*/( -)?}}`, CommentMultiline, nil},
 		{`{{[-]?`, CommentPreproc, Push("template")},
 		{`[^{]+`, Other, nil},
 		{`{`, Other, nil},
 	},
 	"template": {
 		{`[-]?}}`, CommentPreproc, Pop(1)},
-		{`/\*.*?\*/`, Comment, nil},
 		{`(?=}})`, CommentPreproc, Pop(1)}, // Terminate the pipeline
 		{`\(`, Operator, Push("subexpression")},
 		{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
@@ -80,19 +80,19 @@ var goTemplateRules = Rules{
 		{`\s+`, Whitespace, nil},
 		{`\(`, Operator, Push("subexpression")},
 		{`(range|if|else|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},
+		{`\||:?=`, 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+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},
+		{`-?\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},
 	},


Test patch:
diff --git a/lexers/g/go_test.go b/lexers/g/go_test.go
index 583681e..2b949b2 100644
--- a/lexers/g/go_test.go
+++ b/lexers/g/go_test.go
@@ -23,6 +23,9 @@ func TestGoHTMLTemplateIssue126(t *testing.T) {
     {{ with .OutputFormats.Get "RSS" }}
         {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
     {{ end }}
+	{{/*
+		Print all pages
+	*/}}
     {{ range .Data.Pages }}
     <item>
       <title>{{ .Title }}</title>
@@ -48,3 +51,72 @@ func TestGoHTMLTemplateIssue126(t *testing.T) {
 		assert.Equal(t, source, chroma.Stringify(tokens...))
 	}
 }
+
+func TestGoHTMLTemplateMultilineComments(t *testing.T) {
+	for _, source := range []string{
+		`
+{{/*
+	This is a multiline comment
+*/}}
+`,
+		`
+{{- /*
+	This is a multiline comment
+*/}}
+`,
+		`
+{{/*
+	This is a multiline comment
+*/ -}}
+`,
+		`
+{{- /*
+	This is a multiline comment
+*/ -}}
+`,
+	} {
+		tokens, err := chroma.Tokenise(GoHTMLTemplate, nil, source)
+		assert.NoError(t, err)
+		assert.Equal(t, source, chroma.Stringify(tokens...))
+
+		// Make sure that there are no errors
+		for _, token := range tokens {
+			assert.NotEqual(t, chroma.Error, token.Type)
+		}
+
+		// Make sure that multiline comments are printed
+		found := false
+		for _, token := range tokens {
+			if token.Type == chroma.CommentMultiline {
+				found = true
+			}
+		}
+		assert.True(t, found)
+	}
+}
+
+func TestGoHTMLTemplateNegativeNumber(t *testing.T) {
+	for _, source := range []string{
+		`
+{{ fn -3 }}
+`,
+	} {
+		tokens, err := chroma.Tokenise(GoHTMLTemplate, nil, source)
+		assert.NoError(t, err)
+		assert.Equal(t, source, chroma.Stringify(tokens...))
+
+		// Make sure that there are no errors
+		for _, token := range tokens {
+			assert.NotEqual(t, chroma.Error, token.Type)
+		}
+
+		// Make sure that negative number is found
+		found := false
+		for _, token := range tokens {
+			if token.Type == chroma.LiteralNumberInteger {
+				found = true
+			}
+		}
+		assert.True(t, found)
+	}
+}
diff --git a/lexers/lexers_test.go b/lexers/lexers_test.go
index 93d5189..8468a66 100644
--- a/lexers/lexers_test.go
+++ b/lexers/lexers_test.go
@@ -55,7 +55,7 @@ func TestLexers(t *testing.T) {
 			continue
 		}
 
-		base := strings.Split(strings.TrimSuffix(file.Name(), filepath.Ext(file.Name())), "-")[0]
+		base := strings.Split(strings.TrimSuffix(file.Name(), filepath.Ext(file.Name())), ".")[0]
 		lexer := lexers.Get(base)
 		assert.NotNil(t, lexer)
 
diff --git a/lexers/testdata/go-html-template.actual b/lexers/testdata/go-html-template.actual
new file mode 100644
index 0000000..7258787
--- /dev/null
+++ b/lexers/testdata/go-html-template.actual
@@ -0,0 +1,3 @@
+{{/*
+  This is a multiline comment
+*/}}
\ No newline at end of file
diff --git a/lexers/testdata/go-html-template.expected b/lexers/testdata/go-html-template.expected
new file mode 100644
index 0000000..6a32386
--- /dev/null
+++ b/lexers/testdata/go-html-template.expected
@@ -0,0 +1,3 @@
+[
+  {"type":"CommentMultiline","value":"{{/*\n  This is a multiline comment\n*/}}"}
+]
diff --git a/lexers/testdata/go-text-template.actual b/lexers/testdata/go-text-template.actual
new file mode 100644
index 0000000..7761c3d
--- /dev/null
+++ b/lexers/testdata/go-text-template.actual
@@ -0,0 +1,6 @@
+{{/*
+  This is a multiline comment
+*/}}
+
+{{ $myVar := 2 }}
+{{ $myVar = 4 }}
\ No newline at end of file
diff --git a/lexers/testdata/go-text-template.expected b/lexers/testdata/go-text-template.expected
new file mode 100644
index 0000000..f774669
--- /dev/null
+++ b/lexers/testdata/go-text-template.expected
@@ -0,0 +1,23 @@
+[
+  {"type":"CommentMultiline","value":"{{/*\n  This is a multiline comment\n*/}}"},
+  {"type":"Other","value":"\n\n"},
+  {"type":"CommentPreproc","value":"{{"},
+  {"type":"TextWhitespace","value":" "},
+  {"type":"NameOther","value":"$myVar"},
+  {"type":"TextWhitespace","value":" "},
+  {"type":"Operator","value":":="},
+  {"type":"TextWhitespace","value":" "},
+  {"type":"NameOther","value":"2"},
+  {"type":"TextWhitespace","value":" "},
+  {"type":"CommentPreproc","value":"}}"},
+  {"type":"Other","value":"\n"},
+  {"type":"CommentPreproc","value":"{{"},
+  {"type":"TextWhitespace","value":" "},
+  {"type":"NameOther","value":"$myVar"},
+  {"type":"TextWhitespace","value":" "},
+  {"type":"Operator","value":"="},
+  {"type":"TextWhitespace","value":" "},
+  {"type":"NameOther","value":"4"},
+  {"type":"TextWhitespace","value":" "},
+  {"type":"CommentPreproc","value":"}}"}
+]