~ubuntu-core-dev/debian-installer/ubuntu

767 by Colin Watson
* Add gfxboot help text, localisable via DocBook XML and po4a. Eventually
1
#! /usr/bin/python
2
3
import sys
4
import textwrap
5
import re
6
import xml.dom.minidom
7
8
if len(sys.argv) < 3:
9
    print >>sys.stderr, "Usage: %s help.xml install|live" % sys.argv[0]
10
    sys.exit(1)
11
862 by Colin Watson
* Encapsulate UTF-8 encoding pain differently in
12
# Avoid having to do .encode('UTF-8') everywhere. This is a pain; I wish
13
# Python supported something like "sys.stdout.encoding = 'UTF-8'".
14
def fix_stdout():
15
    import codecs
16
    sys.stdout = codecs.EncodedFile(sys.stdout, 'UTF-8')
17
    def null_decode(input, errors='strict'):
18
        return input, len(input)
19
    sys.stdout.decode = null_decode
20
21
fix_stdout()
22
767 by Colin Watson
* Add gfxboot help text, localisable via DocBook XML and po4a. Eventually
23
document = xml.dom.minidom.parse(sys.argv[1])
24
mode = sys.argv[2]
25
26
text = ""
27
paratext = ""
28
29
def getText(nodelist):
30
    text = ""
31
    for node in nodelist:
32
        if node.nodeType == node.ELEMENT_NODE:
33
            if node.tagName == "link":
34
                text += "<\x12%s\x13%s\x10>" % (node.getAttribute("linkend"),
35
                                                getText(node.childNodes))
36
            elif node.tagName == "ulink":
37
                text += "\x11%s\x10" % node.getAttribute("url")
889 by Colin Watson
* Use <literal> rather than <screen> when referring to the boot: prompt in
38
            elif node.tagName in ("emphasis", "screen", "literal"):
767 by Colin Watson
* Add gfxboot help text, localisable via DocBook XML and po4a. Eventually
39
                text += "\x11%s\x10" % getText(node.childNodes)
40
            elif node.tagName == "userinput":
41
                text += "\x11%s\x10" % getText(node.childNodes).rstrip("\x10")
42
            elif node.tagName == "optional":
43
                text += "[%s]" % getText(node.childNodes)
44
            else:
45
                text += getText(node.childNodes)
46
        elif node.nodeType == node.TEXT_NODE:
47
            text += node.data
48
    return re.sub(re.compile(r'^ +| +$', re.MULTILINE), '', text.strip())
49
50
def fill(text, width=76, indent=''):
51
    squashed = re.sub(r'\n+', ' ', text)
52
    wrapper = textwrap.TextWrapper(width=width, initial_indent=indent,
53
                                   subsequent_indent=indent)
54
    # Eww - but textwrap doesn't provide any other way to turn off
55
    # hyphenation ... This may break in a future version of Python.
56
    wrapper.wordsep_re = re.compile(r'(\s+)')
57
    return wrapper.fill(squashed)
58
59
def stripLinks(text):
60
    return re.sub(r'\x12.+?\x13(.+?)\x10', r'\1', text)
61
62
def handleReference(reference):
63
    for refentry in reference.getElementsByTagName("refentry"):
64
        handleRefEntry(refentry)
65
    sys.stdout.write("\0\n")
66
67
def handleRefEntry(refentry):
68
    global text
69
    sys.stdout.write("\x04")
70
    handleRefNameDiv(refentry.getElementsByTagName("refnamediv")[0])
71
    handleRefSection(refentry.getElementsByTagName("refsection")[0])
862 by Colin Watson
* Encapsulate UTF-8 encoding pain differently in
72
    sys.stdout.write(text.rstrip('\n'))
767 by Colin Watson
* Add gfxboot help text, localisable via DocBook XML and po4a. Eventually
73
    text = ''
74
75
def handleRefNameDiv(refnamediv):
76
    global text
77
    refdescriptor = refnamediv.getElementsByTagName("refdescriptor")[0]
78
    keycap = refdescriptor.getElementsByTagName("keycap")[0]
79
    linkname = getText(keycap.childNodes)
80
    refname = refnamediv.getElementsByTagName("refname")[0]
81
    title = getText(refname.childNodes)
82
    text += "\x12%s\x14%s\x10" % (linkname, title)
83
84
def handleRefSection(refsection):
85
    for node in refsection.childNodes:
86
        if node.nodeType == node.ELEMENT_NODE:
87
            if node.tagName == "title":
88
                handleRefSectionTitle(node)
89
            elif node.tagName == "segmentedlist":
90
                handleSegmentedList(node)
91
            elif node.tagName == "variablelist":
92
                handleVariableList(node)
93
            elif node.tagName == "informalexample":
94
                handleInformalExample(node)
95
            elif node.tagName == "para":
