├── setup.cfg
├── test
├── empty.t
├── styles.t
├── paragraph.t
└── lists.t
├── demo
├── README.md
├── send-inputs.sh
├── autoreload.sh
├── demo.sh
└── demo.tsq
├── Makefile
├── bin
└── rst2ansi
├── LICENSE
├── .travis.yml
├── rst2ansi
├── functional.py
├── visitor.py
├── unicode.py
├── wrap.py
├── __init__.py
├── get_terminal_size.py
├── table.py
└── ansi.py
├── setup.py
├── README.rst
└── TODO.md
/setup.cfg:
--------------------------------------------------------------------------------
1 | [bdist_wheel]
2 | python-tag = py3
3 |
--------------------------------------------------------------------------------
/test/empty.t:
--------------------------------------------------------------------------------
1 | Test the rendering of an empty file:
2 |
3 | $ rst2ansi /dev/null
4 |
--------------------------------------------------------------------------------
/demo/README.md:
--------------------------------------------------------------------------------
1 | ## rst2ansi demo files
2 |
3 | These are the scripts and inputs used to record the demo screencast.
4 |
--------------------------------------------------------------------------------
/demo/send-inputs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | pts=$1; shift
3 |
4 | reseq demo/demo.tsq --replay | sudo ttysend -i $pts
5 | wait 3
6 | tmux kill-session -t demo
7 |
--------------------------------------------------------------------------------
/demo/autoreload.sh:
--------------------------------------------------------------------------------
1 | clear
2 | export PYTHONPATH=.
3 | while true;
4 | do inotifywait -e modify out.rst 2>/dev/null >/dev/null
5 | clear
6 | ./bin/rst2ansi out.rst
7 | done
8 |
--------------------------------------------------------------------------------
/demo/demo.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | echo "" > out.rst
4 |
5 | tmux new-session -s demo -n rst2ansi -d 'nvim out.rst -c ":set nobackup" -c ":set noswapfile"'
6 | tmux splitw -t demo -h 'zsh ./demo/autoreload.sh'
7 | tmux lastp -t demo
8 | tmux -2 attach-session -t demo
9 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | PY := python3
2 |
3 | export PATH := $(shell pwd)/bin:$(PATH)
4 | export PYTHONPATH=$(shell pwd)
5 |
6 | BUILD = $(PY) setup.py
7 |
8 | build:
9 | $(BUILD) build
10 |
11 | install:
12 | $(BUILD) install
13 |
14 | test:
15 | cram test -v
16 |
17 | clean:
18 | $(BUILD) clean
19 |
20 | .PHONY: build install test clean
21 |
--------------------------------------------------------------------------------
/bin/rst2ansi:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sys
4 | from rst2ansi import rst2ansi
5 | import argparse
6 | import io
7 |
8 | parser = argparse.ArgumentParser(description='Prints a reStructuredText input in an ansi-decorated format suitable for console output.')
9 | parser.add_argument('file', type=str, nargs='?', help='A path to the file to open')
10 |
11 | args = parser.parse_args()
12 |
13 | def process_file(f):
14 | out = rst2ansi(f.read())
15 | if out:
16 | try:
17 | print(out)
18 | except UnicodeEncodeError:
19 | print(out.encode('ascii', errors='backslashreplace').decode('ascii'))
20 |
21 | if args.file:
22 | with io.open(args.file, 'rb') as f:
23 | process_file(f)
24 | else:
25 | process_file(sys.stdin)
26 |
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright © 2015-2016 Franklin "Snaipe" Mathieu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 |
3 | sudo: false
4 |
5 | python:
6 | - 2.7
7 | - 3.3
8 | - 3.4
9 | - nightly
10 |
11 | matrix:
12 | include:
13 | - python: 3.5
14 | env:
15 | DEPLOY: true
16 |
17 | allow_failures:
18 | - python: nightly
19 |
20 | install: pip install docutils cram
21 |
22 | script:
23 | - make build
24 | - make test
25 |
26 | deploy:
27 | provider: pypi
28 | skip_cleanup: true
29 | user: Snaipe
30 | password:
31 | secure: CjyhyupM4hDysV9FAjB/CmbimFgoMiyN2JvV4sje3mB+iyFAIUp5imDQlW60mbgplrnROXiFyaUpk1OhKCW/Eu6KKnjhQevz/iY/d+Bfk1TnjvsWTNEKU54QAsWxN9AjL92y+e35hN0emFSDd1ZhzWYj+uTJ39zxBsjFmdJS+2xXkhlAdeAblGQkQ9cFRXr2JFTSYDLKTTqSviCzo1iLddl8uPb8fFlESjAyl8AnxrK2d50RC9GW7yz5umox/McjYPhX+VFQ0ITfG/b+wtJveOOoFIUvPKUMxv55sEWUiuMv1ZZ1PPaeXUGkDyvZ0zSoruo8m9ZZlTqUwJdEFuzxlfopod2h86J9fTYD4NKIhgNssO9sqRcgR2sgvNOWQ9wGmZggt3exluHeyL1iBJLU1z0CHDQQXmI3Au41Ziug+O0GokfSTnmCYkMHEkgZtaHj/UINKE9SyNPqEsa+N6KaclImw7+ZI6KUsl38LB2EOU6xouCMe6wBfwnVOmAzvzNH7BAtvu7VcSzyX9ikG4JQIZz73zOnm7Y28ENnsGM18ItRI33lf+D9wNCeff9whH9NTPA7RBrJ4DDP7PC5Mz3em1AlJdkEe360JI6plXZrVffSrpETN2fRAQp0x5fTUO333x1vbWNOW4/bryZ3EEG0VmOFYKcMxv6hL+78esCJuuI=
32 | on:
33 | repo: Snaipe/python-rst2ansi
34 | tags: true
35 | distributions: sdist bdist_wheel
36 | condition: $DEPLOY = true
37 |
--------------------------------------------------------------------------------
/rst2ansi/functional.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | The MIT License (MIT)
4 |
5 | Copyright © 2015-2016 Franklin "Snaipe" Mathieu
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 | """
25 |
26 | def npartial(func, *args, **kwargs):
27 | """
28 | Returns a partial node visitor function
29 | """
30 | def wrapped(self, node):
31 | func(self, *args, **kwargs)
32 | return wrapped
33 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import os
4 | import sys
5 | try:
6 | from setuptools import setup
7 | except ImportError:
8 | from distutils.core import setup
9 |
10 | def read(fname):
11 | return open(os.path.join(os.path.dirname(__file__), fname)).read()
12 |
13 | setup(
14 | name="rst2ansi",
15 | version="0.1.5",
16 | author="Snaipe",
17 | author_email="franklinmathieu@gmail.com",
18 | description="A rst converter to ansi-decorated console output",
19 | long_description=read('README.rst'),
20 | license="MIT",
21 | keywords="rst restructuredtext ansi console code converter",
22 | url="https://github.com/Snaipe/python-rst-to-ansi",
23 | packages=['rst2ansi'],
24 | requires=['docutils'],
25 | scripts=['bin/rst2ansi'],
26 | data_files=[],
27 | classifiers=[
28 | "Development Status :: 4 - Beta",
29 | "Environment :: Console",
30 | "Intended Audience :: Developers",
31 | "Intended Audience :: End Users/Desktop",
32 | "License :: OSI Approved :: MIT License",
33 | "Operating System :: OS Independent",
34 | "Programming Language :: Python :: 2.7",
35 | "Programming Language :: Python :: 3",
36 | "Programming Language :: Python :: 3.3",
37 | "Programming Language :: Python :: 3.4",
38 | "Programming Language :: Python :: 3.5",
39 | "Topic :: Software Development :: Libraries :: Python Modules",
40 | "Topic :: Text Processing :: Markup",
41 | "Topic :: Utilities",
42 | ],
43 | )
44 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | rst2ansi
2 | ========
3 |
4 | |build| |downloads| |pyversions| |format|
5 |
6 | A python module dedicated to rendering RST (reStructuredText) documents
7 | to ansi-escaped strings suitable for display in a terminal.
8 |
9 | |asciicast|
10 |
11 | Installation
12 | ------------
13 |
14 | Requirements
15 | ~~~~~~~~~~~~
16 |
17 | Python 3.3+
18 |
19 | PyPi package
20 | ~~~~~~~~~~~~
21 |
22 | .. code:: bash
23 |
24 | pip install rst2ansi
25 |
26 | Usage
27 | -----
28 |
29 | As a CLI utility:
30 | ~~~~~~~~~~~~~~~~~
31 |
32 | .. code:: bash
33 |
34 | usage: rst2ansi [-h] [file]
35 |
36 | Prints a reStructuredText input in an ansi-decorated format suitable for
37 | console output.
38 |
39 | positional arguments:
40 | file A path to the file to open
41 |
42 | optional arguments:
43 | -h, --help show this help message and exit
44 |
45 | As a python module:
46 | ~~~~~~~~~~~~~~~~~~~
47 |
48 | .. code:: python
49 |
50 | from rst2ansi import rst2ansi
51 |
52 | print(rst2ansi('I **love** reStructuredText!'))
53 |
54 | .. |build| image:: https://api.travis-ci.org/Snaipe/python-rst2ansi.svg
55 | :target: https://travis-ci.org/Snaipe/python-rst2ansi
56 |
57 | .. |downloads| image:: https://img.shields.io/pypi/dm/rst2ansi.svg
58 | :target: https://pypi.python.org/pypi/rst2ansi/
59 |
60 | .. |pyversions| image:: https://img.shields.io/pypi/pyversions/rst2ansi.svg
61 |
62 | .. |format| image:: https://img.shields.io/pypi/format/rst2ansi.svg
63 |
64 | .. |asciicast| image:: https://asciinema.org/a/drykz69gtn557z3hxnbb1jybq.png
65 | :target: https://asciinema.org/a/drykz69gtn557z3hxnbb1jybq
66 |
--------------------------------------------------------------------------------
/rst2ansi/visitor.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | The MIT License (MIT)
4 |
5 | Copyright © 2015-2016 Franklin "Snaipe" Mathieu
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 | """
25 |
26 | from docutils import core, frontend, nodes, utils, writers, languages, io
27 | from docutils.utils.error_reporting import SafeString
28 | from docutils.transforms import writer_aux
29 | from docutils.parsers.rst import roles
30 |
31 | from .ansi import ANSITranslator
32 |
33 | class Writer(writers.Writer):
34 |
35 | def __init__(self, **options):
36 | writers.Writer.__init__(self)
37 | self.translator_class = ANSITranslator
38 | self.options = options
39 |
40 | def translate(self):
41 | visitor = self.translator_class(self.document, **self.options)
42 | self.document.walkabout(visitor)
43 | self.output = visitor.output
44 |
45 | def get_transforms(self):
46 | return writers.Writer.get_transforms(self) + [writer_aux.Admonitions]
47 |
48 |
--------------------------------------------------------------------------------
/rst2ansi/unicode.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | The MIT License (MIT)
4 |
5 | Copyright © 2015-2016 Franklin "Snaipe" Mathieu
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 | """
25 |
26 | from __future__ import unicode_literals
27 |
28 | import sys
29 |
30 | def num_to_superscript(n):
31 | sups = {
32 | '0': '\u2070',
33 | '1': '\xb9',
34 | '2': '\xb2',
35 | '3': '\xb3',
36 | '4': '\u2074',
37 | '5': '\u2075',
38 | '6': '\u2076',
39 | '7': '\u2077',
40 | '8': '\u2078',
41 | '9': '\u2079'
42 | }
43 | return ''.join(sups.get(c, c) for c in str(n))
44 |
45 | def ref_to_unicode(n):
46 | return '⁽' + num_to_superscript(n) + '⁾'
47 |
48 | def u(s):
49 | # Useful for very coarse version differentiation.
50 | PY2 = sys.version_info[0] == 2
51 | PY3 = sys.version_info[0] == 3
52 | if PY3:
53 | return s
54 | else:
55 | # Workaround for standalone backslash
56 | try:
57 | ret_s = unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
58 | except TypeError:
59 | ret_s = s.replace(r'\\', r'\\\\')
60 | return ret_s
61 |
--------------------------------------------------------------------------------
/rst2ansi/wrap.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | The MIT License (MIT)
4 |
5 | Copyright © 2015-2016 Franklin "Snaipe" Mathieu
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 | """
25 |
26 | import re
27 |
28 | _ANSI_CODE = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]')
29 |
30 | def word_size(word):
31 | return len(_ANSI_CODE.sub('', word))
32 |
33 | def wrap(text, width=80, subsequent_indent=''):
34 | words = text.split()
35 | line_size = 0
36 | lines = [[]]
37 |
38 | for w in words:
39 | size = word_size(w) + 1
40 | if size == 0:
41 | continue
42 | if line_size + size - 1 > width and line_size > width / 2:
43 | line_size = len(subsequent_indent)
44 | lines.append([])
45 | while line_size + size - 1 > width:
46 | stripped = width - line_size - 1
47 | lines[-1].append(w[:stripped] + '-')
48 | line_size = len(subsequent_indent)
49 | lines.append([])
50 | w = w[stripped:]
51 | size -= stripped
52 | if size == 0:
53 | continue
54 | lines[-1].append(w)
55 | line_size += size
56 | return [subsequent_indent + ' '.join(words) for words in lines]
57 |
58 |
--------------------------------------------------------------------------------
/rst2ansi/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | The MIT License (MIT)
4 |
5 | Copyright © 2015-2016 Franklin "Snaipe" Mathieu
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 | """
25 |
26 | from __future__ import unicode_literals
27 |
28 | from docutils import nodes, core
29 | from docutils.parsers.rst import roles
30 |
31 | from .visitor import Writer
32 | from .ansi import COLORS, STYLES
33 |
34 | def rst2ansi(input_string, output_encoding='utf-8'):
35 |
36 | overrides = {}
37 | overrides['input_encoding'] = 'unicode'
38 |
39 | def style_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
40 | return [nodes.TextElement(rawtext, text, classes=[name])], []
41 |
42 | for color in COLORS:
43 | roles.register_local_role('ansi-fg-' + color, style_role)
44 | roles.register_local_role('ansi-bg-' + color, style_role)
45 | for style in STYLES:
46 | roles.register_local_role('ansi-' + style, style_role)
47 |
48 | if hasattr(input_string, 'decode'):
49 | input_string = input_string.decode('utf-8')
50 |
51 | out = core.publish_string(input_string, settings_overrides=overrides, writer=Writer(unicode=output_encoding.startswith('utf')))
52 | return out.decode(output_encoding)
53 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | This document describes the TODO list for supporing the full [reStructuredText specification][rstspec].
2 |
3 | * [x] Document Structure
4 | * [x] Document
5 | * [x] Sections
6 | * [x] Transitions
7 | * [x] Body Elements
8 | * [x] Paragraphs
9 | * [x] Bullet Lists
10 | * [x] Enumerated Lists
11 | * [x] Definition Lists
12 | * [ ] Field Lists
13 | * [x] Option Lists
14 | * [x] Literal Blocks
15 | * [x] Line Blocks
16 | * [ ] Block Quotes
17 | * [x] Block Quote
18 | * [ ] Attribution
19 | * [ ] Doctest Blocks
20 | * [x] Tables
21 | * [ ] Explicit Markup Blocks
22 | * [ ] Footnotes
23 | * [ ] Citations
24 | * [x] Hyperlink Targets
25 | * [ ] Directives
26 | * [ ] Admonitions
27 | * [x] Images
28 | * [x] Image
29 | * [x] Figure
30 | * [ ] Body Elements
31 | * [ ] Topic
32 | * [ ] Sidebar
33 | * [x] Line Block
34 | * [x] Parsed Literal Block
35 | * [ ] Code
36 | * [ ] Math
37 | * [ ] Rubric
38 | * [ ] Epigraph
39 | * [ ] Highlights
40 | * [ ] Pull-Quote
41 | * [ ] Compound Paragraph
42 | * [ ] Container
43 | * [ ] Tables
44 | * [ ] Table
45 | * [ ] CSV Table
46 | * [ ] List Table
47 | * [ ] Document Parts
48 | * [ ] Table of Contents
49 | * [ ] Automatic Section Numbering
50 | * [ ] Document Header & Footer
51 | * [ ] References
52 | * [ ] Target Footnotes
53 | * [ ] Footnotes
54 | * [ ] Citations
55 | * [ ] Directives for Substitution Definitions
56 | * [ ] Replacement Text
57 | * [ ] Unicode Character Codes
58 | * [ ] Date
59 | * [ ] Miscellaneous
60 | * [x] Including an External Document Fragment
61 | * [x] Raw Data Pass-Through
62 | * [x] Class
63 | * [x] Custom Interpreted Text Roles
64 | * [x] Setting the Default Interpreted Text Role
65 | * [ ] Metadata Document Title
66 | * [x] Substitution Definitions
67 | * [x] Comments
68 | * [ ] Implicit Hyperlink Targets
69 | * [ ] Inline Markup
70 | * [x] Emphasis
71 | * [x] Strong Emphasis
72 | * [x] Interpreted Text
73 | * [x] Inline Literals
74 | * [x] Hyperlink References
75 | * [x] Inline Internal Targets
76 | * [ ] Footnote References
77 | * [ ] Citation References
78 | * [x] Standalone Hyperlinks
79 | * [ ] Error messages
80 |
81 | [rstspec]: http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html
82 |
--------------------------------------------------------------------------------
/test/styles.t:
--------------------------------------------------------------------------------
1 | Test foreground colors:
2 |
3 | $ echo ':ansi-fg-black:`black`' > styles.rst
4 | $ echo ':ansi-fg-red:`red`' >> styles.rst
5 | $ echo ':ansi-fg-green:`green`' >> styles.rst
6 | $ echo ':ansi-fg-yellow:`yellow`' >> styles.rst
7 | $ echo ':ansi-fg-blue:`blue`' >> styles.rst
8 | $ echo ':ansi-fg-magenta:`magenta`' >> styles.rst
9 | $ echo ':ansi-fg-cyan:`cyan`' >> styles.rst
10 | $ echo ':ansi-fg-white:`white`' >> styles.rst
11 | $ rst2ansi styles.rst
12 | \x1b[30mblack\x1b[0m \x1b[31mred\x1b[0m \x1b[32mgreen\x1b[0m \x1b[33myellow\x1b[0m \x1b[34mblue\x1b[0m \x1b[35mmagenta\x1b[0m \x1b[36mcyan\x1b[0m \x1b[37mwhite\x1b[0m (esc)
13 |
14 | Test background colors:
15 |
16 | $ echo ':ansi-bg-black:`black`' > styles.rst
17 | $ echo ':ansi-bg-red:`red`' >> styles.rst
18 | $ echo ':ansi-bg-green:`green`' >> styles.rst
19 | $ echo ':ansi-bg-yellow:`yellow`' >> styles.rst
20 | $ echo ':ansi-bg-blue:`blue`' >> styles.rst
21 | $ echo ':ansi-bg-magenta:`magenta`' >> styles.rst
22 | $ echo ':ansi-bg-cyan:`cyan`' >> styles.rst
23 | $ echo ':ansi-bg-white:`white`' >> styles.rst
24 | $ rst2ansi styles.rst
25 | \x1b[40mblack\x1b[0m \x1b[41mred\x1b[0m \x1b[42mgreen\x1b[0m \x1b[43myellow\x1b[0m \x1b[44mblue\x1b[0m \x1b[45mmagenta\x1b[0m \x1b[46mcyan\x1b[0m \x1b[47mwhite\x1b[0m (esc)
26 |
27 | Test styles:
28 |
29 | $ echo ':ansi-bold:`bold`' > styles.rst
30 | $ echo ':ansi-dim:`dim`' >> styles.rst
31 | $ echo ':ansi-italic:`italic`' >> styles.rst
32 | $ echo ':ansi-underline:`underline`' >> styles.rst
33 | $ echo ':ansi-blink:`blink`' >> styles.rst
34 | $ echo ':ansi-blink-fast:`blink-fast`' >> styles.rst
35 | $ echo ':ansi-inverse:`inverse`' >> styles.rst
36 | $ echo ':ansi-conceal:`conceal`' >> styles.rst
37 | $ echo ':ansi-strikethrough:`strikethrough`' >> styles.rst
38 | $ rst2ansi styles.rst
39 | \x1b[1mbold\x1b[0m \x1b[2mdim\x1b[0m \x1b[3mitalic\x1b[0m \x1b[4munderline\x1b[0m \x1b[5mblink\x1b[0m \x1b[6mblink-fast\x1b[0m \x1b[7minverse\x1b[0m \x1b[8mconceal\x1b[0m \x1b[9mstrikethrough\x1b[0m (esc)
40 |
41 | Test standard reStructuredText text decorations:
42 |
43 | $ echo '*emphasis*' > styles.rst
44 | $ echo '**strong emphasis**' >> styles.rst
45 | $ rst2ansi styles.rst
46 | \x1b[3memphasis\x1b[0m \x1b[1mstrong emphasis\x1b[0m (esc)
47 |
48 | Test role coalescing:
49 |
50 | $ echo '
51 | > .. role:: blue-and-bold
52 | > :class: ansi-bold ansi-fg-blue
53 | >
54 | > :blue-and-bold:`test`
55 | > ' > styles.rst
56 | $ rst2ansi styles.rst
57 | \x1b[1;34mtest\x1b[0m (esc)
58 |
--------------------------------------------------------------------------------
/test/paragraph.t:
--------------------------------------------------------------------------------
1 | Test simple paragraph:
2 |
3 | $ echo "Lorem ipsum dolor sit amet" > paragraph.rst
4 | $ rst2ansi paragraph.rst
5 | Lorem ipsum dolor sit amet
6 |
7 | Test multi-line paragraph:
8 |
9 | $ echo "Lorem ipsum dolor sit amet,
10 | > consectetur adipiscing elit." > paragraph.rst
11 | $ rst2ansi paragraph.rst
12 | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
13 |
14 | Test multiple paragraphs:
15 |
16 | $ echo "Lorem ipsum dolor sit amet, consectetur adipiscing elit.
17 | >
18 | > Donec a diam lectus." > paragraph.rst
19 | $ rst2ansi paragraph.rst
20 | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
21 |
22 | Donec a diam lectus.
23 |
24 | Test paragraph wrapping:
25 |
26 | $ echo "
27 | > Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam
28 | > lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra
29 | > nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam
30 | > eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim,
31 | > ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula
32 | > ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing
33 | > elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed,
34 | > adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis.
35 | > Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl
36 | > imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio
37 | > eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum
38 | > sociis natoque penatibus et magnis dis parturient montes, nascetur
39 | > ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem
40 | > facilisis semper ac in est.
41 | > " | tr -d '\n' > long_paragraph.rst
42 | $ rst2ansi long_paragraph.rst
43 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus.
44 | Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec
45 | consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero
46 | egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem
47 | lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor.
48 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida
49 | lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque
50 | auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit
51 | pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices
52 | accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada
53 | arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes,
54 | nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem
55 | facilisis semper ac in est.
56 |
--------------------------------------------------------------------------------
/test/lists.t:
--------------------------------------------------------------------------------
1 | Docutils bullet list:
2 | $ echo "
3 | > Docutils Bullet List
4 | >
5 | > - This is item 1
6 | > - This is item 2
7 | >
8 | > - Bullets are '-', '*' or '+'.
9 | > Continuing text must be aligned
10 | > after the bullet and whitespace.
11 | >
12 | > Note that a blank line is required
13 | > before the first item and after the
14 | > last, but is optional between items.
15 | > " > paragraph.rst
16 | $ rst2ansi paragraph.rst
17 | Docutils Bullet List
18 |
19 | \u2022 This is item 1
20 | \u2022 This is item 2
21 | \u2022 Bullets are '-', '*' or '+'. Continuing text must be aligned after the
22 | bullet and whitespace.
23 |
24 | Note that a blank line is required before the first item and after the last, but
25 | is optional between items.
26 |
27 | Docutils enumerated lists:
28 | $ echo "
29 | > Docutils Enumerated List
30 | >
31 | > 3. This is the first item
32 | > 4. This is the second item
33 | > 5. Enumerators are arabic numbers,
34 | > single letters, or roman numerals
35 | > 6. List items should be sequentially
36 | > numbered, but need not start at 1
37 | > (although not all formatters will
38 | > honour the first index).
39 | > #. This item is auto-enumerated
40 | > " > paragraph.rst
41 | $ rst2ansi paragraph.rst
42 | Docutils Enumerated List
43 |
44 | 3. This is the first item
45 | 4. This is the second item
46 | 5. Enumerators are arabic numbers, single letters, or roman numerals
47 | 6. List items should be sequentially numbered, but need not start at 1
48 | (although not all formatters will honour the first index).
49 | 7. This item is auto-enumerated
50 |
51 | Test bullet list:
52 | $ echo "
53 | > Simple bullet list
54 | >
55 | > * list 1
56 | > * list 2 with multiple
57 | > lines
58 | > * list 3
59 | > " > paragraph.rst
60 | $ rst2ansi paragraph.rst
61 | Simple bullet list
62 |
63 | \u2022 list 1
64 | \u2022 list 2 with multiple lines
65 | \u2022 list 3
66 |
67 | Test definition list:
68 | $ echo "
69 | > Definition list
70 | >
71 | > Dinner
72 | > An evening meal.
73 | >
74 | > Lunch
75 | > A meal
76 | > typically
77 | > taken
78 | > mid day
79 | >
80 | > Breakfast
81 | > Morning meal that 'breaks' the overnight 'fast'.
82 | > " > paragraph.rst
83 | $ rst2ansi paragraph.rst
84 | Definition list
85 |
86 | Dinner
87 | An evening meal.
88 |
89 | Lunch
90 | A meal typically taken mid day
91 |
92 | Breakfast
93 | Morning meal that 'breaks' the overnight 'fast'.
94 |
95 | Option list:
96 | $ echo "
97 | > Option List
98 | >
99 | > -a command-line option 'a'
100 | > -b file options can have arguments
101 | > and long descriptions
102 | > --long options can be long also
103 | > --input file long options can also have
104 | > arguments
105 | > TODO: This should work with --input=file also
106 | > /V DOS/VMS-style options too
107 | > --text This is a long text that should span the line so that I can
108 | > see if there is the correct word wrap. If there
109 | > isn't it could be problem, but maybe not.
110 | > " > paragraph.rst
111 | $ rst2ansi paragraph.rst
112 | Option List
113 |
114 | -a
115 | command-line option 'a'
116 | -b file
117 | options can have arguments and long descriptions
118 | --long
119 | options can be long also
120 | --input file
121 | long options can also have arguments TODO: This should work with
122 | --input=file also
123 | /V
124 | DOS/VMS-style options too
125 | --text
126 | This is a long text that should span the line so that I can see if there is
127 | the correct word wrap. If there isn't it could be problem, but maybe
128 | not.
129 |
130 | Check Sub List:
131 | $ echo "
132 | > #. numbered
133 | > #. list
134 | >
135 | > #. and a
136 | > #. sublist
137 | >
138 | > #. end
139 | >
140 | > * unordered
141 | > * list
142 | > " > paragraph.rst
143 | $ rst2ansi paragraph.rst
144 | 1. numbered
145 | 2. list
146 | 1. and a
147 | 2. sublist
148 | 3. end
149 |
150 | \u2022 unordered
151 | \u2022 list
152 |
--------------------------------------------------------------------------------
/rst2ansi/get_terminal_size.py:
--------------------------------------------------------------------------------
1 | """This is a backport of shutil.get_terminal_size from Python 3.3.
2 |
3 | The original implementation is in C, but here we use the ctypes and
4 | fcntl modules to create a pure Python version of os.get_terminal_size.
5 |
6 | Pulled from https://github.com/chrippa/backports.shutil_get_terminal_size
7 |
8 |
9 | The MIT License (MIT)
10 |
11 | Copyright (c) 2014 Christopher Rosell
12 |
13 | Permission is hereby granted, free of charge, to any person obtaining a copy
14 | of this software and associated documentation files (the "Software"), to deal
15 | in the Software without restriction, including without limitation the rights
16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | copies of the Software, and to permit persons to whom the Software is
18 | furnished to do so, subject to the following conditions:
19 |
20 | The above copyright notice and this permission notice shall be included in
21 | all copies or substantial portions of the Software.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | THE SOFTWARE.
30 | """
31 |
32 | import os
33 | import struct
34 | import sys
35 |
36 | from collections import namedtuple
37 |
38 | __all__ = ["get_terminal_size"]
39 |
40 |
41 | terminal_size = namedtuple("terminal_size", "columns lines")
42 |
43 | try:
44 | from ctypes import windll, create_string_buffer, WinError
45 |
46 | _handle_ids = {
47 | 0: -10,
48 | 1: -11,
49 | 2: -12,
50 | }
51 |
52 | def _get_terminal_size(fd):
53 | handle = windll.kernel32.GetStdHandle(_handle_ids[fd])
54 | if handle == 0:
55 | raise OSError('handle cannot be retrieved')
56 | if handle == -1:
57 | raise WinError()
58 | csbi = create_string_buffer(22)
59 | res = windll.kernel32.GetConsoleScreenBufferInfo(handle, csbi)
60 | if res:
61 | res = struct.unpack("hhhhHhhhhhh", csbi.raw)
62 | left, top, right, bottom = res[5:9]
63 | columns = right - left + 1
64 | lines = bottom - top + 1
65 | return terminal_size(columns, lines)
66 | else:
67 | raise WinError()
68 |
69 | except ImportError:
70 | import fcntl
71 | import termios
72 |
73 | def _get_terminal_size(fd):
74 | try:
75 | res = fcntl.ioctl(fd, termios.TIOCGWINSZ, b"\x00" * 4)
76 | except IOError as e:
77 | raise OSError(e)
78 | lines, columns = struct.unpack("hh", res)
79 |
80 | return terminal_size(columns, lines)
81 |
82 |
83 | def get_terminal_size(fallback=(80, 24)):
84 | """Get the size of the terminal window.
85 |
86 | For each of the two dimensions, the environment variable, COLUMNS
87 | and LINES respectively, is checked. If the variable is defined and
88 | the value is a positive integer, it is used.
89 |
90 | When COLUMNS or LINES is not defined, which is the common case,
91 | the terminal connected to sys.__stdout__ is queried
92 | by invoking os.get_terminal_size.
93 |
94 | If the terminal size cannot be successfully queried, either because
95 | the system doesn't support querying, or because we are not
96 | connected to a terminal, the value given in fallback parameter
97 | is used. Fallback defaults to (80, 24) which is the default
98 | size used by many terminal emulators.
99 |
100 | The value returned is a named tuple of type os.terminal_size.
101 | """
102 | # Try the environment first
103 | try:
104 | columns = int(os.environ["COLUMNS"])
105 | except (KeyError, ValueError):
106 | columns = 0
107 |
108 | try:
109 | lines = int(os.environ["LINES"])
110 | except (KeyError, ValueError):
111 | lines = 0
112 |
113 | # Only query if necessary
114 | if columns <= 0 or lines <= 0:
115 | try:
116 | size = _get_terminal_size(sys.__stdout__.fileno())
117 | except (NameError, OSError):
118 | size = terminal_size(*fallback)
119 |
120 | if columns <= 0:
121 | columns = size.columns
122 | if lines <= 0:
123 | lines = size.lines
124 |
125 | return terminal_size(columns, lines)
126 |
127 |
--------------------------------------------------------------------------------
/rst2ansi/table.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | The MIT License (MIT)
4 |
5 | Copyright © 2015-2016 Franklin "Snaipe" Mathieu
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 | """
25 |
26 | from __future__ import unicode_literals
27 |
28 | from docutils import nodes
29 |
30 | from textwrap import wrap
31 |
32 | from .unicode import u
33 |
34 | class CellDimCalculator(nodes.NodeVisitor):
35 |
36 | def __init__(self, document, cols, rows, width):
37 | nodes.NodeVisitor.__init__(self, document)
38 | self.cols = cols
39 | self.rows = rows
40 | self.width = width
41 | self.height = 0
42 |
43 | def visit_paragraph(self, node):
44 | first_line = node.astext().split('\n')[0]
45 |
46 | # handle weird table sizing from simple rst tables
47 | # disregard cells spanning multiple columns, as
48 | # these don't contribute to the cell width calculation
49 | if len(first_line) >= self.width:
50 | self.width = len(first_line) + 2
51 |
52 | sublines = wrap(node.astext(), width = self.width)
53 | self.height = int(len(sublines) / self.rows)
54 | raise nodes.StopTraversal
55 |
56 | def visit_table(self, node):
57 | c = TableSizeCalculator(self.document)
58 | node.walkabout(c)
59 | self.height = int(c.height / self.rows)
60 | raise nodes.StopTraversal
61 |
62 | def visit_literal_block(self, node):
63 | self.height = int(len(node.astext().split('\n')) / self.rows)
64 | raise nodes.StopTraversal
65 |
66 | visit_Text = visit_literal_block
67 |
68 | def __getattr__(self, name):
69 | if name.startswith('visit_') or name.startswith('depart_'):
70 | def noop(*args, **kwargs):
71 | pass
72 | return noop
73 | raise AttributeError(name)
74 |
75 |
76 | class TableSizeCalculator(nodes.NodeVisitor):
77 |
78 | def __init__(self, document):
79 | nodes.NodeVisitor.__init__(self, document)
80 | self.level = 0
81 | self.widths = []
82 | self.heights = []
83 | self.rows = 0
84 |
85 | def __getattr__(self, name):
86 | if name.startswith('visit_') or name.startswith('depart_'):
87 | def noop(*args, **kwargs):
88 | pass
89 | return noop
90 | raise AttributeError(name)
91 |
92 | def visit_table(self, node):
93 | if self.level > 0:
94 | raise nodes.SkipChildren
95 | self.level += 1
96 |
97 | def depart_table(self, node):
98 | self.width = sum(self.widths) + (len(self.widths) + 1)
99 | self.height = sum(self.heights) + (len(self.heights) + 1)
100 | self.level -= 1
101 |
102 | def visit_tgroup(self, node):
103 | self.cols = node.attributes['cols']
104 |
105 | def visit_colspec(self, node):
106 | self.widths.append(node.attributes['colwidth'])
107 |
108 | def visit_row(self, node):
109 | self.rows += 1
110 | self.heights.append(1)
111 | self.col = 0
112 |
113 | def visit_entry(self, node):
114 | cols = node.attributes.get('morecols', 0) + 1
115 | rows = node.attributes.get('morerows', 0) + 1
116 | width = sum(self.widths[self.col:self.col + cols]) + (cols - 1)
117 |
118 | c = CellDimCalculator(self.document, cols, rows, width)
119 | node.walkabout(c)
120 |
121 | # Correct invalid column sizing for simple rst tables
122 | if c.width > width and cols == 1:
123 | self.widths[self.col] = c.width
124 |
125 | self.heights[-1] = max(self.heights[-1], c.height)
126 | self.col += 1
127 | raise nodes.SkipChildren
128 |
129 | class TableDrawer(nodes.NodeVisitor):
130 |
131 | def __init__(self, props, document, **options):
132 | nodes.NodeVisitor.__init__(self, document)
133 | self.props = props
134 | self.level = 0
135 | self.lines = ['']
136 | self.line = 0
137 | self.cursor = 0
138 | self.col = 0
139 | self.row = 0
140 | self.nb_rows = 0
141 | self.options = options
142 |
143 | def unicode_intersection(char, next):
144 | switch = {
145 | ('─', '│'): '┬',
146 | ('┐', '│'): '┐',
147 | ('┘', '│'): '┤',
148 | ('┘', '─'): '┴',
149 | ('┴', '│'): '┼',
150 | ('│', '─'): '├',
151 | ('┤', '─'): '┼',
152 | (' ', '─'): '┘',
153 | ('└', '─'): '└',
154 |
155 | ('═', '│'): '╤',
156 | ('╕', '│'): '╕',
157 | ('╛', '│'): '╡',
158 | ('╛', '═'): '╧',
159 | ('╧', '│'): '╪',
160 | ('│', '═'): '╞',
161 | ('╡', '═'): '╪',
162 | (' ', '═'): '╛',
163 | ('╘', '═'): '╘',
164 | }
165 | return switch[(u(char), u(next))]
166 |
167 | if options.get('unicode', False):
168 | self.char_single_rule = '─'
169 | self.char_double_rule = '═'
170 | self.char_vertical_rule = '│'
171 | self.get_intersection = unicode_intersection
172 | self.top_left = '┌'
173 | self.top_right = '┐'
174 | self.bottom_left = '╘'
175 | else:
176 | self.char_single_rule = '-'
177 | self.char_double_rule = '='
178 | self.char_vertical_rule = '|'
179 | self.get_intersection = lambda *args: '+'
180 | self.top_left = self.bottom_left = self.top_right = '+'
181 |
182 | def __getattr__(self, name):
183 | if name.startswith('visit_') or name.startswith('depart_'):
184 | def noop(*args, **kwargs):
185 | pass
186 | return noop
187 | if name == 'curline':
188 | return self.lines[self.line]
189 | raise AttributeError(name)
190 |
191 | def _draw_rule(self):
192 | self.lines[self.line] += self.top_left + self.char_single_rule * (self.props.width - 2) + self.top_right
193 | self.lines.extend([self.char_vertical_rule + ' ' * (self.props.width - 1)] * (self.props.height - 2))
194 | self.lines.extend([self.bottom_left + ' ' * (self.props.width - 1)])
195 | self.line += 1
196 | self.cursor = 0
197 |
198 | def visit_table(self, node):
199 | if self.level > 0:
200 | raise nodes.SkipChildren
201 | self.level += 1
202 | self._draw_rule()
203 |
204 | def depart_table(self, node):
205 | self.level -= 1
206 |
207 | def visit_row(self, node):
208 | self.col = 0
209 | self.cursor = 0
210 |
211 | def depart_row(self, node):
212 | self.line += self.props.heights[self.row] + 1
213 | self.row += 1
214 | self.local_row += 1
215 |
216 | def visit_thead(self, node):
217 | self.nb_rows = len(node.children)
218 | self.local_row = 0
219 |
220 | visit_tbody = visit_thead
221 |
222 | def visit_entry(self, node):
223 | cols = node.attributes.get('morecols', 0) + 1
224 | rows = node.attributes.get('morerows', 0) + 1
225 |
226 | width = sum(self.props.widths[self.col:self.col + cols]) + (cols - 1)
227 | height = sum(self.props.heights[self.row:self.row + rows]) + (rows - 1)
228 |
229 | rule = self.char_double_rule if self.local_row + rows - 1 == self.nb_rows - 1 else self.char_single_rule
230 | sep = self.char_vertical_rule
231 |
232 | # Draw the horizontal rule
233 |
234 | line = self.lines[self.line + height]
235 | int1 = self.get_intersection(line[self.cursor], rule)
236 | int2 = self.get_intersection(line[self.cursor + width + 1], rule)
237 | line = line[:self.cursor] + int1 + (width * rule) + int2 + line[self.cursor + width + 2:]
238 | self.lines[self.line + height] = line
239 |
240 | # Draw the vertical rule
241 |
242 | for i in range(height):
243 | line = self.lines[self.line + i]
244 | line = line[:self.cursor + width + 1] + sep + line[self.cursor + width + 2:]
245 | self.lines[self.line + i] = line
246 |
247 | line = self.lines[self.line - 1]
248 | int3 = self.get_intersection(line[self.cursor + width + 1], sep)
249 | line = line[:self.cursor + width + 1] + int3 + line[self.cursor + width + 2:]
250 | self.lines[self.line - 1] = line
251 |
252 | self.col += cols
253 | self.cursor += width + 1
254 |
255 | # Do not recurse
256 | raise nodes.SkipChildren
257 |
258 | class TableWriter(nodes.NodeVisitor):
259 |
260 | def __init__(self, props, document, **options):
261 | nodes.NodeVisitor.__init__(self, document)
262 | self.props = props
263 | self.level = 0
264 | self.line = 0
265 | self.cursor = 0
266 | self.col = 0
267 | self.row = 0
268 | self.nb_rows = 0
269 | self.options = options
270 |
271 | def __getattr__(self, name):
272 | if name.startswith('visit_') or name.startswith('depart_'):
273 | def noop(*args, **kwargs):
274 | pass
275 | return noop
276 | raise AttributeError(name)
277 |
278 | def visit_table(self, node):
279 | drawer = TableDrawer(self.props, self.document, **self.options)
280 | node.walkabout(drawer)
281 | self.lines = drawer.lines
282 |
283 | def visit_row(self, node):
284 | self.col = 0
285 | self.cursor = 0
286 |
287 | def depart_row(self, node):
288 | self.line += self.props.heights[self.row] + 1
289 | self.row += 1
290 | self.local_row += 1
291 |
292 | def visit_thead(self, node):
293 | self.nb_rows = len(node.children)
294 | self.local_row = 0
295 |
296 | visit_tbody = visit_thead
297 |
298 | def visit_entry(self, node):
299 | cols = node.attributes.get('morecols', 0) + 1
300 | rows = node.attributes.get('morerows', 0) + 1
301 |
302 | width = sum(self.props.widths[self.col:self.col + cols]) + (cols - 1)
303 | height = sum(self.props.heights[self.row:self.row + rows]) + (rows - 1)
304 |
305 | from .ansi import ANSITranslator
306 |
307 | if node.children:
308 | v = ANSITranslator(self.document, termsize=(width - 2, height), **self.options)
309 | node.children[0].walkabout(v)
310 | v.strip_empty_lines()
311 | i = 1
312 | for l in v.lines:
313 | for sl in l.split('\n'):
314 | line = self.lines[self.line + i]
315 | line = line[:self.cursor + 2] + sl + line[self.cursor + 2 + len(sl):]
316 | self.lines[self.line + i] = line
317 | i += 1
318 |
319 | self.col += cols
320 | self.cursor += width + 1
321 |
322 | # Do not recurse
323 | raise nodes.SkipChildren
324 |
--------------------------------------------------------------------------------
/rst2ansi/ansi.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | The MIT License (MIT)
4 |
5 | Copyright © 2015-2016 Franklin "Snaipe" Mathieu
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 | """
25 |
26 | from __future__ import unicode_literals
27 |
28 | from docutils import core, frontend, nodes, utils, writers, languages, io
29 | from docutils.utils.error_reporting import SafeString
30 | from docutils.transforms import writer_aux
31 | from docutils.parsers.rst import roles
32 |
33 | from copy import deepcopy, copy
34 | from .wrap import wrap
35 |
36 | from .table import TableSizeCalculator, TableWriter
37 | from .unicode import ref_to_unicode, u
38 |
39 | from .get_terminal_size import get_terminal_size
40 |
41 | import shutil
42 |
43 | COLORS = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white')
44 | STYLES = ('bold', 'dim', 'italic', 'underline', 'blink', 'blink-fast', 'inverse', 'conceal', 'strikethrough')
45 |
46 | class ANSICodes(object):
47 |
48 | @staticmethod
49 | def get_color_code(code, fg):
50 | FG = 30
51 | BG = 40
52 | FG_256 = 38
53 | BG_256 = 48
54 |
55 | if code in COLORS:
56 | shift = FG if fg else BG
57 | return str(shift + COLORS.index(code))
58 | elif isinstance(code, int) and 0 <= code <= 255:
59 | shift = FG_256 if fg else BG_256
60 | return str(shift) + ';5;%d' % int(code)
61 | elif not isinstance(code, str) and hasattr(code, "__len__") and len(code) == 3:
62 | for c in code:
63 | if not 0 <= c <= 255:
64 | raise Exception('Invalid color "%s"' % code)
65 |
66 | r, g, b = code
67 | shift = FG_256 if fg else BG_256
68 | return str(shift) + ';2;%d;%d;%d' % (int(r), int(g), int(b))
69 |
70 | raise Exception('Invalid color "%s"' % code)
71 |
72 | @staticmethod
73 | def get_style_code(code):
74 | if code in STYLES:
75 | return str(1 + STYLES.index(code))
76 | raise Exception('Invalid style "%s"' % code)
77 |
78 | @staticmethod
79 | def to_ansi(codes):
80 | return '\x1b[' + ';'.join(codes) + 'm'
81 |
82 | NONE = '0'
83 | RESET = to_ansi.__func__(NONE)
84 |
85 | from .functional import npartial
86 |
87 | class ANSITranslator(nodes.NodeVisitor):
88 |
89 | class Context(object):
90 |
91 | def __init__(self):
92 | self.output = ''
93 | self.indent_level = 0
94 | self.in_list = False
95 | self.has_title = False
96 | self.list_counter = 0
97 | self.node_type = ''
98 |
99 | class StyleContext(object):
100 |
101 | def __init__(self):
102 | self.styles = set()
103 | self.fg = ANSICodes.NONE
104 | self.bg = ANSICodes.NONE
105 |
106 | def __init__(self, document, termsize=None, **options):
107 | nodes.NodeVisitor.__init__(self, document)
108 | self.document = document
109 | self.output = ''
110 | self.lines = ['']
111 | self.line = 0
112 | self.indent_width = 2
113 | self.termsize = termsize or get_terminal_size((80,20))
114 | self.options = options
115 | self.references = []
116 | self.refcount = 0
117 |
118 | self.ctx = self.Context()
119 | self.ctx_stack = []
120 | self.style = self.StyleContext()
121 | self.style_stack = []
122 |
123 | def push_ctx(self, **kwargs):
124 | self.ctx_stack.append(self.ctx)
125 | self.ctx = deepcopy(self.ctx)
126 | for k, v in kwargs.items():
127 | setattr(self.ctx, k, v)
128 |
129 | def pop_ctx(self):
130 | self.ctx = self.ctx_stack.pop()
131 |
132 | def push_style(self, fg=None, bg=None, styles=[]):
133 | self.style_stack.append(self.style)
134 | self.style = deepcopy(self.style)
135 | if fg:
136 | self.style.fg = ANSICodes.get_color_code(fg, True)
137 | if bg:
138 | self.style.bg = ANSICodes.get_color_code(bg, False)
139 | self.style.styles |= {ANSICodes.get_style_code(s) for s in styles}
140 |
141 | self._restyle()
142 |
143 | def pop_style(self):
144 | self.style = self.style_stack.pop()
145 | reset = self.style.fg == ANSICodes.NONE and \
146 | self.style.bg == ANSICodes.NONE and \
147 | not self.style.styles
148 | self._restyle(reset)
149 |
150 | def append(self, *args, **kwargs):
151 | try:
152 | strict = kwargs['strict']
153 | except KeyError:
154 | strict = False
155 | if len(self.lines[self.line]) == 0 and not strict:
156 | self.lines[self.line] += ' ' * self.ctx.indent_level * self.indent_width
157 |
158 | for a in args:
159 | self.lines[self.line] += u(a)
160 |
161 | def newline(self, n=1):
162 | self.lines.extend([''] * n)
163 | self.line += n
164 |
165 | def prevline(self, n=1):
166 | self.line -= n
167 |
168 | def nextline(self, n=1):
169 | self.line += n
170 |
171 | def popline(self):
172 | l = self.lines.pop(self.line)
173 | self.line -= 1
174 | return l
175 |
176 | def replaceline(self, newline, strict=True):
177 | if strict:
178 | self.lines[self.line] = newline
179 | else:
180 | self.lines[self.line] = ''
181 | self.append(newline)
182 |
183 | def addlines(self, lines, strict=False):
184 | if strict:
185 | self.lines.extend(lines)
186 | self.line += len(lines)
187 | self.newline()
188 | else:
189 | for l in lines:
190 | self.append(l)
191 | self.newline()
192 |
193 | def _restyle(self, reset=False):
194 | if reset:
195 | self.append(ANSICodes.RESET)
196 |
197 | styles = list(self.style.styles)
198 | if self.style.fg != ANSICodes.NONE:
199 | styles.append(self.style.fg)
200 | if self.style.bg != ANSICodes.NONE:
201 | styles.append(self.style.bg)
202 |
203 | if styles:
204 | self.append(ANSICodes.to_ansi(styles))
205 |
206 | def strip_empty_lines(self):
207 | remove_last_n = 0
208 | for x in self.lines[::-1]:
209 | if len(x.strip()) != 0:
210 | break
211 | remove_last_n += 1
212 | if remove_last_n != 0:
213 | self.lines = self.lines[:-remove_last_n]
214 |
215 | # Structural nodes
216 |
217 | def visit_document(self, node):
218 | self.push_ctx()
219 |
220 | def _print_references(self):
221 | if not self.references:
222 | return
223 |
224 | self.push_style(styles = ['bold'])
225 | self.append('References:')
226 | self.pop_style()
227 | self.newline(2)
228 |
229 | self.push_ctx(indent_level = self.ctx.indent_level + 1)
230 | for ref in self.references:
231 | self.append('[%s]: <' % ref[0])
232 | self.push_style(fg = 'cyan', styles = ['underline'])
233 | self.append(ref[1])
234 | self.pop_style()
235 | self.append('>')
236 | self.newline()
237 | self.references = []
238 | self.pop_ctx()
239 |
240 | def depart_document(self, node):
241 | self._print_references()
242 | self.depart_section(node)
243 |
244 | self.pop_ctx()
245 | self.strip_empty_lines()
246 |
247 | self.output = '\n'.join(self.lines)
248 |
249 | def wrap_current_line(self):
250 | indent = self.ctx.indent_level * self.indent_width
251 | sublines = wrap(self.curline, width = self.termsize[0] - indent,
252 | subsequent_indent = ' ' * indent)
253 | self.popline()
254 | self.addlines(sublines, strict=True)
255 |
256 | def depart_paragraph(self, node):
257 | if self.options.get('wrap_paragraphs', True):
258 | self.wrap_current_line()
259 | if not self.ctx.in_list:
260 | self.newline()
261 |
262 | def visit_title(self, node):
263 | self.push_style(styles=['bold'])
264 |
265 | def depart_title(self, node):
266 | self.pop_style()
267 | self.push_ctx(has_title = True, indent_level = self.ctx.indent_level + 1)
268 | self.newline(2)
269 |
270 | def visit_subtitle(self, node):
271 | self.prevline(2)
272 | self.append(' - ')
273 |
274 | def depart_subtitle(self, node):
275 | self.nextline(2)
276 |
277 | def visit_Text(self, node):
278 | self.append(node.astext())
279 |
280 | def depart_section(self, node):
281 | if self.ctx.has_title:
282 | self.pop_ctx()
283 |
284 | def depart_transition(self, node):
285 | indent = (self.ctx.indent_level + 2) * self.indent_width
286 | char = '╌' if self.options['unicode'] else '-'
287 | self.append(' ' * indent + char * (self.termsize[0] - 2 * indent) + ' ' * indent, strict=True)
288 | self.newline(2)
289 |
290 | def _get_uri(self, node):
291 | uri = node.attributes.get('refuri', '')
292 | if not uri:
293 | uri = node.attributes.get('uri', '')
294 | return uri
295 |
296 | def visit_reference(self, node):
297 | if self._get_uri(node) == node.astext().strip():
298 | self.append('<')
299 | self.push_style(fg = 'cyan', styles = ['underline'])
300 |
301 | def depart_reference(self, node):
302 | self.pop_style()
303 | if self._get_uri(node) == node.astext().strip():
304 | self.append('>')
305 | else:
306 | self.references.append((self.refcount, self._get_uri(node)))
307 | if self.options['unicode'] and self.options.get('unicode_superscript', False):
308 | self.append(ref_to_unicode(self.refcount))
309 | else:
310 | self.append(' [%s]' % self.refcount)
311 | self.refcount += 1
312 |
313 | # Style nodes
314 |
315 | visit_strong = npartial(push_style, styles=['bold'])
316 | depart_strong = npartial(pop_style)
317 |
318 | visit_emphasis = npartial(push_style, styles=['italic'])
319 | depart_emphasis = npartial(pop_style)
320 |
321 | def visit_TextElement(self, node):
322 | ansi_props = [x[5:] for x in node.attributes['classes'] if x.startswith('ansi-')]
323 | style = {
324 | 'fg': next((x[3:] for x in ansi_props if x.startswith('fg-') and x[3:] in COLORS), None),
325 | 'bg': next((x[3:] for x in ansi_props if x.startswith('bg-') and x[3:] in COLORS), None),
326 | 'styles': (x for x in ansi_props if x in STYLES)
327 | }
328 | self.push_style(**style)
329 |
330 | def depart_TextElement(self, node):
331 | self.pop_style()
332 |
333 | visit_inline = visit_TextElement
334 | depart_inline = depart_TextElement
335 |
336 | # Lists
337 |
338 | def visit_enumerated_list(self, node):
339 | strt = node.attributes.get('start', 1)
340 | self.push_ctx(in_list = True,
341 | list_counter = strt)
342 |
343 | def depart_enumerated_list(self, node):
344 | self.pop_ctx()
345 | if not self.ctx.in_list:
346 | self.newline()
347 |
348 | def visit_bullet_list(self, node):
349 | self.push_ctx(in_list = True,
350 | list_counter = 0)
351 |
352 | def depart_bullet_list(self, node):
353 | self.pop_ctx()
354 | if not self.ctx.in_list:
355 | self.newline()
356 |
357 | def visit_list_item(self, node):
358 | if self.ctx.list_counter:
359 | self.append(str(self.ctx.list_counter) + '. ')
360 | self.ctx.list_counter += 1
361 | else:
362 | self.append('• ' if self.options['unicode'] else '* ')
363 | self.push_ctx(indent_level = self.ctx.indent_level + 1)
364 |
365 | def depart_list_item(self, node):
366 | self.pop_ctx()
367 |
368 | visit_definition_list = npartial(push_ctx, in_list=True, list_counter=0)
369 | depart_definition_list = npartial(pop_ctx)
370 |
371 | def visit_definition(self, node):
372 | self.newline()
373 | self.push_ctx(indent_level = self.ctx.indent_level + 1)
374 |
375 | def depart_definition(self, node):
376 | self.newline()
377 | self.pop_ctx()
378 |
379 | visit_option_list = npartial(push_ctx, in_list=True, list_counter=0)
380 | depart_option_list = npartial(pop_ctx)
381 |
382 | def depart_option(self, node):
383 | self.append(' | ')
384 |
385 | def depart_option_group(self, node):
386 | self.replaceline(self.lines[self.line][:-3], strict=True)
387 | self.push_ctx(indent_level = self.ctx.indent_level + 2)
388 | self.newline()
389 |
390 | def visit_option_argument(self, node):
391 | self.append(' ')
392 |
393 | def depart_option_list_item(self, node):
394 | self.pop_ctx()
395 |
396 | # Tables
397 |
398 | def visit_table(self, node):
399 | props = TableSizeCalculator(self.document)
400 | node.walkabout(props)
401 |
402 | writer = TableWriter(props, self.document, **self.options)
403 | node.walkabout(writer)
404 | self.addlines(writer.lines)
405 |
406 | # Do not recurse
407 | raise nodes.SkipChildren
408 |
409 | def depart_table(self, node):
410 | self.newline()
411 |
412 | # Misc
413 |
414 | def depart_image(self, node):
415 | if type(node.parent) == nodes.figure:
416 | self.visit_reference(node)
417 | self.append('[' + node.attributes.get('alt', 'Image') + ']')
418 | self.depart_reference(node)
419 | self.newline()
420 | else:
421 | self.append('[' + node.attributes.get('alt', 'Image') + ']')
422 |
423 | def depart_caption(self, node):
424 | self.newline(2)
425 |
426 | def visit_substitution_definition(self, node):
427 | raise nodes.SkipChildren
428 |
429 | def visit_comment(self, node):
430 | raise nodes.SkipChildren
431 |
432 | def depart_admonition(self, node):
433 | if self.ctx.has_title:
434 | self.pop_ctx()
435 |
436 | def visit_block_quote(self, node):
437 | self.push_ctx(indent_level = self.ctx.indent_level + 1)
438 |
439 | def depart_block_quote(self, node):
440 | self.pop_ctx()
441 |
442 | def depart_literal_block(self, node):
443 | sublines = self.curline.split('\n')
444 | self.replaceline(sublines[0])
445 | self.newline()
446 | self.addlines(sublines[1:])
447 | self.newline()
448 |
449 | def depart_line(self, node):
450 | if len(self.curline.strip()) == 0:
451 | self.newline()
452 | else:
453 | self.wrap_current_line()
454 |
455 | def visit_line_block(self, node):
456 | indent = self.ctx.indent_level + (1 if self.ctx.node_type == 'line_block' else 0)
457 | self.push_ctx(indent_level = indent, node_type = 'line_block')
458 |
459 | def depart_line_block(self, node):
460 | self.pop_ctx()
461 | if self.ctx.node_type != 'line_block':
462 | self.newline()
463 |
464 | def __getattr__(self, name):
465 | if name.startswith('visit_') or name.startswith('depart_'):
466 | def noop(*args, **kwargs):
467 | pass
468 | return noop
469 | if name == 'curline':
470 | return self.lines[self.line]
471 | raise AttributeError(name)
472 |
473 |
--------------------------------------------------------------------------------
/demo/demo.tsq:
--------------------------------------------------------------------------------
1 | . ESC
2 | @ 0.200000
3 | |ggdGi|
4 | @ 0.100000
5 | |H|
6 | @ 0.100000
7 | |e|
8 | @ 0.100000
9 | |l|
10 | @ 0.100000
11 | |l|
12 | @ 0.100000
13 | |o|
14 | @ 0.100000
15 | |,|
16 | @ 0.100000
17 | | |
18 | @ 0.100000
19 | |w|
20 | @ 0.100000
21 | |o|
22 | @ 0.100000
23 | |r|
24 | @ 0.100000
25 | |l|
26 | @ 0.100000
27 | |d|
28 | @ 0.100000
29 | |!|
30 | @ 0.000815
31 | . LF/^J
32 | @ 0.000815
33 | . ESC
34 | @ 0.000815
35 | |:w|
36 | @ 0.000815
37 | . LF/^J
38 |
39 | @ 1.000000
40 | |13i=|
41 | @ 0.000815
42 | . ESC
43 | @ 0.200000
44 | |o|
45 | @ 0.100000
46 | |N|
47 | @ 0.100000
48 | |i|
49 | @ 0.100000
50 | |c|
51 | @ 0.100000
52 | |e|
53 | @ 0.100000
54 | | |
55 | @ 0.100000
56 | |d|
57 | @ 0.100000
58 | |a|
59 | @ 0.100000
60 | |y|
61 | @ 0.100000
62 | | |
63 | @ 0.100000
64 | |t|
65 | @ 0.100000
66 | |o|
67 | @ 0.100000
68 | |d|
69 | @ 0.100000
70 | |a|
71 | @ 0.100000
72 | |y|
73 | @ 0.100000
74 | |.|
75 | @ 0.000815
76 | . LF/^J
77 | @ 0.000100
78 | . ESC
79 |
80 | @ 0.200000
81 | |15i~|
82 | @ 0.000815
83 | . ESC
84 | @ 0.200000
85 | |:w|
86 | @ 0.000815
87 | . LF/^J
88 |
89 | @ 0.200000
90 | |o|
91 | @ 0.100815
92 | . LF/^J
93 | @ 0.100000
94 | |I|
95 | @ 0.100000
96 | | |
97 | @ 0.100000
98 | |*|
99 | @ 0.100000
100 | |l|
101 | @ 0.100000
102 | |o|
103 | @ 0.100000
104 | |v|
105 | @ 0.100000
106 | |e|
107 | @ 0.100000
108 | |*|
109 | @ 0.100000
110 | | |
111 | @ 0.100000
112 | |r|
113 | @ 0.100000
114 | |e|
115 | @ 0.100000
116 | |S|
117 | @ 0.100000
118 | |t|
119 | @ 0.100000
120 | |r|
121 | @ 0.100000
122 | |u|
123 | @ 0.100000
124 | |c|
125 | @ 0.100000
126 | |t|
127 | @ 0.100000
128 | |u|
129 | @ 0.100000
130 | |r|
131 | @ 0.100000
132 | |e|
133 | @ 0.100000
134 | |d|
135 | @ 0.100000
136 | |T|
137 | @ 0.100000
138 | |e|
139 | @ 0.100000
140 | |x|
141 | @ 0.100000
142 | |t|
143 | @ 0.100000
144 | |!|
145 | @ 0.000815
146 | . LF/^J
147 | @ 0.000100
148 | . ESC
149 |
150 | @ 0.200000
151 | |:w|
152 | @ 0.000815
153 | . LF/^J
154 |
155 | @ 0.200000
156 | |o|
157 | @ 0.100000
158 | |B|
159 | @ 0.100000
160 | |u|
161 | @ 0.100000
162 | |t|
163 | @ 0.100000
164 | | |
165 | @ 0.100000
166 | |I|
167 | @ 0.100000
168 | | |
169 | @ 0.100000
170 | |a|
171 | @ 0.100000
172 | |l|
173 | @ 0.100000
174 | |s|
175 | @ 0.100000
176 | |o|
177 | @ 0.100000
178 | | |
179 | @ 0.100000
180 | |l|
181 | @ 0.100000
182 | |o|
183 | @ 0.100000
184 | |v|
185 | @ 0.100000
186 | |e|
187 | @ 0.100000
188 | | |
189 | @ 0.100000
190 | |m|
191 | @ 0.100000
192 | |y|
193 | @ 0.100000
194 | | |
195 | @ 0.100000
196 | |t|
197 | @ 0.100000
198 | |e|
199 | @ 0.100000
200 | |r|
201 | @ 0.100000
202 | |m|
203 | @ 0.100000
204 | |i|
205 | @ 0.100000
206 | |n|
207 | @ 0.100000
208 | |a|
209 | @ 0.100000
210 | |l|
211 | @ 0.100000
212 | |.|
213 | @ 0.000815
214 | . LF/^J
215 | @ 0.000100
216 | . ESC
217 |
218 | @ 0.200000
219 | |:w|
220 | @ 0.000815
221 | . LF/^J
222 |
223 | @ 0.200000
224 | |o|
225 | @ 0.100000
226 | |S|
227 | @ 0.100000
228 | |o|
229 | @ 0.100000
230 | | |
231 | @ 0.100000
232 | |I|
233 | @ 0.100000
234 | | |
235 | @ 0.100000
236 | |m|
237 | @ 0.100000
238 | |a|
239 | @ 0.100000
240 | |d|
241 | @ 0.100000
242 | |e|
243 | @ 0.100000
244 | | |
245 | @ 0.100000
246 | |*|
247 | @ 0.100000
248 | |*|
249 | @ 0.100000
250 | |r|
251 | @ 0.100000
252 | |s|
253 | @ 0.100000
254 | |t|
255 | @ 0.100000
256 | |2|
257 | @ 0.100000
258 | |a|
259 | @ 0.100000
260 | |n|
261 | @ 0.100000
262 | |s|
263 | @ 0.100000
264 | |i|
265 | @ 0.100000
266 | |*|
267 | @ 0.100000
268 | |*|
269 | @ 0.100000
270 | |,|
271 | @ 0.100000
272 | | |
273 | @ 0.100000
274 | |t|
275 | @ 0.100000
276 | |o|
277 | @ 0.100000
278 | | |
279 | @ 0.100000
280 | |r|
281 | @ 0.100000
282 | |e|
283 | @ 0.100000
284 | |n|
285 | @ 0.100000
286 | |d|
287 | @ 0.100000
288 | |e|
289 | @ 0.100000
290 | |r|
291 | @ 0.100000
292 | | |
293 | @ 0.100000
294 | |r|
295 | @ 0.100000
296 | |e|
297 | @ 0.100000
298 | |S|
299 | @ 0.100000
300 | |t|
301 | @ 0.100000
302 | |r|
303 | @ 0.100000
304 | |u|
305 | @ 0.100000
306 | |c|
307 | @ 0.100000
308 | |t|
309 | @ 0.100000
310 | |u|
311 | @ 0.100000
312 | |r|
313 | @ 0.100000
314 | |e|
315 | @ 0.100000
316 | |d|
317 | @ 0.100000
318 | |T|
319 | @ 0.100000
320 | |e|
321 | @ 0.100000
322 | |x|
323 | @ 0.100000
324 | |t|
325 | @ 0.100000
326 | | |
327 | @ 0.100000
328 | |a|
329 | @ 0.100000
330 | |s|
331 | @ 0.100000
332 | | |
333 | @ 0.100000
334 | |s|
335 | @ 0.100000
336 | |o|
337 | @ 0.100000
338 | |m|
339 | @ 0.100000
340 | |e|
341 | @ 0.100000
342 | | |
343 | @ 0.100000
344 | |A|
345 | @ 0.100000
346 | |N|
347 | @ 0.100000
348 | |S|
349 | @ 0.100000
350 | |I|
351 | @ 0.100000
352 | |-|
353 | @ 0.100000
354 | |d|
355 | @ 0.100000
356 | |e|
357 | @ 0.100000
358 | |c|
359 | @ 0.100000
360 | |o|
361 | @ 0.100000
362 | |r|
363 | @ 0.100000
364 | |a|
365 | @ 0.100000
366 | |t|
367 | @ 0.100000
368 | |e|
369 | @ 0.100000
370 | |d|
371 | @ 0.100000
372 | | |
373 | @ 0.100000
374 | |o|
375 | @ 0.100000
376 | |u|
377 | @ 0.100000
378 | |t|
379 | @ 0.100000
380 | |p|
381 | @ 0.100000
382 | |u|
383 | @ 0.100000
384 | |t|
385 | @ 0.100000
386 | |,|
387 | @ 0.100000
388 | | |
389 | @ 0.100000
390 | |s|
391 | @ 0.100000
392 | |u|
393 | @ 0.100000
394 | |i|
395 | @ 0.100000
396 | |t|
397 | @ 0.100000
398 | |a|
399 | @ 0.100000
400 | |b|
401 | @ 0.100000
402 | |l|
403 | @ 0.100000
404 | |e|
405 | @ 0.100000
406 | | |
407 | @ 0.100000
408 | |f|
409 | @ 0.100000
410 | |o|
411 | @ 0.100000
412 | |r|
413 | @ 0.100000
414 | | |
415 | @ 0.100000
416 | |t|
417 | @ 0.100000
418 | |e|
419 | @ 0.100000
420 | |r|
421 | @ 0.100000
422 | |m|
423 | @ 0.100000
424 | |i|
425 | @ 0.100000
426 | |n|
427 | @ 0.100000
428 | |a|
429 | @ 0.100000
430 | |l|
431 | @ 0.100000
432 | |s|
433 | @ 0.100000
434 | |.|
435 | @ 0.100000
436 | . LF/^J
437 | @ 0.100000
438 | . ESC
439 | @ 0.200000
440 | |:|
441 | @ 0.100000
442 | |w|
443 | @ 0.100000
444 | . LF/^J
445 |
446 | @ 0.100000
447 | |o|
448 | @ 0.100000
449 | |-|
450 | @ 0.100000
451 | |-|
452 | @ 0.100000
453 | |-|
454 | @ 0.100000
455 | |-|
456 | @ 0.100000
457 | |-|
458 | @ 0.100000
459 | |-|
460 | @ 0.100000
461 | |-|
462 | @ 0.100000
463 | |-|
464 | @ 0.100000
465 | |-|
466 | @ 0.100000
467 | |-|
468 | @ 0.100000
469 | . LF/^J
470 | @ 0.100000
471 | . LF/^J
472 | @ 0.100000
473 | |P|
474 | @ 0.100000
475 | |a|
476 | @ 0.100000
477 | |r|
478 | @ 0.100000
479 | |a|
480 | @ 0.100000
481 | |g|
482 | @ 0.100000
483 | |r|
484 | @ 0.100000
485 | |a|
486 | @ 0.100000
487 | |p|
488 | @ 0.100000
489 | |h|
490 | @ 0.100000
491 | |s|
492 | @ 0.100000
493 | | |
494 | @ 0.100000
495 | |a|
496 | @ 0.100000
497 | |r|
498 | @ 0.100000
499 | |e|
500 | @ 0.100000
501 | | |
502 | @ 0.100000
503 | |a|
504 | @ 0.100000
505 | |u|
506 | @ 0.100000
507 | |t|
508 | @ 0.100000
509 | |o|
510 | @ 0.100000
511 | |m|
512 | @ 0.100000
513 | |a|
514 | @ 0.100000
515 | |t|
516 | @ 0.100000
517 | |i|
518 | @ 0.100000
519 | |c|
520 | @ 0.100000
521 | |a|
522 | @ 0.100000
523 | |l|
524 | @ 0.100000
525 | |l|
526 | @ 0.100000
527 | |y|
528 | @ 0.100000
529 | | |
530 | @ 0.100000
531 | |w|
532 | @ 0.100000
533 | |r|
534 | @ 0.100000
535 | |a|
536 | @ 0.100000
537 | |p|
538 | @ 0.100000
539 | |p|
540 | @ 0.100000
541 | |e|
542 | @ 0.100000
543 | |d|
544 | @ 0.100000
545 | | |
546 | @ 0.100000
547 | |t|
548 | @ 0.100000
549 | |o|
550 | @ 0.100000
551 | | |
552 | @ 0.100000
553 | |f|
554 | @ 0.100000
555 | |i|
556 | @ 0.100000
557 | |t|
558 | @ 0.100000
559 | | |
560 | @ 0.100000
561 | |i|
562 | @ 0.100000
563 | |n|
564 | @ 0.100000
565 | | |
566 | @ 0.100000
567 | |t|
568 | @ 0.100000
569 | |h|
570 | @ 0.100000
571 | |e|
572 | @ 0.100000
573 | | |
574 | @ 0.100000
575 | |c|
576 | @ 0.100000
577 | |u|
578 | @ 0.100000
579 | |r|
580 | @ 0.100000
581 | |r|
582 | @ 0.100000
583 | |e|
584 | @ 0.100000
585 | |n|
586 | @ 0.100000
587 | |t|
588 | @ 0.100000
589 | | |
590 | @ 0.100000
591 | |t|
592 | @ 0.100000
593 | |e|
594 | @ 0.100000
595 | |r|
596 | @ 0.100000
597 | |m|
598 | @ 0.100000
599 | |i|
600 | @ 0.100000
601 | |n|
602 | @ 0.100000
603 | |a|
604 | @ 0.100000
605 | |l|
606 | @ 0.100000
607 | | |
608 | @ 0.100000
609 | |w|
610 | @ 0.100000
611 | |i|
612 | @ 0.100000
613 | |n|
614 | @ 0.100000
615 | |d|
616 | @ 0.100000
617 | |o|
618 | @ 0.100000
619 | |w|
620 | @ 0.100000
621 | |.|
622 | @ 0.100000
623 | . LF/^J
624 | @ 0.100000
625 | . ESC
626 | @ 0.200000
627 | |:|
628 | @ 0.100000
629 | |w|
630 | @ 0.100000
631 | . LF/^J
632 |
633 | @ 1.500000
634 | |d|
635 | @ 0.100000
636 | |9|
637 | @ 0.100000
638 | |k|
639 | @ 0.100000
640 | . ESC
641 | @ 0.200000
642 | |o|
643 | @ 0.100000
644 | |P|
645 | @ 0.100000
646 | |a|
647 | @ 0.100000
648 | |r|
649 | @ 0.100000
650 | |a|
651 | @ 0.100000
652 | |g|
653 | @ 0.100000
654 | |r|
655 | @ 0.100000
656 | |a|
657 | @ 0.100000
658 | |p|
659 | @ 0.100000
660 | |h|
661 | @ 0.100000
662 | |s|
663 | @ 0.100000
664 | | |
665 | @ 0.100000
666 | |a|
667 | @ 0.100000
668 | |r|
669 | @ 0.100000
670 | |e|
671 | @ 0.100000
672 | | |
673 | @ 0.100000
674 | |i|
675 | @ 0.100000
676 | |n|
677 | @ 0.100000
678 | |d|
679 | @ 0.100000
680 | |e|
681 | @ 0.100000
682 | |n|
683 | @ 0.100000
684 | |t|
685 | @ 0.100000
686 | |e|
687 | @ 0.100000
688 | |d|
689 | @ 0.100000
690 | | |
691 | @ 0.100000
692 | |t|
693 | @ 0.100000
694 | |o|
695 | @ 0.100000
696 | | |
697 | @ 0.100000
698 | |r|
699 | @ 0.100000
700 | |e|
701 | @ 0.100000
702 | |f|
703 | @ 0.100000
704 | |l|
705 | @ 0.100000
706 | |e|
707 | @ 0.100000
708 | |c|
709 | @ 0.100000
710 | |t|
711 | @ 0.100000
712 | | |
713 | @ 0.100000
714 | |t|
715 | @ 0.100000
716 | |h|
717 | @ 0.100000
718 | |e|
719 | @ 0.100000
720 | | |
721 | @ 0.100000
722 | |s|
723 | @ 0.100000
724 | |e|
725 | @ 0.100000
726 | |c|
727 | @ 0.100000
728 | |t|
729 | @ 0.100000
730 | |i|
731 | @ 0.100000
732 | |o|
733 | @ 0.100000
734 | |n|
735 | @ 0.100000
736 | | |
737 | @ 0.100000
738 | |t|
739 | @ 0.100000
740 | |h|
741 | @ 0.100000
742 | |e|
743 | @ 0.100000
744 | |y|
745 | @ 0.100000
746 | | |
747 | @ 0.100000
748 | |a|
749 | @ 0.100000
750 | |r|
751 | @ 0.100000
752 | |e|
753 | @ 0.100000
754 | | |
755 | @ 0.100000
756 | |i|
757 | @ 0.100000
758 | |n|
759 | @ 0.100000
760 | |.|
761 | @ 0.100000
762 | . LF/^J
763 | @ 0.100000
764 | . ESC
765 | @ 0.200000
766 | |:|
767 | @ 0.100000
768 | |w|
769 | @ 0.100000
770 | . LF/^J
771 | @ 0.100000
772 | |o|
773 | @ 0.100000
774 | |T|
775 | @ 0.100000
776 | |h|
777 | @ 0.100000
778 | |i|
779 | @ 0.100000
780 | |s|
781 | @ 0.100000
782 | | |
783 | @ 0.100000
784 | |i|
785 | @ 0.100000
786 | |s|
787 | @ 0.100000
788 | | |
789 | @ 0.100000
790 | |a|
791 | @ 0.100000
792 | | |
793 | @ 0.100000
794 | |s|
795 | @ 0.100000
796 | |u|
797 | @ 0.100000
798 | |b|
799 | @ 0.100000
800 | |s|
801 | @ 0.100000
802 | |e|
803 | @ 0.100000
804 | |c|
805 | @ 0.100000
806 | |t|
807 | @ 0.100000
808 | |i|
809 | @ 0.100000
810 | |o|
811 | @ 0.100000
812 | |n|
813 | @ 0.100000
814 | . LF/^J
815 | @ 0.100000
816 | . ESC
817 | @ 0.200000
818 | |2|
819 | @ 0.100000
820 | |0|
821 | @ 0.100000
822 | |i|
823 | @ 0.100000
824 | |-|
825 | @ 0.100000
826 | . ESC
827 | @ 0.200000
828 | |o|
829 | @ 0.100000
830 | . LF/^J
831 | @ 0.100000
832 | |A|
833 | @ 0.100000
834 | |n|
835 | @ 0.100000
836 | |d|
837 | @ 0.100000
838 | | |
839 | @ 0.100000
840 | |a|
841 | @ 0.100000
842 | | |
843 | @ 0.100000
844 | |s|
845 | @ 0.100000
846 | |u|
847 | @ 0.100000
848 | |b|
849 | @ 0.100000
850 | |s|
851 | @ 0.100000
852 | |u|
853 | @ 0.100000
854 | |b|
855 | @ 0.100000
856 | |s|
857 | @ 0.100000
858 | |e|
859 | @ 0.100000
860 | |c|
861 | @ 0.100000
862 | |t|
863 | @ 0.100000
864 | |i|
865 | @ 0.100000
866 | |o|
867 | @ 0.100000
868 | |n|
869 | @ 0.100000
870 | . LF/^J
871 | @ 0.100000
872 | . ESC
873 | @ 0.400000
874 | |2|
875 | @ 0.100000
876 | |0|
877 | @ 0.100000
878 | |i|
879 | @ 0.100000
880 | |'|
881 | @ 0.100000
882 | . ESC
883 | @ 0.400000
884 | |o|
885 | @ 0.100000
886 | . LF/^J
887 | @ 0.100000
888 | |T|
889 | @ 0.100000
890 | |h|
891 | @ 0.100000
892 | |i|
893 | @ 0.100000
894 | |s|
895 | @ 0.100000
896 | | |
897 | @ 0.100000
898 | |v|
899 | @ 0.100000
900 | |i|
901 | @ 0.100000
902 | |s|
903 | @ 0.100000
904 | |u|
905 | @ 0.100000
906 | |a|
907 | @ 0.100000
908 | |l|
909 | @ 0.100000
910 | |l|
911 | @ 0.100000
912 | |y|
913 | @ 0.100000
914 | | |
915 | @ 0.100000
916 | |s|
917 | @ 0.100000
918 | |t|
919 | @ 0.100000
920 | |r|
921 | @ 0.100000
922 | |u|
923 | @ 0.100000
924 | |c|
925 | @ 0.100000
926 | |t|
927 | @ 0.100000
928 | |u|
929 | @ 0.100000
930 | |r|
931 | @ 0.100000
932 | |e|
933 | @ 0.100000
934 | |s|
935 | @ 0.100000
936 | | |
937 | @ 0.100000
938 | |t|
939 | @ 0.100000
940 | |h|
941 | @ 0.100000
942 | |e|
943 | @ 0.100000
944 | | |
945 | @ 0.100000
946 | |d|
947 | @ 0.100000
948 | |o|
949 | @ 0.100000
950 | |c|
951 | @ 0.100000
952 | |u|
953 | @ 0.100000
954 | |m|
955 | @ 0.100000
956 | |e|
957 | @ 0.100000
958 | |n|
959 | @ 0.100000
960 | |t|
961 | @ 0.100000
962 | | |
963 | @ 0.100000
964 | |f|
965 | @ 0.100000
966 | |o|
967 | @ 0.100000
968 | |r|
969 | @ 0.100000
970 | | |
971 | @ 0.100000
972 | |b|
973 | @ 0.100000
974 | |e|
975 | @ 0.100000
976 | |t|
977 | @ 0.100000
978 | |t|
979 | @ 0.100000
980 | |e|
981 | @ 0.100000
982 | |r|
983 | @ 0.100000
984 | | |
985 | @ 0.100000
986 | |r|
987 | @ 0.100000
988 | |e|
989 | @ 0.100000
990 | |a|
991 | @ 0.100000
992 | |d|
993 | @ 0.100000
994 | |a|
995 | @ 0.100000
996 | |b|
997 | @ 0.100000
998 | |i|
999 | @ 0.100000
1000 | |l|
1001 | @ 0.100000
1002 | |i|
1003 | @ 0.100000
1004 | |t|
1005 | @ 0.100000
1006 | |y|
1007 | @ 0.100000
1008 | |.|
1009 | @ 0.100000
1010 | . LF/^J
1011 | @ 0.100000
1012 | . ESC
1013 | @ 0.200000
1014 | |:|
1015 | @ 0.100000
1016 | |w|
1017 | @ 0.100000
1018 | . LF/^J
1019 |
1020 | @ 1.500000
1021 | |d|
1022 | @ 0.100000
1023 | |9|
1024 | @ 0.100000
1025 | |k|
1026 | @ 0.100000
1027 | . ESC
1028 | @ 0.200000
1029 | |o|
1030 | @ 0.100000
1031 | |T|
1032 | @ 0.100000
1033 | |a|
1034 | @ 0.100000
1035 | |b|
1036 | @ 0.100000
1037 | |l|
1038 | @ 0.100000
1039 | |e|
1040 | @ 0.100000
1041 | |s|
1042 | @ 0.100000
1043 | | |
1044 | @ 0.100000
1045 | |a|
1046 | @ 0.100000
1047 | |r|
1048 | @ 0.100000
1049 | |e|
1050 | @ 0.100000
1051 | | |
1052 | @ 0.100000
1053 | |p|
1054 | @ 0.100000
1055 | |r|
1056 | @ 0.100000
1057 | |e|
1058 | @ 0.100000
1059 | |t|
1060 | @ 0.100000
1061 | |t|
1062 | @ 0.100000
1063 | |y|
1064 | @ 0.100000
1065 | |-|
1066 | @ 0.100000
1067 | |p|
1068 | @ 0.100000
1069 | |r|
1070 | @ 0.100000
1071 | |i|
1072 | @ 0.100000
1073 | |n|
1074 | @ 0.100000
1075 | |t|
1076 | @ 0.100000
1077 | |e|
1078 | @ 0.100000
1079 | |d|
1080 | @ 0.100000
1081 | | |
1082 | @ 0.100000
1083 | |w|
1084 | @ 0.100000
1085 | |i|
1086 | @ 0.100000
1087 | |t|
1088 | @ 0.100000
1089 | |h|
1090 | @ 0.100000
1091 | | |
1092 | @ 0.100000
1093 | |b|
1094 | @ 0.100000
1095 | |o|
1096 | @ 0.100000
1097 | |x|
1098 | @ 0.100000
1099 | |-|
1100 | @ 0.100000
1101 | |d|
1102 | @ 0.100000
1103 | |r|
1104 | @ 0.100000
1105 | |a|
1106 | @ 0.100000
1107 | |w|
1108 | @ 0.100000
1109 | |i|
1110 | @ 0.100000
1111 | |n|
1112 | @ 0.100000
1113 | |g|
1114 | @ 0.100000
1115 | | |
1116 | @ 0.100000
1117 | |c|
1118 | @ 0.100000
1119 | |h|
1120 | @ 0.100000
1121 | |a|
1122 | @ 0.100000
1123 | |r|
1124 | @ 0.100000
1125 | |a|
1126 | @ 0.100000
1127 | |c|
1128 | @ 0.100000
1129 | |t|
1130 | @ 0.100000
1131 | |e|
1132 | @ 0.100000
1133 | |r|
1134 | @ 0.100000
1135 | |s|
1136 | @ 0.100000
1137 | | |
1138 | @ 0.100000
1139 | |i|
1140 | @ 0.100000
1141 | |f|
1142 | @ 0.100000
1143 | | |
1144 | @ 0.100000
1145 | |y|
1146 | @ 0.100000
1147 | |o|
1148 | @ 0.100000
1149 | |u|
1150 | @ 0.100000
1151 | |r|
1152 | @ 0.100000
1153 | | |
1154 | @ 0.100000
1155 | |t|
1156 | @ 0.100000
1157 | |e|
1158 | @ 0.100000
1159 | |r|
1160 | @ 0.100000
1161 | |m|
1162 | @ 0.100000
1163 | |i|
1164 | @ 0.100000
1165 | |n|
1166 | @ 0.100000
1167 | |a|
1168 | @ 0.100000
1169 | |l|
1170 | @ 0.100000
1171 | | |
1172 | @ 0.100000
1173 | |s|
1174 | @ 0.100000
1175 | |u|
1176 | @ 0.100000
1177 | |p|
1178 | @ 0.100000
1179 | |p|
1180 | @ 0.100000
1181 | |o|
1182 | @ 0.100000
1183 | |r|
1184 | @ 0.100000
1185 | |t|
1186 | @ 0.100000
1187 | |s|
1188 | @ 0.100000
1189 | | |
1190 | @ 0.100000
1191 | |u|
1192 | @ 0.100000
1193 | |n|
1194 | @ 0.100000
1195 | |i|
1196 | @ 0.100000
1197 | |c|
1198 | @ 0.100000
1199 | |o|
1200 | @ 0.100000
1201 | |d|
1202 | @ 0.100000
1203 | |e|
1204 | @ 0.100000
1205 | |,|
1206 | @ 0.100000
1207 | | |
1208 | @ 0.100000
1209 | |a|
1210 | @ 0.100000
1211 | |n|
1212 | @ 0.100000
1213 | |d|
1214 | @ 0.100000
1215 | | |
1216 | @ 0.100000
1217 | |f|
1218 | @ 0.100000
1219 | |a|
1220 | @ 0.100000
1221 | |l|
1222 | @ 0.100000
1223 | |l|
1224 | @ 0.100000
1225 | |s|
1226 | @ 0.100000
1227 | | |
1228 | @ 0.100000
1229 | |b|
1230 | @ 0.100000
1231 | |a|
1232 | @ 0.100000
1233 | |c|
1234 | @ 0.100000
1235 | |k|
1236 | @ 0.100000
1237 | | |
1238 | @ 0.100000
1239 | |t|
1240 | @ 0.100000
1241 | |o|
1242 | @ 0.100000
1243 | | |
1244 | @ 0.100000
1245 | |a|
1246 | @ 0.100000
1247 | |s|
1248 | @ 0.100000
1249 | |c|
1250 | @ 0.100000
1251 | |i|
1252 | @ 0.100000
1253 | |i|
1254 | @ 0.100000
1255 | | |
1256 | @ 0.100000
1257 | |i|
1258 | @ 0.100000
1259 | |f|
1260 | @ 0.100000
1261 | | |
1262 | @ 0.100000
1263 | |i|
1264 | @ 0.100000
1265 | |t|
1266 | @ 0.100000
1267 | | |
1268 | @ 0.100000
1269 | |d|
1270 | @ 0.100000
1271 | |o|
1272 | @ 0.100000
1273 | |e|
1274 | @ 0.100000
1275 | |s|
1276 | @ 0.100000
1277 | | |
1278 | @ 0.100000
1279 | |n|
1280 | @ 0.100000
1281 | |o|
1282 | @ 0.100000
1283 | |t|
1284 | @ 0.100000
1285 | |.|
1286 | @ 0.100000
1287 | . LF/^J
1288 | @ 0.100000
1289 | . ESC
1290 | @ 0.200000
1291 | |:|
1292 | @ 0.100000
1293 | |s|
1294 | @ 0.100000
1295 | |e|
1296 | @ 0.100000
1297 | |t|
1298 | @ 0.100000
1299 | | |
1300 | @ 0.100000
1301 | |p|
1302 | @ 0.100000
1303 | |a|
1304 | @ 0.100000
1305 | |s|
1306 | @ 0.100000
1307 | |t|
1308 | @ 0.100000
1309 | |e|
1310 | @ 0.100000
1311 | . LF/^J
1312 | @ 0.100000
1313 | |o===== ===== ======|
1314 | . LF/^J
1315 | | Inputs Output|
1316 | . LF/^J
1317 | |------------ ------|
1318 | . LF/^J
1319 | | A B A or B|
1320 | . LF/^J
1321 | |===== ===== ======|
1322 | . LF/^J
1323 | |False False False|
1324 | . LF/^J
1325 | |True False True|
1326 | . LF/^J
1327 | |False True True|
1328 | . LF/^J
1329 | |True True True|
1330 | . LF/^J
1331 | |===== ===== ======|
1332 | . LF/^J
1333 | @ 0.100000
1334 | . ESC
1335 | @ 0.200000
1336 | |:|
1337 | @ 0.100000
1338 | |s|
1339 | @ 0.100000
1340 | |e|
1341 | @ 0.100000
1342 | |t|
1343 | @ 0.100000
1344 | | |
1345 | @ 0.100000
1346 | |n|
1347 | @ 0.100000
1348 | |o|
1349 | @ 0.100000
1350 | |p|
1351 | @ 0.100000
1352 | |a|
1353 | @ 0.100000
1354 | |s|
1355 | @ 0.100000
1356 | |t|
1357 | @ 0.100000
1358 | |e|
1359 | @ 0.100000
1360 | . ESC
1361 | @ 0.200000
1362 | |:|
1363 | @ 0.100000
1364 | |w|
1365 | @ 0.100000
1366 | . LF/^J
1367 |
1368 | @ 1.500000
1369 | |d|
1370 | @ 0.100000
1371 | |1|
1372 | @ 0.100000
1373 | |2|
1374 | @ 0.100000
1375 | |k|
1376 | @ 0.100000
1377 | . ESC
1378 | @ 0.200000
1379 | |o|
1380 | @ 0.100000
1381 | |R|
1382 | @ 0.100000
1383 | |S|
1384 | @ 0.100000
1385 | |T|
1386 | @ 0.100000
1387 | | |
1388 | @ 0.100000
1389 | |c|
1390 | @ 0.100000
1391 | |l|
1392 | @ 0.100000
1393 | |a|
1394 | @ 0.100000
1395 | |s|
1396 | @ 0.100000
1397 | |s|
1398 | @ 0.100000
1399 | |e|
1400 | @ 0.100000
1401 | |s|
1402 | @ 0.100000
1403 | | |
1404 | @ 0.100000
1405 | |a|
1406 | @ 0.100000
1407 | |r|
1408 | @ 0.100000
1409 | |e|
1410 | @ 0.100000
1411 | | |
1412 | @ 0.100000
1413 | |a|
1414 | @ 0.100000
1415 | |v|
1416 | @ 0.100000
1417 | |a|
1418 | @ 0.100000
1419 | |i|
1420 | @ 0.100000
1421 | |l|
1422 | @ 0.100000
1423 | |a|
1424 | @ 0.100000
1425 | |b|
1426 | @ 0.100000
1427 | |l|
1428 | @ 0.100000
1429 | |e|
1430 | @ 0.100000
1431 | | |
1432 | @ 0.100000
1433 | |f|
1434 | @ 0.100000
1435 | |o|
1436 | @ 0.100000
1437 | |r|
1438 | @ 0.100000
1439 | | |
1440 | @ 0.100000
1441 | |u|
1442 | @ 0.100000
1443 | |s|
1444 | @ 0.100000
1445 | |e|
1446 | @ 0.100000
1447 | |r|
1448 | @ 0.100000
1449 | | |
1450 | @ 0.100000
1451 | |d|
1452 | @ 0.100000
1453 | |e|
1454 | @ 0.100000
1455 | |f|
1456 | @ 0.100000
1457 | |i|
1458 | @ 0.100000
1459 | |n|
1460 | @ 0.100000
1461 | |e|
1462 | @ 0.100000
1463 | |d|
1464 | @ 0.100000
1465 | | |
1466 | @ 0.100000
1467 | |r|
1468 | @ 0.100000
1469 | |o|
1470 | @ 0.100000
1471 | |l|
1472 | @ 0.100000
1473 | |e|
1474 | @ 0.100000
1475 | |s|
1476 | @ 0.100000
1477 | |:|
1478 | @ 0.100000
1479 | . LF/^J
1480 | @ 0.100000
1481 | . LF/^J
1482 | @ 0.100000
1483 | |.|
1484 | @ 0.100000
1485 | |.|
1486 | @ 0.100000
1487 | | |
1488 | @ 0.100000
1489 | |r|
1490 | @ 0.100000
1491 | |o|
1492 | @ 0.100000
1493 | |l|
1494 | @ 0.100000
1495 | |e|
1496 | @ 0.100000
1497 | |:|
1498 | @ 0.100000
1499 | |:|
1500 | @ 0.100000
1501 | | |
1502 | @ 0.100000
1503 | |i|
1504 | @ 0.100000
1505 | |m|
1506 | @ 0.100000
1507 | |p|
1508 | @ 0.100000
1509 | |o|
1510 | @ 0.100000
1511 | |r|
1512 | @ 0.100000
1513 | |t|
1514 | @ 0.100000
1515 | |a|
1516 | @ 0.100000
1517 | |n|
1518 | @ 0.100000
1519 | |t|
1520 | @ 0.100000
1521 | . LF/^J
1522 | @ 0.100000
1523 | | |
1524 | @ 0.100000
1525 | | |
1526 | @ 0.100000
1527 | | |
1528 | @ 0.100000
1529 | | |
1530 | @ 0.100000
1531 | |:|
1532 | @ 0.100000
1533 | |c|
1534 | @ 0.100000
1535 | |l|
1536 | @ 0.100000
1537 | |a|
1538 | @ 0.100000
1539 | |s|
1540 | @ 0.100000
1541 | |s|
1542 | @ 0.100000
1543 | |:|
1544 | @ 0.100000
1545 | | |
1546 | @ 0.100000
1547 | |a|
1548 | @ 0.100000
1549 | |n|
1550 | @ 0.100000
1551 | |s|
1552 | @ 0.100000
1553 | |i|
1554 | @ 0.100000
1555 | |-|
1556 | @ 0.100000
1557 | |f|
1558 | @ 0.100000
1559 | |g|
1560 | @ 0.100000
1561 | |-|
1562 | @ 0.100000
1563 | |r|
1564 | @ 0.100000
1565 | |e|
1566 | @ 0.100000
1567 | |d|
1568 | @ 0.100000
1569 | | |
1570 | @ 0.100000
1571 | |a|
1572 | @ 0.100000
1573 | |n|
1574 | @ 0.100000
1575 | |s|
1576 | @ 0.100000
1577 | |i|
1578 | @ 0.100000
1579 | |-|
1580 | @ 0.100000
1581 | |b|
1582 | @ 0.100000
1583 | |o|
1584 | @ 0.100000
1585 | |l|
1586 | @ 0.100000
1587 | |d|
1588 | @ 0.100000
1589 | . LF/^J
1590 | @ 0.100000
1591 | . LF/^J
1592 | @ 0.100000
1593 | |:|
1594 | @ 0.100000
1595 | |i|
1596 | @ 0.100000
1597 | |m|
1598 | @ 0.100000
1599 | |p|
1600 | @ 0.100000
1601 | |o|
1602 | @ 0.100000
1603 | |r|
1604 | @ 0.100000
1605 | |t|
1606 | @ 0.100000
1607 | |a|
1608 | @ 0.100000
1609 | |n|
1610 | @ 0.100000
1611 | |t|
1612 | @ 0.100000
1613 | |:|
1614 | @ 0.100000
1615 | |`|
1616 | @ 0.100000
1617 | |T|
1618 | @ 0.100000
1619 | |h|
1620 | @ 0.100000
1621 | |i|
1622 | @ 0.100000
1623 | |s|
1624 | @ 0.100000
1625 | | |
1626 | @ 0.100000
1627 | |i|
1628 | @ 0.100000
1629 | |s|
1630 | @ 0.100000
1631 | | |
1632 | @ 0.100000
1633 | |i|
1634 | @ 0.100000
1635 | |m|
1636 | @ 0.100000
1637 | |p|
1638 | @ 0.100000
1639 | |o|
1640 | @ 0.100000
1641 | |r|
1642 | @ 0.100000
1643 | |t|
1644 | @ 0.100000
1645 | |a|
1646 | @ 0.100000
1647 | |n|
1648 | @ 0.100000
1649 | |t|
1650 | @ 0.100000
1651 | |!|
1652 | @ 0.100000
1653 | |`|
1654 | @ 0.100000
1655 | . LF/^J
1656 | @ 0.100000
1657 | . ESC
1658 | @ 0.200000
1659 | |:|
1660 | @ 0.100000
1661 | |w|
1662 | @ 0.100000
1663 | . LF/^J
1664 |
1665 | # Last frame
1666 |
1667 | @ 1.000000
1668 | |d|
1669 | @ 0.100000
1670 | |6|
1671 | @ 0.100000
1672 | |k|
1673 | @ 0.100000
1674 | . ESC
1675 | @ 0.200000
1676 | |o|
1677 | @ 0.100000
1678 | |r|
1679 | @ 0.100000
1680 | |s|
1681 | @ 0.100000
1682 | |t|
1683 | @ 0.100000
1684 | |2|
1685 | @ 0.100000
1686 | |a|
1687 | @ 0.100000
1688 | |n|
1689 | @ 0.100000
1690 | |s|
1691 | @ 0.100000
1692 | |i|
1693 | @ 0.100000
1694 | | |
1695 | @ 0.100000
1696 | |i|
1697 | @ 0.100000
1698 | |s|
1699 | @ 0.100000
1700 | | |
1701 | @ 0.100000
1702 | |a|
1703 | @ 0.100000
1704 | |v|
1705 | @ 0.100000
1706 | |a|
1707 | @ 0.100000
1708 | |i|
1709 | @ 0.100000
1710 | |l|
1711 | @ 0.100000
1712 | |a|
1713 | @ 0.100000
1714 | |b|
1715 | @ 0.100000
1716 | |l|
1717 | @ 0.100000
1718 | |e|
1719 | @ 0.100000
1720 | | |
1721 | @ 0.100000
1722 | |o|
1723 | @ 0.100000
1724 | |n|
1725 | @ 0.100000
1726 | | |
1727 | @ 0.100000
1728 | |g|
1729 | @ 0.100000
1730 | |i|
1731 | @ 0.100000
1732 | |t|
1733 | @ 0.100000
1734 | |h|
1735 | @ 0.100000
1736 | |u|
1737 | @ 0.100000
1738 | |b|
1739 | @ 0.100000
1740 | | |
1741 | @ 0.100000
1742 | |a|
1743 | @ 0.100000
1744 | |t|
1745 | @ 0.100000
1746 | | |
1747 | @ 0.100000
1748 | |h|
1749 | @ 0.100000
1750 | |t|
1751 | @ 0.100000
1752 | |t|
1753 | @ 0.100000
1754 | |p|
1755 | @ 0.100000
1756 | |s|
1757 | @ 0.100000
1758 | |:|
1759 | @ 0.100000
1760 | |/|
1761 | @ 0.100000
1762 | |/|
1763 | @ 0.100000
1764 | |g|
1765 | @ 0.100000
1766 | |i|
1767 | @ 0.100000
1768 | |t|
1769 | @ 0.100000
1770 | |h|
1771 | @ 0.100000
1772 | |u|
1773 | @ 0.100000
1774 | |b|
1775 | @ 0.100000
1776 | |.|
1777 | @ 0.100000
1778 | |c|
1779 | @ 0.100000
1780 | |o|
1781 | @ 0.100000
1782 | |m|
1783 | @ 0.100000
1784 | |/|
1785 | @ 0.100000
1786 | |S|
1787 | @ 0.100000
1788 | |n|
1789 | @ 0.100000
1790 | |a|
1791 | @ 0.100000
1792 | |i|
1793 | @ 0.100000
1794 | |p|
1795 | @ 0.100000
1796 | |e|
1797 | @ 0.100000
1798 | |/|
1799 | @ 0.100000
1800 | |p|
1801 | @ 0.100000
1802 | |y|
1803 | @ 0.100000
1804 | |t|
1805 | @ 0.100000
1806 | |h|
1807 | @ 0.100000
1808 | |o|
1809 | @ 0.100000
1810 | |n|
1811 | @ 0.100000
1812 | |-|
1813 | @ 0.100000
1814 | |r|
1815 | @ 0.100000
1816 | |s|
1817 | @ 0.100000
1818 | |t|
1819 | @ 0.100000
1820 | |2|
1821 | @ 0.100000
1822 | |a|
1823 | @ 0.100000
1824 | |n|
1825 | @ 0.100000
1826 | |s|
1827 | @ 0.100000
1828 | |i|
1829 | @ 0.100000
1830 | . LF/^J
1831 | @ 0.100000
1832 | . LF/^J
1833 | @ 0.100000
1834 | |-|
1835 | @ 0.100000
1836 | |-|
1837 | @ 0.100000
1838 | |-|
1839 | @ 0.100000
1840 | |-|
1841 | @ 0.100000
1842 | |-|
1843 | @ 0.100000
1844 | |-|
1845 | @ 0.100000
1846 | |-|
1847 | @ 0.100000
1848 | |-|
1849 | @ 0.100000
1850 | |-|
1851 | @ 0.100000
1852 | |-|
1853 | @ 0.100000
1854 | . LF/^J
1855 | @ 0.100000
1856 | . LF/^J
1857 | @ 0.100000
1858 | |H|
1859 | @ 0.100000
1860 | |a|
1861 | @ 0.100000
1862 | |v|
1863 | @ 0.100000
1864 | |e|
1865 | @ 0.100000
1866 | | |
1867 | @ 0.100000
1868 | |a|
1869 | @ 0.100000
1870 | | |
1871 | @ 0.100000
1872 | |n|
1873 | @ 0.100000
1874 | |i|
1875 | @ 0.100000
1876 | |c|
1877 | @ 0.100000
1878 | |e|
1879 | @ 0.100000
1880 | | |
1881 | @ 0.100000
1882 | |d|
1883 | @ 0.100000
1884 | |a|
1885 | @ 0.100000
1886 | |y|
1887 | @ 0.100000
1888 | |!|
1889 | @ 0.100000
1890 | . ESC
1891 | @ 0.200000
1892 | |:|
1893 | @ 0.100000
1894 | |w|
1895 | @ 0.100000
1896 | . LF/^J
1897 |
--------------------------------------------------------------------------------