blob: 404234f68e4960913c5a3bde221064e115f78a96 [file] [log] [blame]
Fred Drakebfc18bd2002-05-03 04:50:51 +00001;;; py2texi.el -- Conversion of Python LaTeX documentation to Texinfo
2
Thomas Wouters89f507f2006-12-13 04:49:30 +00003;; Copyright (C) 2006 Jeroen Dekkers <jeroen@dekkers.cx>
Fred Drakebfc18bd2002-05-03 04:50:51 +00004;; Copyright (C) 1998, 1999, 2001, 2002 Milan Zamazal
5
6;; Author: Milan Zamazal <pdm@zamazal.org>
7;; Version: $Id$
8;; Keywords: python
9
10;; COPYRIGHT NOTICE
11;;
12;; This program is free software; you can redistribute it and/or modify it
13;; under the terms of the GNU General Public License as published by the Free
14;; Software Foundation; either version 2, or (at your option) any later
15;; version.
16;;
17;; This program is distributed in the hope that it will be useful, but
18;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20;; for more details.
21;;
22;; You can find the GNU General Public License at
23;; http://www.gnu.org/copyleft/gpl.html
24;; or you can write to the Free Software Foundation, Inc., 59 Temple Place,
25;; Suite 330, Boston, MA 02111-1307, USA.
26
27;;; Commentary:
28
29;; This is a Q&D hack for conversion of Python manuals to on-line help format.
30;; I desperately needed usable online documenta for Python, so I wrote this.
31;; The result code is ugly and need not contain complete information from
32;; Python manuals. I apologize for my ignorance, especially ignorance to
33;; python.sty. Improvements of this convertor are welcomed.
34
35;; How to use it:
36;; Load this file and apply `M-x py2texi'. You will be asked for name of a
37;; file to be converted.
38
39;; Where to find it:
40;; New versions of this code might be found at
41;; http://www.zamazal.org/software/python/py2texi/ .
42
43;;; Code:
44
45
46(require 'texinfo)
47(eval-when-compile
48 (require 'cl))
49
50
51(defvar py2texi-python-version "2.2"
52 "What to substitute for the \\version macro.")
53
54(defvar py2texi-python-short-version
55 (progn
56 (string-match "[0-9]+\\.[0-9]+" py2texi-python-version)
57 (match-string 0 py2texi-python-version))
58 "Short version number, usually set by the LaTeX commands.")
59
Fred Drake66abcee2002-11-13 19:31:04 +000060(defvar py2texi-texi-file-name nil
61 "If non-nil, that string is used as the name of the Texinfo file.
62Otherwise a generated Texinfo file name is used.")
63
64(defvar py2texi-info-file-name nil
65 "If non-nil, that string is used as the name of the Info file.
66Otherwise a generated Info file name is used.")
67
Fred Drakebfc18bd2002-05-03 04:50:51 +000068(defvar py2texi-stop-on-problems nil
69 "*If non-nil, stop when you encouter soft problem.")
70
71(defconst py2texi-environments
72 '(("abstract" 0 "@quotation" "@end quotation\n")
73 ("center" 0 "" "")
74 ("cfuncdesc" 3
75 (progn (setq findex t)
76 "\n@table @code\n@item \\1 \\2(\\3)\n@findex \\2\n")
Fred Drake66abcee2002-11-13 19:31:04 +000077 "@end table\n")
78 ("cmemberdesc" 3
79 "\n@table @code\n@item \\2 \\3\n"
80 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +000081 ("classdesc" 2
82 (progn (setq obindex t)
83 "\n@table @code\n@item \\1(\\2)\n@obindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +000084 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +000085 ("classdesc*" 1
86 (progn (setq obindex t)
87 "\n@table @code\n@item \\1\n@obindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +000088 "@end table\n")
Fred Drake66758812003-07-02 14:44:08 +000089 ("comment" 0 "\n@ignore\n" "\n@end ignore\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +000090 ("csimplemacrodesc" 1
91 (progn (setq cindex t)
92 "\n@table @code\n@item \\1\n@cindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +000093 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +000094 ("ctypedesc" 1
95 (progn (setq cindex t)
96 "\n@table @code\n@item \\1\n@cindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +000097 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +000098 ("cvardesc" 2
99 (progn (setq findex t)
100 "\n@table @code\n@item \\1 \\2\n@findex \\2\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000101 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000102 ("datadesc" 1
103 (progn (setq findex t)
104 "\n@table @code\n@item \\1\n@findex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000105 "@end table\n")
106 ("datadescni" 1 "\n@table @code\n@item \\1\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000107 ("definitions" 0 "@table @dfn" "@end table\n")
108 ("description" 0 "@table @samp" "@end table\n")
109 ("displaymath" 0 "" "")
110 ("document" 0
111 (concat "@defcodeindex mo\n"
112 "@defcodeindex ob\n"
113 "@titlepage\n"
114 (format "@title " title "\n")
115 (format "@author " author "\n")
116 "@page\n"
117 author-address
118 "@end titlepage\n"
119 "@node Top, , , (dir)\n")
120 (concat "@indices\n"
121 "@contents\n"
122 "@bye\n"))
123 ("enumerate" 0 "@enumerate" "@end enumerate")
Fred Drake3b095582003-07-02 14:22:48 +0000124 ("envdesc" 2 (concat "\n@table @code"
125 "\n@item @backslash{}begin@{\\1@}\\2")
126 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000127 ("excdesc" 1
128 (progn (setq obindex t)
129 "\n@table @code\n@item \\1\n@obindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000130 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000131 ("excclassdesc" 2
132 (progn (setq obindex t)
133 "\n@table @code\n@item \\1(\\2)\n@obindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000134 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000135 ("flushleft" 0 "" "")
Fred Drake66abcee2002-11-13 19:31:04 +0000136 ("fulllineitems" 0 "\n@table @code\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000137 ("funcdesc" 2
138 (progn (setq findex t)
139 "\n@table @code\n@item \\1(\\2)\n@findex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000140 "@end table\n")
141 ("funcdescni" 2 "\n@table @code\n@item \\1(\\2)\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000142 ("itemize" 0 "@itemize @bullet" "@end itemize\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000143 ("list" 2 "\n@table @code\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000144 ("longtableii" 4 (concat "@multitable @columnfractions .5 .5\n"
145 "@item \\3 @tab \\4\n"
146 "@item ------- @tab ------ \n")
147 "@end multitable\n")
148 ("longtableiii" 5 (concat "@multitable @columnfractions .33 .33 .33\n"
149 "@item \\3 @tab \\4 @tab \\5\n"
150 "@item ------- @tab ------ @tab ------\n")
151 "@end multitable\n")
Fred Drake3b095582003-07-02 14:22:48 +0000152 ("macrodesc" 2 (concat "\n@table @code"
153 "\n@item \\1@{\\2@}")
154 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000155 ("memberdesc" 1
156 (progn (setq findex t)
157 "\n@table @code\n@item \\1\n@findex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000158 "@end table\n")
159 ("memberdescni" 1 "\n@table @code\n@item \\1\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000160 ("methoddesc" 2
161 (progn (setq findex t)
162 "\n@table @code\n@item \\1(\\2)\n@findex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000163 "@end table\n")
164 ("methoddescni" 2 "\n@table @code\n@item \\1(\\2)\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000165 ("notice" 0 "@emph{Notice:} " "")
166 ("opcodedesc" 2
167 (progn (setq findex t)
168 "\n@table @code\n@item \\1 \\2\n@findex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000169 "@end table\n")
170 ("productionlist" 0 "\n@table @code\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000171 ("quotation" 0 "@quotation" "@end quotation")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000172 ("quote" 0 "@quotation" "@end quotation")
Fred Drake66abcee2002-11-13 19:31:04 +0000173 ("seealso" 0 "See also:\n@table @emph\n" "@end table\n")
174 ("seealso*" 0 "@table @emph\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000175 ("sloppypar" 0 "" "")
176 ("small" 0 "" "")
177 ("tableii" 4 (concat "@multitable @columnfractions .5 .5\n"
178 "@item \\3 @tab \\4\n"
179 "@item ------- @tab ------ \n")
180 "@end multitable\n")
181 ("tableiii" 5 (concat "@multitable @columnfractions .33 .33 .33\n"
182 "@item \\3 @tab \\4 @tab \\5\n"
183 "@item ------- @tab ------ @tab ------\n")
184 "@end multitable\n")
185 ("tableiv" 6 (concat
186 "@multitable @columnfractions .25 .25 .25 .25\n"
187 "@item \\3 @tab \\4 @tab \\5 @tab \\6\n"
188 "@item ------- @tab ------- @tab ------- @tab -------\n")
189 "@end multitable\n")
190 ("tablev" 7 (concat
191 "@multitable @columnfractions .20 .20 .20 .20 .20\n"
192 "@item \\3 @tab \\4 @tab \\5 @tab \\6 @tab \\7\n"
193 "@item ------- @tab ------- @tab ------- @tab ------- @tab -------\n")
Fred Drake85002632003-07-16 03:35:41 +0000194 "@end multitable\n")
195 ("alltt" 0 "@example" "@end example")
196 )
Fred Drakebfc18bd2002-05-03 04:50:51 +0000197 "Associative list defining substitutions for environments.
198Each list item is of the form (ENVIRONMENT ARGNUM BEGIN END) where:
199- ENVIRONMENT is LaTeX environment name
200- ARGNUM is number of (required) macro arguments
201- BEGIN is substitution for \begin{ENVIRONMENT}
202- END is substitution for \end{ENVIRONMENT}
203Both BEGIN and END are evaled. Moreover, you can reference arguments through
204\N regular expression notation in strings of BEGIN.")
205
206(defconst py2texi-commands
Fred Drake7769bb92003-07-16 03:16:34 +0000207 '(("AA" 0 "@AA{}")
208 ("aa" 0 "@aa{}")
209 ("ABC" 0 "ABC")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000210 ("appendix" 0 (progn (setq appendix t) ""))
211 ("ASCII" 0 "ASCII")
212 ("author" 1 (progn (setq author (match-string 1 string)) ""))
213 ("authoraddress" 1
214 (progn (setq author-address (match-string 1 string)) ""))
215 ("b" 1 "@w{\\1}")
Andrew M. Kuchlinge970d2a2004-07-17 14:43:32 +0000216 ("backslash" 0 "@backslash{}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000217 ("bf" 0 "@destroy")
218 ("bifuncindex" 1 (progn (setq findex t) "@findex{\\1}"))
219 ("C" 0 "C")
220 ("c" 0 "@,")
221 ("catcode" 0 "")
222 ("cdata" 1 "@code{\\1}")
223 ("centerline" 1 "@center \\1")
Fred Drake66abcee2002-11-13 19:31:04 +0000224 ("cfuncline" 3 "@itemx \\1 \\2(\\3)\n@findex \\2")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000225 ("cfunction" 1 "@code{\\1}")
226 ("chapter" 1 (format "@node \\1\n@%s \\1\n"
227 (if appendix "appendix" "chapter")))
228 ("chapter*" 1 "@node \\1\n@unnumbered \\1\n")
229 ("character" 1 "@samp{\\1}")
230 ("citetitle" 1 "@ref{Top,,,\\1}")
231 ("class" 1 "@code{\\1}")
Fred Drake66abcee2002-11-13 19:31:04 +0000232 ("cmemberline" 3 "@itemx \\2 \\3\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000233 ("code" 1 "@code{\\1}")
234 ("command" 1 "@command{\\1}")
235 ("constant" 1 "@code{\\1}")
236 ("copyright" 1 "@copyright{}")
237 ("Cpp" 0 "C++")
Fred Draked805fef2002-06-27 18:38:06 +0000238 ("csimplemacro" 1 "@code{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000239 ("ctype" 1 "@code{\\1}")
240 ("dataline" 1 (progn (setq findex t) "@item \\1\n@findex \\1\n"))
241 ("date" 1 "\\1")
242 ("declaremodule" 2 (progn (setq cindex t) "@label{\\2}@cindex{\\2}"))
Fred Drake346803e2005-03-10 05:02:18 +0000243 ("deprecated" 2 "@emph{This is deprecated in Python \\1. \\2}\n\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000244 ("dfn" 1 "@dfn{\\1}")
245 ("documentclass" 1 py2texi-magic)
246 ("e" 0 "@backslash{}")
247 ("else" 0 (concat "@end ifinfo\n@" (setq last-if "iftex")))
Fred Drake3b095582003-07-02 14:22:48 +0000248 ("env" 1 "@code{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000249 ("EOF" 0 "@code{EOF}")
250 ("email" 1 "@email{\\1}")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000251 ("em" 1 "@emph{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000252 ("emph" 1 "@emph{\\1}")
Fred Drake0bb242b2003-07-16 03:44:48 +0000253 ("envvar" 1 "@env{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000254 ("exception" 1 "@code{\\1}")
255 ("exindex" 1 (progn (setq obindex t) "@obindex{\\1}"))
Thomas Wouters89f507f2006-12-13 04:49:30 +0000256 ("fi" 0 (if (equal last-if "ifx") "" (concat "@end " last-if)))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000257 ("file" 1 "@file{\\1}")
Fred Drake3b095582003-07-02 14:22:48 +0000258 ("filenq" 1 "@file{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000259 ("filevar" 1 "@file{@var{\\1}}")
260 ("footnote" 1 "@footnote{\\1}")
261 ("frac" 0 "")
262 ("funcline" 2 (progn (setq findex t) "@item \\1 \\2\n@findex \\1"))
263 ("funclineni" 2 "@item \\1 \\2")
264 ("function" 1 "@code{\\1}")
265 ("grammartoken" 1 "@code{\\1}")
Fred Drakecc933af2005-03-10 03:59:35 +0000266 ("guilabel" 1 "@strong{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000267 ("hline" 0 "")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000268 ("ifx" 0 (progn (setq last-if "ifx") ""))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000269 ("ifhtml" 0 (concat "@" (setq last-if "ifinfo")))
270 ("iftexi" 0 (concat "@" (setq last-if "ifinfo")))
271 ("index" 1 (progn (setq cindex t) "@cindex{\\1}"))
272 ("indexii" 2 (progn (setq cindex t) "@cindex{\\1 \\2}"))
273 ("indexiii" 3 (progn (setq cindex t) "@cindex{\\1 \\2 \\3}"))
274 ("indexiv" 3 (progn (setq cindex t) "@cindex{\\1 \\2 \\3 \\4}"))
275 ("infinity" 0 "@emph{infinity}")
276 ("it" 0 "@destroy")
277 ("kbd" 1 "@key{\\1}")
278 ("keyword" 1 "@code{\\1}")
279 ("kwindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
280 ("label" 1 "@label{\\1}")
281 ("Large" 0 "")
282 ("LaTeX" 0 "La@TeX{}")
283 ("large" 0 "")
284 ("ldots" 0 "@dots{}")
285 ("leftline" 1 "\\1")
Fred Drake346803e2005-03-10 05:02:18 +0000286 ("leq" 0 "<=")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000287 ("lineii" 2 "@item \\1 @tab \\2")
288 ("lineiii" 3 "@item \\1 @tab \\2 @tab \\3")
289 ("lineiv" 4 "@item \\1 @tab \\2 @tab \\3 @tab \\4")
290 ("linev" 5 "@item \\1 @tab \\2 @tab \\3 @tab \\4 @tab \\5")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000291 ("locallinewidth" 0 "")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000292 ("localmoduletable" 0 "")
293 ("longprogramopt" 1 "@option{--\\1}")
Fred Drake3b095582003-07-02 14:22:48 +0000294 ("macro" 1 "@code{@backslash{}\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000295 ("mailheader" 1 "@code{\\1}")
296 ("makeindex" 0 "")
297 ("makemodindex" 0 "")
298 ("maketitle" 0 (concat "@top " title "\n"))
299 ("makevar" 1 "@code{\\1}")
300 ("manpage" 2 "@samp{\\1(\\2)}")
301 ("mbox" 1 "@w{\\1}")
302 ("member" 1 "@code{\\1}")
303 ("memberline" 1 "@item \\1\n@findex \\1\n")
304 ("menuselection" 1 "@samp{\\1}")
305 ("method" 1 "@code{\\1}")
306 ("methodline" 2 (progn (setq moindex t) "@item \\1(\\2)\n@moindex \\1\n"))
307 ("methodlineni" 2 "@item \\1(\\2)\n")
308 ("mimetype" 1 "@samp{\\1}")
309 ("module" 1 "@samp{\\1}")
Fred Drake66abcee2002-11-13 19:31:04 +0000310 ("moduleauthor" 2 "")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000311 ("modulesynopsis" 1 "\\1")
312 ("moreargs" 0 "@dots{}")
313 ("n" 0 "@backslash{}n")
314 ("newcommand" 2 "")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000315 ("newlength" 1 "")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000316 ("newsgroup" 1 "@samp{\\1}")
317 ("nodename" 1
318 (save-excursion
319 (save-match-data
320 (re-search-backward "^@node "))
321 (delete-region (point) (save-excursion (end-of-line) (point)))
322 (insert "@node " (match-string 1 string))
323 ""))
324 ("noindent" 0 "@noindent ")
325 ("note" 1 "@emph{Note:} \\1")
326 ("NULL" 0 "@code{NULL}")
327 ("obindex" 1 (progn (setq obindex t) "@obindex{\\1}"))
328 ("opindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
329 ("option" 1 "@option{\\1}")
330 ("optional" 1 "[\\1]")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000331 ("paragraph" 1 "@subsubheading \\1")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000332 ("pep" 1 (progn (setq cindex t) "PEP@ \\1@cindex PEP \\1\n"))
333 ("pi" 0 "pi")
334 ("platform" 1 "")
335 ("plusminus" 0 "+-")
336 ("POSIX" 0 "POSIX")
337 ("production" 2 "@item \\1 \\2")
Fred Drake66abcee2002-11-13 19:31:04 +0000338 ("productioncont" 1 "@item @w{} \\1")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000339 ("program" 1 "@command{\\1}")
340 ("programopt" 1 "@option{\\1}")
341 ("protect" 0 "")
342 ("pytype" 1 "@code{\\1}")
343 ("ref" 1 "@ref{\\1}")
344 ("refbimodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
345 ("refmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
346 ("refmodule" 1 "@samp{\\1}")
347 ("refstmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
348 ("regexp" 1 "\"\\1\"")
349 ("release" 1
350 (progn (setq py2texi-python-version (match-string 1 string)) ""))
351 ("renewcommand" 2 "")
352 ("rfc" 1 (progn (setq cindex t) "RFC@ \\1@cindex RFC \\1\n"))
353 ("rm" 0 "@destroy")
354 ("samp" 1 "@samp{\\1}")
355 ("section" 1 (let ((str (match-string 1 string)))
356 (save-match-data
357 (if (string-match "\\(.*\\)[ \t\n]*---[ \t\n]*\\(.*\\)"
358 str)
359 (format
360 "@node %s\n@section %s\n"
361 (py2texi-backslash-quote (match-string 1 str))
362 (py2texi-backslash-quote (match-string 2 str)))
363 "@node \\1\n@section \\1\n"))))
Fred Drake66abcee2002-11-13 19:31:04 +0000364 ("sectionauthor" 2 "")
Fred Drakecc933af2005-03-10 03:59:35 +0000365 ("seelink" 3 "\n@table @url\n@item @strong{\\1}\n(\\2)\n\\3\n@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000366 ("seemodule" 2 "@ref{\\1} \\2")
367 ("seepep" 3 "\n@table @strong\n@item PEP\\1 \\2\n\\3\n@end table\n")
368 ("seerfc" 3 "\n@table @strong\n@item RFC\\1 \\2\n\\3\n@end table\n")
369 ("seetext" 1 "\\1")
370 ("seetitle" 1 "@cite{\\1}")
371 ("seeurl" 2 "\n@table @url\n@item \\1\n\\2\n@end table\n")
372 ("setindexsubitem" 1 (progn (setq cindex t) "@cindex \\1"))
Thomas Wouters89f507f2006-12-13 04:49:30 +0000373 ("setlength" 2 "")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000374 ("setreleaseinfo" 1 (progn (setq py2texi-releaseinfo "")))
375 ("setshortversion" 1
376 (progn (setq py2texi-python-short-version (match-string 1 string)) ""))
377 ("shortversion" 0 py2texi-python-short-version)
378 ("sqrt" 0 "")
379 ("stindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
380 ("stmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
381 ("strong" 1 "@strong{\\1}")
382 ("sub" 0 "/")
383 ("subsection" 1 "@node \\1\n@subsection \\1\n")
384 ("subsubsection" 1 "@node \\1\n@subsubsection \\1\n")
385 ("sum" 0 "")
386 ("tableofcontents" 0 "")
387 ("term" 1 "@item \\1")
Fred Drake3b095582003-07-02 14:22:48 +0000388 ("TeX" 0 "@TeX{}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000389 ("textasciitilde" 0 "~")
390 ("textasciicircum" 0 "^")
391 ("textbackslash" 0 "@backslash{}")
Fred Drake346803e2005-03-10 05:02:18 +0000392 ("textbar" 0 "|")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000393 ("textbf" 1 "@strong{\\1}")
394 ("texteuro" 0 "@euro{}")
Fred Drake346803e2005-03-10 05:02:18 +0000395 ; Unfortunately, this alternate spelling doesn't actually apply to
396 ; the usage found in Python Tutorial, which actually requires a
397 ; Euro symbol to make sense, so this is commented out as well.
398 ; ("texteuro" 0 "Euro ")
Fred Draked805fef2002-06-27 18:38:06 +0000399 ("textgreater" 0 ">")
Fred Drake346803e2005-03-10 05:02:18 +0000400 ("textit" 1 "@i{\\1}")
Fred Draked805fef2002-06-27 18:38:06 +0000401 ("textless" 0 "<")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000402 ("textrm" 1 "\\1")
403 ("texttt" 1 "@code{\\1}")
404 ("textunderscore" 0 "_")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000405 ("tilde" 0 "~")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000406 ("title" 1 (progn (setq title (match-string 1 string)) "@settitle \\1"))
407 ("today" 0 "@today{}")
408 ("token" 1 "@code{\\1}")
409 ("tt" 0 "@destroy")
410 ("ttindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
411 ("u" 0 "@backslash{}u")
412 ("ulink" 2 "\\1")
413 ("UNIX" 0 "UNIX")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000414 ("undefined" 0 "")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000415 ("unspecified" 0 "@dots{}")
416 ("url" 1 "@url{\\1}")
417 ("usepackage" 1 "")
418 ("var" 1 "@var{\\1}")
419 ("verbatiminput" 1 "@code{\\1}")
420 ("version" 0 py2texi-python-version)
421 ("versionadded" 1 "@emph{Added in Python version \\1}")
422 ("versionchanged" 1 "@emph{Changed in Python version \\1}")
423 ("vskip" 1 "")
424 ("vspace" 1 "")
425 ("warning" 1 "@emph{\\1}")
426 ("withsubitem" 2 "\\2")
427 ("XXX" 1 "@strong{\\1}"))
428 "Associative list of command substitutions.
429Each list item is of the form (COMMAND ARGNUM SUBSTITUTION) where:
430- COMMAND is LaTeX command name
431- ARGNUM is number of (required) command arguments
432- SUBSTITUTION substitution for the command. It is evaled and you can
433 reference command arguments through the \\N regexp notation in strings.")
434
435(defvar py2texi-magic "@documentclass\n"
436 "\"Magic\" string for auxiliary insertion at the beginning of document.")
437
438(defvar py2texi-dirs '("./" "../texinputs/")
439 "Where to search LaTeX input files.")
440
441(defvar py2texi-buffer "*py2texi*"
442 "The name of a buffer where Texinfo is generated.")
443
444(defconst py2texi-xemacs (string-match "^XEmacs" (emacs-version))
445 "Running under XEmacs?")
446
447
448(defmacro py2texi-search (regexp &rest body)
449 `(progn
450 (goto-char (point-min))
451 (while (re-search-forward ,regexp nil t)
452 ,@body)))
453
454(defmacro py2texi-search-safe (regexp &rest body)
455 `(py2texi-search ,regexp
456 (unless (py2texi-protected)
457 ,@body)))
458
459
460(defun py2texi-message (message)
461 "Report message and stop if `py2texi-stop-on-problems' is non-nil."
462 (if py2texi-stop-on-problems
463 (error message)
464 (message message)))
465
466
467(defun py2texi-backslash-quote (string)
468 "Double backslahes in STRING."
469 (let ((i 0))
470 (save-match-data
471 (while (setq i (string-match "\\\\" string i))
472 (setq string (replace-match "\\\\\\\\" t nil string))
473 (setq i (+ i 2))))
474 string))
475
476
477(defun py2texi (file)
478 "Convert Python LaTeX documentation FILE to Texinfo."
479 (interactive "fFile to convert: ")
480 (switch-to-buffer (get-buffer-create py2texi-buffer))
481 (erase-buffer)
482 (insert-file file)
483 (let ((case-fold-search nil)
484 (title "")
485 (author "")
486 (author-address "")
487 (appendix nil)
488 (findex nil)
489 (obindex nil)
490 (cindex nil)
491 (moindex nil)
492 last-if)
493 (py2texi-process-verbatims)
494 (py2texi-process-comments)
495 (py2texi-process-includes)
496 (py2texi-process-funnyas)
497 (py2texi-process-environments)
498 (py2texi-process-commands)
499 (py2texi-fix-indentation)
500 (py2texi-fix-nodes)
501 (py2texi-fix-references)
502 (py2texi-fix-indices)
503 (py2texi-process-simple-commands)
504 (py2texi-fix-fonts)
505 (py2texi-fix-braces)
506 (py2texi-fix-backslashes)
507 (py2texi-destroy-empties)
508 (py2texi-fix-newlines)
509 (py2texi-adjust-level))
Fred Drake66abcee2002-11-13 19:31:04 +0000510 (let* ((texi-file-name (or py2texi-texi-file-name
511 (py2texi-texi-file-name file)))
512 (info-file-name (or py2texi-info-file-name
513 (py2texi-info-file-name texi-file-name))))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000514 (goto-char (point-min))
515 (when (looking-at py2texi-magic)
516 (delete-region (point) (progn (beginning-of-line 2) (point)))
517 (insert "\\input texinfo @c -*-texinfo-*-\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000518 (insert "@setfilename " info-file-name))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000519 (when (re-search-forward "@chapter" nil t)
520 (texinfo-all-menus-update t))
521 (goto-char (point-min))
Fred Drake66abcee2002-11-13 19:31:04 +0000522 (write-file texi-file-name)
523 (message (format "You can apply `makeinfo %s' now." texi-file-name))))
524
525
526(defun py2texi-texi-file-name (filename)
527 "Generate name of Texinfo file from original file name FILENAME."
528 (concat filename
529 (if (string-match "\\.tex$" filename) "i" ".texi")))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000530
531
532(defun py2texi-info-file-name (filename)
533 "Generate name of info file from original file name FILENAME."
534 (setq filename (expand-file-name filename))
535 (let ((directory (file-name-directory filename))
536 (basename (file-name-nondirectory filename)))
537 (concat directory "python-"
538 (substring basename 0 (- (length basename) 4)) "info")))
539
540
541(defun py2texi-process-verbatims ()
542 "Process and protect verbatim environments."
543 (let (delimiter
544 beg
545 end)
546 (py2texi-search-safe "\\\\begin{\\(verbatim\\|displaymath\\)}"
Thomas Wouters89f507f2006-12-13 04:49:30 +0000547 (when (save-excursion
548 ; Make sure we aren't looking at a commented out version
549 ; of a verbatim environment
550 (beginning-of-line)
551 (not (looking-at "%")))
552 (replace-match "@example ")
553 (setq beg (copy-marker (point) nil))
554 (re-search-forward "\\\\end{\\(verbatim\\|displaymath\\)}")
555 (setq end (copy-marker (match-beginning 0) nil))
556 (replace-match "@end example")
557 (py2texi-texinfo-escape beg end)
558 (put-text-property (- beg (length "@example "))
559 (+ end (length "@end example"))
560 'py2texi-protected t)))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000561 (py2texi-search-safe "\\\\verb\\([^a-z]\\)"
562 (setq delimiter (match-string 1))
563 (replace-match "@code{")
564 (setq beg (copy-marker (point) nil))
565 (re-search-forward (regexp-quote delimiter))
566 (setq end (copy-marker (match-beginning 0) nil))
567 (replace-match "}")
568 (put-text-property (- beg (length "@code{")) (+ end (length "}"))
569 'py2texi-protected t)
570 (py2texi-texinfo-escape beg end))))
571
572
573(defun py2texi-process-comments ()
574 "Remove comments."
575 (let (point)
576 (py2texi-search-safe "%"
577 (setq point (point))
578 (when (save-excursion
579 (re-search-backward "\\(^\\|[^\\]\\(\\\\\\\\\\)*\\)%\\=" nil t))
580 (delete-region (1- point)
581 (save-excursion (beginning-of-line 2) (point)))))))
582
583
584(defun py2texi-process-includes ()
585 "Include LaTeX input files.
586Do not include .ind files."
587 (let ((path (file-name-directory file))
588 filename
589 dirs
590 includefile)
591 (py2texi-search-safe "\\\\input{\\([^}]+\\)}"
592 (setq filename (match-string 1))
593 (unless (save-match-data (string-match "\\.tex$" filename))
594 (setq filename (concat filename ".tex")))
595 (setq includefile (save-match-data
596 (string-match "\\.ind\\.tex$" filename)))
597 (setq dirs py2texi-dirs)
598 (while (and (not includefile) dirs)
Fred Draked4956aa2003-09-28 03:10:09 +0000599 (setq includefile
600 (concat (file-name-as-directory (car dirs)) filename))
601 (if (not (file-name-absolute-p includefile))
602 (setq includefile
603 (concat (file-name-as-directory path) includefile)))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000604 (unless (file-exists-p includefile)
Fred Draked4956aa2003-09-28 03:10:09 +0000605 (setq includefile nil)
Fred Drakebfc18bd2002-05-03 04:50:51 +0000606 (setq dirs (cdr dirs))))
607 (if includefile
608 (save-restriction
609 (narrow-to-region (match-beginning 0) (match-end 0))
610 (delete-region (point-min) (point-max))
611 (when (stringp includefile)
612 (insert-file-contents includefile)
613 (goto-char (point-min))
614 (insert "\n")
615 (py2texi-process-verbatims)
616 (py2texi-process-comments)
617 (py2texi-process-includes)))
618 (replace-match (format "\\\\emph{Included file %s}" filename))
619 (py2texi-message (format "Input file %s not found" filename))))))
620
621
622(defun py2texi-process-funnyas ()
623 "Convert @s."
624 (py2texi-search-safe "@"
625 (replace-match "@@")))
626
627
628(defun py2texi-process-environments ()
629 "Process LaTeX environments."
630 (let ((stack ())
631 kind
632 environment
633 parameter
634 arguments
635 n
636 string
637 description)
638 (py2texi-search-safe (concat "\\\\\\(begin\\|end\\|item\\)"
639 "\\({\\([^}]*\\)}\\|[[]\\([^]]*\\)[]]\\|\\)")
640 (setq kind (match-string 1)
641 environment (match-string 3)
642 parameter (match-string 4))
643 (replace-match "")
644 (cond
645 ((string= kind "begin")
646 (setq description (assoc environment py2texi-environments))
647 (if description
648 (progn
649 (setq n (cadr description))
650 (setq description (cddr description))
651 (setq string (py2texi-tex-arguments n))
652 (string-match (py2texi-regexp n) string)
653 ; incorrect but sufficient
654 (insert (replace-match (eval (car description))
655 t nil string))
656 (setq stack (cons (cadr description) stack)))
657 (py2texi-message (format "Unknown environment: %s" environment))
658 (setq stack (cons "" stack))))
659 ((string= kind "end")
660 (insert (eval (car stack)))
661 (setq stack (cdr stack)))
662 ((string= kind "item")
663 (insert "\n@item " (or parameter "") "\n"))))
664 (when stack
665 (py2texi-message (format "Unclosed environment: %s" (car stack))))))
666
667
668(defun py2texi-process-commands ()
669 "Process LaTeX commands."
670 (let (done
671 command
672 command-info
673 string
674 n)
675 (while (not done)
676 (setq done t)
677 (py2texi-search-safe "\\\\\\([a-zA-Z*]+\\)\\(\\[[^]]*\\]\\)?"
678 (setq command (match-string 1))
679 (setq command-info (assoc command py2texi-commands))
680 (if command-info
681 (progn
682 (setq done nil)
683 (replace-match "")
684 (setq command-info (cdr command-info))
685 (setq n (car command-info))
686 (setq string (py2texi-tex-arguments n))
687 (string-match (py2texi-regexp n) string)
688 ; incorrect but sufficient
689 (insert (replace-match (eval (cadr command-info))
690 t nil string)))
691 (py2texi-message (format "Unknown command: %s (not processed)"
692 command)))))))
693
694
695(defun py2texi-argument-pattern (count)
696 (let ((filler "\\(?:[^{}]\\|\\\\{\\|\\\\}\\)*"))
697 (if (<= count 0)
698 filler
699 (concat filler "\\(?:{"
700 (py2texi-argument-pattern (1- count))
701 "}" filler "\\)*" filler))))
702(defconst py2texi-tex-argument
703 (concat
704 "{\\("
705 (py2texi-argument-pattern 10) ;really at least 10!
706 "\\)}[ \t%@c\n]*")
707 "Regexp describing LaTeX command argument including argument separators.")
708
709
710(defun py2texi-regexp (n)
711 "Make regexp matching N LaTeX command arguments."
712 (if (= n 0)
713 ""
714 (let ((regexp "^[^{]*"))
715 (while (> n 0)
716 (setq regexp (concat regexp py2texi-tex-argument))
717 (setq n (1- n)))
718 regexp)))
719
720
721(defun py2texi-tex-arguments (n)
722 "Remove N LaTeX command arguments and return them as a string."
723 (let ((point (point))
724 (i 0)
725 result
726 match)
727 (if (= n 0)
728 (progn
729 (when (re-search-forward "\\=\\({}\\| *\\)" nil t)
730 (replace-match ""))
731 "")
732 (while (> n 0)
733 (unless (re-search-forward
734 "\\(\\=\\|[^\\\\]\\)\\(\\\\\\\\\\)*\\([{}]\\)" nil t)
735 (debug))
736 (if (string= (match-string 3) "{")
737 (setq i (1+ i))
738 (setq i (1- i))
739 (when (<= i 0)
740 (setq n (1- n)))))
741 (setq result (buffer-substring-no-properties point (point)))
742 (while (string-match "\n[ \t]*" result)
743 (setq result (replace-match " " t nil result)))
744 (delete-region point (point))
745 result)))
746
747
748(defun py2texi-process-simple-commands ()
749 "Replace single character LaTeX commands."
750 (let (char)
751 (py2texi-search-safe "\\\\\\([^a-z]\\)"
752 (setq char (match-string 1))
753 (replace-match (format "%s%s"
754 (if (or (string= char "{")
755 (string= char "}")
756 (string= char " "))
757 "@"
758 "")
759 (if (string= char "\\")
760 "\\\\"
761 char))))))
762
763
764(defun py2texi-fix-indentation ()
765 "Remove white space at the beginning of lines."
766 (py2texi-search-safe "^[ \t]+"
767 (replace-match "")))
768
769
770(defun py2texi-fix-nodes ()
771 "Remove unwanted characters from nodes and make nodes unique."
772 (let ((nodes (make-hash-table :test 'equal))
773 id
774 counter
775 string
Fred Drake66abcee2002-11-13 19:31:04 +0000776 label
777 index)
Fred Drakebfc18bd2002-05-03 04:50:51 +0000778 (py2texi-search "^@node +\\(.*\\)$"
779 (setq string (match-string 1))
780 (if py2texi-xemacs
781 (replace-match "@node " t)
782 (replace-match "" t nil nil 1))
Fred Drake66abcee2002-11-13 19:31:04 +0000783 (while (string-match "@label{[^}]*}" string)
Fred Drakebfc18bd2002-05-03 04:50:51 +0000784 (setq label (match-string 0 string))
785 (setq string (replace-match "" t nil string)))
Fred Drake66abcee2002-11-13 19:31:04 +0000786 (while (string-match "@..?index{[^}]*}" string)
787 (setq index (match-string 0 string))
788 (setq string (replace-match "" t nil string)))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000789 (while (string-match "@[a-zA-Z]+\\|[{}():]\\|``\\|''" string)
790 (setq string (replace-match "" t nil string)))
791 (while (string-match " -- " string)
792 (setq string (replace-match " - " t nil string)))
Fred Drake66abcee2002-11-13 19:31:04 +0000793 (while (string-match "\\." string)
794 (setq string (replace-match "" t nil string)))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000795 (when (string-match " +$" string)
796 (setq string (replace-match "" t nil string)))
797 (when (string-match "^\\(Built-in\\|Standard\\) Module \\|The " string)
798 (setq string (replace-match "" t nil string)))
799 (string-match "^[^,]+" string)
800 (setq id (match-string 0 string))
801 (setq counter (gethash id nodes))
802 (if counter
803 (progn
804 (setq counter (1+ counter))
805 (setq string (replace-match (format "\\& %d" counter)
806 t nil string)))
807 (setq counter 1))
808 (setf (gethash id nodes) counter)
809 (insert string)
Fred Drake66abcee2002-11-13 19:31:04 +0000810 (beginning-of-line 3)
Fred Drakebfc18bd2002-05-03 04:50:51 +0000811 (when label
Fred Drake66abcee2002-11-13 19:31:04 +0000812 (insert label "\n"))
813 (when index
814 (insert index "\n")))))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000815
816
817(defun py2texi-fix-references ()
818 "Process labels and make references to point to appropriate nodes."
819 (let ((labels ())
820 node)
821 (py2texi-search-safe "@label{\\([^}]*\\)}"
822 (setq node (save-excursion
823 (save-match-data
824 (and (re-search-backward "@node +\\([^,\n]+\\)" nil t)
825 (match-string 1)))))
826 (when node
827 (setq labels (cons (cons (match-string 1) node) labels)))
828 (replace-match ""))
829 (py2texi-search-safe "@ref{\\([^}]*\\)}"
830 (setq node (assoc (match-string 1) labels))
831 (replace-match "")
832 (when node
833 (insert (format "@ref{%s}" (cdr node)))))))
834
835
836(defun py2texi-fix-indices ()
837 "Remove unwanted characters from @*index commands and create final indices."
838 (py2texi-search-safe "@..?index\\>[^\n]*\\(\\)\n"
839 (replace-match "" t nil nil 1))
840 (py2texi-search-safe "@..?index\\>[^\n]*\\(\\)"
841 (replace-match "\n" t nil nil 1))
842 (py2texi-search-safe "@..?index\\({\\)\\([^}]+\\)\\(}+\\)"
843 (replace-match " " t nil nil 1)
844 (replace-match "" t nil nil 3)
845 (let ((string (match-string 2)))
846 (save-match-data
847 (while (string-match "@[a-z]+{" string)
848 (setq string (replace-match "" nil nil string)))
849 (while (string-match "{" string)
850 (setq string (replace-match "" nil nil string))))
851 (replace-match string t t nil 2)))
852 (py2texi-search-safe "@..?index\\>.*\\([{}]\\|@[a-z]*\\)"
853 (replace-match "" t nil nil 1)
854 (goto-char (match-beginning 0)))
855 (py2texi-search-safe "[^\n]\\(\\)@..?index\\>"
856 (replace-match "\n" t nil nil 1))
857 (goto-char (point-max))
858 (re-search-backward "@indices")
859 (replace-match "")
860 (insert (if moindex
861 (concat "@node Module Index\n"
862 "@unnumbered Module Index\n"
863 "@printindex mo\n")
864 "")
865 (if obindex
866 (concat "@node Class-Exception-Object Index\n"
867 "@unnumbered Class, Exception, and Object Index\n"
868 "@printindex ob\n")
869 "")
870 (if findex
871 (concat "@node Function-Method-Variable Index\n"
872 "@unnumbered Function, Method, and Variable Index\n"
873 "@printindex fn\n")
874 "")
875 (if cindex
876 (concat "@node Miscellaneous Index\n"
877 "@unnumbered Miscellaneous Index\n"
878 "@printindex cp\n")
879 "")))
880
881
882(defun py2texi-fix-backslashes ()
883 "Make backslashes from auxiliary commands."
884 (py2texi-search-safe "@backslash{}"
885 (replace-match "\\\\")))
886
887
888(defun py2texi-fix-fonts ()
889 "Remove garbage after unstructured font commands."
890 (let (string)
891 (py2texi-search-safe "@destroy"
892 (replace-match "")
893 (when (eq (preceding-char) ?{)
894 (forward-char -1)
895 (setq string (py2texi-tex-arguments 1))
896 (insert (substring string 1 (1- (length string))))))))
897
898
899(defun py2texi-fix-braces ()
900 "Escape braces for Texinfo."
Thomas Wouters89f507f2006-12-13 04:49:30 +0000901 (py2texi-search "{@{}"
902 (replace-match "@{"))
903 (py2texi-search "{@}}"
904 (replace-match "@}"))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000905 (let (string)
906 (py2texi-search "{"
907 (unless (or (py2texi-protected)
908 (save-excursion
909 (re-search-backward
910 "@\\([a-zA-Z]*\\|multitable.*\\){\\=" nil t)))
911 (forward-char -1)
912 (setq string (py2texi-tex-arguments 1))
913 (insert "@" (substring string 0 (1- (length string))) "@}")))))
914
915
916(defun py2texi-fix-newlines ()
917 "Remove extra newlines."
918 (py2texi-search "\n\n\n+"
919 (replace-match "\n\n"))
920 (py2texi-search-safe "@item.*\n\n"
921 (delete-backward-char 1))
922 (py2texi-search "@end example"
923 (unless (looking-at "\n\n")
924 (insert "\n"))))
925
926
927(defun py2texi-destroy-empties ()
928 "Remove all comments.
929This avoids some makeinfo errors."
930 (py2texi-search "@c\\>"
931 (unless (eq (py2texi-protected) t)
932 (delete-region (- (point) 2) (save-excursion (end-of-line) (point)))
933 (cond
934 ((looking-at "\n\n")
935 (delete-char 1))
936 ((save-excursion (re-search-backward "^[ \t]*\\=" nil t))
937 (delete-region (save-excursion (beginning-of-line) (point))
938 (1+ (point))))))))
939
940
941(defun py2texi-adjust-level ()
942 "Increase heading level to @chapter, if needed.
943This is only needed for distutils, so it has a very simple form only."
944 (goto-char (point-min))
945 (unless (re-search-forward "@chapter\\>" nil t)
946 (py2texi-search-safe "@section\\>"
947 (replace-match "@chapter" t))
948 (py2texi-search-safe "@\\(sub\\)\\(sub\\)?section\\>"
949 (replace-match "" nil nil nil 1))))
950
951
952(defun py2texi-texinfo-escape (beg end)
953 "Escape Texinfo special characters in region."
954 (save-excursion
955 (goto-char beg)
956 (while (re-search-forward "[@{}]" end t)
957 (replace-match "@\\&"))))
958
959
960(defun py2texi-protected ()
961 "Return protection status of the point before current point."
962 (get-text-property (1- (point)) 'py2texi-protected))
963
964
965;;; Announce
966
967(provide 'py2texi)
968
969
970;;; py2texi.el ends here