190 lines
7.1 KiB
Python
190 lines
7.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
pygments.lexers.varnish
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Lexers for Varnish configuration
|
|
|
|
:copyright: Copyright 2006-2020 by the Pygments team, see AUTHORS.
|
|
:license: BSD, see LICENSE for details.
|
|
"""
|
|
|
|
from pygments.lexer import RegexLexer, include, bygroups, using, this, \
|
|
inherit, words
|
|
from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
|
|
Number, Punctuation, Literal
|
|
|
|
__all__ = ['VCLLexer', 'VCLSnippetLexer']
|
|
|
|
|
|
class VCLLexer(RegexLexer):
|
|
"""
|
|
For Varnish Configuration Language (VCL).
|
|
|
|
.. versionadded:: 2.2
|
|
"""
|
|
name = 'VCL'
|
|
aliases = ['vcl']
|
|
filenames = ['*.vcl']
|
|
mimetypes = ['text/x-vclsrc']
|
|
|
|
def analyse_text(text):
|
|
# If the very first line is 'vcl 4.0;' it's pretty much guaranteed
|
|
# that this is VCL
|
|
if text.startswith('vcl 4.0;'):
|
|
return 1.0
|
|
# Skip over comments and blank lines
|
|
# This is accurate enough that returning 0.9 is reasonable.
|
|
# Almost no VCL files start without some comments.
|
|
elif '\nvcl 4.0;' in text[:1000]:
|
|
return 0.9
|
|
|
|
tokens = {
|
|
'probe': [
|
|
include('whitespace'),
|
|
include('comments'),
|
|
(r'(\.\w+)(\s*=\s*)([^;]*)(;)',
|
|
bygroups(Name.Attribute, Operator, using(this), Punctuation)),
|
|
(r'\}', Punctuation, '#pop'),
|
|
],
|
|
'acl': [
|
|
include('whitespace'),
|
|
include('comments'),
|
|
(r'[!/]+', Operator),
|
|
(r';', Punctuation),
|
|
(r'\d+', Number),
|
|
(r'\}', Punctuation, '#pop'),
|
|
],
|
|
'backend': [
|
|
include('whitespace'),
|
|
(r'(\.probe)(\s*=\s*)(\w+)(;)',
|
|
bygroups(Name.Attribute, Operator, Name.Variable.Global, Punctuation)),
|
|
(r'(\.probe)(\s*=\s*)(\{)',
|
|
bygroups(Name.Attribute, Operator, Punctuation), 'probe'),
|
|
(r'(\.\w+\b)(\s*=\s*)([^;]*)(\s*;)',
|
|
bygroups(Name.Attribute, Operator, using(this), Punctuation)),
|
|
(r'\{', Punctuation, '#push'),
|
|
(r'\}', Punctuation, '#pop'),
|
|
],
|
|
'statements': [
|
|
(r'(\d\.)?\d+[sdwhmy]', Literal.Date),
|
|
(r'(\d\.)?\d+ms', Literal.Date),
|
|
(r'(vcl_pass|vcl_hash|vcl_hit|vcl_init|vcl_backend_fetch|vcl_pipe|'
|
|
r'vcl_backend_response|vcl_synth|vcl_deliver|vcl_backend_error|'
|
|
r'vcl_fini|vcl_recv|vcl_purge|vcl_miss)\b', Name.Function),
|
|
(r'(pipe|retry|hash|synth|deliver|purge|abandon|lookup|pass|fail|ok|'
|
|
r'miss|fetch|restart)\b', Name.Constant),
|
|
(r'(beresp|obj|resp|req|req_top|bereq)\.http\.[a-zA-Z_-]+\b', Name.Variable),
|
|
(words((
|
|
'obj.status', 'req.hash_always_miss', 'beresp.backend', 'req.esi_level',
|
|
'req.can_gzip', 'beresp.ttl', 'obj.uncacheable', 'req.ttl', 'obj.hits',
|
|
'client.identity', 'req.hash_ignore_busy', 'obj.reason', 'req.xid',
|
|
'req_top.proto', 'beresp.age', 'obj.proto', 'obj.age', 'local.ip',
|
|
'beresp.uncacheable', 'req.method', 'beresp.backend.ip', 'now',
|
|
'obj.grace', 'req.restarts', 'beresp.keep', 'req.proto', 'resp.proto',
|
|
'bereq.xid', 'bereq.between_bytes_timeout', 'req.esi',
|
|
'bereq.first_byte_timeout', 'bereq.method', 'bereq.connect_timeout',
|
|
'beresp.do_gzip', 'resp.status', 'beresp.do_gunzip',
|
|
'beresp.storage_hint', 'resp.is_streaming', 'beresp.do_stream',
|
|
'req_top.method', 'bereq.backend', 'beresp.backend.name', 'beresp.status',
|
|
'req.url', 'obj.keep', 'obj.ttl', 'beresp.reason', 'bereq.retries',
|
|
'resp.reason', 'bereq.url', 'beresp.do_esi', 'beresp.proto', 'client.ip',
|
|
'bereq.proto', 'server.hostname', 'remote.ip', 'req.backend_hint',
|
|
'server.identity', 'req_top.url', 'beresp.grace', 'beresp.was_304',
|
|
'server.ip', 'bereq.uncacheable'), suffix=r'\b'),
|
|
Name.Variable),
|
|
(r'[!%&+*\-,/<.}{>=|~]+', Operator),
|
|
(r'[();]', Punctuation),
|
|
|
|
(r'[,]+', Punctuation),
|
|
(words(('hash_data', 'regsub', 'regsuball', 'if', 'else',
|
|
'elsif', 'elif', 'synth', 'synthetic', 'ban',
|
|
'return', 'set', 'unset', 'import', 'include', 'new',
|
|
'rollback', 'call'), suffix=r'\b'),
|
|
Keyword),
|
|
(r'storage\.\w+\.\w+\b', Name.Variable),
|
|
(words(('true', 'false')), Name.Builtin),
|
|
(r'\d+\b', Number),
|
|
(r'(backend)(\s+\w+)(\s*\{)',
|
|
bygroups(Keyword, Name.Variable.Global, Punctuation), 'backend'),
|
|
(r'(probe\s)(\s*\w+\s)(\{)',
|
|
bygroups(Keyword, Name.Variable.Global, Punctuation), 'probe'),
|
|
(r'(acl\s)(\s*\w+\s)(\{)',
|
|
bygroups(Keyword, Name.Variable.Global, Punctuation), 'acl'),
|
|
(r'(vcl )(4.0)(;)$',
|
|
bygroups(Keyword.Reserved, Name.Constant, Punctuation)),
|
|
(r'(sub\s+)([a-zA-Z]\w*)(\s*\{)',
|
|
bygroups(Keyword, Name.Function, Punctuation)),
|
|
(r'([a-zA-Z_]\w*)'
|
|
r'(\.)'
|
|
r'([a-zA-Z_]\w*)'
|
|
r'(\s*\(.*\))',
|
|
bygroups(Name.Function, Punctuation, Name.Function, using(this))),
|
|
(r'[a-zA-Z_]\w*', Name),
|
|
],
|
|
'comment': [
|
|
(r'[^*/]+', Comment.Multiline),
|
|
(r'/\*', Comment.Multiline, '#push'),
|
|
(r'\*/', Comment.Multiline, '#pop'),
|
|
(r'[*/]', Comment.Multiline),
|
|
],
|
|
'comments': [
|
|
(r'#.*$', Comment),
|
|
(r'/\*', Comment.Multiline, 'comment'),
|
|
(r'//.*$', Comment),
|
|
],
|
|
'string': [
|
|
(r'"', String, '#pop'),
|
|
(r'[^"\n]+', String), # all other characters
|
|
],
|
|
'multistring': [
|
|
(r'[^"}]', String),
|
|
(r'"\}', String, '#pop'),
|
|
(r'["}]', String),
|
|
],
|
|
'whitespace': [
|
|
(r'L?"', String, 'string'),
|
|
(r'\{"', String, 'multistring'),
|
|
(r'\n', Text),
|
|
(r'\s+', Text),
|
|
(r'\\\n', Text), # line continuation
|
|
],
|
|
'root': [
|
|
include('whitespace'),
|
|
include('comments'),
|
|
include('statements'),
|
|
(r'\s+', Text),
|
|
],
|
|
}
|
|
|
|
|
|
class VCLSnippetLexer(VCLLexer):
|
|
"""
|
|
For Varnish Configuration Language snippets.
|
|
|
|
.. versionadded:: 2.2
|
|
"""
|
|
name = 'VCLSnippets'
|
|
aliases = ['vclsnippets', 'vclsnippet']
|
|
mimetypes = ['text/x-vclsnippet']
|
|
filenames = []
|
|
|
|
def analyse_text(text):
|
|
# override method inherited from VCLLexer
|
|
return 0
|
|
|
|
tokens = {
|
|
'snippetspre': [
|
|
(r'\.\.\.+', Comment),
|
|
(r'(bereq|req|req_top|resp|beresp|obj|client|server|local|remote|'
|
|
r'storage)($|\.\*)', Name.Variable),
|
|
],
|
|
'snippetspost': [
|
|
(r'(backend)\b', Keyword.Reserved),
|
|
],
|
|
'root': [
|
|
include('snippetspre'),
|
|
inherit,
|
|
include('snippetspost'),
|
|
],
|
|
}
|