blob: a3fb94ee31394c0f4c2de6b27e02326a829a6854 [file] [log] [blame]
Fred Drakebfc18bd2002-05-03 04:50:51 +00001;;; py2texi.el -- Conversion of Python LaTeX documentation to Texinfo
2
3;; Copyright (C) 1998, 1999, 2001, 2002 Milan Zamazal
4
5;; Author: Milan Zamazal <pdm@zamazal.org>
6;; Version: $Id$
7;; Keywords: python
8
9;; COPYRIGHT NOTICE
10;;
11;; This program is free software; you can redistribute it and/or modify it
12;; under the terms of the GNU General Public License as published by the Free
13;; Software Foundation; either version 2, or (at your option) any later
14;; version.
15;;
16;; This program is distributed in the hope that it will be useful, but
17;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19;; for more details.
20;;
21;; You can find the GNU General Public License at
22;; http://www.gnu.org/copyleft/gpl.html
23;; or you can write to the Free Software Foundation, Inc., 59 Temple Place,
24;; Suite 330, Boston, MA 02111-1307, USA.
25
26;;; Commentary:
27
28;; This is a Q&D hack for conversion of Python manuals to on-line help format.
29;; I desperately needed usable online documenta for Python, so I wrote this.
30;; The result code is ugly and need not contain complete information from
31;; Python manuals. I apologize for my ignorance, especially ignorance to
32;; python.sty. Improvements of this convertor are welcomed.
33
34;; How to use it:
35;; Load this file and apply `M-x py2texi'. You will be asked for name of a
36;; file to be converted.
37
38;; Where to find it:
39;; New versions of this code might be found at
40;; http://www.zamazal.org/software/python/py2texi/ .
41
42;;; Code:
43
44
45(require 'texinfo)
46(eval-when-compile
47 (require 'cl))
48
49
50(defvar py2texi-python-version "2.2"
51 "What to substitute for the \\version macro.")
52
53(defvar py2texi-python-short-version
54 (progn
55 (string-match "[0-9]+\\.[0-9]+" py2texi-python-version)
56 (match-string 0 py2texi-python-version))
57 "Short version number, usually set by the LaTeX commands.")
58
Fred Drake66abcee2002-11-13 19:31:04 +000059(defvar py2texi-texi-file-name nil
60 "If non-nil, that string is used as the name of the Texinfo file.
61Otherwise a generated Texinfo file name is used.")
62
63(defvar py2texi-info-file-name nil
64 "If non-nil, that string is used as the name of the Info file.
65Otherwise a generated Info file name is used.")
66
Fred Drakebfc18bd2002-05-03 04:50:51 +000067(defvar py2texi-stop-on-problems nil
68 "*If non-nil, stop when you encouter soft problem.")
69
70(defconst py2texi-environments
71 '(("abstract" 0 "@quotation" "@end quotation\n")
72 ("center" 0 "" "")
73 ("cfuncdesc" 3
74 (progn (setq findex t)
75 "\n@table @code\n@item \\1 \\2(\\3)\n@findex \\2\n")
Fred Drake66abcee2002-11-13 19:31:04 +000076 "@end table\n")
77 ("cmemberdesc" 3
78 "\n@table @code\n@item \\2 \\3\n"
79 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +000080 ("classdesc" 2
81 (progn (setq obindex t)
82 "\n@table @code\n@item \\1(\\2)\n@obindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +000083 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +000084 ("classdesc*" 1
85 (progn (setq obindex t)
86 "\n@table @code\n@item \\1\n@obindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +000087 "@end table\n")
Fred Drake66758812003-07-02 14:44:08 +000088 ("comment" 0 "\n@ignore\n" "\n@end ignore\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +000089 ("csimplemacrodesc" 1
90 (progn (setq cindex t)
91 "\n@table @code\n@item \\1\n@cindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +000092 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +000093 ("ctypedesc" 1
94 (progn (setq cindex t)
95 "\n@table @code\n@item \\1\n@cindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +000096 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +000097 ("cvardesc" 2
98 (progn (setq findex t)
99 "\n@table @code\n@item \\1 \\2\n@findex \\2\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000100 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000101 ("datadesc" 1
102 (progn (setq findex t)
103 "\n@table @code\n@item \\1\n@findex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000104 "@end table\n")
105 ("datadescni" 1 "\n@table @code\n@item \\1\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000106 ("definitions" 0 "@table @dfn" "@end table\n")
107 ("description" 0 "@table @samp" "@end table\n")
108 ("displaymath" 0 "" "")
109 ("document" 0
110 (concat "@defcodeindex mo\n"
111 "@defcodeindex ob\n"
112 "@titlepage\n"
113 (format "@title " title "\n")
114 (format "@author " author "\n")
115 "@page\n"
116 author-address
117 "@end titlepage\n"
118 "@node Top, , , (dir)\n")
119 (concat "@indices\n"
120 "@contents\n"
121 "@bye\n"))
122 ("enumerate" 0 "@enumerate" "@end enumerate")
Fred Drake3b095582003-07-02 14:22:48 +0000123 ("envdesc" 2 (concat "\n@table @code"
124 "\n@item @backslash{}begin@{\\1@}\\2")
125 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000126 ("excdesc" 1
127 (progn (setq obindex t)
128 "\n@table @code\n@item \\1\n@obindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000129 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000130 ("excclassdesc" 2
131 (progn (setq obindex t)
132 "\n@table @code\n@item \\1(\\2)\n@obindex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000133 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000134 ("flushleft" 0 "" "")
Fred Drake66abcee2002-11-13 19:31:04 +0000135 ("fulllineitems" 0 "\n@table @code\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000136 ("funcdesc" 2
137 (progn (setq findex t)
138 "\n@table @code\n@item \\1(\\2)\n@findex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000139 "@end table\n")
140 ("funcdescni" 2 "\n@table @code\n@item \\1(\\2)\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000141 ("itemize" 0 "@itemize @bullet" "@end itemize\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000142 ("list" 2 "\n@table @code\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000143 ("longtableii" 4 (concat "@multitable @columnfractions .5 .5\n"
144 "@item \\3 @tab \\4\n"
145 "@item ------- @tab ------ \n")
146 "@end multitable\n")
147 ("longtableiii" 5 (concat "@multitable @columnfractions .33 .33 .33\n"
148 "@item \\3 @tab \\4 @tab \\5\n"
149 "@item ------- @tab ------ @tab ------\n")
150 "@end multitable\n")
Fred Drake3b095582003-07-02 14:22:48 +0000151 ("macrodesc" 2 (concat "\n@table @code"
152 "\n@item \\1@{\\2@}")
153 "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000154 ("memberdesc" 1
155 (progn (setq findex t)
156 "\n@table @code\n@item \\1\n@findex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000157 "@end table\n")
158 ("memberdescni" 1 "\n@table @code\n@item \\1\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000159 ("methoddesc" 2
160 (progn (setq findex t)
161 "\n@table @code\n@item \\1(\\2)\n@findex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000162 "@end table\n")
163 ("methoddescni" 2 "\n@table @code\n@item \\1(\\2)\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000164 ("notice" 0 "@emph{Notice:} " "")
165 ("opcodedesc" 2
166 (progn (setq findex t)
167 "\n@table @code\n@item \\1 \\2\n@findex \\1\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000168 "@end table\n")
169 ("productionlist" 0 "\n@table @code\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000170 ("quotation" 0 "@quotation" "@end quotation")
Fred Drake66abcee2002-11-13 19:31:04 +0000171 ("seealso" 0 "See also:\n@table @emph\n" "@end table\n")
172 ("seealso*" 0 "@table @emph\n" "@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000173 ("sloppypar" 0 "" "")
174 ("small" 0 "" "")
175 ("tableii" 4 (concat "@multitable @columnfractions .5 .5\n"
176 "@item \\3 @tab \\4\n"
177 "@item ------- @tab ------ \n")
178 "@end multitable\n")
179 ("tableiii" 5 (concat "@multitable @columnfractions .33 .33 .33\n"
180 "@item \\3 @tab \\4 @tab \\5\n"
181 "@item ------- @tab ------ @tab ------\n")
182 "@end multitable\n")
183 ("tableiv" 6 (concat
184 "@multitable @columnfractions .25 .25 .25 .25\n"
185 "@item \\3 @tab \\4 @tab \\5 @tab \\6\n"
186 "@item ------- @tab ------- @tab ------- @tab -------\n")
187 "@end multitable\n")
188 ("tablev" 7 (concat
189 "@multitable @columnfractions .20 .20 .20 .20 .20\n"
190 "@item \\3 @tab \\4 @tab \\5 @tab \\6 @tab \\7\n"
191 "@item ------- @tab ------- @tab ------- @tab ------- @tab -------\n")
192 "@end multitable\n"))
193 "Associative list defining substitutions for environments.
194Each list item is of the form (ENVIRONMENT ARGNUM BEGIN END) where:
195- ENVIRONMENT is LaTeX environment name
196- ARGNUM is number of (required) macro arguments
197- BEGIN is substitution for \begin{ENVIRONMENT}
198- END is substitution for \end{ENVIRONMENT}
199Both BEGIN and END are evaled. Moreover, you can reference arguments through
200\N regular expression notation in strings of BEGIN.")
201
202(defconst py2texi-commands
Fred Drake7769bb92003-07-16 03:16:34 +0000203 '(("AA" 0 "@AA{}")
204 ("aa" 0 "@aa{}")
205 ("ABC" 0 "ABC")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000206 ("appendix" 0 (progn (setq appendix t) ""))
207 ("ASCII" 0 "ASCII")
208 ("author" 1 (progn (setq author (match-string 1 string)) ""))
209 ("authoraddress" 1
210 (progn (setq author-address (match-string 1 string)) ""))
211 ("b" 1 "@w{\\1}")
212 ("bf" 0 "@destroy")
213 ("bifuncindex" 1 (progn (setq findex t) "@findex{\\1}"))
214 ("C" 0 "C")
215 ("c" 0 "@,")
216 ("catcode" 0 "")
217 ("cdata" 1 "@code{\\1}")
218 ("centerline" 1 "@center \\1")
Fred Drake66abcee2002-11-13 19:31:04 +0000219 ("cfuncline" 3 "@itemx \\1 \\2(\\3)\n@findex \\2")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000220 ("cfunction" 1 "@code{\\1}")
221 ("chapter" 1 (format "@node \\1\n@%s \\1\n"
222 (if appendix "appendix" "chapter")))
223 ("chapter*" 1 "@node \\1\n@unnumbered \\1\n")
224 ("character" 1 "@samp{\\1}")
225 ("citetitle" 1 "@ref{Top,,,\\1}")
226 ("class" 1 "@code{\\1}")
Fred Drake66abcee2002-11-13 19:31:04 +0000227 ("cmemberline" 3 "@itemx \\2 \\3\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000228 ("code" 1 "@code{\\1}")
229 ("command" 1 "@command{\\1}")
230 ("constant" 1 "@code{\\1}")
231 ("copyright" 1 "@copyright{}")
232 ("Cpp" 0 "C++")
Fred Draked805fef2002-06-27 18:38:06 +0000233 ("csimplemacro" 1 "@code{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000234 ("ctype" 1 "@code{\\1}")
235 ("dataline" 1 (progn (setq findex t) "@item \\1\n@findex \\1\n"))
236 ("date" 1 "\\1")
237 ("declaremodule" 2 (progn (setq cindex t) "@label{\\2}@cindex{\\2}"))
238 ("deprecated" 2 "@emph{This is deprecated in Python \\1. \\2}")
239 ("dfn" 1 "@dfn{\\1}")
240 ("documentclass" 1 py2texi-magic)
241 ("e" 0 "@backslash{}")
242 ("else" 0 (concat "@end ifinfo\n@" (setq last-if "iftex")))
Fred Drake3b095582003-07-02 14:22:48 +0000243 ("env" 1 "@code{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000244 ("EOF" 0 "@code{EOF}")
245 ("email" 1 "@email{\\1}")
246 ("emph" 1 "@emph{\\1}")
247 ("envvar" 1 "@samp{\\1}")
248 ("exception" 1 "@code{\\1}")
249 ("exindex" 1 (progn (setq obindex t) "@obindex{\\1}"))
250 ("fi" 0 (concat "@end " last-if))
251 ("file" 1 "@file{\\1}")
Fred Drake3b095582003-07-02 14:22:48 +0000252 ("filenq" 1 "@file{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000253 ("filevar" 1 "@file{@var{\\1}}")
254 ("footnote" 1 "@footnote{\\1}")
255 ("frac" 0 "")
256 ("funcline" 2 (progn (setq findex t) "@item \\1 \\2\n@findex \\1"))
257 ("funclineni" 2 "@item \\1 \\2")
258 ("function" 1 "@code{\\1}")
259 ("grammartoken" 1 "@code{\\1}")
260 ("hline" 0 "")
261 ("ifhtml" 0 (concat "@" (setq last-if "ifinfo")))
262 ("iftexi" 0 (concat "@" (setq last-if "ifinfo")))
263 ("index" 1 (progn (setq cindex t) "@cindex{\\1}"))
264 ("indexii" 2 (progn (setq cindex t) "@cindex{\\1 \\2}"))
265 ("indexiii" 3 (progn (setq cindex t) "@cindex{\\1 \\2 \\3}"))
266 ("indexiv" 3 (progn (setq cindex t) "@cindex{\\1 \\2 \\3 \\4}"))
267 ("infinity" 0 "@emph{infinity}")
268 ("it" 0 "@destroy")
269 ("kbd" 1 "@key{\\1}")
270 ("keyword" 1 "@code{\\1}")
271 ("kwindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
272 ("label" 1 "@label{\\1}")
273 ("Large" 0 "")
274 ("LaTeX" 0 "La@TeX{}")
275 ("large" 0 "")
276 ("ldots" 0 "@dots{}")
277 ("leftline" 1 "\\1")
278 ("lineii" 2 "@item \\1 @tab \\2")
279 ("lineiii" 3 "@item \\1 @tab \\2 @tab \\3")
280 ("lineiv" 4 "@item \\1 @tab \\2 @tab \\3 @tab \\4")
281 ("linev" 5 "@item \\1 @tab \\2 @tab \\3 @tab \\4 @tab \\5")
282 ("localmoduletable" 0 "")
283 ("longprogramopt" 1 "@option{--\\1}")
Fred Drake3b095582003-07-02 14:22:48 +0000284 ("macro" 1 "@code{@backslash{}\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000285 ("mailheader" 1 "@code{\\1}")
286 ("makeindex" 0 "")
287 ("makemodindex" 0 "")
288 ("maketitle" 0 (concat "@top " title "\n"))
289 ("makevar" 1 "@code{\\1}")
290 ("manpage" 2 "@samp{\\1(\\2)}")
291 ("mbox" 1 "@w{\\1}")
292 ("member" 1 "@code{\\1}")
293 ("memberline" 1 "@item \\1\n@findex \\1\n")
294 ("menuselection" 1 "@samp{\\1}")
295 ("method" 1 "@code{\\1}")
296 ("methodline" 2 (progn (setq moindex t) "@item \\1(\\2)\n@moindex \\1\n"))
297 ("methodlineni" 2 "@item \\1(\\2)\n")
298 ("mimetype" 1 "@samp{\\1}")
299 ("module" 1 "@samp{\\1}")
Fred Drake66abcee2002-11-13 19:31:04 +0000300 ("moduleauthor" 2 "")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000301 ("modulesynopsis" 1 "\\1")
302 ("moreargs" 0 "@dots{}")
303 ("n" 0 "@backslash{}n")
304 ("newcommand" 2 "")
305 ("newsgroup" 1 "@samp{\\1}")
306 ("nodename" 1
307 (save-excursion
308 (save-match-data
309 (re-search-backward "^@node "))
310 (delete-region (point) (save-excursion (end-of-line) (point)))
311 (insert "@node " (match-string 1 string))
312 ""))
313 ("noindent" 0 "@noindent ")
314 ("note" 1 "@emph{Note:} \\1")
315 ("NULL" 0 "@code{NULL}")
316 ("obindex" 1 (progn (setq obindex t) "@obindex{\\1}"))
317 ("opindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
318 ("option" 1 "@option{\\1}")
319 ("optional" 1 "[\\1]")
320 ("pep" 1 (progn (setq cindex t) "PEP@ \\1@cindex PEP \\1\n"))
321 ("pi" 0 "pi")
322 ("platform" 1 "")
323 ("plusminus" 0 "+-")
324 ("POSIX" 0 "POSIX")
325 ("production" 2 "@item \\1 \\2")
Fred Drake66abcee2002-11-13 19:31:04 +0000326 ("productioncont" 1 "@item @w{} \\1")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000327 ("program" 1 "@command{\\1}")
328 ("programopt" 1 "@option{\\1}")
329 ("protect" 0 "")
330 ("pytype" 1 "@code{\\1}")
331 ("ref" 1 "@ref{\\1}")
332 ("refbimodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
333 ("refmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
334 ("refmodule" 1 "@samp{\\1}")
335 ("refstmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
336 ("regexp" 1 "\"\\1\"")
337 ("release" 1
338 (progn (setq py2texi-python-version (match-string 1 string)) ""))
339 ("renewcommand" 2 "")
340 ("rfc" 1 (progn (setq cindex t) "RFC@ \\1@cindex RFC \\1\n"))
341 ("rm" 0 "@destroy")
342 ("samp" 1 "@samp{\\1}")
343 ("section" 1 (let ((str (match-string 1 string)))
344 (save-match-data
345 (if (string-match "\\(.*\\)[ \t\n]*---[ \t\n]*\\(.*\\)"
346 str)
347 (format
348 "@node %s\n@section %s\n"
349 (py2texi-backslash-quote (match-string 1 str))
350 (py2texi-backslash-quote (match-string 2 str)))
351 "@node \\1\n@section \\1\n"))))
Fred Drake66abcee2002-11-13 19:31:04 +0000352 ("sectionauthor" 2 "")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000353 ("seemodule" 2 "@ref{\\1} \\2")
354 ("seepep" 3 "\n@table @strong\n@item PEP\\1 \\2\n\\3\n@end table\n")
355 ("seerfc" 3 "\n@table @strong\n@item RFC\\1 \\2\n\\3\n@end table\n")
356 ("seetext" 1 "\\1")
357 ("seetitle" 1 "@cite{\\1}")
358 ("seeurl" 2 "\n@table @url\n@item \\1\n\\2\n@end table\n")
359 ("setindexsubitem" 1 (progn (setq cindex t) "@cindex \\1"))
360 ("setreleaseinfo" 1 (progn (setq py2texi-releaseinfo "")))
361 ("setshortversion" 1
362 (progn (setq py2texi-python-short-version (match-string 1 string)) ""))
363 ("shortversion" 0 py2texi-python-short-version)
364 ("sqrt" 0 "")
365 ("stindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
366 ("stmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
367 ("strong" 1 "@strong{\\1}")
368 ("sub" 0 "/")
369 ("subsection" 1 "@node \\1\n@subsection \\1\n")
370 ("subsubsection" 1 "@node \\1\n@subsubsection \\1\n")
371 ("sum" 0 "")
372 ("tableofcontents" 0 "")
373 ("term" 1 "@item \\1")
Fred Drake3b095582003-07-02 14:22:48 +0000374 ("TeX" 0 "@TeX{}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000375 ("textasciitilde" 0 "~")
376 ("textasciicircum" 0 "^")
377 ("textbackslash" 0 "@backslash{}")
Fred Draked805fef2002-06-27 18:38:06 +0000378 ("textgreater" 0 ">")
379 ("textless" 0 "<")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000380 ("textrm" 1 "\\1")
381 ("texttt" 1 "@code{\\1}")
382 ("textunderscore" 0 "_")
383 ("title" 1 (progn (setq title (match-string 1 string)) "@settitle \\1"))
384 ("today" 0 "@today{}")
385 ("token" 1 "@code{\\1}")
386 ("tt" 0 "@destroy")
387 ("ttindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
388 ("u" 0 "@backslash{}u")
389 ("ulink" 2 "\\1")
390 ("UNIX" 0 "UNIX")
391 ("unspecified" 0 "@dots{}")
392 ("url" 1 "@url{\\1}")
393 ("usepackage" 1 "")
394 ("var" 1 "@var{\\1}")
395 ("verbatiminput" 1 "@code{\\1}")
396 ("version" 0 py2texi-python-version)
397 ("versionadded" 1 "@emph{Added in Python version \\1}")
398 ("versionchanged" 1 "@emph{Changed in Python version \\1}")
399 ("vskip" 1 "")
400 ("vspace" 1 "")
401 ("warning" 1 "@emph{\\1}")
402 ("withsubitem" 2 "\\2")
403 ("XXX" 1 "@strong{\\1}"))
404 "Associative list of command substitutions.
405Each list item is of the form (COMMAND ARGNUM SUBSTITUTION) where:
406- COMMAND is LaTeX command name
407- ARGNUM is number of (required) command arguments
408- SUBSTITUTION substitution for the command. It is evaled and you can
409 reference command arguments through the \\N regexp notation in strings.")
410
411(defvar py2texi-magic "@documentclass\n"
412 "\"Magic\" string for auxiliary insertion at the beginning of document.")
413
414(defvar py2texi-dirs '("./" "../texinputs/")
415 "Where to search LaTeX input files.")
416
417(defvar py2texi-buffer "*py2texi*"
418 "The name of a buffer where Texinfo is generated.")
419
420(defconst py2texi-xemacs (string-match "^XEmacs" (emacs-version))
421 "Running under XEmacs?")
422
423
424(defmacro py2texi-search (regexp &rest body)
425 `(progn
426 (goto-char (point-min))
427 (while (re-search-forward ,regexp nil t)
428 ,@body)))
429
430(defmacro py2texi-search-safe (regexp &rest body)
431 `(py2texi-search ,regexp
432 (unless (py2texi-protected)
433 ,@body)))
434
435
436(defun py2texi-message (message)
437 "Report message and stop if `py2texi-stop-on-problems' is non-nil."
438 (if py2texi-stop-on-problems
439 (error message)
440 (message message)))
441
442
443(defun py2texi-backslash-quote (string)
444 "Double backslahes in STRING."
445 (let ((i 0))
446 (save-match-data
447 (while (setq i (string-match "\\\\" string i))
448 (setq string (replace-match "\\\\\\\\" t nil string))
449 (setq i (+ i 2))))
450 string))
451
452
453(defun py2texi (file)
454 "Convert Python LaTeX documentation FILE to Texinfo."
455 (interactive "fFile to convert: ")
456 (switch-to-buffer (get-buffer-create py2texi-buffer))
457 (erase-buffer)
458 (insert-file file)
459 (let ((case-fold-search nil)
460 (title "")
461 (author "")
462 (author-address "")
463 (appendix nil)
464 (findex nil)
465 (obindex nil)
466 (cindex nil)
467 (moindex nil)
468 last-if)
469 (py2texi-process-verbatims)
470 (py2texi-process-comments)
471 (py2texi-process-includes)
472 (py2texi-process-funnyas)
473 (py2texi-process-environments)
474 (py2texi-process-commands)
475 (py2texi-fix-indentation)
476 (py2texi-fix-nodes)
477 (py2texi-fix-references)
478 (py2texi-fix-indices)
479 (py2texi-process-simple-commands)
480 (py2texi-fix-fonts)
481 (py2texi-fix-braces)
482 (py2texi-fix-backslashes)
483 (py2texi-destroy-empties)
484 (py2texi-fix-newlines)
485 (py2texi-adjust-level))
Fred Drake66abcee2002-11-13 19:31:04 +0000486 (let* ((texi-file-name (or py2texi-texi-file-name
487 (py2texi-texi-file-name file)))
488 (info-file-name (or py2texi-info-file-name
489 (py2texi-info-file-name texi-file-name))))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000490 (goto-char (point-min))
491 (when (looking-at py2texi-magic)
492 (delete-region (point) (progn (beginning-of-line 2) (point)))
493 (insert "\\input texinfo @c -*-texinfo-*-\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000494 (insert "@setfilename " info-file-name))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000495 (when (re-search-forward "@chapter" nil t)
496 (texinfo-all-menus-update t))
497 (goto-char (point-min))
Fred Drake66abcee2002-11-13 19:31:04 +0000498 (write-file texi-file-name)
499 (message (format "You can apply `makeinfo %s' now." texi-file-name))))
500
501
502(defun py2texi-texi-file-name (filename)
503 "Generate name of Texinfo file from original file name FILENAME."
504 (concat filename
505 (if (string-match "\\.tex$" filename) "i" ".texi")))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000506
507
508(defun py2texi-info-file-name (filename)
509 "Generate name of info file from original file name FILENAME."
510 (setq filename (expand-file-name filename))
511 (let ((directory (file-name-directory filename))
512 (basename (file-name-nondirectory filename)))
513 (concat directory "python-"
514 (substring basename 0 (- (length basename) 4)) "info")))
515
516
517(defun py2texi-process-verbatims ()
518 "Process and protect verbatim environments."
519 (let (delimiter
520 beg
521 end)
522 (py2texi-search-safe "\\\\begin{\\(verbatim\\|displaymath\\)}"
523 (replace-match "@example")
524 (setq beg (copy-marker (point) nil))
525 (re-search-forward "\\\\end{\\(verbatim\\|displaymath\\)}")
526 (setq end (copy-marker (match-beginning 0) nil))
527 (replace-match "@end example")
528 (py2texi-texinfo-escape beg end)
529 (put-text-property (- beg (length "@example"))
530 (+ end (length "@end example"))
531 'py2texi-protected t))
532 (py2texi-search-safe "\\\\verb\\([^a-z]\\)"
533 (setq delimiter (match-string 1))
534 (replace-match "@code{")
535 (setq beg (copy-marker (point) nil))
536 (re-search-forward (regexp-quote delimiter))
537 (setq end (copy-marker (match-beginning 0) nil))
538 (replace-match "}")
539 (put-text-property (- beg (length "@code{")) (+ end (length "}"))
540 'py2texi-protected t)
541 (py2texi-texinfo-escape beg end))))
542
543
544(defun py2texi-process-comments ()
545 "Remove comments."
546 (let (point)
547 (py2texi-search-safe "%"
548 (setq point (point))
549 (when (save-excursion
550 (re-search-backward "\\(^\\|[^\\]\\(\\\\\\\\\\)*\\)%\\=" nil t))
551 (delete-region (1- point)
552 (save-excursion (beginning-of-line 2) (point)))))))
553
554
555(defun py2texi-process-includes ()
556 "Include LaTeX input files.
557Do not include .ind files."
558 (let ((path (file-name-directory file))
559 filename
560 dirs
561 includefile)
562 (py2texi-search-safe "\\\\input{\\([^}]+\\)}"
563 (setq filename (match-string 1))
564 (unless (save-match-data (string-match "\\.tex$" filename))
565 (setq filename (concat filename ".tex")))
566 (setq includefile (save-match-data
567 (string-match "\\.ind\\.tex$" filename)))
568 (setq dirs py2texi-dirs)
569 (while (and (not includefile) dirs)
570 (setq includefile (concat path (car dirs) filename))
571 (unless (file-exists-p includefile)
572 (setq includefile nil)
573 (setq dirs (cdr dirs))))
574 (if includefile
575 (save-restriction
576 (narrow-to-region (match-beginning 0) (match-end 0))
577 (delete-region (point-min) (point-max))
578 (when (stringp includefile)
579 (insert-file-contents includefile)
580 (goto-char (point-min))
581 (insert "\n")
582 (py2texi-process-verbatims)
583 (py2texi-process-comments)
584 (py2texi-process-includes)))
585 (replace-match (format "\\\\emph{Included file %s}" filename))
586 (py2texi-message (format "Input file %s not found" filename))))))
587
588
589(defun py2texi-process-funnyas ()
590 "Convert @s."
591 (py2texi-search-safe "@"
592 (replace-match "@@")))
593
594
595(defun py2texi-process-environments ()
596 "Process LaTeX environments."
597 (let ((stack ())
598 kind
599 environment
600 parameter
601 arguments
602 n
603 string
604 description)
605 (py2texi-search-safe (concat "\\\\\\(begin\\|end\\|item\\)"
606 "\\({\\([^}]*\\)}\\|[[]\\([^]]*\\)[]]\\|\\)")
607 (setq kind (match-string 1)
608 environment (match-string 3)
609 parameter (match-string 4))
610 (replace-match "")
611 (cond
612 ((string= kind "begin")
613 (setq description (assoc environment py2texi-environments))
614 (if description
615 (progn
616 (setq n (cadr description))
617 (setq description (cddr description))
618 (setq string (py2texi-tex-arguments n))
619 (string-match (py2texi-regexp n) string)
620 ; incorrect but sufficient
621 (insert (replace-match (eval (car description))
622 t nil string))
623 (setq stack (cons (cadr description) stack)))
624 (py2texi-message (format "Unknown environment: %s" environment))
625 (setq stack (cons "" stack))))
626 ((string= kind "end")
627 (insert (eval (car stack)))
628 (setq stack (cdr stack)))
629 ((string= kind "item")
630 (insert "\n@item " (or parameter "") "\n"))))
631 (when stack
632 (py2texi-message (format "Unclosed environment: %s" (car stack))))))
633
634
635(defun py2texi-process-commands ()
636 "Process LaTeX commands."
637 (let (done
638 command
639 command-info
640 string
641 n)
642 (while (not done)
643 (setq done t)
644 (py2texi-search-safe "\\\\\\([a-zA-Z*]+\\)\\(\\[[^]]*\\]\\)?"
645 (setq command (match-string 1))
646 (setq command-info (assoc command py2texi-commands))
647 (if command-info
648 (progn
649 (setq done nil)
650 (replace-match "")
651 (setq command-info (cdr command-info))
652 (setq n (car command-info))
653 (setq string (py2texi-tex-arguments n))
654 (string-match (py2texi-regexp n) string)
655 ; incorrect but sufficient
656 (insert (replace-match (eval (cadr command-info))
657 t nil string)))
658 (py2texi-message (format "Unknown command: %s (not processed)"
659 command)))))))
660
661
662(defun py2texi-argument-pattern (count)
663 (let ((filler "\\(?:[^{}]\\|\\\\{\\|\\\\}\\)*"))
664 (if (<= count 0)
665 filler
666 (concat filler "\\(?:{"
667 (py2texi-argument-pattern (1- count))
668 "}" filler "\\)*" filler))))
669(defconst py2texi-tex-argument
670 (concat
671 "{\\("
672 (py2texi-argument-pattern 10) ;really at least 10!
673 "\\)}[ \t%@c\n]*")
674 "Regexp describing LaTeX command argument including argument separators.")
675
676
677(defun py2texi-regexp (n)
678 "Make regexp matching N LaTeX command arguments."
679 (if (= n 0)
680 ""
681 (let ((regexp "^[^{]*"))
682 (while (> n 0)
683 (setq regexp (concat regexp py2texi-tex-argument))
684 (setq n (1- n)))
685 regexp)))
686
687
688(defun py2texi-tex-arguments (n)
689 "Remove N LaTeX command arguments and return them as a string."
690 (let ((point (point))
691 (i 0)
692 result
693 match)
694 (if (= n 0)
695 (progn
696 (when (re-search-forward "\\=\\({}\\| *\\)" nil t)
697 (replace-match ""))
698 "")
699 (while (> n 0)
700 (unless (re-search-forward
701 "\\(\\=\\|[^\\\\]\\)\\(\\\\\\\\\\)*\\([{}]\\)" nil t)
702 (debug))
703 (if (string= (match-string 3) "{")
704 (setq i (1+ i))
705 (setq i (1- i))
706 (when (<= i 0)
707 (setq n (1- n)))))
708 (setq result (buffer-substring-no-properties point (point)))
709 (while (string-match "\n[ \t]*" result)
710 (setq result (replace-match " " t nil result)))
711 (delete-region point (point))
712 result)))
713
714
715(defun py2texi-process-simple-commands ()
716 "Replace single character LaTeX commands."
717 (let (char)
718 (py2texi-search-safe "\\\\\\([^a-z]\\)"
719 (setq char (match-string 1))
720 (replace-match (format "%s%s"
721 (if (or (string= char "{")
722 (string= char "}")
723 (string= char " "))
724 "@"
725 "")
726 (if (string= char "\\")
727 "\\\\"
728 char))))))
729
730
731(defun py2texi-fix-indentation ()
732 "Remove white space at the beginning of lines."
733 (py2texi-search-safe "^[ \t]+"
734 (replace-match "")))
735
736
737(defun py2texi-fix-nodes ()
738 "Remove unwanted characters from nodes and make nodes unique."
739 (let ((nodes (make-hash-table :test 'equal))
740 id
741 counter
742 string
Fred Drake66abcee2002-11-13 19:31:04 +0000743 label
744 index)
Fred Drakebfc18bd2002-05-03 04:50:51 +0000745 (py2texi-search "^@node +\\(.*\\)$"
746 (setq string (match-string 1))
747 (if py2texi-xemacs
748 (replace-match "@node " t)
749 (replace-match "" t nil nil 1))
Fred Drake66abcee2002-11-13 19:31:04 +0000750 (while (string-match "@label{[^}]*}" string)
Fred Drakebfc18bd2002-05-03 04:50:51 +0000751 (setq label (match-string 0 string))
752 (setq string (replace-match "" t nil string)))
Fred Drake66abcee2002-11-13 19:31:04 +0000753 (while (string-match "@..?index{[^}]*}" string)
754 (setq index (match-string 0 string))
755 (setq string (replace-match "" t nil string)))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000756 (while (string-match "@[a-zA-Z]+\\|[{}():]\\|``\\|''" string)
757 (setq string (replace-match "" t nil string)))
758 (while (string-match " -- " string)
759 (setq string (replace-match " - " t nil string)))
Fred Drake66abcee2002-11-13 19:31:04 +0000760 (while (string-match "\\." string)
761 (setq string (replace-match "" t nil string)))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000762 (when (string-match " +$" string)
763 (setq string (replace-match "" t nil string)))
764 (when (string-match "^\\(Built-in\\|Standard\\) Module \\|The " string)
765 (setq string (replace-match "" t nil string)))
766 (string-match "^[^,]+" string)
767 (setq id (match-string 0 string))
768 (setq counter (gethash id nodes))
769 (if counter
770 (progn
771 (setq counter (1+ counter))
772 (setq string (replace-match (format "\\& %d" counter)
773 t nil string)))
774 (setq counter 1))
775 (setf (gethash id nodes) counter)
776 (insert string)
Fred Drake66abcee2002-11-13 19:31:04 +0000777 (beginning-of-line 3)
Fred Drakebfc18bd2002-05-03 04:50:51 +0000778 (when label
Fred Drake66abcee2002-11-13 19:31:04 +0000779 (insert label "\n"))
780 (when index
781 (insert index "\n")))))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000782
783
784(defun py2texi-fix-references ()
785 "Process labels and make references to point to appropriate nodes."
786 (let ((labels ())
787 node)
788 (py2texi-search-safe "@label{\\([^}]*\\)}"
789 (setq node (save-excursion
790 (save-match-data
791 (and (re-search-backward "@node +\\([^,\n]+\\)" nil t)
792 (match-string 1)))))
793 (when node
794 (setq labels (cons (cons (match-string 1) node) labels)))
795 (replace-match ""))
796 (py2texi-search-safe "@ref{\\([^}]*\\)}"
797 (setq node (assoc (match-string 1) labels))
798 (replace-match "")
799 (when node
800 (insert (format "@ref{%s}" (cdr node)))))))
801
802
803(defun py2texi-fix-indices ()
804 "Remove unwanted characters from @*index commands and create final indices."
805 (py2texi-search-safe "@..?index\\>[^\n]*\\(\\)\n"
806 (replace-match "" t nil nil 1))
807 (py2texi-search-safe "@..?index\\>[^\n]*\\(\\)"
808 (replace-match "\n" t nil nil 1))
809 (py2texi-search-safe "@..?index\\({\\)\\([^}]+\\)\\(}+\\)"
810 (replace-match " " t nil nil 1)
811 (replace-match "" t nil nil 3)
812 (let ((string (match-string 2)))
813 (save-match-data
814 (while (string-match "@[a-z]+{" string)
815 (setq string (replace-match "" nil nil string)))
816 (while (string-match "{" string)
817 (setq string (replace-match "" nil nil string))))
818 (replace-match string t t nil 2)))
819 (py2texi-search-safe "@..?index\\>.*\\([{}]\\|@[a-z]*\\)"
820 (replace-match "" t nil nil 1)
821 (goto-char (match-beginning 0)))
822 (py2texi-search-safe "[^\n]\\(\\)@..?index\\>"
823 (replace-match "\n" t nil nil 1))
824 (goto-char (point-max))
825 (re-search-backward "@indices")
826 (replace-match "")
827 (insert (if moindex
828 (concat "@node Module Index\n"
829 "@unnumbered Module Index\n"
830 "@printindex mo\n")
831 "")
832 (if obindex
833 (concat "@node Class-Exception-Object Index\n"
834 "@unnumbered Class, Exception, and Object Index\n"
835 "@printindex ob\n")
836 "")
837 (if findex
838 (concat "@node Function-Method-Variable Index\n"
839 "@unnumbered Function, Method, and Variable Index\n"
840 "@printindex fn\n")
841 "")
842 (if cindex
843 (concat "@node Miscellaneous Index\n"
844 "@unnumbered Miscellaneous Index\n"
845 "@printindex cp\n")
846 "")))
847
848
849(defun py2texi-fix-backslashes ()
850 "Make backslashes from auxiliary commands."
851 (py2texi-search-safe "@backslash{}"
852 (replace-match "\\\\")))
853
854
855(defun py2texi-fix-fonts ()
856 "Remove garbage after unstructured font commands."
857 (let (string)
858 (py2texi-search-safe "@destroy"
859 (replace-match "")
860 (when (eq (preceding-char) ?{)
861 (forward-char -1)
862 (setq string (py2texi-tex-arguments 1))
863 (insert (substring string 1 (1- (length string))))))))
864
865
866(defun py2texi-fix-braces ()
867 "Escape braces for Texinfo."
868 (let (string)
869 (py2texi-search "{"
870 (unless (or (py2texi-protected)
871 (save-excursion
872 (re-search-backward
873 "@\\([a-zA-Z]*\\|multitable.*\\){\\=" nil t)))
874 (forward-char -1)
875 (setq string (py2texi-tex-arguments 1))
876 (insert "@" (substring string 0 (1- (length string))) "@}")))))
877
878
879(defun py2texi-fix-newlines ()
880 "Remove extra newlines."
881 (py2texi-search "\n\n\n+"
882 (replace-match "\n\n"))
883 (py2texi-search-safe "@item.*\n\n"
884 (delete-backward-char 1))
885 (py2texi-search "@end example"
886 (unless (looking-at "\n\n")
887 (insert "\n"))))
888
889
890(defun py2texi-destroy-empties ()
891 "Remove all comments.
892This avoids some makeinfo errors."
893 (py2texi-search "@c\\>"
894 (unless (eq (py2texi-protected) t)
895 (delete-region (- (point) 2) (save-excursion (end-of-line) (point)))
896 (cond
897 ((looking-at "\n\n")
898 (delete-char 1))
899 ((save-excursion (re-search-backward "^[ \t]*\\=" nil t))
900 (delete-region (save-excursion (beginning-of-line) (point))
901 (1+ (point))))))))
902
903
904(defun py2texi-adjust-level ()
905 "Increase heading level to @chapter, if needed.
906This is only needed for distutils, so it has a very simple form only."
907 (goto-char (point-min))
908 (unless (re-search-forward "@chapter\\>" nil t)
909 (py2texi-search-safe "@section\\>"
910 (replace-match "@chapter" t))
911 (py2texi-search-safe "@\\(sub\\)\\(sub\\)?section\\>"
912 (replace-match "" nil nil nil 1))))
913
914
915(defun py2texi-texinfo-escape (beg end)
916 "Escape Texinfo special characters in region."
917 (save-excursion
918 (goto-char beg)
919 (while (re-search-forward "[@{}]" end t)
920 (replace-match "@\\&"))))
921
922
923(defun py2texi-protected ()
924 "Return protection status of the point before current point."
925 (get-text-property (1- (point)) 'py2texi-protected))
926
927
928;;; Announce
929
930(provide 'py2texi)
931
932
933;;; py2texi.el ends here