summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2002-05-03 04:50:51 (GMT)
committerFred Drake <fdrake@acm.org>2002-05-03 04:50:51 (GMT)
commitbfc18bdf031bb473e8f3ed5d9a880458893524a3 (patch)
tree5167c35af9f45319c75ce847a86c108a748e4b05
parenta3b0b298e6c5f5ced9e99dc067e809fece049e66 (diff)
downloadcpython-bfc18bdf031bb473e8f3ed5d9a880458893524a3.zip
cpython-bfc18bdf031bb473e8f3ed5d9a880458893524a3.tar.gz
cpython-bfc18bdf031bb473e8f3ed5d9a880458893524a3.tar.bz2
Integrated SF patch #539487 by Matthias Klose:
This patch adds Milan Zamazal's conversion script and modifies the mkinfo script to build the info doc files from the LaTeX sources. Currently, the mac, doc and inst TeX files are not handled. Explicitly checks for GNU Emacs 21.
-rw-r--r--Doc/Makefile5
-rw-r--r--Doc/info/Makefile97
-rw-r--r--Doc/info/python.dir6
-rwxr-xr-xDoc/tools/mkinfo19
-rw-r--r--Doc/tools/py2texi.el890
5 files changed, 958 insertions, 59 deletions
diff --git a/Doc/Makefile b/Doc/Makefile
index bbeb2a5..47d4fbc 100644
--- a/Doc/Makefile
+++ b/Doc/Makefile
@@ -88,6 +88,9 @@ BUILDINDEX=$(TOOLSDIR)/buildindex.py
PYTHONDOCS="See <i><a href=\"about.html\">About this document...</a></i> for information on suggesting changes."
HTMLBASE= file:`pwd`
+# The emacs binary used to build the info docs. GNU Emacs 21 is required.
+EMACS= emacs
+
# The end of this should reflect the major/minor version numbers of
# the release:
WHATSNEW=whatsnew23
@@ -287,7 +290,7 @@ paper-$(PAPER)/$(WHATSNEW).pdf:
# conversions, as described above. See also the README file.
info:
- cd $(INFODIR) && $(MAKE)
+ cd $(INFODIR) && $(MAKE) EMACS=$(EMACS)
# Targets to convert the manuals to HTML using Nikos Drakos' LaTeX to
# HTML converter. For more info on this program, see
diff --git a/Doc/info/Makefile b/Doc/info/Makefile
index a2c44d3..88c0d6e 100644
--- a/Doc/info/Makefile
+++ b/Doc/info/Makefile
@@ -4,70 +4,67 @@ TOPDIR=..
TOOLSDIR=$(TOPDIR)/tools
HTMLDIR=$(TOPDIR)/html
+# The emacs binary used to build the info docs. GNU Emacs 21 is required.
+EMACS=emacs
+
MKINFO=$(TOOLSDIR)/mkinfo
-SCRIPTS=$(TOOLSDIR)/html2texi.pl $(TOOLSDIR)/checkargs.pm $(TOOLSDIR)/mkinfo \
- $(TOOLSDIR)/fixinfo.el
+SCRIPTS=$(TOOLSDIR)/checkargs.pm $(TOOLSDIR)/mkinfo $(TOOLSDIR)/py2texi.el
+
+# set VERSION to code the VERSION number into the info file name
+# allowing installation of more than one set of python info docs
+# into the same directory
+VERSION=
-all: python-api.info python-ext.info python-lib.info \
- python-ref.info python-tut.info \
- python-dist.info python-inst.info
+all: check-emacs-version \
+ python$(VERSION)-api.info python$(VERSION)-ext.info \
+ python$(VERSION)-lib.info python$(VERSION)-ref.info \
+ python$(VERSION)-tut.info python$(VERSION)-dist.info
+# python$(VERSION)-doc.info python$(VERSION)-inst.info
+# python$(VERSION)-mac.info
-python-api.info: $(HTMLDIR)/api/api.html $(SCRIPTS)
- $(MKINFO) $<
+check-emacs-version:
+ @v="`$(EMACS) --version 2>&1 | egrep '^(GNU |X)Emacs [12]*'`"; \
+ if `echo "$$v" | grep '^GNU Emacs 21' >/dev/null 2>&1`; then \
+ echo "Using $(EMACS) to build the info docs"; \
+ else \
+ echo "GNU Emacs 21 is required to build the info docs"; \
+ echo "Found $$v"; \
+ false; \
+ fi
-python-ext.info: $(HTMLDIR)/ext/ext.html $(SCRIPTS)
- $(MKINFO) $<
+python$(VERSION)-api.info: ../api/api.tex $(SCRIPTS)
+ EMACS=$(EMACS) $(MKINFO) $< $@
-python-lib.info: $(HTMLDIR)/lib/lib.html $(SCRIPTS)
- $(MKINFO) $<
+python$(VERSION)-ext.info: ../ext/ext.tex $(SCRIPTS)
+ EMACS=$(EMACS) $(MKINFO) $< $@
+
+python$(VERSION)-lib.info: ../lib/lib.tex $(SCRIPTS)
+ EMACS=$(EMACS) $(MKINFO) $< $@
# Not built by default; the conversion doesn't really handle it well.
-python-mac.info: $(HTMLDIR)/mac/mac.html $(SCRIPTS)
- $(MKINFO) $<
+python$(VERSION)-mac.info: ../mac/mac.tex $(SCRIPTS)
+ EMACS=$(EMACS) $(MKINFO) $< $@
+
+python$(VERSION)-ref.info: ../ref/ref.tex $(SCRIPTS)
+ EMACS=$(EMACS) $(MKINFO) $< $@
-python-ref.info: $(HTMLDIR)/ref/ref.html $(SCRIPTS)
- $(MKINFO) $<
+python$(VERSION)-tut.info: ../tut/tut.tex $(SCRIPTS)
+ EMACS=$(EMACS) $(MKINFO) $< $@
-python-tut.info: $(HTMLDIR)/tut/tut.html $(SCRIPTS)
- $(MKINFO) $<
+# Not built by default; the conversion doesn't handle it at all.
+python$(VERSION)-doc.info: ../doc/doc.tex $(SCRIPTS)
+ EMACS=$(EMACS) $(MKINFO) $< $@
-python-dist.info: $(HTMLDIR)/dist/dist.html $(SCRIPTS)
- $(MKINFO) $<
+python$(VERSION)-dist.info: ../dist/dist.tex $(SCRIPTS)
+ EMACS=$(EMACS) $(MKINFO) $< $@
-python-inst.info: $(HTMLDIR)/inst/inst.html $(SCRIPTS)
- $(MKINFO) $<
+# Not built by default; the conversion chokes on two @end multitable's
+python$(VERSION)-inst.info: ../inst/inst.tex $(SCRIPTS)
+ EMACS=$(EMACS) $(MKINFO) $< $@
clean:
rm -f *.texi~ *.texi
clobber: clean
- rm -f *.texi python-*.info python-*.info-[0-9]*
-
-
-# This makes sure we can build info files from a "clean" tree,
-# in case we haven't already built the HTML:
-
-$(HTMLDIR)/api/api.html:
- cd $(HTMLDIR) && $(MAKE) api
-
-$(HTMLDIR)/ext/ext.html:
- cd $(HTMLDIR) && $(MAKE) ext
-
-$(HTMLDIR)/lib/lib.html:
- cd $(HTMLDIR) && $(MAKE) lib
-
-$(HTMLDIR)/mac/mac.html:
- cd $(HTMLDIR) && $(MAKE) mac
-
-$(HTMLDIR)/ref/ref.html:
- cd $(HTMLDIR) && $(MAKE) ref
-
-$(HTMLDIR)/tut/tut.html:
- cd $(HTMLDIR) && $(MAKE) tut
-
-$(HTMLDIR)/dist/dist.html:
- cd $(HTMLDIR) && $(MAKE) dist
-
-$(HTMLDIR)/inst/inst.html:
- cd $(HTMLDIR) && $(MAKE) inst
+ rm -f *.texi python*-*.info python*-*.info-[0-9]*
diff --git a/Doc/info/python.dir b/Doc/info/python.dir
index 9a09d70..dce2bb3 100644
--- a/Doc/info/python.dir
+++ b/Doc/info/python.dir
@@ -2,9 +2,11 @@
Python Standard Documentation
* Python Library: (python-lib). Python Library Reference
+* Python Mac Modules: (python-mac). Python Macintosh Modules
* Python Reference: (python-ref). Python Reference Manual
-* Python Distutils: (python-dist). Distributing Python Modules
* Python API: (python-api). Python/C API Reference Manual
* Python Extending: (python-ext). Extending & Embedding Python
-* Python Mac Modules: (python-mac). Python Macintosh Modules
* Python Tutorial: (python-tut). Python Tutorial
+* Documenting Python: (python-doc). Documenting Python
+* Installing Modules: (python-inst). Installing Python Modules
+* Distributing Modules: (python-dist). Distributing Python Modules
diff --git a/Doc/tools/mkinfo b/Doc/tools/mkinfo
index edba1db..64fb86e 100755
--- a/Doc/tools/mkinfo
+++ b/Doc/tools/mkinfo
@@ -17,7 +17,12 @@ MAKEINFO=${MAKEINFO:-makeinfo}
FILENAME="$1"
DOCDIR=`dirname "$FILENAME"`
DOCFILE=`basename "$FILENAME"`
-DOCNAME=`basename "$FILENAME" .html`
+DOCNAME=`basename "$FILENAME" .tex`
+if [ $# -gt 1 ]; then
+ INFONAME="$2"
+else
+ INFONAME="python-$DOCNAME.info"
+fi
# Now build the real directory names, and locate our support stuff:
WORKDIR=`pwd`
@@ -31,18 +36,20 @@ cd $WORKDIR
run() {
# show what we're doing, like make does:
echo "$*"
- $* || exit $?
+ "$@" || exit $?
}
# generate the Texinfo file:
-run $PERL -I$TOOLSDIR $TOOLSDIR/html2texi.pl $DOCDIR/$DOCFILE
-run $EMACS -batch -l $TOOLSDIR/fixinfo.el $DOCNAME.texi
-rm -f $DOCNAME.texi~
+run $EMACS -batch -q --no-site-file -l $TOOLSDIR/py2texi.el \
+ --eval "(setq py2texi-dirs '(\"./\" \"../texinputs/\" \"$DOCDIR\"))" \
+ --eval "(py2texi \"$DOCDIR/$DOCFILE\")" \
+ -f kill-emacs
+echo Done
# generate the .info files:
run $MAKEINFO --footnote-style end --fill-column 72 \
- --paragraph-indent 0 $DOCNAME.texi
+ --paragraph-indent 0 --output=$INFONAME $DOCNAME.texi
diff --git a/Doc/tools/py2texi.el b/Doc/tools/py2texi.el
new file mode 100644
index 0000000..98d452d
--- /dev/null
+++ b/Doc/tools/py2texi.el
@@ -0,0 +1,890 @@
+;;; py2texi.el -- Conversion of Python LaTeX documentation to Texinfo
+
+;; Copyright (C) 1998, 1999, 2001, 2002 Milan Zamazal
+
+;; Author: Milan Zamazal <pdm@zamazal.org>
+;; Version: $Id$
+;; Keywords: python
+
+;; COPYRIGHT NOTICE
+;;
+;; This program is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by the Free
+;; Software Foundation; either version 2, or (at your option) any later
+;; version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+;; for more details.
+;;
+;; You can find the GNU General Public License at
+;; http://www.gnu.org/copyleft/gpl.html
+;; or you can write to the Free Software Foundation, Inc., 59 Temple Place,
+;; Suite 330, Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This is a Q&D hack for conversion of Python manuals to on-line help format.
+;; I desperately needed usable online documenta for Python, so I wrote this.
+;; The result code is ugly and need not contain complete information from
+;; Python manuals. I apologize for my ignorance, especially ignorance to
+;; python.sty. Improvements of this convertor are welcomed.
+
+;; How to use it:
+;; Load this file and apply `M-x py2texi'. You will be asked for name of a
+;; file to be converted.
+
+;; Where to find it:
+;; New versions of this code might be found at
+;; http://www.zamazal.org/software/python/py2texi/ .
+
+;;; Code:
+
+
+(require 'texinfo)
+(eval-when-compile
+ (require 'cl))
+
+
+(defvar py2texi-python-version "2.2"
+ "What to substitute for the \\version macro.")
+
+(defvar py2texi-python-short-version
+ (progn
+ (string-match "[0-9]+\\.[0-9]+" py2texi-python-version)
+ (match-string 0 py2texi-python-version))
+ "Short version number, usually set by the LaTeX commands.")
+
+(defvar py2texi-stop-on-problems nil
+ "*If non-nil, stop when you encouter soft problem.")
+
+(defconst py2texi-environments
+ '(("abstract" 0 "@quotation" "@end quotation\n")
+ ("center" 0 "" "")
+ ("cfuncdesc" 3
+ (progn (setq findex t)
+ "\n@table @code\n@item \\1 \\2(\\3)\n@findex \\2\n")
+ "@end table")
+ ("classdesc" 2
+ (progn (setq obindex t)
+ "\n@table @code\n@item \\1(\\2)\n@obindex \\1\n")
+ "@end table")
+ ("classdesc*" 1
+ (progn (setq obindex t)
+ "\n@table @code\n@item \\1\n@obindex \\1\n")
+ "@end table")
+ ("csimplemacrodesc" 1
+ (progn (setq cindex t)
+ "\n@table @code\n@item \\1\n@cindex \\1\n")
+ "@end table")
+ ("ctypedesc" 1
+ (progn (setq cindex t)
+ "\n@table @code\n@item \\1\n@cindex \\1\n")
+ "@end table")
+ ("cvardesc" 2
+ (progn (setq findex t)
+ "\n@table @code\n@item \\1 \\2\n@findex \\2\n")
+ "@end table")
+ ("datadesc" 1
+ (progn (setq findex t)
+ "\n@table @code\n@item \\1\n@findex \\1\n")
+ "@end table")
+ ("datadescni" 1 "\n@table @code\n@item \\1\n" "@end table")
+ ("definitions" 0 "@table @dfn" "@end table\n")
+ ("description" 0 "@table @samp" "@end table\n")
+ ("displaymath" 0 "" "")
+ ("document" 0
+ (concat "@defcodeindex mo\n"
+ "@defcodeindex ob\n"
+ "@titlepage\n"
+ (format "@title " title "\n")
+ (format "@author " author "\n")
+ "@page\n"
+ author-address
+ "@end titlepage\n"
+ "@node Top, , , (dir)\n")
+ (concat "@indices\n"
+ "@contents\n"
+ "@bye\n"))
+ ("enumerate" 0 "@enumerate" "@end enumerate")
+ ("excdesc" 1
+ (progn (setq obindex t)
+ "\n@table @code\n@item \\1\n@obindex \\1\n")
+ "@end table")
+ ("excclassdesc" 2
+ (progn (setq obindex t)
+ "\n@table @code\n@item \\1(\\2)\n@obindex \\1\n")
+ "@end table")
+ ("flushleft" 0 "" "")
+ ("fulllineitems" 0 "\n@table @code\n" "@end table")
+ ("funcdesc" 2
+ (progn (setq findex t)
+ "\n@table @code\n@item \\1(\\2)\n@findex \\1\n")
+ "@end table")
+ ("funcdescni" 2 "\n@table @code\n@item \\1(\\2)\n" "@end table")
+ ("itemize" 0 "@itemize @bullet" "@end itemize\n")
+ ("list" 2 "\n@table @code\n" "@end table")
+ ("longtableii" 4 (concat "@multitable @columnfractions .5 .5\n"
+ "@item \\3 @tab \\4\n"
+ "@item ------- @tab ------ \n")
+ "@end multitable\n")
+ ("longtableiii" 5 (concat "@multitable @columnfractions .33 .33 .33\n"
+ "@item \\3 @tab \\4 @tab \\5\n"
+ "@item ------- @tab ------ @tab ------\n")
+ "@end multitable\n")
+ ("memberdesc" 1
+ (progn (setq findex t)
+ "\n@table @code\n@item \\1\n@findex \\1\n")
+ "@end table")
+ ("memberdescni" 1 "\n@table @code\n@item \\1\n" "@end table")
+ ("methoddesc" 2
+ (progn (setq findex t)
+ "\n@table @code\n@item \\1(\\2)\n@findex \\1\n")
+ "@end table")
+ ("methoddescni" 2 "\n@table @code\n@item \\1(\\2)\n" "@end table")
+ ("notice" 0 "@emph{Notice:} " "")
+ ("opcodedesc" 2
+ (progn (setq findex t)
+ "\n@table @code\n@item \\1 \\2\n@findex \\1\n")
+ "@end table")
+ ("productionlist" 0 "\n@table @code\n" "@end table")
+ ("quotation" 0 "@quotation" "@end quotation")
+ ("seealso" 0 "See also:\n@table @emph\n" "@end table")
+ ("seealso*" 0 "@table @emph\n" "@end table")
+ ("sloppypar" 0 "" "")
+ ("small" 0 "" "")
+ ("tableii" 4 (concat "@multitable @columnfractions .5 .5\n"
+ "@item \\3 @tab \\4\n"
+ "@item ------- @tab ------ \n")
+ "@end multitable\n")
+ ("tableiii" 5 (concat "@multitable @columnfractions .33 .33 .33\n"
+ "@item \\3 @tab \\4 @tab \\5\n"
+ "@item ------- @tab ------ @tab ------\n")
+ "@end multitable\n")
+ ("tableiv" 6 (concat
+ "@multitable @columnfractions .25 .25 .25 .25\n"
+ "@item \\3 @tab \\4 @tab \\5 @tab \\6\n"
+ "@item ------- @tab ------- @tab ------- @tab -------\n")
+ "@end multitable\n")
+ ("tablev" 7 (concat
+ "@multitable @columnfractions .20 .20 .20 .20 .20\n"
+ "@item \\3 @tab \\4 @tab \\5 @tab \\6 @tab \\7\n"
+ "@item ------- @tab ------- @tab ------- @tab ------- @tab -------\n")
+ "@end multitable\n"))
+ "Associative list defining substitutions for environments.
+Each list item is of the form (ENVIRONMENT ARGNUM BEGIN END) where:
+- ENVIRONMENT is LaTeX environment name
+- ARGNUM is number of (required) macro arguments
+- BEGIN is substitution for \begin{ENVIRONMENT}
+- END is substitution for \end{ENVIRONMENT}
+Both BEGIN and END are evaled. Moreover, you can reference arguments through
+\N regular expression notation in strings of BEGIN.")
+
+(defconst py2texi-commands
+ '(("ABC" 0 "ABC")
+ ("appendix" 0 (progn (setq appendix t) ""))
+ ("ASCII" 0 "ASCII")
+ ("author" 1 (progn (setq author (match-string 1 string)) ""))
+ ("authoraddress" 1
+ (progn (setq author-address (match-string 1 string)) ""))
+ ("b" 1 "@w{\\1}")
+ ("bf" 0 "@destroy")
+ ("bifuncindex" 1 (progn (setq findex t) "@findex{\\1}"))
+ ("C" 0 "C")
+ ("c" 0 "@,")
+ ("catcode" 0 "")
+ ("cdata" 1 "@code{\\1}")
+ ("centerline" 1 "@center \\1")
+ ("cfunction" 1 "@code{\\1}")
+ ("chapter" 1 (format "@node \\1\n@%s \\1\n"
+ (if appendix "appendix" "chapter")))
+ ("chapter*" 1 "@node \\1\n@unnumbered \\1\n")
+ ("character" 1 "@samp{\\1}")
+ ("citetitle" 1 "@ref{Top,,,\\1}")
+ ("class" 1 "@code{\\1}")
+ ("code" 1 "@code{\\1}")
+ ("command" 1 "@command{\\1}")
+ ("constant" 1 "@code{\\1}")
+ ("copyright" 1 "@copyright{}")
+ ("Cpp" 0 "C++")
+ ("ctype" 1 "@code{\\1}")
+ ("dataline" 1 (progn (setq findex t) "@item \\1\n@findex \\1\n"))
+ ("date" 1 "\\1")
+ ("declaremodule" 2 (progn (setq cindex t) "@label{\\2}@cindex{\\2}"))
+ ("deprecated" 2 "@emph{This is deprecated in Python \\1. \\2}")
+ ("dfn" 1 "@dfn{\\1}")
+ ("documentclass" 1 py2texi-magic)
+ ("e" 0 "@backslash{}")
+ ("else" 0 (concat "@end ifinfo\n@" (setq last-if "iftex")))
+ ("EOF" 0 "@code{EOF}")
+ ("email" 1 "@email{\\1}")
+ ("emph" 1 "@emph{\\1}")
+ ("envvar" 1 "@samp{\\1}")
+ ("exception" 1 "@code{\\1}")
+ ("exindex" 1 (progn (setq obindex t) "@obindex{\\1}"))
+ ("fi" 0 (concat "@end " last-if))
+ ("file" 1 "@file{\\1}")
+ ("filevar" 1 "@file{@var{\\1}}")
+ ("footnote" 1 "@footnote{\\1}")
+ ("frac" 0 "")
+ ("funcline" 2 (progn (setq findex t) "@item \\1 \\2\n@findex \\1"))
+ ("funclineni" 2 "@item \\1 \\2")
+ ("function" 1 "@code{\\1}")
+ ("grammartoken" 1 "@code{\\1}")
+ ("hline" 0 "")
+ ("ifhtml" 0 (concat "@" (setq last-if "ifinfo")))
+ ("iftexi" 0 (concat "@" (setq last-if "ifinfo")))
+ ("index" 1 (progn (setq cindex t) "@cindex{\\1}"))
+ ("indexii" 2 (progn (setq cindex t) "@cindex{\\1 \\2}"))
+ ("indexiii" 3 (progn (setq cindex t) "@cindex{\\1 \\2 \\3}"))
+ ("indexiv" 3 (progn (setq cindex t) "@cindex{\\1 \\2 \\3 \\4}"))
+ ("infinity" 0 "@emph{infinity}")
+ ("it" 0 "@destroy")
+ ("kbd" 1 "@key{\\1}")
+ ("keyword" 1 "@code{\\1}")
+ ("kwindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
+ ("label" 1 "@label{\\1}")
+ ("Large" 0 "")
+ ("LaTeX" 0 "La@TeX{}")
+ ("large" 0 "")
+ ("ldots" 0 "@dots{}")
+ ("leftline" 1 "\\1")
+ ("lineii" 2 "@item \\1 @tab \\2")
+ ("lineiii" 3 "@item \\1 @tab \\2 @tab \\3")
+ ("lineiv" 4 "@item \\1 @tab \\2 @tab \\3 @tab \\4")
+ ("linev" 5 "@item \\1 @tab \\2 @tab \\3 @tab \\4 @tab \\5")
+ ("localmoduletable" 0 "")
+ ("longprogramopt" 1 "@option{--\\1}")
+ ("mailheader" 1 "@code{\\1}")
+ ("makeindex" 0 "")
+ ("makemodindex" 0 "")
+ ("maketitle" 0 (concat "@top " title "\n"))
+ ("makevar" 1 "@code{\\1}")
+ ("manpage" 2 "@samp{\\1(\\2)}")
+ ("mbox" 1 "@w{\\1}")
+ ("member" 1 "@code{\\1}")
+ ("memberline" 1 "@item \\1\n@findex \\1\n")
+ ("menuselection" 1 "@samp{\\1}")
+ ("method" 1 "@code{\\1}")
+ ("methodline" 2 (progn (setq moindex t) "@item \\1(\\2)\n@moindex \\1\n"))
+ ("methodlineni" 2 "@item \\1(\\2)\n")
+ ("mimetype" 1 "@samp{\\1}")
+ ("module" 1 "@samp{\\1}")
+ ("moduleauthor" 2 "This module was written by \\1 @email{\\2}.@*")
+ ("modulesynopsis" 1 "\\1")
+ ("moreargs" 0 "@dots{}")
+ ("n" 0 "@backslash{}n")
+ ("newcommand" 2 "")
+ ("newsgroup" 1 "@samp{\\1}")
+ ("nodename" 1
+ (save-excursion
+ (save-match-data
+ (re-search-backward "^@node "))
+ (delete-region (point) (save-excursion (end-of-line) (point)))
+ (insert "@node " (match-string 1 string))
+ ""))
+ ("noindent" 0 "@noindent ")
+ ("note" 1 "@emph{Note:} \\1")
+ ("NULL" 0 "@code{NULL}")
+ ("obindex" 1 (progn (setq obindex t) "@obindex{\\1}"))
+ ("opindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
+ ("option" 1 "@option{\\1}")
+ ("optional" 1 "[\\1]")
+ ("pep" 1 (progn (setq cindex t) "PEP@ \\1@cindex PEP \\1\n"))
+ ("pi" 0 "pi")
+ ("platform" 1 "")
+ ("plusminus" 0 "+-")
+ ("POSIX" 0 "POSIX")
+ ("production" 2 "@item \\1 \\2")
+ ("program" 1 "@command{\\1}")
+ ("programopt" 1 "@option{\\1}")
+ ("protect" 0 "")
+ ("pytype" 1 "@code{\\1}")
+ ("ref" 1 "@ref{\\1}")
+ ("refbimodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
+ ("refmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
+ ("refmodule" 1 "@samp{\\1}")
+ ("refstmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
+ ("regexp" 1 "\"\\1\"")
+ ("release" 1
+ (progn (setq py2texi-python-version (match-string 1 string)) ""))
+ ("renewcommand" 2 "")
+ ("rfc" 1 (progn (setq cindex t) "RFC@ \\1@cindex RFC \\1\n"))
+ ("rm" 0 "@destroy")
+ ("samp" 1 "@samp{\\1}")
+ ("section" 1 (let ((str (match-string 1 string)))
+ (save-match-data
+ (if (string-match "\\(.*\\)[ \t\n]*---[ \t\n]*\\(.*\\)"
+ str)
+ (format
+ "@node %s\n@section %s\n"
+ (py2texi-backslash-quote (match-string 1 str))
+ (py2texi-backslash-quote (match-string 2 str)))
+ "@node \\1\n@section \\1\n"))))
+ ("sectionauthor" 2
+ "\nThis manual section was written by \\1 @email{\\2}.@*")
+ ("seemodule" 2 "@ref{\\1} \\2")
+ ("seepep" 3 "\n@table @strong\n@item PEP\\1 \\2\n\\3\n@end table\n")
+ ("seerfc" 3 "\n@table @strong\n@item RFC\\1 \\2\n\\3\n@end table\n")
+ ("seetext" 1 "\\1")
+ ("seetitle" 1 "@cite{\\1}")
+ ("seeurl" 2 "\n@table @url\n@item \\1\n\\2\n@end table\n")
+ ("setindexsubitem" 1 (progn (setq cindex t) "@cindex \\1"))
+ ("setreleaseinfo" 1 (progn (setq py2texi-releaseinfo "")))
+ ("setshortversion" 1
+ (progn (setq py2texi-python-short-version (match-string 1 string)) ""))
+ ("shortversion" 0 py2texi-python-short-version)
+ ("sqrt" 0 "")
+ ("stindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
+ ("stmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
+ ("strong" 1 "@strong{\\1}")
+ ("sub" 0 "/")
+ ("subsection" 1 "@node \\1\n@subsection \\1\n")
+ ("subsubsection" 1 "@node \\1\n@subsubsection \\1\n")
+ ("sum" 0 "")
+ ("tableofcontents" 0 "")
+ ("term" 1 "@item \\1")
+ ("textasciitilde" 0 "~")
+ ("textasciicircum" 0 "^")
+ ("textbackslash" 0 "@backslash{}")
+ ("textrm" 1 "\\1")
+ ("texttt" 1 "@code{\\1}")
+ ("textunderscore" 0 "_")
+ ("title" 1 (progn (setq title (match-string 1 string)) "@settitle \\1"))
+ ("today" 0 "@today{}")
+ ("token" 1 "@code{\\1}")
+ ("tt" 0 "@destroy")
+ ("ttindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
+ ("u" 0 "@backslash{}u")
+ ("ulink" 2 "\\1")
+ ("UNIX" 0 "UNIX")
+ ("unspecified" 0 "@dots{}")
+ ("url" 1 "@url{\\1}")
+ ("usepackage" 1 "")
+ ("var" 1 "@var{\\1}")
+ ("verbatiminput" 1 "@code{\\1}")
+ ("version" 0 py2texi-python-version)
+ ("versionadded" 1 "@emph{Added in Python version \\1}")
+ ("versionchanged" 1 "@emph{Changed in Python version \\1}")
+ ("vskip" 1 "")
+ ("vspace" 1 "")
+ ("warning" 1 "@emph{\\1}")
+ ("withsubitem" 2 "\\2")
+ ("XXX" 1 "@strong{\\1}"))
+ "Associative list of command substitutions.
+Each list item is of the form (COMMAND ARGNUM SUBSTITUTION) where:
+- COMMAND is LaTeX command name
+- ARGNUM is number of (required) command arguments
+- SUBSTITUTION substitution for the command. It is evaled and you can
+ reference command arguments through the \\N regexp notation in strings.")
+
+(defvar py2texi-magic "@documentclass\n"
+ "\"Magic\" string for auxiliary insertion at the beginning of document.")
+
+(defvar py2texi-dirs '("./" "../texinputs/")
+ "Where to search LaTeX input files.")
+
+(defvar py2texi-buffer "*py2texi*"
+ "The name of a buffer where Texinfo is generated.")
+
+(defconst py2texi-xemacs (string-match "^XEmacs" (emacs-version))
+ "Running under XEmacs?")
+
+
+(defmacro py2texi-search (regexp &rest body)
+ `(progn
+ (goto-char (point-min))
+ (while (re-search-forward ,regexp nil t)
+ ,@body)))
+
+(defmacro py2texi-search-safe (regexp &rest body)
+ `(py2texi-search ,regexp
+ (unless (py2texi-protected)
+ ,@body)))
+
+
+(defun py2texi-message (message)
+ "Report message and stop if `py2texi-stop-on-problems' is non-nil."
+ (if py2texi-stop-on-problems
+ (error message)
+ (message message)))
+
+
+(defun py2texi-backslash-quote (string)
+ "Double backslahes in STRING."
+ (let ((i 0))
+ (save-match-data
+ (while (setq i (string-match "\\\\" string i))
+ (setq string (replace-match "\\\\\\\\" t nil string))
+ (setq i (+ i 2))))
+ string))
+
+
+(defun py2texi (file)
+ "Convert Python LaTeX documentation FILE to Texinfo."
+ (interactive "fFile to convert: ")
+ (switch-to-buffer (get-buffer-create py2texi-buffer))
+ (erase-buffer)
+ (insert-file file)
+ (let ((case-fold-search nil)
+ (title "")
+ (author "")
+ (author-address "")
+ (appendix nil)
+ (findex nil)
+ (obindex nil)
+ (cindex nil)
+ (moindex nil)
+ last-if)
+ (py2texi-process-verbatims)
+ (py2texi-process-comments)
+ (py2texi-process-includes)
+ (py2texi-process-funnyas)
+ (py2texi-process-environments)
+ (py2texi-process-commands)
+ (py2texi-fix-indentation)
+ (py2texi-fix-nodes)
+ (py2texi-fix-references)
+ (py2texi-fix-indices)
+ (py2texi-process-simple-commands)
+ (py2texi-fix-fonts)
+ (py2texi-fix-braces)
+ (py2texi-fix-backslashes)
+ (py2texi-destroy-empties)
+ (py2texi-fix-newlines)
+ (py2texi-adjust-level))
+ (let* ((filename (concat "./"
+ (file-name-nondirectory file)
+ (if (string-match "\\.tex$" file) "i" ".texi")))
+ (infofilename (py2texi-info-file-name filename)))
+ (goto-char (point-min))
+ (when (looking-at py2texi-magic)
+ (delete-region (point) (progn (beginning-of-line 2) (point)))
+ (insert "\\input texinfo @c -*-texinfo-*-\n")
+ (insert "@setfilename " (file-name-nondirectory infofilename)))
+ (when (re-search-forward "@chapter" nil t)
+ (texinfo-all-menus-update t))
+ (goto-char (point-min))
+ (write-file filename)
+ (message (format "You can apply `makeinfo %s' now." filename))))
+
+
+(defun py2texi-info-file-name (filename)
+ "Generate name of info file from original file name FILENAME."
+ (setq filename (expand-file-name filename))
+ (let ((directory (file-name-directory filename))
+ (basename (file-name-nondirectory filename)))
+ (concat directory "python-"
+ (substring basename 0 (- (length basename) 4)) "info")))
+
+
+(defun py2texi-process-verbatims ()
+ "Process and protect verbatim environments."
+ (let (delimiter
+ beg
+ end)
+ (py2texi-search-safe "\\\\begin{\\(verbatim\\|displaymath\\)}"
+ (replace-match "@example")
+ (setq beg (copy-marker (point) nil))
+ (re-search-forward "\\\\end{\\(verbatim\\|displaymath\\)}")
+ (setq end (copy-marker (match-beginning 0) nil))
+ (replace-match "@end example")
+ (py2texi-texinfo-escape beg end)
+ (put-text-property (- beg (length "@example"))
+ (+ end (length "@end example"))
+ 'py2texi-protected t))
+ (py2texi-search-safe "\\\\verb\\([^a-z]\\)"
+ (setq delimiter (match-string 1))
+ (replace-match "@code{")
+ (setq beg (copy-marker (point) nil))
+ (re-search-forward (regexp-quote delimiter))
+ (setq end (copy-marker (match-beginning 0) nil))
+ (replace-match "}")
+ (put-text-property (- beg (length "@code{")) (+ end (length "}"))
+ 'py2texi-protected t)
+ (py2texi-texinfo-escape beg end))))
+
+
+(defun py2texi-process-comments ()
+ "Remove comments."
+ (let (point)
+ (py2texi-search-safe "%"
+ (setq point (point))
+ (when (save-excursion
+ (re-search-backward "\\(^\\|[^\\]\\(\\\\\\\\\\)*\\)%\\=" nil t))
+ (delete-region (1- point)
+ (save-excursion (beginning-of-line 2) (point)))))))
+
+
+(defun py2texi-process-includes ()
+ "Include LaTeX input files.
+Do not include .ind files."
+ (let ((path (file-name-directory file))
+ filename
+ dirs
+ includefile)
+ (py2texi-search-safe "\\\\input{\\([^}]+\\)}"
+ (setq filename (match-string 1))
+ (unless (save-match-data (string-match "\\.tex$" filename))
+ (setq filename (concat filename ".tex")))
+ (setq includefile (save-match-data
+ (string-match "\\.ind\\.tex$" filename)))
+ (setq dirs py2texi-dirs)
+ (while (and (not includefile) dirs)
+ (setq includefile (concat path (car dirs) filename))
+ (unless (file-exists-p includefile)
+ (setq includefile nil)
+ (setq dirs (cdr dirs))))
+ (if includefile
+ (save-restriction
+ (narrow-to-region (match-beginning 0) (match-end 0))
+ (delete-region (point-min) (point-max))
+ (when (stringp includefile)
+ (insert-file-contents includefile)
+ (goto-char (point-min))
+ (insert "\n")
+ (py2texi-process-verbatims)
+ (py2texi-process-comments)
+ (py2texi-process-includes)))
+ (replace-match (format "\\\\emph{Included file %s}" filename))
+ (py2texi-message (format "Input file %s not found" filename))))))
+
+
+(defun py2texi-process-funnyas ()
+ "Convert @s."
+ (py2texi-search-safe "@"
+ (replace-match "@@")))
+
+
+(defun py2texi-process-environments ()
+ "Process LaTeX environments."
+ (let ((stack ())
+ kind
+ environment
+ parameter
+ arguments
+ n
+ string
+ description)
+ (py2texi-search-safe (concat "\\\\\\(begin\\|end\\|item\\)"
+ "\\({\\([^}]*\\)}\\|[[]\\([^]]*\\)[]]\\|\\)")
+ (setq kind (match-string 1)
+ environment (match-string 3)
+ parameter (match-string 4))
+ (replace-match "")
+ (cond
+ ((string= kind "begin")
+ (setq description (assoc environment py2texi-environments))
+ (if description
+ (progn
+ (setq n (cadr description))
+ (setq description (cddr description))
+ (setq string (py2texi-tex-arguments n))
+ (string-match (py2texi-regexp n) string)
+ ; incorrect but sufficient
+ (insert (replace-match (eval (car description))
+ t nil string))
+ (setq stack (cons (cadr description) stack)))
+ (py2texi-message (format "Unknown environment: %s" environment))
+ (setq stack (cons "" stack))))
+ ((string= kind "end")
+ (insert (eval (car stack)))
+ (setq stack (cdr stack)))
+ ((string= kind "item")
+ (insert "\n@item " (or parameter "") "\n"))))
+ (when stack
+ (py2texi-message (format "Unclosed environment: %s" (car stack))))))
+
+
+(defun py2texi-process-commands ()
+ "Process LaTeX commands."
+ (let (done
+ command
+ command-info
+ string
+ n)
+ (while (not done)
+ (setq done t)
+ (py2texi-search-safe "\\\\\\([a-zA-Z*]+\\)\\(\\[[^]]*\\]\\)?"
+ (setq command (match-string 1))
+ (setq command-info (assoc command py2texi-commands))
+ (if command-info
+ (progn
+ (setq done nil)
+ (replace-match "")
+ (setq command-info (cdr command-info))
+ (setq n (car command-info))
+ (setq string (py2texi-tex-arguments n))
+ (string-match (py2texi-regexp n) string)
+ ; incorrect but sufficient
+ (insert (replace-match (eval (cadr command-info))
+ t nil string)))
+ (py2texi-message (format "Unknown command: %s (not processed)"
+ command)))))))
+
+
+(defun py2texi-argument-pattern (count)
+ (let ((filler "\\(?:[^{}]\\|\\\\{\\|\\\\}\\)*"))
+ (if (<= count 0)
+ filler
+ (concat filler "\\(?:{"
+ (py2texi-argument-pattern (1- count))
+ "}" filler "\\)*" filler))))
+(defconst py2texi-tex-argument
+ (concat
+ "{\\("
+ (py2texi-argument-pattern 10) ;really at least 10!
+ "\\)}[ \t%@c\n]*")
+ "Regexp describing LaTeX command argument including argument separators.")
+
+
+(defun py2texi-regexp (n)
+ "Make regexp matching N LaTeX command arguments."
+ (if (= n 0)
+ ""
+ (let ((regexp "^[^{]*"))
+ (while (> n 0)
+ (setq regexp (concat regexp py2texi-tex-argument))
+ (setq n (1- n)))
+ regexp)))
+
+
+(defun py2texi-tex-arguments (n)
+ "Remove N LaTeX command arguments and return them as a string."
+ (let ((point (point))
+ (i 0)
+ result
+ match)
+ (if (= n 0)
+ (progn
+ (when (re-search-forward "\\=\\({}\\| *\\)" nil t)
+ (replace-match ""))
+ "")
+ (while (> n 0)
+ (unless (re-search-forward
+ "\\(\\=\\|[^\\\\]\\)\\(\\\\\\\\\\)*\\([{}]\\)" nil t)
+ (debug))
+ (if (string= (match-string 3) "{")
+ (setq i (1+ i))
+ (setq i (1- i))
+ (when (<= i 0)
+ (setq n (1- n)))))
+ (setq result (buffer-substring-no-properties point (point)))
+ (while (string-match "\n[ \t]*" result)
+ (setq result (replace-match " " t nil result)))
+ (delete-region point (point))
+ result)))
+
+
+(defun py2texi-process-simple-commands ()
+ "Replace single character LaTeX commands."
+ (let (char)
+ (py2texi-search-safe "\\\\\\([^a-z]\\)"
+ (setq char (match-string 1))
+ (replace-match (format "%s%s"
+ (if (or (string= char "{")
+ (string= char "}")
+ (string= char " "))
+ "@"
+ "")
+ (if (string= char "\\")
+ "\\\\"
+ char))))))
+
+
+(defun py2texi-fix-indentation ()
+ "Remove white space at the beginning of lines."
+ (py2texi-search-safe "^[ \t]+"
+ (replace-match "")))
+
+
+(defun py2texi-fix-nodes ()
+ "Remove unwanted characters from nodes and make nodes unique."
+ (let ((nodes (make-hash-table :test 'equal))
+ id
+ counter
+ string
+ label)
+ (py2texi-search "^@node +\\(.*\\)$"
+ (setq string (match-string 1))
+ (if py2texi-xemacs
+ (replace-match "@node " t)
+ (replace-match "" t nil nil 1))
+ (when (string-match "@label{[^}]*}" string)
+ (setq label (match-string 0 string))
+ (setq string (replace-match "" t nil string)))
+ (while (string-match "@[a-zA-Z]+\\|[{}():]\\|``\\|''" string)
+ (setq string (replace-match "" t nil string)))
+ (while (string-match " -- " string)
+ (setq string (replace-match " - " t nil string)))
+ (when (string-match " +$" string)
+ (setq string (replace-match "" t nil string)))
+ (when (string-match "^\\(Built-in\\|Standard\\) Module \\|The " string)
+ (setq string (replace-match "" t nil string)))
+ (string-match "^[^,]+" string)
+ (setq id (match-string 0 string))
+ (setq counter (gethash id nodes))
+ (if counter
+ (progn
+ (setq counter (1+ counter))
+ (setq string (replace-match (format "\\& %d" counter)
+ t nil string)))
+ (setq counter 1))
+ (setf (gethash id nodes) counter)
+ (insert string)
+ (when label
+ (beginning-of-line 3)
+ (insert label "\n")))))
+
+
+(defun py2texi-fix-references ()
+ "Process labels and make references to point to appropriate nodes."
+ (let ((labels ())
+ node)
+ (py2texi-search-safe "@label{\\([^}]*\\)}"
+ (setq node (save-excursion
+ (save-match-data
+ (and (re-search-backward "@node +\\([^,\n]+\\)" nil t)
+ (match-string 1)))))
+ (when node
+ (setq labels (cons (cons (match-string 1) node) labels)))
+ (replace-match ""))
+ (py2texi-search-safe "@ref{\\([^}]*\\)}"
+ (setq node (assoc (match-string 1) labels))
+ (replace-match "")
+ (when node
+ (insert (format "@ref{%s}" (cdr node)))))))
+
+
+(defun py2texi-fix-indices ()
+ "Remove unwanted characters from @*index commands and create final indices."
+ (py2texi-search-safe "@..?index\\>[^\n]*\\(\\)\n"
+ (replace-match "" t nil nil 1))
+ (py2texi-search-safe "@..?index\\>[^\n]*\\(\\)"
+ (replace-match "\n" t nil nil 1))
+ (py2texi-search-safe "@..?index\\({\\)\\([^}]+\\)\\(}+\\)"
+ (replace-match " " t nil nil 1)
+ (replace-match "" t nil nil 3)
+ (let ((string (match-string 2)))
+ (save-match-data
+ (while (string-match "@[a-z]+{" string)
+ (setq string (replace-match "" nil nil string)))
+ (while (string-match "{" string)
+ (setq string (replace-match "" nil nil string))))
+ (replace-match string t t nil 2)))
+ (py2texi-search-safe "@..?index\\>.*\\([{}]\\|@[a-z]*\\)"
+ (replace-match "" t nil nil 1)
+ (goto-char (match-beginning 0)))
+ (py2texi-search-safe "[^\n]\\(\\)@..?index\\>"
+ (replace-match "\n" t nil nil 1))
+ (goto-char (point-max))
+ (re-search-backward "@indices")
+ (replace-match "")
+ (insert (if moindex
+ (concat "@node Module Index\n"
+ "@unnumbered Module Index\n"
+ "@printindex mo\n")
+ "")
+ (if obindex
+ (concat "@node Class-Exception-Object Index\n"
+ "@unnumbered Class, Exception, and Object Index\n"
+ "@printindex ob\n")
+ "")
+ (if findex
+ (concat "@node Function-Method-Variable Index\n"
+ "@unnumbered Function, Method, and Variable Index\n"
+ "@printindex fn\n")
+ "")
+ (if cindex
+ (concat "@node Miscellaneous Index\n"
+ "@unnumbered Miscellaneous Index\n"
+ "@printindex cp\n")
+ "")))
+
+
+(defun py2texi-fix-backslashes ()
+ "Make backslashes from auxiliary commands."
+ (py2texi-search-safe "@backslash{}"
+ (replace-match "\\\\")))
+
+
+(defun py2texi-fix-fonts ()
+ "Remove garbage after unstructured font commands."
+ (let (string)
+ (py2texi-search-safe "@destroy"
+ (replace-match "")
+ (when (eq (preceding-char) ?{)
+ (forward-char -1)
+ (setq string (py2texi-tex-arguments 1))
+ (insert (substring string 1 (1- (length string))))))))
+
+
+(defun py2texi-fix-braces ()
+ "Escape braces for Texinfo."
+ (let (string)
+ (py2texi-search "{"
+ (unless (or (py2texi-protected)
+ (save-excursion
+ (re-search-backward
+ "@\\([a-zA-Z]*\\|multitable.*\\){\\=" nil t)))
+ (forward-char -1)
+ (setq string (py2texi-tex-arguments 1))
+ (insert "@" (substring string 0 (1- (length string))) "@}")))))
+
+
+(defun py2texi-fix-newlines ()
+ "Remove extra newlines."
+ (py2texi-search "\n\n\n+"
+ (replace-match "\n\n"))
+ (py2texi-search-safe "@item.*\n\n"
+ (delete-backward-char 1))
+ (py2texi-search "@end example"
+ (unless (looking-at "\n\n")
+ (insert "\n"))))
+
+
+(defun py2texi-destroy-empties ()
+ "Remove all comments.
+This avoids some makeinfo errors."
+ (py2texi-search "@c\\>"
+ (unless (eq (py2texi-protected) t)
+ (delete-region (- (point) 2) (save-excursion (end-of-line) (point)))
+ (cond
+ ((looking-at "\n\n")
+ (delete-char 1))
+ ((save-excursion (re-search-backward "^[ \t]*\\=" nil t))
+ (delete-region (save-excursion (beginning-of-line) (point))
+ (1+ (point))))))))
+
+
+(defun py2texi-adjust-level ()
+ "Increase heading level to @chapter, if needed.
+This is only needed for distutils, so it has a very simple form only."
+ (goto-char (point-min))
+ (unless (re-search-forward "@chapter\\>" nil t)
+ (py2texi-search-safe "@section\\>"
+ (replace-match "@chapter" t))
+ (py2texi-search-safe "@\\(sub\\)\\(sub\\)?section\\>"
+ (replace-match "" nil nil nil 1))))
+
+
+(defun py2texi-texinfo-escape (beg end)
+ "Escape Texinfo special characters in region."
+ (save-excursion
+ (goto-char beg)
+ (while (re-search-forward "[@{}]" end t)
+ (replace-match "@\\&"))))
+
+
+(defun py2texi-protected ()
+ "Return protection status of the point before current point."
+ (get-text-property (1- (point)) 'py2texi-protected))
+
+
+;;; Announce
+
+(provide 'py2texi)
+
+
+;;; py2texi.el ends here