rev |
line source |
bos@552
|
1 #!/usr/bin/python
|
bos@552
|
2 #
|
bos@552
|
3 # This is the most horrible of hacks. Pretend you're not looking.</para>
|
bos@552
|
4
|
bos@552
|
5 import cStringIO as StringIO
|
bos@552
|
6 import re, sys
|
bos@552
|
7
|
bos@552
|
8 sections = {
|
bos@552
|
9 'chapter': 'chapter',
|
bos@552
|
10 'section': 'sect1',
|
bos@552
|
11 'subsection': 'sect2',
|
bos@552
|
12 'subsubsection': 'sect3',
|
bos@552
|
13 }
|
bos@552
|
14
|
bos@552
|
15 envs = {
|
bos@552
|
16 'codesample2': 'programlisting',
|
bos@552
|
17 'codesample4': 'programlisting',
|
bos@552
|
18 'enumerate': 'orderedlist',
|
bos@552
|
19 'figure': 'figure',
|
bos@552
|
20 'itemize': 'itemizedlist',
|
bos@552
|
21 'note': 'note',
|
bos@552
|
22 'quote': 'blockquote',
|
bos@552
|
23 }
|
bos@552
|
24
|
bos@552
|
25 def process(ifp, ofp):
|
bos@552
|
26 stack = []
|
bos@552
|
27 para = True
|
bos@552
|
28 inlist = False
|
bos@552
|
29 for line in ifp:
|
bos@552
|
30 if line.startswith('%%% Local Variables:'):
|
bos@552
|
31 break
|
bos@552
|
32 line = (line.rstrip()
|
bos@552
|
33 .replace(' ', ' ')
|
bos@552
|
34 .replace('&', '&')
|
bos@552
|
35 .replace('&emdash;', '&emdash;')
|
bos@552
|
36 .replace('\_', '_')
|
bos@552
|
37 .replace('\{', '{')
|
bos@552
|
38 .replace('\}', '}')
|
bos@552
|
39 .replace('\$', '$')
|
bos@552
|
40 .replace('\%', '%')
|
bos@552
|
41 .replace('\#', '#')
|
bos@552
|
42 .replace('<', '<')
|
bos@552
|
43 .replace('>', '>')
|
bos@552
|
44 .replace('<quote>', '<quote>')
|
bos@552
|
45 .replace("</quote>", '</quote>')
|
bos@552
|
46 .replace('\\', '\\'))
|
bos@552
|
47 line = re.sub(r'\s*\\(?:centering|small)\b\s*', '', line)
|
bos@552
|
48 line = re.sub(r'\\(?:hgrc\\|hgrc)\b',
|
bos@552
|
49 r'<filename role="special"> /.hgrc</filename>', line)
|
bos@552
|
50 line = re.sub(r'\\item\[(?P<key>[^]]+)\]', r'\item \g<key>:', line)
|
bos@552
|
51 line = re.sub(r'\\bug{(?P<id>\d+)}',
|
bos@552
|
52 r'<ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue\g<id>">issue \g<id></ulink>', line)
|
bos@552
|
53 line = re.sub(r'\\cite{([^}]+)}', r'<citation>\1</citation>', line)
|
bos@552
|
54 line = re.sub(r'\\hggopt{(?P<opt>[^}]+)}',
|
bos@552
|
55 r'<option role="hg-opt-global">\g<opt></option>', line)
|
bos@552
|
56 line = re.sub(r'\\hgxopt{(?P<ext>[^}]+)}{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
|
bos@552
|
57 r'<option role="hg-ext-\g<ext>-cmd-\g<cmd>-opt">\g<opt></option>', line)
|
bos@552
|
58 line = re.sub(r'\\hgxcmd{(?P<ext>[^}]+)}{(?P<cmd>[^}]+)}',
|
bos@552
|
59 r'<command role="hg-ext-\g<ext>">\g<cmd></command>', line)
|
bos@552
|
60 line = re.sub(r'\\hgext{(?P<ext>[^}]+)}',
|
bos@552
|
61 r'<literal role="hg-ext">\g<ext></literal>', line)
|
bos@552
|
62 line = re.sub(r'\\hgopt{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
|
bos@552
|
63 r'<option role="hg-opt-\g<cmd>">\g<opt></option>',
|
bos@552
|
64 line)
|
bos@552
|
65 line = re.sub(r'\\cmdopt{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
|
bos@552
|
66 r'<option role="cmd-opt-\g<cmd>">\g<opt></option>',
|
bos@552
|
67 line)
|
bos@552
|
68 line = re.sub(r'\\hgcmd{(?P<cmd>[^}]+)}',
|
bos@552
|
69 r'<command role="hg-cmd">hg \g<cmd></command>', line)
|
bos@552
|
70 line = re.sub(r'\\caption{(?P<text>[^}]+?)}',
|
bos@552
|
71 r'<caption>\g<text></caption>', line)
|
bos@552
|
72 line = re.sub(r'\\grafix{(?P<name>[^}]+)}',
|
bos@552
|
73 r'<mediaobject><imageobject><imagedata fileref="\g<name>"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject>', line)
|
bos@552
|
74 line = re.sub(r'\\envar{(?P<name>[^}]+)}',
|
bos@552
|
75 r'<envar>\g<name></envar>', line)
|
bos@552
|
76 line = re.sub(r'\\rcsection{(?P<sect>[^}]+)}',
|
bos@552
|
77 r'<literal role="rc-\g<sect>">\g<sect></literal>', line)
|
bos@552
|
78 line = re.sub(r'\\rcitem{(?P<sect>[^}]+)}{(?P<name>[^}]+)}',
|
bos@552
|
79 r'<envar role="rc-item-\g<sect>">\g<name></envar>', line)
|
bos@552
|
80 line = re.sub(r'\\dirname{(?P<dir>[^}]+?)}',
|
bos@552
|
81 r'<filename class="directory">\g<dir></filename>', line)
|
bos@552
|
82 line = re.sub(r'\\filename{(?P<file>[^}]+?)}',
|
bos@552
|
83 r'<filename>\g<file></filename>', line)
|
bos@552
|
84 line = re.sub(r'\\tildefile{(?P<file>[^}]+)}',
|
bos@552
|
85 r'<filename role="home"> /\g<file></filename>', line)
|
bos@552
|
86 line = re.sub(r'\\sfilename{(?P<file>[^}]+)}',
|
bos@552
|
87 r'<filename role="special">\g<file></filename>', line)
|
bos@552
|
88 line = re.sub(r'\\sdirname{(?P<dir>[^}]+)}',
|
bos@552
|
89 r'<filename role="special" class="directory">\g<dir></filename>', line)
|
bos@552
|
90 line = re.sub(r'\\interaction{(?P<id>[^}]+)}',
|
bos@552
|
91 r'<!-- &interaction.\g<id>; -->', line)
|
bos@552
|
92 line = re.sub(r'\\excode{(?P<id>[^}]+)}',
|
bos@552
|
93 r'<!-- &example.\g<id>; -->', line)
|
bos@552
|
94 line = re.sub(r'\\pymod{(?P<mod>[^}]+)}',
|
bos@552
|
95 r'<literal role="py-mod">\g<mod></literal>', line)
|
bos@552
|
96 line = re.sub(r'\\pymodclass{(?P<mod>[^}]+)}{(?P<class>[^}]+)}',
|
bos@552
|
97 r'<literal url="py-mod-\g<mod>">\g<class></ulink>', line)
|
bos@552
|
98 line = re.sub(r'\\url{(?P<url>[^}]+)}',
|
bos@552
|
99 r'<ulink url="\g<url>">\g<url></ulink>', line)
|
bos@552
|
100 line = re.sub(r'\\href{(?P<url>[^}]+)}{(?P<text>[^}]+)}',
|
bos@552
|
101 r'<ulink url="\g<url>">\g<text></ulink>', line)
|
bos@552
|
102 line = re.sub(r'\\command{(?P<cmd>[^}]+)}',
|
bos@552
|
103 r'<command>\g<cmd></command>', line)
|
bos@552
|
104 line = re.sub(r'\\option{(?P<opt>[^}]+)}',
|
bos@552
|
105 r'<option>\g<opt></option>', line)
|
bos@552
|
106 line = re.sub(r'\\ref{(?P<id>[^}]+)}', r'<xref id="\g<id>"/>', line)
|
bos@552
|
107 line = re.sub(r'\\emph{(?P<txt>[^}]+)}',
|
bos@552
|
108 r'<emphasis>\g<txt></emphasis>', line)
|
bos@552
|
109 line = re.sub(r'\\texttt{(?P<txt>[^}]+)}',
|
bos@552
|
110 r'<literal>\g<txt></literal>', line)
|
bos@552
|
111 line = re.sub(r'\\textbf{(?P<txt>[^}]+)}',
|
bos@552
|
112 r'<emphasis role="bold">\g<txt></emphasis>', line)
|
bos@552
|
113 line = re.sub(r'\\hook{(?P<name>[^}]+)}',
|
bos@552
|
114 r'<literal role="hook">\g<name></literal>', line)
|
bos@552
|
115 line = re.sub(r'\\tplfilter{(?P<name>[^}]+)}',
|
bos@552
|
116 r'<literal role="template-filter">\g<name></literal>', line)
|
bos@552
|
117 line = re.sub(r'\\tplkword{(?P<name>[^}]+)}',
|
bos@552
|
118 r'<literal role="template-keyword">\g<name></literal>', line)
|
bos@552
|
119 line = re.sub(r'\\tplkwfilt{(?P<tpl>[^}]+)}{(?P<name>[^}]+)}',
|
bos@552
|
120 r'<literal role="template-kw-filt-\g<tpl>">\g<name></literal>', line)
|
bos@552
|
121 line = re.sub(r'\\[vV]erb(.)(?P<txt>[^\1]+?)\1',
|
bos@552
|
122 r'<literal>\g<txt></literal>', line)
|
bos@552
|
123 line = re.sub(r'\\package{(?P<name>[^}]+)}',
|
bos@552
|
124 r'<literal role="package">\g<name></literal>', line)
|
bos@552
|
125 line = re.sub(r'\\hgcmdargs{(?P<cmd>[^}]+)}{(?P<args>[^}]+)}',
|
bos@552
|
126 r'<command role="hg-cmd">hg \g<cmd> \g<args></command>',
|
bos@552
|
127 line)
|
bos@552
|
128 line = re.sub(r'\\cmdargs{(?P<cmd>[^}]+)}{(?P<args>[^}]+)}',
|
bos@552
|
129 r'<command>\g<cmd> \g<args></command>',
|
bos@552
|
130 line)
|
bos@552
|
131 m = re.match(r'\\(chapter|section|subsection|subsubsection){(.*)}', line)
|
bos@552
|
132 if m:
|
bos@552
|
133 kind, content = m.groups()
|
bos@552
|
134 sec = sections[kind]
|
bos@552
|
135 while stack and stack[-1] >= sec:
|
bos@552
|
136 close = stack.pop()
|
bos@552
|
137 print >> ofp, '</%s>' % close
|
bos@552
|
138 stack.append(sec)
|
bos@552
|
139 print >> ofp, '<%s>\n<title>%s</title>' % (sec, content)
|
bos@552
|
140 else:
|
bos@552
|
141 m = re.match(r'\s*\\(begin|end){(?P<sect>[^}]+)}', line)
|
bos@552
|
142 if m:
|
bos@552
|
143 if not para:
|
bos@552
|
144 print >> ofp, '</para>'
|
bos@552
|
145 if inlist:
|
bos@552
|
146 ofp.write('</listitem>')
|
bos@552
|
147 para = True
|
bos@552
|
148 state, env = m.groups()
|
bos@552
|
149 env = envs[env]
|
bos@552
|
150 if state == 'begin':
|
bos@552
|
151 ofp.write('<')
|
bos@552
|
152 if env == 'itemizedlist':
|
bos@552
|
153 inlist = True
|
bos@552
|
154 else:
|
bos@552
|
155 ofp.write('</')
|
bos@552
|
156 if env == 'itemizedlist':
|
bos@552
|
157 inlist = False
|
bos@552
|
158 print >> ofp, env + '>'
|
bos@552
|
159 else:
|
bos@552
|
160 if line.startswith('\\item '):
|
bos@552
|
161 para = True
|
bos@552
|
162 line = line[6:]
|
bos@552
|
163 if line and para:
|
bos@552
|
164 if inlist:
|
bos@552
|
165 ofp.write('<listitem>')
|
bos@552
|
166 ofp.write('<para>')
|
bos@552
|
167 para = False
|
bos@552
|
168 if not line and not para:
|
bos@552
|
169 print >> ofp, '</para>'
|
bos@552
|
170 if inlist:
|
bos@552
|
171 ofp.write('</listitem>')
|
bos@552
|
172 para = True
|
bos@552
|
173 print >> ofp, line
|
bos@552
|
174 while stack:
|
bos@552
|
175 print >> ofp, '</%s>' % stack.pop()
|
bos@552
|
176 ofp.write('\n'.join(['<!--',
|
bos@552
|
177 'local variables: ',
|
bos@552
|
178 'sgml-parent-document: ("00book.xml" "book" "chapter")',
|
bos@552
|
179 'end:',
|
bos@552
|
180 '-->']))
|
bos@552
|
181
|
bos@552
|
182
|
bos@552
|
183 if __name__ == '__main__':
|
bos@552
|
184 for name in sys.argv[1:]:
|
bos@552
|
185 if not name.endswith('.tex'):
|
bos@552
|
186 continue
|
bos@552
|
187 newname = name[:-3] + 'xml'
|
bos@552
|
188 ofp = StringIO.StringIO()
|
bos@552
|
189 process(open(name), ofp)
|
bos@552
|
190 s = ofp.getvalue()
|
bos@552
|
191 s = re.sub('\n+</para>', '</para>', s, re.M)
|
bos@552
|
192 open(newname, 'w').write(s)
|