Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Caddyfile lexer to fix edgecases and improve colouring #365

Merged
merged 3 commits into from May 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
117 changes: 59 additions & 58 deletions lexers/c/caddyfile.go
Expand Up @@ -5,15 +5,20 @@ import (
"github.com/alecthomas/chroma/lexers/internal"
)

// CaddyfileCommon are the rules common to both of the lexer variants
var CaddyfileCommon = Rules{
// caddyfileCommon are the rules common to both of the lexer variants
var caddyfileCommon = Rules{
"site_block_common": {
// Import keyword
{`(import)(\s+)([^\s]+)`, ByGroups(Keyword, Text, NameVariableMagic), nil},
// Matcher definition
{`@[^\s]+\s+`, NameDecorator, Push("matcher")},
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
// Matcher token stub for docs
{`\[\<matcher\>\]`, NameDecorator, Push("matcher")},
// These cannot have matchers but may have things that look like
// matchers in their arguments, so we just parse as a subdirective.
{`try_files`, Keyword, Push("subdirective")},
// These are special, they can nest more directives
{`handle|route|handle_path|not`, Keyword, Push("nested_directive")},
{`handle_errors|handle|route|handle_path|not`, Keyword, Push("nested_directive")},
// Any other directive
{`[^\s#]+`, Keyword, Push("directive")},
Include("base"),
Expand All @@ -40,7 +45,9 @@ var CaddyfileCommon = Rules{
"nested_block": {
{`\}`, Punctuation, Pop(2)},
// Matcher definition
{`@[^\s]+\s+`, NameDecorator, Push("matcher")},
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
// Something that starts with literally < is probably a docs stub
{`\<[^#]+\>`, Keyword, Push("nested_directive")},
// Any other directive
{`[^\s#]+`, Keyword, Push("nested_directive")},
Include("base"),
Expand All @@ -60,32 +67,33 @@ var CaddyfileCommon = Rules{
"directive": {
{`\{(?=\s)`, Punctuation, Push("block")},
Include("matcher_token"),
Include("comments_pop"),
Include("comments_pop_1"),
{`\n`, Text, Pop(1)},
Include("base"),
},
"nested_directive": {
{`\{(?=\s)`, Punctuation, Push("nested_block")},
Include("matcher_token"),
Include("comments_pop"),
Include("comments_pop_1"),
{`\n`, Text, Pop(1)},
Include("base"),
},
"subdirective": {
{`\{(?=\s)`, Punctuation, Push("block")},
Include("comments_pop"),
Include("comments_pop_1"),
{`\n`, Text, Pop(1)},
Include("base"),
},
"arguments": {
{`\{(?=\s)`, Punctuation, Push("block")},
Include("comments_pop"),
Include("comments_pop_2"),
{`\\\n`, Text, nil}, // Skip escaped newlines
{`\n`, Text, Pop(2)},
Include("base"),
},
"deep_subdirective": {
{`\{(?=\s)`, Punctuation, Push("block")},
Include("comments_pop"),
Include("comments_pop_3"),
{`\n`, Text, Pop(3)},
Include("base"),
},
Expand All @@ -99,30 +107,41 @@ var CaddyfileCommon = Rules{
{`^#.*\n`, CommentSingle, nil}, // Comment at start of line
{`\s+#.*\n`, CommentSingle, nil}, // Comment preceded by whitespace
},
"comments_pop": {
"comments_pop_1": {
{`^#.*\n`, CommentSingle, Pop(1)}, // Comment at start of line
{`\s+#.*\n`, CommentSingle, Pop(1)}, // Comment preceded by whitespace
},
"comments_pop_2": {
{`^#.*\n`, CommentSingle, Pop(2)}, // Comment at start of line
{`\s+#.*\n`, CommentSingle, Pop(2)}, // Comment preceded by whitespace
},
"comments_pop_3": {
{`^#.*\n`, CommentSingle, Pop(3)}, // Comment at start of line
{`\s+#.*\n`, CommentSingle, Pop(3)}, // Comment preceded by whitespace
},
"base": {
Include("comments"),
{`on|off`, NameConstant, nil},
{`(on|off|first|last|before|after|internal|strip_prefix|strip_suffix|replace)\b`, NameConstant, nil},
{`(https?://)?([a-z0-9.-]+)(:)([0-9]+)`, ByGroups(Name, Name, Punctuation, LiteralNumberInteger), nil},
{`[a-z-]+/[a-z-+]+`, LiteralString, nil},
{`[0-9]+[km]?\b`, LiteralNumberInteger, nil},
{`\{[\w+.-]+\}`, NameAttribute, nil}, // Placeholder
{`[^\s#{}$]+`, LiteralString, nil},
{`\{[\w+.\$-]+\}`, LiteralStringEscape, nil}, // Placeholder
{`\[(?=[^#{}$]+\])`, Punctuation, nil},
{`\]|\|`, Punctuation, nil},
{`[^\s#{}$\]]+`, LiteralString, nil},
{`/[^\s#]*`, Name, nil},
{`\s+`, Text, nil},
},
}

// CaddyfileRules are the merged rules for the main Caddyfile lexer
var CaddyfileRules = (func(a Rules, b Rules) Rules {
for k, v := range b {
a[k] = v
}
return a
})(
// Caddyfile lexer.
var Caddyfile = internal.Register(MustNewLexer(
&Config{
Name: "Caddyfile",
Aliases: []string{"caddyfile", "caddy"},
Filenames: []string{"Caddyfile*"},
MimeTypes: []string{},
},
Rules{
"root": {
Include("comments"),
Expand All @@ -131,28 +150,33 @@ var CaddyfileRules = (func(a Rules, b Rules) Rules {
// Snippets
{`(\([^\s#]+\))(\s*)(\{)`, ByGroups(NameVariableAnonymous, Text, Punctuation), Push("snippet")},
// Site label
{`[^#{(\s,]+`, NameLabel, Push("label")},
{`[^#{(\s,]+`, GenericHeading, Push("label")},
// Site label with placeholder
{`\{[\w+.-]+\}`, NameAttribute, Push("label")},
{`\{[\w+.\$-]+\}`, LiteralStringEscape, Push("label")},
{`\s+`, Text, nil},
},
"globals": {
{`\}`, Punctuation, Pop(1)},
{`[^\s#]+`, KeywordType, Push("directive")},
{`[^\s#]+`, Keyword, Push("directive")},
Include("base"),
},
"snippet": {
{`\}`, Punctuation, Pop(1)},
// Matcher definition
{`@[^\s]+\s+`, NameDecorator, Push("matcher")},
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
// Any directive
{`[^\s#]+`, KeywordType, Push("directive")},
{`[^\s#]+`, Keyword, Push("directive")},
Include("base"),
},
"label": {
{`,`, Text, nil},
// Allow multiple labels, comma separated, newlines after
// a comma means another label is coming
{`,\s*\n?`, Text, nil},
{` `, Text, nil},
{`[^#{(\s,]+`, NameLabel, nil},
// Site label with placeholder
{`\{[\w+.\$-]+\}`, LiteralStringEscape, nil},
// Site label
{`[^#{(\s,]+`, GenericHeading, nil},
// Comment after non-block label (hack because comments end in \n)
{`#.*\n`, CommentSingle, Push("site_block")},
// Note: if \n, we'll never pop out of the site_block, it's valid
Expand All @@ -162,35 +186,7 @@ var CaddyfileRules = (func(a Rules, b Rules) Rules {
{`\}`, Punctuation, Pop(2)},
Include("site_block_common"),
},
},
CaddyfileCommon,
)

// CaddyfileDirectiveRules are the merged rules for the secondary lexer
var CaddyfileDirectiveRules = (func(a Rules, b Rules) Rules {
for k, v := range b {
a[k] = v
}
return a
})(
Rules{
// Same as "site_block" in Caddyfile
"root": {
Include("site_block_common"),
},
},
CaddyfileCommon,
)

// Caddyfile lexer.
var Caddyfile = internal.Register(MustNewLexer(
&Config{
Name: "Caddyfile",
Aliases: []string{"caddyfile", "caddy"},
Filenames: []string{"Caddyfile*"},
MimeTypes: []string{},
},
CaddyfileRules,
}.Merge(caddyfileCommon),
))

// Caddyfile directive-only lexer.
Expand All @@ -201,5 +197,10 @@ var CaddyfileDirectives = internal.Register(MustNewLexer(
Filenames: []string{},
MimeTypes: []string{},
},
CaddyfileDirectiveRules,
Rules{
// Same as "site_block" in Caddyfile
"root": {
Include("site_block_common"),
},
}.Merge(caddyfileCommon),
))
4 changes: 3 additions & 1 deletion lexers/testdata/caddyfile.actual
Expand Up @@ -13,9 +13,11 @@
redir @blocked /
}

example.com, fake.org {
example.com, fake.org, {$ENV_SITE} {
root * /srv

respond /get-env {$ENV_VAR}

tls off

route {
Expand Down
42 changes: 27 additions & 15 deletions lexers/testdata/caddyfile.expected
@@ -1,13 +1,13 @@
[
{"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t"},
{"type":"KeywordType","value":"debug"},
{"type":"Keyword","value":"debug"},
{"type":"Text","value":"\n\t"},
{"type":"KeywordType","value":"admin"},
{"type":"Keyword","value":"admin"},
{"type":"Text","value":" "},
{"type":"NameConstant","value":"off"},
{"type":"Text","value":"\n\t"},
{"type":"KeywordType","value":"on_demand_tls"},
{"type":"Keyword","value":"on_demand_tls"},
{"type":"Text","value":" "},
{"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t\t"},
Expand All @@ -23,7 +23,8 @@
{"type":"Text","value":" "},
{"type":"Punctuation","value":"{"},
{"type":"Text","value":" \n\t"},
{"type":"NameDecorator","value":"@blocked "},
{"type":"NameDecorator","value":"@blocked"},
{"type":"Text","value":" "},
{"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t\t"},
{"type":"Keyword","value":"path"},
Expand All @@ -38,17 +39,19 @@
{"type":"Text","value":"\n\t"},
{"type":"Punctuation","value":"}"},
{"type":"Text","value":"\n\t"},
{"type":"KeywordType","value":"redir"},
{"type":"Keyword","value":"redir"},
{"type":"Text","value":" "},
{"type":"NameDecorator","value":"@blocked"},
{"type":"Text","value":" "},
{"type":"LiteralString","value":"/"},
{"type":"Text","value":"\n"},
{"type":"Punctuation","value":"}"},
{"type":"Text","value":"\n\n"},
{"type":"NameLabel","value":"example.com"},
{"type":"GenericHeading","value":"example.com"},
{"type":"Text","value":", "},
{"type":"GenericHeading","value":"fake.org"},
{"type":"Text","value":", "},
{"type":"NameLabel","value":"fake.org"},
{"type":"LiteralStringEscape","value":"{$ENV_SITE}"},
{"type":"Text","value":" "},
{"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t"},
Expand All @@ -58,6 +61,12 @@
{"type":"Text","value":" "},
{"type":"LiteralString","value":"/srv"},
{"type":"Text","value":"\n\n\t"},
{"type":"Keyword","value":"respond"},
{"type":"Text","value":" "},
{"type":"NameDecorator","value":"/get-env"},
{"type":"Text","value":" "},
{"type":"LiteralStringEscape","value":"{$ENV_VAR}"},
{"type":"Text","value":"\n\n\t"},
{"type":"Keyword","value":"tls"},
{"type":"Text","value":" "},
{"type":"NameConstant","value":"off"},
Expand All @@ -67,7 +76,8 @@
{"type":"Punctuation","value":"{"},
{"type":"CommentSingle","value":"\n\t\t# Add trailing slash for directory requests\n"},
{"type":"Text","value":"\t\t"},
{"type":"NameDecorator","value":"@canonicalPath "},
{"type":"NameDecorator","value":"@canonicalPath"},
{"type":"Text","value":" "},
{"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t\t\t"},
{"type":"Keyword","value":"file"},
Expand All @@ -76,7 +86,7 @@
{"type":"Text","value":"\n\t\t\t\t"},
{"type":"Keyword","value":"try_files"},
{"type":"Text","value":" "},
{"type":"NameAttribute","value":"{path}"},
{"type":"LiteralStringEscape","value":"{path}"},
{"type":"LiteralString","value":"/index.php"},
{"type":"Text","value":"\n\t\t\t"},
{"type":"Punctuation","value":"}"},
Expand All @@ -93,7 +103,7 @@
{"type":"Text","value":" "},
{"type":"NameDecorator","value":"@canonicalPath"},
{"type":"Text","value":" "},
{"type":"NameAttribute","value":"{path}"},
{"type":"LiteralStringEscape","value":"{path}"},
{"type":"LiteralString","value":"/"},
{"type":"Text","value":" "},
{"type":"LiteralNumberInteger","value":"308"},
Expand All @@ -109,9 +119,9 @@
{"type":"Text","value":"\n\t\t\t\t"},
{"type":"Keyword","value":"try_files"},
{"type":"Text","value":" "},
{"type":"NameAttribute","value":"{path}"},
{"type":"LiteralStringEscape","value":"{path}"},
{"type":"Text","value":" "},
{"type":"NameAttribute","value":"{path}"},
{"type":"LiteralStringEscape","value":"{path}"},
{"type":"LiteralString","value":"/index.php"},
{"type":"Text","value":" "},
{"type":"LiteralString","value":"index.php"},
Expand All @@ -128,7 +138,7 @@
{"type":"Text","value":" "},
{"type":"NameDecorator","value":"@indexFiles"},
{"type":"Text","value":" "},
{"type":"NameAttribute","value":"{http.matchers.file.relative}"},
{"type":"LiteralStringEscape","value":"{http.matchers.file.relative}"},
{"type":"CommentSingle","value":"\n\n\t\t# Proxy PHP files to the FastCGI responder\n"},
{"type":"Text","value":"\t\t"},
{"type":"NameDecorator","value":"@phpFiles"},
Expand Down Expand Up @@ -165,7 +175,8 @@
{"type":"Text","value":"\n\t"},
{"type":"Punctuation","value":"}"},
{"type":"Text","value":"\n\n\t"},
{"type":"NameDecorator","value":"@encode_exts "},
{"type":"NameDecorator","value":"@encode_exts"},
{"type":"Text","value":" "},
{"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t\t"},
{"type":"Keyword","value":"path"},
Expand Down Expand Up @@ -216,7 +227,8 @@
{"type":"Text","value":"\n\t"},
{"type":"Punctuation","value":"}"},
{"type":"Text","value":"\n\n\t"},
{"type":"NameDecorator","value":"@singleLine "},
{"type":"NameDecorator","value":"@singleLine"},
{"type":"Text","value":" "},
{"type":"Keyword","value":"not"},
{"type":"Text","value":" "},
{"type":"Keyword","value":"path"},
Expand Down