96
                handlePara(node)
97
            else:
98
                handleRefSection(node)
99
100
def handleRefSectionTitle(title):
101
    global text
102
    if len(title.childNodes) > 0:
103
        text += "\x11%s\x10" % getText(title.childNodes)
104
        text += "\n\n"
105
106
def handleSegmentedList(segmentedlist):
107
    global text
108
109
    segmentedlistclass = segmentedlist.getAttribute("class")
110
    if segmentedlistclass == "helpindex":
111
        keywidth = 7
112
    elif segmentedlistclass == "bootparams-hardware":
113
        keywidth = 39
114
    elif segmentedlistclass == "bootparams-disk":
115
        keywidth = 29
116
    else: # segmentedlistclass == "bootparams-installer"
117
        keywidth = 40
118
119
    handleSegmentedListTitle(segmentedlist.getElementsByTagName("title")[0])
120
    handleSegTitles(segmentedlist.getElementsByTagName("segtitle"), keywidth)
121
    handleSegListItems(segmentedlist.getElementsByTagName("seglistitem"),
122
                       keywidth)
123
    text += "\n"
124
125
def handleSegmentedListTitle(title):
126
    global text
127
    if len(title.childNodes) > 0:
128
        text += "\x11%s\x10" % getText(title.childNodes)
129
        text += "\n\n"
130
131
def handleSegTitles(segtitles, keywidth):
132
    global text
133
    if len(segtitles) >= 2:
134
        text += "\x11%-*s%s\x10" % (keywidth, getText(segtitles[0].childNodes),
135
                                    getText(segtitles[1].childNodes))
136
        text += "\n\n"
137
138
def handleSegListItems(seglistitems, keywidth):
139
    global text
140
    for seglistitem in seglistitems:
141
        segs = seglistitem.getElementsByTagName("seg")
142
        key = fill(getText(segs[0].childNodes))
143
        plainkey = stripLinks(key.split("\n")[-1])
144
        topic = getText(segs[1].childNodes)
145
        if len(plainkey) > keywidth - 1:
146
            text += "%s\n%s%s" % (key, " " * keywidth, topic)
147
        else:
148
            text += "%s%s%s" % (key, " " * (keywidth - len(plainkey)), topic)
149
        text += "\n"
150
151
def handleVariableList(variablelist):
152
    global text
153
    for varlistentry in variablelist.getElementsByTagName("varlistentry"):
154
        handleVarListEntry(varlistentry)
155
    text += "\n"
156
157
def handleVarListEntry(varlistentry):
158
    global text
159
    terms = varlistentry.getElementsByTagName("term")
160
    text += ", ".join(map(
161
        lambda term: "\x11%s\x10" % getText(term.childNodes), terms))
162
    text += "\n"
163
    listitem = varlistentry.getElementsByTagName("listitem")[0]
164
    text += fill(getText(listitem.childNodes), 76, '  ')
165
    text += "\n"
166
167
def handleInformalExample(informalexample):
168
    global text
169
    for screen in informalexample.getElementsByTagName("screen"):
170
        text += "  " + getText(screen.childNodes)
171
    text += "\n\n"
172
173
# This whole nobreak business sucks. It's there because
174
# Locale::Po4a::Docbook doesn't want to translate <phrase> elements within
175
# <para>s separately, but instead globs them together into one big msgid.
176
# To work around this, we do <para class="nobreak"> <para class="nobreak">
177
# ... <para>, but of course then we have to make sure to collect all the
178
# text up to the break and make sure to fill it together.
179
def handlePara(para):
180
    global text, paratext
181
    if paratext != "":
182
        lastchar = ord(paratext[-1])
183
        if lastchar >= 32 and lastchar <= 127 and not paratext[-1].isspace():
184
            paratext += " "
185
    paratext += getText(para.childNodes)
186
    if (not para.hasAttribute("class") or
187
        para.getAttribute("class") != "nobreak"):
188
        text += fill(paratext)
189
        text += "\n\n"
190
        paratext = ""
191
192
def preprocess(parent):
193
    global mode
194
    nodelist = parent.childNodes
195
    for node in nodelist:
196
        if node.nodeType == node.ELEMENT_NODE:
197
            if node.hasAttribute("condition"):
886 by Colin Watson
* Adjust help text to refer to gfxboot UI where appropriate (LP: #66881).
198
                match = True
199
                for condition in node.getAttribute("condition").split(';'):
200
                    if condition != "gfxboot" and condition != mode:
201
                        match = False
202
                        break
203
                if not match:
767 by Colin Watson
* Add gfxboot help text, localisable via DocBook XML and po4a. Eventually
204
                    parent.removeChild(node).unlink()
205
                    continue
206
        preprocess(node)
207
208
preprocess(document)
209
210
reference = document.getElementsByTagName("reference")[0]
211
handleReference(reference)