chiark / gitweb /
Prep v233: Unmask now needed functions in src/basic
[elogind.git] / tools / make-man-index.py
1 #  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
2 #
3 #  This file is part of elogind.
4 #
5 #  Copyright 2012 Lennart Poettering
6 #  Copyright 2013 Zbigniew Jędrzejewski-Szmek
7 #
8 #  elogind is free software; you can redistribute it and/or modify it
9 #  under the terms of the GNU Lesser General Public License as published by
10 #  the Free Software Foundation; either version 2.1 of the License, or
11 #  (at your option) any later version.
12 #
13 #  elogind is distributed in the hope that it will be useful, but
14 #  WITHOUT ANY WARRANTY; without even the implied warranty of
15 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 #  Lesser General Public License for more details.
17 #
18 #  You should have received a copy of the GNU Lesser General Public License
19 #  along with elogind; If not, see <http://www.gnu.org/licenses/>.
20
21 import collections
22 import sys
23 import re
24 from xml_helper import *
25
26 MDASH = ' — ' if sys.version_info.major >= 3 else ' -- '
27
28 TEMPLATE = '''\
29 <refentry id="elogind.index" conditional="HAVE_PYTHON">
30
31   <refentryinfo>
32     <title>elogind.index</title>
33     <productname>elogind</productname>
34
35     <authorgroup>
36       <author>
37         <contrib>Developer</contrib>
38         <firstname>Lennart</firstname>
39         <surname>Poettering</surname>
40         <email>lennart@poettering.net</email>
41       </author>
42     </authorgroup>
43   </refentryinfo>
44
45   <refmeta>
46     <refentrytitle>elogind.index</refentrytitle>
47     <manvolnum>7</manvolnum>
48   </refmeta>
49
50   <refnamediv>
51     <refname>elogind.index</refname>
52     <refpurpose>List all manpages from the elogind project</refpurpose>
53   </refnamediv>
54 </refentry>
55 '''
56
57 SUMMARY = '''\
58   <refsect1>
59     <title>See Also</title>
60     <para>
61       <citerefentry><refentrytitle>elogind.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
62     </para>
63
64     <para id='counts' />
65   </refsect1>
66 '''
67
68 COUNTS = '\
69 This index contains {count} entries, referring to {pages} individual manual pages.'
70
71
72 def check_id(page, t):
73     id = t.getroot().get('id')
74     if not re.search('/' + id + '[.]', page):
75         raise ValueError("id='{}' is not the same as page name '{}'".format(id, page))
76
77 def make_index(pages):
78     index = collections.defaultdict(list)
79     for p in pages:
80         t = xml_parse(p)
81         check_id(p, t)
82         section = t.find('./refmeta/manvolnum').text
83         refname = t.find('./refnamediv/refname').text
84         purpose = ' '.join(t.find('./refnamediv/refpurpose').text.split())
85         for f in t.findall('./refnamediv/refname'):
86             infos = (f.text, section, purpose, refname)
87             index[f.text[0].upper()].append(infos)
88     return index
89
90 def add_letter(template, letter, pages):
91     refsect1 = tree.SubElement(template, 'refsect1')
92     title = tree.SubElement(refsect1, 'title')
93     title.text = letter
94     para = tree.SubElement(refsect1, 'para')
95     for info in sorted(pages, key=lambda info: str.lower(info[0])):
96         refname, section, purpose, realname = info
97
98         b = tree.SubElement(para, 'citerefentry')
99         c = tree.SubElement(b, 'refentrytitle')
100         c.text = refname
101         d = tree.SubElement(b, 'manvolnum')
102         d.text = section
103
104         b.tail = MDASH + purpose # + ' (' + p + ')'
105
106         tree.SubElement(para, 'sbr')
107
108 def add_summary(template, indexpages):
109     count = 0
110     pages = set()
111     for group in indexpages:
112         count += len(group)
113         for info in group:
114             refname, section, purpose, realname = info
115             pages.add((realname, section))
116
117     refsect1 = tree.fromstring(SUMMARY)
118     template.append(refsect1)
119
120     para = template.find(".//para[@id='counts']")
121     para.text = COUNTS.format(count=count, pages=len(pages))
122
123 def make_page(*xml_files):
124     template = tree.fromstring(TEMPLATE)
125     index = make_index(xml_files)
126
127     for letter in sorted(index):
128         add_letter(template, letter, index[letter])
129
130     add_summary(template, index.values())
131
132     return template
133
134 if __name__ == '__main__':
135     with open(sys.argv[1], 'wb') as f:
136         f.write(xml_print(make_page(*sys.argv[2:])))