diff options
Diffstat (limited to 'python/pyyaml/examples')
-rw-r--r-- | python/pyyaml/examples/pygments-lexer/example.yaml | 302 | ||||
-rw-r--r-- | python/pyyaml/examples/pygments-lexer/yaml.py | 431 | ||||
-rw-r--r-- | python/pyyaml/examples/yaml-highlight/yaml_hl.cfg | 115 | ||||
-rwxr-xr-x | python/pyyaml/examples/yaml-highlight/yaml_hl.py | 114 |
4 files changed, 962 insertions, 0 deletions
diff --git a/python/pyyaml/examples/pygments-lexer/example.yaml b/python/pyyaml/examples/pygments-lexer/example.yaml new file mode 100644 index 0000000000..9c0ed9d082 --- /dev/null +++ b/python/pyyaml/examples/pygments-lexer/example.yaml @@ -0,0 +1,302 @@ + +# +# Examples from the Preview section of the YAML specification +# (http://yaml.org/spec/1.2/#Preview) +# + +# Sequence of scalars +--- +- Mark McGwire +- Sammy Sosa +- Ken Griffey + +# Mapping scalars to scalars +--- +hr: 65 # Home runs +avg: 0.278 # Batting average +rbi: 147 # Runs Batted In + +# Mapping scalars to sequences +--- +american: + - Boston Red Sox + - Detroit Tigers + - New York Yankees +national: + - New York Mets + - Chicago Cubs + - Atlanta Braves + +# Sequence of mappings +--- +- + name: Mark McGwire + hr: 65 + avg: 0.278 +- + name: Sammy Sosa + hr: 63 + avg: 0.288 + +# Sequence of sequences +--- +- [name , hr, avg ] +- [Mark McGwire, 65, 0.278] +- [Sammy Sosa , 63, 0.288] + +# Mapping of mappings +--- +Mark McGwire: {hr: 65, avg: 0.278} +Sammy Sosa: { + hr: 63, + avg: 0.288 + } + +# Two documents in a stream +--- # Ranking of 1998 home runs +- Mark McGwire +- Sammy Sosa +- Ken Griffey +--- # Team ranking +- Chicago Cubs +- St Louis Cardinals + +# Documents with the end indicator +--- +time: 20:03:20 +player: Sammy Sosa +action: strike (miss) +... +--- +time: 20:03:47 +player: Sammy Sosa +action: grand slam +... + +# Comments +--- +hr: # 1998 hr ranking + - Mark McGwire + - Sammy Sosa +rbi: + # 1998 rbi ranking + - Sammy Sosa + - Ken Griffey + +# Anchors and aliases +--- +hr: + - Mark McGwire + # Following node labeled SS + - &SS Sammy Sosa +rbi: + - *SS # Subsequent occurrence + - Ken Griffey + +# Mapping between sequences +--- +? - Detroit Tigers + - Chicago cubs +: + - 2001-07-23 +? [ New York Yankees, + Atlanta Braves ] +: [ 2001-07-02, 2001-08-12, + 2001-08-14 ] + +# Inline nested mapping +--- +# products purchased +- item : Super Hoop + quantity: 1 +- item : Basketball + quantity: 4 +- item : Big Shoes + quantity: 1 + +# Literal scalars +--- | # ASCII art + \//||\/|| + // || ||__ + +# Folded scalars +--- > + Mark McGwire's + year was crippled + by a knee injury. + +# Preserved indented block in a folded scalar +--- +> + Sammy Sosa completed another + fine season with great stats. + + 63 Home Runs + 0.288 Batting Average + + What a year! + +# Indentation determines scope +--- +name: Mark McGwire +accomplishment: > + Mark set a major league + home run record in 1998. +stats: | + 65 Home Runs + 0.278 Batting Average + +# Quoted scalars +--- +unicode: "Sosa did fine.\u263A" +control: "\b1998\t1999\t2000\n" +hex esc: "\x0d\x0a is \r\n" +single: '"Howdy!" he cried.' +quoted: ' # not a ''comment''.' +tie-fighter: '|\-*-/|' + +# Multi-line flow scalars +--- +plain: + This unquoted scalar + spans many lines. +quoted: "So does this + quoted scalar.\n" + +# Integers +--- +canonical: 12345 +decimal: +12_345 +sexagesimal: 3:25:45 +octal: 014 +hexadecimal: 0xC + +# Floating point +--- +canonical: 1.23015e+3 +exponential: 12.3015e+02 +sexagesimal: 20:30.15 +fixed: 1_230.15 +negative infinity: -.inf +not a number: .NaN + +# Miscellaneous +--- +null: ~ +true: boolean +false: boolean +string: '12345' + +# Timestamps +--- +canonical: 2001-12-15T02:59:43.1Z +iso8601: 2001-12-14t21:59:43.10-05:00 +spaced: 2001-12-14 21:59:43.10 -5 +date: 2002-12-14 + +# Various explicit tags +--- +not-date: !!str 2002-04-28 +picture: !!binary | + R0lGODlhDAAMAIQAAP//9/X + 17unp5WZmZgAAAOfn515eXv + Pz7Y6OjuDg4J+fn5OTk6enp + 56enmleECcgggoBADs= +application specific tag: !something | + The semantics of the tag + above may be different for + different documents. + +# Global tags +%TAG ! tag:clarkevans.com,2002: +--- !shape + # Use the ! handle for presenting + # tag:clarkevans.com,2002:circle +- !circle + center: &ORIGIN {x: 73, y: 129} + radius: 7 +- !line + start: *ORIGIN + finish: { x: 89, y: 102 } +- !label + start: *ORIGIN + color: 0xFFEEBB + text: Pretty vector drawing. + +# Unordered sets +--- !!set +# sets are represented as a +# mapping where each key is +# associated with the empty string +? Mark McGwire +? Sammy Sosa +? Ken Griff + +# Ordered mappings +--- !!omap +# ordered maps are represented as +# a sequence of mappings, with +# each mapping having one key +- Mark McGwire: 65 +- Sammy Sosa: 63 +- Ken Griffy: 58 + +# Full length example +--- !<tag:clarkevans.com,2002:invoice> +invoice: 34843 +date : 2001-01-23 +bill-to: &id001 + given : Chris + family : Dumars + address: + lines: | + 458 Walkman Dr. + Suite #292 + city : Royal Oak + state : MI + postal : 48046 +ship-to: *id001 +product: + - sku : BL394D + quantity : 4 + description : Basketball + price : 450.00 + - sku : BL4438H + quantity : 1 + description : Super Hoop + price : 2392.00 +tax : 251.42 +total: 4443.52 +comments: + Late afternoon is best. + Backup contact is Nancy + Billsmer @ 338-4338. + +# Another full-length example +--- +Time: 2001-11-23 15:01:42 -5 +User: ed +Warning: + This is an error message + for the log file +--- +Time: 2001-11-23 15:02:31 -5 +User: ed +Warning: + A slightly different error + message. +--- +Date: 2001-11-23 15:03:17 -5 +User: ed +Fatal: + Unknown variable "bar" +Stack: + - file: TopClass.py + line: 23 + code: | + x = MoreObject("345\n") + - file: MoreClass.py + line: 58 + code: |- + foo = bar + diff --git a/python/pyyaml/examples/pygments-lexer/yaml.py b/python/pyyaml/examples/pygments-lexer/yaml.py new file mode 100644 index 0000000000..1ce9dac9e4 --- /dev/null +++ b/python/pyyaml/examples/pygments-lexer/yaml.py @@ -0,0 +1,431 @@ + +""" +yaml.py + +Lexer for YAML, a human-friendly data serialization language +(http://yaml.org/). + +Written by Kirill Simonov <xi@resolvent.net>. + +License: Whatever suitable for inclusion into the Pygments package. +""" + +from pygments.lexer import \ + ExtendedRegexLexer, LexerContext, include, bygroups +from pygments.token import \ + Text, Comment, Punctuation, Name, Literal + +__all__ = ['YAMLLexer'] + + +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 + + +def something(TokenClass): + """Do not produce empty tokens.""" + def callback(lexer, match, context): + text = match.group() + if not text: + return + yield match.start(), TokenClass, text + context.pos = match.end() + return callback + +def reset_indent(TokenClass): + """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(), TokenClass, text + context.pos = match.end() + return callback + +def save_indent(TokenClass, 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(), TokenClass, text + if extra: + yield match.start()+len(text), TokenClass.Error, extra + context.pos = match.end() + return callback + +def set_indent(TokenClass, 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(), TokenClass, text + context.pos = match.end() + return callback + +def set_block_scalar_indent(TokenClass): + """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(), TokenClass, text + context.pos = match.end() + return callback + +def parse_block_scalar_empty_line(IndentTokenClass, ContentTokenClass): + """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(), IndentTokenClass, text + else: + indentation = text[:context.block_scalar_indent] + content = text[context.block_scalar_indent:] + yield match.start(), IndentTokenClass, indentation + yield (match.start()+context.block_scalar_indent, + ContentTokenClass, content) + context.pos = match.end() + return callback + +def parse_block_scalar_indent(TokenClass): + """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(), TokenClass, text + context.pos = match.end() + return callback + +def parse_plain_scalar_indent(TokenClass): + """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(), TokenClass, text + context.pos = match.end() + return callback + + +class YAMLLexer(ExtendedRegexLexer): + """Lexer for the YAML language.""" + + name = 'YAML' + aliases = ['yaml'] + filenames = ['*.yaml', '*.yml'] + mimetypes = ['text/x-yaml'] + + tokens = { + + # the root rules + 'root': [ + # ignored whitespaces + (r'[ ]+(?=#|$)', Text.Blank), + # line breaks + (r'\n+', Text.Break), + # a comment + (r'#[^\n]*', Comment.Single), + # the '%YAML' directive + (r'^%YAML(?=[ ]|$)', reset_indent(Name.Directive), + 'yaml-directive'), + # the %TAG directive + (r'^%TAG(?=[ ]|$)', reset_indent(Name.Directive), + 'tag-directive'), + # document start and document end indicators + (r'^(?:---|\.\.\.)(?=[ ]|$)', + reset_indent(Punctuation.Document), 'block-line'), + # indentation spaces + (r'[ ]*(?![ \t\n\r\f\v]|$)', + save_indent(Text.Indent, start=True), + ('block-line', 'indentation')), + ], + + # trailing whitespaces after directives or a block scalar indicator + 'ignored-line': [ + # ignored whitespaces + (r'[ ]+(?=#|$)', Text.Blank), + # a comment + (r'#[^\n]*', Comment.Single), + # line break + (r'\n', Text.Break, '#pop:2'), + ], + + # the %YAML directive + 'yaml-directive': [ + # the version number + (r'([ ]+)([0-9]+\.[0-9]+)', + bygroups(Text.Blank, Literal.Version), '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.Blank, Name.Type, Text.Blank, Name.Type), + 'ignored-line'), + ], + + # block scalar indicators and indentation spaces + 'indentation': [ + # trailing whitespaces are ignored + (r'[ ]*$', something(Text.Blank), '#pop:2'), + # whitespaces preceeding block collection indicators + (r'[ ]+(?=[?:-](?:[ ]|$))', save_indent(Text.Indent)), + # block collection indicators + (r'[?:-](?=[ ]|$)', set_indent(Punctuation.Indicator)), + # the beginning a block line + (r'[ ]*', save_indent(Text.Indent), '#pop'), + ], + + # an indented line in the block context + 'block-line': [ + # the line end + (r'[ ]*(?=#|$)', something(Text.Blank), '#pop'), + # whitespaces separating tokens + (r'[ ]+', Text.Blank), + # 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(Literal.Scalar.Plain), + 'plain-scalar-in-block-context'), + ], + + # tags, anchors, aliases + 'descriptors' : [ + # a full-form tag + (r'!<[0-9A-Za-z;/?:@&=+$,_.!~*\'()\[\]%-]+>', Name.Type), + # a tag in the form '!', '!suffix' or '!handle!suffix' + (r'!(?:[0-9A-Za-z_-]+)?' + r'(?:![0-9A-Za-z;/?:@&=+$,_.!~*\'()\[\]%-]+)?', Name.Type), + # an anchor + (r'&[0-9A-Za-z_-]+', Name.Anchor), + # an alias + (r'\*[0-9A-Za-z_-]+', Name.Alias), + ], + + # 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'\'', Literal.Scalar.Flow.Quote, 'single-quoted-scalar'), + # a double-quoted scalar + (r'\"', Literal.Scalar.Flow.Quote, 'double-quoted-scalar'), + ], + + # the content of a flow collection + 'flow-collection': [ + # whitespaces + (r'[ ]+', Text.Blank), + # line breaks + (r'\n+', Text.Break), + # 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(Literal.Scalar.Plain), + '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.Break), + # empty line + (r'^[ ]+$', + parse_block_scalar_empty_line(Text.Indent, + Literal.Scalar.Block)), + # indentation spaces (we may leave the state here) + (r'^[ ]*', parse_block_scalar_indent(Text.Indent)), + # line content + (r'[^\n\r\f\v]+', Literal.Scalar.Block), + ], + + # 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.Blank), + # line breaks are ignored + (r'\n+', Text.Break), + # other whitespaces are a part of the value + (r'[ ]+', Literal.Scalar.Flow), + ], + + # single-quoted scalars + 'single-quoted-scalar': [ + # include whitespace and line break rules + include('quoted-scalar-whitespaces'), + # escaping of the quote character + (r'\'\'', Literal.Scalar.Flow.Escape), + # regular non-whitespace characters + (r'[^ \t\n\r\f\v\']+', Literal.Scalar.Flow), + # the closing quote + (r'\'', Literal.Scalar.Flow.Quote, '#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]', Literal.Scalar.Flow.Escape), + # escape codes + (r'\\(?:x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})', + Literal.Scalar.Flow.Escape), + # regular non-whitespace characters + (r'[^ \t\n\r\f\v\"\\]+', Literal.Scalar.Flow), + # the closing quote + (r'"', Literal.Scalar.Flow.Quote, '#pop'), + ], + + # the beginning of a new line while scanning a plain scalar + 'plain-scalar-in-block-context-new-line': [ + # empty lines + (r'^[ ]+$', Text.Blank), + # line breaks + (r'\n+', Text.Break), + # document start and document end indicators + (r'^(?=---|\.\.\.)', something(Punctuation.Document), '#pop:3'), + # indentation spaces (we may leave the block line state here) + (r'^[ ]*', parse_plain_scalar_indent(Text.Indent), '#pop'), + ], + + # a plain scalar in the block context + 'plain-scalar-in-block-context': [ + # the scalar ends with the ':' indicator + (r'[ ]*(?=:[ ]|:$)', something(Text.Blank), '#pop'), + # the scalar ends with whitespaces followed by a comment + (r'[ ]+(?=#)', Text.Blank, '#pop'), + # trailing whitespaces are ignored + (r'[ ]+$', Text.Blank), + # line breaks are ignored + (r'\n+', Text.Break, '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.Blank), '#pop'), + # the scalar ends with a comment + (r'[ ]+(?=#)', Text.Blank, '#pop'), + # leading and trailing whitespaces are ignored + (r'^[ ]+|[ ]+$', Text.Blank), + # line breaks are ignored + (r'\n+', Text.Break), + # other whitespaces are a part of the value + (r'[ ]+', Literal.Scalar.Plain), + # regular non-whitespace characters + (r'[^ \t\n\r\f\v,:?\[\]{}]+', Literal.Scalar.Plain), + ], + + } + + 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) + + diff --git a/python/pyyaml/examples/yaml-highlight/yaml_hl.cfg b/python/pyyaml/examples/yaml-highlight/yaml_hl.cfg new file mode 100644 index 0000000000..69bb847764 --- /dev/null +++ b/python/pyyaml/examples/yaml-highlight/yaml_hl.cfg @@ -0,0 +1,115 @@ +%YAML 1.1 +--- + +ascii: + + header: "\e[0;1;30;40m" + + footer: "\e[0m" + + tokens: + stream-start: + stream-end: + directive: { start: "\e[35m", end: "\e[0;1;30;40m" } + document-start: { start: "\e[35m", end: "\e[0;1;30;40m" } + document-end: { start: "\e[35m", end: "\e[0;1;30;40m" } + block-sequence-start: + block-mapping-start: + block-end: + flow-sequence-start: { start: "\e[33m", end: "\e[0;1;30;40m" } + flow-mapping-start: { start: "\e[33m", end: "\e[0;1;30;40m" } + flow-sequence-end: { start: "\e[33m", end: "\e[0;1;30;40m" } + flow-mapping-end: { start: "\e[33m", end: "\e[0;1;30;40m" } + key: { start: "\e[33m", end: "\e[0;1;30;40m" } + value: { start: "\e[33m", end: "\e[0;1;30;40m" } + block-entry: { start: "\e[33m", end: "\e[0;1;30;40m" } + flow-entry: { start: "\e[33m", end: "\e[0;1;30;40m" } + alias: { start: "\e[32m", end: "\e[0;1;30;40m" } + anchor: { start: "\e[32m", end: "\e[0;1;30;40m" } + tag: { start: "\e[32m", end: "\e[0;1;30;40m" } + scalar: { start: "\e[36m", end: "\e[0;1;30;40m" } + + replaces: + - "\r\n": "\n" + - "\r": "\n" + - "\n": "\n" + - "\x85": "\n" + - "\u2028": "\n" + - "\u2029": "\n" + +html: &html + + tokens: + stream-start: + stream-end: + directive: { start: <code class="directive_token">, end: </code> } + document-start: { start: <code class="document_start_token">, end: </code> } + document-end: { start: <code class="document_end_token">, end: </code> } + block-sequence-start: + block-mapping-start: + block-end: + flow-sequence-start: { start: <code class="delimiter_token">, end: </code> } + flow-mapping-start: { start: <code class="delimiter_token">, end: </code> } + flow-sequence-end: { start: <code class="delimiter_token">, end: </code> } + flow-mapping-end: { start: <code class="delimiter_token">, end: </code> } + key: { start: <code class="delimiter_token">, end: </code> } + value: { start: <code class="delimiter_token">, end: </code> } + block-entry: { start: <code class="delimiter_token">, end: </code> } + flow-entry: { start: <code class="delimiter_token">, end: </code> } + alias: { start: <code class="anchor_token">, end: </code> } + anchor: { start: <code class="anchor_token">, end: </code> } + tag: { start: <code class="tag_token">, end: </code> } + scalar: { start: <code class="scalar_token">, end: </code> } + + events: + stream-start: { start: <pre class="yaml_stream"> } + stream-end: { end: </pre> } + document-start: { start: <span class="document"> } + document-end: { end: </span> } + sequence-start: { start: <span class="sequence"> } + sequence-end: { end: </span> } + mapping-start: { start: <span class="mapping"> } + mapping-end: { end: </span> } + scalar: { start: <span class="scalar">, end: </span> } + + replaces: + - "\r\n": "\n" + - "\r": "\n" + - "\n": "\n" + - "\x85": "\n" + - "\u2028": "\n" + - "\u2029": "\n" + - "&": "&" + - "<": "<" + - ">": ">" + +html-page: + + header: | + <html> + <head> + <title>A YAML stream</title> + <style type="text/css"> + .document { background: #FFF } + .sequence { background: #EEF } + .mapping { background: #EFE } + .scalar { background: #FEE } + .directive_token { color: #C0C } + .document_start_token { color: #C0C; font-weight: bold } + .document_end_token { color: #C0C; font-weight: bold } + .delimiter_token { color: #600; font-weight: bold } + .anchor_token { color: #090 } + .tag_token { color: #090 } + .scalar_token { color: #000 } + .yaml_stream { color: #999 } + </style> + <body> + + footer: | + </body> + </html> + + <<: *html + + +# vim: ft=yaml diff --git a/python/pyyaml/examples/yaml-highlight/yaml_hl.py b/python/pyyaml/examples/yaml-highlight/yaml_hl.py new file mode 100755 index 0000000000..d6f7bf4eb2 --- /dev/null +++ b/python/pyyaml/examples/yaml-highlight/yaml_hl.py @@ -0,0 +1,114 @@ +#!/usr/bin/python + +import yaml, codecs, sys, os.path, optparse + +class Style: + + def __init__(self, header=None, footer=None, + tokens=None, events=None, replaces=None): + self.header = header + self.footer = footer + self.replaces = replaces + self.substitutions = {} + for domain, Class in [(tokens, 'Token'), (events, 'Event')]: + if not domain: + continue + for key in domain: + name = ''.join([part.capitalize() for part in key.split('-')]) + cls = getattr(yaml, '%s%s' % (name, Class)) + value = domain[key] + if not value: + continue + start = value.get('start') + end = value.get('end') + if start: + self.substitutions[cls, -1] = start + if end: + self.substitutions[cls, +1] = end + + def __setstate__(self, state): + self.__init__(**state) + +yaml.add_path_resolver(u'tag:yaml.org,2002:python/object:__main__.Style', + [None], dict) +yaml.add_path_resolver(u'tag:yaml.org,2002:pairs', + [None, u'replaces'], list) + +class YAMLHighlight: + + def __init__(self, options): + config = yaml.load(file(options.config, 'rb').read()) + self.style = config[options.style] + if options.input: + self.input = file(options.input, 'rb') + else: + self.input = sys.stdin + if options.output: + self.output = file(options.output, 'wb') + else: + self.output = sys.stdout + + def highlight(self): + input = self.input.read() + if input.startswith(codecs.BOM_UTF16_LE): + input = unicode(input, 'utf-16-le') + elif input.startswith(codecs.BOM_UTF16_BE): + input = unicode(input, 'utf-16-be') + else: + input = unicode(input, 'utf-8') + substitutions = self.style.substitutions + tokens = yaml.scan(input) + events = yaml.parse(input) + markers = [] + number = 0 + for token in tokens: + number += 1 + if token.start_mark.index != token.end_mark.index: + cls = token.__class__ + if (cls, -1) in substitutions: + markers.append([token.start_mark.index, +2, number, substitutions[cls, -1]]) + if (cls, +1) in substitutions: + markers.append([token.end_mark.index, -2, number, substitutions[cls, +1]]) + number = 0 + for event in events: + number += 1 + cls = event.__class__ + if (cls, -1) in substitutions: + markers.append([event.start_mark.index, +1, number, substitutions[cls, -1]]) + if (cls, +1) in substitutions: + markers.append([event.end_mark.index, -1, number, substitutions[cls, +1]]) + markers.sort() + markers.reverse() + chunks = [] + position = len(input) + for index, weight1, weight2, substitution in markers: + if index < position: + chunk = input[index:position] + for substring, replacement in self.style.replaces: + chunk = chunk.replace(substring, replacement) + chunks.append(chunk) + position = index + chunks.append(substitution) + chunks.reverse() + result = u''.join(chunks) + if self.style.header: + self.output.write(self.style.header) + self.output.write(result.encode('utf-8')) + if self.style.footer: + self.output.write(self.style.footer) + +if __name__ == '__main__': + parser = optparse.OptionParser() + parser.add_option('-s', '--style', dest='style', default='ascii', + help="specify the highlighting style", metavar='STYLE') + parser.add_option('-c', '--config', dest='config', + default=os.path.join(os.path.dirname(sys.argv[0]), 'yaml_hl.cfg'), + help="set an alternative configuration file", metavar='CONFIG') + parser.add_option('-i', '--input', dest='input', default=None, + help="set the input file (default: stdin)", metavar='FILE') + parser.add_option('-o', '--output', dest='output', default=None, + help="set the output file (default: stdout)", metavar='FILE') + (options, args) = parser.parse_args() + hl = YAMLHighlight(options) + hl.highlight() + |