blob: 82dc5bb994c9c0173d4607c4d96f61ee942af893 [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")
Fred Drake85002632003-07-16 03:35:41 +0000192 "@end multitable\n")
193 ("alltt" 0 "@example" "@end example")
194 )
Fred Drakebfc18bd2002-05-03 04:50:51 +0000195 "Associative list defining substitutions for environments.
196Each list item is of the form (ENVIRONMENT ARGNUM BEGIN END) where:
197- ENVIRONMENT is LaTeX environment name
198- ARGNUM is number of (required) macro arguments
199- BEGIN is substitution for \begin{ENVIRONMENT}
200- END is substitution for \end{ENVIRONMENT}
201Both BEGIN and END are evaled. Moreover, you can reference arguments through
202\N regular expression notation in strings of BEGIN.")
203
204(defconst py2texi-commands
Fred Drake7769bb92003-07-16 03:16:34 +0000205 '(("AA" 0 "@AA{}")
206 ("aa" 0 "@aa{}")
207 ("ABC" 0 "ABC")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000208 ("appendix" 0 (progn (setq appendix t) ""))
209 ("ASCII" 0 "ASCII")
210 ("author" 1 (progn (setq author (match-string 1 string)) ""))
211 ("authoraddress" 1
212 (progn (setq author-address (match-string 1 string)) ""))
213 ("b" 1 "@w{\\1}")
Andrew M. Kuchlinge970d2a2004-07-17 14:43:32 +0000214 ("backslash" 0 "@backslash{}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000215 ("bf" 0 "@destroy")
216 ("bifuncindex" 1 (progn (setq findex t) "@findex{\\1}"))
217 ("C" 0 "C")
218 ("c" 0 "@,")
219 ("catcode" 0 "")
220 ("cdata" 1 "@code{\\1}")
221 ("centerline" 1 "@center \\1")
Fred Drake66abcee2002-11-13 19:31:04 +0000222 ("cfuncline" 3 "@itemx \\1 \\2(\\3)\n@findex \\2")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000223 ("cfunction" 1 "@code{\\1}")
224 ("chapter" 1 (format "@node \\1\n@%s \\1\n"
225 (if appendix "appendix" "chapter")))
226 ("chapter*" 1 "@node \\1\n@unnumbered \\1\n")
227 ("character" 1 "@samp{\\1}")
228 ("citetitle" 1 "@ref{Top,,,\\1}")
229 ("class" 1 "@code{\\1}")
Fred Drake66abcee2002-11-13 19:31:04 +0000230 ("cmemberline" 3 "@itemx \\2 \\3\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000231 ("code" 1 "@code{\\1}")
232 ("command" 1 "@command{\\1}")
233 ("constant" 1 "@code{\\1}")
234 ("copyright" 1 "@copyright{}")
235 ("Cpp" 0 "C++")
Fred Draked805fef2002-06-27 18:38:06 +0000236 ("csimplemacro" 1 "@code{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000237 ("ctype" 1 "@code{\\1}")
238 ("dataline" 1 (progn (setq findex t) "@item \\1\n@findex \\1\n"))
239 ("date" 1 "\\1")
240 ("declaremodule" 2 (progn (setq cindex t) "@label{\\2}@cindex{\\2}"))
241 ("deprecated" 2 "@emph{This is deprecated in Python \\1. \\2}")
242 ("dfn" 1 "@dfn{\\1}")
243 ("documentclass" 1 py2texi-magic)
244 ("e" 0 "@backslash{}")
245 ("else" 0 (concat "@end ifinfo\n@" (setq last-if "iftex")))
Fred Drake3b095582003-07-02 14:22:48 +0000246 ("env" 1 "@code{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000247 ("EOF" 0 "@code{EOF}")
248 ("email" 1 "@email{\\1}")
249 ("emph" 1 "@emph{\\1}")
Fred Drake0bb242b2003-07-16 03:44:48 +0000250 ("envvar" 1 "@env{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000251 ("exception" 1 "@code{\\1}")
252 ("exindex" 1 (progn (setq obindex t) "@obindex{\\1}"))
253 ("fi" 0 (concat "@end " last-if))
254 ("file" 1 "@file{\\1}")
Fred Drake3b095582003-07-02 14:22:48 +0000255 ("filenq" 1 "@file{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000256 ("filevar" 1 "@file{@var{\\1}}")
257 ("footnote" 1 "@footnote{\\1}")
258 ("frac" 0 "")
259 ("funcline" 2 (progn (setq findex t) "@item \\1 \\2\n@findex \\1"))
260 ("funclineni" 2 "@item \\1 \\2")
261 ("function" 1 "@code{\\1}")
262 ("grammartoken" 1 "@code{\\1}")
Fred Drakecc933af2005-03-10 03:59:35 +0000263 ("guilabel" 1 "@strong{\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000264 ("hline" 0 "")
265 ("ifhtml" 0 (concat "@" (setq last-if "ifinfo")))
266 ("iftexi" 0 (concat "@" (setq last-if "ifinfo")))
267 ("index" 1 (progn (setq cindex t) "@cindex{\\1}"))
268 ("indexii" 2 (progn (setq cindex t) "@cindex{\\1 \\2}"))
269 ("indexiii" 3 (progn (setq cindex t) "@cindex{\\1 \\2 \\3}"))
270 ("indexiv" 3 (progn (setq cindex t) "@cindex{\\1 \\2 \\3 \\4}"))
271 ("infinity" 0 "@emph{infinity}")
272 ("it" 0 "@destroy")
273 ("kbd" 1 "@key{\\1}")
274 ("keyword" 1 "@code{\\1}")
275 ("kwindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
276 ("label" 1 "@label{\\1}")
277 ("Large" 0 "")
278 ("LaTeX" 0 "La@TeX{}")
279 ("large" 0 "")
280 ("ldots" 0 "@dots{}")
281 ("leftline" 1 "\\1")
282 ("lineii" 2 "@item \\1 @tab \\2")
283 ("lineiii" 3 "@item \\1 @tab \\2 @tab \\3")
284 ("lineiv" 4 "@item \\1 @tab \\2 @tab \\3 @tab \\4")
285 ("linev" 5 "@item \\1 @tab \\2 @tab \\3 @tab \\4 @tab \\5")
286 ("localmoduletable" 0 "")
287 ("longprogramopt" 1 "@option{--\\1}")
Fred Drake3b095582003-07-02 14:22:48 +0000288 ("macro" 1 "@code{@backslash{}\\1}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000289 ("mailheader" 1 "@code{\\1}")
290 ("makeindex" 0 "")
291 ("makemodindex" 0 "")
292 ("maketitle" 0 (concat "@top " title "\n"))
293 ("makevar" 1 "@code{\\1}")
294 ("manpage" 2 "@samp{\\1(\\2)}")
295 ("mbox" 1 "@w{\\1}")
296 ("member" 1 "@code{\\1}")
297 ("memberline" 1 "@item \\1\n@findex \\1\n")
298 ("menuselection" 1 "@samp{\\1}")
299 ("method" 1 "@code{\\1}")
300 ("methodline" 2 (progn (setq moindex t) "@item \\1(\\2)\n@moindex \\1\n"))
301 ("methodlineni" 2 "@item \\1(\\2)\n")
302 ("mimetype" 1 "@samp{\\1}")
303 ("module" 1 "@samp{\\1}")
Fred Drake66abcee2002-11-13 19:31:04 +0000304 ("moduleauthor" 2 "")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000305 ("modulesynopsis" 1 "\\1")
306 ("moreargs" 0 "@dots{}")
307 ("n" 0 "@backslash{}n")
308 ("newcommand" 2 "")
309 ("newsgroup" 1 "@samp{\\1}")
310 ("nodename" 1
311 (save-excursion
312 (save-match-data
313 (re-search-backward "^@node "))
314 (delete-region (point) (save-excursion (end-of-line) (point)))
315 (insert "@node " (match-string 1 string))
316 ""))
317 ("noindent" 0 "@noindent ")
318 ("note" 1 "@emph{Note:} \\1")
319 ("NULL" 0 "@code{NULL}")
320 ("obindex" 1 (progn (setq obindex t) "@obindex{\\1}"))
321 ("opindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
322 ("option" 1 "@option{\\1}")
323 ("optional" 1 "[\\1]")
324 ("pep" 1 (progn (setq cindex t) "PEP@ \\1@cindex PEP \\1\n"))
325 ("pi" 0 "pi")
326 ("platform" 1 "")
327 ("plusminus" 0 "+-")
328 ("POSIX" 0 "POSIX")
329 ("production" 2 "@item \\1 \\2")
Fred Drake66abcee2002-11-13 19:31:04 +0000330 ("productioncont" 1 "@item @w{} \\1")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000331 ("program" 1 "@command{\\1}")
332 ("programopt" 1 "@option{\\1}")
333 ("protect" 0 "")
334 ("pytype" 1 "@code{\\1}")
335 ("ref" 1 "@ref{\\1}")
336 ("refbimodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
337 ("refmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
338 ("refmodule" 1 "@samp{\\1}")
339 ("refstmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
340 ("regexp" 1 "\"\\1\"")
341 ("release" 1
342 (progn (setq py2texi-python-version (match-string 1 string)) ""))
343 ("renewcommand" 2 "")
344 ("rfc" 1 (progn (setq cindex t) "RFC@ \\1@cindex RFC \\1\n"))
345 ("rm" 0 "@destroy")
346 ("samp" 1 "@samp{\\1}")
347 ("section" 1 (let ((str (match-string 1 string)))
348 (save-match-data
349 (if (string-match "\\(.*\\)[ \t\n]*---[ \t\n]*\\(.*\\)"
350 str)
351 (format
352 "@node %s\n@section %s\n"
353 (py2texi-backslash-quote (match-string 1 str))
354 (py2texi-backslash-quote (match-string 2 str)))
355 "@node \\1\n@section \\1\n"))))
Fred Drake66abcee2002-11-13 19:31:04 +0000356 ("sectionauthor" 2 "")
Fred Drakecc933af2005-03-10 03:59:35 +0000357 ("seelink" 3 "\n@table @url\n@item @strong{\\1}\n(\\2)\n\\3\n@end table\n")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000358 ("seemodule" 2 "@ref{\\1} \\2")
359 ("seepep" 3 "\n@table @strong\n@item PEP\\1 \\2\n\\3\n@end table\n")
360 ("seerfc" 3 "\n@table @strong\n@item RFC\\1 \\2\n\\3\n@end table\n")
361 ("seetext" 1 "\\1")
362 ("seetitle" 1 "@cite{\\1}")
363 ("seeurl" 2 "\n@table @url\n@item \\1\n\\2\n@end table\n")
364 ("setindexsubitem" 1 (progn (setq cindex t) "@cindex \\1"))
365 ("setreleaseinfo" 1 (progn (setq py2texi-releaseinfo "")))
366 ("setshortversion" 1
367 (progn (setq py2texi-python-short-version (match-string 1 string)) ""))
368 ("shortversion" 0 py2texi-python-short-version)
369 ("sqrt" 0 "")
370 ("stindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
371 ("stmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
372 ("strong" 1 "@strong{\\1}")
373 ("sub" 0 "/")
374 ("subsection" 1 "@node \\1\n@subsection \\1\n")
375 ("subsubsection" 1 "@node \\1\n@subsubsection \\1\n")
376 ("sum" 0 "")
377 ("tableofcontents" 0 "")
378 ("term" 1 "@item \\1")
Fred Drake3b095582003-07-02 14:22:48 +0000379 ("TeX" 0 "@TeX{}")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000380 ("textasciitilde" 0 "~")
381 ("textasciicircum" 0 "^")
382 ("textbackslash" 0 "@backslash{}")
Fred Draked805fef2002-06-27 18:38:06 +0000383 ("textgreater" 0 ">")
384 ("textless" 0 "<")
Fred Drakebfc18bd2002-05-03 04:50:51 +0000385 ("textrm" 1 "\\1")
386 ("texttt" 1 "@code{\\1}")
387 ("textunderscore" 0 "_")
388 ("title" 1 (progn (setq title (match-string 1 string)) "@settitle \\1"))
389 ("today" 0 "@today{}")
390 ("token" 1 "@code{\\1}")
391 ("tt" 0 "@destroy")
392 ("ttindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
393 ("u" 0 "@backslash{}u")
394 ("ulink" 2 "\\1")
395 ("UNIX" 0 "UNIX")
396 ("unspecified" 0 "@dots{}")
397 ("url" 1 "@url{\\1}")
398 ("usepackage" 1 "")
399 ("var" 1 "@var{\\1}")
400 ("verbatiminput" 1 "@code{\\1}")
401 ("version" 0 py2texi-python-version)
402 ("versionadded" 1 "@emph{Added in Python version \\1}")
403 ("versionchanged" 1 "@emph{Changed in Python version \\1}")
404 ("vskip" 1 "")
405 ("vspace" 1 "")
406 ("warning" 1 "@emph{\\1}")
407 ("withsubitem" 2 "\\2")
408 ("XXX" 1 "@strong{\\1}"))
409 "Associative list of command substitutions.
410Each list item is of the form (COMMAND ARGNUM SUBSTITUTION) where:
411- COMMAND is LaTeX command name
412- ARGNUM is number of (required) command arguments
413- SUBSTITUTION substitution for the command. It is evaled and you can
414 reference command arguments through the \\N regexp notation in strings.")
415
416(defvar py2texi-magic "@documentclass\n"
417 "\"Magic\" string for auxiliary insertion at the beginning of document.")
418
419(defvar py2texi-dirs '("./" "../texinputs/")
420 "Where to search LaTeX input files.")
421
422(defvar py2texi-buffer "*py2texi*"
423 "The name of a buffer where Texinfo is generated.")
424
425(defconst py2texi-xemacs (string-match "^XEmacs" (emacs-version))
426 "Running under XEmacs?")
427
428
429(defmacro py2texi-search (regexp &rest body)
430 `(progn
431 (goto-char (point-min))
432 (while (re-search-forward ,regexp nil t)
433 ,@body)))
434
435(defmacro py2texi-search-safe (regexp &rest body)
436 `(py2texi-search ,regexp
437 (unless (py2texi-protected)
438 ,@body)))
439
440
441(defun py2texi-message (message)
442 "Report message and stop if `py2texi-stop-on-problems' is non-nil."
443 (if py2texi-stop-on-problems
444 (error message)
445 (message message)))
446
447
448(defun py2texi-backslash-quote (string)
449 "Double backslahes in STRING."
450 (let ((i 0))
451 (save-match-data
452 (while (setq i (string-match "\\\\" string i))
453 (setq string (replace-match "\\\\\\\\" t nil string))
454 (setq i (+ i 2))))
455 string))
456
457
458(defun py2texi (file)
459 "Convert Python LaTeX documentation FILE to Texinfo."
460 (interactive "fFile to convert: ")
461 (switch-to-buffer (get-buffer-create py2texi-buffer))
462 (erase-buffer)
463 (insert-file file)
464 (let ((case-fold-search nil)
465 (title "")
466 (author "")
467 (author-address "")
468 (appendix nil)
469 (findex nil)
470 (obindex nil)
471 (cindex nil)
472 (moindex nil)
473 last-if)
474 (py2texi-process-verbatims)
475 (py2texi-process-comments)
476 (py2texi-process-includes)
477 (py2texi-process-funnyas)
478 (py2texi-process-environments)
479 (py2texi-process-commands)
480 (py2texi-fix-indentation)
481 (py2texi-fix-nodes)
482 (py2texi-fix-references)
483 (py2texi-fix-indices)
484 (py2texi-process-simple-commands)
485 (py2texi-fix-fonts)
486 (py2texi-fix-braces)
487 (py2texi-fix-backslashes)
488 (py2texi-destroy-empties)
489 (py2texi-fix-newlines)
490 (py2texi-adjust-level))
Fred Drake66abcee2002-11-13 19:31:04 +0000491 (let* ((texi-file-name (or py2texi-texi-file-name
492 (py2texi-texi-file-name file)))
493 (info-file-name (or py2texi-info-file-name
494 (py2texi-info-file-name texi-file-name))))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000495 (goto-char (point-min))
496 (when (looking-at py2texi-magic)
497 (delete-region (point) (progn (beginning-of-line 2) (point)))
498 (insert "\\input texinfo @c -*-texinfo-*-\n")
Fred Drake66abcee2002-11-13 19:31:04 +0000499 (insert "@setfilename " info-file-name))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000500 (when (re-search-forward "@chapter" nil t)
501 (texinfo-all-menus-update t))
502 (goto-char (point-min))
Fred Drake66abcee2002-11-13 19:31:04 +0000503 (write-file texi-file-name)
504 (message (format "You can apply `makeinfo %s' now." texi-file-name))))
505
506
507(defun py2texi-texi-file-name (filename)
508 "Generate name of Texinfo file from original file name FILENAME."
509 (concat filename
510 (if (string-match "\\.tex$" filename) "i" ".texi")))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000511
512
513(defun py2texi-info-file-name (filename)
514 "Generate name of info file from original file name FILENAME."
515 (setq filename (expand-file-name filename))
516 (let ((directory (file-name-directory filename))
517 (basename (file-name-nondirectory filename)))
518 (concat directory "python-"
519 (substring basename 0 (- (length basename) 4)) "info")))
520
521
522(defun py2texi-process-verbatims ()
523 "Process and protect verbatim environments."
524 (let (delimiter
525 beg
526 end)
527 (py2texi-search-safe "\\\\begin{\\(verbatim\\|displaymath\\)}"
528 (replace-match "@example")
529 (setq beg (copy-marker (point) nil))
530 (re-search-forward "\\\\end{\\(verbatim\\|displaymath\\)}")
531 (setq end (copy-marker (match-beginning 0) nil))
532 (replace-match "@end example")
533 (py2texi-texinfo-escape beg end)
534 (put-text-property (- beg (length "@example"))
535 (+ end (length "@end example"))
536 'py2texi-protected t))
537 (py2texi-search-safe "\\\\verb\\([^a-z]\\)"
538 (setq delimiter (match-string 1))
539 (replace-match "@code{")
540 (setq beg (copy-marker (point) nil))
541 (re-search-forward (regexp-quote delimiter))
542 (setq end (copy-marker (match-beginning 0) nil))
543 (replace-match "}")
544 (put-text-property (- beg (length "@code{")) (+ end (length "}"))
545 'py2texi-protected t)
546 (py2texi-texinfo-escape beg end))))
547
548
549(defun py2texi-process-comments ()
550 "Remove comments."
551 (let (point)
552 (py2texi-search-safe "%"
553 (setq point (point))
554 (when (save-excursion
555 (re-search-backward "\\(^\\|[^\\]\\(\\\\\\\\\\)*\\)%\\=" nil t))
556 (delete-region (1- point)
557 (save-excursion (beginning-of-line 2) (point)))))))
558
559
560(defun py2texi-process-includes ()
561 "Include LaTeX input files.
562Do not include .ind files."
563 (let ((path (file-name-directory file))
564 filename
565 dirs
566 includefile)
567 (py2texi-search-safe "\\\\input{\\([^}]+\\)}"
568 (setq filename (match-string 1))
569 (unless (save-match-data (string-match "\\.tex$" filename))
570 (setq filename (concat filename ".tex")))
571 (setq includefile (save-match-data
572 (string-match "\\.ind\\.tex$" filename)))
573 (setq dirs py2texi-dirs)
574 (while (and (not includefile) dirs)
Fred Draked4956aa2003-09-28 03:10:09 +0000575 (setq includefile
576 (concat (file-name-as-directory (car dirs)) filename))
577 (if (not (file-name-absolute-p includefile))
578 (setq includefile
579 (concat (file-name-as-directory path) includefile)))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000580 (unless (file-exists-p includefile)
Fred Draked4956aa2003-09-28 03:10:09 +0000581 (setq includefile nil)
Fred Drakebfc18bd2002-05-03 04:50:51 +0000582 (setq dirs (cdr dirs))))
583 (if includefile
584 (save-restriction
585 (narrow-to-region (match-beginning 0) (match-end 0))
586 (delete-region (point-min) (point-max))
587 (when (stringp includefile)
588 (insert-file-contents includefile)
589 (goto-char (point-min))
590 (insert "\n")
591 (py2texi-process-verbatims)
592 (py2texi-process-comments)
593 (py2texi-process-includes)))
594 (replace-match (format "\\\\emph{Included file %s}" filename))
595 (py2texi-message (format "Input file %s not found" filename))))))
596
597
598(defun py2texi-process-funnyas ()
599 "Convert @s."
600 (py2texi-search-safe "@"
601 (replace-match "@@")))
602
603
604(defun py2texi-process-environments ()
605 "Process LaTeX environments."
606 (let ((stack ())
607 kind
608 environment
609 parameter
610 arguments
611 n
612 string
613 description)
614 (py2texi-search-safe (concat "\\\\\\(begin\\|end\\|item\\)"
615 "\\({\\([^}]*\\)}\\|[[]\\([^]]*\\)[]]\\|\\)")
616 (setq kind (match-string 1)
617 environment (match-string 3)
618 parameter (match-string 4))
619 (replace-match "")
620 (cond
621 ((string= kind "begin")
622 (setq description (assoc environment py2texi-environments))
623 (if description
624 (progn
625 (setq n (cadr description))
626 (setq description (cddr description))
627 (setq string (py2texi-tex-arguments n))
628 (string-match (py2texi-regexp n) string)
629 ; incorrect but sufficient
630 (insert (replace-match (eval (car description))
631 t nil string))
632 (setq stack (cons (cadr description) stack)))
633 (py2texi-message (format "Unknown environment: %s" environment))
634 (setq stack (cons "" stack))))
635 ((string= kind "end")
636 (insert (eval (car stack)))
637 (setq stack (cdr stack)))
638 ((string= kind "item")
639 (insert "\n@item " (or parameter "") "\n"))))
640 (when stack
641 (py2texi-message (format "Unclosed environment: %s" (car stack))))))
642
643
644(defun py2texi-process-commands ()
645 "Process LaTeX commands."
646 (let (done
647 command
648 command-info
649 string
650 n)
651 (while (not done)
652 (setq done t)
653 (py2texi-search-safe "\\\\\\([a-zA-Z*]+\\)\\(\\[[^]]*\\]\\)?"
654 (setq command (match-string 1))
655 (setq command-info (assoc command py2texi-commands))
656 (if command-info
657 (progn
658 (setq done nil)
659 (replace-match "")
660 (setq command-info (cdr command-info))
661 (setq n (car command-info))
662 (setq string (py2texi-tex-arguments n))
663 (string-match (py2texi-regexp n) string)
664 ; incorrect but sufficient
665 (insert (replace-match (eval (cadr command-info))
666 t nil string)))
667 (py2texi-message (format "Unknown command: %s (not processed)"
668 command)))))))
669
670
671(defun py2texi-argument-pattern (count)
672 (let ((filler "\\(?:[^{}]\\|\\\\{\\|\\\\}\\)*"))
673 (if (<= count 0)
674 filler
675 (concat filler "\\(?:{"
676 (py2texi-argument-pattern (1- count))
677 "}" filler "\\)*" filler))))
678(defconst py2texi-tex-argument
679 (concat
680 "{\\("
681 (py2texi-argument-pattern 10) ;really at least 10!
682 "\\)}[ \t%@c\n]*")
683 "Regexp describing LaTeX command argument including argument separators.")
684
685
686(defun py2texi-regexp (n)
687 "Make regexp matching N LaTeX command arguments."
688 (if (= n 0)
689 ""
690 (let ((regexp "^[^{]*"))
691 (while (> n 0)
692 (setq regexp (concat regexp py2texi-tex-argument))
693 (setq n (1- n)))
694 regexp)))
695
696
697(defun py2texi-tex-arguments (n)
698 "Remove N LaTeX command arguments and return them as a string."
699 (let ((point (point))
700 (i 0)
701 result
702 match)
703 (if (= n 0)
704 (progn
705 (when (re-search-forward "\\=\\({}\\| *\\)" nil t)
706 (replace-match ""))
707 "")
708 (while (> n 0)
709 (unless (re-search-forward
710 "\\(\\=\\|[^\\\\]\\)\\(\\\\\\\\\\)*\\([{}]\\)" nil t)
711 (debug))
712 (if (string= (match-string 3) "{")
713 (setq i (1+ i))
714 (setq i (1- i))
715 (when (<= i 0)
716 (setq n (1- n)))))
717 (setq result (buffer-substring-no-properties point (point)))
718 (while (string-match "\n[ \t]*" result)
719 (setq result (replace-match " " t nil result)))
720 (delete-region point (point))
721 result)))
722
723
724(defun py2texi-process-simple-commands ()
725 "Replace single character LaTeX commands."
726 (let (char)
727 (py2texi-search-safe "\\\\\\([^a-z]\\)"
728 (setq char (match-string 1))
729 (replace-match (format "%s%s"
730 (if (or (string= char "{")
731 (string= char "}")
732 (string= char " "))
733 "@"
734 "")
735 (if (string= char "\\")
736 "\\\\"
737 char))))))
738
739
740(defun py2texi-fix-indentation ()
741 "Remove white space at the beginning of lines."
742 (py2texi-search-safe "^[ \t]+"
743 (replace-match "")))
744
745
746(defun py2texi-fix-nodes ()
747 "Remove unwanted characters from nodes and make nodes unique."
748 (let ((nodes (make-hash-table :test 'equal))
749 id
750 counter
751 string
Fred Drake66abcee2002-11-13 19:31:04 +0000752 label
753 index)
Fred Drakebfc18bd2002-05-03 04:50:51 +0000754 (py2texi-search "^@node +\\(.*\\)$"
755 (setq string (match-string 1))
756 (if py2texi-xemacs
757 (replace-match "@node " t)
758 (replace-match "" t nil nil 1))
Fred Drake66abcee2002-11-13 19:31:04 +0000759 (while (string-match "@label{[^}]*}" string)
Fred Drakebfc18bd2002-05-03 04:50:51 +0000760 (setq label (match-string 0 string))
761 (setq string (replace-match "" t nil string)))
Fred Drake66abcee2002-11-13 19:31:04 +0000762 (while (string-match "@..?index{[^}]*}" string)
763 (setq index (match-string 0 string))
764 (setq string (replace-match "" t nil string)))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000765 (while (string-match "@[a-zA-Z]+\\|[{}():]\\|``\\|''" string)
766 (setq string (replace-match "" t nil string)))
767 (while (string-match " -- " string)
768 (setq string (replace-match " - " t nil string)))
Fred Drake66abcee2002-11-13 19:31:04 +0000769 (while (string-match "\\." string)
770 (setq string (replace-match "" t nil string)))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000771 (when (string-match " +$" string)
772 (setq string (replace-match "" t nil string)))
773 (when (string-match "^\\(Built-in\\|Standard\\) Module \\|The " string)
774 (setq string (replace-match "" t nil string)))
775 (string-match "^[^,]+" string)
776 (setq id (match-string 0 string))
777 (setq counter (gethash id nodes))
778 (if counter
779 (progn
780 (setq counter (1+ counter))
781 (setq string (replace-match (format "\\& %d" counter)
782 t nil string)))
783 (setq counter 1))
784 (setf (gethash id nodes) counter)
785 (insert string)
Fred Drake66abcee2002-11-13 19:31:04 +0000786 (beginning-of-line 3)
Fred Drakebfc18bd2002-05-03 04:50:51 +0000787 (when label
Fred Drake66abcee2002-11-13 19:31:04 +0000788 (insert label "\n"))
789 (when index
790 (insert index "\n")))))
Fred Drakebfc18bd2002-05-03 04:50:51 +0000791
792
793(defun py2texi-fix-references ()
794 "Process labels and make references to point to appropriate nodes."
795 (let ((labels ())
796 node)
797 (py2texi-search-safe "@label{\\([^}]*\\)}"
798 (setq node (save-excursion
799 (save-match-data
800 (and (re-search-backward "@node +\\([^,\n]+\\)" nil t)
801 (match-string 1)))))
802 (when node
803 (setq labels (cons (cons (match-string 1) node) labels)))
804 (replace-match ""))
805 (py2texi-search-safe "@ref{\\([^}]*\\)}"
806 (setq node (assoc (match-string 1) labels))
807 (replace-match "")
808 (when node
809 (insert (format "@ref{%s}" (cdr node)))))))
810
811
812(defun py2texi-fix-indices ()
813 "Remove unwanted characters from @*index commands and create final indices."
814 (py2texi-search-safe "@..?index\\>[^\n]*\\(\\)\n"
815 (replace-match "" t nil nil 1))
816 (py2texi-search-safe "@..?index\\>[^\n]*\\(\\)"
817 (replace-match "\n" t nil nil 1))
818 (py2texi-search-safe "@..?index\\({\\)\\([^}]+\\)\\(}+\\)"
819 (replace-match " " t nil nil 1)
820 (replace-match "" t nil nil 3)
821 (let ((string (match-string 2)))
822 (save-match-data
823 (while (string-match "@[a-z]+{" string)
824 (setq string (replace-match "" nil nil string)))
825 (while (string-match "{" string)
826 (setq string (replace-match "" nil nil string))))
827 (replace-match string t t nil 2)))
828 (py2texi-search-safe "@..?index\\>.*\\([{}]\\|@[a-z]*\\)"
829 (replace-match "" t nil nil 1)
830 (goto-char (match-beginning 0)))
831 (py2texi-search-safe "[^\n]\\(\\)@..?index\\>"
832 (replace-match "\n" t nil nil 1))
833 (goto-char (point-max))
834 (re-search-backward "@indices")
835 (replace-match "")
836 (insert (if moindex
837 (concat "@node Module Index\n"
838 "@unnumbered Module Index\n"
839 "@printindex mo\n")
840 "")
841 (if obindex
842 (concat "@node Class-Exception-Object Index\n"
843 "@unnumbered Class, Exception, and Object Index\n"
844 "@printindex ob\n")
845 "")
846 (if findex
847 (concat "@node Function-Method-Variable Index\n"
848 "@unnumbered Function, Method, and Variable Index\n"
849 "@printindex fn\n")
850 "")
851 (if cindex
852 (concat "@node Miscellaneous Index\n"
853 "@unnumbered Miscellaneous Index\n"
854 "@printindex cp\n")
855 "")))
856
857
858(defun py2texi-fix-backslashes ()
859 "Make backslashes from auxiliary commands."
860 (py2texi-search-safe "@backslash{}"
861 (replace-match "\\\\")))
862
863
864(defun py2texi-fix-fonts ()
865 "Remove garbage after unstructured font commands."
866 (let (string)
867 (py2texi-search-safe "@destroy"
868 (replace-match "")
869 (when (eq (preceding-char) ?{)
870 (forward-char -1)
871 (setq string (py2texi-tex-arguments 1))
872 (insert (substring string 1 (1- (length string))))))))
873
874
875(defun py2texi-fix-braces ()
876 "Escape braces for Texinfo."
877 (let (string)
878 (py2texi-search "{"
879 (unless (or (py2texi-protected)
880 (save-excursion
881 (re-search-backward
882 "@\\([a-zA-Z]*\\|multitable.*\\){\\=" nil t)))
883 (forward-char -1)
884 (setq string (py2texi-tex-arguments 1))
885 (insert "@" (substring string 0 (1- (length string))) "@}")))))
886
887
888(defun py2texi-fix-newlines ()
889 "Remove extra newlines."
890 (py2texi-search "\n\n\n+"
891 (replace-match "\n\n"))
892 (py2texi-search-safe "@item.*\n\n"
893 (delete-backward-char 1))
894 (py2texi-search "@end example"
895 (unless (looking-at "\n\n")
896 (insert "\n"))))
897
898
899(defun py2texi-destroy-empties ()
900 "Remove all comments.
901This avoids some makeinfo errors."
902 (py2texi-search "@c\\>"
903 (unless (eq (py2texi-protected) t)
904 (delete-region (- (point) 2) (save-excursion (end-of-line) (point)))
905 (cond
906 ((looking-at "\n\n")
907 (delete-char 1))
908 ((save-excursion (re-search-backward "^[ \t]*\\=" nil t))
909 (delete-region (save-excursion (beginning-of-line) (point))
910 (1+ (point))))))))
911
912
913(defun py2texi-adjust-level ()
914 "Increase heading level to @chapter, if needed.
915This is only needed for distutils, so it has a very simple form only."
916 (goto-char (point-min))
917 (unless (re-search-forward "@chapter\\>" nil t)
918 (py2texi-search-safe "@section\\>"
919 (replace-match "@chapter" t))
920 (py2texi-search-safe "@\\(sub\\)\\(sub\\)?section\\>"
921 (replace-match "" nil nil nil 1))))
922
923
924(defun py2texi-texinfo-escape (beg end)
925 "Escape Texinfo special characters in region."
926 (save-excursion
927 (goto-char beg)
928 (while (re-search-forward "[@{}]" end t)
929 (replace-match "@\\&"))))
930
931
932(defun py2texi-protected ()
933 "Return protection status of the point before current point."
934 (get-text-property (1- (point)) 'py2texi-protected))
935
936
937;;; Announce
938
939(provide 'py2texi)
940
941
942;;; py2texi.el ends here