1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2
# See LICENSE for details.
5
"""man2lore: Converts man page source (i.e. groff) into lore-compatible html.
7
This is nasty and hackish (and doesn't support lots of real groff), but is good
8
enough for converting fairly simple man pages.
10
from __future__ import nested_scopes
13
quoteRE = re.compile('"(.*?)"')
16
text = text.replace('<', '<').replace('>', '>')
17
text = quoteRE.sub('<q>\\1</q>', text)
21
if s[0] == s[-1] == '"':
32
def convert(self, inf, outf):
33
self.write = outf.write
35
for line in inf.readlines():
36
if line.rstrip() and line.rstrip()[-1] == '\\':
37
longline += line.rstrip()[:-1] + ' '
40
line = longline + line
42
self.lineReceived(line)
44
self.write('</body>\n</html>\n')
46
def lineReceived(self, line):
48
f = getattr(self, 'macro_' + line[1:3].rstrip().upper(), None)
54
def continueReceived(self, cont):
58
f = getattr(self, 'macro_' + cont[:2].rstrip().upper(), None)
65
if self.state != 'regular':
66
self.write('</%s>' % self.state)
68
self.write('</dd>\n\n')
71
self.write('</dl>\n\n')
74
self.write('</p>\n\n')
78
if not self.tp and not self.para:
82
def macro_TH(self, line):
83
self.write('<html><head>\n')
84
parts = [stripQuotes(x) for x in line.split(' ', 2)] + ['', '']
85
title, manSection = parts[:2]
86
self.write('<title>%s.%s</title>' % (title, manSection))
87
self.write('</head>\n<body>\n\n')
88
self.write('<h1>%s.%s</h1>\n\n' % (title, manSection))
92
def macro_SH(self, line):
96
self.text(stripQuotes(line))
99
self.write('</h2>\n\n')
101
def macro_B(self, line):
103
words[0] = '\\fB' + words[0] + '\\fR '
104
self.text(' '.join(words))
106
def macro_NM(self, line):
109
self.text(self.name + ' ')
111
def macro_NS(self, line):
112
parts = line.split(' Ns ')
119
self.continueReceived(l)
121
def macro_OO(self, line):
123
self.continueReceived(line)
125
def macro_OC(self, line):
127
self.continueReceived(line)
129
def macro_OP(self, line):
131
self.continueReceived(line)
134
def macro_FL(self, line):
136
self.text('\\fB-%s\\fR' % parts[0])
137
self.continueReceived(' '.join(parts[1:]))
139
def macro_AR(self, line):
141
self.text('\\fI %s\\fR' % parts[0])
142
self.continueReceived(' '.join(parts[1:]))
144
def macro_PP(self, line):
147
def macro_TP(self, line):
149
self.write('</dd>\n\n')
152
def macro_BL(self, line):
153
#assert self.tp == 0, self.tp
157
def macro_EL(self, line):
161
#assert self.tp == 1, self.tp
162
self.write('</dl>\n\n')
165
def macro_IT(self, line):
169
#assert self.tp == 1, (self.tp, line)
171
self.continueReceived(line)
175
def text(self, line):
180
bits = line.split('\\')
181
self.write(escape(bits[0]))
184
self.write('<em>' + escape(bit[2:]))
186
elif bit[:2] == 'fB':
187
self.write('<strong>' + escape(bit[2:]))
188
self.state = 'strong'
189
elif bit[:2] == 'fR':
190
self.write('</%s>' % self.state)
191
self.write(escape(bit[2:]))
192
self.state = 'regular'
193
elif bit[:3] == '(co':
194
self.write('©' + escape(bit[3:]))
196
self.write(escape(bit))
201
class ProcessingFunctionFactory:
203
def generate_lore(self, d, filenameGenerator=None):
204
ext = d.get('ext', '.html')
205
return lambda file,_: ManConverter().convert(open(file),
206
open(os.path.splitext(file)[0]+ext, 'w'))
208
factory = ProcessingFunctionFactory()
210
if __name__ == '__main__':
212
mc = ManConverter().convert(open(sys.argv[1]), sys.stdout)