chiark / gitweb /
man: generate an index of directives
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 9 Aug 2012 16:08:14 +0000 (18:08 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 17 Sep 2012 10:42:22 +0000 (12:42 +0200)
Systemd has a large (and growing) number of manpages. Sometimes it's
not immediately obvious, where to look for a directive. Especially,
when something is described in more than one place. Making sense of
all the settings should be easier with an index.

Makefile.am
make-directive-index.py [new file with mode: 0644]

index 12c2d2e..b0649e4 100644 (file)
@@ -684,8 +684,32 @@ man/index.html: make-man-index.py $(XML_FILES)
        $(AM_V_at)$(MKDIR_P) $(dir $@)
        $(AM_V_GEN)$(PYTHON) $^ > $@
 
+MANPAGES += \
+       man/systemd.directives.5
+
 EXTRA_DIST += \
        man/index.html
+
+XML_DIRECTIVE_FILES = \
+       man/systemd.unit.xml \
+       man/systemd.service.xml \
+       man/systemd.socket.xml \
+       man/systemd.mount.xml \
+       man/systemd.automount.xml \
+       man/systemd.swap.xml \
+       man/systemd.target.xml \
+       man/systemd.path.xml \
+       man/systemd.timer.xml \
+       man/systemd.snapshot.xml \
+       man/systemd.exec.xml
+
+man/systemd.directives.xml: make-directive-index.py $(XML_DIRECTIVE_FILES)
+       $(AM_V_at)$(MKDIR_P) $(dir $@)
+       $(AM_V_GEN)$(PYTHON) $^ > $@
+
+EXTRA_DIST += \
+       man/systemd.directives.xml
+
 endif
 
 endif
@@ -695,7 +719,8 @@ EXTRA_DIST += \
        ${XML_FILES:.xml=.html} \
        $(MANPAGES) \
        $(MANPAGES_ALIAS) \
-       make-man-index.py
+       make-man-index.py \
+       make-directive-index.py
 
 # ------------------------------------------------------------------------------
 noinst_LTLIBRARIES += \
diff --git a/make-directive-index.py b/make-directive-index.py
new file mode 100644 (file)
index 0000000..0c3b67a
--- /dev/null
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+import sys
+import collections
+import xml.etree.ElementTree as tree
+
+TEMPLATE = '''\
+<refentry id="systemd.directives">
+
+        <refentryinfo>
+                <title>systemd.directives</title>
+                <productname>systemd</productname>
+
+                <authorgroup>
+                        <author>
+                                <contrib>Developer</contrib>
+                                <firstname>Zbigniew</firstname>
+                                <surname>Jędrzejewski-Szmek</surname>
+                                <email>zbyszek@in.waw.pl</email>
+                        </author>
+                </authorgroup>
+        </refentryinfo>
+
+        <refmeta>
+                <refentrytitle>systemd.directives</refentrytitle>
+                <manvolnum>5</manvolnum>
+        </refmeta>
+
+        <refnamediv>
+                <refname>systemd.directives</refname>
+                <refpurpose>Index of configuration directives</refpurpose>
+        </refnamediv>
+
+        <refsect1>
+                <title>Unit directives</title>
+
+                <para>Directives for configuring units, used in unit
+                files.</para>
+
+                <variablelist id='unit-directives' />
+        </refsect1>
+</refentry>
+'''
+
+def _extract_directives(directive_groups, page):
+    t = tree.parse(page)
+    section = t.find('./refmeta/manvolnum').text
+    pagename = t.find('./refmeta/refentrytitle').text
+    for variablelist in t.iterfind('.//variablelist'):
+        klass = variablelist.attrib.get('class') or 'unit-directives'
+        stor = directive_groups[klass]
+        for varname in variablelist.iterfind('./varlistentry/term/varname'):
+            text = ''.join(varname.text.partition('=')[:2])
+            stor[text].append((pagename, section))
+
+def _make_section(refentry, name, directives):
+    varlist = refentry.find(".//*[@id='{}']".format(name))
+    for varname, manpages in sorted(directives.items()):
+        entry = tree.SubElement(varlist, 'varlistentry')
+        a = tree.SubElement(tree.SubElement(entry, 'term'), 'varname')
+        a.text = varname
+        para = tree.SubElement(tree.SubElement(entry, 'listitem'), 'para')
+
+        b = None
+        for manpage, manvolume in sorted(manpages):
+                if b is not None:
+                        b.tail = ', '
+                b = tree.SubElement(para, 'citerefentry')
+                c = tree.SubElement(b, 'refentrytitle')
+                c.text = manpage
+                d = tree.SubElement(b, 'manvolnum')
+                d.text = manvolume
+        entry.tail = '\n\n'
+
+def _make_page(directive_groups):
+    """Create an XML tree from directive_groups.
+
+    directive_groups = {
+       'class': {'variable': [('manpage', 'manvolume'), ...],
+                 'variable2': ...},
+       ...
+    }
+    """
+    refentry = tree.fromstring(TEMPLATE)
+
+    for name, directives in directive_groups.items():
+            _make_section(refentry, name, directives)
+
+    return refentry
+
+def make_page(xml_files):
+    "Extract directives from xml_files and return XML index tree."
+    directive_groups = {name:collections.defaultdict(list)
+                        for name in ['unit-directives',
+                                     ]}
+    for page in xml_files:
+        _extract_directives(directive_groups, page)
+
+    return _make_page(directive_groups)
+
+if __name__ == '__main__':
+    tree.dump(make_page(sys.argv[1:]))