mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
Delete the LaTeX doc tree.
This commit is contained in:
parent
2d16490944
commit
739c01d47b
490 changed files with 0 additions and 150234 deletions
|
@ -1,71 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
"""Add reference count annotations to the Python/C API Reference."""
|
||||
__version__ = '$Revision$'
|
||||
|
||||
import getopt
|
||||
import os
|
||||
import sys
|
||||
|
||||
import refcounts
|
||||
|
||||
|
||||
PREFIX_1 = r"\begin{cfuncdesc}{PyObject*}{"
|
||||
PREFIX_2 = r"\begin{cfuncdesc}{PyVarObject*}{"
|
||||
|
||||
|
||||
def main():
|
||||
rcfile = os.path.join(os.path.dirname(refcounts.__file__), os.pardir,
|
||||
"api", "refcounts.dat")
|
||||
outfile = "-"
|
||||
opts, args = getopt.getopt(sys.argv[1:], "o:r:", ["output=", "refcounts="])
|
||||
for opt, arg in opts:
|
||||
if opt in ("-o", "--output"):
|
||||
outfile = arg
|
||||
elif opt in ("-r", "--refcounts"):
|
||||
rcfile = arg
|
||||
rcdict = refcounts.load(rcfile)
|
||||
if outfile == "-":
|
||||
output = sys.stdout
|
||||
else:
|
||||
output = open(outfile, "w")
|
||||
if not args:
|
||||
args = ["-"]
|
||||
for infile in args:
|
||||
if infile == "-":
|
||||
input = sys.stdin
|
||||
else:
|
||||
input = open(infile)
|
||||
while 1:
|
||||
line = input.readline()
|
||||
if not line:
|
||||
break
|
||||
prefix = None
|
||||
if line.startswith(PREFIX_1):
|
||||
prefix = PREFIX_1
|
||||
elif line.startswith(PREFIX_2):
|
||||
prefix = PREFIX_2
|
||||
if prefix:
|
||||
s = line[len(prefix):].split('}', 1)[0]
|
||||
try:
|
||||
info = rcdict[s]
|
||||
except KeyError:
|
||||
sys.stderr.write("No refcount data for %s\n" % s)
|
||||
else:
|
||||
if info.result_type in ("PyObject*", "PyVarObject*"):
|
||||
if info.result_refs is None:
|
||||
rc = "Always \NULL{}"
|
||||
else:
|
||||
rc = info.result_refs and "New" or "Borrowed"
|
||||
rc = rc + " reference"
|
||||
line = (r"\begin{cfuncdesc}[%s]{%s}{"
|
||||
% (rc, info.result_type)) \
|
||||
+ line[len(prefix):]
|
||||
output.write(line)
|
||||
if infile != "-":
|
||||
input.close()
|
||||
if outfile != "-":
|
||||
output.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,397 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
__version__ = '$Revision$'
|
||||
|
||||
import os.path
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
|
||||
from xml.sax.saxutils import quoteattr
|
||||
|
||||
|
||||
bang_join = "!".join
|
||||
null_join = "".join
|
||||
|
||||
REPLACEMENTS = [
|
||||
# Hackish way to deal with macros replaced with simple text
|
||||
(re.compile(r"\\ABC\b"), "ABC"),
|
||||
(re.compile(r"\\ASCII\b"), "ASCII"),
|
||||
(re.compile(r"\\Cpp\b"), "C++"),
|
||||
(re.compile(r"\\EOF\b"), "EOF"),
|
||||
(re.compile(r"\\NULL\b"), "NULL"),
|
||||
(re.compile(r"\\POSIX\b"), "POSIX"),
|
||||
(re.compile(r"\\UNIX\b"), "Unix"),
|
||||
# deal with turds left over from LaTeX2HTML
|
||||
(re.compile(r"<#\d+#>"), ""),
|
||||
]
|
||||
|
||||
class Node:
|
||||
continuation = 0
|
||||
|
||||
def __init__(self, link, str, seqno):
|
||||
self.links = [link]
|
||||
self.seqno = seqno
|
||||
for pattern, replacement in REPLACEMENTS:
|
||||
str = pattern.sub(replacement, str)
|
||||
# build up the text
|
||||
self.text = split_entry_text(str)
|
||||
self.key = list(split_entry_key(str))
|
||||
|
||||
def __eq__(self, other):
|
||||
return cmp(self, other) == 0
|
||||
|
||||
def __lt__(self, other):
|
||||
return cmp(self, other) == -1
|
||||
|
||||
def __gt__(self, other):
|
||||
return cmp(self, other) == 1
|
||||
|
||||
def __cmp__(self, other):
|
||||
"""Comparison operator includes sequence number, for use with
|
||||
list.sort()."""
|
||||
return self.cmp_entry(other) or cmp(self.seqno, other.seqno)
|
||||
|
||||
def cmp_entry(self, other):
|
||||
"""Comparison 'operator' that ignores sequence number."""
|
||||
c = 0
|
||||
for i in range(min(len(self.key), len(other.key))):
|
||||
c = (cmp_part(self.key[i], other.key[i])
|
||||
or cmp_part(self.text[i], other.text[i]))
|
||||
if c:
|
||||
break
|
||||
return c or cmp(self.key, other.key) or cmp(self.text, other.text)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Node for %s (%s)>" % (bang_join(self.text), self.seqno)
|
||||
|
||||
def __str__(self):
|
||||
return bang_join(self.key)
|
||||
|
||||
def dump(self):
|
||||
return "%s\1%s###%s\n" \
|
||||
% ("\1".join(self.links),
|
||||
bang_join(self.text),
|
||||
self.seqno)
|
||||
|
||||
|
||||
def cmp_part(s1, s2):
|
||||
result = cmp(s1, s2)
|
||||
if result == 0:
|
||||
return 0
|
||||
l1 = s1.lower()
|
||||
l2 = s2.lower()
|
||||
minlen = min(len(s1), len(s2))
|
||||
if len(s1) < len(s2) and l1 == l2[:len(s1)]:
|
||||
result = -1
|
||||
elif len(s2) < len(s1) and l2 == l1[:len(s2)]:
|
||||
result = 1
|
||||
else:
|
||||
result = cmp(l1, l2) or cmp(s1, s2)
|
||||
return result
|
||||
|
||||
|
||||
def split_entry(str, which):
|
||||
stuff = []
|
||||
parts = str.split('!')
|
||||
parts = [part.split('@') for part in parts]
|
||||
for entry in parts:
|
||||
if len(entry) != 1:
|
||||
key = entry[which]
|
||||
else:
|
||||
key = entry[0]
|
||||
stuff.append(key)
|
||||
return stuff
|
||||
|
||||
|
||||
_rmtt = re.compile(r"""(.*)<tt(?: class=['"][a-z0-9]+["'])?>(.*)</tt>(.*)$""",
|
||||
re.IGNORECASE)
|
||||
_rmparens = re.compile(r"\(\)")
|
||||
|
||||
def split_entry_key(str):
|
||||
parts = split_entry(str, 1)
|
||||
for i in range(len(parts)):
|
||||
m = _rmtt.match(parts[i])
|
||||
if m:
|
||||
parts[i] = null_join(m.group(1, 2, 3))
|
||||
else:
|
||||
parts[i] = parts[i].lower()
|
||||
# remove '()' from the key:
|
||||
parts[i] = _rmparens.sub('', parts[i])
|
||||
return map(trim_ignored_letters, parts)
|
||||
|
||||
|
||||
def split_entry_text(str):
|
||||
if '<' in str:
|
||||
m = _rmtt.match(str)
|
||||
if m:
|
||||
str = null_join(m.group(1, 2, 3))
|
||||
return split_entry(str, 1)
|
||||
|
||||
|
||||
def load(fp):
|
||||
nodes = []
|
||||
rx = re.compile("(.*)\1(.*)###(.*)$")
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
m = rx.match(line)
|
||||
if m:
|
||||
link, str, seqno = m.group(1, 2, 3)
|
||||
nodes.append(Node(link, str, seqno))
|
||||
return nodes
|
||||
|
||||
|
||||
def trim_ignored_letters(s):
|
||||
# ignore $ to keep environment variables with the
|
||||
# leading letter from the name
|
||||
if s.startswith("$"):
|
||||
return s[1:].lower()
|
||||
else:
|
||||
return s.lower()
|
||||
|
||||
def get_first_letter(s):
|
||||
if s.startswith("<tex2html_percent_mark>"):
|
||||
return "%"
|
||||
else:
|
||||
return trim_ignored_letters(s)[0]
|
||||
|
||||
|
||||
def split_letters(nodes):
|
||||
letter_groups = []
|
||||
if nodes:
|
||||
group = []
|
||||
append = group.append
|
||||
letter = get_first_letter(nodes[0].text[0])
|
||||
letter_groups.append((letter, group))
|
||||
for node in nodes:
|
||||
nletter = get_first_letter(node.text[0])
|
||||
if letter != nletter:
|
||||
letter = nletter
|
||||
group = []
|
||||
letter_groups.append((letter, group))
|
||||
append = group.append
|
||||
append(node)
|
||||
return letter_groups
|
||||
|
||||
|
||||
def group_symbols(groups):
|
||||
entries = []
|
||||
ident_letters = string.ascii_letters + "_"
|
||||
while groups[0][0] not in ident_letters:
|
||||
entries += groups[0][1]
|
||||
del groups[0]
|
||||
if entries:
|
||||
groups.insert(0, ("Symbols", entries))
|
||||
|
||||
|
||||
# need a function to separate the nodes into columns...
|
||||
def split_columns(nodes, columns=1):
|
||||
if columns <= 1:
|
||||
return [nodes]
|
||||
# This is a rough height; we may have to increase to avoid breaks before
|
||||
# a subitem.
|
||||
colheight = int(len(nodes) / columns)
|
||||
numlong = int(len(nodes) % columns)
|
||||
if numlong:
|
||||
colheight = colheight + 1
|
||||
else:
|
||||
numlong = columns
|
||||
cols = []
|
||||
for i in range(numlong):
|
||||
start = i * colheight
|
||||
end = start + colheight
|
||||
cols.append(nodes[start:end])
|
||||
del nodes[:end]
|
||||
colheight = colheight - 1
|
||||
try:
|
||||
numshort = int(len(nodes) / colheight)
|
||||
except ZeroDivisionError:
|
||||
cols = cols + (columns - len(cols)) * [[]]
|
||||
else:
|
||||
for i in range(numshort):
|
||||
start = i * colheight
|
||||
end = start + colheight
|
||||
cols.append(nodes[start:end])
|
||||
#
|
||||
# If items continue across columns, make sure they are marked
|
||||
# as continuations so the user knows to look at the previous column.
|
||||
#
|
||||
for i in range(len(cols) - 1):
|
||||
try:
|
||||
prev = cols[i][-1]
|
||||
next = cols[i + 1][0]
|
||||
except IndexError:
|
||||
return cols
|
||||
else:
|
||||
n = min(len(prev.key), len(next.key))
|
||||
for j in range(n):
|
||||
if prev.key[j] != next.key[j]:
|
||||
break
|
||||
next.continuation = j + 1
|
||||
return cols
|
||||
|
||||
|
||||
DL_LEVEL_INDENT = " "
|
||||
|
||||
def format_column(nodes):
|
||||
strings = ["<dl compact='compact'>"]
|
||||
append = strings.append
|
||||
level = 0
|
||||
previous = []
|
||||
for node in nodes:
|
||||
current = node.text
|
||||
count = 0
|
||||
for i in range(min(len(current), len(previous))):
|
||||
if previous[i] != current[i]:
|
||||
break
|
||||
count = i + 1
|
||||
if count > level:
|
||||
append("<dl compact='compact'>" * (count - level) + "\n")
|
||||
level = count
|
||||
elif level > count:
|
||||
append("\n")
|
||||
append(level * DL_LEVEL_INDENT)
|
||||
append("</dl>" * (level - count))
|
||||
level = count
|
||||
# else: level == count
|
||||
for i in range(count, len(current) - 1):
|
||||
term = node.text[i]
|
||||
level = level + 1
|
||||
if node.continuation > i:
|
||||
extra = " (continued)"
|
||||
else:
|
||||
extra = ""
|
||||
append("\n<dt>%s%s\n<dd>\n%s<dl compact='compact'>"
|
||||
% (term, extra, level * DL_LEVEL_INDENT))
|
||||
append("\n%s<dt>%s%s</a>"
|
||||
% (level * DL_LEVEL_INDENT, node.links[0], node.text[-1]))
|
||||
for link in node.links[1:]:
|
||||
append(",\n%s %s[Link]</a>" % (level * DL_LEVEL_INDENT, link))
|
||||
previous = current
|
||||
append("\n")
|
||||
append("</dl>" * (level + 1))
|
||||
return null_join(strings)
|
||||
|
||||
|
||||
def format_nodes(nodes, columns=1):
|
||||
strings = []
|
||||
append = strings.append
|
||||
if columns > 1:
|
||||
colnos = range(columns)
|
||||
colheight = int(len(nodes) / columns)
|
||||
if len(nodes) % columns:
|
||||
colheight = colheight + 1
|
||||
colwidth = int(100 / columns)
|
||||
append('<table width="100%"><tr valign="top">')
|
||||
for col in split_columns(nodes, columns):
|
||||
append('<td width="%d%%">\n' % colwidth)
|
||||
append(format_column(col))
|
||||
append("\n</td>")
|
||||
append("\n</tr></table>")
|
||||
else:
|
||||
append(format_column(nodes))
|
||||
return null_join(strings)
|
||||
|
||||
|
||||
def format_letter(letter):
|
||||
if letter == '.':
|
||||
lettername = ". (dot)"
|
||||
elif letter == '_':
|
||||
lettername = "_ (underscore)"
|
||||
else:
|
||||
lettername = letter.capitalize()
|
||||
return "\n<hr />\n<h2 id=%s>%s</h2>\n\n" \
|
||||
% (quoteattr("letter-" + letter), lettername)
|
||||
|
||||
|
||||
def format_html_letters(nodes, columns, group_symbol_nodes):
|
||||
letter_groups = split_letters(nodes)
|
||||
if group_symbol_nodes:
|
||||
group_symbols(letter_groups)
|
||||
items = []
|
||||
for letter, nodes in letter_groups:
|
||||
s = "<b><a href=\"#letter-%s\">%s</a></b>" % (letter, letter)
|
||||
items.append(s)
|
||||
s = ["<hr /><center>\n%s</center>\n" % " |\n".join(items)]
|
||||
for letter, nodes in letter_groups:
|
||||
s.append(format_letter(letter))
|
||||
s.append(format_nodes(nodes, columns))
|
||||
return null_join(s)
|
||||
|
||||
def format_html(nodes, columns):
|
||||
return format_nodes(nodes, columns)
|
||||
|
||||
|
||||
def collapse(nodes):
|
||||
"""Collapse sequences of nodes with matching keys into a single node.
|
||||
Destructive."""
|
||||
if len(nodes) < 2:
|
||||
return
|
||||
prev = nodes[0]
|
||||
i = 1
|
||||
while i < len(nodes):
|
||||
node = nodes[i]
|
||||
if not node.cmp_entry(prev):
|
||||
prev.links.append(node.links[0])
|
||||
del nodes[i]
|
||||
else:
|
||||
i = i + 1
|
||||
prev = node
|
||||
|
||||
|
||||
def dump(nodes, fp):
|
||||
for node in nodes:
|
||||
fp.write(node.dump())
|
||||
|
||||
|
||||
def process_nodes(nodes, columns, letters=0, group_symbol_nodes=0):
|
||||
nodes.sort()
|
||||
collapse(nodes)
|
||||
if letters:
|
||||
return format_html_letters(nodes, columns, group_symbol_nodes)
|
||||
else:
|
||||
return format_html(nodes, columns)
|
||||
|
||||
|
||||
def main():
|
||||
import getopt
|
||||
ifn = "-"
|
||||
ofn = "-"
|
||||
columns = 1
|
||||
letters = 0
|
||||
group_symbol_nodes = 1
|
||||
opts, args = getopt.getopt(sys.argv[1:], "c:lo:",
|
||||
["columns=", "dont-group-symbols",
|
||||
"group-symbols", "letters", "output="])
|
||||
for opt, val in opts:
|
||||
if opt in ("-o", "--output"):
|
||||
ofn = val
|
||||
elif opt in ("-c", "--columns"):
|
||||
columns = int(val, 10)
|
||||
elif opt in ("-l", "--letters"):
|
||||
letters = 1
|
||||
elif opt == "--group-symbols":
|
||||
group_symbol_nodes = 1
|
||||
elif opt == "--dont-group-symbols":
|
||||
group_symbol_nodes = 0
|
||||
if not args:
|
||||
args = [ifn]
|
||||
nodes = []
|
||||
for fn in args:
|
||||
nodes = nodes + load(open(fn))
|
||||
num_nodes = len(nodes)
|
||||
html = process_nodes(nodes, columns, letters, group_symbol_nodes)
|
||||
program = os.path.basename(sys.argv[0])
|
||||
if ofn == "-":
|
||||
sys.stdout.write(html)
|
||||
sys.stderr.write("\n%s: %d index nodes" % (program, num_nodes))
|
||||
else:
|
||||
open(ofn, "w").write(html)
|
||||
print()
|
||||
print("%s: %d index nodes" % (program, num_nodes))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,112 +0,0 @@
|
|||
#! /usr/bin/perl
|
||||
|
||||
package checkargs;
|
||||
require 5.004; # uses "for my $var"
|
||||
require Exporter;
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(check_args check_args_range check_args_at_least);
|
||||
use strict;
|
||||
use Carp;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
checkargs -- Provide rudimentary argument checking for perl5 functions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
check_args(cArgsExpected, @_)
|
||||
check_args_range(cArgsMin, cArgsMax, @_)
|
||||
check_args_at_least(cArgsMin, @_)
|
||||
where "@_" should be supplied literally.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
As the first line of user-written subroutine foo, do one of the following:
|
||||
|
||||
my ($arg1, $arg2) = check_args(2, @_);
|
||||
my ($arg1, @rest) = check_args_range(1, 4, @_);
|
||||
my ($arg1, @rest) = check_args_at_least(1, @_);
|
||||
my @args = check_args_at_least(0, @_);
|
||||
|
||||
These functions may also be called for side effect (put a call to one
|
||||
of the functions near the beginning of the subroutine), but using the
|
||||
argument checkers to set the argument list is the recommended usage.
|
||||
|
||||
The number of arguments and their definedness are checked; if the wrong
|
||||
number are received, the program exits with an error message.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael D. Ernst <F<mernst@cs.washington.edu>>
|
||||
|
||||
=cut
|
||||
|
||||
## Need to check that use of caller(1) really gives desired results.
|
||||
## Need to give input chunk information.
|
||||
## Is this obviated by Perl 5.003's declarations? Not entirely, I think.
|
||||
|
||||
sub check_args ( $@ )
|
||||
{
|
||||
my ($num_formals, @args) = @_;
|
||||
my ($pack, $file_arg, $line_arg, $subname, $hasargs, $wantarr) = caller(1);
|
||||
if (@_ < 1) { croak "check_args needs at least 7 args, got ", scalar(@_), ": @_\n "; }
|
||||
if ((!wantarray) && ($num_formals != 0))
|
||||
{ croak "check_args called in scalar context"; }
|
||||
# Can't use croak below here: it would only go out to caller, not its caller
|
||||
my $num_actuals = @args;
|
||||
if ($num_actuals != $num_formals)
|
||||
{ die "$file_arg:$line_arg: function $subname expected $num_formals argument",
|
||||
(($num_formals == 1) ? "" : "s"),
|
||||
", got $num_actuals",
|
||||
(($num_actuals == 0) ? "" : ": @args"),
|
||||
"\n"; }
|
||||
for my $index (0..$#args)
|
||||
{ if (!defined($args[$index]))
|
||||
{ die "$file_arg:$line_arg: function $subname undefined argument ", $index+1, ": @args[0..$index-1]\n"; } }
|
||||
return @args;
|
||||
}
|
||||
|
||||
sub check_args_range ( $$@ )
|
||||
{
|
||||
my ($min_formals, $max_formals, @args) = @_;
|
||||
my ($pack, $file_arg, $line_arg, $subname, $hasargs, $wantarr) = caller(1);
|
||||
if (@_ < 2) { croak "check_args_range needs at least 8 args, got ", scalar(@_), ": @_"; }
|
||||
if ((!wantarray) && ($max_formals != 0) && ($min_formals !=0) )
|
||||
{ croak "check_args_range called in scalar context"; }
|
||||
# Can't use croak below here: it would only go out to caller, not its caller
|
||||
my $num_actuals = @args;
|
||||
if (($num_actuals < $min_formals) || ($num_actuals > $max_formals))
|
||||
{ die "$file_arg:$line_arg: function $subname expected $min_formals-$max_formals arguments, got $num_actuals",
|
||||
($num_actuals == 0) ? "" : ": @args", "\n"; }
|
||||
for my $index (0..$#args)
|
||||
{ if (!defined($args[$index]))
|
||||
{ die "$file_arg:$line_arg: function $subname undefined argument ", $index+1, ": @args[0..$index-1]\n"; } }
|
||||
return @args;
|
||||
}
|
||||
|
||||
sub check_args_at_least ( $@ )
|
||||
{
|
||||
my ($min_formals, @args) = @_;
|
||||
my ($pack, $file_arg, $line_arg, $subname, $hasargs, $wantarr) = caller(1);
|
||||
# Don't do this, because we want every sub to start with a call to check_args*
|
||||
# if ($min_formals == 0)
|
||||
# { die "Isn't it pointless to check for at least zero args to $subname?\n"; }
|
||||
if (scalar(@_) < 1)
|
||||
{ croak "check_args_at_least needs at least 1 arg, got ", scalar(@_), ": @_"; }
|
||||
if ((!wantarray) && ($min_formals != 0))
|
||||
{ croak "check_args_at_least called in scalar context"; }
|
||||
# Can't use croak below here: it would only go out to caller, not its caller
|
||||
my $num_actuals = @args;
|
||||
if ($num_actuals < $min_formals)
|
||||
{ die "$file_arg:$line_arg: function $subname expected at least $min_formals argument",
|
||||
($min_formals == 1) ? "" : "s",
|
||||
", got $num_actuals",
|
||||
($num_actuals == 0) ? "" : ": @args", "\n"; }
|
||||
for my $index (0..$#args)
|
||||
{ if (!defined($args[$index]))
|
||||
{ warn "$file_arg:$line_arg: function $subname undefined argument ", $index+1, ": @args[0..$index-1]\n"; last; } }
|
||||
return @args;
|
||||
}
|
||||
|
||||
1; # successful import
|
||||
__END__
|
|
@ -1,26 +0,0 @@
|
|||
#! /bin/sh
|
||||
# -*- ksh -*-
|
||||
|
||||
# This script *helps* locate lines of normal content that end in '}';
|
||||
# this is useful since LaTeX2HTML (at least the old version that we
|
||||
# use) breaks on many lines that end that way.
|
||||
#
|
||||
# Usage: cklatex files... | less
|
||||
#
|
||||
# *Read* the output looking for suspicious lines!
|
||||
|
||||
grep -n "[^ ]}\$" $@ | \
|
||||
grep -v '\\begin{' | \
|
||||
grep -v '\\end{' | \
|
||||
grep -v '\\input{' | \
|
||||
grep -v '\\documentclass{' | \
|
||||
grep -v '\\title{' | \
|
||||
grep -v '\\chapter{' | \
|
||||
grep -v '\\chapter\*{' | \
|
||||
grep -v '\\section{' | \
|
||||
grep -v '\\subsection{' | \
|
||||
grep -v '\\subsubsection{' | \
|
||||
grep -v '\\sectionauthor{' | \
|
||||
grep -v '\\moduleauthor{'
|
||||
|
||||
exit $?
|
|
@ -1,157 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
from __future__ import with_statement
|
||||
import errno
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import string
|
||||
|
||||
if __name__ == "__main__":
|
||||
_base = sys.argv[0]
|
||||
else:
|
||||
_base = __file__
|
||||
|
||||
_script_home = os.path.abspath(os.path.dirname(_base))
|
||||
|
||||
srcdir = os.path.dirname(os.path.dirname(_script_home))
|
||||
|
||||
EXCLUDES = ["bitset.h", "cStringIO.h", "graminit.h", "grammar.h",
|
||||
"longintrepr.h", "metagrammar.h",
|
||||
"node.h", "opcode.h", "osdefs.h", "pgenheaders.h",
|
||||
"py_curses.h", "parsetok.h", "symtable.h", "token.h"]
|
||||
|
||||
|
||||
def list_headers():
|
||||
"""Return a list of headers."""
|
||||
incdir = os.path.join(srcdir, "Include")
|
||||
return [os.path.join(incdir, fn) for fn in os.listdir(incdir)
|
||||
if fn.endswith(".h") and fn not in EXCLUDES]
|
||||
|
||||
|
||||
def matcher(pattern):
|
||||
return re.compile(pattern).search
|
||||
|
||||
MATCHERS = [
|
||||
# XXX this should also deal with ctypedesc, cvardesc and cmemberdesc
|
||||
matcher(r"\\begin\{cfuncdesc\}\{(?P<result>[^}]*)\}\{(?P<sym>[^}]*)\}{(?P<params>[^}]*)\}"),
|
||||
matcher(r"\\cfuncline\{(?P<result>[^})]*)\}\{(?P<sym>[^}]*)\}{(?P<params>[^}]*)\}"),
|
||||
]
|
||||
|
||||
def list_documented_items():
|
||||
"""Return a list of everything that's already documented."""
|
||||
apidir = os.path.join(srcdir, "Doc", "api")
|
||||
files = [fn for fn in os.listdir(apidir) if fn.endswith(".tex")]
|
||||
L = []
|
||||
for fn in files:
|
||||
fullname = os.path.join(apidir, fn)
|
||||
data = open(fullname).read()
|
||||
for matcher in MATCHERS:
|
||||
pos = 0
|
||||
while 1:
|
||||
m = matcher(data, pos)
|
||||
if not m: break
|
||||
pos = m.end()
|
||||
sym = m.group("sym")
|
||||
result = m.group("result")
|
||||
params = m.group("params")
|
||||
# replace all whitespace with a single one
|
||||
params = " ".join(params.split())
|
||||
L.append((sym, result, params, fn))
|
||||
return L
|
||||
|
||||
def normalize_type(t):
|
||||
t = t.strip()
|
||||
s = t.rfind("*")
|
||||
if s != -1:
|
||||
# strip everything after the pointer name
|
||||
t = t[:s+1]
|
||||
# Drop the variable name
|
||||
s = t.split()
|
||||
typenames = 1
|
||||
if len(s)>1 and s[0]=='unsigned' and s[1]=='int':
|
||||
typenames = 2
|
||||
if len(s) > typenames and s[-1][0] in string.letters:
|
||||
del s[-1]
|
||||
if not s:
|
||||
print "XXX", t
|
||||
return ""
|
||||
# Drop register
|
||||
if s[0] == "register":
|
||||
del s[0]
|
||||
# discard all spaces
|
||||
return ''.join(s)
|
||||
|
||||
def compare_type(t1, t2):
|
||||
t1 = normalize_type(t1)
|
||||
t2 = normalize_type(t2)
|
||||
if t1 == r'\moreargs' and t2 == '...':
|
||||
return False
|
||||
if t1 != t2:
|
||||
#print "different:", t1, t2
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def compare_types(ret, params, hret, hparams):
|
||||
if not compare_type(ret, hret):
|
||||
return False
|
||||
params = params.split(",")
|
||||
hparams = hparams.split(",")
|
||||
if not params and hparams == ['void']:
|
||||
return True
|
||||
if not hparams and params == ['void']:
|
||||
return True
|
||||
if len(params) != len(hparams):
|
||||
return False
|
||||
for p1, p2 in zip(params, hparams):
|
||||
if not compare_type(p1, p2):
|
||||
return False
|
||||
return True
|
||||
|
||||
def main():
|
||||
headers = list_headers()
|
||||
documented = list_documented_items()
|
||||
|
||||
lines = []
|
||||
for h in headers:
|
||||
data = open(h).read()
|
||||
data, n = re.subn(r"PyAPI_FUNC\(([^)]*)\)", r"\1", data)
|
||||
name = os.path.basename(h)
|
||||
with open(name, "w") as f:
|
||||
f.write(data)
|
||||
cmd = ("ctags -f - --file-scope=no --c-kinds=p --fields=S "
|
||||
"-Istaticforward -Istatichere=static " + name)
|
||||
with os.popen(cmd) as f:
|
||||
lines.extend(f.readlines())
|
||||
os.unlink(name)
|
||||
L = {}
|
||||
prevsym = None
|
||||
for line in lines:
|
||||
if not line:
|
||||
break
|
||||
sym, filename, signature = line.split(None, 2)
|
||||
if sym == prevsym:
|
||||
continue
|
||||
expr = "\^(.*)%s" % sym
|
||||
m = re.search(expr, signature)
|
||||
if not m:
|
||||
print "Could not split",signature, "using",expr
|
||||
rettype = m.group(1).strip()
|
||||
m = re.search("signature:\(([^)]*)\)", signature)
|
||||
if not m:
|
||||
print "Could not get signature from", signature
|
||||
params = m.group(1)
|
||||
L[sym] = (rettype, params)
|
||||
|
||||
for sym, ret, params, fn in documented:
|
||||
if sym not in L:
|
||||
print "No declaration for '%s'" % sym
|
||||
continue
|
||||
hret, hparams = L[sym]
|
||||
if not compare_types(ret, params, hret, hparams):
|
||||
print "Declaration error for %s (%s):" % (sym, fn)
|
||||
print ret+": "+params
|
||||
print hret+": "+hparams
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,78 +0,0 @@
|
|||
# Generate custlib.tex, which is a site-specific library document.
|
||||
|
||||
# Phase I: list all the things that can be imported
|
||||
|
||||
import glob
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
modules = {}
|
||||
|
||||
for modname in sys.builtin_module_names:
|
||||
modules[modname] = modname
|
||||
|
||||
for dir in sys.path:
|
||||
# Look for *.py files
|
||||
filelist = glob.glob(os.path.join(dir, '*.py'))
|
||||
for file in filelist:
|
||||
path, file = os.path.split(file)
|
||||
base, ext = os.path.splitext(file)
|
||||
modules[base.lower()] = base
|
||||
|
||||
# Look for shared library files
|
||||
filelist = (glob.glob(os.path.join(dir, '*.so')) +
|
||||
glob.glob(os.path.join(dir, '*.sl')) +
|
||||
glob.glob(os.path.join(dir, '*.o')) )
|
||||
for file in filelist:
|
||||
path, file = os.path.split(file)
|
||||
base, ext = os.path.splitext(file)
|
||||
if base[-6:] == 'module':
|
||||
base = base[:-6]
|
||||
modules[base.lower()] = base
|
||||
|
||||
# Minor oddity: the types module is documented in libtypes2.tex
|
||||
if 'types' in modules:
|
||||
del modules['types']
|
||||
modules['types2'] = None
|
||||
|
||||
# Phase II: find all documentation files (lib*.tex)
|
||||
# and eliminate modules that don't have one.
|
||||
|
||||
docs = {}
|
||||
filelist = glob.glob('lib*.tex')
|
||||
for file in filelist:
|
||||
modname = file[3:-4]
|
||||
docs[modname] = modname
|
||||
|
||||
mlist = list(modules.keys())
|
||||
mlist = filter(lambda x, docs=docs: x in docs, mlist)
|
||||
mlist.sort()
|
||||
mlist = map(lambda x, docs=docs: docs[x], mlist)
|
||||
|
||||
modules = mlist
|
||||
|
||||
# Phase III: write custlib.tex
|
||||
|
||||
# Write the boilerplate
|
||||
# XXX should be fancied up.
|
||||
print("""\documentstyle[twoside,11pt,myformat]{report}
|
||||
\\title{Python Library Reference}
|
||||
\\input{boilerplate}
|
||||
\\makeindex % tell \\index to actually write the .idx file
|
||||
\\begin{document}
|
||||
\\pagenumbering{roman}
|
||||
\\maketitle
|
||||
\\input{copyright}
|
||||
\\begin{abstract}
|
||||
\\noindent This is a customized version of the Python Library Reference.
|
||||
\\end{abstract}
|
||||
\\pagebreak
|
||||
{\\parskip = 0mm \\tableofcontents}
|
||||
\\pagebreak\\pagenumbering{arabic}""")
|
||||
|
||||
for modname in mlist:
|
||||
print("\\input{lib%s}" % (modname,))
|
||||
|
||||
# Write the end
|
||||
print("""\\input{custlib.ind} % Index
|
||||
\\end{document}""")
|
|
@ -1,136 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import errno
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
_base = sys.argv[0]
|
||||
else:
|
||||
_base = __file__
|
||||
|
||||
_script_home = os.path.abspath(os.path.dirname(_base))
|
||||
|
||||
srcdir = os.path.dirname(os.path.dirname(_script_home))
|
||||
|
||||
EXCLUDES = ["bitset.h", "cStringIO.h", "graminit.h", "grammar.h",
|
||||
"longintrepr.h", "metagrammar.h",
|
||||
"node.h", "opcode.h", "osdefs.h", "pgenheaders.h",
|
||||
"py_curses.h", "parsetok.h", "symtable.h", "token.h"]
|
||||
|
||||
|
||||
def list_headers():
|
||||
"""Return a list of headers."""
|
||||
incdir = os.path.join(srcdir, "Include")
|
||||
return [fn for fn in os.listdir(incdir)
|
||||
if fn.endswith(".h") and fn not in EXCLUDES]
|
||||
|
||||
|
||||
def matcher(pattern):
|
||||
return re.compile(pattern).match
|
||||
|
||||
MATCHERS = [
|
||||
matcher(r"\\begin\{cfuncdesc\}\{[^{]*\}\{(?P<sym>[^{]*)\}"),
|
||||
matcher(r"\\cfuncline\{[^{]*\}\{(?P<sym>[^{]*)\}"),
|
||||
matcher(r"\\begin\{ctypedesc\}(\[[^{]*\])?\{(?P<sym>[^{]*)\}"),
|
||||
matcher(r"\\begin\{cvardesc\}\{[^{]*\}\{(?P<sym>[^{]*)\}"),
|
||||
matcher(r"\\begin\{cmemberdesc\}\{[^{]*\}\{(?P<sym>[^{]*)\}"),
|
||||
matcher(r"\\cmemberline\{[^{]*\}\{(?P<sym>[^{]*)\}"),
|
||||
matcher(r"\\begin\{csimplemacrodesc\}\{(?P<sym>[^{]*)\}"),
|
||||
]
|
||||
|
||||
|
||||
def list_documented_items():
|
||||
"""Return a list of everything that's already documented."""
|
||||
apidir = os.path.join(srcdir, "Doc", "api")
|
||||
files = [fn for fn in os.listdir(apidir) if fn.endswith(".tex")]
|
||||
L = []
|
||||
for fn in files:
|
||||
fullname = os.path.join(apidir, fn)
|
||||
for line in open(fullname):
|
||||
line = line.lstrip()
|
||||
if not line.startswith("\\"):
|
||||
continue
|
||||
for matcher in MATCHERS:
|
||||
m = matcher(line)
|
||||
if m:
|
||||
L.append(m.group("sym"))
|
||||
break
|
||||
return L
|
||||
|
||||
def split_documented(all, documented):
|
||||
"""Split the list of all symbols into documented and undocumented
|
||||
categories."""
|
||||
doc = []
|
||||
undoc = []
|
||||
for t in all:
|
||||
if t[0] in documented:
|
||||
doc.append(t)
|
||||
else:
|
||||
undoc.append(t)
|
||||
return doc, undoc
|
||||
|
||||
def print_list(L, title=None):
|
||||
"""Dump a list to stdout."""
|
||||
if title:
|
||||
print title + ":"
|
||||
print "-" * (len(title) + 1)
|
||||
w = 0
|
||||
for sym, filename in L:
|
||||
w = max(w, len(sym))
|
||||
if w % 4 == 0:
|
||||
w += 4
|
||||
else:
|
||||
w += (4 - (w % 4))
|
||||
for sym, filename in L:
|
||||
print "%-*s%s" % (w, sym, filename)
|
||||
|
||||
|
||||
_spcjoin = ' '.join
|
||||
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
if args:
|
||||
headers = args
|
||||
documented = []
|
||||
else:
|
||||
os.chdir(os.path.join(srcdir, "Include"))
|
||||
headers = list_headers()
|
||||
documented = list_documented_items()
|
||||
|
||||
cmd = ("ctags -f - --file-scope=no --c-types=dgpstux "
|
||||
"-Istaticforward -Istatichere=static "
|
||||
+ _spcjoin(headers))
|
||||
fp = os.popen(cmd)
|
||||
L = []
|
||||
prevsym = None
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
sym, filename = line.split()[:2]
|
||||
if sym == prevsym:
|
||||
continue
|
||||
if not sym.endswith("_H"):
|
||||
L.append((sym, filename))
|
||||
prevsym = sym
|
||||
L.sort()
|
||||
fp.close()
|
||||
|
||||
try:
|
||||
if documented:
|
||||
documented, undocumented = split_documented(L, documented)
|
||||
print_list(documented, "Documented symbols")
|
||||
if undocumented:
|
||||
print
|
||||
print_list(undocumented, "Undocumented symbols")
|
||||
else:
|
||||
print_list(L)
|
||||
except IOError as e:
|
||||
if e.errno != errno.EPIPE:
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,63 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# -*- Python -*-
|
||||
|
||||
import fileinput
|
||||
import getopt
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
declare_rx = re.compile(
|
||||
r"\\declaremodule(?:\[[a-zA-Z0-9]*\]*)?{[a-zA-Z_0-9]+}{([a-zA-Z_0-9]+)}")
|
||||
|
||||
module_rx = re.compile(r"\\module{([a-zA-Z_0-9]+)}")
|
||||
|
||||
def main():
|
||||
try:
|
||||
just_list = 0
|
||||
print_lineno = 0
|
||||
opts, args = getopt.getopt(sys.argv[1:], "ln", ["list", "number"])
|
||||
for opt, arg in opts:
|
||||
if opt in ("-l", "--list"):
|
||||
just_list = 1
|
||||
elif opt in ("-n", "--number"):
|
||||
print_lineno = 1
|
||||
files = args
|
||||
if not files:
|
||||
files = glob.glob("*.tex")
|
||||
files.sort()
|
||||
modulename = None
|
||||
for line in fileinput.input(files):
|
||||
if line[:9] == r"\section{":
|
||||
modulename = None
|
||||
continue
|
||||
if line[:16] == r"\modulesynopsys{":
|
||||
continue
|
||||
m = declare_rx.match(line)
|
||||
if m:
|
||||
modulename = m.group(1)
|
||||
continue
|
||||
if not modulename:
|
||||
continue
|
||||
m = module_rx.search(line)
|
||||
if m:
|
||||
name = m.group(1)
|
||||
if name != modulename:
|
||||
filename = fileinput.filename()
|
||||
if just_list:
|
||||
print filename
|
||||
fileinput.nextfile()
|
||||
modulename = None
|
||||
elif print_lineno:
|
||||
print "%s(%d):%s" \
|
||||
% (filename, fileinput.filelineno(), line[:-1])
|
||||
else:
|
||||
print "%s:%s" % (filename, line[:-1])
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,128 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Released to the public domain by Skip Montanaro, 28 March 2002
|
||||
|
||||
"""
|
||||
findsyms.py - try to identify undocumented symbols exported by modules
|
||||
|
||||
Usage: findsyms.py librefdir
|
||||
|
||||
For each lib*.tex file in the libref manual source directory, identify which
|
||||
module is documented, import the module if possible, then search the LaTeX
|
||||
source for the symbols global to that module. Report any that don't seem to
|
||||
be documented.
|
||||
|
||||
Certain exceptions are made to the list of undocumented symbols:
|
||||
|
||||
* don't mention symbols in which all letters are upper case on the
|
||||
assumption they are manifest constants
|
||||
|
||||
* don't mention symbols that are themselves modules
|
||||
|
||||
* don't mention symbols that match those exported by os, math, string,
|
||||
types, or __builtin__ modules
|
||||
|
||||
Finally, if a name is exported by the module but fails a getattr() lookup,
|
||||
that anomaly is reported.
|
||||
"""
|
||||
|
||||
import __builtin__
|
||||
import getopt
|
||||
import glob
|
||||
import math
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
import types
|
||||
import warnings
|
||||
|
||||
def usage():
|
||||
print >> sys.stderr, """
|
||||
usage: %s dir
|
||||
where 'dir' is the Library Reference Manual source directory.
|
||||
""" % os.path.basename(sys.argv[0])
|
||||
|
||||
def main():
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "")
|
||||
except getopt.error:
|
||||
usage()
|
||||
return
|
||||
|
||||
if not args:
|
||||
usage()
|
||||
return
|
||||
|
||||
libdir = args[0]
|
||||
|
||||
warnings.filterwarnings("error")
|
||||
|
||||
pat = re.compile(r"\\declaremodule\s*{[^}]*}\s*{([^}]*)}")
|
||||
|
||||
missing = []
|
||||
filelist = glob.glob(os.path.join(libdir, "lib*.tex"))
|
||||
filelist.sort()
|
||||
for f in filelist:
|
||||
mod = f[3:-4]
|
||||
if not mod: continue
|
||||
data = open(f).read()
|
||||
mods = re.findall(pat, data)
|
||||
if not mods:
|
||||
print "No module declarations found in", f
|
||||
continue
|
||||
for modname in mods:
|
||||
# skip special modules
|
||||
if modname.startswith("__"):
|
||||
continue
|
||||
try:
|
||||
mod = __import__(modname)
|
||||
except ImportError:
|
||||
missing.append(modname)
|
||||
continue
|
||||
except DeprecationWarning:
|
||||
print "Deprecated module:", modname
|
||||
continue
|
||||
if hasattr(mod, "__all__"):
|
||||
all = mod.__all__
|
||||
else:
|
||||
all = [k for k in dir(mod) if k[0] != "_"]
|
||||
mentioned = 0
|
||||
all.sort()
|
||||
for name in all:
|
||||
if data.find(name) == -1:
|
||||
# certain names are predominantly used for testing
|
||||
if name in ("main","test","_test"):
|
||||
continue
|
||||
# is it some sort of manifest constant?
|
||||
if name.upper() == name:
|
||||
continue
|
||||
try:
|
||||
item = getattr(mod, name)
|
||||
except AttributeError:
|
||||
print " ", name, "exposed, but not an attribute"
|
||||
continue
|
||||
# don't care about modules that might be exposed
|
||||
if type(item) == types.ModuleType:
|
||||
continue
|
||||
# check a few modules which tend to be import *'d
|
||||
isglobal = 0
|
||||
for m in (os, math, string, __builtin__, types):
|
||||
if hasattr(m, name) and item == getattr(m, name):
|
||||
isglobal = 1
|
||||
break
|
||||
if isglobal: continue
|
||||
if not mentioned:
|
||||
print "Not mentioned in", modname, "docs:"
|
||||
mentioned = 1
|
||||
print " ", name
|
||||
if missing:
|
||||
missing.sort()
|
||||
print "Could not import:"
|
||||
print " ", ", ".join(missing)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/sh
|
||||
sed -e 's/{\\ptt[ ]*\\char[ ]*'"'"'137}/_/g' <"$1" > "@$1" && mv "@$1" $1
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/sed -f
|
||||
s/{\\tt \\hackscore {}\\hackscore {}/\\sectcode{__/
|
||||
s/\\hackscore {}\\hackscore {}/__/
|
|
@ -1,15 +0,0 @@
|
|||
(defun fix-python-texinfo ()
|
||||
(goto-char (point-min))
|
||||
(replace-regexp "\\(@setfilename \\)\\([-a-z]*\\)$"
|
||||
"\\1python-\\2.info")
|
||||
(replace-string "@node Front Matter\n@chapter Abstract\n"
|
||||
"@node Abstract\n@section Abstract\n")
|
||||
(mark-whole-buffer)
|
||||
(texinfo-master-menu 'update-all-nodes)
|
||||
(save-buffer)
|
||||
) ;; fix-python-texinfo
|
||||
|
||||
;; now really do it:
|
||||
(find-file (car command-line-args-left))
|
||||
(fix-python-texinfo)
|
||||
(kill-emacs)
|
|
@ -1,97 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
"""Generate a page count report of the PostScript version of the manuals."""
|
||||
|
||||
__version__ = '$Revision$'
|
||||
|
||||
import getopt
|
||||
import sys
|
||||
|
||||
|
||||
class PageCounter:
|
||||
def __init__(self):
|
||||
self.doclist = []
|
||||
self.total = 0
|
||||
self.title_width = 0
|
||||
self.version = ""
|
||||
|
||||
def add_document(self, prefix, title):
|
||||
count = count_pages(prefix + ".ps")
|
||||
self.doclist.append((title, prefix, count))
|
||||
self.title_width = max(self.title_width, len(title))
|
||||
self.total = self.total + count
|
||||
|
||||
def dump(self):
|
||||
fmt = "%%-%ds (%%s.ps, %%d pages)" % self.title_width
|
||||
for item in self.doclist:
|
||||
print fmt % item
|
||||
print
|
||||
print " Total page count: %d" % self.total
|
||||
|
||||
def parse_options(self):
|
||||
opts, args = getopt.getopt(sys.argv[1:], "r:", ["release="])
|
||||
assert not args
|
||||
for opt, arg in opts:
|
||||
if opt in ("-r", "--release"):
|
||||
self.version = arg
|
||||
|
||||
def run(self):
|
||||
self.parse_options()
|
||||
if self.version:
|
||||
version = self.version[:3]
|
||||
self.add_document("whatsnew" + version.replace(".", ""),
|
||||
"What's New in Python " + version)
|
||||
for prefix, title in [
|
||||
("api", "Python/C API"),
|
||||
("ext", "Extending and Embedding the Python Interpreter"),
|
||||
("lib", "Python Library Reference"),
|
||||
("mac", "Macintosh Module Reference"),
|
||||
("ref", "Python Reference Manual"),
|
||||
("tut", "Python Tutorial"),
|
||||
("doc", "Documenting Python"),
|
||||
("inst", "Installing Python Modules"),
|
||||
("dist", "Distributing Python Modules"),
|
||||
]:
|
||||
self.add_document(prefix, title)
|
||||
print self.PREFIX
|
||||
self.dump()
|
||||
print self.SUFFIX
|
||||
|
||||
PREFIX = """\
|
||||
This is the PostScript version of the standard Python documentation.
|
||||
If you plan to print this, be aware that some of the documents are
|
||||
long. It is formatted for printing on two-sided paper; if you do plan
|
||||
to print this, *please* print two-sided if you have a printer capable
|
||||
of it! To locate published copies of the larger manuals, or other
|
||||
Python reference material, consult the Python Bookstore at:
|
||||
|
||||
http://wiki.python.org/moin/PythonBooks
|
||||
|
||||
The following manuals are included in this package:
|
||||
"""
|
||||
SUFFIX = """\
|
||||
|
||||
|
||||
If you have any questions, comments, or suggestions regarding these
|
||||
documents, please send them via email to docs@python.org.
|
||||
"""
|
||||
|
||||
def count_pages(filename):
|
||||
fp = open(filename)
|
||||
count = 0
|
||||
while 1:
|
||||
lines = fp.readlines(1024*40)
|
||||
if not lines:
|
||||
break
|
||||
for line in lines:
|
||||
if line[:7] == "%%Page:":
|
||||
count = count + 1
|
||||
fp.close()
|
||||
return count
|
||||
|
||||
|
||||
def main():
|
||||
PageCounter().run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,71 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
try:
|
||||
__file__
|
||||
except NameError:
|
||||
__file__ = sys.argv[0]
|
||||
|
||||
tools = os.path.dirname(os.path.abspath(__file__))
|
||||
Doc = os.path.dirname(tools)
|
||||
src = os.path.dirname(Doc)
|
||||
patchlevel_h = os.path.join(src, "Include", "patchlevel.h")
|
||||
|
||||
# This won't pick out all #defines, but it will pick up the ones we
|
||||
# care about.
|
||||
rx = re.compile(r"\s*#define\s+([a-zA-Z][a-zA-Z_0-9]*)\s+([a-zA-Z_0-9]+)")
|
||||
|
||||
d = {}
|
||||
f = open(patchlevel_h)
|
||||
for line in f:
|
||||
m = rx.match(line)
|
||||
if m is not None:
|
||||
name, value = m.group(1, 2)
|
||||
d[name] = value
|
||||
f.close()
|
||||
|
||||
release = "%s.%s" % (d["PY_MAJOR_VERSION"], d["PY_MINOR_VERSION"])
|
||||
micro = int(d["PY_MICRO_VERSION"])
|
||||
shortversion = release
|
||||
if micro != 0:
|
||||
release += "." + str(micro)
|
||||
level = d["PY_RELEASE_LEVEL"]
|
||||
|
||||
suffixes = {
|
||||
"PY_RELEASE_LEVEL_ALPHA": "a",
|
||||
"PY_RELEASE_LEVEL_BETA": "b",
|
||||
"PY_RELEASE_LEVEL_GAMMA": "c",
|
||||
}
|
||||
|
||||
releaseinfo = ""
|
||||
if level != "PY_RELEASE_LEVEL_FINAL":
|
||||
releaseinfo = suffixes[level] + str(int(d["PY_RELEASE_SERIAL"]))
|
||||
|
||||
def write_file(name, text):
|
||||
"""Write text to a file if the file doesn't exist or if text
|
||||
differs from any existing content."""
|
||||
if os.path.exists(name):
|
||||
f = open(name, "r")
|
||||
s = f.read()
|
||||
f.close()
|
||||
if s == text:
|
||||
return
|
||||
f = open(name, "w")
|
||||
f.write(text)
|
||||
f.close()
|
||||
|
||||
patchlevel_tex = os.path.join(Doc, "commontex", "patchlevel.tex")
|
||||
|
||||
write_file(patchlevel_tex,
|
||||
"%% This file is generated by ../tools/getversioninfo;\n"
|
||||
"%% do not edit manually.\n"
|
||||
"\n"
|
||||
"\\release{%s}\n"
|
||||
"\\setreleaseinfo{%s}\n"
|
||||
"\\setshortversion{%s}\n"
|
||||
% (release, releaseinfo, shortversion))
|
||||
|
||||
print(release + releaseinfo)
|
File diff suppressed because it is too large
Load diff
|
@ -1,100 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
"""Combine similar index entries into an entry and subentries.
|
||||
|
||||
For example:
|
||||
|
||||
\item {foobar} (in module flotz), 23
|
||||
\item {foobar} (in module whackit), 4323
|
||||
|
||||
becomes
|
||||
|
||||
\item {foobar}
|
||||
\subitem in module flotz, 23
|
||||
\subitem in module whackit, 4323
|
||||
|
||||
Note that an item which matches the format of a collapsable item but which
|
||||
isn't part of a group of similar items is not modified.
|
||||
"""
|
||||
__version__ = '$Revision$'
|
||||
|
||||
import re
|
||||
import io
|
||||
import sys
|
||||
|
||||
|
||||
def cmp_entries(e1, e2):
|
||||
return cmp(e1[1].lower(), e2[1].lower()) or cmp(e1, e2)
|
||||
|
||||
|
||||
def dump_entries(write, entries):
|
||||
if len(entries) == 1:
|
||||
write(" \\item %s (%s)%s\n" % entries[0])
|
||||
return
|
||||
write(" \item %s\n" % entries[0][0])
|
||||
# now sort these in a case insensitive manner:
|
||||
if len(entries) > 0:
|
||||
entries.sort(cmp_entries)
|
||||
for xxx, subitem, pages in entries:
|
||||
write(" \subitem %s%s\n" % (subitem, pages))
|
||||
|
||||
|
||||
breakable_re = re.compile(
|
||||
r" \\item (.*) [(](.*)[)]((?:(?:, \d+)|(?:, \\[a-z]*\{\d+\}))+)")
|
||||
|
||||
|
||||
def process(ifn, ofn=None):
|
||||
if ifn == "-":
|
||||
ifp = sys.stdin
|
||||
else:
|
||||
ifp = open(ifn)
|
||||
if ofn is None:
|
||||
ofn = ifn
|
||||
ofp = io.StringIO()
|
||||
entries = []
|
||||
match = breakable_re.match
|
||||
write = ofp.write
|
||||
while 1:
|
||||
line = ifp.readline()
|
||||
if not line:
|
||||
break
|
||||
m = match(line)
|
||||
if m:
|
||||
entry = m.group(1, 2, 3)
|
||||
if entries and entries[-1][0] != entry[0]:
|
||||
dump_entries(write, entries)
|
||||
entries = []
|
||||
entries.append(entry)
|
||||
elif entries:
|
||||
dump_entries(write, entries)
|
||||
entries = []
|
||||
write(line)
|
||||
else:
|
||||
write(line)
|
||||
del write
|
||||
del match
|
||||
ifp.close()
|
||||
data = ofp.getvalue()
|
||||
ofp.close()
|
||||
if ofn == "-":
|
||||
ofp = sys.stdout
|
||||
else:
|
||||
ofp = open(ofn, "w")
|
||||
ofp.write(data)
|
||||
ofp.close()
|
||||
|
||||
|
||||
def main():
|
||||
import getopt
|
||||
outfile = None
|
||||
opts, args = getopt.getopt(sys.argv[1:], "o:")
|
||||
for opt, val in opts:
|
||||
if opt in ("-o", "--output"):
|
||||
outfile = val
|
||||
filename = args[0]
|
||||
outfile = outfile or filename
|
||||
process(filename, outfile)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,25 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
# This Python program sorts and reformats the table of keywords in ref2.tex
|
||||
|
||||
def raw_input(prompt):
|
||||
import sys
|
||||
sys.stdout.write(prompt)
|
||||
sys.stdout.flush()
|
||||
return sys.stdin.readline()
|
||||
|
||||
l = []
|
||||
try:
|
||||
while 1:
|
||||
l = l + raw_input().split()
|
||||
except EOFError:
|
||||
pass
|
||||
l.sort()
|
||||
for x in l[:]:
|
||||
while l.count(x) > 1: l.remove(x)
|
||||
ncols = 5
|
||||
nrows = (len(l)+ncols-1)/ncols
|
||||
for i in range(nrows):
|
||||
for j in range(i, len(l), nrows):
|
||||
print(l[j].ljust(10), end=' ')
|
||||
print()
|
|
@ -1,182 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# -*- Python -*-
|
||||
#
|
||||
# This script can be used to identify undocumented modules in the Python
|
||||
# standard library. Use it like this:
|
||||
#
|
||||
# .../Doc/tools/listmodules --ignore-from .../Doc/paper-<paper>/modlib.idx
|
||||
|
||||
"""%(program)s - list modules in the Python standard library
|
||||
|
||||
-a, --annotate Annotate the module names with the subdirectory they
|
||||
live in
|
||||
-c, --categorize Group the modules by subdirectory
|
||||
-i <file>,
|
||||
|
||||
--ignore-from <file> Ignore the modules listed in <file>. <file> may
|
||||
contain a list of module names or a module index file
|
||||
as produced when formatting the Python documentation
|
||||
(.idx or .html flavor).
|
||||
|
||||
If neither -a nor -c are given, the modules are listed in alphabetical
|
||||
order.
|
||||
|
||||
Note that -a and -c are mutually exclusive.
|
||||
|
||||
Limitation: Modules loadable as shared objects may not be listed,
|
||||
though this script attempts to locate such modules.
|
||||
|
||||
"""
|
||||
|
||||
__version__ = '$Revision$'
|
||||
|
||||
import getopt
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
REMOVE_DIRS = ["encodings", "distutils",
|
||||
"lib-old", ""test"]
|
||||
|
||||
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
annotate = 0
|
||||
builtin = 0
|
||||
categorize = 0
|
||||
ignore_dict = {}
|
||||
ignore = ignore_dict.has_key
|
||||
try:
|
||||
opts, args = getopt.getopt(
|
||||
args, "abchi:",
|
||||
["annotate", "built-in", "categorize", "help", "ignore-from="])
|
||||
except getopt.error as msg:
|
||||
sys.stdout = sys.stderr
|
||||
print msg
|
||||
print
|
||||
usage()
|
||||
sys.exit(2)
|
||||
for opt, arg in opts:
|
||||
if opt in ("-a", "--annotate"):
|
||||
annotate = 1
|
||||
elif opt in ("-b", "--built-in"):
|
||||
builtin = 1
|
||||
elif opt in ("-c", "--categorize"):
|
||||
categorize = 1
|
||||
elif opt in ("-h", "--help"):
|
||||
usage()
|
||||
sys.exit()
|
||||
elif opt in ("-i", "--ignore-from"):
|
||||
data = open(arg).read()
|
||||
if data[:1] == "\\":
|
||||
ignore_from_idx(data, ignore_dict)
|
||||
else:
|
||||
ignore_from_modulelist(data, ignore_dict)
|
||||
if args or (annotate and categorize):
|
||||
usage()
|
||||
sys.exit(2)
|
||||
#
|
||||
# Populate the database:
|
||||
#
|
||||
srcdir = os.path.normpath(os.path.join(
|
||||
os.path.dirname(sys.argv[0]), os.pardir, os.pardir))
|
||||
os.chdir(srcdir)
|
||||
modules_by_name = {}
|
||||
modules_by_dir = {}
|
||||
if builtin:
|
||||
l = []
|
||||
modules_by_dir["<builtin>"] = l
|
||||
for name in sys.builtin_module_names:
|
||||
if not ignore(name):
|
||||
modules_by_name[name] = "<built-in>"
|
||||
l.append(name)
|
||||
rx = re.compile("Lib/plat-[a-zA-Z0-9]*/")
|
||||
fp = os.popen("find Lib -name \*.py -print", "r")
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
m = rx.match(line)
|
||||
if m:
|
||||
line = "Lib/plat-*/" + line[m.end():]
|
||||
line = line[4:-4] # strip off 'Lib/' and '.py\n'
|
||||
dir, name = os.path.split(line)
|
||||
dir = dir or "<standard>"
|
||||
if ignore(name):
|
||||
continue
|
||||
if dir not in REMOVE_DIRS:
|
||||
modules_by_name[name] = dir
|
||||
l = modules_by_dir.get(dir, [])
|
||||
modules_by_dir[dir] = l
|
||||
if name not in l:
|
||||
l.append(name)
|
||||
# load up extension modules:
|
||||
pwd = os.getcwd()
|
||||
try:
|
||||
os.chdir("Modules")
|
||||
dir = "<extension>"
|
||||
for line in glob.glob("*module.c"):
|
||||
name = line[:-8]
|
||||
if ignore(name) or modules_by_name.has_key(name) or name == "xx":
|
||||
continue
|
||||
modules_by_name[name] = dir
|
||||
l = modules_by_dir.get(dir, [])
|
||||
modules_by_dir[dir] = l
|
||||
if name not in l:
|
||||
l.append(name)
|
||||
finally:
|
||||
os.chdir(pwd)
|
||||
#
|
||||
# Dump the results:
|
||||
#
|
||||
if annotate:
|
||||
modules = modules_by_name.items()
|
||||
modules.sort()
|
||||
width = max(map(len, modules_by_name.keys()))
|
||||
format = "%%-%ds %%s" % width
|
||||
for name, dir in modules:
|
||||
if dir and dir[0] != "<":
|
||||
print format % (name, dir)
|
||||
else:
|
||||
print name
|
||||
elif categorize:
|
||||
modules = modules_by_dir.items()
|
||||
modules.sort()
|
||||
width = max(map(len, modules_by_dir.keys()))
|
||||
format = "%%-%ds %%s" % width
|
||||
for dir, names in modules:
|
||||
names.sort()
|
||||
print format % (dir, names[0])
|
||||
for name in names[1:]:
|
||||
print format % ('', name)
|
||||
print
|
||||
else:
|
||||
modules = modules_by_name.keys()
|
||||
modules.sort()
|
||||
print "\n".join(modules)
|
||||
|
||||
|
||||
def ignore_from_modulelist(data, ignore_dict):
|
||||
for name in data.split():
|
||||
ignore_dict[name] = name
|
||||
|
||||
def ignore_from_idx(data, ignore_dict):
|
||||
data = data.replace(r"\hackscore {}", "_")
|
||||
rx = re.compile(r"\\indexentry\s*{([^@]*)@")
|
||||
for line in data.split("\n"):
|
||||
m = rx.match(line)
|
||||
if m:
|
||||
name = m.group(1)
|
||||
ignore_dict[name] = name
|
||||
|
||||
|
||||
def usage():
|
||||
vars = {}
|
||||
vars["program"] = os.path.basename(sys.argv[0])
|
||||
print __doc__ % vars
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,125 +0,0 @@
|
|||
# $Id$
|
||||
#
|
||||
# Locate all standard modules available in this build.
|
||||
#
|
||||
# This script is designed to run on Python 1.5.2 and newer.
|
||||
#
|
||||
# Written by Fredrik Lundh, January 2005
|
||||
#
|
||||
|
||||
import imp, sys, os, re, time
|
||||
|
||||
identifier = "python-%s-%s" % (sys.version[:3], sys.platform)
|
||||
timestamp = time.strftime("%Y%m%dT%H%M%SZ", time.gmtime(time.time()))
|
||||
|
||||
# known test packages
|
||||
TEST_PACKAGES = "test.", "bsddb.test.", "distutils.tests."
|
||||
|
||||
try:
|
||||
import platform
|
||||
platform = platform.platform()
|
||||
except:
|
||||
platform = None # unknown
|
||||
|
||||
suffixes = imp.get_suffixes()
|
||||
|
||||
def get_suffix(file):
|
||||
for suffix in suffixes:
|
||||
if file[-len(suffix[0]):] == suffix[0]:
|
||||
return suffix
|
||||
return None
|
||||
|
||||
def main():
|
||||
|
||||
path = getpath()
|
||||
|
||||
modules = {}
|
||||
for m in sys.builtin_module_names:
|
||||
modules[m] = None
|
||||
|
||||
for p in path:
|
||||
modules.update(getmodules(p))
|
||||
|
||||
keys = sorted(modules.keys())
|
||||
|
||||
# filter out known test packages
|
||||
def cb(m):
|
||||
for d in TEST_PACKAGES:
|
||||
if m[:len(d)] == d:
|
||||
return 0
|
||||
return 1
|
||||
keys = filter(cb, keys)
|
||||
|
||||
try:
|
||||
outfile = sys.argv[1]
|
||||
if outfile == "-":
|
||||
outfile = None
|
||||
elif outfile == "-f":
|
||||
outfile = "modules-" + identifier + ".txt"
|
||||
except IndexError:
|
||||
outfile = None
|
||||
|
||||
if not outfile:
|
||||
out = sys.stdout
|
||||
else:
|
||||
out = open(outfile, "w")
|
||||
|
||||
out.write("# module list (generated by listmodules.py)\n")
|
||||
out.write("#\n")
|
||||
out.write("# timestamp=%s\n" % repr(timestamp))
|
||||
out.write("# sys.version=%s\n" % repr(sys.version))
|
||||
out.write("# sys.platform=%s\n" % repr(sys.platform))
|
||||
if platform:
|
||||
out.write("# platform=%s\n" % repr(platform))
|
||||
out.write("#\n")
|
||||
|
||||
for k in keys:
|
||||
out.write(k + "\n")
|
||||
|
||||
if out is not sys.stdout:
|
||||
out.close()
|
||||
print(out.name, "ok (%d modules)" % len(modules))
|
||||
|
||||
def getmodules(p):
|
||||
# get modules in a given directory
|
||||
modules = {}
|
||||
for f in os.listdir(p):
|
||||
f = os.path.join(p, f)
|
||||
if os.path.isfile(f):
|
||||
m, e = os.path.splitext(f)
|
||||
suffix = get_suffix(f)
|
||||
if not suffix:
|
||||
continue
|
||||
m = os.path.basename(m)
|
||||
if re.compile("(?i)[a-z_]\w*$").match(m):
|
||||
if suffix[2] == imp.C_EXTENSION:
|
||||
# check that this extension can be imported
|
||||
try:
|
||||
__import__(m)
|
||||
except ImportError:
|
||||
continue
|
||||
modules[m] = f
|
||||
elif os.path.isdir(f):
|
||||
m = os.path.basename(f)
|
||||
if os.path.isfile(os.path.join(f, "__init__.py")):
|
||||
for mm, f in getmodules(f).items():
|
||||
modules[m + "." + mm] = f
|
||||
return modules
|
||||
|
||||
def getpath():
|
||||
path = map(os.path.normcase, map(os.path.abspath, sys.path[:]))
|
||||
# get rid of site packages
|
||||
for p in path:
|
||||
if p[-13:] == "site-packages":
|
||||
def cb(p, site_package_path=os.path.abspath(p)):
|
||||
return p[:len(site_package_path)] != site_package_path
|
||||
path = filter(cb, path)
|
||||
break
|
||||
# get rid of non-existent directories and the current directory
|
||||
def cb(p, cwd=os.path.normcase(os.getcwd())):
|
||||
return os.path.isdir(p) and p != cwd
|
||||
path = filter(cb, path)
|
||||
return path
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,129 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Simple little checker for individual libref manual sections
|
||||
#
|
||||
# usage: makesec.sh section
|
||||
#
|
||||
|
||||
# This script builds the minimal file necessary to run a single section
|
||||
# through latex, does so, then converts the resulting dvi file to ps or pdf
|
||||
# and feeds the result into a viewer. It's by no means foolproof, but seems
|
||||
# to work okay for me (knock wood). It sure beats manually commenting out
|
||||
# most of the man lib.tex file and running everything manually.
|
||||
|
||||
# It attempts to locate an appropriate dvi converter and viewer for the
|
||||
# selected output format. It understands the following environment
|
||||
# variables:
|
||||
#
|
||||
# PYSRC - refers to the root of your build tree (dir containing Doc)
|
||||
# DVICVT - refers to a dvi converter like dvips or dvipdf
|
||||
# VIEWER - refers to an appropriate viewer for the ps/pdf file
|
||||
#
|
||||
# Of the three, only PYSRC is currently required. The other two can be set
|
||||
# to specify unusual tools which perform those tasks.
|
||||
|
||||
# Known issues:
|
||||
# - It would be nice if the script could determine PYSRC on its own.
|
||||
# - Something about \seealso{}s blows the latex stack, so they need
|
||||
# to be commented out for now.
|
||||
|
||||
if [ x$PYSRC = x ] ; then
|
||||
echo "PYSRC must refer to the Python source tree" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d $PYSRC/Doc ] ; then
|
||||
echo "Can't find a Doc subdirectory in $PYSRC" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$#" -ne 1 ] ; then
|
||||
echo "Must specify a single libref manual section on cmd line" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# settle on a dvi converter
|
||||
if [ x$DVICVT != x ] ; then
|
||||
converter=$DVICVT
|
||||
ext=`echo $DVICVT | sed -e 's/^dvi//'`
|
||||
result=lib.$ext
|
||||
elif [ x`which dvipdf` != x ] ; then
|
||||
converter=`which dvipdf`
|
||||
ext=.pdf
|
||||
elif [ x`which dvips` != x ] ; then
|
||||
converter=`which dvips`
|
||||
ext=.ps
|
||||
else
|
||||
echo "Can't find a reasonable dvi converter" 1>&2
|
||||
echo "Set DVICVT to refer to one" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# how about a viewer?
|
||||
if [ x$VIEWER != x ] ; then
|
||||
viewer=$VIEWER
|
||||
elif [ $ext = ".ps" -a x`which gv` != x ] ; then
|
||||
viewer=gv
|
||||
elif [ $ext = ".ps" -a x`which gs` != x ] ; then
|
||||
viewer=gs
|
||||
elif [ $ext = ".pdf" -a x`which acroread` != x ] ; then
|
||||
viewer=acroread
|
||||
elif [ $ext = ".pdf" -a "`uname`" = "Darwin" -a x`which open` != x ] ; then
|
||||
viewer=open
|
||||
elif [ $ext = ".pdf" -a x`which acroread` != x ] ; then
|
||||
viewer=acroread
|
||||
else
|
||||
echo "Can't find a reasonable viewer" 1>&2
|
||||
echo "Set VIEWER to refer to one" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# make sure necessary links are in place
|
||||
for f in howto.cls pypaper.sty ; do
|
||||
rm -f $f
|
||||
ln -s $PYSRC/Doc/$f
|
||||
done
|
||||
|
||||
export TEXINPUTS=.:$PYSRC/Doc/texinputs:
|
||||
|
||||
# strip extension in case they gave full filename
|
||||
inp=`basename $1 .tex`
|
||||
|
||||
# create the minimal framework necessary to run section through latex
|
||||
tmpf=lib.tex
|
||||
cat > $tmpf <<EOF
|
||||
\documentclass{manual}
|
||||
|
||||
% NOTE: this file controls which chapters/sections of the library
|
||||
% manual are actually printed. It is easy to customize your manual
|
||||
% by commenting out sections that you are not interested in.
|
||||
|
||||
\title{Python Library Reference}
|
||||
|
||||
\input{boilerplate}
|
||||
|
||||
\makeindex % tell \index to actually write the
|
||||
% .idx file
|
||||
\makemodindex % ... and the module index as well.
|
||||
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
|
||||
\ifhtml
|
||||
\chapter*{Front Matter\label{front}}
|
||||
\fi
|
||||
|
||||
\input{$inp}
|
||||
\end{document}
|
||||
EOF
|
||||
|
||||
latex $tmpf
|
||||
|
||||
$converter lib
|
||||
|
||||
$viewer lib.pdf
|
||||
|
||||
rm -f $tmpf howto.cls pypaper.sty *.idx *.syn
|
||||
rm -f lib.aux lib.log
|
|
@ -1,65 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# -*- Python -*-
|
||||
|
||||
import support
|
||||
import sys
|
||||
|
||||
|
||||
def collect(fp):
|
||||
names = []
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
line = line.strip()
|
||||
if line:
|
||||
names.append(line)
|
||||
else:
|
||||
names = []
|
||||
return names
|
||||
|
||||
|
||||
def main():
|
||||
options = support.Options()
|
||||
options.columns = 4
|
||||
options.variables["title"] = "Acknowledgements"
|
||||
options.parse(sys.argv[1:])
|
||||
names = collect(sys.stdin)
|
||||
percol = (len(names) + options.columns - 1) // options.columns
|
||||
colnums = []
|
||||
for i in range(options.columns):
|
||||
colnums.append(percol*i)
|
||||
options.aesop_type = "information"
|
||||
fp = options.get_output_file()
|
||||
fp.write(options.get_header().rstrip() + "\n")
|
||||
fp.write(THANKS + "\n")
|
||||
fp.write('<table width="100%" align="center">\n')
|
||||
for i in range(percol):
|
||||
fp.write(" <tr>\n")
|
||||
for j in colnums:
|
||||
try:
|
||||
fp.write(" <td>%s</td>\n" % names[i + j])
|
||||
except IndexError:
|
||||
pass
|
||||
fp.write(" </tr>\n")
|
||||
fp.write("</table>\n")
|
||||
fp.write(options.get_footer().rstrip() + "\n")
|
||||
fp.close()
|
||||
|
||||
THANKS = '''\
|
||||
|
||||
<p>These people have contributed in some way to the Python
|
||||
documentation. This list is probably not complete -- if you feel that
|
||||
you or anyone else should be on this list, please let us know (send
|
||||
email to <a
|
||||
href="mailto:docs@python.org">docs@python.org</a>), and
|
||||
we will be glad to correct the problem.</p>
|
||||
|
||||
<p>It is only with the input and contributions of the Python community
|
||||
that Python has such wonderful documentation -- <b>Thank You!</b></p>
|
||||
|
||||
'''
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,659 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# -*- Python -*-
|
||||
"""usage: %(program)s [options...] file ...
|
||||
|
||||
Options specifying formats to build:
|
||||
--html HyperText Markup Language (default)
|
||||
--pdf Portable Document Format
|
||||
--ps PostScript
|
||||
--dvi 'DeVice Indepentent' format from TeX
|
||||
--text ASCII text (requires lynx)
|
||||
|
||||
More than one output format may be specified, or --all.
|
||||
|
||||
HTML options:
|
||||
--address, -a Specify an address for page footers.
|
||||
--dir Specify the directory for HTML output.
|
||||
--link Specify the number of levels to include on each page.
|
||||
--split, -s Specify a section level for page splitting, default: %(max_split_depth)s.
|
||||
--iconserver, -i Specify location of icons (default: ./).
|
||||
--image-type Specify the image type to use in HTML output;
|
||||
values: gif, png (default).
|
||||
--numeric Don't rename the HTML files; just keep node#.html for
|
||||
the filenames.
|
||||
--style Specify the CSS file to use for the output (filename,
|
||||
not a URL).
|
||||
--up-link URL to a parent document.
|
||||
--up-title Title of a parent document.
|
||||
--favicon Icon to display in the browsers location bar.
|
||||
|
||||
Other options:
|
||||
--a4 Format for A4 paper.
|
||||
--letter Format for US letter paper (the default).
|
||||
--help, -H Show this text.
|
||||
--logging, -l Log stdout and stderr to a file (*.how).
|
||||
--debugging, -D Echo commands as they are executed.
|
||||
--keep, -k Keep temporary files around.
|
||||
--quiet, -q Do not print command output to stdout.
|
||||
(stderr is also lost, sorry; see *.how for errors)
|
||||
"""
|
||||
|
||||
import getopt
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
|
||||
MYDIR = os.path.abspath(sys.path[0])
|
||||
TOPDIR = os.path.dirname(MYDIR)
|
||||
|
||||
ISTFILE = os.path.join(TOPDIR, "texinputs", "python.ist")
|
||||
NODE2LABEL_SCRIPT = os.path.join(MYDIR, "node2label.pl")
|
||||
L2H_INIT_FILE = os.path.join(TOPDIR, "perl", "l2hinit.perl")
|
||||
|
||||
BIBTEX_BINARY = "bibtex"
|
||||
DVIPS_BINARY = "dvips"
|
||||
LATEX_BINARY = "latex"
|
||||
LATEX2HTML_BINARY = "latex2html"
|
||||
LYNX_BINARY = "lynx"
|
||||
MAKEINDEX_BINARY = "makeindex"
|
||||
PDFLATEX_BINARY = "pdflatex"
|
||||
PERL_BINARY = "perl"
|
||||
PYTHON_BINARY = "python"
|
||||
|
||||
|
||||
def usage(options, file):
|
||||
print(__doc__ % options, file=file)
|
||||
|
||||
def error(options, message, err=2):
|
||||
print(message, file=sys.stderr)
|
||||
print(file=sys.stderr)
|
||||
usage(options, sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
class Options:
|
||||
program = os.path.basename(sys.argv[0])
|
||||
#
|
||||
address = ''
|
||||
builddir = None
|
||||
debugging = 0
|
||||
discard_temps = 1
|
||||
have_temps = 0
|
||||
icon_server = "."
|
||||
image_type = "png"
|
||||
logging = 0
|
||||
max_link_depth = 3
|
||||
max_split_depth = 6
|
||||
paper = "letter"
|
||||
quiet = 0
|
||||
runs = 0
|
||||
numeric = 0
|
||||
global_module_index = None
|
||||
style_file = os.path.join(TOPDIR, "html", "style.css")
|
||||
about_file = os.path.join(TOPDIR, "html", "about.dat")
|
||||
up_link = None
|
||||
up_title = None
|
||||
favicon = None
|
||||
#
|
||||
# 'dvips_safe' is a weird option. It is used mostly to make
|
||||
# LaTeX2HTML not try to be too smart about protecting the user
|
||||
# from a bad version of dvips -- some versions would core dump if
|
||||
# the path to the source DVI contained a dot, and it's appearantly
|
||||
# difficult to determine if the version available has that bug.
|
||||
# This option gets set when PostScript output is requested
|
||||
# (because we're going to run dvips regardless, and we'll either
|
||||
# know it succeeds before LaTeX2HTML is run, or we'll have
|
||||
# detected the failure and bailed), or the user asserts that it's
|
||||
# safe from the command line.
|
||||
#
|
||||
# So, why does LaTeX2HTML think it appropriate to protect the user
|
||||
# from a dvips that's only potentially going to core dump? Only
|
||||
# because they want to avoid doing a lot of work just to have to
|
||||
# bail later with no useful intermediates. Unfortunately, they
|
||||
# bail *before* they know whether dvips will be needed at all.
|
||||
# I've gone around the bush a few times with the LaTeX2HTML
|
||||
# developers over whether this is appropriate behavior, and they
|
||||
# don't seem interested in changing their position.
|
||||
#
|
||||
dvips_safe = 0
|
||||
#
|
||||
DEFAULT_FORMATS = ("html",)
|
||||
ALL_FORMATS = ("dvi", "html", "pdf", "ps", "text")
|
||||
|
||||
def __init__(self):
|
||||
self.formats = []
|
||||
self.l2h_init_files = []
|
||||
|
||||
def __getitem__(self, key):
|
||||
# This is used when formatting the usage message.
|
||||
try:
|
||||
return getattr(self, key)
|
||||
except AttributeError:
|
||||
raise KeyError(key)
|
||||
|
||||
def parse(self, args):
|
||||
opts, args = getopt.getopt(args, "Hi:a:s:lDkqr:",
|
||||
["all", "postscript", "help", "iconserver=",
|
||||
"address=", "a4", "letter", "l2h-init=",
|
||||
"link=", "split=", "logging", "debugging",
|
||||
"keep", "quiet", "runs=", "image-type=",
|
||||
"about=", "numeric", "style=", "paper=",
|
||||
"up-link=", "up-title=", "dir=",
|
||||
"global-module-index=", "dvips-safe",
|
||||
"favicon="]
|
||||
+ list(self.ALL_FORMATS))
|
||||
for opt, arg in opts:
|
||||
if opt == "--all":
|
||||
self.formats = list(self.ALL_FORMATS)
|
||||
self.dvips_safe = "ps" in self.formats
|
||||
elif opt in ("-H", "--help"):
|
||||
usage(self, sys.stdout)
|
||||
sys.exit()
|
||||
elif opt == "--iconserver":
|
||||
self.icon_server = arg
|
||||
elif opt in ("-a", "--address"):
|
||||
self.address = arg
|
||||
elif opt == "--a4":
|
||||
self.paper = "a4"
|
||||
elif opt == "--letter":
|
||||
self.paper = "letter"
|
||||
elif opt == "--link":
|
||||
self.max_link_depth = int(arg)
|
||||
elif opt in ("-s", "--split"):
|
||||
self.max_split_depth = int(arg)
|
||||
elif opt in ("-l", "--logging"):
|
||||
self.logging = self.logging + 1
|
||||
elif opt in ("-D", "--debugging"):
|
||||
self.debugging = self.debugging + 1
|
||||
elif opt in ("-k", "--keep"):
|
||||
self.discard_temps = 0
|
||||
elif opt in ("-q", "--quiet"):
|
||||
self.quiet = 1
|
||||
elif opt in ("-r", "--runs"):
|
||||
self.runs = int(arg)
|
||||
elif opt == "--image-type":
|
||||
self.image_type = arg
|
||||
elif opt == "--about":
|
||||
# always make this absolute:
|
||||
self.about_file = os.path.normpath(
|
||||
os.path.abspath(arg))
|
||||
elif opt == "--numeric":
|
||||
self.numeric = 1
|
||||
elif opt == "--style":
|
||||
self.style_file = os.path.abspath(arg)
|
||||
elif opt == "--l2h-init":
|
||||
self.l2h_init_files.append(os.path.abspath(arg))
|
||||
elif opt == "--favicon":
|
||||
self.favicon = arg
|
||||
elif opt == "--up-link":
|
||||
self.up_link = arg
|
||||
elif opt == "--up-title":
|
||||
self.up_title = arg
|
||||
elif opt == "--global-module-index":
|
||||
self.global_module_index = arg
|
||||
elif opt == "--dir":
|
||||
if os.sep == "\\":
|
||||
arg = re.sub("/", "\\\\", arg)
|
||||
self.builddir = os.path.expanduser(arg)
|
||||
elif opt == "--paper":
|
||||
self.paper = arg
|
||||
elif opt == "--dvips-safe":
|
||||
self.dvips_safe = 1
|
||||
#
|
||||
# Format specifiers:
|
||||
#
|
||||
elif opt[2:] in self.ALL_FORMATS:
|
||||
self.add_format(opt[2:])
|
||||
elif opt == "--postscript":
|
||||
# synonym for --ps
|
||||
self.add_format("ps")
|
||||
self.initialize()
|
||||
#
|
||||
# return the args to allow the caller access:
|
||||
#
|
||||
return args
|
||||
|
||||
def add_format(self, format):
|
||||
"""Add a format to the formats list if not present."""
|
||||
if not format in self.formats:
|
||||
if format == "ps":
|
||||
# assume this is safe since we're going to run it anyway
|
||||
self.dvips_safe = 1
|
||||
self.formats.append(format)
|
||||
|
||||
def initialize(self):
|
||||
"""Complete initialization. This is needed if parse() isn't used."""
|
||||
# add the default format if no formats were specified:
|
||||
if not self.formats:
|
||||
self.formats = self.DEFAULT_FORMATS
|
||||
# determine the base set of texinputs directories:
|
||||
texinputs = os.environ.get("TEXINPUTS", "").split(os.pathsep)
|
||||
if not texinputs:
|
||||
texinputs = ['']
|
||||
mydirs = [os.path.join(TOPDIR, "paper-" + self.paper),
|
||||
os.path.join(TOPDIR, "texinputs"),
|
||||
]
|
||||
if '' in texinputs:
|
||||
i = texinputs.index('')
|
||||
texinputs[i:i] = mydirs
|
||||
else:
|
||||
texinputs += mydirs
|
||||
self.base_texinputs = texinputs
|
||||
if self.builddir:
|
||||
self.builddir = os.path.abspath(self.builddir)
|
||||
|
||||
|
||||
class Job:
|
||||
latex_runs = 0
|
||||
|
||||
def __init__(self, options, path):
|
||||
self.options = options
|
||||
self.doctype = get_doctype(path)
|
||||
self.filedir, self.doc = split_pathname(path)
|
||||
self.builddir = os.path.abspath(options.builddir or self.doc)
|
||||
if ("html" in options.formats or "text" in options.formats):
|
||||
if not os.path.exists(self.builddir):
|
||||
os.mkdir(self.builddir)
|
||||
self.log_filename = os.path.join(self.builddir, self.doc + ".how")
|
||||
else:
|
||||
self.log_filename = os.path.abspath(self.doc + ".how")
|
||||
if os.path.exists(self.log_filename):
|
||||
os.unlink(self.log_filename)
|
||||
l2hconf = self.doc + ".l2h"
|
||||
if os.path.exists(l2hconf):
|
||||
if os.path.exists(l2hconf + "~"):
|
||||
os.unlink(l2hconf + "~")
|
||||
os.rename(l2hconf, l2hconf + "~")
|
||||
self.l2h_aux_init_file = self.doc + ".l2h"
|
||||
self.write_l2h_aux_init_file()
|
||||
|
||||
def build(self):
|
||||
self.setup_texinputs()
|
||||
formats = self.options.formats
|
||||
if "dvi" in formats or "ps" in formats:
|
||||
self.build_dvi()
|
||||
if "pdf" in formats:
|
||||
self.build_pdf()
|
||||
if "ps" in formats:
|
||||
self.build_ps()
|
||||
if "html" in formats:
|
||||
self.require_temps()
|
||||
self.build_html(self.builddir)
|
||||
if self.options.icon_server == ".":
|
||||
pattern = os.path.join(TOPDIR, "html", "icons",
|
||||
"*." + self.options.image_type)
|
||||
imgs = glob.glob(pattern)
|
||||
if not imgs:
|
||||
self.warning(
|
||||
"Could not locate support images of type %s."
|
||||
% repr(self.options.image_type))
|
||||
for fn in imgs:
|
||||
new_fn = os.path.join(self.builddir, os.path.basename(fn))
|
||||
shutil.copyfile(fn, new_fn)
|
||||
if "text" in formats:
|
||||
self.require_temps()
|
||||
tempdir = self.doc
|
||||
need_html = "html" not in formats
|
||||
if self.options.max_split_depth != 1:
|
||||
fp = open(self.l2h_aux_init_file, "a")
|
||||
fp.write("# re-hack this file for --text:\n")
|
||||
l2hoption(fp, "MAX_SPLIT_DEPTH", "1")
|
||||
fp.write("1;\n")
|
||||
fp.close()
|
||||
tempdir = self.doc + "-temp-html"
|
||||
need_html = 1
|
||||
if need_html:
|
||||
self.build_html(tempdir, max_split_depth=1)
|
||||
self.build_text(tempdir)
|
||||
if self.options.discard_temps:
|
||||
self.cleanup()
|
||||
|
||||
def setup_texinputs(self):
|
||||
texinputs = [self.filedir] + self.options.base_texinputs
|
||||
os.environ["TEXINPUTS"] = os.pathsep.join(texinputs)
|
||||
self.message("TEXINPUTS=" + os.environ["TEXINPUTS"])
|
||||
|
||||
def build_aux(self, binary=None):
|
||||
if binary is None:
|
||||
binary = LATEX_BINARY
|
||||
new_index( "%s.ind" % self.doc, "genindex")
|
||||
new_index("mod%s.ind" % self.doc, "modindex")
|
||||
self.run("%s %s" % (binary, self.doc))
|
||||
self.use_bibtex = check_for_bibtex(self.doc + ".aux")
|
||||
self.latex_runs = 1
|
||||
|
||||
def build_dvi(self):
|
||||
self.use_latex(LATEX_BINARY)
|
||||
|
||||
def build_pdf(self):
|
||||
self.use_latex(PDFLATEX_BINARY)
|
||||
|
||||
def use_latex(self, binary):
|
||||
self.require_temps(binary=binary)
|
||||
if self.latex_runs < 2:
|
||||
if os.path.isfile("mod%s.idx" % self.doc):
|
||||
self.run("%s mod%s.idx" % (MAKEINDEX_BINARY, self.doc))
|
||||
use_indfix = 0
|
||||
if os.path.isfile(self.doc + ".idx"):
|
||||
use_indfix = 1
|
||||
# call to Doc/tools/fix_hack omitted; doesn't appear necessary
|
||||
self.run("%s %s.idx" % (MAKEINDEX_BINARY, self.doc))
|
||||
import indfix
|
||||
indfix.process(self.doc + ".ind")
|
||||
if self.use_bibtex:
|
||||
self.run("%s %s" % (BIBTEX_BINARY, self.doc))
|
||||
self.process_synopsis_files()
|
||||
self.run("%s %s" % (binary, self.doc))
|
||||
self.latex_runs = self.latex_runs + 1
|
||||
if os.path.isfile("mod%s.idx" % self.doc):
|
||||
self.run("%s -s %s mod%s.idx"
|
||||
% (MAKEINDEX_BINARY, ISTFILE, self.doc))
|
||||
if use_indfix:
|
||||
self.run("%s -s %s %s.idx"
|
||||
% (MAKEINDEX_BINARY, ISTFILE, self.doc))
|
||||
indfix.process(self.doc + ".ind")
|
||||
self.process_synopsis_files()
|
||||
#
|
||||
# and now finish it off:
|
||||
#
|
||||
if os.path.isfile(self.doc + ".toc") and binary == PDFLATEX_BINARY:
|
||||
import toc2bkm
|
||||
if self.doctype == "manual":
|
||||
bigpart = "chapter"
|
||||
else:
|
||||
bigpart = "section"
|
||||
toc2bkm.process(self.doc + ".toc", self.doc + ".bkm", bigpart)
|
||||
if self.use_bibtex:
|
||||
self.run("%s %s" % (BIBTEX_BINARY, self.doc))
|
||||
self.run("%s %s" % (binary, self.doc))
|
||||
self.latex_runs = self.latex_runs + 1
|
||||
|
||||
def process_synopsis_files(self):
|
||||
synopsis_files = glob.glob(self.doc + "*.syn")
|
||||
for path in synopsis_files:
|
||||
uniqify_module_table(path)
|
||||
|
||||
def build_ps(self):
|
||||
self.run("%s -N0 -o %s.ps %s" % (DVIPS_BINARY, self.doc, self.doc))
|
||||
|
||||
def build_html(self, builddir, max_split_depth=None):
|
||||
if max_split_depth is None:
|
||||
max_split_depth = self.options.max_split_depth
|
||||
texfile = None
|
||||
for p in os.environ["TEXINPUTS"].split(os.pathsep):
|
||||
fn = os.path.join(p, self.doc + ".tex")
|
||||
if os.path.isfile(fn):
|
||||
texfile = fn
|
||||
break
|
||||
if not texfile:
|
||||
self.warning("Could not locate %s.tex; aborting." % self.doc)
|
||||
sys.exit(1)
|
||||
# remove leading ./ (or equiv.); might avoid problems w/ dvips
|
||||
if texfile[:2] == os.curdir + os.sep:
|
||||
texfile = texfile[2:]
|
||||
# build the command line and run LaTeX2HTML:
|
||||
if not os.path.isdir(builddir):
|
||||
os.mkdir(builddir)
|
||||
else:
|
||||
for fname in glob.glob(os.path.join(builddir, "*.html")):
|
||||
os.unlink(fname)
|
||||
args = [LATEX2HTML_BINARY,
|
||||
"-init_file", self.l2h_aux_init_file,
|
||||
"-dir", builddir,
|
||||
texfile
|
||||
]
|
||||
self.run(" ".join(args)) # XXX need quoting!
|
||||
# ... postprocess
|
||||
shutil.copyfile(self.options.style_file,
|
||||
os.path.join(builddir, self.doc + ".css"))
|
||||
shutil.copyfile(os.path.join(builddir, self.doc + ".html"),
|
||||
os.path.join(builddir, "index.html"))
|
||||
if max_split_depth != 1:
|
||||
label_file = os.path.join(builddir, "labels.pl")
|
||||
fp = open(label_file)
|
||||
about_node = None
|
||||
target = " = q/about/;\n"
|
||||
x = len(target)
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
if line[-x:] == target:
|
||||
line = fp.readline()
|
||||
m = re.search(r"\|(node\d+\.[a-z]+)\|", line)
|
||||
about_node = m.group(1)
|
||||
shutil.copyfile(os.path.join(builddir, about_node),
|
||||
os.path.join(builddir, "about.html"))
|
||||
break
|
||||
if not self.options.numeric:
|
||||
pwd = os.getcwd()
|
||||
try:
|
||||
os.chdir(builddir)
|
||||
self.run("%s %s *.html" % (PERL_BINARY, NODE2LABEL_SCRIPT))
|
||||
finally:
|
||||
os.chdir(pwd)
|
||||
# These files need to be cleaned up here since builddir there
|
||||
# can be more than one, so we clean each of them.
|
||||
if self.options.discard_temps:
|
||||
for fn in ("images.tex", "images.log", "images.aux"):
|
||||
safe_unlink(os.path.join(builddir, fn))
|
||||
|
||||
def build_text(self, tempdir=None):
|
||||
if tempdir is None:
|
||||
tempdir = self.doc
|
||||
indexfile = os.path.join(tempdir, "index.html")
|
||||
self.run("%s -nolist -dump %s >%s.txt"
|
||||
% (LYNX_BINARY, indexfile, self.doc))
|
||||
|
||||
def require_temps(self, binary=None):
|
||||
if not self.latex_runs:
|
||||
self.build_aux(binary=binary)
|
||||
|
||||
def write_l2h_aux_init_file(self):
|
||||
options = self.options
|
||||
fp = open(self.l2h_aux_init_file, "w")
|
||||
d = string_to_perl(os.path.dirname(L2H_INIT_FILE))
|
||||
fp.write("package main;\n"
|
||||
"push (@INC, '%s');\n"
|
||||
"$mydir = '%s';\n"
|
||||
% (d, d))
|
||||
fp.write(open(L2H_INIT_FILE).read())
|
||||
for filename in options.l2h_init_files:
|
||||
fp.write("\n# initialization code incorporated from:\n# ")
|
||||
fp.write(filename)
|
||||
fp.write("\n")
|
||||
fp.write(open(filename).read())
|
||||
fp.write("\n"
|
||||
"# auxillary init file for latex2html\n"
|
||||
"# generated by mkhowto\n"
|
||||
"$NO_AUTO_LINK = 1;\n"
|
||||
)
|
||||
l2hoption(fp, "ABOUT_FILE", options.about_file)
|
||||
l2hoption(fp, "ICONSERVER", options.icon_server)
|
||||
l2hoption(fp, "IMAGE_TYPE", options.image_type)
|
||||
l2hoption(fp, "ADDRESS", options.address)
|
||||
l2hoption(fp, "MAX_LINK_DEPTH", options.max_link_depth)
|
||||
l2hoption(fp, "MAX_SPLIT_DEPTH", options.max_split_depth)
|
||||
l2hoption(fp, "EXTERNAL_UP_LINK", options.up_link)
|
||||
l2hoption(fp, "EXTERNAL_UP_TITLE", options.up_title)
|
||||
l2hoption(fp, "FAVORITES_ICON", options.favicon)
|
||||
l2hoption(fp, "GLOBAL_MODULE_INDEX", options.global_module_index)
|
||||
l2hoption(fp, "DVIPS_SAFE", options.dvips_safe)
|
||||
fp.write("1;\n")
|
||||
fp.close()
|
||||
|
||||
def cleanup(self):
|
||||
self.__have_temps = 0
|
||||
for pattern in ("%s.aux", "%s.log", "%s.out", "%s.toc", "%s.bkm",
|
||||
"%s.idx", "%s.ilg", "%s.ind", "%s.pla",
|
||||
"%s.bbl", "%s.blg",
|
||||
"mod%s.idx", "mod%s.ind", "mod%s.ilg",
|
||||
):
|
||||
safe_unlink(pattern % self.doc)
|
||||
map(safe_unlink, glob.glob(self.doc + "*.syn"))
|
||||
for spec in ("IMG*", "*.pl", "WARNINGS", "index.dat", "modindex.dat"):
|
||||
pattern = os.path.join(self.doc, spec)
|
||||
map(safe_unlink, glob.glob(pattern))
|
||||
if "dvi" not in self.options.formats:
|
||||
safe_unlink(self.doc + ".dvi")
|
||||
if os.path.isdir(self.doc + "-temp-html"):
|
||||
shutil.rmtree(self.doc + "-temp-html", ignore_errors=1)
|
||||
if not self.options.logging:
|
||||
os.unlink(self.log_filename)
|
||||
if not self.options.debugging:
|
||||
os.unlink(self.l2h_aux_init_file)
|
||||
|
||||
def run(self, command):
|
||||
self.message(command)
|
||||
if sys.platform.startswith("win"):
|
||||
rc = os.system(command)
|
||||
else:
|
||||
rc = os.system("(%s) </dev/null >>%s 2>&1"
|
||||
% (command, self.log_filename))
|
||||
if rc:
|
||||
self.warning(
|
||||
"Session transcript and error messages are in %s."
|
||||
% self.log_filename)
|
||||
result = 1
|
||||
if hasattr(os, "WIFEXITED"):
|
||||
if os.WIFEXITED(rc):
|
||||
result = os.WEXITSTATUS(rc)
|
||||
self.warning("Exited with status %s." % result)
|
||||
else:
|
||||
self.warning("Killed by signal %s." % os.WSTOPSIG(rc))
|
||||
else:
|
||||
self.warning("Return code: %s" % rc)
|
||||
sys.stderr.write("The relevant lines from the transcript are:\n")
|
||||
sys.stderr.write("-" * 72 + "\n")
|
||||
sys.stderr.writelines(get_run_transcript(self.log_filename))
|
||||
sys.exit(result)
|
||||
|
||||
def message(self, msg):
|
||||
msg = "+++ " + msg
|
||||
if not self.options.quiet:
|
||||
print(msg)
|
||||
self.log(msg + "\n")
|
||||
|
||||
def warning(self, msg):
|
||||
msg = "*** %s\n" % msg
|
||||
sys.stderr.write(msg)
|
||||
self.log(msg)
|
||||
|
||||
def log(self, msg):
|
||||
fp = open(self.log_filename, "a")
|
||||
fp.write(msg)
|
||||
fp.close()
|
||||
|
||||
|
||||
def get_run_transcript(filename):
|
||||
"""Return lines from the transcript file for the most recent run() call."""
|
||||
fp = open(filename)
|
||||
lines = fp.readlines()
|
||||
fp.close()
|
||||
lines.reverse()
|
||||
L = []
|
||||
for line in lines:
|
||||
L.append(line)
|
||||
if line[:4] == "+++ ":
|
||||
break
|
||||
L.reverse()
|
||||
return L
|
||||
|
||||
|
||||
def safe_unlink(path):
|
||||
"""Unlink a file without raising an error if it doesn't exist."""
|
||||
try:
|
||||
os.unlink(path)
|
||||
except os.error:
|
||||
pass
|
||||
|
||||
|
||||
def split_pathname(path):
|
||||
path = os.path.abspath(path)
|
||||
dirname, basename = os.path.split(path)
|
||||
if basename[-4:] == ".tex":
|
||||
basename = basename[:-4]
|
||||
return dirname, basename
|
||||
|
||||
|
||||
_doctype_rx = re.compile(r"\\documentclass(?:\[[^]]*\])?{([a-zA-Z]*)}")
|
||||
def get_doctype(path):
|
||||
fp = open(path)
|
||||
doctype = None
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
m = _doctype_rx.match(line)
|
||||
if m:
|
||||
doctype = m.group(1)
|
||||
break
|
||||
fp.close()
|
||||
return doctype
|
||||
|
||||
|
||||
def main():
|
||||
options = Options()
|
||||
try:
|
||||
args = options.parse(sys.argv[1:])
|
||||
except getopt.error as msg:
|
||||
error(options, msg)
|
||||
if not args:
|
||||
# attempt to locate single .tex file in current directory:
|
||||
args = glob.glob("*.tex")
|
||||
if not args:
|
||||
error(options, "No file to process.")
|
||||
if len(args) > 1:
|
||||
error(options, "Could not deduce which files should be processed.")
|
||||
#
|
||||
# parameters are processed, let's go!
|
||||
#
|
||||
for path in args:
|
||||
Job(options, path).build()
|
||||
|
||||
|
||||
def l2hoption(fp, option, value):
|
||||
if value:
|
||||
fp.write('$%s = "%s";\n' % (option, string_to_perl(str(value))))
|
||||
|
||||
|
||||
_to_perl = {}
|
||||
for c in map(chr, range(1, 256)):
|
||||
_to_perl[c] = c
|
||||
_to_perl["@"] = "\\@"
|
||||
_to_perl["$"] = "\\$"
|
||||
_to_perl['"'] = '\\"'
|
||||
|
||||
def string_to_perl(s):
|
||||
return ''.join(map(_to_perl.get, s))
|
||||
|
||||
|
||||
def check_for_bibtex(filename):
|
||||
fp = open(filename)
|
||||
pos = fp.read().find(r"\bibdata{")
|
||||
fp.close()
|
||||
return pos >= 0
|
||||
|
||||
def uniqify_module_table(filename):
|
||||
lines = open(filename).readlines()
|
||||
if len(lines) > 1:
|
||||
if lines[-1] == lines[-2]:
|
||||
del lines[-1]
|
||||
open(filename, "w").writelines(lines)
|
||||
|
||||
|
||||
def new_index(filename, label="genindex"):
|
||||
fp = open(filename, "w")
|
||||
fp.write(r"""\
|
||||
\begin{theindex}
|
||||
\label{%s}
|
||||
\end{theindex}
|
||||
""" % label)
|
||||
fp.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,65 +0,0 @@
|
|||
#! /bin/sh
|
||||
# -*- Ksh -*-
|
||||
|
||||
# Script to drive the HTML-info conversion process.
|
||||
# Pass in upto three parameters:
|
||||
# - the name of the main tex file
|
||||
# - the name of the output file in texi format (optional)
|
||||
# - the name of the output file in info format (optional)
|
||||
#
|
||||
# Written by Fred L. Drake, Jr. <fdrake@acm.org>
|
||||
|
||||
EMACS=${EMACS:-emacs}
|
||||
MAKEINFO=${MAKEINFO:-makeinfo}
|
||||
|
||||
|
||||
# Normalize file name since something called by html2texi.pl seems to
|
||||
# screw up with relative path names.
|
||||
FILENAME="$1"
|
||||
DOCDIR=`dirname "$FILENAME"`
|
||||
DOCFILE=`basename "$FILENAME"`
|
||||
DOCNAME=`basename "$FILENAME" .tex`
|
||||
if [ $# -gt 1 ]; then
|
||||
TEXINAME="$2"
|
||||
else
|
||||
TEXINAME="python-$DOCNAME.texi"
|
||||
fi
|
||||
if [ $# -gt 2 ]; then
|
||||
INFONAME="$3"
|
||||
else
|
||||
INFONAME="python-$DOCNAME.info"
|
||||
fi
|
||||
|
||||
# Now build the real directory names, and locate our support stuff:
|
||||
WORKDIR=`pwd`
|
||||
cd `dirname $0`
|
||||
TOOLSDIR=`pwd`
|
||||
cd $DOCDIR
|
||||
DOCDIR=`pwd`
|
||||
cd $WORKDIR
|
||||
|
||||
COMMONDIR="`dirname $DOCDIR`/commontex"
|
||||
|
||||
|
||||
run() {
|
||||
# show what we're doing, like make does:
|
||||
echo "$*"
|
||||
"$@" || exit $?
|
||||
}
|
||||
|
||||
|
||||
# generate the Texinfo file:
|
||||
|
||||
run $EMACS -batch -q --no-site-file -l $TOOLSDIR/py2texi.el \
|
||||
--eval "(setq py2texi-dirs '(\"$DOCDIR\" \"$COMMONDIR\" \"../texinputs\"))" \
|
||||
--eval "(setq py2texi-texi-file-name \"$TEXINAME\")" \
|
||||
--eval "(setq py2texi-info-file-name \"$INFONAME\")" \
|
||||
--eval "(py2texi \"$DOCDIR/$DOCFILE\")" \
|
||||
-f kill-emacs
|
||||
echo Done
|
||||
|
||||
|
||||
# generate the .info files:
|
||||
|
||||
run $MAKEINFO --footnote-style end --fill-column 72 \
|
||||
--paragraph-indent 0 --output=$INFONAME $TEXINAME
|
|
@ -1,158 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# -*- Python -*-
|
||||
|
||||
"""usage: %(program)s [options] file...
|
||||
|
||||
Supported options:
|
||||
|
||||
--address addr
|
||||
-a addr Set the address text to include at the end of the generated
|
||||
HTML; this should be used for contact information.
|
||||
--columns cols
|
||||
-c cols Set the number of columns each index section should be
|
||||
displayed in. The default is 1.
|
||||
--help
|
||||
-h Display this help message.
|
||||
--letters
|
||||
-l Split the output into sections by letter.
|
||||
--output file
|
||||
-o file Write output to 'file' instead of standard out.
|
||||
--iconserver is Use 'is' as the directory containing icons for the
|
||||
navigation bar. The default is 'icons'.
|
||||
--title str Set the page title to 'str'. The default is 'Global
|
||||
Module Index'.
|
||||
--uplink url Set the upward link URL. The default is './'.
|
||||
--uptitle str Set the upward link title. The default is 'Python
|
||||
Documentation Index'.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from xml.sax.saxutils import quoteattr
|
||||
|
||||
import buildindex
|
||||
import support
|
||||
|
||||
|
||||
class IndexOptions(support.Options):
|
||||
aesop_type = "links"
|
||||
|
||||
def __init__(self):
|
||||
support.Options.__init__(self)
|
||||
self.add_args("l", ["letters"])
|
||||
self.letters = 0
|
||||
|
||||
def handle_option(self, opt, val):
|
||||
if opt in ("-l", "--letters"):
|
||||
self.letters = 1
|
||||
|
||||
def usage(self):
|
||||
program = os.path.basename(sys.argv[0])
|
||||
print(__doc__ % {"program": program})
|
||||
|
||||
links = [
|
||||
('author', 'acks.html', 'Acknowledgements'),
|
||||
('help', 'about.html', 'About the Python Documentation'),
|
||||
]
|
||||
|
||||
def get_header(self):
|
||||
header = support.Options.get_header(self)
|
||||
s = ''
|
||||
for rel, href, title in self.links:
|
||||
s += '<link rel="%s" href="%s"' % (rel, href)
|
||||
if title:
|
||||
s += ' title=' + quoteattr(title)
|
||||
s += '>\n '
|
||||
return header.replace("<link ", s + "<link ", 1)
|
||||
|
||||
|
||||
class Node(buildindex.Node):
|
||||
def __init__(self, link, str, seqno, platinfo):
|
||||
self.annotation = platinfo or None
|
||||
if str[0][-5:] == "</tt>":
|
||||
str = str[:-5]
|
||||
self.modname = str
|
||||
buildindex.Node.__init__(self, link, self.modname, seqno)
|
||||
if platinfo:
|
||||
s = '<tt class="module">%s</tt> %s' \
|
||||
% (self.modname, self.annotation)
|
||||
else:
|
||||
s = '<tt class="module">%s</tt>' % str
|
||||
self.text = [s]
|
||||
|
||||
def __str__(self):
|
||||
if self.annotation:
|
||||
return '<tt class="module">%s</tt> %s' \
|
||||
% (self.modname, self.annotation)
|
||||
else:
|
||||
return '<tt class="module">%s</tt>' % self.modname
|
||||
|
||||
_rx = re.compile(
|
||||
"<dt><a href=['\"](module-.*\.html)(?:#l2h-\d+)?['\"]>"
|
||||
"<tt class=['\"]module['\"]>([a-zA-Z_][a-zA-Z0-9_.]*)</tt>\s*(<em>"
|
||||
"\(<span class=['\"]platform['\"]>.*</span>\)</em>)?</a>")
|
||||
|
||||
def main():
|
||||
options = IndexOptions()
|
||||
options.variables["title"] = "Global Module Index"
|
||||
options.parse(sys.argv[1:])
|
||||
args = options.args
|
||||
if not args:
|
||||
args = ["-"]
|
||||
#
|
||||
# Collect the input data:
|
||||
#
|
||||
nodes = []
|
||||
has_plat_flag = 0
|
||||
for ifn in args:
|
||||
if ifn == "-":
|
||||
ifp = sys.stdin
|
||||
dirname = ''
|
||||
else:
|
||||
ifp = open(ifn)
|
||||
dirname = os.path.dirname(ifn)
|
||||
while 1:
|
||||
line = ifp.readline()
|
||||
if not line:
|
||||
break
|
||||
m = _rx.match(line)
|
||||
if m:
|
||||
# This line specifies a module!
|
||||
basename, modname, platinfo = m.group(1, 2, 3)
|
||||
has_plat_flag = has_plat_flag or platinfo
|
||||
linkfile = os.path.join(dirname, basename)
|
||||
nodes.append(Node('<a href="%s">' % linkfile, modname,
|
||||
len(nodes), platinfo))
|
||||
ifp.close()
|
||||
#
|
||||
# Generate all output:
|
||||
#
|
||||
num_nodes = len(nodes)
|
||||
# Here's the HTML generation:
|
||||
parts = [options.get_header(),
|
||||
buildindex.process_nodes(nodes, options.columns, options.letters),
|
||||
options.get_footer(),
|
||||
]
|
||||
if has_plat_flag:
|
||||
parts.insert(1, PLAT_DISCUSS)
|
||||
html = ''.join(parts)
|
||||
program = os.path.basename(sys.argv[0])
|
||||
fp = options.get_output_file()
|
||||
fp.write(html.rstrip() + "\n")
|
||||
if options.outputfile == "-":
|
||||
sys.stderr.write("%s: %d index nodes\n" % (program, num_nodes))
|
||||
else:
|
||||
print()
|
||||
print("%s: %d index nodes" % (program, num_nodes))
|
||||
|
||||
|
||||
PLAT_DISCUSS = """
|
||||
<p> Some module names are followed by an annotation indicating what
|
||||
platform they are available on.</p>
|
||||
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,85 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
#
|
||||
# Simple script to create the table that lists the packages available
|
||||
# for download. This expects the downloadable files and the Makefile
|
||||
# to be in the current directory.
|
||||
#
|
||||
# The output of this script can be pasted directly into the download
|
||||
# page for the documentation.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from os.path import isfile
|
||||
|
||||
|
||||
PKG_TYPES = [
|
||||
# human name, filename prefix
|
||||
("HTML", "html"),
|
||||
("PDF (US-Letter)", "pdf-letter"),
|
||||
("PDF (A4)", "pdf-a4"),
|
||||
("PostScript (US-Letter)", "postscript-letter"),
|
||||
("PostScript (A4)", "postscript-a4"),
|
||||
("GNU info", "info"),
|
||||
("iSilo", "isilo"),
|
||||
("LaTeX", "latex"),
|
||||
]
|
||||
|
||||
getversioninfo = os.path.join(os.path.dirname(__file__), "getversioninfo")
|
||||
fp = os.popen('"%s" "%s"' % (sys.executable, getversioninfo), "r")
|
||||
release = fp.readline().strip()
|
||||
fp.close()
|
||||
|
||||
print '''\
|
||||
<table border="1" cellpadding="3" align="center">
|
||||
<thead>
|
||||
<tr bgcolor="#99ccff"><th rowspan="2">Content</th>
|
||||
<th colspan="3">Format</th></tr>
|
||||
<tr bgcolor="#99ccff"><th>ZIP</th><th>GZip</th><th>BZip2</th></tr>
|
||||
</thead>
|
||||
<tbody>'''
|
||||
|
||||
# formatted using FILE_TEMPLATE % (release, prefix, release, extension)
|
||||
FILE_TEMPLATE = '''\
|
||||
<td><a href="../../ftp/python/doc/%s/%s-%s%s"
|
||||
>%dK</a></td>'''
|
||||
|
||||
NO_FILE_TEMPLATE = '''\
|
||||
<td> </td>'''
|
||||
|
||||
def get_size(prefix, ext):
|
||||
fn = "%s-%s%s" % (prefix, release, ext)
|
||||
return int(round(os.path.getsize(fn) / 1024.0))
|
||||
|
||||
def get_file_cell(prefix, ext, have):
|
||||
if have:
|
||||
kb = get_size(prefix, ext)
|
||||
return FILE_TEMPLATE % (release, prefix, release, ext, kb)
|
||||
else:
|
||||
return NO_FILE_TEMPLATE
|
||||
|
||||
for name, prefix in PKG_TYPES:
|
||||
zip_fn = "%s-%s.zip" % (prefix, release)
|
||||
tgz_fn = "%s-%s.tgz" % (prefix, release)
|
||||
bz2_fn = "%s-%s.tar.bz2" % (prefix, release)
|
||||
|
||||
have_zip = isfile(zip_fn)
|
||||
have_tgz = isfile(tgz_fn)
|
||||
have_bz2 = isfile(bz2_fn)
|
||||
|
||||
have_some = have_zip or have_tgz or have_bz2
|
||||
|
||||
if not have_some:
|
||||
print " <!--"
|
||||
print " <tr><td>%s</td>" % name
|
||||
print get_file_cell(prefix, ".zip", have_zip)
|
||||
print get_file_cell(prefix, ".tgz", have_tgz)
|
||||
print get_file_cell(prefix, ".tar.bz2", have_bz2)
|
||||
print " </tr>"
|
||||
if not have_some:
|
||||
print " -->"
|
||||
|
||||
print '''\
|
||||
</tbody>
|
||||
</table>
|
||||
'''
|
|
@ -1,164 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# -*- Python -*-
|
||||
|
||||
"""%(program)s - script to create the latex source distribution
|
||||
|
||||
usage:
|
||||
%(program)s [-t|--tools] release [tag]
|
||||
|
||||
with -t|--tools: doesn't include the documents, only the framework
|
||||
|
||||
without [tag]: generate from the current version that's checked in
|
||||
(*NOT* what's in the current directory!)
|
||||
|
||||
with [tag]: generate from the named tag
|
||||
"""
|
||||
#* should be modified to get the Python version number automatically
|
||||
# from the Makefile or someplace.
|
||||
|
||||
import getopt
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
try:
|
||||
__file__
|
||||
except NameError:
|
||||
__file__ = sys.argv[0]
|
||||
|
||||
tools = os.path.dirname(os.path.abspath(__file__))
|
||||
Doc = os.path.dirname(tools)
|
||||
patchlevel_tex = os.path.join(Doc, "commontex", "patchlevel.tex")
|
||||
|
||||
quiet = 0
|
||||
rx = re.compile(r":ext:(?:[a-zA-Z0-9]+@)?cvs\.([a-zA-Z0-9]+).sourceforge.net:"
|
||||
r"/cvsroot/\1")
|
||||
|
||||
|
||||
def main():
|
||||
global quiet
|
||||
anonymous = False
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "Aabgtzq",
|
||||
["all", "bzip2", "gzip", "tools", "zip",
|
||||
"quiet", "anonymous"])
|
||||
except getopt.error as e:
|
||||
usage(warning=str(e))
|
||||
sys.exit(2)
|
||||
if len(args) not in (1, 2):
|
||||
usage(warning="wrong number of parameters")
|
||||
sys.exit(2)
|
||||
tools = 0
|
||||
formats = {}
|
||||
for opt, arg in opts:
|
||||
if opt in ("-t", "--tools"):
|
||||
tools = 1
|
||||
elif opt in ("-q", "--quiet"):
|
||||
quiet = quiet + 1
|
||||
elif opt in ("-b", "--bzip2"):
|
||||
formats["bzip2"] = 1
|
||||
elif opt in ("-g", "--gzip"):
|
||||
formats["gzip"] = 1
|
||||
elif opt in ("-z", "--zip"):
|
||||
formats["zip"] = 1
|
||||
elif opt in ("-a", "--all"):
|
||||
formats["bzip2"] = 1
|
||||
formats["gzip"] = 1
|
||||
formats["zip"] = 1
|
||||
elif opt in ("-A", "--anonymous"):
|
||||
anonymous = True
|
||||
if formats:
|
||||
# make order human-predictable
|
||||
formats = formats.keys()
|
||||
formats.sort()
|
||||
else:
|
||||
formats = ["gzip"]
|
||||
release = args[0]
|
||||
svntag = None
|
||||
if len(args) > 1:
|
||||
svntag = args[1]
|
||||
tempdir = tempfile.mktemp()
|
||||
os.mkdir(tempdir)
|
||||
pkgdir = os.path.join(tempdir, "Python-Docs-" + release)
|
||||
pwd = os.getcwd()
|
||||
mydir = os.path.abspath(os.path.dirname(sys.argv[0]))
|
||||
os.chdir(tempdir)
|
||||
if not quiet:
|
||||
print "--- current directory is:", tempdir
|
||||
if not svntag:
|
||||
svntag = "trunk"
|
||||
svnbase = "http://svn.python.org/projects/python"
|
||||
run("svn export %s/%s/Doc Python-Docs-%s"
|
||||
% (svnbase, svntag, release))
|
||||
|
||||
# Copy in the version informtation, if we're not just going to
|
||||
# rip it back out:
|
||||
if not tools:
|
||||
if not os.path.exists(patchlevel_tex):
|
||||
run(os.path.join(here, "getversioninfo"))
|
||||
dest = os.path.join("Python-Docs-" + release, "commontex",
|
||||
"patchlevel.tex")
|
||||
shutil.copyfile(patchlevel_tex, dest)
|
||||
|
||||
# Copy in the license file:
|
||||
LICENSE = os.path.normpath(
|
||||
os.path.join(mydir, os.pardir, os.pardir, "LICENSE"))
|
||||
shutil.copyfile(LICENSE, "LICENSE")
|
||||
if tools:
|
||||
archive = "doctools-" + release
|
||||
# we don't want the actual documents in this case:
|
||||
for d in ("api", "dist", "doc", "ext", "inst",
|
||||
"lib", "mac", "ref", "tut", "commontex"):
|
||||
shutil.rmtree(os.path.join(pkgdir, d))
|
||||
else:
|
||||
archive = "latex-" + release
|
||||
|
||||
# XXX should also remove the .cvsignore files at this point
|
||||
|
||||
os.chdir(tempdir)
|
||||
archive = os.path.join(pwd, archive)
|
||||
for format in formats:
|
||||
if format == "bzip2":
|
||||
run("tar cf - Python-Docs-%s | bzip2 -9 >%s.tar.bz2"
|
||||
% (release, archive))
|
||||
elif format == "gzip":
|
||||
run("tar cf - Python-Docs-%s | gzip -9 >%s.tgz"
|
||||
% (release, archive))
|
||||
elif format == "zip":
|
||||
if os.path.exists(archive + ".zip"):
|
||||
os.unlink(archive + ".zip")
|
||||
run("zip -q -r9 %s.zip Python-Docs-%s"
|
||||
% (archive, release))
|
||||
|
||||
# clean up the work area:
|
||||
os.chdir(pwd)
|
||||
shutil.rmtree(tempdir)
|
||||
|
||||
|
||||
def run(cmd):
|
||||
if quiet < 2:
|
||||
print "+++", cmd
|
||||
if quiet:
|
||||
cmd = "%s >/dev/null" % cmd
|
||||
rc = os.system(cmd)
|
||||
if rc:
|
||||
sys.exit(rc)
|
||||
|
||||
|
||||
def usage(warning=None):
|
||||
stdout = sys.stdout
|
||||
sys.stdout = sys.stderr
|
||||
program = os.path.basename(sys.argv[0])
|
||||
try:
|
||||
if warning:
|
||||
print "%s: %s\n" % (program, warning)
|
||||
print __doc__ % {"program": program}
|
||||
finally:
|
||||
sys.stdout = stdout
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,71 +0,0 @@
|
|||
#! /usr/bin/env perl
|
||||
|
||||
# On Cygwin, we actually have to generate a temporary file when doing
|
||||
# the inplace edit, or we'll get permission errors. Not sure who's
|
||||
# bug this is, except that it isn't ours. To deal with this, we
|
||||
# generate backups during the edit phase and remove them at the end.
|
||||
#
|
||||
use English;
|
||||
$INPLACE_EDIT = '.bak';
|
||||
|
||||
# read the labels, then reverse the mappings
|
||||
require "labels.pl";
|
||||
|
||||
%nodes = ();
|
||||
my $key;
|
||||
# sort so that we get a consistent assignment for nodes with multiple labels
|
||||
foreach $label (sort keys %external_labels) {
|
||||
#
|
||||
# If the label can't be used as a filename on non-Unix platforms,
|
||||
# skip it. Such labels may be used internally within the documentation,
|
||||
# but will never be used for filename generation.
|
||||
#
|
||||
if ($label =~ /^([-.a-zA-Z0-9]+)$/) {
|
||||
$key = $external_labels{$label};
|
||||
$key =~ s|^/||;
|
||||
$nodes{$key} = $label;
|
||||
}
|
||||
}
|
||||
|
||||
# This adds the "internal" labels added for indexing. These labels will not
|
||||
# be used for file names.
|
||||
require "intlabels.pl";
|
||||
foreach $label (keys %internal_labels) {
|
||||
$key = $internal_labels{$label};
|
||||
$key =~ s|^/||;
|
||||
if (defined($nodes{$key})) {
|
||||
$nodes{$label} = $nodes{$key};
|
||||
}
|
||||
}
|
||||
|
||||
# collect labels that have been used
|
||||
%newnames = ();
|
||||
|
||||
while (<>) {
|
||||
# don't want to do one s/// per line per node
|
||||
# so look for lines with hrefs, then do s/// on nodes present
|
||||
if (/(HREF|href)=[\"\']node\d+\.html[\#\"\']/) {
|
||||
@parts = split(/(HREF|href)\=[\"\']/);
|
||||
shift @parts;
|
||||
for $node (@parts) {
|
||||
$node =~ s/[\#\"\'].*$//g;
|
||||
chomp($node);
|
||||
if (defined($nodes{$node})) {
|
||||
$label = $nodes{$node};
|
||||
if (s/(HREF|href)=([\"\'])$node([\#\"\'])/href=$2$label.html$3/g) {
|
||||
s/(HREF|href)=([\"\'])$label.html/href=$2$label.html/g;
|
||||
$newnames{$node} = "$label.html";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
print;
|
||||
}
|
||||
|
||||
foreach $oldname (keys %newnames) {
|
||||
rename($oldname, $newnames{$oldname});
|
||||
}
|
||||
|
||||
foreach $filename (glob('*.bak')) {
|
||||
unlink($filename);
|
||||
}
|
|
@ -1,519 +0,0 @@
|
|||
"""
|
||||
Makes the necesary files to convert from plain html of
|
||||
Python 1.5 and 1.5.x Documentation to
|
||||
Microsoft HTML Help format version 1.1
|
||||
Doesn't change the html's docs.
|
||||
|
||||
by hernan.foffani@iname.com
|
||||
no copyright and no responsabilities.
|
||||
|
||||
modified by Dale Nagata for Python 1.5.2
|
||||
|
||||
Renamed from make_chm.py to prechm.py, and checked into the Python
|
||||
project, 19-Apr-2002 by Tim Peters. Assorted modifications by Tim
|
||||
and Fred Drake. Obtained from Robin Dunn's .chm packaging of the
|
||||
Python 2.2 docs, at <http://alldunn.com/python/>.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from formatter import NullWriter, AbstractFormatter
|
||||
from htmllib import HTMLParser
|
||||
import getopt
|
||||
import cgi
|
||||
|
||||
usage_mode = '''
|
||||
Usage: prechm.py [-c] [-k] [-p] [-v 1.5[.x]] filename
|
||||
-c: does not build filename.hhc (Table of Contents)
|
||||
-k: does not build filename.hhk (Index)
|
||||
-p: does not build filename.hhp (Project File)
|
||||
-v 1.5[.x]: makes help for the python 1.5[.x] docs
|
||||
(default is python 1.5.2 docs)
|
||||
'''
|
||||
|
||||
# Project file (*.hhp) template. 'arch' is the file basename (like
|
||||
# the pythlp in pythlp.hhp); 'version' is the doc version number (like
|
||||
# the 2.2 in Python 2.2).
|
||||
# The magical numbers in the long line under [WINDOWS] set most of the
|
||||
# user-visible features (visible buttons, tabs, etc).
|
||||
# About 0x10384e: This defines the buttons in the help viewer. The
|
||||
# following defns are taken from htmlhelp.h. Not all possibilities
|
||||
# actually work, and not all those that work are available from the Help
|
||||
# Workshop GUI. In particular, the Zoom/Font button works and is not
|
||||
# available from the GUI. The ones we're using are marked with 'x':
|
||||
#
|
||||
# 0x000002 Hide/Show x
|
||||
# 0x000004 Back x
|
||||
# 0x000008 Forward x
|
||||
# 0x000010 Stop
|
||||
# 0x000020 Refresh
|
||||
# 0x000040 Home x
|
||||
# 0x000080 Forward
|
||||
# 0x000100 Back
|
||||
# 0x000200 Notes
|
||||
# 0x000400 Contents
|
||||
# 0x000800 Locate x
|
||||
# 0x001000 Options x
|
||||
# 0x002000 Print x
|
||||
# 0x004000 Index
|
||||
# 0x008000 Search
|
||||
# 0x010000 History
|
||||
# 0x020000 Favorites
|
||||
# 0x040000 Jump 1
|
||||
# 0x080000 Jump 2
|
||||
# 0x100000 Zoom/Font x
|
||||
# 0x200000 TOC Next
|
||||
# 0x400000 TOC Prev
|
||||
|
||||
project_template = '''
|
||||
[OPTIONS]
|
||||
Compiled file=%(arch)s.chm
|
||||
Contents file=%(arch)s.hhc
|
||||
Default Window=%(arch)s
|
||||
Default topic=index.html
|
||||
Display compile progress=No
|
||||
Full text search stop list file=%(arch)s.stp
|
||||
Full-text search=Yes
|
||||
Index file=%(arch)s.hhk
|
||||
Language=0x409
|
||||
Title=Python %(version)s Documentation
|
||||
|
||||
[WINDOWS]
|
||||
%(arch)s="Python %(version)s Documentation","%(arch)s.hhc","%(arch)s.hhk",\
|
||||
"index.html","index.html",,,,,0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0
|
||||
|
||||
[FILES]
|
||||
'''
|
||||
|
||||
contents_header = '''\
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1">
|
||||
<!-- Sitemap 1.0 -->
|
||||
</HEAD><BODY>
|
||||
<OBJECT type="text/site properties">
|
||||
<param name="Window Styles" value="0x801227">
|
||||
<param name="ImageType" value="Folder">
|
||||
</OBJECT>
|
||||
<UL>
|
||||
'''
|
||||
|
||||
contents_footer = '''\
|
||||
</UL></BODY></HTML>
|
||||
'''
|
||||
|
||||
object_sitemap = '''\
|
||||
<OBJECT type="text/sitemap">
|
||||
<param name="Name" value="%s">
|
||||
<param name="Local" value="%s">
|
||||
</OBJECT>
|
||||
'''
|
||||
|
||||
# List of words the full text search facility shouldn't index. This
|
||||
# becomes file ARCH.stp. Note that this list must be pretty small!
|
||||
# Different versions of the MS docs claim the file has a maximum size of
|
||||
# 256 or 512 bytes (including \r\n at the end of each line).
|
||||
# Note that "and", "or", "not" and "near" are operators in the search
|
||||
# language, so no point indexing them even if we wanted to.
|
||||
stop_list = '''
|
||||
a and are as at
|
||||
be but by
|
||||
for
|
||||
if in into is it
|
||||
near no not
|
||||
of on or
|
||||
such
|
||||
that the their then there these they this to
|
||||
was will with
|
||||
'''
|
||||
|
||||
# s is a string or None. If None or empty, return None. Else tack '.html'
|
||||
# on to the end, unless it's already there.
|
||||
def addhtml(s):
|
||||
if s:
|
||||
if not s.endswith('.html'):
|
||||
s += '.html'
|
||||
return s
|
||||
|
||||
# Convenience class to hold info about "a book" in HTMLHelp terms == a doc
|
||||
# directory in Python terms.
|
||||
class Book:
|
||||
def __init__(self, directory, title, firstpage,
|
||||
contentpage=None, indexpage=None):
|
||||
self.directory = directory
|
||||
self.title = title
|
||||
self.firstpage = addhtml(firstpage)
|
||||
self.contentpage = addhtml(contentpage)
|
||||
self.indexpage = addhtml(indexpage)
|
||||
|
||||
# Library Doc list of books:
|
||||
# each 'book' : (Dir, Title, First page, Content page, Index page)
|
||||
supported_libraries = {
|
||||
'2.5':
|
||||
[
|
||||
Book('.', 'Main page', 'index'),
|
||||
Book('.', 'Global Module Index', 'modindex'),
|
||||
Book('whatsnew', "What's New", 'index', 'contents'),
|
||||
Book('tut','Tutorial','tut','node2'),
|
||||
Book('lib','Library Reference','lib','contents','genindex'),
|
||||
Book('ref','Language Reference','ref','contents','genindex'),
|
||||
Book('mac','Macintosh Reference','mac','contents','genindex'),
|
||||
Book('ext','Extending and Embedding','ext','contents'),
|
||||
Book('api','Python/C API','api','contents','genindex'),
|
||||
Book('doc','Documenting Python','doc','contents'),
|
||||
Book('inst','Installing Python Modules', 'inst', 'index'),
|
||||
Book('dist','Distributing Python Modules', 'dist', 'index', 'genindex'),
|
||||
],
|
||||
|
||||
'2.4':
|
||||
[
|
||||
Book('.', 'Main page', 'index'),
|
||||
Book('.', 'Global Module Index', 'modindex'),
|
||||
Book('whatsnew', "What's New", 'index', 'contents'),
|
||||
Book('tut','Tutorial','tut','node2'),
|
||||
Book('lib','Library Reference','lib','contents','genindex'),
|
||||
Book('ref','Language Reference','ref','contents','genindex'),
|
||||
Book('mac','Macintosh Reference','mac','contents','genindex'),
|
||||
Book('ext','Extending and Embedding','ext','contents'),
|
||||
Book('api','Python/C API','api','contents','genindex'),
|
||||
Book('doc','Documenting Python','doc','contents'),
|
||||
Book('inst','Installing Python Modules', 'inst', 'index'),
|
||||
Book('dist','Distributing Python Modules', 'dist', 'index', 'genindex'),
|
||||
],
|
||||
|
||||
'2.3':
|
||||
[
|
||||
Book('.', 'Main page', 'index'),
|
||||
Book('.', 'Global Module Index', 'modindex'),
|
||||
Book('whatsnew', "What's New", 'index', 'contents'),
|
||||
Book('tut','Tutorial','tut','node2'),
|
||||
Book('lib','Library Reference','lib','contents','genindex'),
|
||||
Book('ref','Language Reference','ref','contents','genindex'),
|
||||
Book('mac','Macintosh Reference','mac','contents','genindex'),
|
||||
Book('ext','Extending and Embedding','ext','contents'),
|
||||
Book('api','Python/C API','api','contents','genindex'),
|
||||
Book('doc','Documenting Python','doc','contents'),
|
||||
Book('inst','Installing Python Modules', 'inst', 'index'),
|
||||
Book('dist','Distributing Python Modules', 'dist', 'index'),
|
||||
],
|
||||
|
||||
'2.2':
|
||||
[
|
||||
Book('.', 'Main page', 'index'),
|
||||
Book('.', 'Global Module Index', 'modindex'),
|
||||
Book('whatsnew', "What's New", 'index', 'contents'),
|
||||
Book('tut','Tutorial','tut','node2'),
|
||||
Book('lib','Library Reference','lib','contents','genindex'),
|
||||
Book('ref','Language Reference','ref','contents','genindex'),
|
||||
Book('mac','Macintosh Reference','mac','contents','genindex'),
|
||||
Book('ext','Extending and Embedding','ext','contents'),
|
||||
Book('api','Python/C API','api','contents','genindex'),
|
||||
Book('doc','Documenting Python','doc','contents'),
|
||||
Book('inst','Installing Python Modules', 'inst', 'index'),
|
||||
Book('dist','Distributing Python Modules', 'dist', 'index'),
|
||||
],
|
||||
|
||||
'2.1.1':
|
||||
[
|
||||
Book('.', 'Main page', 'index'),
|
||||
Book('.', 'Global Module Index', 'modindex'),
|
||||
Book('tut','Tutorial','tut','node2'),
|
||||
Book('lib','Library Reference','lib','contents','genindex'),
|
||||
Book('ref','Language Reference','ref','contents','genindex'),
|
||||
Book('mac','Macintosh Reference','mac','contents','genindex'),
|
||||
Book('ext','Extending and Embedding','ext','contents'),
|
||||
Book('api','Python/C API','api','contents','genindex'),
|
||||
Book('doc','Documenting Python','doc','contents'),
|
||||
Book('inst','Installing Python Modules', 'inst', 'index'),
|
||||
Book('dist','Distributing Python Modules', 'dist', 'index'),
|
||||
],
|
||||
|
||||
'2.0.0':
|
||||
[
|
||||
Book('.', 'Global Module Index', 'modindex'),
|
||||
Book('tut','Tutorial','tut','node2'),
|
||||
Book('lib','Library Reference','lib','contents','genindex'),
|
||||
Book('ref','Language Reference','ref','contents','genindex'),
|
||||
Book('mac','Macintosh Reference','mac','contents','genindex'),
|
||||
Book('ext','Extending and Embedding','ext','contents'),
|
||||
Book('api','Python/C API','api','contents','genindex'),
|
||||
Book('doc','Documenting Python','doc','contents'),
|
||||
Book('inst','Installing Python Modules', 'inst', 'contents'),
|
||||
Book('dist','Distributing Python Modules', 'dist', 'contents'),
|
||||
],
|
||||
|
||||
# <dnagata@creo.com> Apr 17/99: library for 1.5.2 version:
|
||||
# <hernan.foffani@iname.com> May 01/99: library for 1.5.2 (04/30/99):
|
||||
'1.5.2':
|
||||
[
|
||||
Book('tut','Tutorial','tut','node2'),
|
||||
Book('lib','Library Reference','lib','contents','genindex'),
|
||||
Book('ref','Language Reference','ref','contents','genindex'),
|
||||
Book('mac','Macintosh Reference','mac','contents','genindex'),
|
||||
Book('ext','Extending and Embedding','ext','contents'),
|
||||
Book('api','Python/C API','api','contents','genindex'),
|
||||
Book('doc','Documenting Python','doc','contents')
|
||||
],
|
||||
|
||||
# library for 1.5.1 version:
|
||||
'1.5.1':
|
||||
[
|
||||
Book('tut','Tutorial','tut','contents'),
|
||||
Book('lib','Library Reference','lib','contents','genindex'),
|
||||
Book('ref','Language Reference','ref-1','ref-2','ref-11'),
|
||||
Book('ext','Extending and Embedding','ext','contents'),
|
||||
Book('api','Python/C API','api','contents','genindex')
|
||||
],
|
||||
|
||||
# library for 1.5 version:
|
||||
'1.5':
|
||||
[
|
||||
Book('tut','Tutorial','tut','node1'),
|
||||
Book('lib','Library Reference','lib','node1','node268'),
|
||||
Book('ref','Language Reference','ref-1','ref-2','ref-11'),
|
||||
Book('ext','Extending and Embedding','ext','node1'),
|
||||
Book('api','Python/C API','api','node1','node48')
|
||||
]
|
||||
}
|
||||
|
||||
# AlmostNullWriter doesn't print anything; it just arranges to save the
|
||||
# text sent to send_flowing_data(). This is used to capture the text
|
||||
# between an anchor begin/end pair, e.g. for TOC entries.
|
||||
|
||||
class AlmostNullWriter(NullWriter):
|
||||
|
||||
def __init__(self):
|
||||
NullWriter.__init__(self)
|
||||
self.saved_clear()
|
||||
|
||||
def send_flowing_data(self, data):
|
||||
stripped = data.strip()
|
||||
if stripped: # don't bother to save runs of whitespace
|
||||
self.saved.append(stripped)
|
||||
|
||||
# Forget all saved text.
|
||||
def saved_clear(self):
|
||||
self.saved = []
|
||||
|
||||
# Return all saved text as a string.
|
||||
def saved_get(self):
|
||||
return ' '.join(self.saved)
|
||||
|
||||
class HelpHtmlParser(HTMLParser):
|
||||
|
||||
def __init__(self, formatter, path, output):
|
||||
HTMLParser.__init__(self, formatter)
|
||||
self.path = path # relative path
|
||||
self.ft = output # output file
|
||||
self.indent = 0 # number of tabs for pretty printing of files
|
||||
self.proc = False # True when actively processing, else False
|
||||
# (headers, footers, etc)
|
||||
# XXX This shouldn't need to be a stack -- anchors shouldn't nest.
|
||||
# XXX See SF bug <http://www.python.org/sf/546579>.
|
||||
self.hrefstack = [] # stack of hrefs from anchor begins
|
||||
|
||||
def begin_group(self):
|
||||
self.indent += 1
|
||||
self.proc = True
|
||||
|
||||
def finish_group(self):
|
||||
self.indent -= 1
|
||||
# stop processing when back to top level
|
||||
self.proc = self.indent > 0
|
||||
|
||||
def anchor_bgn(self, href, name, type):
|
||||
if self.proc:
|
||||
# XXX See SF bug <http://www.python.org/sf/546579>.
|
||||
# XXX index.html for the 2.2.1 language reference manual contains
|
||||
# XXX nested <a></a> tags in the entry for the section on blank
|
||||
# XXX lines. We want to ignore the nested part completely.
|
||||
if len(self.hrefstack) == 0:
|
||||
self.saved_clear()
|
||||
self.hrefstack.append(href)
|
||||
|
||||
def anchor_end(self):
|
||||
if self.proc:
|
||||
# XXX See XXX above.
|
||||
if self.hrefstack:
|
||||
title = cgi.escape(self.saved_get(), True)
|
||||
path = self.path + '/' + self.hrefstack.pop()
|
||||
self.tab(object_sitemap % (title, path))
|
||||
|
||||
def start_dl(self, atr_val):
|
||||
self.begin_group()
|
||||
|
||||
def end_dl(self):
|
||||
self.finish_group()
|
||||
|
||||
def do_dt(self, atr_val):
|
||||
# no trailing newline on purpose!
|
||||
self.tab("<LI>")
|
||||
|
||||
# Write text to output file.
|
||||
def write(self, text):
|
||||
self.ft.write(text)
|
||||
|
||||
# Write text to output file after indenting by self.indent tabs.
|
||||
def tab(self, text=''):
|
||||
self.write('\t' * self.indent)
|
||||
if text:
|
||||
self.write(text)
|
||||
|
||||
# Forget all saved text.
|
||||
def saved_clear(self):
|
||||
self.formatter.writer.saved_clear()
|
||||
|
||||
# Return all saved text as a string.
|
||||
def saved_get(self):
|
||||
return self.formatter.writer.saved_get()
|
||||
|
||||
class IdxHlpHtmlParser(HelpHtmlParser):
|
||||
# nothing special here, seems enough with parent class
|
||||
pass
|
||||
|
||||
class TocHlpHtmlParser(HelpHtmlParser):
|
||||
|
||||
def start_dl(self, atr_val):
|
||||
self.begin_group()
|
||||
self.tab('<UL>\n')
|
||||
|
||||
def end_dl(self):
|
||||
self.finish_group()
|
||||
self.tab('</UL>\n')
|
||||
|
||||
def start_ul(self, atr_val):
|
||||
self.begin_group()
|
||||
self.tab('<UL>\n')
|
||||
|
||||
def end_ul(self):
|
||||
self.finish_group()
|
||||
self.tab('</UL>\n')
|
||||
|
||||
def do_li(self, atr_val):
|
||||
# no trailing newline on purpose!
|
||||
self.tab("<LI>")
|
||||
|
||||
def index(path, indexpage, output):
|
||||
parser = IdxHlpHtmlParser(AbstractFormatter(AlmostNullWriter()),
|
||||
path, output)
|
||||
f = open(path + '/' + indexpage)
|
||||
parser.feed(f.read())
|
||||
parser.close()
|
||||
f.close()
|
||||
|
||||
def content(path, contentpage, output):
|
||||
parser = TocHlpHtmlParser(AbstractFormatter(AlmostNullWriter()),
|
||||
path, output)
|
||||
f = open(path + '/' + contentpage)
|
||||
parser.feed(f.read())
|
||||
parser.close()
|
||||
f.close()
|
||||
|
||||
def do_index(library, output):
|
||||
output.write('<UL>\n')
|
||||
for book in library:
|
||||
print('\t', book.title, '-', book.indexpage)
|
||||
if book.indexpage:
|
||||
index(book.directory, book.indexpage, output)
|
||||
output.write('</UL>\n')
|
||||
|
||||
def do_content(library, version, output):
|
||||
output.write(contents_header)
|
||||
for book in library:
|
||||
print('\t', book.title, '-', book.firstpage)
|
||||
path = book.directory + "/" + book.firstpage
|
||||
output.write('<LI>')
|
||||
output.write(object_sitemap % (book.title, path))
|
||||
if book.contentpage:
|
||||
content(book.directory, book.contentpage, output)
|
||||
output.write(contents_footer)
|
||||
|
||||
# Fill in the [FILES] section of the project (.hhp) file.
|
||||
# 'library' is the list of directory description tuples from
|
||||
# supported_libraries for the version of the docs getting generated.
|
||||
def do_project(library, output, arch, version):
|
||||
output.write(project_template % locals())
|
||||
pathseen = {}
|
||||
for book in library:
|
||||
directory = book.directory
|
||||
path = directory + '\\%s\n'
|
||||
for page in os.listdir(directory):
|
||||
if page.endswith('.html') or page.endswith('.css'):
|
||||
fullpath = path % page
|
||||
if fullpath not in pathseen:
|
||||
output.write(fullpath)
|
||||
pathseen[fullpath] = True
|
||||
|
||||
def openfile(file):
|
||||
try:
|
||||
p = open(file, "w")
|
||||
except IOError as msg:
|
||||
print(file, ":", msg)
|
||||
sys.exit(1)
|
||||
return p
|
||||
|
||||
def usage():
|
||||
print(usage_mode)
|
||||
sys.exit(0)
|
||||
|
||||
def do_it(args = None):
|
||||
if not args:
|
||||
args = sys.argv[1:]
|
||||
|
||||
if not args:
|
||||
usage()
|
||||
|
||||
try:
|
||||
optlist, args = getopt.getopt(args, 'ckpv:')
|
||||
except getopt.error as msg:
|
||||
print(msg)
|
||||
usage()
|
||||
|
||||
if not args or len(args) > 1:
|
||||
usage()
|
||||
arch = args[0]
|
||||
|
||||
version = None
|
||||
for opt in optlist:
|
||||
if opt[0] == '-v':
|
||||
version = opt[1]
|
||||
break
|
||||
if not version:
|
||||
usage()
|
||||
|
||||
library = supported_libraries[version]
|
||||
|
||||
if not (('-p','') in optlist):
|
||||
fname = arch + '.stp'
|
||||
f = openfile(fname)
|
||||
print("Building stoplist", fname, "...")
|
||||
words = stop_list.split()
|
||||
words.sort()
|
||||
for word in words:
|
||||
print(word, file=f)
|
||||
f.close()
|
||||
|
||||
f = openfile(arch + '.hhp')
|
||||
print("Building Project...")
|
||||
do_project(library, f, arch, version)
|
||||
if version == '2.0.0':
|
||||
for image in os.listdir('icons'):
|
||||
f.write('icons'+ '\\' + image + '\n')
|
||||
|
||||
f.close()
|
||||
|
||||
if not (('-c','') in optlist):
|
||||
f = openfile(arch + '.hhc')
|
||||
print("Building Table of Content...")
|
||||
do_content(library, version, f)
|
||||
f.close()
|
||||
|
||||
if not (('-k','') in optlist):
|
||||
f = openfile(arch + '.hhk')
|
||||
print("Building Index...")
|
||||
do_index(library, f)
|
||||
f.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
do_it()
|
|
@ -1,138 +0,0 @@
|
|||
#! /bin/sh
|
||||
|
||||
# Script to push docs from my development area to SourceForge, where the
|
||||
# update-docs.sh script unpacks them into their final destination.
|
||||
|
||||
TARGETHOST=www.python.org
|
||||
TARGETDIR=/usr/home/fdrake/tmp
|
||||
|
||||
PKGTYPE="bzip" # must be one of: bzip, tar, zip ("tar" implies gzip)
|
||||
|
||||
TARGET="$TARGETHOST:$TARGETDIR"
|
||||
|
||||
ADDRESSES='python-dev@python.org doc-sig@python.org python-list@python.org'
|
||||
|
||||
TOOLDIR="`dirname $0`"
|
||||
VERSION=`$TOOLDIR/getversioninfo`
|
||||
|
||||
# Set $EXTRA to something non-empty if this is a non-trunk version:
|
||||
EXTRA=`echo "$VERSION" | sed 's/^[0-9][0-9]*\.[0-9][0-9]*//'`
|
||||
|
||||
if echo "$EXTRA" | grep -q '[.]' ; then
|
||||
DOCLABEL="maintenance"
|
||||
DOCTYPE="maint"
|
||||
else
|
||||
DOCLABEL="development"
|
||||
DOCTYPE="devel"
|
||||
fi
|
||||
|
||||
DOCTYPE_SPECIFIED=false
|
||||
EXPLANATION=''
|
||||
ANNOUNCE=true
|
||||
|
||||
getopt -T >/dev/null
|
||||
if [ $? -eq 4 ] ; then
|
||||
# We have a sufficiently useful getopt(1) implementation.
|
||||
eval "set -- `getopt -ssh m:p:qt:F: \"$@\"`"
|
||||
else
|
||||
# This version of getopt doesn't support quoting of long options
|
||||
# with spaces, so let's not rely on it at all.
|
||||
:
|
||||
fi
|
||||
|
||||
while [ "$#" -gt 0 ] ; do
|
||||
case "$1" in
|
||||
-m)
|
||||
EXPLANATION="$2"
|
||||
shift 2
|
||||
;;
|
||||
-p)
|
||||
PKGTYPE="$2"
|
||||
shift 1
|
||||
;;
|
||||
-q)
|
||||
ANNOUNCE=false
|
||||
shift 1
|
||||
;;
|
||||
-t)
|
||||
DOCTYPE="$2"
|
||||
DOCTYPE_SPECIFIED=true
|
||||
shift 2
|
||||
;;
|
||||
-F)
|
||||
EXPLANATION="`cat $2`"
|
||||
shift 2
|
||||
;;
|
||||
--)
|
||||
shift 1
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option: $1" >&2
|
||||
exit 2
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ "$1" ] ; then
|
||||
if [ "$EXPLANATION" ] ; then
|
||||
echo "Explanation may only be given once!" >&2
|
||||
exit 2
|
||||
fi
|
||||
EXPLANATION="$1"
|
||||
shift
|
||||
fi
|
||||
|
||||
START="`pwd`"
|
||||
MYDIR="`dirname $0`"
|
||||
cd "$MYDIR"
|
||||
MYDIR="`pwd`"
|
||||
|
||||
if [ "$PKGTYPE" = bzip ] ; then
|
||||
PKGEXT=tar.bz2
|
||||
elif [ "$PKGTYPE" = tar ] ; then
|
||||
PKGEXT=tgz
|
||||
elif [ "$PKGTYPE" = zip ] ; then
|
||||
PKGEXT=zip
|
||||
else
|
||||
echo 1>&2 "unsupported package type: $PKGTYPE"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# switch to .../Doc/
|
||||
cd ..
|
||||
|
||||
# If $DOCTYPE was not specified explicitly, look for .doctype in
|
||||
# .../Doc/ and use the content of that file if present.
|
||||
if $DOCTYPE_SPECIFIED ; then
|
||||
:
|
||||
elif [ -f .doctype ] ; then
|
||||
DOCTYPE="`cat .doctype`"
|
||||
fi
|
||||
|
||||
make --no-print-directory ${PKGTYPE}html || exit $?
|
||||
PACKAGE="html-$VERSION.$PKGEXT"
|
||||
scp "$PACKAGE" tools/update-docs.sh $TARGET/ || exit $?
|
||||
ssh "$TARGETHOST" tmp/update-docs.sh $DOCTYPE $PACKAGE '&&' rm tmp/update-docs.sh || exit $?
|
||||
|
||||
if $ANNOUNCE ; then
|
||||
sendmail $ADDRESSES <<EOF
|
||||
To: $ADDRESSES
|
||||
From: "Fred L. Drake" <fdrake@acm.org>
|
||||
Subject: [$DOCLABEL doc updates]
|
||||
X-No-Archive: yes
|
||||
|
||||
The $DOCLABEL version of the documentation has been updated:
|
||||
|
||||
http://$TARGETHOST/dev/doc/$DOCTYPE/
|
||||
|
||||
$EXPLANATION
|
||||
|
||||
A downloadable package containing the HTML is also available:
|
||||
|
||||
http://$TARGETHOST/dev/doc/python-docs-$DOCTYPE.$PKGEXT
|
||||
EOF
|
||||
exit $?
|
||||
fi
|
|
@ -1,970 +0,0 @@
|
|||
;;; py2texi.el -- Conversion of Python LaTeX documentation to Texinfo
|
||||
|
||||
;; Copyright (C) 2006 Jeroen Dekkers <jeroen@dekkers.cx>
|
||||
;; 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-texi-file-name nil
|
||||
"If non-nil, that string is used as the name of the Texinfo file.
|
||||
Otherwise a generated Texinfo file name is used.")
|
||||
|
||||
(defvar py2texi-info-file-name nil
|
||||
"If non-nil, that string is used as the name of the Info file.
|
||||
Otherwise a generated Info file name is used.")
|
||||
|
||||
(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\n")
|
||||
("cmemberdesc" 3
|
||||
"\n@table @code\n@item \\2 \\3\n"
|
||||
"@end table\n")
|
||||
("classdesc" 2
|
||||
(progn (setq obindex t)
|
||||
"\n@table @code\n@item \\1(\\2)\n@obindex \\1\n")
|
||||
"@end table\n")
|
||||
("classdesc*" 1
|
||||
(progn (setq obindex t)
|
||||
"\n@table @code\n@item \\1\n@obindex \\1\n")
|
||||
"@end table\n")
|
||||
("comment" 0 "\n@ignore\n" "\n@end ignore\n")
|
||||
("csimplemacrodesc" 1
|
||||
(progn (setq cindex t)
|
||||
"\n@table @code\n@item \\1\n@cindex \\1\n")
|
||||
"@end table\n")
|
||||
("ctypedesc" 1
|
||||
(progn (setq cindex t)
|
||||
"\n@table @code\n@item \\1\n@cindex \\1\n")
|
||||
"@end table\n")
|
||||
("cvardesc" 2
|
||||
(progn (setq findex t)
|
||||
"\n@table @code\n@item \\1 \\2\n@findex \\2\n")
|
||||
"@end table\n")
|
||||
("datadesc" 1
|
||||
(progn (setq findex t)
|
||||
"\n@table @code\n@item \\1\n@findex \\1\n")
|
||||
"@end table\n")
|
||||
("datadescni" 1 "\n@table @code\n@item \\1\n" "@end table\n")
|
||||
("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")
|
||||
("envdesc" 2 (concat "\n@table @code"
|
||||
"\n@item @backslash{}begin@{\\1@}\\2")
|
||||
"@end table\n")
|
||||
("excdesc" 1
|
||||
(progn (setq obindex t)
|
||||
"\n@table @code\n@item \\1\n@obindex \\1\n")
|
||||
"@end table\n")
|
||||
("excclassdesc" 2
|
||||
(progn (setq obindex t)
|
||||
"\n@table @code\n@item \\1(\\2)\n@obindex \\1\n")
|
||||
"@end table\n")
|
||||
("flushleft" 0 "" "")
|
||||
("fulllineitems" 0 "\n@table @code\n" "@end table\n")
|
||||
("funcdesc" 2
|
||||
(progn (setq findex t)
|
||||
"\n@table @code\n@item \\1(\\2)\n@findex \\1\n")
|
||||
"@end table\n")
|
||||
("funcdescni" 2 "\n@table @code\n@item \\1(\\2)\n" "@end table\n")
|
||||
("itemize" 0 "@itemize @bullet" "@end itemize\n")
|
||||
("list" 2 "\n@table @code\n" "@end table\n")
|
||||
("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")
|
||||
("macrodesc" 2 (concat "\n@table @code"
|
||||
"\n@item \\1@{\\2@}")
|
||||
"@end table\n")
|
||||
("memberdesc" 1
|
||||
(progn (setq findex t)
|
||||
"\n@table @code\n@item \\1\n@findex \\1\n")
|
||||
"@end table\n")
|
||||
("memberdescni" 1 "\n@table @code\n@item \\1\n" "@end table\n")
|
||||
("methoddesc" 2
|
||||
(progn (setq findex t)
|
||||
"\n@table @code\n@item \\1(\\2)\n@findex \\1\n")
|
||||
"@end table\n")
|
||||
("methoddescni" 2 "\n@table @code\n@item \\1(\\2)\n" "@end table\n")
|
||||
("notice" 0 "@emph{Notice:} " "")
|
||||
("opcodedesc" 2
|
||||
(progn (setq findex t)
|
||||
"\n@table @code\n@item \\1 \\2\n@findex \\1\n")
|
||||
"@end table\n")
|
||||
("productionlist" 0 "\n@table @code\n" "@end table\n")
|
||||
("quotation" 0 "@quotation" "@end quotation")
|
||||
("quote" 0 "@quotation" "@end quotation")
|
||||
("seealso" 0 "See also:\n@table @emph\n" "@end table\n")
|
||||
("seealso*" 0 "@table @emph\n" "@end table\n")
|
||||
("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")
|
||||
("alltt" 0 "@example" "@end example")
|
||||
)
|
||||
"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
|
||||
'(("AA" 0 "@AA{}")
|
||||
("aa" 0 "@aa{}")
|
||||
("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}")
|
||||
("backslash" 0 "@backslash{}")
|
||||
("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")
|
||||
("cfuncline" 3 "@itemx \\1 \\2(\\3)\n@findex \\2")
|
||||
("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}")
|
||||
("cmemberline" 3 "@itemx \\2 \\3\n")
|
||||
("code" 1 "@code{\\1}")
|
||||
("command" 1 "@command{\\1}")
|
||||
("constant" 1 "@code{\\1}")
|
||||
("copyright" 1 "@copyright{}")
|
||||
("Cpp" 0 "C++")
|
||||
("csimplemacro" 1 "@code{\\1}")
|
||||
("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}\n\n")
|
||||
("dfn" 1 "@dfn{\\1}")
|
||||
("documentclass" 1 py2texi-magic)
|
||||
("e" 0 "@backslash{}")
|
||||
("else" 0 (concat "@end ifinfo\n@" (setq last-if "iftex")))
|
||||
("env" 1 "@code{\\1}")
|
||||
("EOF" 0 "@code{EOF}")
|
||||
("email" 1 "@email{\\1}")
|
||||
("em" 1 "@emph{\\1}")
|
||||
("emph" 1 "@emph{\\1}")
|
||||
("envvar" 1 "@env{\\1}")
|
||||
("exception" 1 "@code{\\1}")
|
||||
("exindex" 1 (progn (setq obindex t) "@obindex{\\1}"))
|
||||
("fi" 0 (if (equal last-if "ifx") "" (concat "@end " last-if)))
|
||||
("file" 1 "@file{\\1}")
|
||||
("filenq" 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}")
|
||||
("guilabel" 1 "@strong{\\1}")
|
||||
("hline" 0 "")
|
||||
("ifx" 0 (progn (setq last-if "ifx") ""))
|
||||
("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")
|
||||
("leq" 0 "<=")
|
||||
("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")
|
||||
("locallinewidth" 0 "")
|
||||
("localmoduletable" 0 "")
|
||||
("longprogramopt" 1 "@option{--\\1}")
|
||||
("macro" 1 "@code{@backslash{}\\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 "")
|
||||
("modulesynopsis" 1 "\\1")
|
||||
("moreargs" 0 "@dots{}")
|
||||
("n" 0 "@backslash{}n")
|
||||
("newcommand" 2 "")
|
||||
("newlength" 1 "")
|
||||
("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]")
|
||||
("paragraph" 1 "@subsubheading \\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")
|
||||
("productioncont" 1 "@item @w{} \\1")
|
||||
("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 "")
|
||||
("seelink" 3 "\n@table @url\n@item @strong{\\1}\n(\\2)\n\\3\n@end table\n")
|
||||
("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"))
|
||||
("setlength" 2 "")
|
||||
("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")
|
||||
("TeX" 0 "@TeX{}")
|
||||
("textasciitilde" 0 "~")
|
||||
("textasciicircum" 0 "^")
|
||||
("textbackslash" 0 "@backslash{}")
|
||||
("textbar" 0 "|")
|
||||
("textbf" 1 "@strong{\\1}")
|
||||
("texteuro" 0 "@euro{}")
|
||||
; Unfortunately, this alternate spelling doesn't actually apply to
|
||||
; the usage found in Python Tutorial, which actually requires a
|
||||
; Euro symbol to make sense, so this is commented out as well.
|
||||
; ("texteuro" 0 "Euro ")
|
||||
("textgreater" 0 ">")
|
||||
("textit" 1 "@i{\\1}")
|
||||
("textless" 0 "<")
|
||||
("textrm" 1 "\\1")
|
||||
("texttt" 1 "@code{\\1}")
|
||||
("textunderscore" 0 "_")
|
||||
("tilde" 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")
|
||||
("undefined" 0 "")
|
||||
("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* ((texi-file-name (or py2texi-texi-file-name
|
||||
(py2texi-texi-file-name file)))
|
||||
(info-file-name (or py2texi-info-file-name
|
||||
(py2texi-info-file-name texi-file-name))))
|
||||
(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 " info-file-name))
|
||||
(when (re-search-forward "@chapter" nil t)
|
||||
(texinfo-all-menus-update t))
|
||||
(goto-char (point-min))
|
||||
(write-file texi-file-name)
|
||||
(message (format "You can apply `makeinfo %s' now." texi-file-name))))
|
||||
|
||||
|
||||
(defun py2texi-texi-file-name (filename)
|
||||
"Generate name of Texinfo file from original file name FILENAME."
|
||||
(concat filename
|
||||
(if (string-match "\\.tex$" filename) "i" ".texi")))
|
||||
|
||||
|
||||
(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\\)}"
|
||||
(when (save-excursion
|
||||
; Make sure we aren't looking at a commented out version
|
||||
; of a verbatim environment
|
||||
(beginning-of-line)
|
||||
(not (looking-at "%")))
|
||||
(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 (file-name-as-directory (car dirs)) filename))
|
||||
(if (not (file-name-absolute-p includefile))
|
||||
(setq includefile
|
||||
(concat (file-name-as-directory path) includefile)))
|
||||
(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
|
||||
index)
|
||||
(py2texi-search "^@node +\\(.*\\)$"
|
||||
(setq string (match-string 1))
|
||||
(if py2texi-xemacs
|
||||
(replace-match "@node " t)
|
||||
(replace-match "" t nil nil 1))
|
||||
(while (string-match "@label{[^}]*}" string)
|
||||
(setq label (match-string 0 string))
|
||||
(setq string (replace-match "" t nil string)))
|
||||
(while (string-match "@..?index{[^}]*}" string)
|
||||
(setq index (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)))
|
||||
(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)
|
||||
(beginning-of-line 3)
|
||||
(when label
|
||||
(insert label "\n"))
|
||||
(when index
|
||||
(insert index "\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."
|
||||
(py2texi-search "{@{}"
|
||||
(replace-match "@{"))
|
||||
(py2texi-search "{@}}"
|
||||
(replace-match "@}"))
|
||||
(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
|
|
@ -1,97 +0,0 @@
|
|||
"""Support functions for loading the reference count data file."""
|
||||
__version__ = '$Revision$'
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
# Determine the expected location of the reference count file:
|
||||
try:
|
||||
p = os.path.dirname(__file__)
|
||||
except NameError:
|
||||
p = os.path.dirname(sys.argv[0])
|
||||
p = os.path.normpath(os.path.join(os.getcwd(), p, os.pardir,
|
||||
"api", "refcounts.dat"))
|
||||
DEFAULT_PATH = p
|
||||
del p
|
||||
|
||||
|
||||
def load(path=DEFAULT_PATH):
|
||||
return loadfile(open(path))
|
||||
|
||||
|
||||
def loadfile(fp):
|
||||
d = {}
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
line = line.strip()
|
||||
if line[:1] in ("", "#"):
|
||||
# blank lines and comments
|
||||
continue
|
||||
parts = line.split(":", 4)
|
||||
if len(parts) != 5:
|
||||
raise ValueError("Not enough fields in %r" % line)
|
||||
function, type, arg, refcount, comment = parts
|
||||
if refcount == "null":
|
||||
refcount = None
|
||||
elif refcount:
|
||||
refcount = int(refcount)
|
||||
else:
|
||||
refcount = None
|
||||
#
|
||||
# Get the entry, creating it if needed:
|
||||
#
|
||||
try:
|
||||
entry = d[function]
|
||||
except KeyError:
|
||||
entry = d[function] = Entry(function)
|
||||
#
|
||||
# Update the entry with the new parameter or the result information.
|
||||
#
|
||||
if arg:
|
||||
entry.args.append((arg, type, refcount))
|
||||
else:
|
||||
entry.result_type = type
|
||||
entry.result_refs = refcount
|
||||
return d
|
||||
|
||||
|
||||
class Entry:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.args = []
|
||||
self.result_type = ''
|
||||
self.result_refs = None
|
||||
|
||||
|
||||
def dump(d):
|
||||
"""Dump the data in the 'canonical' format, with functions in
|
||||
sorted order."""
|
||||
items = sorted(d.items())
|
||||
first = 1
|
||||
for k, entry in items:
|
||||
if first:
|
||||
first = 0
|
||||
else:
|
||||
print()
|
||||
s = entry.name + ":%s:%s:%s:"
|
||||
if entry.result_refs is None:
|
||||
r = ""
|
||||
else:
|
||||
r = entry.result_refs
|
||||
print(s % (entry.result_type, "", r))
|
||||
for t, n, r in entry.args:
|
||||
if r is None:
|
||||
r = ""
|
||||
print(s % (t, n, r))
|
||||
|
||||
|
||||
def main():
|
||||
d = load()
|
||||
dump(d)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,54 +0,0 @@
|
|||
"""Simple script to replace @DATE@ and friends with real information.
|
||||
|
||||
Usage: rewrite.py boilerplate.tex [VAR=value] ... <template >output
|
||||
"""
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
def get_info(fp):
|
||||
s = fp.read()
|
||||
|
||||
d = {}
|
||||
start = s.find(r"\date{")
|
||||
if start >= 0:
|
||||
end = s.find("}", start)
|
||||
date = s[start+6:end]
|
||||
if date == r"\today":
|
||||
date = time.strftime("%B %d, %Y", time.localtime(time.time()))
|
||||
d["DATE"] = date
|
||||
return d
|
||||
|
||||
|
||||
def main():
|
||||
s = sys.stdin.read()
|
||||
if "@" in s:
|
||||
# yes, we actully need to load the replacement values
|
||||
d = get_info(open(sys.argv[1]))
|
||||
for arg in sys.argv[2:]:
|
||||
name, value = arg.split("=", 1)
|
||||
d[name] = value
|
||||
start = 0
|
||||
while 1:
|
||||
start = s.find("@", start)
|
||||
if start < 0:
|
||||
break
|
||||
end = s.find("@", start+1)
|
||||
name = s[start+1:end]
|
||||
if name:
|
||||
value = d.get(name)
|
||||
if value is None:
|
||||
start = end + 1
|
||||
else:
|
||||
s = s[:start] + value + s[end+1:]
|
||||
start = start + len(value)
|
||||
else:
|
||||
# "@@" --> "@"
|
||||
s = s[:start] + s[end:]
|
||||
start = end
|
||||
sys.stdout.write(s)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,67 +0,0 @@
|
|||
# Simple makefile to control XML generation for the entire document tree.
|
||||
# This should be used from the top-level directory (Doc/), not the directory
|
||||
# that actually contains this file:
|
||||
#
|
||||
# $ pwd
|
||||
# .../Doc
|
||||
# $ make -f tools/sgmlconv/Makefile
|
||||
|
||||
TOPDIR=.
|
||||
TOOLSDIR=tools
|
||||
|
||||
SGMLRULES=../$(TOOLSDIR)/sgmlconv/make.rules
|
||||
# The 'inst' and 'tut' directories break the conversion, so skip them for now.
|
||||
SUBDIRS=api dist ext lib mac ref
|
||||
SUBMAKE=$(MAKE) -f $(SGMLRULES) TOOLSDIR=../$(TOOLSDIR)
|
||||
|
||||
all: xml
|
||||
|
||||
.PHONY: esis xml
|
||||
.PHONY: $(SUBDIRS)
|
||||
|
||||
xml:
|
||||
for DIR in $(SUBDIRS) ; do \
|
||||
(cd $$DIR && $(SUBMAKE) xml) || exit $$? ; done
|
||||
|
||||
esis:
|
||||
for DIR in $(SUBDIRS) ; do \
|
||||
(cd $$DIR && $(SUBMAKE) esis) || exit $$? ; done
|
||||
|
||||
esis1:
|
||||
for DIR in $(SUBDIRS) ; do \
|
||||
(cd $$DIR && $(SUBMAKE) esis1) || exit $$? ; done
|
||||
|
||||
tarball: xml
|
||||
tar cf - tools/sgmlconv */*.xml | gzip -9 >xml-1.5.2b2.tgz
|
||||
|
||||
api:
|
||||
cd api && $(SUBMAKE)
|
||||
|
||||
dist:
|
||||
cd dist && $(SUBMAKE)
|
||||
|
||||
ext:
|
||||
cd ext && $(SUBMAKE)
|
||||
|
||||
inst:
|
||||
cd inst && $(SUBMAKE)
|
||||
|
||||
lib:
|
||||
cd lib && $(SUBMAKE)
|
||||
|
||||
mac:
|
||||
cd mac && $(SUBMAKE)
|
||||
|
||||
ref:
|
||||
cd ref && $(SUBMAKE)
|
||||
|
||||
tut:
|
||||
cd tut && $(SUBMAKE)
|
||||
|
||||
clean:
|
||||
for DIR in $(SUBDIRS) ; do \
|
||||
(cd $$DIR && $(SUBMAKE) clean) || exit $$? ; done
|
||||
|
||||
clobber:
|
||||
for DIR in $(SUBDIRS) ; do \
|
||||
(cd $$DIR && $(SUBMAKE) clobber) || exit $$? ; done
|
|
@ -1,58 +0,0 @@
|
|||
These scripts and Makefile fragment are used to convert the Python
|
||||
documentation in LaTeX format to XML.
|
||||
|
||||
This material is preliminary and incomplete. Python 2.0 is required.
|
||||
|
||||
To convert all documents to XML:
|
||||
|
||||
cd Doc/
|
||||
make -f tools/sgmlconv/Makefile
|
||||
|
||||
To convert one document to XML:
|
||||
|
||||
cd Doc/<document-dir>
|
||||
make -f ../tools/sgmlconv/make.rules TOOLSDIR=../tools
|
||||
|
||||
Please send comments and bug reports to docs@python.org.
|
||||
|
||||
|
||||
What do the tools do?
|
||||
---------------------
|
||||
|
||||
latex2esis.py
|
||||
Reads in a conversion specification written in XML
|
||||
(conversion.xml), reads a LaTeX document fragment, and interprets
|
||||
the markup according to the specification. The output is a stream
|
||||
of ESIS events like those created by the nsgmls SGML parser, but
|
||||
is *not* guaranteed to represent a single tree! This is done to
|
||||
allow conversion per entity rather than per document. Since many
|
||||
of the LaTeX files for the Python documentation contain two
|
||||
sections on closely related modules, it is important to allow both
|
||||
of the resulting <section> elements to exist in the same output
|
||||
stream. Additionally, since comments are not supported in ESIS,
|
||||
comments are converted to <COMMENT> elements, which might exist at
|
||||
the same level as the top-level content elements.
|
||||
|
||||
The output of latex2esis.py gets saved as <filename>.esis1.
|
||||
|
||||
docfixer.py
|
||||
This is the really painful part of the conversion. Well, it's the
|
||||
second really painful part, but more of the pain is specific to
|
||||
the structure of the Python documentation and desired output
|
||||
rather than to the parsing of LaTeX markup.
|
||||
|
||||
This script loads the ESIS data created by latex2esis.py into a
|
||||
DOM document *fragment* (remember, the latex2esis.py output may
|
||||
not be well-formed). Once loaded, it walks over the tree many
|
||||
times looking for a variety of possible specific
|
||||
micro-conversions. Most of the code is not in any way "general".
|
||||
After processing the fragment, a new ESIS data stream is written
|
||||
out. Like the input, it may not represent a well-formed
|
||||
document, but does represent a parsed entity.
|
||||
|
||||
The output of docfixer.py is what gets saved in <filename>.esis.
|
||||
|
||||
esis2sgml.py
|
||||
Reads an ESIS stream and convert to SGML or XML. This also
|
||||
converts <COMMENT> elements to real comments. This works quickly
|
||||
because there's not much to actually do.
|
|
@ -1,914 +0,0 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<conversion>
|
||||
<!-- Miscellaneous. -->
|
||||
<macro name="declaremodule">
|
||||
<attribute name="id" optional="yes"/>
|
||||
<attribute name="type"/>
|
||||
<attribute name="name"/>
|
||||
</macro>
|
||||
<macro name="modulesynopsis">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="platform">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="deprecated">
|
||||
<attribute name="version"/>
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="label">
|
||||
<attribute name="id"/>
|
||||
</macro>
|
||||
<macro name="nodename" outputname="label">
|
||||
<attribute name="id"/>
|
||||
</macro>
|
||||
<macro name="localmoduletable"/>
|
||||
<macro name="manpage">
|
||||
<attribute name="name"/>
|
||||
<attribute name="section"/>
|
||||
</macro>
|
||||
<macro name="module">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="moduleauthor">
|
||||
<attribute name="name"/>
|
||||
<attribute name="email"/>
|
||||
</macro>
|
||||
<macro name="citetitle">
|
||||
<attribute name="href" optional="yes"/>
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="pep">
|
||||
<attribute name="num"/>
|
||||
</macro>
|
||||
<macro name="rfc">
|
||||
<attribute name="num"/>
|
||||
</macro>
|
||||
<macro name="sectionauthor" outputname="author">
|
||||
<attribute name="name"/>
|
||||
<attribute name="email"/>
|
||||
</macro>
|
||||
<macro name="author">
|
||||
<attribute name="name"/>
|
||||
</macro>
|
||||
<macro name="authoraddress">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="shortversion"/>
|
||||
<macro name="note">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="warning">
|
||||
<content/>
|
||||
</macro>
|
||||
<environment name="notice">
|
||||
<attribute name="role" optional="yes"/>
|
||||
</environment>
|
||||
|
||||
<macro name="menuselection">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="sub"/>
|
||||
|
||||
<!-- These are broken: we need to re-order the optional and required
|
||||
parameters, making the optional parameter the content for the
|
||||
element. latex2esis.py is not powerful enough to handle this.
|
||||
-->
|
||||
<macro name="versionadded">
|
||||
<attribute name="info" optional="yes"/>
|
||||
<attribute name="version"/>
|
||||
</macro>
|
||||
<macro name="versionchanged">
|
||||
<attribute name="info" optional="yes"/>
|
||||
<attribute name="version"/>
|
||||
</macro>
|
||||
|
||||
<!-- Module referencing. -->
|
||||
<macro name="refmodule" outputname="module">
|
||||
<!-- this causes the optional parameter to \refmodule to be
|
||||
discarded -->
|
||||
<attribute name="" optional="yes"/>
|
||||
<content/>
|
||||
</macro>
|
||||
|
||||
<!-- Information units. -->
|
||||
<!-- C things. -->
|
||||
<environment name="cfuncdesc">
|
||||
<attribute name="type"/>
|
||||
<attribute name="name"/>
|
||||
<child name="args"/>
|
||||
</environment>
|
||||
<environment name="csimplemacrodesc">
|
||||
<attribute name="name"/>
|
||||
</environment>
|
||||
<environment name="ctypedesc">
|
||||
<attribute name="tag" optional="yes"/>
|
||||
<attribute name="name"/>
|
||||
</environment>
|
||||
<environment name="cvardesc">
|
||||
<attribute name="type"/>
|
||||
<attribute name="name"/>
|
||||
</environment>
|
||||
|
||||
<!-- Python things. -->
|
||||
<macro name="optional">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="unspecified"/>
|
||||
<macro name="moreargs"/>
|
||||
<environment name="classdesc">
|
||||
<attribute name="name"/>
|
||||
<child name="args"/>
|
||||
</environment>
|
||||
<environment name="classdesc*" outputname="classdesc">
|
||||
<attribute name="name"/>
|
||||
</environment>
|
||||
<environment name="datadesc">
|
||||
<attribute name="name"/>
|
||||
</environment>
|
||||
<environment name="datadescni" outputname="datadesc">
|
||||
<attribute name="index">no</attribute>
|
||||
<attribute name="name"/>
|
||||
</environment>
|
||||
<macro name="dataline">
|
||||
<attribute name="name"/>
|
||||
</macro>
|
||||
<environment name="excclassdesc">
|
||||
<attribute name="name"/>
|
||||
<child name="args"/>
|
||||
</environment>
|
||||
<environment name="excdesc">
|
||||
<attribute name="name"/>
|
||||
</environment>
|
||||
|
||||
<environment name="funcdesc">
|
||||
<attribute name="name"/>
|
||||
<child name="args"/>
|
||||
</environment>
|
||||
<macro name="funcline">
|
||||
<attribute name="name"/>
|
||||
<child name="args"/>
|
||||
</macro>
|
||||
<environment name="funcdescni" outputname="funcdesc">
|
||||
<attribute name="index">no</attribute>
|
||||
<attribute name="name"/>
|
||||
<child name="args"/>
|
||||
</environment>
|
||||
<macro name="funclineni" outputname="funcline">
|
||||
<attribute name="index">no</attribute>
|
||||
<attribute name="name"/>
|
||||
<child name="args"/>
|
||||
</macro>
|
||||
|
||||
<environment name="memberdesc">
|
||||
<attribute name="class" optional="yes"/>
|
||||
<attribute name="name"/>
|
||||
</environment>
|
||||
<environment name="memberdescni" outputname="memberdesc">
|
||||
<attribute name="index">no</attribute>
|
||||
<attribute name="class" optional="yes"/>
|
||||
<attribute name="name"/>
|
||||
</environment>
|
||||
<macro name="memberline">
|
||||
<attribute name="name"/>
|
||||
</macro>
|
||||
|
||||
<environment name="methoddesc">
|
||||
<attribute name="class" optional="yes"/>
|
||||
<attribute name="name"/>
|
||||
<child name="args"/>
|
||||
</environment>
|
||||
<macro name="methodline">
|
||||
<attribute name="class" optional="yes"/>
|
||||
<attribute name="name"/>
|
||||
<child name="args"/>
|
||||
</macro>
|
||||
<environment name="methoddescni">
|
||||
<attribute name="index">no</attribute>
|
||||
<attribute name="class" optional="yes"/>
|
||||
<attribute name="name"/>
|
||||
<child name="args"/>
|
||||
</environment>
|
||||
<macro name="methodlineni" outputname="methodline">
|
||||
<attribute name="index">no</attribute>
|
||||
<attribute name="class" optional="yes"/>
|
||||
<attribute name="name"/>
|
||||
<child name="args"/>
|
||||
</macro>
|
||||
|
||||
<environment name="opcodedesc">
|
||||
<attribute name="name"/>
|
||||
<attribute name="var"/>
|
||||
</environment>
|
||||
|
||||
<!-- "See also:" sections. -->
|
||||
<environment name="seealso*" outputname="seealso">
|
||||
<attribute name="sidebar">no</attribute>
|
||||
</environment>
|
||||
<macro name="seemodule">
|
||||
<!-- this causes the optional parameter to \seemodule to be
|
||||
discarded -->
|
||||
<attribute name="" optional="yes"/>
|
||||
<attribute name="name"/>
|
||||
<child name="description"/>
|
||||
</macro>
|
||||
<macro name="seepep">
|
||||
<attribute name="number"/>
|
||||
<child name="title"/>
|
||||
<child name="description"/>
|
||||
</macro>
|
||||
<macro name="seerfc">
|
||||
<attribute name="number"/>
|
||||
<child name="title"/>
|
||||
<child name="description"/>
|
||||
</macro>
|
||||
<macro name="seetext">
|
||||
<child name="description"/>
|
||||
</macro>
|
||||
<macro name="seetitle">
|
||||
<attribute name="href" optional="yes"/>
|
||||
<child name="title"/>
|
||||
<child name="description"/>
|
||||
</macro>
|
||||
<macro name="seeurl">
|
||||
<attribute name="href"/>
|
||||
<child name="description"/>
|
||||
</macro>
|
||||
|
||||
<!-- Index-generating markup. -->
|
||||
<macro name="index" outputname="indexterm">
|
||||
<attribute name="term1"/>
|
||||
</macro>
|
||||
<macro name="indexii" outputname="indexterm">
|
||||
<attribute name="term1"/>
|
||||
<attribute name="term2"/>
|
||||
</macro>
|
||||
<macro name="indexiii" outputname="indexterm">
|
||||
<attribute name="term1"/>
|
||||
<attribute name="term2"/>
|
||||
<attribute name="term3"/>
|
||||
</macro>
|
||||
<macro name="indexiv" outputname="indexterm">
|
||||
<attribute name="term1"/>
|
||||
<attribute name="term2"/>
|
||||
<attribute name="term3"/>
|
||||
<attribute name="term4"/>
|
||||
</macro>
|
||||
|
||||
<macro name="ttindex" outputname="indexterm">
|
||||
<attribute name="style">tt</attribute>
|
||||
<attribute name="term1"/>
|
||||
</macro>
|
||||
|
||||
<macro name="refmodindex">
|
||||
<attribute name="module"/>
|
||||
</macro>
|
||||
<macro name="stmodindex">
|
||||
<attribute name="module"/>
|
||||
</macro>
|
||||
<macro name="refbimodindex" outputname="refmodindex">
|
||||
<attribute name="module"/>
|
||||
</macro>
|
||||
<macro name="refexmodindex" outputname="refmodindex">
|
||||
<attribute name="module"/>
|
||||
</macro>
|
||||
<macro name="refstmodindex" outputname="refmodindex">
|
||||
<attribute name="module"/>
|
||||
</macro>
|
||||
|
||||
<macro name="bifuncindex">
|
||||
<attribute name="name"/>
|
||||
</macro>
|
||||
<macro name="exindex">
|
||||
<attribute name="name"/>
|
||||
</macro>
|
||||
<macro name="obindex">
|
||||
<attribute name="name"/>
|
||||
</macro>
|
||||
<macro name="kwindex">
|
||||
<attribute name="name"/>
|
||||
</macro>
|
||||
<macro name="opindex">
|
||||
<attribute name="type"/>
|
||||
</macro>
|
||||
<macro name="stindex">
|
||||
<attribute name="type"/>
|
||||
</macro>
|
||||
<macro name="withsubitem">
|
||||
<attribute name="text"/>
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="setindexsubitem">
|
||||
<attribute name="text"/>
|
||||
</macro>
|
||||
|
||||
<!-- Entity management. -->
|
||||
<macro name="include" outputname="xi:include">
|
||||
<attribute name="href"/>
|
||||
</macro>
|
||||
<macro name="input" outputname="xi:include">
|
||||
<attribute name="href"/>
|
||||
</macro>
|
||||
|
||||
<!-- Large-scale document structure. -->
|
||||
<macro name="documentclass">
|
||||
<attribute name="classname"/>
|
||||
</macro>
|
||||
|
||||
<macro name="usepackage">
|
||||
<attribute name="options" optional="yes"/>
|
||||
<attribute name="pkg"/>
|
||||
</macro>
|
||||
|
||||
<environment name="document"
|
||||
endcloses="chapter chapter* section section*
|
||||
subsection subsection*
|
||||
subsubsection subsubsection*
|
||||
paragraph paragraph* subparagraph
|
||||
subparagraph*">
|
||||
<attribute name="xmlns:xi"
|
||||
>http://www.w3.org/2001/XInclude</attribute>
|
||||
</environment>
|
||||
|
||||
<macro name="chapter"
|
||||
closes="chapter chapter* section section* subsection subsection*
|
||||
subsubsection subsubsection*
|
||||
paragraph paragraph* subparagraph subparagraph*">
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
<macro name="chapter*" outputname="chapter"
|
||||
closes="chapter chapter* section section* subsection subsection*
|
||||
subsubsection subsubsection*
|
||||
paragraph paragraph* subparagraph subparagraph*">
|
||||
<attribute name="numbered">no</attribute>
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
|
||||
<macro name="section"
|
||||
closes="section section* subsection subsection*
|
||||
subsubsection subsubsection*
|
||||
paragraph paragraph* subparagraph subparagraph*">
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
<macro name="section*" outputname="section"
|
||||
closes="section section* subsection subsection*
|
||||
subsubsection subsubsection*
|
||||
paragraph paragraph* subparagraph subparagraph*">
|
||||
<attribute name="numbered">no</attribute>
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
|
||||
<macro name="subsection"
|
||||
closes="subsection subsection* subsubsection subsubsection*
|
||||
paragraph paragraph* subparagraph subparagraph*">
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
<macro name="subsection*" outputname="subsection"
|
||||
closes="subsection subsection* subsubsection subsubsection*
|
||||
paragraph paragraph* subparagraph subparagraph*">
|
||||
<attribute name="numbered">no</attribute>
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
|
||||
<macro name="subsubsection"
|
||||
closes="subsubsection subsubsection*
|
||||
paragraph paragraph* subparagraph subparagraph*">
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
<macro name="subsubsection*" outputname="subsubsection"
|
||||
closes="subsubsection subsubsection*
|
||||
paragraph paragraph* subparagraph subparagraph*">
|
||||
<attribute name="numbered">no</attribute>
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
|
||||
<macro name="paragraph"
|
||||
closes="paragraph paragraph* subparagraph subparagraph*">
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
<macro name="paragraph*" outputname="paragraph"
|
||||
closes="paragraph paragraph* subparagraph subparagraph*">
|
||||
<attribute name="numbered">no</attribute>
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
|
||||
<macro name="subparagraph"
|
||||
closes="subparagraph subparagraph*">
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
<macro name="subparagraph*" outputname="subparagraph"
|
||||
closes="subparagraph subparagraph*">
|
||||
<attribute name="numbered">no</attribute>
|
||||
<text>
|
||||
</text>
|
||||
<child name="title"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
<macro name="title">
|
||||
<content/>
|
||||
</macro>
|
||||
|
||||
<macro name="appendix" outputname="back-matter"
|
||||
closes="chapter chapter* section subsection subsubsection
|
||||
paragraph subparagraph"/>
|
||||
|
||||
<environment name="list"
|
||||
endcloses="item">
|
||||
<attribute name="bullet"/>
|
||||
<attribute name="init"/>
|
||||
</environment>
|
||||
<macro name="item" closes="item">
|
||||
<child name="leader" optional="yes"/>
|
||||
<content implied="yes"/>
|
||||
</macro>
|
||||
|
||||
<macro name="ref">
|
||||
<attribute name="ref"/>
|
||||
</macro>
|
||||
|
||||
<environment name="description" outputname="descriptionlist"
|
||||
endcloses="item"/>
|
||||
|
||||
<environment name="enumerate" outputname="enumeration"
|
||||
endcloses="item"/>
|
||||
|
||||
<environment name="fulllineitems"
|
||||
endcloses="item"/>
|
||||
|
||||
<environment name="itemize"
|
||||
endcloses="item"/>
|
||||
|
||||
<environment name="definitions" outputname="definitionlist"
|
||||
encloses="term"/>
|
||||
<macro name="term" closes="definition">
|
||||
<!-- not really optional, but uses the [] syntax -->
|
||||
<child name="term" optional="yes"/>
|
||||
<child name="definition" implied="yes"/>
|
||||
</macro>
|
||||
|
||||
<environment name="alltt" outputname="verbatim"/>
|
||||
<environment name="comment" verbatim="yes"/>
|
||||
<environment name="verbatim" verbatim="yes"/>
|
||||
<environment name="verbatim*" verbatim="yes">
|
||||
<!-- not used anywhere, but it's a standard LaTeXism -->
|
||||
<attribute name="spaces">visible</attribute>
|
||||
</environment>
|
||||
<macro name="verbatiminput" ouptutname="xi:include">
|
||||
<attribute name="parse">text</attribute>
|
||||
<attribute name="href"/>
|
||||
</macro>
|
||||
|
||||
<!-- Table markup. -->
|
||||
<macro name="hline"/>
|
||||
<environment name="tableii" outputname="table">
|
||||
<attribute name="cols">2</attribute>
|
||||
<attribute name="colspec"/>
|
||||
<attribute name="style"/>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</environment>
|
||||
<environment name="longtableii" outputname="table">
|
||||
<attribute name="cols">2</attribute>
|
||||
<attribute name="colspec"/>
|
||||
<attribute name="style"/>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</environment>
|
||||
<macro name="lineii" outputname="row">
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</macro>
|
||||
|
||||
<environment name="tableiii" outputname="table">
|
||||
<attribute name="cols">3</attribute>
|
||||
<attribute name="colspec"/>
|
||||
<attribute name="style"/>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</environment>
|
||||
<environment name="longtableiii" outputname="table">
|
||||
<attribute name="cols">3</attribute>
|
||||
<attribute name="colspec"/>
|
||||
<attribute name="style"/>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</environment>
|
||||
<macro name="lineiii" outputname="row">
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</macro>
|
||||
|
||||
<environment name="tableiv" outputname="table">
|
||||
<attribute name="cols">4</attribute>
|
||||
<attribute name="colspec"/>
|
||||
<attribute name="style"/>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</environment>
|
||||
<environment name="longtableiv" outputname="table">
|
||||
<attribute name="cols">4</attribute>
|
||||
<attribute name="colspec"/>
|
||||
<attribute name="style"/>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</environment>
|
||||
<macro name="lineiv" outputname="row">
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</macro>
|
||||
|
||||
<environment name="tablev" outputname="table">
|
||||
<attribute name="cols">4</attribute>
|
||||
<attribute name="colspec"/>
|
||||
<attribute name="style"/>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</environment>
|
||||
<environment name="longtablev" outputname="table">
|
||||
<attribute name="cols">4</attribute>
|
||||
<attribute name="colspec"/>
|
||||
<attribute name="style"/>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</environment>
|
||||
<macro name="linev" outputname="row">
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
<text>
|
||||
</text>
|
||||
<child name="entry"/>
|
||||
</macro>
|
||||
|
||||
<!-- These are handled at a later translation stage, at least for now. -->
|
||||
<macro name="Cpp" outputname="">
|
||||
<text>C++</text>
|
||||
</macro>
|
||||
<macro name="geq" outputname="">
|
||||
<entityref name="geq"/>
|
||||
</macro>
|
||||
<macro name="infinity" outputname="">
|
||||
<entityref name="infin"/>
|
||||
</macro>
|
||||
<macro name="LaTeX" outputname="">
|
||||
<text>LaTeX</text>
|
||||
</macro>
|
||||
<macro name="ldots" outputname="">
|
||||
<text>...</text>
|
||||
</macro>
|
||||
<macro name="leq" outputname="">
|
||||
<entityref name="leq"/>
|
||||
</macro>
|
||||
<macro name="plusminus" outputname="">
|
||||
<entityref name="plusmn"/>
|
||||
</macro>
|
||||
<macro name="TeX" outputname="">
|
||||
<text>TeX</text>
|
||||
</macro>
|
||||
<macro name="version"/>
|
||||
|
||||
<!-- Distutils things. -->
|
||||
<macro name="command">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="option">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="filevar" outputname="var">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="XXX" outputname="editorial-comment">
|
||||
<content/>
|
||||
</macro>
|
||||
|
||||
<!-- Grammar production lists -->
|
||||
<environment name="productionlist">
|
||||
<attribute name="grammar" optional="yes"/>
|
||||
</environment>
|
||||
<macro name="production">
|
||||
<attribute name="token"/>
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="productioncont">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="token" outputname="grammartoken">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="grammartoken">
|
||||
<content/>
|
||||
</macro>
|
||||
|
||||
<!-- Misc. -->
|
||||
<macro name="emph">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="strong">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="textrm">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="texttt">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="code">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="exception">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="keyword">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="samp">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="class">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="cdata">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="cfunction">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="csimplemacro">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="ctype">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="pytype">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="character">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="constant">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="envvar" outputname="envar">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="file" outputname="filename">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="filenq" outputname="filename">
|
||||
<attribute name="quote">no</attribute>
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="function">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="kbd" outputname="keysym">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="mailheader">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="makevar">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="method">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="member">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="mimetype">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="newsgroup">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="program" outputname="command">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="programopt" outputname="option">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="longprogramopt" outputname="longoption">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="regexp">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="var">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="email">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="ulink">
|
||||
<!-- order of the parameters makes this difficult;
|
||||
we'll need to fix it up to <ulink href="...">...</ulink>
|
||||
in docfixer.py.
|
||||
-->
|
||||
<child name="text"/>
|
||||
<child name="href"/>
|
||||
</macro>
|
||||
<macro name="url">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="footnote">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="dfn" outputname="definedterm">
|
||||
<content/>
|
||||
</macro>
|
||||
|
||||
<macro name="mbox">
|
||||
<content/>
|
||||
</macro>
|
||||
|
||||
<!-- minimal math stuff to get by -->
|
||||
<macro name="pi"/>
|
||||
<macro name="sqrt">
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="frac" outputname="fraction">
|
||||
<child name="numerator"/>
|
||||
<child name="denominator"/>
|
||||
</macro>
|
||||
<macro name="sum">
|
||||
<content/>
|
||||
</macro>
|
||||
|
||||
<macro name="leftline" outputname="">
|
||||
<content/>
|
||||
</macro>
|
||||
|
||||
<!-- Conversions to text; perhaps could be different? There's -->
|
||||
<!-- no way for a style sheet to work with these this way. -->
|
||||
<macro name="ABC" outputname="">
|
||||
<text>ABC</text>
|
||||
</macro>
|
||||
<macro name="ASCII" outputname="">
|
||||
<text>ASCII</text>
|
||||
</macro>
|
||||
<macro name="C" outputname="">
|
||||
<text>C</text>
|
||||
</macro>
|
||||
<macro name="EOF" outputname="">
|
||||
<text>EOF</text>
|
||||
</macro>
|
||||
<macro name="e" outputname="">
|
||||
<text>\</text>
|
||||
</macro>
|
||||
<macro name="NULL" outputname="constant">
|
||||
<text>NULL</text>
|
||||
</macro>
|
||||
<macro name="POSIX" outputname="">
|
||||
<text>POSIX</text>
|
||||
</macro>
|
||||
<macro name="UNIX" outputname="">
|
||||
<text>Unix</text>
|
||||
</macro>
|
||||
<macro name="textasciicircum" outputname="">
|
||||
<text>^</text>
|
||||
</macro>
|
||||
<macro name="textasciitilde" outputname="">
|
||||
<text>~</text>
|
||||
</macro>
|
||||
<macro name="textbackslash" outputname="">
|
||||
<text>\</text>
|
||||
</macro>
|
||||
<macro name="textbar" outputname="">
|
||||
<text>|</text>
|
||||
</macro>
|
||||
<macro name="textgreater" outputname="">
|
||||
<text>></text>
|
||||
</macro>
|
||||
<macro name="textless" outputname="">
|
||||
<text><</text>
|
||||
</macro>
|
||||
|
||||
<!-- These will end up disappearing as well! -->
|
||||
<macro name="catcode" outputname=""/>
|
||||
<macro name="fi" outputname=""/>
|
||||
<macro name="ifhtml" outputname=""/>
|
||||
<macro name="indexname" outputname=""/>
|
||||
<macro name="labelwidth" outputname=""/>
|
||||
<macro name="large" outputname=""/>
|
||||
<macro name="leftmargin" outputname=""/>
|
||||
<macro name="makeindex" outputname=""/>
|
||||
<macro name="makemodindex" outputname=""/>
|
||||
<macro name="maketitle" outputname=""/>
|
||||
<macro name="noindent" outputname=""/>
|
||||
<macro name="protect" outputname=""/>
|
||||
<macro name="textwidth"/>
|
||||
<macro name="renewcommand">
|
||||
<attribute name="macro"/>
|
||||
<attribute name="nargs" optional="yes"/>
|
||||
<content/>
|
||||
</macro>
|
||||
<macro name="tableofcontents" outputname=""/>
|
||||
<macro name="vspace">
|
||||
<attribute name="size"/>
|
||||
</macro>
|
||||
</conversion>
|
File diff suppressed because it is too large
Load diff
|
@ -1,263 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
"""Convert ESIS events to SGML or XML markup.
|
||||
|
||||
This is limited, but seems sufficient for the ESIS generated by the
|
||||
latex2esis.py script when run over the Python documentation.
|
||||
"""
|
||||
|
||||
# This should have an explicit option to indicate whether the *INPUT* was
|
||||
# generated from an SGML or an XML application.
|
||||
|
||||
import errno
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
import esistools
|
||||
|
||||
|
||||
AUTOCLOSE = ()
|
||||
|
||||
EMPTIES_FILENAME = "../sgml/empties.dat"
|
||||
LIST_EMPTIES = 0
|
||||
|
||||
|
||||
_elem_map = {}
|
||||
_attr_map = {}
|
||||
_token_map = {}
|
||||
|
||||
_normalize_case = str
|
||||
|
||||
def map_gi(sgmlgi, map):
|
||||
uncased = _normalize_case(sgmlgi)
|
||||
try:
|
||||
return map[uncased]
|
||||
except IndexError:
|
||||
map[uncased] = sgmlgi
|
||||
return sgmlgi
|
||||
|
||||
def null_map_gi(sgmlgi, map):
|
||||
return sgmlgi
|
||||
|
||||
|
||||
def format_attrs(attrs, xml=0):
|
||||
attrs = sorted(attrs.items())
|
||||
parts = []
|
||||
append = parts.append
|
||||
for name, value in attrs:
|
||||
if xml:
|
||||
append('%s="%s"' % (name, escape(value)))
|
||||
else:
|
||||
# this is a little bogus, but should do for now
|
||||
if name == value and isnmtoken(value):
|
||||
append(value)
|
||||
elif istoken(value):
|
||||
if value == "no" + name:
|
||||
append(value)
|
||||
else:
|
||||
append("%s=%s" % (name, value))
|
||||
else:
|
||||
append('%s="%s"' % (name, escape(value)))
|
||||
if parts:
|
||||
parts.insert(0, '')
|
||||
return " ".join(parts)
|
||||
|
||||
|
||||
_nmtoken_rx = re.compile("[a-z][-._a-z0-9]*$", re.IGNORECASE)
|
||||
def isnmtoken(s):
|
||||
return _nmtoken_rx.match(s) is not None
|
||||
|
||||
_token_rx = re.compile("[a-z0-9][-._a-z0-9]*$", re.IGNORECASE)
|
||||
def istoken(s):
|
||||
return _token_rx.match(s) is not None
|
||||
|
||||
|
||||
def convert(ifp, ofp, xml=0, autoclose=(), verbatims=()):
|
||||
if xml:
|
||||
autoclose = ()
|
||||
attrs = {}
|
||||
lastopened = None
|
||||
knownempties = []
|
||||
knownempty = 0
|
||||
lastempty = 0
|
||||
inverbatim = 0
|
||||
while 1:
|
||||
line = ifp.readline()
|
||||
if not line:
|
||||
break
|
||||
|
||||
type = line[0]
|
||||
data = line[1:]
|
||||
if data and data[-1] == "\n":
|
||||
data = data[:-1]
|
||||
if type == "-":
|
||||
data = esistools.decode(data)
|
||||
data = escape(data)
|
||||
if not inverbatim:
|
||||
data = data.replace("---", "—")
|
||||
ofp.write(data)
|
||||
if "\n" in data:
|
||||
lastopened = None
|
||||
knownempty = 0
|
||||
lastempty = 0
|
||||
elif type == "(":
|
||||
if data == "COMMENT":
|
||||
ofp.write("<!--")
|
||||
continue
|
||||
data = map_gi(data, _elem_map)
|
||||
if knownempty and xml:
|
||||
ofp.write("<%s%s/>" % (data, format_attrs(attrs, xml)))
|
||||
else:
|
||||
ofp.write("<%s%s>" % (data, format_attrs(attrs, xml)))
|
||||
if knownempty and data not in knownempties:
|
||||
# accumulate knowledge!
|
||||
knownempties.append(data)
|
||||
attrs = {}
|
||||
lastopened = data
|
||||
lastempty = knownempty
|
||||
knownempty = 0
|
||||
inverbatim = data in verbatims
|
||||
elif type == ")":
|
||||
if data == "COMMENT":
|
||||
ofp.write("-->")
|
||||
continue
|
||||
data = map_gi(data, _elem_map)
|
||||
if xml:
|
||||
if not lastempty:
|
||||
ofp.write("</%s>" % data)
|
||||
elif data not in knownempties:
|
||||
if data in autoclose:
|
||||
pass
|
||||
elif lastopened == data:
|
||||
ofp.write("</>")
|
||||
else:
|
||||
ofp.write("</%s>" % data)
|
||||
lastopened = None
|
||||
lastempty = 0
|
||||
inverbatim = 0
|
||||
elif type == "A":
|
||||
name, type, value = data.split(" ", 2)
|
||||
name = map_gi(name, _attr_map)
|
||||
attrs[name] = esistools.decode(value)
|
||||
elif type == "e":
|
||||
knownempty = 1
|
||||
elif type == "&":
|
||||
ofp.write("&%s;" % data)
|
||||
knownempty = 0
|
||||
else:
|
||||
raise RuntimeError("unrecognized ESIS event type: '%s'" % type)
|
||||
|
||||
if LIST_EMPTIES:
|
||||
dump_empty_element_names(knownempties)
|
||||
|
||||
|
||||
def dump_empty_element_names(knownempties):
|
||||
d = {}
|
||||
for gi in knownempties:
|
||||
d[gi] = gi
|
||||
knownempties.append("")
|
||||
if os.path.isfile(EMPTIES_FILENAME):
|
||||
fp = open(EMPTIES_FILENAME)
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
gi = line.strip()
|
||||
if gi:
|
||||
d[gi] = gi
|
||||
fp = open(EMPTIES_FILENAME, "w")
|
||||
gilist = sorted(d.keys())
|
||||
fp.write("\n".join(gilist))
|
||||
fp.write("\n")
|
||||
fp.close()
|
||||
|
||||
|
||||
def update_gi_map(map, names, fromsgml=1):
|
||||
for name in names.split(","):
|
||||
if fromsgml:
|
||||
uncased = name.lower()
|
||||
else:
|
||||
uncased = name
|
||||
map[uncased] = name
|
||||
|
||||
|
||||
def main():
|
||||
import getopt
|
||||
import sys
|
||||
#
|
||||
autoclose = AUTOCLOSE
|
||||
xml = 1
|
||||
xmldecl = 0
|
||||
elem_names = ''
|
||||
attr_names = ''
|
||||
value_names = ''
|
||||
verbatims = ('verbatim', 'interactive-session')
|
||||
opts, args = getopt.getopt(sys.argv[1:], "adesx",
|
||||
["autoclose=", "declare", "sgml", "xml",
|
||||
"elements-map=", "attributes-map",
|
||||
"values-map="])
|
||||
for opt, arg in opts:
|
||||
if opt in ("-d", "--declare"):
|
||||
xmldecl = 1
|
||||
elif opt == "-e":
|
||||
global LIST_EMPTIES
|
||||
LIST_EMPTIES = 1
|
||||
elif opt in ("-s", "--sgml"):
|
||||
xml = 0
|
||||
elif opt in ("-x", "--xml"):
|
||||
xml = 1
|
||||
elif opt in ("-a", "--autoclose"):
|
||||
autoclose = arg.split(",")
|
||||
elif opt == "--elements-map":
|
||||
elem_names = ("%s,%s" % (elem_names, arg))[1:]
|
||||
elif opt == "--attributes-map":
|
||||
attr_names = ("%s,%s" % (attr_names, arg))[1:]
|
||||
elif opt == "--values-map":
|
||||
value_names = ("%s,%s" % (value_names, arg))[1:]
|
||||
#
|
||||
# open input streams:
|
||||
#
|
||||
if len(args) == 0:
|
||||
ifp = sys.stdin
|
||||
ofp = sys.stdout
|
||||
elif len(args) == 1:
|
||||
ifp = open(args[0])
|
||||
ofp = sys.stdout
|
||||
elif len(args) == 2:
|
||||
ifp = open(args[0])
|
||||
ofp = open(args[1], "w")
|
||||
else:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
#
|
||||
# setup the name maps:
|
||||
#
|
||||
if elem_names or attr_names or value_names:
|
||||
# assume the origin was SGML; ignore case of the names from the ESIS
|
||||
# stream but set up conversion tables to get the case right on output
|
||||
global _normalize_case
|
||||
_normalize_case = string.lower
|
||||
update_gi_map(_elem_map, elem_names.split(","))
|
||||
update_gi_map(_attr_map, attr_names.split(","))
|
||||
update_gi_map(_values_map, value_names.split(","))
|
||||
else:
|
||||
global map_gi
|
||||
map_gi = null_map_gi
|
||||
#
|
||||
# run the conversion:
|
||||
#
|
||||
try:
|
||||
if xml and xmldecl:
|
||||
opf.write('<?xml version="1.0" encoding="iso8859-1"?>\n')
|
||||
convert(ifp, ofp, xml=xml, autoclose=autoclose, verbatims=verbatims)
|
||||
except IOError as e:
|
||||
(err, msg) = e
|
||||
if err != errno.EPIPE:
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,312 +0,0 @@
|
|||
"""Miscellaneous utility functions useful for dealing with ESIS streams."""
|
||||
|
||||
import re
|
||||
|
||||
import xml.dom.pulldom
|
||||
|
||||
import xml.sax
|
||||
import xml.sax.handler
|
||||
import xml.sax.xmlreader
|
||||
|
||||
|
||||
_data_match = re.compile(r"[^\\][^\\]*").match
|
||||
|
||||
def decode(s):
|
||||
r = ''
|
||||
while s:
|
||||
m = _data_match(s)
|
||||
if m:
|
||||
r = r + m.group()
|
||||
s = s[m.end():]
|
||||
elif s[1] == "\\":
|
||||
r = r + "\\"
|
||||
s = s[2:]
|
||||
elif s[1] == "n":
|
||||
r = r + "\n"
|
||||
s = s[2:]
|
||||
elif s[1] == "%":
|
||||
s = s[2:]
|
||||
n, s = s.split(";", 1)
|
||||
r = r + unichr(int(n))
|
||||
else:
|
||||
raise ValueError("can't handle %r" % s)
|
||||
return r
|
||||
|
||||
|
||||
_charmap = {}
|
||||
for c in range(128):
|
||||
_charmap[chr(c)] = chr(c)
|
||||
_charmap[unichr(c + 128)] = chr(c + 128)
|
||||
_charmap["\n"] = r"\n"
|
||||
_charmap["\\"] = r"\\"
|
||||
del c
|
||||
|
||||
_null_join = ''.join
|
||||
def encode(s):
|
||||
try:
|
||||
return _null_join(map(_charmap.get, s))
|
||||
except TypeError:
|
||||
raise Exception("could not encode %r: %r" % (s, map(_charmap.get, s)))
|
||||
|
||||
|
||||
class ESISReader(xml.sax.xmlreader.XMLReader):
|
||||
"""SAX Reader which reads from an ESIS stream.
|
||||
|
||||
No verification of the document structure is performed by the
|
||||
reader; a general verifier could be used as the target
|
||||
ContentHandler instance.
|
||||
|
||||
"""
|
||||
_decl_handler = None
|
||||
_lexical_handler = None
|
||||
|
||||
_public_id = None
|
||||
_system_id = None
|
||||
|
||||
_buffer = ""
|
||||
_is_empty = 0
|
||||
_lineno = 0
|
||||
_started = 0
|
||||
|
||||
def __init__(self, contentHandler=None, errorHandler=None):
|
||||
xml.sax.xmlreader.XMLReader.__init__(self)
|
||||
self._attrs = {}
|
||||
self._attributes = Attributes(self._attrs)
|
||||
self._locator = Locator()
|
||||
self._empties = {}
|
||||
if contentHandler:
|
||||
self.setContentHandler(contentHandler)
|
||||
if errorHandler:
|
||||
self.setErrorHandler(errorHandler)
|
||||
|
||||
def get_empties(self):
|
||||
return list(self._empties.keys())
|
||||
|
||||
#
|
||||
# XMLReader interface
|
||||
#
|
||||
|
||||
def parse(self, source):
|
||||
raise RuntimeError
|
||||
self._locator._public_id = source.getPublicId()
|
||||
self._locator._system_id = source.getSystemId()
|
||||
fp = source.getByteStream()
|
||||
handler = self.getContentHandler()
|
||||
if handler:
|
||||
handler.startDocument()
|
||||
lineno = 0
|
||||
while 1:
|
||||
token, data = self._get_token(fp)
|
||||
if token is None:
|
||||
break
|
||||
lineno = lineno + 1
|
||||
self._locator._lineno = lineno
|
||||
self._handle_token(token, data)
|
||||
handler = self.getContentHandler()
|
||||
if handler:
|
||||
handler.startDocument()
|
||||
|
||||
def feed(self, data):
|
||||
if not self._started:
|
||||
handler = self.getContentHandler()
|
||||
if handler:
|
||||
handler.startDocument()
|
||||
self._started = 1
|
||||
data = self._buffer + data
|
||||
self._buffer = None
|
||||
lines = data.split("\n")
|
||||
if lines:
|
||||
for line in lines[:-1]:
|
||||
self._lineno = self._lineno + 1
|
||||
self._locator._lineno = self._lineno
|
||||
if not line:
|
||||
e = xml.sax.SAXParseException(
|
||||
"ESIS input line contains no token type mark",
|
||||
None, self._locator)
|
||||
self.getErrorHandler().error(e)
|
||||
else:
|
||||
self._handle_token(line[0], line[1:])
|
||||
self._buffer = lines[-1]
|
||||
else:
|
||||
self._buffer = ""
|
||||
|
||||
def close(self):
|
||||
handler = self.getContentHandler()
|
||||
if handler:
|
||||
handler.endDocument()
|
||||
self._buffer = ""
|
||||
|
||||
def _get_token(self, fp):
|
||||
try:
|
||||
line = fp.readline()
|
||||
except IOError as e:
|
||||
e = SAXException("I/O error reading input stream", e)
|
||||
self.getErrorHandler().fatalError(e)
|
||||
return
|
||||
if not line:
|
||||
return None, None
|
||||
if line[-1] == "\n":
|
||||
line = line[:-1]
|
||||
if not line:
|
||||
e = xml.sax.SAXParseException(
|
||||
"ESIS input line contains no token type mark",
|
||||
None, self._locator)
|
||||
self.getErrorHandler().error(e)
|
||||
return
|
||||
return line[0], line[1:]
|
||||
|
||||
def _handle_token(self, token, data):
|
||||
handler = self.getContentHandler()
|
||||
if token == '-':
|
||||
if data and handler:
|
||||
handler.characters(decode(data))
|
||||
elif token == ')':
|
||||
if handler:
|
||||
handler.endElement(decode(data))
|
||||
elif token == '(':
|
||||
if self._is_empty:
|
||||
self._empties[data] = 1
|
||||
self._is_empty = 0
|
||||
if handler:
|
||||
handler.startElement(data, self._attributes)
|
||||
self._attrs.clear()
|
||||
elif token == 'A':
|
||||
name, value = data.split(' ', 1)
|
||||
if value != "IMPLIED":
|
||||
type, value = value.split(' ', 1)
|
||||
self._attrs[name] = (decode(value), type)
|
||||
elif token == '&':
|
||||
# entity reference in SAX?
|
||||
pass
|
||||
elif token == '?':
|
||||
if handler:
|
||||
if ' ' in data:
|
||||
target, data = data.split(None, 1)
|
||||
else:
|
||||
target, data = data, ""
|
||||
handler.processingInstruction(target, decode(data))
|
||||
elif token == 'N':
|
||||
handler = self.getDTDHandler()
|
||||
if handler:
|
||||
handler.notationDecl(data, self._public_id, self._system_id)
|
||||
self._public_id = None
|
||||
self._system_id = None
|
||||
elif token == 'p':
|
||||
self._public_id = decode(data)
|
||||
elif token == 's':
|
||||
self._system_id = decode(data)
|
||||
elif token == 'e':
|
||||
self._is_empty = 1
|
||||
elif token == 'C':
|
||||
pass
|
||||
else:
|
||||
e = SAXParseException("unknown ESIS token in event stream",
|
||||
None, self._locator)
|
||||
self.getErrorHandler().error(e)
|
||||
|
||||
def setContentHandler(self, handler):
|
||||
old = self.getContentHandler()
|
||||
if old:
|
||||
old.setDocumentLocator(None)
|
||||
if handler:
|
||||
handler.setDocumentLocator(self._locator)
|
||||
xml.sax.xmlreader.XMLReader.setContentHandler(self, handler)
|
||||
|
||||
def getProperty(self, property):
|
||||
if property == xml.sax.handler.property_lexical_handler:
|
||||
return self._lexical_handler
|
||||
|
||||
elif property == xml.sax.handler.property_declaration_handler:
|
||||
return self._decl_handler
|
||||
|
||||
else:
|
||||
raise xml.sax.SAXNotRecognizedException("unknown property %r"
|
||||
% (property, ))
|
||||
|
||||
def setProperty(self, property, value):
|
||||
if property == xml.sax.handler.property_lexical_handler:
|
||||
if self._lexical_handler:
|
||||
self._lexical_handler.setDocumentLocator(None)
|
||||
if value:
|
||||
value.setDocumentLocator(self._locator)
|
||||
self._lexical_handler = value
|
||||
|
||||
elif property == xml.sax.handler.property_declaration_handler:
|
||||
if self._decl_handler:
|
||||
self._decl_handler.setDocumentLocator(None)
|
||||
if value:
|
||||
value.setDocumentLocator(self._locator)
|
||||
self._decl_handler = value
|
||||
|
||||
else:
|
||||
raise xml.sax.SAXNotRecognizedException()
|
||||
|
||||
def getFeature(self, feature):
|
||||
if feature == xml.sax.handler.feature_namespaces:
|
||||
return 1
|
||||
else:
|
||||
return xml.sax.xmlreader.XMLReader.getFeature(self, feature)
|
||||
|
||||
def setFeature(self, feature, enabled):
|
||||
if feature == xml.sax.handler.feature_namespaces:
|
||||
pass
|
||||
else:
|
||||
xml.sax.xmlreader.XMLReader.setFeature(self, feature, enabled)
|
||||
|
||||
|
||||
class Attributes(xml.sax.xmlreader.AttributesImpl):
|
||||
# self._attrs has the form {name: (value, type)}
|
||||
|
||||
def getType(self, name):
|
||||
return self._attrs[name][1]
|
||||
|
||||
def getValue(self, name):
|
||||
return self._attrs[name][0]
|
||||
|
||||
def getValueByQName(self, name):
|
||||
return self._attrs[name][0]
|
||||
|
||||
def __getitem__(self, name):
|
||||
return self._attrs[name][0]
|
||||
|
||||
def get(self, name, default=None):
|
||||
if name in self._attrs:
|
||||
return self._attrs[name][0]
|
||||
return default
|
||||
|
||||
def items(self):
|
||||
L = []
|
||||
for name, (value, type) in self._attrs.items():
|
||||
L.append((name, value))
|
||||
return L
|
||||
|
||||
def values(self):
|
||||
L = []
|
||||
for value, type in list(self._attrs.values()):
|
||||
L.append(value)
|
||||
return L
|
||||
|
||||
|
||||
class Locator(xml.sax.xmlreader.Locator):
|
||||
_lineno = -1
|
||||
_public_id = None
|
||||
_system_id = None
|
||||
|
||||
def getLineNumber(self):
|
||||
return self._lineno
|
||||
|
||||
def getPublicId(self):
|
||||
return self._public_id
|
||||
|
||||
def getSystemId(self):
|
||||
return self._system_id
|
||||
|
||||
|
||||
def parse(stream_or_string, parser=None):
|
||||
if type(stream_or_string) in [type(""), type(u"")]:
|
||||
stream = open(stream_or_string)
|
||||
else:
|
||||
stream = stream_or_string
|
||||
if not parser:
|
||||
parser = ESISReader()
|
||||
return xml.dom.pulldom.DOMEventStream(stream, parser, (2 ** 14) - 20)
|
|
@ -1,566 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
"""Generate ESIS events based on a LaTeX source document and
|
||||
configuration data.
|
||||
|
||||
The conversion is not strong enough to work with arbitrary LaTeX
|
||||
documents; it has only been designed to work with the highly stylized
|
||||
markup used in the standard Python documentation. A lot of
|
||||
information about specific markup is encoded in the control table
|
||||
passed to the convert() function; changing this table can allow this
|
||||
tool to support additional LaTeX markups.
|
||||
|
||||
The format of the table is largely undocumented; see the commented
|
||||
headers where the table is specified in main(). There is no provision
|
||||
to load an alternate table from an external file.
|
||||
"""
|
||||
|
||||
import errno
|
||||
import getopt
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import xml.sax
|
||||
import xml.sax.saxutils
|
||||
|
||||
from esistools import encode
|
||||
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
|
||||
class LaTeXFormatError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class LaTeXStackError(LaTeXFormatError):
|
||||
def __init__(self, found, stack):
|
||||
msg = "environment close for %s doesn't match;\n stack = %s" \
|
||||
% (found, stack)
|
||||
self.found = found
|
||||
self.stack = stack[:]
|
||||
LaTeXFormatError.__init__(self, msg)
|
||||
|
||||
|
||||
_begin_env_rx = re.compile(r"[\\]begin{([^}]*)}")
|
||||
_end_env_rx = re.compile(r"[\\]end{([^}]*)}")
|
||||
_begin_macro_rx = re.compile(r"[\\]([a-zA-Z]+[*]?) ?({|\s*\n?)")
|
||||
_comment_rx = re.compile("%+ ?(.*)\n[ \t]*")
|
||||
_text_rx = re.compile(r"[^]~%\\{}]+")
|
||||
_optional_rx = re.compile(r"\s*[[]([^]]*)[]]", re.MULTILINE)
|
||||
# _parameter_rx is this complicated to allow {...} inside a parameter;
|
||||
# this is useful to match tabular layout specifications like {c|p{24pt}}
|
||||
_parameter_rx = re.compile("[ \n]*{(([^{}}]|{[^}]*})*)}")
|
||||
_token_rx = re.compile(r"[a-zA-Z][a-zA-Z0-9.-]*$")
|
||||
_start_group_rx = re.compile("[ \n]*{")
|
||||
_start_optional_rx = re.compile("[ \n]*[[]")
|
||||
|
||||
|
||||
ESCAPED_CHARS = "$%#^ {}&~"
|
||||
|
||||
|
||||
def dbgmsg(msg):
|
||||
if DEBUG:
|
||||
sys.stderr.write(msg + "\n")
|
||||
|
||||
def pushing(name, point, depth):
|
||||
dbgmsg("pushing <%s> at %s" % (name, point))
|
||||
|
||||
def popping(name, point, depth):
|
||||
dbgmsg("popping </%s> at %s" % (name, point))
|
||||
|
||||
|
||||
class _Stack(list):
|
||||
def append(self, entry):
|
||||
if not isinstance(entry, str):
|
||||
raise LaTeXFormatError("cannot push non-string on stack: %r"
|
||||
% (entry, ))
|
||||
#dbgmsg("%s<%s>" % (" "*len(self.data), entry))
|
||||
list.append(self, entry)
|
||||
|
||||
def pop(self, index=-1):
|
||||
entry = self[index]
|
||||
del self[index]
|
||||
#dbgmsg("%s</%s>" % (" " * len(self), entry))
|
||||
|
||||
def __delitem__(self, index):
|
||||
entry = self[index]
|
||||
list.__delitem__(self, index)
|
||||
#dbgmsg("%s</%s>" % (" " * len(self), entry))
|
||||
|
||||
|
||||
def new_stack():
|
||||
if DEBUG:
|
||||
return _Stack()
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
class Conversion:
|
||||
def __init__(self, ifp, ofp, table):
|
||||
self.write = ofp.write
|
||||
self.ofp = ofp
|
||||
self.table = table
|
||||
L = [s.rstrip() for s in ifp.readlines()]
|
||||
L.append("")
|
||||
self.line = "\n".join(L)
|
||||
self.preamble = 1
|
||||
|
||||
def convert(self):
|
||||
self.subconvert()
|
||||
|
||||
def subconvert(self, endchar=None, depth=0):
|
||||
#
|
||||
# Parses content, including sub-structures, until the character
|
||||
# 'endchar' is found (with no open structures), or until the end
|
||||
# of the input data is endchar is None.
|
||||
#
|
||||
stack = new_stack()
|
||||
line = self.line
|
||||
while line:
|
||||
if line[0] == endchar and not stack:
|
||||
self.line = line
|
||||
return line
|
||||
m = _comment_rx.match(line)
|
||||
if m:
|
||||
text = m.group(1)
|
||||
if text:
|
||||
self.write("(COMMENT\n- %s \n)COMMENT\n-\\n\n"
|
||||
% encode(text))
|
||||
line = line[m.end():]
|
||||
continue
|
||||
m = _begin_env_rx.match(line)
|
||||
if m:
|
||||
name = m.group(1)
|
||||
entry = self.get_env_entry(name)
|
||||
# re-write to use the macro handler
|
||||
line = r"\%s %s" % (name, line[m.end():])
|
||||
continue
|
||||
m = _end_env_rx.match(line)
|
||||
if m:
|
||||
# end of environment
|
||||
envname = m.group(1)
|
||||
entry = self.get_entry(envname)
|
||||
while stack and envname != stack[-1] \
|
||||
and stack[-1] in entry.endcloses:
|
||||
self.write(")%s\n" % stack.pop())
|
||||
if stack and envname == stack[-1]:
|
||||
self.write(")%s\n" % entry.outputname)
|
||||
del stack[-1]
|
||||
else:
|
||||
raise LaTeXStackError(envname, stack)
|
||||
line = line[m.end():]
|
||||
continue
|
||||
m = _begin_macro_rx.match(line)
|
||||
if m:
|
||||
# start of macro
|
||||
macroname = m.group(1)
|
||||
if macroname == "c":
|
||||
# Ugh! This is a combining character...
|
||||
endpos = m.end()
|
||||
self.combining_char("c", line[endpos])
|
||||
line = line[endpos + 1:]
|
||||
continue
|
||||
entry = self.get_entry(macroname)
|
||||
if entry.verbatim:
|
||||
# magic case!
|
||||
pos = line.find("\\end{%s}" % macroname)
|
||||
text = line[m.end(1):pos]
|
||||
stack.append(entry.name)
|
||||
self.write("(%s\n" % entry.outputname)
|
||||
self.write("-%s\n" % encode(text))
|
||||
self.write(")%s\n" % entry.outputname)
|
||||
stack.pop()
|
||||
line = line[pos + len("\\end{%s}" % macroname):]
|
||||
continue
|
||||
while stack and stack[-1] in entry.closes:
|
||||
top = stack.pop()
|
||||
topentry = self.get_entry(top)
|
||||
if topentry.outputname:
|
||||
self.write(")%s\n-\\n\n" % topentry.outputname)
|
||||
#
|
||||
if entry.outputname and entry.empty:
|
||||
self.write("e\n")
|
||||
#
|
||||
params, optional, empty = self.start_macro(macroname)
|
||||
# rip off the macroname
|
||||
if params:
|
||||
line = line[m.end(1):]
|
||||
elif empty:
|
||||
line = line[m.end(1):]
|
||||
else:
|
||||
line = line[m.end():]
|
||||
opened = 0
|
||||
implied_content = 0
|
||||
|
||||
# handle attribute mappings here:
|
||||
for pentry in params:
|
||||
if pentry.type == "attribute":
|
||||
if pentry.optional:
|
||||
m = _optional_rx.match(line)
|
||||
if m and entry.outputname:
|
||||
line = line[m.end():]
|
||||
self.dump_attr(pentry, m.group(1))
|
||||
elif pentry.text and entry.outputname:
|
||||
# value supplied by conversion spec:
|
||||
self.dump_attr(pentry, pentry.text)
|
||||
else:
|
||||
m = _parameter_rx.match(line)
|
||||
if not m:
|
||||
raise LaTeXFormatError(
|
||||
"could not extract parameter %s for %s: %r"
|
||||
% (pentry.name, macroname, line[:100]))
|
||||
if entry.outputname:
|
||||
self.dump_attr(pentry, m.group(1))
|
||||
line = line[m.end():]
|
||||
elif pentry.type == "child":
|
||||
if pentry.optional:
|
||||
m = _optional_rx.match(line)
|
||||
if m:
|
||||
line = line[m.end():]
|
||||
if entry.outputname and not opened:
|
||||
opened = 1
|
||||
self.write("(%s\n" % entry.outputname)
|
||||
stack.append(macroname)
|
||||
stack.append(pentry.name)
|
||||
self.write("(%s\n" % pentry.name)
|
||||
self.write("-%s\n" % encode(m.group(1)))
|
||||
self.write(")%s\n" % pentry.name)
|
||||
stack.pop()
|
||||
else:
|
||||
if entry.outputname and not opened:
|
||||
opened = 1
|
||||
self.write("(%s\n" % entry.outputname)
|
||||
stack.append(entry.name)
|
||||
self.write("(%s\n" % pentry.name)
|
||||
stack.append(pentry.name)
|
||||
self.line = skip_white(line)[1:]
|
||||
line = self.subconvert(
|
||||
"}", len(stack) + depth + 1)[1:]
|
||||
self.write(")%s\n" % stack.pop())
|
||||
elif pentry.type == "content":
|
||||
if pentry.implied:
|
||||
implied_content = 1
|
||||
else:
|
||||
if entry.outputname and not opened:
|
||||
opened = 1
|
||||
self.write("(%s\n" % entry.outputname)
|
||||
stack.append(entry.name)
|
||||
line = skip_white(line)
|
||||
if line[0] != "{":
|
||||
raise LaTeXFormatError(
|
||||
"missing content for " + macroname)
|
||||
self.line = line[1:]
|
||||
line = self.subconvert("}", len(stack) + depth + 1)
|
||||
if line and line[0] == "}":
|
||||
line = line[1:]
|
||||
elif pentry.type == "text" and pentry.text:
|
||||
if entry.outputname and not opened:
|
||||
opened = 1
|
||||
stack.append(entry.name)
|
||||
self.write("(%s\n" % entry.outputname)
|
||||
#dbgmsg("--- text: %r" % pentry.text)
|
||||
self.write("-%s\n" % encode(pentry.text))
|
||||
elif pentry.type == "entityref":
|
||||
self.write("&%s\n" % pentry.name)
|
||||
if entry.outputname:
|
||||
if not opened:
|
||||
self.write("(%s\n" % entry.outputname)
|
||||
stack.append(entry.name)
|
||||
if not implied_content:
|
||||
self.write(")%s\n" % entry.outputname)
|
||||
stack.pop()
|
||||
continue
|
||||
if line[0] == endchar and not stack:
|
||||
self.line = line[1:]
|
||||
return self.line
|
||||
if line[0] == "}":
|
||||
# end of macro or group
|
||||
macroname = stack[-1]
|
||||
if macroname:
|
||||
conversion = self.table[macroname]
|
||||
if conversion.outputname:
|
||||
# otherwise, it was just a bare group
|
||||
self.write(")%s\n" % conversion.outputname)
|
||||
del stack[-1]
|
||||
line = line[1:]
|
||||
continue
|
||||
if line[0] == "~":
|
||||
# don't worry about the "tie" aspect of this command
|
||||
line = line[1:]
|
||||
self.write("- \n")
|
||||
continue
|
||||
if line[0] == "{":
|
||||
stack.append("")
|
||||
line = line[1:]
|
||||
continue
|
||||
if line[0] == "\\" and line[1] in ESCAPED_CHARS:
|
||||
self.write("-%s\n" % encode(line[1]))
|
||||
line = line[2:]
|
||||
continue
|
||||
if line[:2] == r"\\":
|
||||
self.write("(BREAK\n)BREAK\n")
|
||||
line = line[2:]
|
||||
continue
|
||||
if line[:2] == r"\_":
|
||||
line = "_" + line[2:]
|
||||
continue
|
||||
if line[:2] in (r"\'", r'\"'):
|
||||
# combining characters...
|
||||
self.combining_char(line[1], line[2])
|
||||
line = line[3:]
|
||||
continue
|
||||
m = _text_rx.match(line)
|
||||
if m:
|
||||
text = encode(m.group())
|
||||
self.write("-%s\n" % text)
|
||||
line = line[m.end():]
|
||||
continue
|
||||
# special case because of \item[]
|
||||
# XXX can we axe this???
|
||||
if line[0] == "]":
|
||||
self.write("-]\n")
|
||||
line = line[1:]
|
||||
continue
|
||||
# avoid infinite loops
|
||||
extra = ""
|
||||
if len(line) > 100:
|
||||
extra = "..."
|
||||
raise LaTeXFormatError("could not identify markup: %r%s"
|
||||
% (line[:100], extra))
|
||||
while stack:
|
||||
entry = self.get_entry(stack[-1])
|
||||
if entry.closes:
|
||||
self.write(")%s\n-%s\n" % (entry.outputname, encode("\n")))
|
||||
del stack[-1]
|
||||
else:
|
||||
break
|
||||
if stack:
|
||||
raise LaTeXFormatError("elements remain on stack: "
|
||||
+ ", ".join(stack))
|
||||
# otherwise we just ran out of input here...
|
||||
|
||||
# This is a really limited table of combinations, but it will have
|
||||
# to do for now.
|
||||
_combinations = {
|
||||
("c", "c"): 0x00E7,
|
||||
("'", "e"): 0x00E9,
|
||||
('"', "o"): 0x00F6,
|
||||
}
|
||||
|
||||
def combining_char(self, prefix, char):
|
||||
ordinal = self._combinations[(prefix, char)]
|
||||
self.write("-\\%%%d;\n" % ordinal)
|
||||
|
||||
def start_macro(self, name):
|
||||
conversion = self.get_entry(name)
|
||||
parameters = conversion.parameters
|
||||
optional = parameters and parameters[0].optional
|
||||
return parameters, optional, conversion.empty
|
||||
|
||||
def get_entry(self, name):
|
||||
entry = self.table.get(name)
|
||||
if entry is None:
|
||||
dbgmsg("get_entry(%r) failing; building default entry!" % (name, ))
|
||||
# not defined; build a default entry:
|
||||
entry = TableEntry(name)
|
||||
entry.has_content = 1
|
||||
entry.parameters.append(Parameter("content"))
|
||||
self.table[name] = entry
|
||||
return entry
|
||||
|
||||
def get_env_entry(self, name):
|
||||
entry = self.table.get(name)
|
||||
if entry is None:
|
||||
# not defined; build a default entry:
|
||||
entry = TableEntry(name, 1)
|
||||
entry.has_content = 1
|
||||
entry.parameters.append(Parameter("content"))
|
||||
entry.parameters[-1].implied = 1
|
||||
self.table[name] = entry
|
||||
elif not entry.environment:
|
||||
raise LaTeXFormatError(
|
||||
name + " is defined as a macro; expected environment")
|
||||
return entry
|
||||
|
||||
def dump_attr(self, pentry, value):
|
||||
if not (pentry.name and value):
|
||||
return
|
||||
if _token_rx.match(value):
|
||||
dtype = "TOKEN"
|
||||
else:
|
||||
dtype = "CDATA"
|
||||
self.write("A%s %s %s\n" % (pentry.name, dtype, encode(value)))
|
||||
|
||||
|
||||
def convert(ifp, ofp, table):
|
||||
c = Conversion(ifp, ofp, table)
|
||||
try:
|
||||
c.convert()
|
||||
except IOError as e:
|
||||
(err, msg) = e
|
||||
if err != errno.EPIPE:
|
||||
raise
|
||||
|
||||
|
||||
def skip_white(line):
|
||||
while line and line[0] in " %\n\t\r":
|
||||
line = line[1:].lstrip()
|
||||
return line
|
||||
|
||||
|
||||
|
||||
class TableEntry:
|
||||
def __init__(self, name, environment=0):
|
||||
self.name = name
|
||||
self.outputname = name
|
||||
self.environment = environment
|
||||
self.empty = not environment
|
||||
self.has_content = 0
|
||||
self.verbatim = 0
|
||||
self.auto_close = 0
|
||||
self.parameters = []
|
||||
self.closes = []
|
||||
self.endcloses = []
|
||||
|
||||
class Parameter:
|
||||
def __init__(self, type, name=None, optional=0):
|
||||
self.type = type
|
||||
self.name = name
|
||||
self.optional = optional
|
||||
self.text = ''
|
||||
self.implied = 0
|
||||
|
||||
|
||||
class TableHandler(xml.sax.handler.ContentHandler):
|
||||
def __init__(self):
|
||||
self.__table = {}
|
||||
self.__buffer = ''
|
||||
self.__methods = {}
|
||||
|
||||
def get_table(self):
|
||||
for entry in self.__table.values():
|
||||
if entry.environment and not entry.has_content:
|
||||
p = Parameter("content")
|
||||
p.implied = 1
|
||||
entry.parameters.append(p)
|
||||
entry.has_content = 1
|
||||
return self.__table
|
||||
|
||||
def startElement(self, tag, attrs):
|
||||
try:
|
||||
start, end = self.__methods[tag]
|
||||
except KeyError:
|
||||
start = getattr(self, "start_" + tag, None)
|
||||
end = getattr(self, "end_" + tag, None)
|
||||
self.__methods[tag] = (start, end)
|
||||
if start:
|
||||
start(attrs)
|
||||
|
||||
def endElement(self, tag):
|
||||
start, end = self.__methods[tag]
|
||||
if end:
|
||||
end()
|
||||
|
||||
def endDocument(self):
|
||||
self.__methods.clear()
|
||||
|
||||
def characters(self, data):
|
||||
self.__buffer += data
|
||||
|
||||
def start_environment(self, attrs):
|
||||
name = attrs["name"]
|
||||
self.__current = TableEntry(name, environment=1)
|
||||
self.__current.verbatim = attrs.get("verbatim") == "yes"
|
||||
if "outputname" in attrs:
|
||||
self.__current.outputname = attrs.get("outputname")
|
||||
self.__current.endcloses = attrs.get("endcloses", "").split()
|
||||
def end_environment(self):
|
||||
self.end_macro()
|
||||
|
||||
def start_macro(self, attrs):
|
||||
name = attrs["name"]
|
||||
self.__current = TableEntry(name)
|
||||
self.__current.closes = attrs.get("closes", "").split()
|
||||
if "outputname" in attrs:
|
||||
self.__current.outputname = attrs.get("outputname")
|
||||
def end_macro(self):
|
||||
name = self.__current.name
|
||||
if name in self.__table:
|
||||
raise ValueError("name %r already in use" % (name,))
|
||||
self.__table[name] = self.__current
|
||||
self.__current = None
|
||||
|
||||
def start_attribute(self, attrs):
|
||||
name = attrs.get("name")
|
||||
optional = attrs.get("optional") == "yes"
|
||||
if name:
|
||||
p = Parameter("attribute", name, optional=optional)
|
||||
else:
|
||||
p = Parameter("attribute", optional=optional)
|
||||
self.__current.parameters.append(p)
|
||||
self.__buffer = ''
|
||||
def end_attribute(self):
|
||||
self.__current.parameters[-1].text = self.__buffer
|
||||
|
||||
def start_entityref(self, attrs):
|
||||
name = attrs["name"]
|
||||
p = Parameter("entityref", name)
|
||||
self.__current.parameters.append(p)
|
||||
|
||||
def start_child(self, attrs):
|
||||
name = attrs["name"]
|
||||
p = Parameter("child", name, attrs.get("optional") == "yes")
|
||||
self.__current.parameters.append(p)
|
||||
self.__current.empty = 0
|
||||
|
||||
def start_content(self, attrs):
|
||||
p = Parameter("content")
|
||||
p.implied = attrs.get("implied") == "yes"
|
||||
if self.__current.environment:
|
||||
p.implied = 1
|
||||
self.__current.parameters.append(p)
|
||||
self.__current.has_content = 1
|
||||
self.__current.empty = 0
|
||||
|
||||
def start_text(self, attrs):
|
||||
self.__current.empty = 0
|
||||
self.__buffer = ''
|
||||
def end_text(self):
|
||||
p = Parameter("text")
|
||||
p.text = self.__buffer
|
||||
self.__current.parameters.append(p)
|
||||
|
||||
|
||||
def load_table(fp):
|
||||
ch = TableHandler()
|
||||
xml.sax.parse(fp, ch)
|
||||
return ch.get_table()
|
||||
|
||||
|
||||
def main():
|
||||
global DEBUG
|
||||
#
|
||||
opts, args = getopt.getopt(sys.argv[1:], "D", ["debug"])
|
||||
for opt, arg in opts:
|
||||
if opt in ("-D", "--debug"):
|
||||
DEBUG += 1
|
||||
if len(args) == 0:
|
||||
ifp = sys.stdin
|
||||
ofp = sys.stdout
|
||||
elif len(args) == 1:
|
||||
ifp = open(args[0])
|
||||
ofp = sys.stdout
|
||||
elif len(args) == 2:
|
||||
ifp = open(args[0])
|
||||
ofp = open(args[1], "w")
|
||||
else:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
table = load_table(open(os.path.join(sys.path[0], 'conversion.xml')))
|
||||
convert(ifp, ofp, table)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,48 +0,0 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# Extra magic needed by the LaTeX->XML conversion process. This requires
|
||||
# $(TOOLSDIR) to be properly defined.
|
||||
|
||||
DOCFIXER= $(TOOLSDIR)/sgmlconv/docfixer.py
|
||||
ESIS2ML= $(TOOLSDIR)/sgmlconv/esis2sgml.py
|
||||
LATEX2ESIS= $(TOOLSDIR)/sgmlconv/latex2esis.py
|
||||
CONVERSION= $(TOOLSDIR)/sgmlconv/conversion.xml
|
||||
|
||||
ESISTARGETS= $(patsubst %.tex,%.esis,$(wildcard *.tex))
|
||||
ESIS1TARGETS= $(patsubst %.tex,%.esis1,$(wildcard *.tex))
|
||||
XMLTARGETS= $(patsubst %.tex,%.xml,$(wildcard *.tex))
|
||||
|
||||
L2EFLAGS=
|
||||
|
||||
all: xml
|
||||
|
||||
esis: $(ESISTARGETS)
|
||||
esis1: $(ESIS1TARGETS)
|
||||
xml: $(XMLTARGETS)
|
||||
|
||||
ESISTOOLS= $(TOOLSDIR)/sgmlconv/esistools.py
|
||||
|
||||
$(ESISTARGETS): $(LATEX2ESIS) $(DOCFIXER) $(ESISTOOLS) $(CONVERSION)
|
||||
$(ESIS1TARGETS): $(LATEX2ESIS) $(CONVERSION)
|
||||
# This variant is easier to work with while debugging the conversion spec:
|
||||
#$(ESISTARGETS): $(LATEX2ESIS) $(DOCFIXER) $(ESISTOOLS)
|
||||
$(XMLTARGETS): $(ESIS2ML)
|
||||
|
||||
|
||||
.SUFFIXES: .esis .esis1 .tex .xml
|
||||
|
||||
.tex.esis1:
|
||||
$(LATEX2ESIS) $(L2EFLAGS) $< $@
|
||||
|
||||
.esis1.esis:
|
||||
$(DOCFIXER) $< $@
|
||||
|
||||
.esis.xml:
|
||||
$(ESIS2ML) --xml $< $@
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.esis *.esis1
|
||||
|
||||
clobber: clean
|
||||
rm -f *.xml
|
|
@ -1,202 +0,0 @@
|
|||
"""Miscellaneous support code shared by some of the tool scripts.
|
||||
|
||||
This includes option parsing code, HTML formatting code, and a couple of
|
||||
useful helpers.
|
||||
|
||||
"""
|
||||
__version__ = '$Revision$'
|
||||
|
||||
|
||||
import getopt
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
|
||||
class Options:
|
||||
__short_args = "a:c:ho:"
|
||||
__long_args = [
|
||||
# script controls
|
||||
"columns=", "help", "output=",
|
||||
|
||||
# content components
|
||||
"address=", "iconserver=", "favicon=",
|
||||
"title=", "uplink=", "uptitle=",
|
||||
"image-type=",
|
||||
]
|
||||
|
||||
outputfile = "-"
|
||||
columns = 1
|
||||
letters = 0
|
||||
uplink = "index.html"
|
||||
uptitle = "Python Documentation Index"
|
||||
favicon = None
|
||||
|
||||
# The "Aesop Meta Tag" is poorly described, and may only be used
|
||||
# by the Aesop search engine (www.aesop.com), but doesn't hurt.
|
||||
#
|
||||
# There are a number of values this may take to roughly categorize
|
||||
# a page. A page should be marked according to its primary
|
||||
# category. Known values are:
|
||||
# 'personal' -- personal-info
|
||||
# 'information' -- information
|
||||
# 'interactive' -- interactive media
|
||||
# 'multimedia' -- multimedia presenetation (non-sales)
|
||||
# 'sales' -- sales material
|
||||
# 'links' -- links to other information pages
|
||||
#
|
||||
# Setting the aesop_type value to one of these strings will cause
|
||||
# get_header() to add the appropriate <meta> tag to the <head>.
|
||||
#
|
||||
aesop_type = None
|
||||
|
||||
def __init__(self):
|
||||
self.args = []
|
||||
self.variables = {"address": "",
|
||||
"iconserver": "icons",
|
||||
"imgtype": "png",
|
||||
"title": "Global Module Index",
|
||||
}
|
||||
|
||||
def add_args(self, short=None, long=None):
|
||||
if short:
|
||||
self.__short_args = self.__short_args + short
|
||||
if long:
|
||||
self.__long_args = self.__long_args + long
|
||||
|
||||
def parse(self, args):
|
||||
try:
|
||||
opts, args = getopt.getopt(args, self.__short_args,
|
||||
self.__long_args)
|
||||
except getopt.error:
|
||||
sys.stdout = sys.stderr
|
||||
self.usage()
|
||||
sys.exit(2)
|
||||
self.args = self.args + args
|
||||
for opt, val in opts:
|
||||
if opt in ("-a", "--address"):
|
||||
val = val.strip()
|
||||
if val:
|
||||
val = "<address>\n%s\n</address>\n" % val
|
||||
self.variables["address"] = val
|
||||
elif opt in ("-h", "--help"):
|
||||
self.usage()
|
||||
sys.exit()
|
||||
elif opt in ("-o", "--output"):
|
||||
self.outputfile = val
|
||||
elif opt in ("-c", "--columns"):
|
||||
self.columns = int(val)
|
||||
elif opt == "--title":
|
||||
self.variables["title"] = val.strip()
|
||||
elif opt == "--uplink":
|
||||
self.uplink = val.strip()
|
||||
elif opt == "--uptitle":
|
||||
self.uptitle = val.strip()
|
||||
elif opt == "--iconserver":
|
||||
self.variables["iconserver"] = val.strip() or "."
|
||||
elif opt == "--favicon":
|
||||
self.favicon = val.strip()
|
||||
elif opt == "--image-type":
|
||||
self.variables["imgtype"] = val.strip()
|
||||
else:
|
||||
self.handle_option(opt, val)
|
||||
if self.uplink and self.uptitle:
|
||||
self.variables["uplinkalt"] = "up"
|
||||
self.variables["uplinkicon"] = "up"
|
||||
else:
|
||||
self.variables["uplinkalt"] = ""
|
||||
self.variables["uplinkicon"] = "blank"
|
||||
self.variables["uplink"] = self.uplink
|
||||
self.variables["uptitle"] = self.uptitle
|
||||
|
||||
def handle_option(self, opt, val):
|
||||
raise getopt.error("option %s not recognized" % opt)
|
||||
|
||||
def get_header(self):
|
||||
s = HEAD % self.variables
|
||||
if self.uplink:
|
||||
if self.uptitle:
|
||||
link = ('<link rel="up" href="%s" title="%s">\n '
|
||||
'<link rel="start" href="%s" title="%s">'
|
||||
% (self.uplink, self.uptitle,
|
||||
self.uplink, self.uptitle))
|
||||
else:
|
||||
link = ('<link rel="up" href="%s">\n '
|
||||
'<link rel="start" href="%s">'
|
||||
% (self.uplink, self.uplink))
|
||||
repl = " %s\n</head>" % link
|
||||
s = s.replace("</head>", repl, 1)
|
||||
if self.aesop_type:
|
||||
meta = '<meta name="aesop" content="%s">\n ' % self.aesop_type
|
||||
# Insert this in the middle of the head that's been
|
||||
# generated so far, keeping <meta> and <link> elements in
|
||||
# neat groups:
|
||||
s = s.replace("<link ", meta + "<link ", 1)
|
||||
if self.favicon:
|
||||
ext = os.path.splitext(self.favicon)[1]
|
||||
if ext in (".gif", ".png"):
|
||||
type = ' type="image/%s"' % ext[1:]
|
||||
else:
|
||||
type = ''
|
||||
link = ('<link rel="SHORTCUT ICON" href="%s"%s>\n '
|
||||
% (self.favicon, type))
|
||||
s = s.replace("<link ", link + "<link ", 1)
|
||||
return s
|
||||
|
||||
def get_footer(self):
|
||||
return TAIL % self.variables
|
||||
|
||||
def get_output_file(self, filename=None):
|
||||
if filename is None:
|
||||
filename = self.outputfile
|
||||
if filename == "-":
|
||||
return sys.stdout
|
||||
else:
|
||||
return open(filename, "w")
|
||||
|
||||
|
||||
NAVIGATION = '''\
|
||||
<div class="navigation">
|
||||
<table width="100%%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td><img width="32" height="32" align="bottom" border="0" alt=""
|
||||
src="%(iconserver)s/blank.%(imgtype)s"></td>
|
||||
<td><a href="%(uplink)s"
|
||||
title="%(uptitle)s"><img width="32" height="32" align="bottom" border="0"
|
||||
alt="%(uplinkalt)s"
|
||||
src="%(iconserver)s/%(uplinkicon)s.%(imgtype)s"></a></td>
|
||||
<td><img width="32" height="32" align="bottom" border="0" alt=""
|
||||
src="%(iconserver)s/blank.%(imgtype)s"></td>
|
||||
<td align="center" width="100%%">%(title)s</td>
|
||||
<td><img width="32" height="32" align="bottom" border="0" alt=""
|
||||
src="%(iconserver)s/blank.%(imgtype)s"></td>
|
||||
<td><img width="32" height="32" align="bottom" border="0" alt=""
|
||||
src="%(iconserver)s/blank.%(imgtype)s"></td>
|
||||
<td><img width="32" height="32" align="bottom" border="0" alt=""
|
||||
src="%(iconserver)s/blank.%(imgtype)s"></td>
|
||||
</tr></table>
|
||||
<b class="navlabel">Up:</b> <span class="sectref"><a href="%(uplink)s"
|
||||
title="%(uptitle)s">%(uptitle)s</A></span>
|
||||
<br></div>
|
||||
'''
|
||||
|
||||
HEAD = '''\
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>%(title)s</title>
|
||||
<meta name="description" content="%(title)s">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="STYLESHEET" href="lib/lib.css">
|
||||
</head>
|
||||
<body>
|
||||
''' + NAVIGATION + '''\
|
||||
<hr>
|
||||
|
||||
<h2>%(title)s</h2>
|
||||
|
||||
'''
|
||||
|
||||
TAIL = "<hr>\n" + NAVIGATION + '''\
|
||||
%(address)s</body>
|
||||
</html>
|
||||
'''
|
|
@ -1,160 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
"""Convert a LaTeX .toc file to some PDFTeX magic to create that neat outline.
|
||||
|
||||
The output file has an extension of '.bkm' instead of '.out', since hyperref
|
||||
already uses that extension.
|
||||
"""
|
||||
|
||||
import getopt
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
|
||||
|
||||
# Ench item in an entry is a tuple of:
|
||||
#
|
||||
# Section #, Title String, Page #, List of Sub-entries
|
||||
#
|
||||
# The return value of parse_toc() is such a tuple.
|
||||
|
||||
cline_re = r"""^
|
||||
\\contentsline\ \{([a-z]*)} # type of section in $1
|
||||
\{(?:\\numberline\ \{([0-9.A-Z]+)})? # section number
|
||||
(.*)} # title string
|
||||
\{(\d+)}$""" # page number
|
||||
|
||||
cline_rx = re.compile(cline_re, re.VERBOSE)
|
||||
|
||||
OUTER_TO_INNER = -1
|
||||
|
||||
_transition_map = {
|
||||
('chapter', 'section'): OUTER_TO_INNER,
|
||||
('section', 'subsection'): OUTER_TO_INNER,
|
||||
('subsection', 'subsubsection'): OUTER_TO_INNER,
|
||||
('subsubsection', 'subsection'): 1,
|
||||
('subsection', 'section'): 1,
|
||||
('section', 'chapter'): 1,
|
||||
('subsection', 'chapter'): 2,
|
||||
('subsubsection', 'section'): 2,
|
||||
('subsubsection', 'chapter'): 3,
|
||||
}
|
||||
|
||||
INCLUDED_LEVELS = ("chapter", "section", "subsection", "subsubsection")
|
||||
|
||||
|
||||
class BadSectionNesting(Exception):
|
||||
"""Raised for unsupported section level transitions."""
|
||||
|
||||
def __init__(self, level, newsection, path, lineno):
|
||||
self.level = level
|
||||
self.newsection = newsection
|
||||
self.path = path
|
||||
self.lineno = lineno
|
||||
|
||||
def __str__(self):
|
||||
return ("illegal transition from %s to %s at %s (line %s)"
|
||||
% (self.level, self.newsection, self.path, self.lineno))
|
||||
|
||||
|
||||
def parse_toc(fp, bigpart=None):
|
||||
toc = top = []
|
||||
stack = [toc]
|
||||
level = bigpart or 'chapter'
|
||||
lineno = 0
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
lineno = lineno + 1
|
||||
m = cline_rx.match(line)
|
||||
if m:
|
||||
stype, snum, title, pageno = m.group(1, 2, 3, 4)
|
||||
title = clean_title(title)
|
||||
entry = (stype, snum, title, int(pageno), [])
|
||||
if stype == level:
|
||||
toc.append(entry)
|
||||
else:
|
||||
if stype not in INCLUDED_LEVELS:
|
||||
# we don't want paragraphs & subparagraphs
|
||||
continue
|
||||
try:
|
||||
direction = _transition_map[(level, stype)]
|
||||
except KeyError:
|
||||
raise BadSectionNesting(level, stype, fp.name, lineno)
|
||||
if direction == OUTER_TO_INNER:
|
||||
toc = toc[-1][-1]
|
||||
stack.insert(0, toc)
|
||||
toc.append(entry)
|
||||
else:
|
||||
for i in range(direction):
|
||||
del stack[0]
|
||||
toc = stack[0]
|
||||
toc.append(entry)
|
||||
level = stype
|
||||
else:
|
||||
sys.stderr.write("l.%s: " + line)
|
||||
return top
|
||||
|
||||
|
||||
hackscore_rx = re.compile(r"\\hackscore\s*{[^}]*}")
|
||||
raisebox_rx = re.compile(r"\\raisebox\s*{[^}]*}")
|
||||
title_rx = re.compile(r"\\([a-zA-Z])+\s+")
|
||||
title_trans = string.maketrans("", "")
|
||||
|
||||
def clean_title(title):
|
||||
title = raisebox_rx.sub("", title)
|
||||
title = hackscore_rx.sub(r"\\_", title)
|
||||
pos = 0
|
||||
while 1:
|
||||
m = title_rx.search(title, pos)
|
||||
if m:
|
||||
start = m.start()
|
||||
if title[start:start+15] != "\\textunderscore":
|
||||
title = title[:start] + title[m.end():]
|
||||
pos = start + 1
|
||||
else:
|
||||
break
|
||||
title = title.translate(title_trans, "{}")
|
||||
return title
|
||||
|
||||
|
||||
def write_toc(toc, fp):
|
||||
for entry in toc:
|
||||
write_toc_entry(entry, fp, 0)
|
||||
|
||||
def write_toc_entry(entry, fp, layer):
|
||||
stype, snum, title, pageno, toc = entry
|
||||
s = "\\pdfoutline goto name{page%03d}" % pageno
|
||||
if toc:
|
||||
s = "%s count -%d" % (s, len(toc))
|
||||
if snum:
|
||||
title = "%s %s" % (snum, title)
|
||||
s = "%s {%s}\n" % (s, title)
|
||||
fp.write(s)
|
||||
for entry in toc:
|
||||
write_toc_entry(entry, fp, layer + 1)
|
||||
|
||||
|
||||
def process(ifn, ofn, bigpart=None):
|
||||
toc = parse_toc(open(ifn), bigpart)
|
||||
write_toc(toc, open(ofn, "w"))
|
||||
|
||||
|
||||
def main():
|
||||
bigpart = None
|
||||
opts, args = getopt.getopt(sys.argv[1:], "c:")
|
||||
if opts:
|
||||
bigpart = opts[0][1]
|
||||
if not args:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
for filename in args:
|
||||
base, ext = os.path.splitext(filename)
|
||||
ext = ext or ".toc"
|
||||
process(base + ext, base + ".bkm", bigpart)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,93 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
"""\
|
||||
This script prints out a list of undocumented symbols found in
|
||||
Python include files, prefixed by their tag kind.
|
||||
|
||||
Pass Python's include files to ctags, parse the output into a
|
||||
dictionary mapping symbol names to tag kinds.
|
||||
|
||||
Then, the .tex files from Python docs are read into a giant string.
|
||||
|
||||
Finally all symbols not found in the docs are written to standard
|
||||
output, prefixed with their tag kind.
|
||||
"""
|
||||
|
||||
# Which kind of tags do we need?
|
||||
TAG_KINDS = "dpst"
|
||||
|
||||
# Doc sections to use
|
||||
DOCSECTIONS = ["api"]# ["api", "ext"]
|
||||
|
||||
# Only print symbols starting with this prefix,
|
||||
# to get all symbols, use an empty string
|
||||
PREFIXES = ("Py", "PY")
|
||||
|
||||
INCLUDEPATTERN = "*.h"
|
||||
|
||||
# end of customization section
|
||||
|
||||
|
||||
# Tested with EXUBERANT CTAGS
|
||||
# see http://ctags.sourceforge.net
|
||||
#
|
||||
# ctags fields are separated by tabs.
|
||||
# The first field is the name, the last field the type:
|
||||
# d macro definitions (and #undef names)
|
||||
# e enumerators
|
||||
# f function definitions
|
||||
# g enumeration names
|
||||
# m class, struct, or union members
|
||||
# n namespaces
|
||||
# p function prototypes and declarations
|
||||
# s structure names
|
||||
# t typedefs
|
||||
# u union names
|
||||
# v variable definitions
|
||||
# x extern and forward variable declarations
|
||||
|
||||
import os, glob, re, sys
|
||||
|
||||
def findnames(file, prefixes=()):
|
||||
names = {}
|
||||
for line in file:
|
||||
if line[0] == '!':
|
||||
continue
|
||||
fields = line.split()
|
||||
name, tag = fields[0], fields[-1]
|
||||
if tag == 'd' and name.endswith('_H'):
|
||||
continue
|
||||
if prefixes:
|
||||
sw = name.startswith
|
||||
for prefix in prefixes:
|
||||
if sw(prefix):
|
||||
names[name] = tag
|
||||
else:
|
||||
names[name] = tag
|
||||
return names
|
||||
|
||||
def print_undoc_symbols(prefix, docdir, incdir):
|
||||
docs = []
|
||||
|
||||
for sect in DOCSECTIONS:
|
||||
for file in glob.glob(os.path.join(docdir, sect, "*.tex")):
|
||||
docs.append(open(file).read())
|
||||
|
||||
docs = "\n".join(docs)
|
||||
|
||||
incfiles = os.path.join(incdir, INCLUDEPATTERN)
|
||||
|
||||
fp = os.popen("ctags -IPyAPI_FUNC -IPy_GCC_ATTRIBUTE --c-types=%s -f - %s"
|
||||
% (TAG_KINDS, incfiles))
|
||||
dict = findnames(fp, prefix)
|
||||
names = sorted(dict.keys())
|
||||
for name in names:
|
||||
if not re.search("%s\\W" % name, docs):
|
||||
print(dict[name], name)
|
||||
|
||||
if __name__ == '__main__':
|
||||
srcdir = os.path.dirname(sys.argv[0])
|
||||
incdir = os.path.normpath(os.path.join(srcdir, "../../Include"))
|
||||
docdir = os.path.normpath(os.path.join(srcdir, ".."))
|
||||
|
||||
print_undoc_symbols(PREFIXES, docdir, incdir)
|
|
@ -1,31 +0,0 @@
|
|||
#! /bin/sh
|
||||
|
||||
# Script which installs a development snapshot of the documentation
|
||||
# into the development website.
|
||||
#
|
||||
# The push-docs.sh script pushes this to the server when needed
|
||||
# and removes it when done.
|
||||
|
||||
if [ -z "$HOME" ] ; then
|
||||
HOME=`grep "$LOGNAME" /etc/passwd | sed 's|^.*:\([^:]*\):[^:]*$|\1|'`
|
||||
export HOME
|
||||
fi
|
||||
|
||||
DOCTYPE="$1"
|
||||
UPDATES="$HOME/tmp/$2"
|
||||
|
||||
TMPDIR="$$-docs"
|
||||
|
||||
cd /ftp/ftp.python.org/pub/www.python.org/dev/doc/ || exit $?
|
||||
mkdir $TMPDIR || exit $?
|
||||
cd $TMPDIR || exit $?
|
||||
(bzip2 -dc "$UPDATES" | tar xf -) || exit $?
|
||||
cd .. || exit $?
|
||||
|
||||
if [ -d $DOCTYPE ] ; then
|
||||
mv $DOCTYPE $DOCTYPE-temp
|
||||
fi
|
||||
mv $TMPDIR/Python-Docs-* $DOCTYPE
|
||||
rmdir $TMPDIR
|
||||
rm -rf $DOCTYPE-temp || exit $?
|
||||
mv "$UPDATES" python-docs-$DOCTYPE.tar.bz2 || exit $?
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/sh
|
||||
sed -n 's%^\\input{\(lib[a-zA-Z0-9_]*\)}.*%../lib/\1.tex%p' ../lib/lib.tex
|
Loading…
Add table
Add a link
Reference in a new issue