source: doc/user-guide/genhelp.py @ d6acf79

Last change on this file since d6acf79 was d6acf79, checked in by dequis <dx@…>, at 2015-05-16T18:50:49Z

genhelp.py: Comments!

  • Property mode set to 100644
File size: 6.3 KB
Line 
1#!/usr/bin/env python
2#
3# This program is free software; you can redistribute it and/or
4# modify it under the terms of the GNU General Public License
5# as published by the Free Software Foundation; either version 2
6# of the License, or (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 51 Franklin Street, Fifth Floor,
16# Boston, MA  02110-1301, USA.
17
18
19import re
20import xml.etree.ElementTree as ET
21
22IN_FILE = 'help.xml'
23OUT_FILE = 'help.txt'
24NORMALIZE_RE = re.compile(r"([^<>\s\t])[\s\t]+([^<>\s\t])")
25
26# Helpers
27
28def normalize(x):
29    """Normalize whitespace of a string.
30
31    The regexp turns any sequence of whitespace into a single space if it's in
32    the middle of the tag text, and then all newlines and tabs are removed,
33    keeping spaces.
34    """
35
36    x = NORMALIZE_RE.sub(r"\1 \2", x or '')
37    return x.replace("\n", "").replace("\t", "")
38
39def join(list):
40    """Turns any iterator into a string"""
41    return ''.join([str(x) for x in list])
42
43def fix_tree(tag, debug=False, lvl=''):
44    """Walks the XML tree and modifies it in-place fixing various details"""
45
46    # The include tags have an ugly namespace in the tag name. Simplify that.
47    if tag.tag.count("XInclude"):
48        tag.tag = 'include'
49
50    # Print a pretty tree-like representation of the processed tags
51    if debug:
52        print("%s<%s>%r" % (lvl, tag.tag, [tag.text, normalize(tag.text)]))
53
54    for subtag in tag:
55        fix_tree(subtag, debug, lvl + "  ")
56
57    if debug:
58        print("%s</%s>%r" % (lvl, tag.tag, [tag.tail, normalize(tag.tail)]))
59
60    # Actually normalize whitespace
61    tag.text = normalize(tag.text)
62    tag.tail = normalize(tag.tail)
63
64
65# Main logic
66
67def process_file(filename, parent=None):
68    tree = ET.parse(open(filename)).getroot()
69    fix_tree(tree)
70    return parse_tag(tree, parent)
71
72def parse_tag(tag, parent):
73    """Calls a tag_... function based on the tag name"""
74
75    fun = globals()["tag_%s" % tag.tag.replace("-", "_")]
76    return join(fun(tag, parent))
77
78def parse_subtags(tag, parent=None):
79    yield tag.text
80
81    for subtag in tag:
82        yield parse_tag(subtag, tag)
83
84    yield tag.tail
85
86
87# Main tag handlers
88
89def handle_subject(tag, parent):
90    """Tag handler for preface, chapter, sect1 and sect2 (aliased below)"""
91
92    yield '?%s\n' % tag.attrib['id']
93
94    first = True
95    for element in tag:
96        if element.tag in ["para", "variablelist", "simplelist",
97                           "command-list", "ircexample"]:
98            if not first:
99                # Spaces between paragraphs
100                yield "\n"
101            first = False
102
103            if element.attrib.get('title', ''):
104                yield element.attrib['title']
105                yield "\n"
106            yield join(parse_tag(element, tag)).rstrip("\n")
107            yield "\n"
108
109    yield "%\n"
110
111    for element in tag:
112        if element.tag in ["sect1", "sect2"]:
113            yield join(handle_subject(element, tag))
114
115    for element in tag.findall("bitlbee-command"):
116        yield join(handle_command(element))
117
118    for element in tag.findall("bitlbee-setting"):
119        yield join(handle_setting(element))
120
121def handle_command(tag, prefix=''):
122    """Tag handler for <bitlbee-command> (called from handle_subject)"""
123
124    this_cmd = prefix + tag.attrib['name']
125
126    yield "?%s\n" % this_cmd
127    for syntax in tag.findall("syntax"):
128        yield '\x02Syntax:\x02 %s\n' % syntax.text
129
130    yield "\n"
131    yield join(parse_subtags(tag.find("description"))).rstrip()
132    yield "\n"
133
134    for example in tag.findall("ircexample"):
135        yield "\n\x02Example:\x02\n"
136        yield join(parse_subtags(example)).rstrip()
137        yield "\n"
138
139    yield "%\n"
140
141    for element in tag.findall("bitlbee-command"):
142        yield join(handle_command(element, this_cmd + " "))
143
144def handle_setting(tag):
145    """Tag handler for <bitlbee-setting> (called from handle_subject)"""
146
147    yield "?set %s\n" % tag.attrib['name']
148    yield "\x02Type:\x02 %s\n" % tag.attrib["type"]
149    yield "\x02Scope:\x02 %s\n" % tag.attrib["scope"]
150
151    if tag.find("default") is not None:
152        yield "\x02Default:\x02 %s\n" % tag.findtext("default")
153
154    if tag.find("possible-values") is not None:
155        yield "\x02Possible Values:\x02 %s\n" % tag.findtext("possible-values")
156
157    yield "\n"
158    yield join(parse_subtags(tag.find("description"))).rstrip()
159    yield "\n%\n"
160
161
162# Aliases for tags that behave like subjects
163tag_preface = handle_subject
164tag_chapter = handle_subject
165tag_sect1 = handle_subject
166tag_sect2 = handle_subject
167
168# Aliases for tags that don't have any special behavior
169tag_ulink = parse_subtags
170tag_note = parse_subtags
171tag_book = parse_subtags
172tag_ircexample = parse_subtags
173
174
175# Handlers for specific tags
176
177def tag_include(tag, parent):
178    return process_file(tag.attrib['href'], tag)
179
180def tag_para(tag, parent):
181    return join(parse_subtags(tag)) + "\n\n"
182
183def tag_emphasis(tag, parent):
184    return "\x02%s\x02%s" % (tag.text, tag.tail)
185
186def tag_ircline(tag, parent):
187    return "\x02<%s>\x02 %s\n" % (tag.attrib['nick'], join(parse_subtags(tag)))
188
189def tag_ircaction(tag, parent):
190    return "\x02* %s\x02 %s\n" % (tag.attrib['nick'], join(parse_subtags(tag)))
191
192def tag_command_list(tag, parent):
193    yield "These are all root commands. See \x02help <command name>\x02 " \
194          "for more details on each command.\n\n"
195
196    for subtag in parent.findall("bitlbee-command"):
197        yield " * \x02%s\x02 - %s\n" % \
198            (subtag.attrib['name'],
199             subtag.findtext("short-description"))
200
201    yield "\nMost commands can be shortened. For example instead of " \
202          "\x02account list\x02, try \x02ac l\x02.\n\n"
203
204def tag_variablelist(tag, parent):
205    for subtag in tag:
206        yield " \x02%s\x02 - %s\n" % \
207            (subtag.findtext("term"),
208             join(parse_subtags(subtag.find("listitem/para"))))
209    yield '\n'
210
211def tag_simplelist(tag, parent):
212    for subtag in tag:
213        yield " - %s\n" % join(parse_subtags(subtag))
214    yield '\n'
215
216
217def main():
218    txt = process_file(IN_FILE)
219    open(OUT_FILE, "w").write(txt)
220
221if __name__ == '__main__':
222    main()
Note: See TracBrowser for help on using the repository browser.