...

Source file src/github.com/alecthomas/chroma/v2/lexers/caddyfile.go

Documentation: github.com/alecthomas/chroma/v2/lexers

     1  package lexers
     2  
     3  import (
     4  	. "github.com/alecthomas/chroma/v2" // nolint
     5  )
     6  
     7  // caddyfileCommon are the rules common to both of the lexer variants
     8  func caddyfileCommonRules() Rules {
     9  	return Rules{
    10  		"site_block_common": {
    11  			// Import keyword
    12  			{`(import)(\s+)([^\s]+)`, ByGroups(Keyword, Text, NameVariableMagic), nil},
    13  			// Matcher definition
    14  			{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
    15  			// Matcher token stub for docs
    16  			{`\[\<matcher\>\]`, NameDecorator, Push("matcher")},
    17  			// These cannot have matchers but may have things that look like
    18  			// matchers in their arguments, so we just parse as a subdirective.
    19  			{`try_files`, Keyword, Push("subdirective")},
    20  			// These are special, they can nest more directives
    21  			{`handle_errors|handle|route|handle_path|not`, Keyword, Push("nested_directive")},
    22  			// Any other directive
    23  			{`[^\s#]+`, Keyword, Push("directive")},
    24  			Include("base"),
    25  		},
    26  		"matcher": {
    27  			{`\{`, Punctuation, Push("block")},
    28  			// Not can be one-liner
    29  			{`not`, Keyword, Push("deep_not_matcher")},
    30  			// Any other same-line matcher
    31  			{`[^\s#]+`, Keyword, Push("arguments")},
    32  			// Terminators
    33  			{`\n`, Text, Pop(1)},
    34  			{`\}`, Punctuation, Pop(1)},
    35  			Include("base"),
    36  		},
    37  		"block": {
    38  			{`\}`, Punctuation, Pop(2)},
    39  			// Not can be one-liner
    40  			{`not`, Keyword, Push("not_matcher")},
    41  			// Any other subdirective
    42  			{`[^\s#]+`, Keyword, Push("subdirective")},
    43  			Include("base"),
    44  		},
    45  		"nested_block": {
    46  			{`\}`, Punctuation, Pop(2)},
    47  			// Matcher definition
    48  			{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
    49  			// Something that starts with literally < is probably a docs stub
    50  			{`\<[^#]+\>`, Keyword, Push("nested_directive")},
    51  			// Any other directive
    52  			{`[^\s#]+`, Keyword, Push("nested_directive")},
    53  			Include("base"),
    54  		},
    55  		"not_matcher": {
    56  			{`\}`, Punctuation, Pop(2)},
    57  			{`\{(?=\s)`, Punctuation, Push("block")},
    58  			{`[^\s#]+`, Keyword, Push("arguments")},
    59  			{`\s+`, Text, nil},
    60  		},
    61  		"deep_not_matcher": {
    62  			{`\}`, Punctuation, Pop(2)},
    63  			{`\{(?=\s)`, Punctuation, Push("block")},
    64  			{`[^\s#]+`, Keyword, Push("deep_subdirective")},
    65  			{`\s+`, Text, nil},
    66  		},
    67  		"directive": {
    68  			{`\{(?=\s)`, Punctuation, Push("block")},
    69  			Include("matcher_token"),
    70  			Include("comments_pop_1"),
    71  			{`\n`, Text, Pop(1)},
    72  			Include("base"),
    73  		},
    74  		"nested_directive": {
    75  			{`\{(?=\s)`, Punctuation, Push("nested_block")},
    76  			Include("matcher_token"),
    77  			Include("comments_pop_1"),
    78  			{`\n`, Text, Pop(1)},
    79  			Include("base"),
    80  		},
    81  		"subdirective": {
    82  			{`\{(?=\s)`, Punctuation, Push("block")},
    83  			Include("comments_pop_1"),
    84  			{`\n`, Text, Pop(1)},
    85  			Include("base"),
    86  		},
    87  		"arguments": {
    88  			{`\{(?=\s)`, Punctuation, Push("block")},
    89  			Include("comments_pop_2"),
    90  			{`\\\n`, Text, nil}, // Skip escaped newlines
    91  			{`\n`, Text, Pop(2)},
    92  			Include("base"),
    93  		},
    94  		"deep_subdirective": {
    95  			{`\{(?=\s)`, Punctuation, Push("block")},
    96  			Include("comments_pop_3"),
    97  			{`\n`, Text, Pop(3)},
    98  			Include("base"),
    99  		},
   100  		"matcher_token": {
   101  			{`@[^\s]+`, NameDecorator, Push("arguments")},         // Named matcher
   102  			{`/[^\s]+`, NameDecorator, Push("arguments")},         // Path matcher
   103  			{`\*`, NameDecorator, Push("arguments")},              // Wildcard path matcher
   104  			{`\[\<matcher\>\]`, NameDecorator, Push("arguments")}, // Matcher token stub for docs
   105  		},
   106  		"comments": {
   107  			{`^#.*\n`, CommentSingle, nil},   // Comment at start of line
   108  			{`\s+#.*\n`, CommentSingle, nil}, // Comment preceded by whitespace
   109  		},
   110  		"comments_pop_1": {
   111  			{`^#.*\n`, CommentSingle, Pop(1)},   // Comment at start of line
   112  			{`\s+#.*\n`, CommentSingle, Pop(1)}, // Comment preceded by whitespace
   113  		},
   114  		"comments_pop_2": {
   115  			{`^#.*\n`, CommentSingle, Pop(2)},   // Comment at start of line
   116  			{`\s+#.*\n`, CommentSingle, Pop(2)}, // Comment preceded by whitespace
   117  		},
   118  		"comments_pop_3": {
   119  			{`^#.*\n`, CommentSingle, Pop(3)},   // Comment at start of line
   120  			{`\s+#.*\n`, CommentSingle, Pop(3)}, // Comment preceded by whitespace
   121  		},
   122  		"base": {
   123  			Include("comments"),
   124  			{`(on|off|first|last|before|after|internal|strip_prefix|strip_suffix|replace)\b`, NameConstant, nil},
   125  			{`(https?://)?([a-z0-9.-]+)(:)([0-9]+)`, ByGroups(Name, Name, Punctuation, LiteralNumberInteger), nil},
   126  			{`[a-z-]+/[a-z-+]+`, LiteralString, nil},
   127  			{`[0-9]+[km]?\b`, LiteralNumberInteger, nil},
   128  			{`\{[\w+.\$-]+\}`, LiteralStringEscape, nil}, // Placeholder
   129  			{`\[(?=[^#{}$]+\])`, Punctuation, nil},
   130  			{`\]|\|`, Punctuation, nil},
   131  			{`[^\s#{}$\]]+`, LiteralString, nil},
   132  			{`/[^\s#]*`, Name, nil},
   133  			{`\s+`, Text, nil},
   134  		},
   135  	}
   136  }
   137  
   138  // Caddyfile lexer.
   139  var Caddyfile = Register(MustNewLexer(
   140  	&Config{
   141  		Name:      "Caddyfile",
   142  		Aliases:   []string{"caddyfile", "caddy"},
   143  		Filenames: []string{"Caddyfile*"},
   144  		MimeTypes: []string{},
   145  	},
   146  	caddyfileRules,
   147  ))
   148  
   149  func caddyfileRules() Rules {
   150  	return Rules{
   151  		"root": {
   152  			Include("comments"),
   153  			// Global options block
   154  			{`^\s*(\{)\s*$`, ByGroups(Punctuation), Push("globals")},
   155  			// Snippets
   156  			{`(\([^\s#]+\))(\s*)(\{)`, ByGroups(NameVariableAnonymous, Text, Punctuation), Push("snippet")},
   157  			// Site label
   158  			{`[^#{(\s,]+`, GenericHeading, Push("label")},
   159  			// Site label with placeholder
   160  			{`\{[\w+.\$-]+\}`, LiteralStringEscape, Push("label")},
   161  			{`\s+`, Text, nil},
   162  		},
   163  		"globals": {
   164  			{`\}`, Punctuation, Pop(1)},
   165  			{`[^\s#]+`, Keyword, Push("directive")},
   166  			Include("base"),
   167  		},
   168  		"snippet": {
   169  			{`\}`, Punctuation, Pop(1)},
   170  			// Matcher definition
   171  			{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
   172  			// Any directive
   173  			{`[^\s#]+`, Keyword, Push("directive")},
   174  			Include("base"),
   175  		},
   176  		"label": {
   177  			// Allow multiple labels, comma separated, newlines after
   178  			// a comma means another label is coming
   179  			{`,\s*\n?`, Text, nil},
   180  			{` `, Text, nil},
   181  			// Site label with placeholder
   182  			{`\{[\w+.\$-]+\}`, LiteralStringEscape, nil},
   183  			// Site label
   184  			{`[^#{(\s,]+`, GenericHeading, nil},
   185  			// Comment after non-block label (hack because comments end in \n)
   186  			{`#.*\n`, CommentSingle, Push("site_block")},
   187  			// Note: if \n, we'll never pop out of the site_block, it's valid
   188  			{`\{(?=\s)|\n`, Punctuation, Push("site_block")},
   189  		},
   190  		"site_block": {
   191  			{`\}`, Punctuation, Pop(2)},
   192  			Include("site_block_common"),
   193  		},
   194  	}.Merge(caddyfileCommonRules())
   195  }
   196  
   197  // Caddyfile directive-only lexer.
   198  var CaddyfileDirectives = Register(MustNewLexer(
   199  	&Config{
   200  		Name:      "Caddyfile Directives",
   201  		Aliases:   []string{"caddyfile-directives", "caddyfile-d", "caddy-d"},
   202  		Filenames: []string{},
   203  		MimeTypes: []string{},
   204  	},
   205  	caddyfileDirectivesRules,
   206  ))
   207  
   208  func caddyfileDirectivesRules() Rules {
   209  	return Rules{
   210  		// Same as "site_block" in Caddyfile
   211  		"root": {
   212  			Include("site_block_common"),
   213  		},
   214  	}.Merge(caddyfileCommonRules())
   215  }
   216  

View as plain text