diff options
author | Mike Frysinger <vapier@gentoo.org> | 2013-09-29 22:12:51 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2013-09-29 22:12:51 +0000 |
commit | d3eb31ff5471d019c2c3989e7bd1cd00ad061df2 (patch) | |
tree | 923174ab32da8194c2c194077468ed55065cbedf /man/mkman.py | |
parent | qcache: include errno when warning about cache read errors (diff) | |
download | portage-utils-d3eb31ff5471d019c2c3989e7bd1cd00ad061df2.tar.gz portage-utils-d3eb31ff5471d019c2c3989e7bd1cd00ad061df2.tar.bz2 portage-utils-d3eb31ff5471d019c2c3989e7bd1cd00ad061df2.zip |
man: rewrite helper script in python to avoid `help2man` as that tends to mangle things
Diffstat (limited to 'man/mkman.py')
-rwxr-xr-x | man/mkman.py | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/man/mkman.py b/man/mkman.py new file mode 100755 index 0000000..cd0fa7a --- /dev/null +++ b/man/mkman.py @@ -0,0 +1,160 @@ +#!/usr/bin/python + +"""Generate man pages for the q applets""" + +from __future__ import print_function + +import datetime +import functools +import glob +import locale +import multiprocessing +import os +import re +import subprocess +import sys + + +MKMAN_DIR = os.path.realpath(os.path.join(__file__, '..')) +FRAGS_DIR = os.path.join(MKMAN_DIR, 'include') + +TOPDIR = os.path.join(MKMAN_DIR, '..') +Q = os.path.join(TOPDIR, 'q') + + +def FindApplets(): + """Return a list of all supported applets""" + applets = os.path.join(TOPDIR, 'applets.sh') + return subprocess.check_output([applets]).splitlines() + + +COMMON_AUTHORS = [ + 'Ned Ludd <solar@gentoo.org>', + 'Mike Frysinger <vapier@gentoo.org>', +] +TEMPLATE = r""".TH %(applet)s "1" "%(date)s" "Gentoo Foundation" "%(applet)s" +.SH NAME +%(applet)s \- %(short_desc)s +.SH SYNOPSIS +.B %(applet)s +\fI%(usage)s\fR +.SH DESCRIPTION +%(description)s +.SH OPTIONS +%(options)s +%(extra_sections)s +.SH "REPORTING BUGS" +Please report bugs via http://bugs.gentoo.org/ +.br +Product: Portage Development; Component: Tools +.SH AUTHORS +.nf +%(authors)s +.fi +.SH "SEE ALSO" +%(see_also)s +""" + +def MkMan(applets, applet, output): + """Generate a man page for |applet| and write it to |output|""" + print('%-10s: generating %s' % (applet, output)) + + # Extract the main use string and description: + # Usage: q <applet> <args> : invoke a portage utility applet + ahelp = subprocess.check_output([Q, applet, '--help']) + lines = ahelp.splitlines() + m = re.search(r'^Usage: %s (.*) : (.*)' % applet, ahelp) + usage = m.group(1) + short_desc = m.group(2) + + authors = COMMON_AUTHORS + see_also = sorted(['.BR %s (1)' % x for x in applets if x != applet]) + + description = '' + desc_file = os.path.join(FRAGS_DIR, '%s.desc' % applet) + if os.path.exists(desc_file): + description = open(desc_file).read().rstrip() + + # Extract all the options + options = [] + for line, i in zip(lines, xrange(len(lines))): + if not line.startswith('Options: '): + continue + + for option in [x.strip().split() for x in lines[i + 1:]]: + flags = [option[0].rstrip(',')] + option.pop(0) + if option[0][0] == '-': + flags += [option[0].rstrip(',')] + option.pop(0) + + if option[0] == '<arg>': + flags = [r'\fB%s\fR \fI<arg>\fR' % x for x in flags] + option.pop(0) + else: + flags = [r'\fB%s\fR' % x for x in flags] + + assert option[0] == '*', 'help line for %s is broken: %r' % (applet, option) + option.pop(0) + + options += [ + '.TP', + ', '.join(flags).replace('-', r'\-'), + ' '.join(option), + ] + break + + # Handle applets that have applets + extra_sections = [] + if 'Currently defined applets:' in ahelp: + alines = lines[lines.index('Currently defined applets:') + 1:] + alines = alines[:alines.index('')] + extra_sections += ( + ['.SH APPLETS', '.nf', + '.B This applet also has sub applets:'] + + alines + + ['.fi'] + ) + + # Handle any fragments this applet has available + for frag in sorted(glob.glob(os.path.join(FRAGS_DIR, '%s-*.include' % applet))): + with open(frag) as f: + extra_sections += [x.rstrip() for x in f.readlines()] + + data = { + 'applet': applet, + 'date': datetime.datetime.now().strftime('%b %Y'), + 'short_desc': short_desc, + 'usage': usage, + 'description': description, + 'options': '\n'.join(options), + 'extra_sections': '\n'.join(extra_sections), + 'authors': '\n'.join(authors), + 'see_also': ',\n'.join(see_also), + 'rcsid': '', + } + with open(output, 'w') as f: + f.write(TEMPLATE % data) + + +def _MkMan(applets, applet): + """Trampoline to MkMan for multiprocessing pickle""" + output = os.path.join(MKMAN_DIR, '%s.1' % applet) + MkMan(applets, applet, output) + + +def main(argv): + os.environ['NOCOLOR'] = '1' + + if not argv: + argv = FindApplets() + # Support file completion like "qfile.1" or "./qdepends.1" + applets = [os.path.basename(x).split('.', 1)[0] for x in argv] + + p = multiprocessing.Pool() + functor = functools.partial(_MkMan, applets) + p.map(functor, applets) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) |