Skip to content

Commit 66a5eb6

Browse files
committed
update mallard2man.py from libbson
1 parent c725c7e commit 66a5eb6

File tree

1 file changed

+49
-12
lines changed

1 file changed

+49
-12
lines changed

doc/mallard2man.py

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"""
3030

3131
import os
32+
import re
3233
import sys
3334

3435
import codecs
@@ -56,6 +57,10 @@
5657
TD = '{http://projectmallard.org/1.0/}td'
5758
OUTPUT = '{http://projectmallard.org/1.0/}output'
5859

60+
# Matches "\" and "-", but not "\-".
61+
replaceables = re.compile(r'(\\(?!-))|((?<!\\)-)')
62+
63+
5964
class Convert(object):
6065
title = None
6166
subtitle = None
@@ -69,6 +74,9 @@ def __init__(self, inFile, outFile, section):
6974
self.section = section
7075
self.sections = []
7176

77+
# Map: section id -> section element.
78+
self.sections_map = {}
79+
7280
def _parse(self):
7381
self.tree = ElementTree.ElementTree()
7482
self.tree.parse(open(self.inFile))
@@ -87,23 +95,57 @@ def _get_parent(self, ele):
8795
return self.parent_map[ele]
8896

8997
def _extract(self):
90-
# Try to extract the title.
98+
# Extract the title and subtitle.
9199
for child in self.root.getchildren():
92100
if child.tag == TITLE:
93101
self.title = child.text.strip()
94102
elif child.tag == SUBTITLE:
95103
self.subtitle = child.text.strip()
96104
elif child.tag == SECTION:
105+
if child.get('id'):
106+
self.sections_map[child.get('id')] = child
97107
self.sections.append(child)
98108

109+
if not self.subtitle and 'description' in self.sections_map:
110+
# No "subtitle" element, use description section title as subtitle.
111+
self.subtitle = self._section_text(self.sections_map['description'])
112+
113+
def _section_text(self, section):
114+
# Find <section id="description"><p>some text</p></section>.
115+
for child in section:
116+
if child.tag != TITLE:
117+
return self._textify_elem(child)
118+
119+
def _textify_elem(self, elem):
120+
return ''.join(elem.itertext()).strip()
121+
99122
def _writeComment(self, text=''):
100123
lines = text.split('\n')
101124
for line in lines:
102125
self.outFile.write('.\\" ')
103126
self.outFile.write(line)
104127
self.outFile.write('\n')
105128

129+
def _escape_char(self, match):
130+
c = match.group(0)
131+
if c == "-":
132+
return r"\(hy"
133+
elif c == "\\":
134+
return "\\e"
135+
136+
assert False, "invalid char passed to _escape_char: %r" % c
137+
138+
def _escape(self, text):
139+
# Avoid "hyphen-used-as-minus-sign" lintian warning about man pages,
140+
# and escape text like "\0" as "\\0". We'll replace all "-" with "\(hy",
141+
# which is an explicit hyphen, but leave alone the first line's
142+
# "name \- description" text.
143+
return replaceables.sub(self._escape_char, text)
144+
106145
def _write(self, text):
146+
self._write_noescape(self._escape(text))
147+
148+
def _write_noescape(self, text):
107149
self.outFile.write(text)
108150

109151
def _writeCommand(self, text):
@@ -135,11 +177,7 @@ def _generateHeader(self):
135177
title = self.title.replace('()','').upper()
136178
self._write('.TH "%s" "%s" "%s" "%s"\n' % (title, self.section, date, GROUP))
137179
self._write('.SH NAME\n')
138-
139-
if self.subtitle:
140-
self._write('%s \\- %s\n' % (self.title, self.subtitle))
141-
else:
142-
self._write('%s\n' % self.title)
180+
self._write_noescape('%s \\- %s\n' % (self.title, self.subtitle))
143181

144182
def _generateSection(self, section):
145183
# Try to render the title first
@@ -165,7 +203,7 @@ def _generateCode(self, code):
165203
is_synopsis = self._get_parent(code).tag.endswith('synopsis')
166204
if text and '\n' not in text and not is_synopsis:
167205
text = text.replace('()', '(%s)' % self.section)
168-
self._writeCommand('.BR ' + text)
206+
self._writeCommand('.B ' + text)
169207
else:
170208
self._writeCommand('.nf')
171209
self._writeLine(code.text)
@@ -203,7 +241,7 @@ def _generateList(self, l):
203241
self._generateElement(child)
204242

205243
def _generateEM(self, em):
206-
self._writeCommand('.BR %s' % em.text)
244+
self._writeCommand('.B %s' % em.text)
207245

208246
def _generateOutput(self, output):
209247
self._generateCode(output)
@@ -274,18 +312,17 @@ def _generateLink(self, link):
274312
if text and '()' in text:
275313
text = text.replace('()', '(%s)' % self.section)
276314
if text:
277-
self._writeCommand('.BR ' + text)
315+
self._writeCommand('.B ' + text)
278316

279317
def _generateSections(self):
280318
for section in self.sections:
281319
self._generateElement(section)
282320

283321
def _generateFooter(self):
284-
self._write('\n.BR')
322+
self._write('\n.B')
285323
self._write('\n.SH COLOPHON')
286324
self._write('\nThis page is part of %s.' % GROUP)
287-
self._write('\nPlease report any bugs at\n')
288-
self._write('\\%' + BUG_URL.replace('-','\\-') + '.')
325+
self._write('\nPlease report any bugs at %s.' % BUG_URL.replace('-','\\-'))
289326

290327
def _generate(self):
291328
self.realname = self.outFile

0 commit comments

Comments
 (0)