]> git.proxmox.com Git - mirror_ovs.git/blame - python/build/nroff.py
nroff: Fix style of names.
[mirror_ovs.git] / python / build / nroff.py
CommitLineData
7b8c46c8
BP
1# Copyright (c) 2010, 2011, 2012, 2015 Nicira, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at:
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import re
16
17from ovs.db import error
18
4d9d1d9e 19def text_to_nroff(s, font=r'\fR'):
7b8c46c8
BP
20 def escape(match):
21 c = match.group(0)
22
23 # In Roman type, let -- in XML be \- in nroff. That gives us a way to
24 # write minus signs, which is important in some places in manpages.
25 #
26 # Bold in nroff usually represents literal text, where there's no
27 # distinction between hyphens and minus sign. The convention in nroff
28 # appears to be to use a minus sign in such cases, so we follow that
29 # convention.
30 #
31 # Finally, we always output - as a minus sign when it is followed by a
32 # digit.
33 if c.startswith('-'):
34 if c == '--' and font == r'\fR':
35 return r'\-'
36 if c != '-' or font in (r'\fB', r'\fL'):
37 return c.replace('-', r'\-')
38 else:
39 return '-'
40
41 if c == '\\':
42 return r'\e'
43 elif c == '"':
44 return r'\(dq'
45 elif c == "'":
46 return r'\(cq'
47 elif c == ".":
48 # groff(7) says that . can be escaped by \. but in practice groff
49 # still gives an error with \. at the beginning of a line.
7102846b 50 return r'\[char46]'
7b8c46c8
BP
51 else:
52 raise error.Error("bad escape")
53
54 # Escape - \ " ' . as needed by nroff.
55 s = re.sub('(-[0-9]|--|[-"\'\\\\.])', escape, s)
56 return s
57
4d9d1d9e
BP
58def escape_nroff_literal(s, font=r'\fB'):
59 return font + r'%s\fR' % text_to_nroff(s, font)
7b8c46c8 60
4d9d1d9e 61def inline_xml_to_nroff(node, font, to_upper=False):
7b8c46c8
BP
62 if node.nodeType == node.TEXT_NODE:
63 if to_upper:
4d9d1d9e 64 return text_to_nroff(node.data.upper(), font)
7b8c46c8 65 else:
4d9d1d9e 66 return text_to_nroff(node.data, font)
7b8c46c8 67 elif node.nodeType == node.ELEMENT_NODE:
d75ef07f 68 if node.tagName in ['code', 'em', 'option', 'env']:
7b8c46c8
BP
69 s = r'\fB'
70 for child in node.childNodes:
4d9d1d9e 71 s += inline_xml_to_nroff(child, r'\fB')
7b8c46c8
BP
72 return s + font
73 elif node.tagName == 'ref':
74 s = r'\fB'
75 if node.hasAttribute('column'):
76 s += node.attributes['column'].nodeValue
77 if node.hasAttribute('key'):
78 s += ':' + node.attributes['key'].nodeValue
79 elif node.hasAttribute('table'):
80 s += node.attributes['table'].nodeValue
81 elif node.hasAttribute('group'):
82 s += node.attributes['group'].nodeValue
83 elif node.hasAttribute('db'):
84 s += node.attributes['db'].nodeValue
85 else:
86 raise error.Error("'ref' lacks required attributes: %s" % node.attributes.keys())
87 return s + font
88 elif node.tagName == 'var' or node.tagName == 'dfn':
89 s = r'\fI'
90 for child in node.childNodes:
4d9d1d9e 91 s += inline_xml_to_nroff(child, r'\fI')
7b8c46c8
BP
92 return s + font
93 else:
94 raise error.Error("element <%s> unknown or invalid here" % node.tagName)
95 else:
96 raise error.Error("unknown node %s in inline xml" % node)
97
98def pre_to_nroff(nodes, para, font):
99 s = para + '\n.nf\n'
100 for node in nodes:
101 if node.nodeType != node.TEXT_NODE:
102 fatal("<pre> element may only have text children")
103 for line in node.data.split('\n'):
4d9d1d9e 104 s += escape_nroff_literal(line, font) + '\n.br\n'
7b8c46c8
BP
105 s += '.fi\n'
106 return s
107
4d9d1d9e 108def block_xml_to_nroff(nodes, para='.PP'):
7b8c46c8
BP
109 s = ''
110 for node in nodes:
111 if node.nodeType == node.TEXT_NODE:
4d9d1d9e 112 s += text_to_nroff(node.data)
7b8c46c8
BP
113 s = s.lstrip()
114 elif node.nodeType == node.ELEMENT_NODE:
115 if node.tagName in ['ul', 'ol']:
116 if s != "":
117 s += "\n"
118 s += ".RS\n"
119 i = 0
4d9d1d9e
BP
120 for li_node in node.childNodes:
121 if (li_node.nodeType == node.ELEMENT_NODE
122 and li_node.tagName == 'li'):
7b8c46c8
BP
123 i += 1
124 if node.tagName == 'ul':
125 s += ".IP \\(bu\n"
126 else:
127 s += ".IP %d. .25in\n" % i
4d9d1d9e
BP
128 s += block_xml_to_nroff(li_node.childNodes, ".IP")
129 elif (li_node.nodeType != node.TEXT_NODE
130 or not li_node.data.isspace()):
7b8c46c8
BP
131 raise error.Error("<%s> element may only have <li> children" % node.tagName)
132 s += ".RE\n"
133 elif node.tagName == 'dl':
134 if s != "":
135 s += "\n"
136 s += ".RS\n"
137 prev = "dd"
4d9d1d9e
BP
138 for li_node in node.childNodes:
139 if (li_node.nodeType == node.ELEMENT_NODE
140 and li_node.tagName == 'dt'):
7b8c46c8
BP
141 if prev == 'dd':
142 s += '.TP\n'
143 else:
144 s += '.TQ .5in\n'
145 prev = 'dt'
4d9d1d9e
BP
146 elif (li_node.nodeType == node.ELEMENT_NODE
147 and li_node.tagName == 'dd'):
7b8c46c8
BP
148 if prev == 'dd':
149 s += '.IP\n'
150 prev = 'dd'
4d9d1d9e
BP
151 elif (li_node.nodeType != node.TEXT_NODE
152 or not li_node.data.isspace()):
7b8c46c8 153 raise error.Error("<dl> element may only have <dt> and <dd> children")
4d9d1d9e 154 s += block_xml_to_nroff(li_node.childNodes, ".IP")
7b8c46c8
BP
155 s += ".RE\n"
156 elif node.tagName == 'p':
157 if s != "":
158 if not s.endswith("\n"):
159 s += "\n"
160 s += para + "\n"
4d9d1d9e 161 s += block_xml_to_nroff(node.childNodes, para)
7b8c46c8
BP
162 elif node.tagName in ('h1', 'h2', 'h3'):
163 if s != "":
164 if not s.endswith("\n"):
165 s += "\n"
166 nroffTag = {'h1': 'SH', 'h2': 'SS', 'h3': 'ST'}[node.tagName]
167 s += '.%s "' % nroffTag
168 for child_node in node.childNodes:
4d9d1d9e 169 s += inline_xml_to_nroff(child_node, r'\fR',
7b8c46c8
BP
170 to_upper=(nroffTag == 'SH'))
171 s += '"\n'
172 elif node.tagName == 'pre':
173 fixed = node.getAttribute('fixed')
174 if fixed == 'yes':
175 font = r'\fL'
176 else:
177 font = r'\fB'
178 s += pre_to_nroff(node.childNodes, para, font)
179 else:
4d9d1d9e 180 s += inline_xml_to_nroff(node, r'\fR')
7b8c46c8
BP
181 else:
182 raise error.Error("unknown node %s in block xml" % node)
183 if s != "" and not s.endswith('\n'):
184 s += '\n'
185 return s