1 |
vapier 13/09/29 22:12:51 |
2 |
|
3 |
Added: mkman.py |
4 |
Removed: mkman.sh |
5 |
Log: |
6 |
man: rewrite helper script in python to avoid `help2man` as that tends to mangle things |
7 |
|
8 |
Revision Changes Path |
9 |
1.1 portage-utils/man/mkman.py |
10 |
|
11 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/man/mkman.py?rev=1.1&view=markup |
12 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/man/mkman.py?rev=1.1&content-type=text/plain |
13 |
|
14 |
Index: mkman.py |
15 |
=================================================================== |
16 |
#!/usr/bin/python |
17 |
|
18 |
"""Generate man pages for the q applets""" |
19 |
|
20 |
from __future__ import print_function |
21 |
|
22 |
import datetime |
23 |
import functools |
24 |
import glob |
25 |
import locale |
26 |
import multiprocessing |
27 |
import os |
28 |
import re |
29 |
import subprocess |
30 |
import sys |
31 |
|
32 |
|
33 |
MKMAN_DIR = os.path.realpath(os.path.join(__file__, '..')) |
34 |
FRAGS_DIR = os.path.join(MKMAN_DIR, 'include') |
35 |
|
36 |
TOPDIR = os.path.join(MKMAN_DIR, '..') |
37 |
Q = os.path.join(TOPDIR, 'q') |
38 |
|
39 |
|
40 |
def FindApplets(): |
41 |
"""Return a list of all supported applets""" |
42 |
applets = os.path.join(TOPDIR, 'applets.sh') |
43 |
return subprocess.check_output([applets]).splitlines() |
44 |
|
45 |
|
46 |
COMMON_AUTHORS = [ |
47 |
'Ned Ludd <solar@g.o>', |
48 |
'Mike Frysinger <vapier@g.o>', |
49 |
] |
50 |
TEMPLATE = r""".TH %(applet)s "1" "%(date)s" "Gentoo Foundation" "%(applet)s" |
51 |
.SH NAME |
52 |
%(applet)s \- %(short_desc)s |
53 |
.SH SYNOPSIS |
54 |
.B %(applet)s |
55 |
\fI%(usage)s\fR |
56 |
.SH DESCRIPTION |
57 |
%(description)s |
58 |
.SH OPTIONS |
59 |
%(options)s |
60 |
%(extra_sections)s |
61 |
.SH "REPORTING BUGS" |
62 |
Please report bugs via http://bugs.gentoo.org/ |
63 |
.br |
64 |
Product: Portage Development; Component: Tools |
65 |
.SH AUTHORS |
66 |
.nf |
67 |
%(authors)s |
68 |
.fi |
69 |
.SH "SEE ALSO" |
70 |
%(see_also)s |
71 |
""" |
72 |
|
73 |
def MkMan(applets, applet, output): |
74 |
"""Generate a man page for |applet| and write it to |output|""" |
75 |
print('%-10s: generating %s' % (applet, output)) |
76 |
|
77 |
# Extract the main use string and description: |
78 |
# Usage: q <applet> <args> : invoke a portage utility applet |
79 |
ahelp = subprocess.check_output([Q, applet, '--help']) |
80 |
lines = ahelp.splitlines() |
81 |
m = re.search(r'^Usage: %s (.*) : (.*)' % applet, ahelp) |
82 |
usage = m.group(1) |
83 |
short_desc = m.group(2) |
84 |
|
85 |
authors = COMMON_AUTHORS |
86 |
see_also = sorted(['.BR %s (1)' % x for x in applets if x != applet]) |
87 |
|
88 |
description = '' |
89 |
desc_file = os.path.join(FRAGS_DIR, '%s.desc' % applet) |
90 |
if os.path.exists(desc_file): |
91 |
description = open(desc_file).read().rstrip() |
92 |
|
93 |
# Extract all the options |
94 |
options = [] |
95 |
for line, i in zip(lines, xrange(len(lines))): |
96 |
if not line.startswith('Options: '): |
97 |
continue |
98 |
|
99 |
for option in [x.strip().split() for x in lines[i + 1:]]: |
100 |
flags = [option[0].rstrip(',')] |
101 |
option.pop(0) |
102 |
if option[0][0] == '-': |
103 |
flags += [option[0].rstrip(',')] |
104 |
option.pop(0) |
105 |
|
106 |
if option[0] == '<arg>': |
107 |
flags = [r'\fB%s\fR \fI<arg>\fR' % x for x in flags] |
108 |
option.pop(0) |
109 |
else: |
110 |
flags = [r'\fB%s\fR' % x for x in flags] |
111 |
|
112 |
assert option[0] == '*', 'help line for %s is broken: %r' % (applet, option) |
113 |
option.pop(0) |
114 |
|
115 |
options += [ |
116 |
'.TP', |
117 |
', '.join(flags).replace('-', r'\-'), |
118 |
' '.join(option), |
119 |
] |
120 |
break |
121 |
|
122 |
# Handle applets that have applets |
123 |
extra_sections = [] |
124 |
if 'Currently defined applets:' in ahelp: |
125 |
alines = lines[lines.index('Currently defined applets:') + 1:] |
126 |
alines = alines[:alines.index('')] |
127 |
extra_sections += ( |
128 |
['.SH APPLETS', '.nf', |
129 |
'.B This applet also has sub applets:'] + |
130 |
alines + |
131 |
['.fi'] |
132 |
) |
133 |
|
134 |
# Handle any fragments this applet has available |
135 |
for frag in sorted(glob.glob(os.path.join(FRAGS_DIR, '%s-*.include' % applet))): |
136 |
with open(frag) as f: |
137 |
extra_sections += [x.rstrip() for x in f.readlines()] |
138 |
|
139 |
data = { |
140 |
'applet': applet, |
141 |
'date': datetime.datetime.now().strftime('%b %Y'), |
142 |
'short_desc': short_desc, |
143 |
'usage': usage, |
144 |
'description': description, |
145 |
'options': '\n'.join(options), |
146 |
'extra_sections': '\n'.join(extra_sections), |
147 |
'authors': '\n'.join(authors), |
148 |
'see_also': ',\n'.join(see_also), |
149 |
'rcsid': '', |
150 |
} |
151 |
with open(output, 'w') as f: |
152 |
f.write(TEMPLATE % data) |
153 |
|
154 |
|
155 |
def _MkMan(applets, applet): |
156 |
"""Trampoline to MkMan for multiprocessing pickle""" |
157 |
output = os.path.join(MKMAN_DIR, '%s.1' % applet) |
158 |
MkMan(applets, applet, output) |
159 |
|
160 |
|
161 |
def main(argv): |
162 |
os.environ['NOCOLOR'] = '1' |
163 |
|
164 |
if not argv: |
165 |
argv = FindApplets() |
166 |
# Support file completion like "qfile.1" or "./qdepends.1" |
167 |
applets = [os.path.basename(x).split('.', 1)[0] for x in argv] |
168 |
|
169 |
p = multiprocessing.Pool() |
170 |
functor = functools.partial(_MkMan, applets) |
171 |
p.map(functor, applets) |
172 |
|
173 |
|
174 |
if __name__ == '__main__': |
175 |
sys.exit(main(sys.argv[1:])) |