forked from debops/yaml2rst
-
Notifications
You must be signed in to change notification settings - Fork 0
/
yaml2rst.py
128 lines (108 loc) · 4.25 KB
/
yaml2rst.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# -*- coding: utf-8 -*-
"""
yaml2rst – A Simple Tool for Documenting YAML Files
"""
#
# Copyright 2015 by Hartmut Goebel <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import print_function
import re
__author__ = "Hartmut Goebel <[email protected]>"
__copyright__ = "Copyright 2015 by Hartmut Goebel <[email protected]>"
__licence__ = "GNU General Public License version 3 (GPL v3)"
__version__ = "0.3dev"
STATE_TEXT = 0
STATE_YAML = 1
def setup_patterns():
# Create rst patterns, copied from `docutils/parsers/rst/states.py`
# Function has been placed in the public domain.
class Struct:
"""Stores data attributes for dotted-attribute access."""
def __init__(self, **keywordargs):
self.__dict__.update(keywordargs)
enum = Struct()
enum.formatinfo = {
'parens': Struct(prefix='(', suffix=')', start=1, end=-1),
'rparen': Struct(prefix='', suffix=')', start=0, end=-1),
'period': Struct(prefix='', suffix='.', start=0, end=-1)}
enum.formats = enum.formatinfo.keys()
enum.sequences = ['arabic', 'loweralpha', 'upperalpha',
'lowerroman', 'upperroman'] # ORDERED!
enum.sequencepats = {'arabic': '[0-9]+',
'loweralpha': '[a-z]',
'upperalpha': '[A-Z]',
'lowerroman': '[ivxlcdm]+',
'upperroman': '[IVXLCDM]+',}
pats = {}
pats['nonalphanum7bit'] = '[!-/:-@[-`{-~]'
pats['alpha'] = '[a-zA-Z]'
pats['alphanum'] = '[a-zA-Z0-9]'
pats['alphanumplus'] = '[a-zA-Z0-9_-]'
pats['enum'] = ('(%(arabic)s|%(loweralpha)s|%(upperalpha)s|%(lowerroman)s'
'|%(upperroman)s|#)' % enum.sequencepats)
for format in enum.formats:
pats[format] = '(?P<%s>%s%s%s)' % (
format, re.escape(enum.formatinfo[format].prefix),
pats['enum'], re.escape(enum.formatinfo[format].suffix))
patterns = {
'bullet': u'[-+*\u2022\u2023\u2043]( +|$)',
'enumerator': r'(%(parens)s|%(rparen)s|%(period)s)( +|$)' % pats,
}
for name, pat in patterns.items():
patterns[name] = re.compile(pat)
return patterns
PATTERNS = setup_patterns()
def get_indent(line):
stripped_line = line.lstrip()
indent = len(line) - len(stripped_line)
if (PATTERNS['bullet'].match(stripped_line) or
PATTERNS['enumerator'].match(stripped_line)):
indent += len(stripped_line.split(None, 1)[0])+1
return indent
def convert(lines):
state = STATE_TEXT
last_text_line = ''
last_indent = ''
for line in lines:
line = line.rstrip()
if not line:
# do not change state if the line is empty
yield ''
elif line.startswith('# ') or line == '#':
if state != STATE_TEXT:
yield ''
line = last_text_line = line[2:]
yield line
last_indent = get_indent(line)* ' '
state = STATE_TEXT
elif line == '---':
pass
else:
if line.startswith('---'):
line = line[3:]
if state != STATE_YAML:
if not last_text_line.endswith('::'):
yield last_indent + '::'
yield ''
yield last_indent + ' ' + line
state = STATE_YAML
def convert_text(yaml_text):
return '\n'.join(convert(yaml_text.splitlines()))
def convert_file(infilename, outfilename):
with open(infilename) as infh:
with open(outfilename, "w") as outfh:
for l in convert(infh.readlines()):
print(l.rstrip(), file=outfh)