Index: doc/user-guide/genhelp.py
===================================================================
--- doc/user-guide/genhelp.py	(revision 9740ce9c9f432788e88f789e517058139f69bdda)
+++ doc/user-guide/genhelp.py	(revision d6acf79c2e60881fc5a5043bb32b92ee4f9a7f94)
@@ -1,2 +1,20 @@
+#!/usr/bin/env python
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA  02110-1301, USA.
+
+
 import re
 import xml.etree.ElementTree as ET
@@ -6,26 +24,46 @@
 NORMALIZE_RE = re.compile(r"([^<>\s\t])[\s\t]+([^<>\s\t])")
 
-def join(list):
-    return ''.join([str(x) for x in list])
+# Helpers
 
 def normalize(x):
+    """Normalize whitespace of a string.
+
+    The regexp turns any sequence of whitespace into a single space if it's in
+    the middle of the tag text, and then all newlines and tabs are removed,
+    keeping spaces.
+    """
+
     x = NORMALIZE_RE.sub(r"\1 \2", x or '')
     return x.replace("\n", "").replace("\t", "")
 
-def fix_tree(tag, lvl=''):
+def join(list):
+    """Turns any iterator into a string"""
+    return ''.join([str(x) for x in list])
+
+def fix_tree(tag, debug=False, lvl=''):
+    """Walks the XML tree and modifies it in-place fixing various details"""
+
+    # The include tags have an ugly namespace in the tag name. Simplify that.
     if tag.tag.count("XInclude"):
         tag.tag = 'include'
 
-    #print("%s<%s>%r" % (lvl, tag.tag, [tag.text, normalize(tag.text)]))
-
-    for subtag in tag:
-        fix_tree(subtag, lvl + "  ")
-
-    #print("%s</%s>%r" % (lvl, tag.tag, [tag.tail, normalize(tag.tail)]))
-
+    # Print a pretty tree-like representation of the processed tags
+    if debug:
+        print("%s<%s>%r" % (lvl, tag.tag, [tag.text, normalize(tag.text)]))
+
+    for subtag in tag:
+        fix_tree(subtag, debug, lvl + "  ")
+
+    if debug:
+        print("%s</%s>%r" % (lvl, tag.tag, [tag.tail, normalize(tag.tail)]))
+
+    # Actually normalize whitespace
     tag.text = normalize(tag.text)
     tag.tail = normalize(tag.tail)
 
-def parse_file(filename, parent=None):
+
+# Main logic
+
+def process_file(filename, parent=None):
     tree = ET.parse(open(filename)).getroot()
     fix_tree(tree)
@@ -33,4 +71,6 @@
 
 def parse_tag(tag, parent):
+    """Calls a tag_... function based on the tag name"""
+
     fun = globals()["tag_%s" % tag.tag.replace("-", "_")]
     return join(fun(tag, parent))
@@ -44,5 +84,10 @@
     yield tag.tail
 
+
+# Main tag handlers
+
 def handle_subject(tag, parent):
+    """Tag handler for preface, chapter, sect1 and sect2 (aliased below)"""
+
     yield '?%s\n' % tag.attrib['id']
 
@@ -52,4 +97,5 @@
                            "command-list", "ircexample"]:
             if not first:
+                # Spaces between paragraphs
                 yield "\n"
             first = False
@@ -74,4 +120,6 @@
 
 def handle_command(tag, prefix=''):
+    """Tag handler for <bitlbee-command> (called from handle_subject)"""
+
     this_cmd = prefix + tag.attrib['name']
 
@@ -95,4 +143,6 @@
 
 def handle_setting(tag):
+    """Tag handler for <bitlbee-setting> (called from handle_subject)"""
+
     yield "?set %s\n" % tag.attrib['name']
     yield "\x02Type:\x02 %s\n" % tag.attrib["type"]
@@ -109,4 +159,6 @@
     yield "\n%\n"
 
+
+# Aliases for tags that behave like subjects
 tag_preface = handle_subject
 tag_chapter = handle_subject
@@ -114,4 +166,5 @@
 tag_sect2 = handle_subject
 
+# Aliases for tags that don't have any special behavior
 tag_ulink = parse_subtags
 tag_note = parse_subtags
@@ -119,6 +172,9 @@
 tag_ircexample = parse_subtags
 
+
+# Handlers for specific tags
+
 def tag_include(tag, parent):
-    return parse_file(tag.attrib['href'], tag)
+    return process_file(tag.attrib['href'], tag)
 
 def tag_para(tag, parent):
@@ -158,6 +214,7 @@
     yield '\n'
 
+
 def main():
-    txt = parse_file(IN_FILE)
+    txt = process_file(IN_FILE)
     open(OUT_FILE, "w").write(txt)
 
