--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ThirdParty/Pygments/pygments/lexers/text.py Mon Dec 28 16:03:33 2009 +0000 @@ -0,0 +1,1496 @@ +# -*- coding: utf-8 -*- +""" + pygments.lexers.text + ~~~~~~~~~~~~~~~~~~~~ + + Lexers for non-source code file types. + + :copyright: Copyright 2006-2009 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import re +try: + set +except NameError: + from sets import Set as set +from bisect import bisect + +from pygments.lexer import Lexer, LexerContext, RegexLexer, ExtendedRegexLexer, \ + bygroups, include, using, this, do_insertions +from pygments.token import Punctuation, Text, Comment, Keyword, Name, String, \ + Generic, Operator, Number, Whitespace, Literal +from pygments.util import get_bool_opt +from pygments.lexers.other import BashLexer + +__all__ = ['IniLexer', 'SourcesListLexer', 'BaseMakefileLexer', + 'MakefileLexer', 'DiffLexer', 'IrcLogsLexer', 'TexLexer', + 'GroffLexer', 'ApacheConfLexer', 'BBCodeLexer', 'MoinWikiLexer', + 'RstLexer', 'VimLexer', 'GettextLexer', 'SquidConfLexer', + 'DebianControlLexer', 'DarcsPatchLexer', 'YamlLexer', + 'LighttpdConfLexer', 'NginxConfLexer'] + + +class IniLexer(RegexLexer): + """ + Lexer for configuration files in INI style. + """ + + name = 'INI' + aliases = ['ini', 'cfg'] + filenames = ['*.ini', '*.cfg', '*.properties'] + mimetypes = ['text/x-ini'] + + tokens = { + 'root': [ + (r'\s+', Text), + (r'[;#].*?$', Comment), + (r'\[.*?\]$', Keyword), + (r'(.*?)([ \t]*)(=)([ \t]*)(.*?)$', + bygroups(Name.Attribute, Text, Operator, Text, String)) + ] + } + + def analyse_text(text): + npos = text.find('\n') + if npos < 3: + return False + return text[0] == '[' and text[npos-1] == ']' + + +class SourcesListLexer(RegexLexer): + """ + Lexer that highlights debian sources.list files. + + *New in Pygments 0.7.* + """ + + name = 'Debian Sourcelist' + aliases = ['sourceslist', 'sources.list'] + filenames = ['sources.list'] + mimetype = ['application/x-debian-sourceslist'] + + tokens = { + 'root': [ + (r'\s+', Text), + (r'#.*?$', Comment), + (r'^(deb(?:-src)?)(\s+)', + bygroups(Keyword, Text), 'distribution') + ], + 'distribution': [ + (r'#.*?$', Comment, '#pop'), + (r'\$\(ARCH\)', Name.Variable), + (r'[^\s$[]+', String), + (r'\[', String.Other, 'escaped-distribution'), + (r'\$', String), + (r'\s+', Text, 'components') + ], + 'escaped-distribution': [ + (r'\]', String.Other, '#pop'), + (r'\$\(ARCH\)', Name.Variable), + (r'[^\]$]+', String.Other), + (r'\$', String.Other) + ], + 'components': [ + (r'#.*?$', Comment, '#pop:2'), + (r'$', Text, '#pop:2'), + (r'\s+', Text), + (r'\S+', Keyword.Pseudo), + ] + } + + def analyse_text(text): + for line in text.split('\n'): + line = line.strip() + if not (line.startswith('#') or line.startswith('deb ') or + line.startswith('deb-src ') or not line): + return False + return True + + +class MakefileLexer(Lexer): + """ + Lexer for BSD and GNU make extensions (lenient enough to handle both in + the same file even). + + *Rewritten in Pygments 0.10.* + """ + + name = 'Makefile' + aliases = ['make', 'makefile', 'mf', 'bsdmake'] + filenames = ['*.mak', 'Makefile', 'makefile', 'Makefile.*', 'GNUmakefile'] + mimetypes = ['text/x-makefile'] + + r_special = re.compile(r'^(?:' + # BSD Make + r'\.\s*(include|undef|error|warning|if|else|elif|endif|for|endfor)|' + # GNU Make + r'\s*(ifeq|ifneq|ifdef|ifndef|else|endif|-?include|define|endef|:))(?=\s)') + r_comment = re.compile(r'^\s*@?#') + + def get_tokens_unprocessed(self, text): + ins = [] + lines = text.splitlines(True) + done = '' + lex = BaseMakefileLexer(**self.options) + backslashflag = False + for line in lines: + if self.r_special.match(line) or backslashflag: + ins.append((len(done), [(0, Comment.Preproc, line)])) + backslashflag = line.strip().endswith('\\') + elif self.r_comment.match(line): + ins.append((len(done), [(0, Comment, line)])) + else: + done += line + for item in do_insertions(ins, lex.get_tokens_unprocessed(done)): + yield item + + +class BaseMakefileLexer(RegexLexer): + """ + Lexer for simple Makefiles (no preprocessing). + + *New in Pygments 0.10.* + """ + + name = 'Makefile' + aliases = ['basemake'] + filenames = [] + mimetypes = [] + + tokens = { + 'root': [ + (r'^(?:[\t ]+.*\n|\n)+', using(BashLexer)), + (r'\$\((?:.*\\\n|.*\n)+', using(BashLexer)), + (r'\s+', Text), + (r'#.*?\n', Comment), + (r'(export)(\s+)(?=[a-zA-Z0-9_${}\t -]+\n)', + bygroups(Keyword, Text), 'export'), + (r'export\s+', Keyword), + # assignment + (r'([a-zA-Z0-9_${}.-]+)(\s*)([!?:+]?=)([ \t]*)((?:.*\\\n|.*\n)+)', + bygroups(Name.Variable, Text, Operator, Text, using(BashLexer))), + # strings + (r'"(\\\\|\\"|[^"])*"', String.Double), + (r"'(\\\\|\\'|[^'])*'", String.Single), + # targets + (r'([^\n:]+)(:+)([ \t]*)', bygroups(Name.Function, Operator, Text), + 'block-header'), + # TODO: add paren handling (grr) + ], + 'export': [ + (r'[a-zA-Z0-9_${}-]+', Name.Variable), + (r'\n', Text, '#pop'), + (r'\s+', Text), + ], + 'block-header': [ + (r'[^,\\\n#]+', Number), + (r',', Punctuation), + (r'#.*?\n', Comment), + (r'\\\n', Text), # line continuation + (r'\\.', Text), + (r'(?:[\t ]+.*\n|\n)+', using(BashLexer), '#pop'), + ], + } + + +class DiffLexer(RegexLexer): + """ + Lexer for unified or context-style diffs or patches. + """ + + name = 'Diff' + aliases = ['diff', 'udiff'] + filenames = ['*.diff', '*.patch'] + mimetypes = ['text/x-diff', 'text/x-patch'] + + tokens = { + 'root': [ + (r' .*\n', Text), + (r'\+.*\n', Generic.Inserted), + (r'-.*\n', Generic.Deleted), + (r'!.*\n', Generic.Strong), + (r'@.*\n', Generic.Subheading), + (r'([Ii]ndex|diff).*\n', Generic.Heading), + (r'=.*\n', Generic.Heading), + (r'.*\n', Text), + ] + } + + def analyse_text(text): + if text[:7] == 'Index: ': + return True + if text[:5] == 'diff ': + return True + if text[:4] == '--- ': + return 0.9 + + +DPATCH_KEYWORDS = ['hunk', 'addfile', 'adddir', 'rmfile', 'rmdir', 'move', + 'replace'] + +class DarcsPatchLexer(RegexLexer): + """ + DarcsPatchLexer is a lexer for the various versions of the darcs patch + format. Examples of this format are derived by commands such as + ``darcs annotate --patch`` and ``darcs send``. + + *New in Pygments 0.10.* + """ + name = 'Darcs Patch' + aliases = ['dpatch'] + filenames = ['*.dpatch', '*.darcspatch'] + + tokens = { + 'root': [ + (r'<', Operator), + (r'>', Operator), + (r'{', Operator), + (r'}', Operator), + (r'(\[)((?:TAG )?)(.*)(\n)(.*)(\*\*)(\d+)(\s?)(\])', + bygroups(Operator, Keyword, Name, Text, Name, Operator, + Literal.Date, Text, Operator)), + (r'(\[)((?:TAG )?)(.*)(\n)(.*)(\*\*)(\d+)(\s?)', + bygroups(Operator, Keyword, Name, Text, Name, Operator, + Literal.Date, Text), 'comment'), + (r'New patches:', Generic.Heading), + (r'Context:', Generic.Heading), + (r'Patch bundle hash:', Generic.Heading), + (r'(\s*)(%s)(.*\n)' % '|'.join(DPATCH_KEYWORDS), + bygroups(Text, Keyword, Text)), + (r'\+', Generic.Inserted, "insert"), + (r'-', Generic.Deleted, "delete"), + (r'.*\n', Text), + ], + 'comment': [ + (r'[^\]].*\n', Comment), + (r'\]', Operator, "#pop"), + ], + 'specialText': [ # darcs add [_CODE_] special operators for clarity + (r'\n', Text, "#pop"), # line-based + (r'\[_[^_]*_]', Operator), + ], + 'insert': [ + include('specialText'), + (r'\[', Generic.Inserted), + (r'[^\n\[]*', Generic.Inserted), + ], + 'delete': [ + include('specialText'), + (r'\[', Generic.Deleted), + (r'[^\n\[]*', Generic.Deleted), + ], + } + + +class IrcLogsLexer(RegexLexer): + """ + Lexer for IRC logs in *irssi*, *xchat* or *weechat* style. + """ + + name = 'IRC logs' + aliases = ['irc'] + filenames = ['*.weechatlog'] + mimetypes = ['text/x-irclog'] + + flags = re.VERBOSE | re.MULTILINE + timestamp = r""" + ( + # irssi / xchat and others + (?: \[|\()? # Opening bracket or paren for the timestamp + (?: # Timestamp + (?: (?:\d{1,4} [-/]?)+ # Date as - or /-separated groups of digits + [T ])? # Date/time separator: T or space + (?: \d?\d [:.]?)+ # Time as :/.-separated groups of 1 or 2 digits + ) + (?: \]|\))?\s+ # Closing bracket or paren for the timestamp + | + # weechat + \d{4}\s\w{3}\s\d{2}\s # Date + \d{2}:\d{2}:\d{2}\s+ # Time + Whitespace + | + # xchat + \w{3}\s\d{2}\s # Date + \d{2}:\d{2}:\d{2}\s+ # Time + Whitespace + )? + """ + tokens = { + 'root': [ + # log start/end + (r'^\*\*\*\*(.*)\*\*\*\*$', Comment), + # hack + ("^" + timestamp + r'(\s*<[^>]*>\s*)$', bygroups(Comment.Preproc, Name.Tag)), + # normal msgs + ("^" + timestamp + r""" + (\s*<.*?>\s*) # Nick """, + bygroups(Comment.Preproc, Name.Tag), 'msg'), + # /me msgs + ("^" + timestamp + r""" + (\s*[*]\s+) # Star + ([^\s]+\s+.*?\n) # Nick + rest of message """, + bygroups(Comment.Preproc, Keyword, Generic.Inserted)), + # join/part msgs + ("^" + timestamp + r""" + (\s*(?:\*{3}|<?-[!@=P]?->?)\s*) # Star(s) or symbols + ([^\s]+\s+) # Nick + Space + (.*?\n) # Rest of message """, + bygroups(Comment.Preproc, Keyword, String, Comment)), + (r"^.*?\n", Text), + ], + 'msg': [ + (r"[^\s]+:(?!//)", Name.Attribute), # Prefix + (r".*\n", Text, '#pop'), + ], + } + + +class BBCodeLexer(RegexLexer): + """ + A lexer that highlights BBCode(-like) syntax. + + *New in Pygments 0.6.* + """ + + name = 'BBCode' + aliases = ['bbcode'] + mimetypes = ['text/x-bbcode'] + + tokens = { + 'root' : [ + (r'[\s\w]+', Text), + (r'(\[)(/?[^\]\n\r=]+)(\])', + bygroups(Keyword, Keyword.Pseudo, Keyword)), + (r'(\[)([^\]\n\r=]+)(=)([^\]\n\r]+)(\])', + bygroups(Keyword, Keyword.Pseudo, Operator, String, Keyword)), + ], + } + + +class TexLexer(RegexLexer): + """ + Lexer for the TeX and LaTeX typesetting languages. + """ + + name = 'TeX' + aliases = ['tex', 'latex'] + filenames = ['*.tex', '*.aux', '*.toc'] + mimetypes = ['text/x-tex', 'text/x-latex'] + + tokens = { + 'general': [ + (r'%.*?\n', Comment), + (r'[{}]', Name.Builtin), + (r'[&_^]', Name.Builtin), + ], + 'root': [ + (r'\\\[', String.Backtick, 'displaymath'), + (r'\\\(', String, 'inlinemath'), + (r'\$\$', String.Backtick, 'displaymath'), + (r'\$', String, 'inlinemath'), + (r'\\([a-zA-Z]+|.)', Keyword, 'command'), + include('general'), + (r'[^\\$%&_^{}]+', Text), + ], + 'math': [ + (r'\\([a-zA-Z]+|.)', Name.Variable), + include('general'), + (r'[0-9]+', Number), + (r'[-=!+*/()\[\]]', Operator), + (r'[^=!+*/()\[\]\\$%&_^{}0-9-]+', Name.Builtin), + ], + 'inlinemath': [ + (r'\\\)', String, '#pop'), + (r'\$', String, '#pop'), + include('math'), + ], + 'displaymath': [ + (r'\\\]', String, '#pop'), + (r'\$\$', String, '#pop'), + (r'\$', Name.Builtin), + include('math'), + ], + 'command': [ + (r'\[.*?\]', Name.Attribute), + (r'\*', Keyword), + (r'', Text, '#pop'), + ], + } + + def analyse_text(text): + for start in ("\\documentclass", "\\input", "\\documentstyle", + "\\relax"): + if text[:len(start)] == start: + return True + + +class GroffLexer(RegexLexer): + """ + Lexer for the (g)roff typesetting language, supporting groff + extensions. Mainly useful for highlighting manpage sources. + + *New in Pygments 0.6.* + """ + + name = 'Groff' + aliases = ['groff', 'nroff', 'man'] + filenames = ['*.[1234567]', '*.man'] + mimetypes = ['application/x-troff', 'text/troff'] + + tokens = { + 'root': [ + (r'(?i)(\.)(\w+)', bygroups(Text, Keyword), 'request'), + (r'\.', Punctuation, 'request'), + # Regular characters, slurp till we find a backslash or newline + (r'[^\\\n]*', Text, 'textline'), + ], + 'textline': [ + include('escapes'), + (r'[^\\\n]+', Text), + (r'\n', Text, '#pop'), + ], + 'escapes': [ + # groff has many ways to write escapes. + (r'\\"[^\n]*', Comment), + (r'\\[fn]\w', String.Escape), + (r'\\\(..', String.Escape), + (r'\\.\[.*\]', String.Escape), + (r'\\.', String.Escape), + (r'\\\n', Text, 'request'), + ], + 'request': [ + (r'\n', Text, '#pop'), + include('escapes'), + (r'"[^\n"]+"', String.Double), + (r'\d+', Number), + (r'\S+', String), + (r'\s+', Text), + ], + } + + def analyse_text(text): + if text[:1] != '.': + return False + if text[:3] == '.\\"': + return True + if text[:4] == '.TH ': + return True + if text[1:3].isalnum() and text[3].isspace(): + return 0.9 + + +class ApacheConfLexer(RegexLexer): + """ + Lexer for configuration files following the Apache config file + format. + + *New in Pygments 0.6.* + """ + + name = 'ApacheConf' + aliases = ['apacheconf', 'aconf', 'apache'] + filenames = ['.htaccess', 'apache.conf', 'apache2.conf'] + mimetypes = ['text/x-apacheconf'] + flags = re.MULTILINE | re.IGNORECASE + + tokens = { + 'root': [ + (r'\s+', Text), + (r'(#.*?)$', Comment), + (r'(<[^\s>]+)(?:(\s+)(.*?))?(>)', + bygroups(Name.Tag, Text, String, Name.Tag)), + (r'([a-zA-Z][a-zA-Z0-9]*)(\s+)', + bygroups(Name.Builtin, Text), 'value'), + (r'\.+', Text), + ], + 'value': [ + (r'$', Text, '#pop'), + (r'[^\S\n]+', Text), + (r'\d+\.\d+\.\d+\.\d+(?:/\d+)?', Number), + (r'\d+', Number), + (r'/([a-zA-Z0-9][a-zA-Z0-9_./-]+)', String.Other), + (r'(on|off|none|any|all|double|email|dns|min|minimal|' + r'os|productonly|full|emerg|alert|crit|error|warn|' + r'notice|info|debug|registry|script|inetd|standalone|' + r'user|group)\b', Keyword), + (r'"([^"\\]*(?:\\.[^"\\]*)*)"', String.Double), + (r'[^\s"]+', Text) + ] + } + + +class MoinWikiLexer(RegexLexer): + """ + For MoinMoin (and Trac) Wiki markup. + + *New in Pygments 0.7.* + """ + + name = 'MoinMoin/Trac Wiki markup' + aliases = ['trac-wiki', 'moin'] + filenames = [] + mimetypes = ['text/x-trac-wiki'] + flags = re.MULTILINE | re.IGNORECASE + + tokens = { + 'root': [ + (r'^#.*$', Comment), + (r'(!)(\S+)', bygroups(Keyword, Text)), # Ignore-next + # Titles + (r'^(=+)([^=]+)(=+)(\s*#.+)?$', + bygroups(Generic.Heading, using(this), Generic.Heading, String)), + # Literal code blocks, with optional shebang + (r'({{{)(\n#!.+)?', bygroups(Name.Builtin, Name.Namespace), 'codeblock'), + (r'(\'\'\'?|\|\||`|__|~~|\^|,,|::)', Comment), # Formatting + # Lists + (r'^( +)([.*-])( )', bygroups(Text, Name.Builtin, Text)), + (r'^( +)([a-zivx]{1,5}\.)( )', bygroups(Text, Name.Builtin, Text)), + # Other Formatting + (r'\[\[\w+.*?\]\]', Keyword), # Macro + (r'(\[[^\s\]]+)(\s+[^\]]+?)?(\])', + bygroups(Keyword, String, Keyword)), # Link + (r'^----+$', Keyword), # Horizontal rules + (r'[^\n\'\[{!_~^,|]+', Text), + (r'\n', Text), + (r'.', Text), + ], + 'codeblock': [ + (r'}}}', Name.Builtin, '#pop'), + # these blocks are allowed to be nested in Trac, but not MoinMoin + (r'{{{', Text, '#push'), + (r'[^{}]+', Comment.Preproc), # slurp boring text + (r'.', Comment.Preproc), # allow loose { or } + ], + } + + +class RstLexer(RegexLexer): + """ + For `reStructuredText <http://docutils.sf.net/rst.html>`_ markup. + + *New in Pygments 0.7.* + + Additional options accepted: + + `handlecodeblocks` + Highlight the contents of ``.. sourcecode:: langauge`` and + ``.. code:: language`` directives with a lexer for the given + language (default: ``True``). *New in Pygments 0.8.* + """ + name = 'reStructuredText' + aliases = ['rst', 'rest', 'restructuredtext'] + filenames = ['*.rst', '*.rest'] + mimetypes = ["text/x-rst", "text/prs.fallenstein.rst"] + flags = re.MULTILINE + + def _handle_sourcecode(self, match): + from pygments.lexers import get_lexer_by_name + from pygments.util import ClassNotFound + + # section header + yield match.start(1), Punctuation, match.group(1) + yield match.start(2), Text, match.group(2) + yield match.start(3), Operator.Word, match.group(3) + yield match.start(4), Punctuation, match.group(4) + yield match.start(5), Text, match.group(5) + yield match.start(6), Keyword, match.group(6) + yield match.start(7), Text, match.group(7) + + # lookup lexer if wanted and existing + lexer = None + if self.handlecodeblocks: + try: + lexer = get_lexer_by_name(match.group(6).strip()) + except ClassNotFound: + pass + indention = match.group(8) + indention_size = len(indention) + code = (indention + match.group(9) + match.group(10) + match.group(11)) + + # no lexer for this language. handle it like it was a code block + if lexer is None: + yield match.start(8), String, code + return + + # highlight the lines with the lexer. + ins = [] + codelines = code.splitlines(True) + code = '' + for line in codelines: + if len(line) > indention_size: + ins.append((len(code), [(0, Text, line[:indention_size])])) + code += line[indention_size:] + else: + code += line + for item in do_insertions(ins, lexer.get_tokens_unprocessed(code)): + yield item + + tokens = { + 'root': [ + # Heading with overline + (r'^(=+|-+|`+|:+|\.+|\'+|"+|~+|\^+|_+|\*+|\++|#+)([ \t]*\n)(.+)(\n)(\1)(\n)', + bygroups(Generic.Heading, Text, Generic.Heading, + Text, Generic.Heading, Text)), + # Plain heading + (r'^(\S.*)(\n)(={3,}|-{3,}|`{3,}|:{3,}|\.{3,}|\'{3,}|"{3,}|' + r'~{3,}|\^{3,}|_{3,}|\*{3,}|\+{3,}|#{3,})(\n)', + bygroups(Generic.Heading, Text, Generic.Heading, Text)), + # Bulleted lists + (r'^(\s*)([-*+])( .+\n(?:\1 .+\n)*)', + bygroups(Text, Number, using(this, state='inline'))), + # Numbered lists + (r'^(\s*)([0-9#ivxlcmIVXLCM]+\.)( .+\n(?:\1 .+\n)*)', + bygroups(Text, Number, using(this, state='inline'))), + (r'^(\s*)(\(?[0-9#ivxlcmIVXLCM]+\))( .+\n(?:\1 .+\n)*)', + bygroups(Text, Number, using(this, state='inline'))), + # Numbered, but keep words at BOL from becoming lists + (r'^(\s*)([A-Z]+\.)( .+\n(?:\1 .+\n)+)', + bygroups(Text, Number, using(this, state='inline'))), + (r'^(\s*)(\(?[A-Za-z]+\))( .+\n(?:\1 .+\n)+)', + bygroups(Text, Number, using(this, state='inline'))), + # Sourcecode directives + (r'^( *\.\.)(\s*)((?:source)?code)(::)([ \t]*)([^\n]+)' + r'(\n[ \t]*\n)([ \t]+)(.*)(\n)((?:(?:\8.*|)\n)+)', + _handle_sourcecode), + # A directive + (r'^( *\.\.)(\s*)([\w-]+)(::)(?:([ \t]*)(.+))?', + bygroups(Punctuation, Text, Operator.Word, Punctuation, Text, Keyword)), + # A reference target + (r'^( *\.\.)(\s*)([\w\t ]+:)(.*?)$', + bygroups(Punctuation, Text, Name.Tag, using(this, state='inline'))), + # A footnote target + (r'^( *\.\.)(\s*)(\[.+\])(.*?)$', + bygroups(Punctuation, Text, Name.Tag, using(this, state='inline'))), + # Comments + (r'^ *\.\..*(\n( +.*\n|\n)+)?', Comment.Preproc), + # Field list + (r'^( *)(:.*?:)([ \t]+)(.*?)$', bygroups(Text, Name.Class, Text, + Name.Function)), + # Definition list + (r'^([^ ].*(?<!::)\n)((?:(?: +.*)\n)+)', + bygroups(using(this, state='inline'), using(this, state='inline'))), + # Code blocks + (r'(::)(\n[ \t]*\n)([ \t]+)(.*)(\n)((?:(?:\3.*|)\n)+)', + bygroups(String.Escape, Text, String, String, Text, String)), + include('inline'), + ], + 'inline': [ + (r'\\.', Text), # escape + (r'``', String, 'literal'), # code + (r'(`)(.+?)(`__?)', + bygroups(Punctuation, using(this), Punctuation)), # reference + (r'(`.+?`)(:[a-zA-Z0-9-]+?:)?', + bygroups(Name.Variable, Name.Attribute)), # role + (r'(:[a-zA-Z0-9-]+?:)(`.+?`)', + bygroups(Name.Attribute, Name.Variable)), # user-defined role + (r'\*\*.+?\*\*', Generic.Strong), # Strong emphasis + (r'\*.+?\*', Generic.Emph), # Emphasis + (r'\[.*?\]_', String), # Footnote or citation + (r'<.+?>', Name.Tag), # Hyperlink + (r'[^\\\n\[*`:]+', Text), + (r'.', Text), + ], + 'literal': [ + (r'[^`\\]+', String), + (r'\\.', String), + (r'``', String, '#pop'), + (r'[`\\]', String), + ] + } + + def __init__(self, **options): + self.handlecodeblocks = get_bool_opt(options, 'handlecodeblocks', True) + RegexLexer.__init__(self, **options) + + def analyse_text(text): + if text[:2] == '..' and text[2:3] != '.': + return 0.3 + p1 = text.find("\n") + p2 = text.find("\n", p1 + 1) + if (p2 > -1 and # has two lines + p1 * 2 + 1 == p2 and # they are the same length + text[p1+1] in '-=' and # the next line both starts and ends with + text[p1+1] == text[p2-1]): # ...a sufficiently high header + return 0.5 + + +class VimLexer(RegexLexer): + """ + Lexer for VimL script files. + + *New in Pygments 0.8.* + """ + name = 'VimL' + aliases = ['vim'] + filenames = ['*.vim', '.vimrc'] + mimetypes = ['text/x-vim'] + flags = re.MULTILINE + + tokens = { + 'root': [ + # Who decided that doublequote was a good comment character?? + (r'^\s*".*', Comment), + (r'(?<=\s)"[^\-:.%#=*].*', Comment), + + (r'[ \t]+', Text), + # TODO: regexes can have other delims + (r'/(\\\\|\\/|[^\n/])*/', String.Regex), + (r'"(\\\\|\\"|[^\n"])*"', String.Double), + (r"'(\\\\|\\'|[^\n'])*'", String.Single), + (r'-?\d+', Number), + (r'#[0-9a-f]{6}', Number.Hex), + (r'^:', Punctuation), + (r'[()<>+=!|,~-]', Punctuation), # Inexact list. Looks decent. + (r'\b(let|if|else|endif|elseif|fun|function|endfunction)\b', + Keyword), + (r'\b(NONE|bold|italic|underline|dark|light)\b', Name.Builtin), + (r'\b\w+\b', Name.Other), # These are postprocessed below + (r'.', Text), + ], + } + def __init__(self, **options): + from pygments.lexers._vimbuiltins import command, option, auto + self._cmd = command + self._opt = option + self._aut = auto + + RegexLexer.__init__(self, **options) + + def is_in(self, w, mapping): + r""" + It's kind of difficult to decide if something might be a keyword + in VimL because it allows you to abbreviate them. In fact, + 'ab[breviate]' is a good example. :ab, :abbre, or :abbreviate are + valid ways to call it so rather than making really awful regexps + like:: + + \bab(?:b(?:r(?:e(?:v(?:i(?:a(?:t(?:e)?)?)?)?)?)?)?)?\b + + we match `\b\w+\b` and then call is_in() on those tokens. See + `scripts/get_vimkw.py` for how the lists are extracted. + """ + p = bisect(mapping, (w,)) + if p > 0: + if mapping[p-1][0] == w[:len(mapping[p-1][0])] and \ + mapping[p-1][1][:len(w)] == w: return True + if p < len(mapping): + return mapping[p][0] == w[:len(mapping[p][0])] and \ + mapping[p][1][:len(w)] == w + return False + + def get_tokens_unprocessed(self, text): + # TODO: builtins are only subsequent tokens on lines + # and 'keywords' only happen at the beginning except + # for :au ones + for index, token, value in \ + RegexLexer.get_tokens_unprocessed(self, text): + if token is Name.Other: + if self.is_in(value, self._cmd): + yield index, Keyword, value + elif self.is_in(value, self._opt) or \ + self.is_in(value, self._aut): + yield index, Name.Builtin, value + else: + yield index, Text, value + else: + yield index, token, value + + +class GettextLexer(RegexLexer): + """ + Lexer for Gettext catalog files. + + *New in Pygments 0.9.* + """ + name = 'Gettext Catalog' + aliases = ['pot', 'po'] + filenames = ['*.pot', '*.po'] + mimetypes = ['application/x-gettext', 'text/x-gettext', 'text/gettext'] + + tokens = { + 'root': [ + (r'^#,\s.*?$', Keyword.Type), + (r'^#:\s.*?$', Keyword.Declaration), + #(r'^#$', Comment), + (r'^(#|#\.\s|#\|\s|#~\s|#\s).*$', Comment.Single), + (r'^(")([\w-]*:)(.*")$', + bygroups(String, Name.Property, String)), + (r'^".*"$', String), + (r'^(msgid|msgid_plural|msgstr)(\s+)(".*")$', + bygroups(Name.Variable, Text, String)), + (r'^(msgstr\[)(\d)(\])(\s+)(".*")$', + bygroups(Name.Variable, Number.Integer, Name.Variable, Text, String)), + ] + } + + +class SquidConfLexer(RegexLexer): + """ + Lexer for `squid <http://www.squid-cache.org/>`_ configuration files. + + *New in Pygments 0.9.* + """ + + name = 'SquidConf' + aliases = ['squidconf', 'squid.conf', 'squid'] + filenames = ['squid.conf'] + mimetypes = ['text/x-squidconf'] + flags = re.IGNORECASE + + keywords = [ "acl", "always_direct", "announce_host", + "announce_period", "announce_port", "announce_to", + "anonymize_headers", "append_domain", "as_whois_server", + "auth_param_basic", "authenticate_children", + "authenticate_program", "authenticate_ttl", "broken_posts", + "buffered_logs", "cache_access_log", "cache_announce", + "cache_dir", "cache_dns_program", "cache_effective_group", + "cache_effective_user", "cache_host", "cache_host_acl", + "cache_host_domain", "cache_log", "cache_mem", + "cache_mem_high", "cache_mem_low", "cache_mgr", + "cachemgr_passwd", "cache_peer", "cache_peer_access", + "cahce_replacement_policy", "cache_stoplist", + "cache_stoplist_pattern", "cache_store_log", "cache_swap", + "cache_swap_high", "cache_swap_log", "cache_swap_low", + "client_db", "client_lifetime", "client_netmask", + "connect_timeout", "coredump_dir", "dead_peer_timeout", + "debug_options", "delay_access", "delay_class", + "delay_initial_bucket_level", "delay_parameters", + "delay_pools", "deny_info", "dns_children", "dns_defnames", + "dns_nameservers", "dns_testnames", "emulate_httpd_log", + "err_html_text", "fake_user_agent", "firewall_ip", + "forwarded_for", "forward_snmpd_port", "fqdncache_size", + "ftpget_options", "ftpget_program", "ftp_list_width", + "ftp_passive", "ftp_user", "half_closed_clients", + "header_access", "header_replace", "hierarchy_stoplist", + "high_response_time_warning", "high_page_fault_warning", + "htcp_port", "http_access", "http_anonymizer", "httpd_accel", + "httpd_accel_host", "httpd_accel_port", + "httpd_accel_uses_host_header", "httpd_accel_with_proxy", + "http_port", "http_reply_access", "icp_access", + "icp_hit_stale", "icp_port", "icp_query_timeout", + "ident_lookup", "ident_lookup_access", "ident_timeout", + "incoming_http_average", "incoming_icp_average", + "inside_firewall", "ipcache_high", "ipcache_low", + "ipcache_size", "local_domain", "local_ip", "logfile_rotate", + "log_fqdn", "log_icp_queries", "log_mime_hdrs", + "maximum_object_size", "maximum_single_addr_tries", + "mcast_groups", "mcast_icp_query_timeout", "mcast_miss_addr", + "mcast_miss_encode_key", "mcast_miss_port", "memory_pools", + "memory_pools_limit", "memory_replacement_policy", + "mime_table", "min_http_poll_cnt", "min_icp_poll_cnt", + "minimum_direct_hops", "minimum_object_size", + "minimum_retry_timeout", "miss_access", "negative_dns_ttl", + "negative_ttl", "neighbor_timeout", "neighbor_type_domain", + "netdb_high", "netdb_low", "netdb_ping_period", + "netdb_ping_rate", "never_direct", "no_cache", + "passthrough_proxy", "pconn_timeout", "pid_filename", + "pinger_program", "positive_dns_ttl", "prefer_direct", + "proxy_auth", "proxy_auth_realm", "query_icmp", "quick_abort", + "quick_abort", "quick_abort_max", "quick_abort_min", + "quick_abort_pct", "range_offset_limit", "read_timeout", + "redirect_children", "redirect_program", + "redirect_rewrites_host_header", "reference_age", + "reference_age", "refresh_pattern", "reload_into_ims", + "request_body_max_size", "request_size", "request_timeout", + "shutdown_lifetime", "single_parent_bypass", + "siteselect_timeout", "snmp_access", "snmp_incoming_address", + "snmp_port", "source_ping", "ssl_proxy", + "store_avg_object_size", "store_objects_per_bucket", + "strip_query_terms", "swap_level1_dirs", "swap_level2_dirs", + "tcp_incoming_address", "tcp_outgoing_address", + "tcp_recv_bufsize", "test_reachability", "udp_hit_obj", + "udp_hit_obj_size", "udp_incoming_address", + "udp_outgoing_address", "unique_hostname", "unlinkd_program", + "uri_whitespace", "useragent_log", "visible_hostname", + "wais_relay", "wais_relay_host", "wais_relay_port", + ] + + opts = [ "proxy-only", "weight", "ttl", "no-query", "default", + "round-robin", "multicast-responder", "on", "off", "all", + "deny", "allow", "via", "parent", "no-digest", "heap", "lru", + "realm", "children", "credentialsttl", "none", "disable", + "offline_toggle", "diskd", "q1", "q2", + ] + + actions = [ "shutdown", "info", "parameter", "server_list", + "client_list", r'squid\.conf', + ] + + actions_stats = [ "objects", "vm_objects", "utilization", + "ipcache", "fqdncache", "dns", "redirector", "io", + "reply_headers", "filedescriptors", "netdb", + ] + + actions_log = [ "status", "enable", "disable", "clear"] + + acls = [ "url_regex", "urlpath_regex", "referer_regex", "port", + "proto", "req_mime_type", "rep_mime_type", "method", + "browser", "user", "src", "dst", "time", "dstdomain", "ident", + "snmp_community", + ] + + ip_re = r'\b(?:\d{1,3}\.){3}\d{1,3}\b' + + def makelistre(list): + return r'\b(?:'+'|'.join(list)+r')\b' + + tokens = { + 'root': [ + (r'\s+', Text), + (r'#', Comment, 'comment'), + (makelistre(keywords), Keyword), + (makelistre(opts), Name.Constant), + # Actions + (makelistre(actions), String), + (r'stats/'+makelistre(actions), String), + (r'log/'+makelistre(actions)+r'=', String), + (makelistre(acls), Keyword), + (ip_re+r'(?:/(?:'+ip_re+r')|\d+)?', Number), + (r'\b\d+\b', Number), + (r'\S+', Text), + ], + 'comment': [ + (r'\s*TAG:.*', String.Escape, '#pop'), + (r'.*', Comment, '#pop'), + ], + } + + +class DebianControlLexer(RegexLexer): + """ + Lexer for Debian ``control`` files and ``apt-cache show <pkg>`` outputs. + + *New in Pygments 0.9.* + """ + name = 'Debian Control file' + aliases = ['control'] + filenames = ['control'] + + tokens = { + 'root': [ + (r'^(Description)', Keyword, 'description'), + (r'^(Maintainer)(:\s*)', bygroups(Keyword, Text), 'maintainer'), + (r'^((Build-)?Depends)', Keyword, 'depends'), + (r'^((?:Python-)?Version)(:\s*)([^\s]+)$', + bygroups(Keyword, Text, Number)), + (r'^((?:Installed-)?Size)(:\s*)([^\s]+)$', + bygroups(Keyword, Text, Number)), + (r'^(MD5Sum|SHA1|SHA256)(:\s*)([^\s]+)$', + bygroups(Keyword, Text, Number)), + (r'^([a-zA-Z\-0-9\.]*?)(:\s*)(.*?)$', + bygroups(Keyword, Whitespace, String)), + ], + 'maintainer': [ + (r'<[^>]+>', Generic.Strong), + (r'<[^>]+>$', Generic.Strong, '#pop'), + (r',\n?', Text), + (r'.', Text), + ], + 'description': [ + (r'(.*)(Homepage)(: )([^\s]+)', bygroups(Text, String, Name, Name.Class)), + (r':.*\n', Generic.Strong), + (r' .*\n', Text), + ('', Text, '#pop'), + ], + 'depends': [ + (r':\s*', Text), + (r'(\$)(\{)(\w+\s*:\s*\w+)', bygroups(Operator, Text, Name.Entity)), + (r'\(', Text, 'depend_vers'), + (r',', Text), + (r'\|', Operator), + (r'[\s]+', Text), + (r'[}\)]\s*$', Text, '#pop'), + (r'[}]', Text), + (r'[^,]$', Name.Function, '#pop'), + (r'([\+\.a-zA-Z0-9-][\s\n]*)', Name.Function), + ], + 'depend_vers': [ + (r'\),', Text, '#pop'), + (r'\)[^,]', Text, '#pop:2'), + (r'([><=]+)(\s*)([^\)]+)', bygroups(Operator, Text, Number)) + ] + } + + +class YamlLexerContext(LexerContext): + """Indentation context for the YAML lexer.""" + + def __init__(self, *args, **kwds): + super(YamlLexerContext, self).__init__(*args, **kwds) + self.indent_stack = [] + self.indent = -1 + self.next_indent = 0 + self.block_scalar_indent = None + + +class YamlLexer(ExtendedRegexLexer): + """ + Lexer for `YAML <http://yaml.org/>`_, a human-friendly data serialization + language. + + *New in Pygments 0.11.* + """ + + name = 'YAML' + aliases = ['yaml'] + filenames = ['*.yaml', '*.yml'] + mimetypes = ['text/x-yaml'] + + + def something(token_class): + """Do not produce empty tokens.""" + def callback(lexer, match, context): + text = match.group() + if not text: + return + yield match.start(), token_class, text + context.pos = match.end() + return callback + + def reset_indent(token_class): + """Reset the indentation levels.""" + def callback(lexer, match, context): + text = match.group() + context.indent_stack = [] + context.indent = -1 + context.next_indent = 0 + context.block_scalar_indent = None + yield match.start(), token_class, text + context.pos = match.end() + return callback + + def save_indent(token_class, start=False): + """Save a possible indentation level.""" + def callback(lexer, match, context): + text = match.group() + extra = '' + if start: + context.next_indent = len(text) + if context.next_indent < context.indent: + while context.next_indent < context.indent: + context.indent = context.indent_stack.pop() + if context.next_indent > context.indent: + extra = text[context.indent:] + text = text[:context.indent] + else: + context.next_indent += len(text) + if text: + yield match.start(), token_class, text + if extra: + yield match.start()+len(text), token_class.Error, extra + context.pos = match.end() + return callback + + def set_indent(token_class, implicit=False): + """Set the previously saved indentation level.""" + def callback(lexer, match, context): + text = match.group() + if context.indent < context.next_indent: + context.indent_stack.append(context.indent) + context.indent = context.next_indent + if not implicit: + context.next_indent += len(text) + yield match.start(), token_class, text + context.pos = match.end() + return callback + + def set_block_scalar_indent(token_class): + """Set an explicit indentation level for a block scalar.""" + def callback(lexer, match, context): + text = match.group() + context.block_scalar_indent = None + if not text: + return + increment = match.group(1) + if increment: + current_indent = max(context.indent, 0) + increment = int(increment) + context.block_scalar_indent = current_indent + increment + if text: + yield match.start(), token_class, text + context.pos = match.end() + return callback + + def parse_block_scalar_empty_line(indent_token_class, content_token_class): + """Process an empty line in a block scalar.""" + def callback(lexer, match, context): + text = match.group() + if (context.block_scalar_indent is None or + len(text) <= context.block_scalar_indent): + if text: + yield match.start(), indent_token_class, text + else: + indentation = text[:context.block_scalar_indent] + content = text[context.block_scalar_indent:] + yield match.start(), indent_token_class, indentation + yield (match.start()+context.block_scalar_indent, + content_token_class, content) + context.pos = match.end() + return callback + + def parse_block_scalar_indent(token_class): + """Process indentation spaces in a block scalar.""" + def callback(lexer, match, context): + text = match.group() + if context.block_scalar_indent is None: + if len(text) <= max(context.indent, 0): + context.stack.pop() + context.stack.pop() + return + context.block_scalar_indent = len(text) + else: + if len(text) < context.block_scalar_indent: + context.stack.pop() + context.stack.pop() + return + if text: + yield match.start(), token_class, text + context.pos = match.end() + return callback + + def parse_plain_scalar_indent(token_class): + """Process indentation spaces in a plain scalar.""" + def callback(lexer, match, context): + text = match.group() + if len(text) <= context.indent: + context.stack.pop() + context.stack.pop() + return + if text: + yield match.start(), token_class, text + context.pos = match.end() + return callback + + + + tokens = { + # the root rules + 'root': [ + # ignored whitespaces + (r'[ ]+(?=#|$)', Text), + # line breaks + (r'\n+', Text), + # a comment + (r'#[^\n]*', Comment.Single), + # the '%YAML' directive + (r'^%YAML(?=[ ]|$)', reset_indent(Name.Tag), 'yaml-directive'), + # the %TAG directive + (r'^%TAG(?=[ ]|$)', reset_indent(Name.Tag), 'tag-directive'), + # document start and document end indicators + (r'^(?:---|\.\.\.)(?=[ ]|$)', reset_indent(Name.Namespace), + 'block-line'), + # indentation spaces + (r'[ ]*(?![ \t\n\r\f\v]|$)', save_indent(Text, start=True), + ('block-line', 'indentation')), + ], + + # trailing whitespaces after directives or a block scalar indicator + 'ignored-line': [ + # ignored whitespaces + (r'[ ]+(?=#|$)', Text), + # a comment + (r'#[^\n]*', Comment.Single), + # line break + (r'\n', Text, '#pop:2'), + ], + + # the %YAML directive + 'yaml-directive': [ + # the version number + (r'([ ]+)([0-9]+\.[0-9]+)', + bygroups(Text, Number), 'ignored-line'), + ], + + # the %YAG directive + 'tag-directive': [ + # a tag handle and the corresponding prefix + (r'([ ]+)(!|![0-9A-Za-z_-]*!)' + r'([ ]+)(!|!?[0-9A-Za-z;/?:@&=+$,_.!~*\'()\[\]%-]+)', + bygroups(Text, Keyword.Type, Text, Keyword.Type), + 'ignored-line'), + ], + + # block scalar indicators and indentation spaces + 'indentation': [ + # trailing whitespaces are ignored + (r'[ ]*$', something(Text), '#pop:2'), + # whitespaces preceeding block collection indicators + (r'[ ]+(?=[?:-](?:[ ]|$))', save_indent(Text)), + # block collection indicators + (r'[?:-](?=[ ]|$)', set_indent(Punctuation.Indicator)), + # the beginning a block line + (r'[ ]*', save_indent(Text), '#pop'), + ], + + # an indented line in the block context + 'block-line': [ + # the line end + (r'[ ]*(?=#|$)', something(Text), '#pop'), + # whitespaces separating tokens + (r'[ ]+', Text), + # tags, anchors and aliases, + include('descriptors'), + # block collections and scalars + include('block-nodes'), + # flow collections and quoted scalars + include('flow-nodes'), + # a plain scalar + (r'(?=[^ \t\n\r\f\v?:,\[\]{}#&*!|>\'"%@`-]|[?:-][^ \t\n\r\f\v])', + something(Name.Variable), + 'plain-scalar-in-block-context'), + ], + + # tags, anchors, aliases + 'descriptors' : [ + # a full-form tag + (r'!<[0-9A-Za-z;/?:@&=+$,_.!~*\'()\[\]%-]+>', Keyword.Type), + # a tag in the form '!', '!suffix' or '!handle!suffix' + (r'!(?:[0-9A-Za-z_-]+)?' + r'(?:![0-9A-Za-z;/?:@&=+$,_.!~*\'()\[\]%-]+)?', Keyword.Type), + # an anchor + (r'&[0-9A-Za-z_-]+', Name.Label), + # an alias + (r'\*[0-9A-Za-z_-]+', Name.Variable), + ], + + # block collections and scalars + 'block-nodes': [ + # implicit key + (r':(?=[ ]|$)', set_indent(Punctuation.Indicator, implicit=True)), + # literal and folded scalars + (r'[|>]', Punctuation.Indicator, + ('block-scalar-content', 'block-scalar-header')), + ], + + # flow collections and quoted scalars + 'flow-nodes': [ + # a flow sequence + (r'\[', Punctuation.Indicator, 'flow-sequence'), + # a flow mapping + (r'\{', Punctuation.Indicator, 'flow-mapping'), + # a single-quoted scalar + (r'\'', String, 'single-quoted-scalar'), + # a double-quoted scalar + (r'\"', String, 'double-quoted-scalar'), + ], + + # the content of a flow collection + 'flow-collection': [ + # whitespaces + (r'[ ]+', Text), + # line breaks + (r'\n+', Text), + # a comment + (r'#[^\n]*', Comment.Single), + # simple indicators + (r'[?:,]', Punctuation.Indicator), + # tags, anchors and aliases + include('descriptors'), + # nested collections and quoted scalars + include('flow-nodes'), + # a plain scalar + (r'(?=[^ \t\n\r\f\v?:,\[\]{}#&*!|>\'"%@`])', + something(Name.Variable), + 'plain-scalar-in-flow-context'), + ], + + # a flow sequence indicated by '[' and ']' + 'flow-sequence': [ + # include flow collection rules + include('flow-collection'), + # the closing indicator + (r'\]', Punctuation.Indicator, '#pop'), + ], + + # a flow mapping indicated by '{' and '}' + 'flow-mapping': [ + # include flow collection rules + include('flow-collection'), + # the closing indicator + (r'\}', Punctuation.Indicator, '#pop'), + ], + + # block scalar lines + 'block-scalar-content': [ + # line break + (r'\n', Text), + # empty line + (r'^[ ]+$', + parse_block_scalar_empty_line(Text, Name.Constant)), + # indentation spaces (we may leave the state here) + (r'^[ ]*', parse_block_scalar_indent(Text)), + # line content + (r'[^\n\r\f\v]+', Name.Constant), + ], + + # the content of a literal or folded scalar + 'block-scalar-header': [ + # indentation indicator followed by chomping flag + (r'([1-9])?[+-]?(?=[ ]|$)', + set_block_scalar_indent(Punctuation.Indicator), + 'ignored-line'), + # chomping flag followed by indentation indicator + (r'[+-]?([1-9])?(?=[ ]|$)', + set_block_scalar_indent(Punctuation.Indicator), + 'ignored-line'), + ], + + # ignored and regular whitespaces in quoted scalars + 'quoted-scalar-whitespaces': [ + # leading and trailing whitespaces are ignored + (r'^[ ]+|[ ]+$', Text), + # line breaks are ignored + (r'\n+', Text), + # other whitespaces are a part of the value + (r'[ ]+', Name.Variable), + ], + + # single-quoted scalars + 'single-quoted-scalar': [ + # include whitespace and line break rules + include('quoted-scalar-whitespaces'), + # escaping of the quote character + (r'\'\'', String.Escape), + # regular non-whitespace characters + (r'[^ \t\n\r\f\v\']+', String), + # the closing quote + (r'\'', String, '#pop'), + ], + + # double-quoted scalars + 'double-quoted-scalar': [ + # include whitespace and line break rules + include('quoted-scalar-whitespaces'), + # escaping of special characters + (r'\\[0abt\tn\nvfre "\\N_LP]', String), + # escape codes + (r'\\(?:x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})', + String.Escape), + # regular non-whitespace characters + (r'[^ \t\n\r\f\v\"\\]+', String), + # the closing quote + (r'"', String, '#pop'), + ], + + # the beginning of a new line while scanning a plain scalar + 'plain-scalar-in-block-context-new-line': [ + # empty lines + (r'^[ ]+$', Text), + # line breaks + (r'\n+', Text), + # document start and document end indicators + (r'^(?=---|\.\.\.)', something(Name.Namespace), '#pop:3'), + # indentation spaces (we may leave the block line state here) + (r'^[ ]*', parse_plain_scalar_indent(Text), '#pop'), + ], + + # a plain scalar in the block context + 'plain-scalar-in-block-context': [ + # the scalar ends with the ':' indicator + (r'[ ]*(?=:[ ]|:$)', something(Text), '#pop'), + # the scalar ends with whitespaces followed by a comment + (r'[ ]+(?=#)', Text, '#pop'), + # trailing whitespaces are ignored + (r'[ ]+$', Text), + # line breaks are ignored + (r'\n+', Text, 'plain-scalar-in-block-context-new-line'), + # other whitespaces are a part of the value + (r'[ ]+', Literal.Scalar.Plain), + # regular non-whitespace characters + (r'(?::(?![ \t\n\r\f\v])|[^ \t\n\r\f\v:])+', Literal.Scalar.Plain), + ], + + # a plain scalar is the flow context + 'plain-scalar-in-flow-context': [ + # the scalar ends with an indicator character + (r'[ ]*(?=[,:?\[\]{}])', something(Text), '#pop'), + # the scalar ends with a comment + (r'[ ]+(?=#)', Text, '#pop'), + # leading and trailing whitespaces are ignored + (r'^[ ]+|[ ]+$', Text), + # line breaks are ignored + (r'\n+', Text), + # other whitespaces are a part of the value + (r'[ ]+', Name.Variable), + # regular non-whitespace characters + (r'[^ \t\n\r\f\v,:?\[\]{}]+', Name.Variable), + ], + + } + + def get_tokens_unprocessed(self, text=None, context=None): + if context is None: + context = YamlLexerContext(text, 0) + return super(YamlLexer, self).get_tokens_unprocessed(text, context) + + +class LighttpdConfLexer(RegexLexer): + """ + Lexer for `Lighttpd <http://lighttpd.net/>`_ configuration files. + + *New in Pygments 0.11.* + """ + name = 'Lighttpd configuration file' + aliases = ['lighty', 'lighttpd'] + filenames = [] + mimetypes = ['text/x-lighttpd-conf'] + + tokens = { + 'root': [ + (r'#.*\n', Comment.Single), + (r'/\S*', Name), # pathname + (r'[a-zA-Z._-]+', Keyword), + (r'\d+\.\d+\.\d+\.\d+(?:/\d+)?', Number), + (r'[0-9]+', Number), + (r'=>|=~|\+=|==|=|\+', Operator), + (r'\$[A-Z]+', Name.Builtin), + (r'[(){}\[\],]', Punctuation), + (r'"([^"\\]*(?:\\.[^"\\]*)*)"', String.Double), + (r'\s+', Text), + ], + + } + + +class NginxConfLexer(RegexLexer): + """ + Lexer for `Nginx <http://nginx.net/>`_ configuration files. + + *New in Pygments 0.11.* + """ + name = 'Nginx configuration file' + aliases = ['nginx'] + filenames = [] + mimetypes = ['text/x-nginx-conf'] + + tokens = { + 'root': [ + (r'(include)(\s+)([^\s;]+)', bygroups(Keyword, Text, Name)), + (r'[^\s;#]+', Keyword, 'stmt'), + include('base'), + ], + 'block': [ + (r'}', Punctuation, '#pop:2'), + (r'[^\s;#]+', Keyword.Namespace, 'stmt'), + include('base'), + ], + 'stmt': [ + (r'{', Punctuation, 'block'), + (r';', Punctuation, '#pop'), + include('base'), + ], + 'base': [ + (r'#.*\n', Comment.Single), + (r'on|off', Name.Constant), + (r'\$[^\s;#()]+', Name.Variable), + (r'([a-z0-9.-]+)(:)([0-9]+)', + bygroups(Name, Punctuation, Number.Integer)), + (r'[a-z-]+/[a-z-+]+', String), # mimetype + #(r'[a-zA-Z._-]+', Keyword), + (r'[0-9]+[km]?\b', Number.Integer), + (r'(~)(\s*)([^\s{]+)', bygroups(Punctuation, Text, String.Regex)), + (r'[:=~]', Punctuation), + (r'[^\s;#{}$]+', String), # catch all + (r'/[^\s;#]*', Name), # pathname + (r'\s+', Text), + ], + }