1
0
mirror of https://github.com/alecthomas/chroma.git synced 2025-04-23 12:08:58 +02:00

Update Caddyfile lexer to fix edgecases and improve colouring

This commit is contained in:
Francis Lavoie 2020-05-16 13:48:35 -04:00 committed by Alec Thomas
parent bd463054be
commit 155bdea915
2 changed files with 99 additions and 97 deletions

View File

@ -5,15 +5,20 @@ import (
"github.com/alecthomas/chroma/lexers/internal" "github.com/alecthomas/chroma/lexers/internal"
) )
// CaddyfileCommon are the rules common to both of the lexer variants // caddyfileCommon are the rules common to both of the lexer variants
var CaddyfileCommon = Rules{ var caddyfileCommon = Rules{
"site_block_common": { "site_block_common": {
// Import keyword // Import keyword
{`(import)(\s+)([^\s]+)`, ByGroups(Keyword, Text, NameVariableMagic), nil}, {`(import)(\s+)([^\s]+)`, ByGroups(Keyword, Text, NameVariableMagic), nil},
// Matcher definition // 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 // 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 // Any other directive
{`[^\s#]+`, Keyword, Push("directive")}, {`[^\s#]+`, Keyword, Push("directive")},
Include("base"), Include("base"),
@ -40,7 +45,9 @@ var CaddyfileCommon = Rules{
"nested_block": { "nested_block": {
{`\}`, Punctuation, Pop(2)}, {`\}`, Punctuation, Pop(2)},
// Matcher definition // 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 // Any other directive
{`[^\s#]+`, Keyword, Push("nested_directive")}, {`[^\s#]+`, Keyword, Push("nested_directive")},
Include("base"), Include("base"),
@ -60,32 +67,33 @@ var CaddyfileCommon = Rules{
"directive": { "directive": {
{`\{(?=\s)`, Punctuation, Push("block")}, {`\{(?=\s)`, Punctuation, Push("block")},
Include("matcher_token"), Include("matcher_token"),
Include("comments_pop"), Include("comments_pop_1"),
{`\n`, Text, Pop(1)}, {`\n`, Text, Pop(1)},
Include("base"), Include("base"),
}, },
"nested_directive": { "nested_directive": {
{`\{(?=\s)`, Punctuation, Push("nested_block")}, {`\{(?=\s)`, Punctuation, Push("nested_block")},
Include("matcher_token"), Include("matcher_token"),
Include("comments_pop"), Include("comments_pop_1"),
{`\n`, Text, Pop(1)}, {`\n`, Text, Pop(1)},
Include("base"), Include("base"),
}, },
"subdirective": { "subdirective": {
{`\{(?=\s)`, Punctuation, Push("block")}, {`\{(?=\s)`, Punctuation, Push("block")},
Include("comments_pop"), Include("comments_pop_1"),
{`\n`, Text, Pop(1)}, {`\n`, Text, Pop(1)},
Include("base"), Include("base"),
}, },
"arguments": { "arguments": {
{`\{(?=\s)`, Punctuation, Push("block")}, {`\{(?=\s)`, Punctuation, Push("block")},
Include("comments_pop"), Include("comments_pop_2"),
{`\\\n`, Text, nil}, // Skip escaped newlines
{`\n`, Text, Pop(2)}, {`\n`, Text, Pop(2)},
Include("base"), Include("base"),
}, },
"deep_subdirective": { "deep_subdirective": {
{`\{(?=\s)`, Punctuation, Push("block")}, {`\{(?=\s)`, Punctuation, Push("block")},
Include("comments_pop"), Include("comments_pop_3"),
{`\n`, Text, Pop(3)}, {`\n`, Text, Pop(3)},
Include("base"), Include("base"),
}, },
@ -99,89 +107,33 @@ var CaddyfileCommon = Rules{
{`^#.*\n`, CommentSingle, nil}, // Comment at start of line {`^#.*\n`, CommentSingle, nil}, // Comment at start of line
{`\s+#.*\n`, CommentSingle, nil}, // Comment preceded by whitespace {`\s+#.*\n`, CommentSingle, nil}, // Comment preceded by whitespace
}, },
"comments_pop": { "comments_pop_1": {
{`^#.*\n`, CommentSingle, Pop(1)}, // Comment at start of line {`^#.*\n`, CommentSingle, Pop(1)}, // Comment at start of line
{`\s+#.*\n`, CommentSingle, Pop(1)}, // Comment preceded by whitespace {`\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": { "base": {
Include("comments"), Include("comments"),
{`on|off`, NameConstant, nil}, {`on|off|first|last|before|after|internal|strip_prefix|strip_suffix|replace`, NameConstant, nil},
{`(https?://)?([a-z0-9.-]+)(:)([0-9]+)`, ByGroups(Name, Name, Punctuation, LiteralNumberInteger), nil}, {`(https?://)?([a-z0-9.-]+)(:)([0-9]+)`, ByGroups(Name, Name, Punctuation, LiteralNumberInteger), nil},
{`[a-z-]+/[a-z-+]+`, LiteralString, nil}, {`[a-z-]+/[a-z-+]+`, LiteralString, nil},
{`[0-9]+[km]?\b`, LiteralNumberInteger, nil}, {`[0-9]+[km]?\b`, LiteralNumberInteger, nil},
{`\{[\w+.-]+\}`, NameAttribute, nil}, // Placeholder {`\{[\w+.-]+\}`, LiteralStringEscape, nil}, // Placeholder
{`[^\s#{}$]+`, LiteralString, nil}, {`\[(?=[^#{}$]+\])`, Punctuation, nil},
{`\]|\|`, Punctuation, nil},
{`[^\s#{}$\]]+`, LiteralString, nil},
{`/[^\s#]*`, Name, nil}, {`/[^\s#]*`, Name, nil},
{`\s+`, Text, 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
})(
Rules{
"root": {
Include("comments"),
// Global options block
{`^\s*(\{)\s*$`, ByGroups(Punctuation), Push("globals")},
// Snippets
{`(\([^\s#]+\))(\s*)(\{)`, ByGroups(NameVariableAnonymous, Text, Punctuation), Push("snippet")},
// Site label
{`[^#{(\s,]+`, NameLabel, Push("label")},
// Site label with placeholder
{`\{[\w+.-]+\}`, NameAttribute, Push("label")},
{`\s+`, Text, nil},
},
"globals": {
{`\}`, Punctuation, Pop(1)},
{`[^\s#]+`, KeywordType, Push("directive")},
Include("base"),
},
"snippet": {
{`\}`, Punctuation, Pop(1)},
// Matcher definition
{`@[^\s]+\s+`, NameDecorator, Push("matcher")},
// Any directive
{`[^\s#]+`, KeywordType, Push("directive")},
Include("base"),
},
"label": {
{`,`, Text, nil},
{` `, Text, nil},
{`[^#{(\s,]+`, NameLabel, 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
{`\{(?=\s)|\n`, Punctuation, Push("site_block")},
},
"site_block": {
{`\}`, 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. // Caddyfile lexer.
var Caddyfile = internal.Register(MustNewLexer( var Caddyfile = internal.Register(MustNewLexer(
&Config{ &Config{
@ -190,7 +142,48 @@ var Caddyfile = internal.Register(MustNewLexer(
Filenames: []string{"Caddyfile*"}, Filenames: []string{"Caddyfile*"},
MimeTypes: []string{}, MimeTypes: []string{},
}, },
CaddyfileRules, Rules{
"root": {
Include("comments"),
// Global options block
{`^\s*(\{)\s*$`, ByGroups(Punctuation), Push("globals")},
// Snippets
{`(\([^\s#]+\))(\s*)(\{)`, ByGroups(NameVariableAnonymous, Text, Punctuation), Push("snippet")},
// Site label
{`[^#{(\s,]+`, GenericHeading, Push("label")},
// Site label with placeholder
{`\{[\w+.-]+\}`, NameAttribute, Push("label")},
{`\s+`, Text, nil},
},
"globals": {
{`\}`, Punctuation, Pop(1)},
{`[^\s#]+`, Keyword, Push("directive")},
Include("base"),
},
"snippet": {
{`\}`, Punctuation, Pop(1)},
// Matcher definition
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
// Any directive
{`[^\s#]+`, Keyword, Push("directive")},
Include("base"),
},
"label": {
// Allow multiple labels, comma separated, newlines after
// a comma means another label is coming
{`,\s*\n?`, Text, nil},
{` `, Text, nil},
{`[^#{(\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
{`\{(?=\s)|\n`, Punctuation, Push("site_block")},
},
"site_block": {
{`\}`, Punctuation, Pop(2)},
Include("site_block_common"),
},
}.Merge(caddyfileCommon),
)) ))
// Caddyfile directive-only lexer. // Caddyfile directive-only lexer.
@ -201,5 +194,10 @@ var CaddyfileDirectives = internal.Register(MustNewLexer(
Filenames: []string{}, Filenames: []string{},
MimeTypes: []string{}, MimeTypes: []string{},
}, },
CaddyfileDirectiveRules, Rules{
// Same as "site_block" in Caddyfile
"root": {
Include("site_block_common"),
},
}.Merge(caddyfileCommon),
)) ))

View File

@ -1,13 +1,13 @@
[ [
{"type":"Punctuation","value":"{"}, {"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t"}, {"type":"Text","value":"\n\t"},
{"type":"KeywordType","value":"debug"}, {"type":"Keyword","value":"debug"},
{"type":"Text","value":"\n\t"}, {"type":"Text","value":"\n\t"},
{"type":"KeywordType","value":"admin"}, {"type":"Keyword","value":"admin"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"NameConstant","value":"off"}, {"type":"NameConstant","value":"off"},
{"type":"Text","value":"\n\t"}, {"type":"Text","value":"\n\t"},
{"type":"KeywordType","value":"on_demand_tls"}, {"type":"Keyword","value":"on_demand_tls"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"Punctuation","value":"{"}, {"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t\t"}, {"type":"Text","value":"\n\t\t"},
@ -24,6 +24,7 @@
{"type":"Punctuation","value":"{"}, {"type":"Punctuation","value":"{"},
{"type":"Text","value":" \n\t"}, {"type":"Text","value":" \n\t"},
{"type":"NameDecorator","value":"@blocked"}, {"type":"NameDecorator","value":"@blocked"},
{"type":"Text","value":" "},
{"type":"Punctuation","value":"{"}, {"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t\t"}, {"type":"Text","value":"\n\t\t"},
{"type":"Keyword","value":"path"}, {"type":"Keyword","value":"path"},
@ -38,7 +39,7 @@
{"type":"Text","value":"\n\t"}, {"type":"Text","value":"\n\t"},
{"type":"Punctuation","value":"}"}, {"type":"Punctuation","value":"}"},
{"type":"Text","value":"\n\t"}, {"type":"Text","value":"\n\t"},
{"type":"KeywordType","value":"redir"}, {"type":"Keyword","value":"redir"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"NameDecorator","value":"@blocked"}, {"type":"NameDecorator","value":"@blocked"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
@ -46,9 +47,9 @@
{"type":"Text","value":"\n"}, {"type":"Text","value":"\n"},
{"type":"Punctuation","value":"}"}, {"type":"Punctuation","value":"}"},
{"type":"Text","value":"\n\n"}, {"type":"Text","value":"\n\n"},
{"type":"NameLabel","value":"example.com"}, {"type":"GenericHeading","value":"example.com"},
{"type":"Text","value":", "}, {"type":"Text","value":", "},
{"type":"NameLabel","value":"fake.org"}, {"type":"GenericHeading","value":"fake.org"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"Punctuation","value":"{"}, {"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t"}, {"type":"Text","value":"\n\t"},
@ -68,6 +69,7 @@
{"type":"CommentSingle","value":"\n\t\t# Add trailing slash for directory requests\n"}, {"type":"CommentSingle","value":"\n\t\t# Add trailing slash for directory requests\n"},
{"type":"Text","value":"\t\t"}, {"type":"Text","value":"\t\t"},
{"type":"NameDecorator","value":"@canonicalPath"}, {"type":"NameDecorator","value":"@canonicalPath"},
{"type":"Text","value":" "},
{"type":"Punctuation","value":"{"}, {"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t\t\t"}, {"type":"Text","value":"\n\t\t\t"},
{"type":"Keyword","value":"file"}, {"type":"Keyword","value":"file"},
@ -76,7 +78,7 @@
{"type":"Text","value":"\n\t\t\t\t"}, {"type":"Text","value":"\n\t\t\t\t"},
{"type":"Keyword","value":"try_files"}, {"type":"Keyword","value":"try_files"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"NameAttribute","value":"{path}"}, {"type":"LiteralStringEscape","value":"{path}"},
{"type":"LiteralString","value":"/index.php"}, {"type":"LiteralString","value":"/index.php"},
{"type":"Text","value":"\n\t\t\t"}, {"type":"Text","value":"\n\t\t\t"},
{"type":"Punctuation","value":"}"}, {"type":"Punctuation","value":"}"},
@ -93,7 +95,7 @@
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"NameDecorator","value":"@canonicalPath"}, {"type":"NameDecorator","value":"@canonicalPath"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"NameAttribute","value":"{path}"}, {"type":"LiteralStringEscape","value":"{path}"},
{"type":"LiteralString","value":"/"}, {"type":"LiteralString","value":"/"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"LiteralNumberInteger","value":"308"}, {"type":"LiteralNumberInteger","value":"308"},
@ -109,9 +111,9 @@
{"type":"Text","value":"\n\t\t\t\t"}, {"type":"Text","value":"\n\t\t\t\t"},
{"type":"Keyword","value":"try_files"}, {"type":"Keyword","value":"try_files"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"NameAttribute","value":"{path}"}, {"type":"LiteralStringEscape","value":"{path}"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"NameAttribute","value":"{path}"}, {"type":"LiteralStringEscape","value":"{path}"},
{"type":"LiteralString","value":"/index.php"}, {"type":"LiteralString","value":"/index.php"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"LiteralString","value":"index.php"}, {"type":"LiteralString","value":"index.php"},
@ -128,7 +130,7 @@
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"NameDecorator","value":"@indexFiles"}, {"type":"NameDecorator","value":"@indexFiles"},
{"type":"Text","value":" "}, {"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":"CommentSingle","value":"\n\n\t\t# Proxy PHP files to the FastCGI responder\n"},
{"type":"Text","value":"\t\t"}, {"type":"Text","value":"\t\t"},
{"type":"NameDecorator","value":"@phpFiles"}, {"type":"NameDecorator","value":"@phpFiles"},
@ -166,6 +168,7 @@
{"type":"Punctuation","value":"}"}, {"type":"Punctuation","value":"}"},
{"type":"Text","value":"\n\n\t"}, {"type":"Text","value":"\n\n\t"},
{"type":"NameDecorator","value":"@encode_exts"}, {"type":"NameDecorator","value":"@encode_exts"},
{"type":"Text","value":" "},
{"type":"Punctuation","value":"{"}, {"type":"Punctuation","value":"{"},
{"type":"Text","value":"\n\t\t"}, {"type":"Text","value":"\n\t\t"},
{"type":"Keyword","value":"path"}, {"type":"Keyword","value":"path"},
@ -217,6 +220,7 @@
{"type":"Punctuation","value":"}"}, {"type":"Punctuation","value":"}"},
{"type":"Text","value":"\n\n\t"}, {"type":"Text","value":"\n\n\t"},
{"type":"NameDecorator","value":"@singleLine"}, {"type":"NameDecorator","value":"@singleLine"},
{"type":"Text","value":" "},
{"type":"Keyword","value":"not"}, {"type":"Keyword","value":"not"},
{"type":"Text","value":" "}, {"type":"Text","value":" "},
{"type":"Keyword","value":"path"}, {"type":"Keyword","value":"path"},