summaryrefslogtreecommitdiff
path: root/Master
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-06-21 00:23:51 +0000
committerKarl Berry <karl@freefriends.org>2009-06-21 00:23:51 +0000
commitd5c69362ef92a985a1cecefe6bbbca5eb51e822a (patch)
treeb6af1179a24bd3d2401d9540741fc4c161d7664b /Master
parentf7498423bd232008266cf75bb0c1faa1465fbb1e (diff)
sage 2.2.1 (20jun09), omitting python scripts in bin
git-svn-id: svn://tug.org/texlive/trunk@13843 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/README23
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/example.pdfbin254523 -> 199517 bytes
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/example.tex125
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/extractsagecode.py84
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/makestatic.py84
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/remote-sagetex.py344
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/sagetex.py222
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdfbin241432 -> 356078 bytes
-rw-r--r--Master/texmf-dist/doc/latex/sagetex/sagetexparse.py151
-rw-r--r--Master/texmf-dist/source/latex/sagetex/py-and-sty.dtx907
-rw-r--r--Master/texmf-dist/source/latex/sagetex/remote-sagetex.dtx438
-rw-r--r--Master/texmf-dist/source/latex/sagetex/sagetexpackage.dtx1511
-rw-r--r--Master/texmf-dist/source/latex/sagetex/sagetexpackage.ins91
-rw-r--r--Master/texmf-dist/source/latex/sagetex/scripts.dtx424
-rw-r--r--Master/texmf-dist/tex/latex/sagetex/sagetex.sty133
15 files changed, 3374 insertions, 1163 deletions
diff --git a/Master/texmf-dist/doc/latex/sagetex/README b/Master/texmf-dist/doc/latex/sagetex/README
index 2e9d512d0eb..d677252b478 100644
--- a/Master/texmf-dist/doc/latex/sagetex/README
+++ b/Master/texmf-dist/doc/latex/sagetex/README
@@ -3,13 +3,21 @@ computations, and plots from the Sage mathematics software suite
(http://sagemath.org) into LaTeX documents.
====================================================================
-To use SageTeX, you need the files sagetex.sty and sagetex.py. If those
-haven't been extracted from the .dtx file, you'll need to do:
+The recommended way to acquire and install SageTeX is by installing the
+Sage spkg; visit http://sagemath.org/packages/optional/, find the
+current version number, and run "sage -i sagetex-[version]" in a
+terminal. Then you'll need to make the file sagetex.sty known to TeX;
+that file will be in SAGE_ROOT/local/share/texmf/tex/generic/sagetex,
+along with documentation and examples.
+
+If you can't or don't want to install SageTeX by using Sage, you can use
+this CTAN package. If sagetex.py and sagetex.sty haven't been extracted
+from the .dtx file, you'll need to do:
0. Run `latex sagetexpackage.ins'
If a PDF file of the documentation wasn't included with this
-distribution of SageTex, you will need to build the documentation
+distribution of SageTeX, you will need to build the documentation
yourself. To do that:
1. Run `latex sagetexpackage.dtx'
@@ -30,7 +38,12 @@ the documentation.)
To use the SageTeX package with your own documents, see the
"Installation" section of the documentation.
-This works builds on a lot of work by others; see the "Credits" section
+SageTeX now includes `remote-sagetex.py', a plain Python script that
+allows you to use a remote Sage server instead of a local Sage
+installation, so now you can use SageTeX on any computer with TeX and
+Python 2.6 installed.
+
+This work builds on a lot of work by others; see the "Credits" section
of the documentation for credits. The source code may be modified and
distributed under the terms of the GPL, v2 or later; the documentation
may be modified and distributed under a Creative Commons Attribution -
@@ -40,4 +53,4 @@ section of the documentation.
Please let me know if you find any bugs or have any ideas for
improvement!
-- Dan Drake <ddrake@member.ams.org>
+- Dan Drake <http://mathsci.kaist.ac.kr/~drake/>
diff --git a/Master/texmf-dist/doc/latex/sagetex/example.pdf b/Master/texmf-dist/doc/latex/sagetex/example.pdf
index 52b3ba0e34a..270018177db 100644
--- a/Master/texmf-dist/doc/latex/sagetex/example.pdf
+++ b/Master/texmf-dist/doc/latex/sagetex/example.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/sagetex/example.tex b/Master/texmf-dist/doc/latex/sagetex/example.tex
index 0f84e3152e6..d9c67589fbc 100644
--- a/Master/texmf-dist/doc/latex/sagetex/example.tex
+++ b/Master/texmf-dist/doc/latex/sagetex/example.tex
@@ -1,32 +1,39 @@
% General example LaTeX file for including Sage calculations and plots
-% Build with: (pdf)latex example.tex; sage example.sage; pdflatex
-% example.tex Please read README and the documentation of the SageTeX
-% package for more information!
+% Build with:
+%
+% (pdf)latex example.tex; sage example.sage; pdflatex example.tex
+%
+% Please read README and the documentation of the SageTeX package for
+% more information!
\documentclass{article}
-\title{Examples of embedding Sage in \LaTeX}
-\author{}
-
+\title{Examples of embedding Sage in \LaTeX{} with \textsf{Sage\TeX}}
+\author{Dan Drake and others}
+\usepackage{amsmath}
\usepackage{sagetex}
-%
-% If you want sagetex to use Imagemagick's convert utility to make eps
-% files from png files when generating a dvi file, add the
-% "imagemagick" option above:
+%
+% If you want SageTeX to use Imagemagick's `convert' utility to make eps
+% files from png files when generating a dvi file, add the "imagemagick"
+% option above:
%
% \usepackage[imagemagick]{sagetex}
+\setlength{\sagetexindent}{10ex}
+
\begin{document}
\maketitle
\section{Inline Sage, code blocks}
This is an example $2+2=\sage{2+2}$. If you raise the current year mod
-$100$ ($\sage{mod(\the\year, 100)}$) to the power of the current day
-($\the\day$), you get $\sage{Integer(mod(\the\year, 100))^\the\day}$.
-Also, $\the\year$ modulo $42$ is $\sage{\the\year \percent 42}$.
+$100$ (which equals $\sage{mod(\the\year, 100)}$) to the power of the
+current day ($\the\day$), you get $\sage{Integer(mod(\the\year,
+100))^\the\day}$. Also, $\the\year$ modulo $42$ is $\sage{\the\year
+\percent 42}$.
Code block which uses a variable \texttt{s} to store the solutions:
\begin{sageblock}
+ 1+1
var('a,b,c')
eqn = [a+b*c==1, b-a*c==0, a+b==5]
s = solve(eqn, a,b,c)
@@ -46,8 +53,8 @@ E = EllipticCurve("37a")
\end{sageblock}
You can't do assignment inside \verb|\sage| macros, since Sage doesn't
know how to typeset the output of such a thing. So you have to use a
-code block. The elliptic curve $E$ given by $\sage{E}$
-has discriminant $\sage{E.discriminant()}$.
+code block. The elliptic curve $E$ given by $\sage{E}$ has discriminant
+$\sage{E.discriminant()}$.
You can do anything in a code block that you can do in Sage and/or
Python. Here we save an elliptic curve into a file.
@@ -60,8 +67,8 @@ except IOError:
E.save('E2')
\end{sageblock}
-The 9999th Fourier coefficient of $\sage{E}$ is
-$\sage{E.anlist(100000)[9999]}$.
+The 9999th Fourier coefficient of $\sage{E}$ is
+$\sage{E.anlist(100000)[9999]}$.
The following code block doesn't appear in the typeset file\dots
\begin{sagesilent}
@@ -72,9 +79,9 @@ but we can refer to whatever we did in that code block: $e=\sage{e}$.
\begin{sageblock}
var('x')
- f = log(sin(x)/x)
+ f(x) = log(sin(x)/x)
\end{sageblock}
-The Taylor Series of $f$ is: $\sage{ f.taylor(x, 0, 10) }$.
+The Taylor Series of $f$ begins: $\sage{ f.taylor(x, 0, 10) }$.
\section{Plotting}
@@ -83,8 +90,10 @@ Here's a plot of the elliptic curve $E$.
\sageplot{E.plot(-3,3)}
\begin{sagesilent}
+ # the var line is unecessary unless you've defined x to be something
+ # other than a symbolic variable
var('x')
- f=-x^3+3*x^2+7*x-4
+ f(x) = -x^3+3*x^2+7*x-4
\end{sagesilent}
You can use variables to hold plot objects and do stuff with them.
@@ -94,7 +103,7 @@ You can use variables to hold plot objects and do stuff with them.
Here's a small plot of $f$ from $-5$ to $5$, which I've centered:
-\centerline{\sageplot[scale=.2]{p}}
+\begin{center} \sageplot[scale=.2]{p} \end{center}
On second thought, use the default size of $3/4$ the \verb|\textwidth|
and don't use axes:
@@ -120,7 +129,7 @@ almost all situations. (Although see the section on 3D plotting.)
\sageplot[angle=45, width=.5\textwidth][png]{plot1}
If you use regular \verb|latex| to make a DVI file, you'll see a box,
-beause DVI files can't include PNG files. If you use \verb|pdflatex|
+because DVI files can't include PNG files. If you use \verb|pdflatex|
that will work. See the documentation for details.
When using \verb|\sageplot|, you can pass in just about anything that
@@ -160,12 +169,15 @@ And here's the picture:
\sageplot{matrixprogram}
+Reset \texttt{x} in Sage so that it's not a generator for the polynomial
+ring: \sage{var('x')}
+
\subsection{3D plotting}
3D plotting right now is problematic because there's no convenient way
to produce vector graphics. We can make PNGs, though, and since the
\verb|sageplot| command defaults to EPS and PDF, \emph{you must specify
-a valid format for 3D plotting}. Sage right now (version 2.10.3) can't
+a valid format for 3D plotting}. Sage right now (version 3.4.2) can't
produce EPS or PDF files from plot3d objects, so if you don't specify a
valid format, things will go badly. You can specify the
``\texttt{imagemagick}'' option, which will use the Imagemagick
@@ -182,4 +194,71 @@ Here's the famous Sage cube graph:
% passing an option to includegraphics
\sageplot[][png]{G.plot3d(engine='tachyon')}
+\section{Pausing Sage\TeX}
+\label{sec:pausing-sagetex}
+
+Sometimes you want to ``pause'' for a bit while writing your document if
+you have embedded a long calculation or just want to concentrate on the
+\LaTeX{} and ignore any Sage stuff. You can use the \verb|\sagetexpause|
+and \verb|\sagetexunpause| macros to do that.
+
+\sagetexpause
+
+A calculation: $\sage{factor(2^325 + 1)}$ and a code environment that
+simulates a time-consuming calculation. While paused, this will get
+skipped over.
+\begin{sageblock}
+ import time
+ time.sleep(15)
+\end{sageblock}
+
+Graphics are also skipped: \sageplot{plot(2*sin(x^2) + x^2, (x, 0, 5))}
+
+\sagetexunpause
+
+\section{Make Sage write your \LaTeX{} for you}
+
+With \textsf{Sage\TeX}, you can not only have Sage do your math for you,
+it can write parts of your \LaTeX{} document for you! For example, I
+hate writing \texttt{tabular} environments; there's too many fiddly
+little bits of punctuation and whatnot\ldots and what if you want to add
+a column? It's a pain---or rather, it \emph{was} a pain. Here's how to
+make Pascal's triangle. It requires the \texttt{amsmath} package because
+of what Sage does when producing a \LaTeX{} representation of a string.
+(It puts it inside a \verb|\text| macro.)
+
+\begin{sageblock}
+def pascals_triangle(n):
+ # start of the table
+ s = r"\begin{tabular}{cc|" + "r" * (n+1) + "}"
+ s += r" & & $k$: & \\"
+ # second row, with k values:
+ s += r" & "
+ for k in [0..n]:
+ s += "& %d " % k
+ s += r"\\"
+ # the n = 0 row:
+ s += r"\hline" + "\n" + r"$n$: & 0 & 1 & \\"
+ # now the rest of the rows
+ for r in [1..n]:
+ s += " & %d " % r
+ for k in [0..r]:
+ s += "& %d " % binomial(r, k)
+ s += r"\\"
+ # add the last line and return
+ s += r"\end{tabular}"
+ return s
+
+# how big should the table be?
+n = 8
+\end{sageblock}
+
+Okay, now here's the table. To change the size, edit \texttt{n} above.
+If you have several tables, you can use this to get them all the same
+size, while changing only one thing.
+
+\begin{center}
+ \sage{pascals_triangle(n)}
+\end{center}
+
\end{document}
diff --git a/Master/texmf-dist/doc/latex/sagetex/extractsagecode.py b/Master/texmf-dist/doc/latex/sagetex/extractsagecode.py
new file mode 100644
index 00000000000..62200d42d68
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/sagetex/extractsagecode.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+##
+## This is file `extractsagecode.py',
+## generated with the docstrip utility.
+##
+## The original source files were:
+##
+## scripts.dtx (with options: `extractscript')
+##
+## This is a generated file. It is part of the SageTeX package.
+##
+## Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
+##
+## 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 of the License, 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 should have received a copy of the GNU General Public License along
+## with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+import sys
+import time
+import getopt
+import os.path
+from sagetexparse import SageCodeExtractor
+
+def usage():
+ print("""Usage: %s [-h|--help] [-o|--overwrite] inputfile [outputfile]
+
+Extracts Sage code from `inputfile'.
+
+`inputfile' can include the .tex extension or not. If you provide
+`outputfile', the results will be written to a file of that name,
+otherwise the result will be printed to stdout.
+
+Specify `-o' or `--overwrite' to overwrite the file if it exists.
+
+See the SageTeX documentation for more details.""" % sys.argv[0])
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], 'ho', ['help', 'overwrite'])
+except getopt.GetoptError, err:
+ print str(err)
+ usage()
+ sys.exit(2)
+
+overwrite = False
+for o, a in opts:
+ if o in ('-h', '--help'):
+ usage()
+ sys.exit()
+ elif o in ('-o', '--overwrite'):
+ overwrite = True
+
+if len(args) == 0 or len(args) > 2:
+ print('Error: wrong number of arguments. Make sure to specify options first.\n')
+ usage()
+ sys.exit(2)
+
+if len(args) == 2 and (os.path.exists(args[1]) and not overwrite):
+ print('Error: %s exists and overwrite option not specified.' % args[1])
+ sys.exit(1)
+
+src, ext = os.path.splitext(args[0])
+sagecode = SageCodeExtractor(src)
+header = """\
+# This file contains Sage code extracted from %s%s.
+# Processed %s.
+
+""" % (src, ext, time.strftime('%a %d %b %Y %H:%M:%S', time.localtime()))
+
+if len(args) == 2:
+ dest = open(args[1], 'w')
+else:
+ dest = sys.stdout
+
+dest.write(header)
+dest.write(sagecode.result)
diff --git a/Master/texmf-dist/doc/latex/sagetex/makestatic.py b/Master/texmf-dist/doc/latex/sagetex/makestatic.py
new file mode 100644
index 00000000000..2121d9b78c5
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/sagetex/makestatic.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+##
+## This is file `makestatic.py',
+## generated with the docstrip utility.
+##
+## The original source files were:
+##
+## scripts.dtx (with options: `staticscript')
+##
+## This is a generated file. It is part of the SageTeX package.
+##
+## Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
+##
+## 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 of the License, 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 should have received a copy of the GNU General Public License along
+## with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+import sys
+import time
+import getopt
+import os.path
+from sagetexparse import DeSageTex
+
+def usage():
+ print("""Usage: %s [-h|--help] [-o|--overwrite] inputfile [outputfile]
+
+Removes SageTeX macros from `inputfile' and replaces them with the
+Sage-computed results to make a "static" file. You'll need to have run
+Sage on `inputfile' already.
+
+`inputfile' can include the .tex extension or not. If you provide
+`outputfile', the results will be written to a file of that name.
+Specify `-o' or `--overwrite' to overwrite the file if it exists.
+
+See the SageTeX documentation for more details.""" % sys.argv[0])
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], 'ho', ['help', 'overwrite'])
+except getopt.GetoptError, err:
+ print str(err)
+ usage()
+ sys.exit(2)
+
+overwrite = False
+for o, a in opts:
+ if o in ('-h', '--help'):
+ usage()
+ sys.exit()
+ elif o in ('-o', '--overwrite'):
+ overwrite = True
+
+if len(args) == 0 or len(args) > 2:
+ print('Error: wrong number of arguments. Make sure to specify options first.\n')
+ usage()
+ sys.exit(2)
+
+if len(args) == 2 and (os.path.exists(args[1]) and not overwrite):
+ print('Error: %s exists and overwrite option not specified.' % args[1])
+ sys.exit(1)
+
+src, ext = os.path.splitext(args[0])
+desagetexed = DeSageTex(src)
+header = """\
+## SageTeX commands have been automatically removed from this file and
+## replaced with plain LaTeX. Processed %s.
+
+""" % time.strftime('%a %d %b %Y %H:%M:%S', time.localtime())
+
+if len(args) == 2:
+ dest = open(args[1], 'w')
+else:
+ dest = sys.stdout
+
+dest.write(header)
+dest.write(desagetexed.result)
diff --git a/Master/texmf-dist/doc/latex/sagetex/remote-sagetex.py b/Master/texmf-dist/doc/latex/sagetex/remote-sagetex.py
new file mode 100644
index 00000000000..e8946bd1814
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/sagetex/remote-sagetex.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python
+##
+## This is file `remote-sagetex.py',
+## generated with the docstrip utility.
+##
+## The original source files were:
+##
+## remote-sagetex.dtx (with options: `remotesagetex')
+##
+## This is a generated file. It is part of the SageTeX package.
+##
+## Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
+##
+## 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 of the License, 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 should have received a copy of the GNU General Public License along
+## with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+from __future__ import print_function
+import json
+import sys
+import time
+import re
+import urllib
+import hashlib
+import os
+import os.path
+import shutil
+import getopt
+from contextlib import closing
+
+#########################################################################
+# You can provide a filename here and the script will read your login #
+# information from that file. The format must be: #
+# #
+# server = 'http://foo.com:8000' #
+# username = 'my_name' #
+# password = 's33krit' #
+# #
+# You can omit one or more of those lines, use " quotes, and put hash #
+# marks at the beginning of a line for comments. Command-line args #
+# take precedence over information from the file. #
+#########################################################################
+login_info_file = None # e.g. '/home/foo/Private/sagetex-login.txt'
+
+usage = """Process a SageTeX-generated .sage file using a remote Sage server.
+
+Usage: {0} [options] inputfile.sage
+
+Options:
+
+ -h, --help: print this message
+ -s, --server: the Sage server to contact
+ -u, --username: username on the server
+ -p, --password: your password
+ -f, --file: get login information from a file
+
+If the server does not begin with the four characters `http', then
+`https://' will be prepended to the server name.
+
+You can hard-code the filename from which to read login information into
+the remote-sagetex script. Command-line arguments take precedence over
+the contents of that file. See the SageTeX documentation for formatting
+details.
+
+If any of the server, username, and password are omitted, you will be
+asked to provide them.
+
+See the SageTeX documentation for more details on usage and limitations
+of remote-sagetex.""".format(sys.argv[0])
+
+server, username, password = (None,) * 3
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], 'hs:u:p:f:',
+ ['help', 'server=', 'user=', 'password=', 'file='])
+except getopt.GetoptError as err:
+ print(str(err), usage, sep='\n\n')
+ sys.exit(2)
+
+for o, a in opts:
+ if o in ('-h', '--help'):
+ print(usage)
+ sys.exit()
+ elif o in ('-s', '--server'):
+ server = a
+ elif o in ('-u', '--user'):
+ username = a
+ elif o in ('-p', '--password'):
+ password = a
+ elif o in ('-f', '--file'):
+ login_info_file = a
+
+if len(args) != 1:
+ print('Error: must specify exactly one file. Please specify options first.',
+ usage, sep='\n\n')
+ sys.exit(2)
+
+jobname = os.path.splitext(args[0])[0]
+traceback_str = 'Exception in SageTeX session {0}:'.format(time.time())
+def parsedotsage(fn):
+ with open(fn, 'r') as f:
+ inline = re.compile(r" _st_.inline\((?P<num>\d+), (?P<code>.*)\)")
+ plot = re.compile(r" _st_.plot\((?P<num>\d+), (?P<code>.*)\)")
+ goboom = re.compile(r" _st_.goboom\((?P<num>\d+)\)")
+ pausemsg = re.compile(r"print.'(?P<msg>SageTeX (un)?paused.*)'")
+ blockbegin = re.compile(r"_st_.blockbegin\(\)")
+ ignore = re.compile(r"(try:)|(except):")
+ in_comment = False
+ in_block = False
+ cmds = []
+ for line in f.readlines():
+ if line.startswith('"""'):
+ in_comment = not in_comment
+ elif not in_comment:
+ m = pausemsg.match(line)
+ if m:
+ cmds.append({'type': 'pause',
+ 'msg': m.group('msg')})
+ m = inline.match(line)
+ if m:
+ cmds.append({'type': 'inline',
+ 'num': m.group('num'),
+ 'code': m.group('code')})
+ m = plot.match(line)
+ if m:
+ cmds.append({'type': 'plot',
+ 'num': m.group('num'),
+ 'code': m.group('code')})
+ m = goboom.match(line)
+ if m:
+ cmds[-1]['goboom'] = m.group('num')
+ if in_block:
+ in_block = False
+ if in_block and not ignore.match(line):
+ cmds[-1]['code'] += line
+ if blockbegin.match(line):
+ cmds.append({'type': 'block',
+ 'code': ''})
+ in_block = True
+ return cmds
+debug = False
+class RemoteSage:
+ def __init__(self, server, user, password):
+ self._srv = server.rstrip('/')
+ sep = '___S_A_G_E___'
+ self._response = re.compile('(?P<header>.*)' + sep +
+ '\n*(?P<output>.*)', re.DOTALL)
+ self._404 = re.compile('404 Not Found')
+ self._session = self._get_url('login',
+ urllib.urlencode({'username': user,
+ 'password':
+ password}))['session']
+ self._codewrap = """try:
+{{0}}
+except:
+ print('{0}')
+ traceback.print_exc()""".format(traceback_str)
+ self.do_block("""
+ import traceback
+ def __st_plot__(counter, _p_, format='notprovided', **kwargs):
+ if format == 'notprovided':
+ formats = ['eps', 'pdf']
+ else:
+ formats = [format]
+ for fmt in formats:
+ plotfilename = 'plot-%s.%s' % (counter, fmt)
+ _p_.save(filename=plotfilename, **kwargs)""")
+
+ def _encode(self, d):
+ return 'session={0}&'.format(self._session) + urllib.urlencode(d)
+
+ def _get_url(self, action, u):
+ with closing(urllib.urlopen(self._srv + '/simple/' + action +
+ '?' + u)) as h:
+ data = self._response.match(h.read())
+ result = json.loads(data.group('header'))
+ result['output'] = data.group('output').rstrip()
+ return result
+
+ def _get_file(self, fn, cell, ofn=None):
+ with closing(urllib.urlopen(self._srv + '/simple/' + 'file' + '?' +
+ self._encode({'cell': cell, 'file': fn}))) as h:
+ myfn = ofn if ofn else fn
+ data = h.read()
+ if not self._404.search(data):
+ with open(myfn, 'w') as f:
+ f.write(data)
+ else:
+ print('Remote server reported {0} could not be found:'.format(
+ fn))
+ print(data)
+ def _do_cell(self, code):
+ realcode = self._codewrap.format(code)
+ result = self._get_url('compute', self._encode({'code': realcode}))
+ if result['status'] == 'computing':
+ cell = result['cell_id']
+ while result['status'] == 'computing':
+ sys.stdout.write('working...')
+ sys.stdout.flush()
+ time.sleep(10)
+ result = self._get_url('status', self._encode({'cell': cell}))
+ if debug:
+ print('cell: <<<', realcode, '>>>', 'result: <<<',
+ result['output'], '>>>', sep='\n')
+ return result
+
+ def do_inline(self, code):
+ return self._do_cell(' print(latex({0}))'.format(code))
+
+ def do_block(self, code):
+ result = self._do_cell(code)
+ for fn in result['files']:
+ self._get_file(fn, result['cell_id'])
+ return result
+
+ def do_plot(self, num, code, plotdir):
+ result = self._do_cell(' __st_plot__({0}, {1})'.format(num, code))
+ for fn in result['files']:
+ self._get_file(fn, result['cell_id'], os.path.join(plotdir, fn))
+ return result
+ def close(self):
+ sys.stdout.write('Logging out of {0}...'.format(server))
+ sys.stdout.flush()
+ self._get_url('logout', self._encode({}))
+ print('done')
+def do_plot_setup(plotdir):
+ printc('initializing plots directory...')
+ if os.path.isdir(plotdir):
+ shutil.rmtree(plotdir)
+ os.mkdir(plotdir)
+ return True
+
+did_plot_setup = False
+plotdir = 'sage-plots-for-' + jobname + '.tex'
+
+def labelline(n, s):
+ return r'\newlabel{@sageinline' + str(n) + '}{{' + s + '}{}{}{}{}}\n'
+
+def printc(s):
+ print(s, end='')
+ sys.stdout.flush()
+
+error = re.compile("(^" + traceback_str + ")|(^Syntax Error:)", re.MULTILINE)
+
+def check_for_error(string, line):
+ if error.search(string):
+ print("""
+**** Error in Sage code on line {0} of {1}.tex!
+{2}
+**** Running Sage on {1}.sage failed! Fix {1}.tex and try again.""".format(
+ line, jobname, string))
+ sys.exit(1)
+print('Processing Sage code for {0}.tex using remote Sage server.'.format(
+ jobname))
+
+if login_info_file:
+ with open(login_info_file, 'r') as f:
+ print('Reading login information from {0}.'.format(login_info_file))
+ get_val = lambda x: x.split('=')[1].strip().strip('\'"')
+ for line in f:
+ print(line)
+ if not line.startswith('#'):
+ if line.startswith('server') and not server:
+ server = get_val(line)
+ if line.startswith('username') and not username:
+ username = get_val(line)
+ if line.startswith('password') and not password:
+ password = get_val(line)
+
+if not server:
+ server = raw_input('Enter server: ')
+
+if not server.startswith('http'):
+ server = 'https://' + server
+
+if not username:
+ username = raw_input('Enter username: ')
+
+if not password:
+ from getpass import getpass
+ password = getpass('Please enter password for user {0} on {1}: '.format(
+ username, server))
+
+printc('Parsing {0}.sage...'.format(jobname))
+cmds = parsedotsage(jobname + '.sage')
+print('done.')
+
+sout = '% This file was *autogenerated* from the file {0}.sage.\n'.format(
+ os.path.splitext(jobname)[0])
+
+printc('Logging into {0} and starting session...'.format(server))
+with closing(RemoteSage(server, username, password)) as sage:
+ print('done.')
+ for cmd in cmds:
+ if cmd['type'] == 'inline':
+ printc('Inline formula {0}...'.format(cmd['num']))
+ result = sage.do_inline(cmd['code'])
+ check_for_error(result['output'], cmd['goboom'])
+ sout += labelline(cmd['num'], result['output'])
+ print('done.')
+ if cmd['type'] == 'block':
+ printc('Code block begin...')
+ result = sage.do_block(cmd['code'])
+ check_for_error(result['output'], cmd['goboom'])
+ print('end.')
+ if cmd['type'] == 'plot':
+ printc('Plot {0}...'.format(cmd['num']))
+ if not did_plot_setup:
+ did_plot_setup = do_plot_setup(plotdir)
+ result = sage.do_plot(cmd['num'], cmd['code'], plotdir)
+ check_for_error(result['output'], cmd['goboom'])
+ print('done.')
+ if cmd['type'] == 'pause':
+ print(cmd['msg'])
+ if int(time.time()) % 2280 == 0:
+ printc('Unscheduled offworld activation; closing iris...')
+ time.sleep(1)
+ print('end.')
+
+with open(jobname + '.sage', 'r') as sagef:
+ h = hashlib.md5()
+ for line in sagef:
+ if (not line.startswith(' _st_.goboom') and
+ not line.startswith("print 'SageT")):
+ h.update(line)
+ sout += """%{0}% md5sum of corresponding .sage file
+{1} (minus "goboom" and pause/unpause lines)
+""".format(h.hexdigest(), '%')
+
+printc('Writing .sout file...')
+with open(jobname + '.sout', 'w') as soutf:
+ soutf.write(sout)
+ print('done.')
+print('Sage processing complete. Run LaTeX on {0}.tex again.'.format(jobname))
+
diff --git a/Master/texmf-dist/doc/latex/sagetex/sagetex.py b/Master/texmf-dist/doc/latex/sagetex/sagetex.py
index 2686b4348f5..576847894f7 100644
--- a/Master/texmf-dist/doc/latex/sagetex/sagetex.py
+++ b/Master/texmf-dist/doc/latex/sagetex/sagetex.py
@@ -1,38 +1,39 @@
-"""
-%%
-%% This is file `sagetex.py',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% sagetexpackage.dtx (with options: `python')
-%%
-%% This is a generated file.
-%%
-%% Copyright (C) 2008 by Dan Drake <ddrake@member.ams.org>
-%%
-%% 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 of the License, 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 should have received a copy of the GNU General Public License along
-%% with this program. If not, see <http://www.gnu.org/licenses/>
-%%
+##
+## This is file `sagetex.py',
+## generated with the docstrip utility.
+##
+## The original source files were:
+##
+## sagetexpackage.dtx (with options: `python')
+## py-and-sty.dtx (with options: `python')
+##
+## This is a generated file. It is part of the SageTeX package.
+##
+## Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
+##
+## 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 of the License, 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 should have received a copy of the GNU General Public License along
+## with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+__version__ = """
+ [2009/06/17 v2.2.1 embedding Sage into LaTeX documents]
"""
import sys
if __name__ == "__main__":
print("""This file is part of the SageTeX package.
It is not meant to be called directly.
-This file will be used by Sage scripts generated from a LaTeX document
-using the sagetex package. Keep it somewhere where Sage and Python can
-find it and it will automatically be imported.""")
+This file will be automatically used by Sage scripts generated from a
+LaTeX document using the SageTeX package.""")
sys.exit()
from sage.misc.latex import latex
import os
@@ -41,86 +42,83 @@ import hashlib
import traceback
import subprocess
import shutil
-initplot_done = False
-dirname = None
-filename = ""
-def progress(t,linebreak=True):
- if linebreak:
- print(t)
- else:
- sys.stdout.write(t)
-def openout(f):
- global filename
- filename = f
- global _file_
- _file_ = open(f + '.sout.tmp', 'w')
- s = '% This file was *autogenerated* from the file ' + \
- os.path.splitext(filename)[0] + '.sage.\n'
- _file_.write(s)
- progress('Processing Sage code for %s.tex...' % filename)
-def initplot(f):
- global initplot_done
- if not initplot_done:
- progress('Initializing plots directory')
- global dirname
- dirname = 'sage-plots-for-' + f + '.tex'
- if os.path.isdir(dirname):
- shutil.rmtree(dirname)
- os.mkdir(dirname)
- initplot_done = True
-def inline(counter, s):
- progress('Inline formula %s' % counter)
- _file_.write('\\newlabel{@sagelabel' + str(counter) + '}{{' + \
- latex(s) + '}{}{}{}{}}\n')
-def blockbegin():
- progress('Code block begin...', False)
-def blockend():
- progress('end')
-def plot(counter, p, format='notprovided', epsmagick=False, **kwargs):
- global dirname
- progress('Plot %s' % counter)
- if format == 'notprovided':
- formats = ['eps', 'pdf']
- else:
- formats = [format]
- for fmt in formats:
- plotfilename = os.path.join(dirname, 'plot-%s.%s' % (counter, fmt))
- #print(' plotting %s with args %s' % (plotfilename, kwargs))
- p.save(filename=plotfilename, **kwargs)
- if format != 'notprovided' and epsmagick is True:
- print('Calling Imagemagick to convert plot-%s.%s to EPS' % \
- (counter, format))
- toeps(counter, format)
-def toeps(counter, ext):
- global dirname
- subprocess.check_call(['convert',\
- '%s/plot-%s.%s' % (dirname, counter, ext), \
- '%s/plot-%s.eps' % (dirname, counter)])
-def goboom(line):
- global filename
- print('\n**** Error in Sage code on line %s of %s.tex! Traceback\
- follows.' % (line, filename))
- traceback.print_exc()
- print('\n**** Running Sage on %s.sage failed! Fix %s.tex and try\
- again.' % (filename, filename))
- os.remove(filename + '.sout.tmp')
- sys.exit(1)
-def endofdoc():
- global filename
- sagef = open(filename + '.sage', 'r')
- m = hashlib.md5()
- for line in sagef:
- if line[0:15] != ' sagetex.goboom':
- m.update(line)
- s = '%' + m.hexdigest() + '% md5sum of .sage file (minus "goboom" \
-lines) that produced this\n'
- _file_.write(s)
- _file_.close()
- os.rename(filename + '.sout.tmp', filename + '.sout')
- progress('Sage processing complete. Run LaTeX on %s.tex again.' %\
- filename)
-"""
-\endinput
-%%
-%% End of file `sagetex.py'.
-"""
+class SageTeXProcessor():
+ def __init__(self, jobname):
+ self.progress('Processing Sage code for %s.tex...' % jobname)
+ self.didinitplot = False
+ self.useimagemagick = False
+ self.useepstopdf = False
+ self.plotdir = 'sage-plots-for-' + jobname + '.tex'
+ self.filename = jobname
+ self.souttmp = open(self.filename + '.sout.tmp', 'w')
+ s = '% This file was *autogenerated* from the file ' + \
+ os.path.splitext(jobname)[0] + '.sage.\n'
+ self.souttmp.write(s)
+ def progress(self, t,linebreak=True):
+ if linebreak:
+ print(t)
+ else:
+ sys.stdout.write(t)
+ sys.stdout.flush()
+ def initplot(self):
+ self.progress('Initializing plots directory')
+ if os.path.isdir(self.plotdir):
+ shutil.rmtree(self.plotdir)
+ os.mkdir(self.plotdir)
+ self.didinitplot = True
+ def inline(self, counter, s):
+ self.progress('Inline formula %s' % counter)
+ self.souttmp.write('\\newlabel{@sageinline' + str(counter) + '}{{' + \
+ latex(s).rstrip() + '}{}{}{}{}}\n')
+ def blockbegin(self):
+ self.progress('Code block begin...', False)
+ def blockend(self):
+ self.progress('end')
+ def plot(self, counter, _p_, format='notprovided', **kwargs):
+ if not self.didinitplot:
+ self.initplot()
+ self.progress('Plot %s' % counter)
+ if format == 'notprovided':
+ formats = ['eps', 'pdf']
+ else:
+ formats = [format]
+ for fmt in formats:
+ if fmt == 'pdf' and self.useepstopdf:
+ epsfile = os.path.join(self.plotdir, 'plot-%s.eps' % counter)
+ self.progress('Calling epstopdf to convert plot-%s.eps to PDF' % \
+ counter)
+ subprocess.check_call(['epstopdf', epsfile])
+ continue
+ plotfilename = os.path.join(self.plotdir, 'plot-%s.%s' % (counter, fmt))
+ _p_.save(filename=plotfilename, **kwargs)
+ if format != 'notprovided' and self.useimagemagick:
+ self.progress('Calling Imagemagick to convert plot-%s.%s to EPS' % \
+ (counter, format))
+ self.toeps(counter, format)
+ def toeps(self, counter, ext):
+ subprocess.check_call(['convert',\
+ '%s/plot-%s.%s' % (self.plotdir, counter, ext), \
+ '%s/plot-%s.eps' % (self.plotdir, counter)])
+ def goboom(self, line):
+ print('\n**** Error in Sage code on line %s of %s.tex! Traceback\
+ follows.' % (line, self.filename))
+ traceback.print_exc()
+ print('\n**** Running Sage on %s.sage failed! Fix %s.tex and try\
+ again.' % ((self.filename,) * 2))
+ self.souttmp.close()
+ os.remove(self.filename + '.sout.tmp')
+ sys.exit(int(1))
+ def endofdoc(self):
+ sagef = open(self.filename + '.sage', 'r')
+ m = hashlib.md5()
+ for line in sagef:
+ if line[0:12] != " _st_.goboom" and line[0:12] != "print 'SageT":
+ m.update(line)
+ s = '%' + m.hexdigest() + '% md5sum of corresponding .sage file\
+ (minus "goboom" and pause/unpause lines)\n'
+ self.souttmp.write(s)
+ self.souttmp.close()
+ os.rename(self.filename + '.sout.tmp', self.filename + '.sout')
+ self.progress('Sage processing complete. Run LaTeX on %s.tex again.' %\
+ self.filename)
+
diff --git a/Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdf b/Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdf
index 43a32df1580..2f9fc546ecd 100644
--- a/Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdf
+++ b/Master/texmf-dist/doc/latex/sagetex/sagetexpackage.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/sagetex/sagetexparse.py b/Master/texmf-dist/doc/latex/sagetex/sagetexparse.py
new file mode 100644
index 00000000000..c1927348032
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/sagetex/sagetexparse.py
@@ -0,0 +1,151 @@
+##
+## This is file `sagetexparse.py',
+## generated with the docstrip utility.
+##
+## The original source files were:
+##
+## scripts.dtx (with options: `parsermod')
+##
+## This is a generated file. It is part of the SageTeX package.
+##
+## Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
+##
+## 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 of the License, 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 should have received a copy of the GNU General Public License along
+## with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+import sys
+from pyparsing import *
+def skipToMatching(opener, closer):
+ nest = nestedExpr(opener, closer)
+ nest.setParseAction(lambda l, s, t: l[s:getTokensEndLoc()])
+ return nest
+
+curlybrackets = skipToMatching('{', '}')
+squarebrackets = skipToMatching('[', ']')
+sagemacroparser = r'\sage' + curlybrackets('code')
+sageplotparser = (r'\sageplot'
+ + Optional(squarebrackets)('opts')
+ + Optional(squarebrackets)('format')
+ + curlybrackets('code'))
+sagetexpause = Literal(r'\sagetexpause')
+sagetexunpause = Literal(r'\sagetexunpause')
+class SoutParser():
+ def __init__(self, fn):
+ self.label = []
+ parselabel = (r'\newlabel{@sageinline'
+ + Word(nums)('num')
+ + '}{'
+ + curlybrackets('result')
+ + '{}{}{}{}}')
+ parselabel.ignore('%' + restOfLine)
+ parselabel.setParseAction(self.newlabel)
+ try:
+ OneOrMore(parselabel).parseFile(fn)
+ except IOError:
+ print 'Error accessing %s; exiting. Does your .sout file exist?' % fn
+ sys.exit(1)
+ def newlabel(self, s, l, t):
+ self.label.append(t.result[1:-1])
+class DeSageTex():
+ def __init__(self, fn):
+ self.sagen = 0
+ self.plotn = 0
+ self.fn = fn
+ self.sout = SoutParser(fn + '.sout')
+ smacro = sagemacroparser
+ smacro.setParseAction(self.sage)
+ usepackage = (r'\usepackage'
+ + Optional(squarebrackets)
+ + '{sagetex}')
+ usepackage.setParseAction(replaceWith(r"""% "\usepackage{sagetex}" line was here:
+\RequirePackage{verbatim}
+\RequirePackage{graphicx}
+\newcommand{\sagetexpause}{\relax}
+\newcommand{\sagetexunpause}{\relax}"""))
+ splot = sageplotparser
+ splot.setParseAction(self.plot)
+ beginorend = oneOf('begin end')
+ blockorverb = 'sage' + oneOf('block verbatim')
+ blockorverb.setParseAction(replaceWith('verbatim'))
+ senv = '\\' + beginorend + '{' + blockorverb + '}'
+ silent = Literal('sagesilent')
+ silent.setParseAction(replaceWith('comment'))
+ ssilent = '\\' + beginorend + '{' + silent + '}'
+ stexindent = Suppress(r'\setlength{\sagetexindent}' + curlybrackets)
+ doit = smacro | senv | ssilent | usepackage | splot | stexindent
+ doit.ignore('%' + restOfLine)
+ doit.ignore(r'\begin{verbatim}' + SkipTo(r'\end{verbatim}'))
+ doit.ignore(r'\begin{comment}' + SkipTo(r'\end{comment}'))
+ doit.ignore(r'\sagetexpause' + SkipTo(r'\sagetexunpause'))
+ str = ''.join(open(fn + '.tex', 'r').readlines())
+ self.result = doit.transformString(str)
+ def sage(self, s, l, t):
+ self.sagen += 1
+ return self.sout.label[self.sagen - 1]
+ def plot(self, s, l, t):
+ self.plotn += 1
+ if len(t.opts) == 0:
+ opts = r'[width=.75\textwidth]'
+ else:
+ opts = t.opts[0]
+ return (r'\includegraphics%s{sage-plots-for-%s.tex/plot-%s}' %
+ (opts, self.fn, self.plotn - 1))
+class SageCodeExtractor():
+ def __init__(self, fn):
+ smacro = sagemacroparser
+ smacro.setParseAction(self.macroout)
+
+ splot = sageplotparser
+ splot.setParseAction(self.plotout)
+ env_names = oneOf('sageblock sageverbatim sagesilent')
+ senv = r'\begin{' + env_names('env') + '}' + SkipTo(
+ r'\end{' + matchPreviousExpr(env_names) + '}')('code')
+ senv.leaveWhitespace()
+ senv.setParseAction(self.envout)
+
+ spause = sagetexpause
+ spause.setParseAction(self.pause)
+
+ sunpause = sagetexunpause
+ sunpause.setParseAction(self.unpause)
+
+ doit = smacro | splot | senv | spause | sunpause
+
+ str = ''.join(open(fn + '.tex', 'r').readlines())
+ self.result = ''
+
+ doit.transformString(str)
+
+ def macroout(self, s, l, t):
+ self.result += '# \\sage{} from line %s\n' % lineno(l, s)
+ self.result += t.code[1:-1] + '\n\n'
+
+ def plotout(self, s, l, t):
+ self.result += '# \\sageplot{} from line %s:\n' % lineno(l, s)
+ if t.format is not '':
+ self.result += '# format: %s' % t.format[0][1:-1] + '\n'
+ self.result += t.code[1:-1] + '\n\n'
+
+ def envout(self, s, l, t):
+ self.result += '# %s environment from line %s:' % (t.env,
+ lineno(l, s))
+ self.result += t.code[0] + '\n'
+
+ def pause(self, s, l, t):
+ self.result += ('# SageTeX (probably) paused on input line %s.\n\n' %
+ (lineno(l, s)))
+
+ def unpause(self, s, l, t):
+ self.result += ('# SageTeX (probably) unpaused on input line %s.\n\n' %
+ (lineno(l, s)))
+
diff --git a/Master/texmf-dist/source/latex/sagetex/py-and-sty.dtx b/Master/texmf-dist/source/latex/sagetex/py-and-sty.dtx
new file mode 100644
index 00000000000..3798ec58547
--- /dev/null
+++ b/Master/texmf-dist/source/latex/sagetex/py-and-sty.dtx
@@ -0,0 +1,907 @@
+% \section{Implementation}
+% \label{sec:implementation}
+%
+% There are two pieces to this package: a \LTX style file, and a
+% Python module. They are mutually interdependent, so it makes sense to
+% document them both here.
+%
+% \subsection{The style file}
+% \label{sec:sty-file}
+%
+% \iffalse
+% tell docstrip to put code into the .sty file
+%<*latex>
+% \fi
+%
+% All macros and counters intended for use internal to this package
+% begin with ``|ST@|''.
+%
+% \subsubsection{Initialization}
+%
+% Let's begin by loading some packages. The key bits of |sageblock| and
+% friends are stol---um, adapted from the |verbatim| package manual. So
+% grab the |verbatim| package.
+% \begin{macrocode}
+\RequirePackage{verbatim}
+% \end{macrocode}
+% Unsurprisingly, the |\sageplot| command works poorly without graphics
+% support.
+% \begin{macrocode}
+\RequirePackage{graphicx}
+% \end{macrocode}
+% The |makecmds| package gives us a |\provideenvironment| which we need,
+% and we use |ifpdf| and |ifthen| in |\sageplot| so we know what kind of
+% files to look for.
+% \begin{macrocode}
+\RequirePackage{makecmds}
+\RequirePackage{ifpdf}
+\RequirePackage{ifthen}
+% \end{macrocode}
+%
+% Next set up the counters, default indent, and flags.
+% \begin{macrocode}
+\newcounter{ST@inline}
+\newcounter{ST@plot}
+\setcounter{ST@inline}{0}
+\setcounter{ST@plot}{0}
+\newlength{\sagetexindent}
+\setlength{\sagetexindent}{5ex}
+\newif\ifST@paused
+\ST@pausedfalse
+% \end{macrocode}
+% Set up the file stuff, which will get run at the beginning of the
+% document, after we know what's happening with the |final| option.
+% First, we open the |.sage| file:
+% \begin{macrocode}
+\AtBeginDocument{\@ifundefined{ST@final}{%
+\newwrite\ST@sf%
+\immediate\openout\ST@sf=\jobname.sage%
+% \end{macrocode}
+% \begin{macro}{\ST@wsf}
+% We will write a lot of stuff to that file, so make a convenient
+% abbreviation, then use it to put the initial commands into the
+% |.sage| file. The hash mark below gets doubled when written to the
+% file, for some obscure reason related to parameter expansion. It's
+% valid Python, though, so I haven't bothered figuring out how to get
+% a single hash. We are assuming that the extension is |.tex|; see the
+% |initplot| documentation on page~\pageref{initplot} for discussion
+% of file extensions. The ``|(\jobname.sage)|'' business is there
+% because the comment below will get pulled into the autogenerated
+% |.py| file (second order autogeneration!) and I'd like to reduce
+% possible confusion if someone is looking around in those files.
+% \begin{macrocode}
+\newcommand{\ST@wsf}[1]{\immediate\write\ST@sf{#1}}%
+\ST@wsf{# This file (\jobname.sage) was *autogenerated* from the file \jobname.tex.}%
+\ST@wsf{import sagetex}%
+\ST@wsf{_st_ = sagetex.SageTeXProcessor('\jobname')}}%
+% \end{macrocode}
+% On the other hand, if the |ST@final| flag is set, don't bother with
+% any of the file stuff, and make |\ST@wsf| a no-op.
+% \begin{macrocode}
+{\newcommand{\ST@wsf}[1]{\relax}}}
+% \end{macrocode}
+% \end{macro}
+% Now we declare our options, which mostly just set flags that we check
+% at the beginning of the document, and when running the |.sage| file.
+% \changes{v2.0}{2008/04/04}{Add \texttt{epstopdf} option}
+% \changes{v2.0}{2008/12/16}{Add \texttt{final} option}
+%
+% The |final| option controls whether or not we write the |.sage| file;
+% the |imagemagick| and |epstopdf| options both want to write something
+% to that same file. So we put off all the actual file stuff until the
+% beginning of the document---by that time, we'll have processed the
+% |final| option (or not) and can check the |\ST@final| flag to see what
+% to do. (We must do this because we can't specify code that runs if an
+% option \emph{isn't} defined.)
+%
+% For |final|, we set a flag for other guys to check, and if there's no
+% |.sout| file, we warn the user that something fishy is going on.
+% \begin{macrocode}
+\DeclareOption{final}{%
+ \newcommand{\ST@final}{x}%
+ \IfFileExists{\jobname.sout}{}{\AtEndDocument{\PackageWarningNoLine{sagetex}%
+ {`final' option provided, but \jobname.sout^^Jdoesn't exist! No Sage
+ input will appear in your document. Remove the `final'^^Joption and
+ rerun LaTeX on your document}}}}
+% \end{macrocode}
+% For |imagemagick|, we set two flags: one for \LTX and one for Sage.
+% It's important that we set |ST@useimagmagick| \emph{before} the
+% beginning of the document, so that the graphics commands can check
+% that. We do wait until the beginning of the document to do file
+% writing stuff.
+% \begin{macrocode}
+\DeclareOption{imagemagick}{%
+ \newcommand{\ST@useimagemagick}{x}%
+ \AtBeginDocument{%
+ \@ifundefined{ST@final}{%
+ \ST@wsf{_st_.useimagemagick = True}}{}}}
+% \end{macrocode}
+% For |epstopdf|, we just set a flag for Sage. Then, process the options.
+% \begin{macrocode}
+\DeclareOption{epstopdf}{%
+\AtBeginDocument{%
+\@ifundefined{ST@final}{%
+ \ST@wsf{_st_.useepstopdf = True}}{}}}
+\ProcessOptions\relax
+% \end{macrocode}
+% The |\relax| is a little incantation suggested by the ``\LaTeXe{} for
+% class and package writers'' manual, section 4.7.
+%
+% Pull in the |.sout| file if it exists, or do nothing if it doesn't. I
+% suppose we could do this inside an |AtBeginDocument| but I don't see
+% any particular reason to do that. It will work whenever we load it. If
+% the |.sout| file isn't found, print the usual \TeX-style message. This
+% allows programs
+% (\href{http://www.phys.psu.edu/~collins/software/latexmk-jcc/}{\texttt{Latexmk}}, for example)
+% that read the |.log| file or terminal output to detect
+% the need for another typesetting run to do so. If the ``\texttt{No
+% file foo.sout}'' line doesn't work for some software package, please
+% let me know and I can change it to use |PackageInfo| or whatever.
+% \begin{macrocode}
+\InputIfFileExists{\jobname.sout}{}{\typeout{No file \jobname.sout.}}
+% \end{macrocode}
+% \changes{v2.1.1}{2009/05/14}{Add typeout if .sout file not found}
+%
+% The user might load the |hyperref| package after this one (indeed, the
+% |hyperref| documentation insists that it be loaded last) or not at
+% all---so when we hit the beginning of the document, provide a dummy
+% |NoHyper| environment if one hasn't been defined by the |hyperref|
+% package. We need this for the |\sage| macro below.
+% \begin{macrocode}
+\AtBeginDocument{\provideenvironment{NoHyper}{}{}}
+% \end{macrocode}
+%
+% \subsubsection{The \texttt{\protect\bslash sage} macro}
+% \label{sec:sagemacro}
+%
+% \begin{macro}{\sage}
+% This macro combines |\ref|, |\label|, and Sage all at once. First, we
+% use Sage to get a \LTX representation of whatever you give this
+% function. The Sage script writes a |\newlabel| line into the |.sout|
+% file, and we read the output using the |\ref| command. Usually, |\ref|
+% pulls in a section or theorem number, but it will pull in arbitrary
+% text just as well.
+%
+% The first thing it does it write its argument into the |.sage| file,
+% along with a counter so we can produce a unique label. We wrap a
+% try/except around the function call so that we can provide a more
+% helpful error message in case something goes wrong. (In particular, we
+% can tell the user which line of the |.tex| file contains the offending
+% code.) We can use |^^J| to put linebreaks into the |.sage| file, but
+% \LTX wants to put a space after that, which is why we don't put the
+% ``except'' on its own line here in the source.
+% \begin{macrocode}
+\newcommand{\sage}[1]{\ST@wsf{%
+try:^^J
+ _st_.inline(\theST@inline, #1)^^Jexcept:^^J
+ _st_.goboom(\the\inputlineno)}%
+% \end{macrocode}
+% The |inline| function of the Python module is documented on page
+% \pageref{inlinefn}. Back in \LTX-land: if paused, say so.
+% \begin{macrocode}
+\ifST@paused
+ \mbox{(Sage\TeX{} is paused)}%
+% \end{macrocode}
+% Otherwise\ldots our use of |\newlabel| and |\ref| seems awfully clever
+% until you load the |hyperref| package, which gleefully tries to
+% hyperlink the hell out of everything. This is great until it hits one
+% of our special |\newlabel|s and gets deeply confused. Fortunately the
+% |hyperref| folks are willing to accomodate people like us, and give us
+% a |NoHyper| environment.
+% \begin{macrocode}
+\else
+ \begin{NoHyper}\ref{@sageinline\theST@inline}\end{NoHyper}
+% \end{macrocode}
+% Now check if the label has already been defined. (The internal
+% implementation of labels in \LTX involves defining a macro called
+% ``|r@@labelname|''.) If it hasn't, we set a flag so that we can tell
+% the user to run Sage on the |.sage| file at the end of the run.
+% \begin{macrocode}
+ \@ifundefined{r@@sageinline\theST@inline}{\gdef\ST@rerun{x}}{}
+\fi
+% \end{macrocode}
+% In any case, the last thing to do is step the counter.
+% \begin{macrocode}
+\stepcounter{ST@inline}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\percent}
+% A macro that inserts a percent sign. This is more-or-less stolen from the
+% \textsf{Docstrip} manual; there they change the catcode inside a group
+% and use |gdef|, but here we try to be more \LaTeX y and use
+% |\newcommand|.
+% \begin{macrocode}
+\catcode`\%=12
+\newcommand{\percent}{%}
+\catcode`\%=14
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{The \texttt{\protect\bslash sageplot} macro and friends}
+% \label{sec:sageplotmacro}
+%
+% Plotting is rather more complicated, and requires several helper
+% macros that accompany |\sageplot|.
+%
+% \begin{macro}{\ST@plotdir}
+% A little abbreviation for the plot directory. We don't use
+% |\graphicspath| because it's
+% \href{http://www.tex.ac.uk/cgi-bin/texfaq2html?label=graphicspath}{
+% apparently slow}---also, since we know right where our plots are
+% going, no need to have \LTX looking for them.
+% \begin{macrocode}
+\newcommand{\ST@plotdir}{sage-plots-for-\jobname.tex}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ST@missingfilebox}
+% The code that makes the ``file not found'' box. This shows up in a
+% couple places below, so let's just define it once.
+% \begin{macrocode}
+\newcommand{\ST@missingfilebox}{\framebox[2cm]{\rule[-1cm]{0cm}{2cm}\textbf{??}}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\sageplot}
+% \changes{v1.3}{2008/03/08}{Iron out warnings, cool \TikZ flowchart}
+% This function is similar to |\sage|. The neat thing that we take
+% advantage of is that commas aren't special for arguments to \LTX
+% commands, so it's easy to capture a bunch of keyword arguments that
+% get passed right into a Python function.
+%
+% This macro has two optional arguments, which can't be defined using
+% \LTX's |\newcommand|; we use Scott Pakin's brilliant
+% \href{http://tug.ctan.org/tex-archive/support/newcommand/}{|newcommand|}
+% package to create this macro; the options I fed to his script were
+% similar to this:
+%\begin{center}
+% |MACRO sageplot OPT[#1={width}] OPT[#2={notprovided}] #3|
+%\end{center}
+% Observe that we are using a Python script to write \LTX code which
+% writes Python code which writes \LTX code. Crazy!
+%
+% Here's the wrapper command which does whatever magic we need to get
+% two optional arguments.
+% \begin{macrocode}
+\newcommand{\sageplot}[1][width=.75\textwidth]{%
+ \@ifnextchar[{\ST@sageplot[#1]}{\ST@sageplot[#1][notprovided]}}
+% \end{macrocode}
+% The first optional argument |#1| will get shoved right into the
+% optional argument for |\includegraphics|, so the user has easy control
+% over the \LTX aspects of the plotting. We define a default size of
+% $3/4$ the textwidth, which seems reasonable. (Perhaps a future version
+% of \ST will allow the user to specify in the package options a set of
+% default options to be used throughout.) The second optional argument
+% |#2| is the file format and allows us to tell what files to look for.
+% It defaults to ``notprovided'', which tells the Python module to
+% create EPS and PDF files. Everything in |#3| gets put into the Python
+% function call, so the user can put in keyword arguments there which
+% get interpreted correctly by Python.
+%
+% \begin{macro}{\ST@sageplot}
+% \changes{v2.0}{2008/12/16}{Change to use only keyword arguments: see issue
+% 2 on bitbucket tracker}
+% Let's see the real code here. We write a couple lines to the |.sage|
+% file, including a counter, input line number, and all of the mandatory
+% argument; all this is wrapped in another try/except.
+% \begin{macrocode}
+\def\ST@sageplot[#1][#2]#3{\ST@wsf{try:^^J
+ _st_.plot(\theST@plot, format='#2', _p_=#3)^^Jexcept:^^J
+ _st_.goboom(\the\inputlineno)}%
+% \end{macrocode}
+% The Python |plot| function is documented on page~\pageref{plotfn}.
+%
+% Now we include the appropriate graphics file. Because the user might
+% be producing DVI or PDF files, and have supplied a file format or not,
+% and so on, the logic we follow is a bit complicated.
+% \autoref{f:sageplottree} shows what we do; for completeness---and
+% because I think drawing trees with \TikZ is really cool---we show what
+% |\ST@inclgrfx| does in \autoref{f:stig}. This entire complicated
+% business is intended to avoid doing an |\includegraphics| command on a
+% file that doesn't exist, and to issue warnings appropriate to the
+% situation.
+%
+% \begin{figure}
+% \centering
+% \begin{tikzpicture}
+% \tikzstyle{level 1}=[sibling distance=6cm]
+% \tikzstyle{level 2}=[sibling distance=3cm]
+% \node [box] {DVI or PDF?}
+% child {node [box] {Format provided?}
+% child {node [box] {STig EPS}
+% edge from parent node[left] {no}}
+% child {node [box] {IM option set?}
+% child {node [box, text width=3cm] {Warn that DVI + PNG = bad}
+% edge from parent node[left] {no}}
+% child {node [box] {STig EPS}
+% edge from parent node[right] {yes}}
+% edge from parent node[right] {yes}}
+% edge from parent node[left] {DVI}}
+% child {node [box] {Format provided?}
+% child {node [box] {STig PDF}
+% edge from parent node[left] {no}}
+% child {node [box] {STig \texttt{\#2}}
+% edge from parent node[right] {yes}}
+% edge from parent node[right] {PDF}};
+% \end{tikzpicture}
+% \caption{The logic tree that \texttt{\bslash sageplot} uses to
+% decide whether to run \texttt{\bslash includegraphics} or to yell at
+% the user. ``Format'' is the \texttt{\#2} argument to \texttt{\bslash
+% sageplot}, ``STig ext''
+% means a call to \texttt{\bslash ST@inclgrfx} with ``ext'' as the
+% second argument, and ``IM'' is Imagemagick.}
+% \label{f:sageplottree}
+% \end{figure}
+%
+% If we are creating a PDF, we check to see if the user asked for a
+% different format, and use that if necessary:
+% \begin{macrocode}
+\ifpdf
+ \ifthenelse{\equal{#2}{notprovided}}%
+ {\ST@inclgrfx{#1}{pdf}}%
+ {\ST@inclgrfx{#1}{#2}}%
+% \end{macrocode}
+% Otherwise, we are creating a DVI file, which only supports EPS. If the
+% user provided a format anyway, don't include the file (since it won't
+% work) and warn the user about this. (Unless the file doesn't exist, in
+% which case we do the same thing that |\ST@inclgrfx| does.)
+% \begin{macrocode}
+\else
+ \ifthenelse{\equal{#2}{notprovided}}%
+ {\ST@inclgrfx{#1}{eps}}%
+% \end{macrocode}
+% If a format is provided, we check to see if we're using the
+% imagemagick option. If not, we're going to issue some sort of warning,
+% depending on whether the file exists yet or not.
+% \begin{macrocode}
+ {\@ifundefined{ST@useimagemagick}%
+ {\IfFileExists{\ST@plotdir/plot-\theST@plot.#2}%
+ {\ST@missingfilebox%
+ \PackageWarning{sagetex}{Graphics file
+ \ST@plotdir/plot-\theST@plot.#2\space on page \thepage\space
+ cannot be used with DVI output. Use pdflatex or create an EPS
+ file. Plot command is}}%
+ {\ST@missingfilebox%
+ \PackageWarning{sagetex}{Graphics file
+ \ST@plotdir/plot-\theST@plot.#2\space on page \thepage\space
+ does not exist. Plot command is}%
+ \gdef\ST@rerun{x}}}%
+% \end{macrocode}
+% Otherwise, we are using Imagemagick, so try to include an EPS file
+% anyway.
+% \begin{macrocode}
+ {\ST@inclgrfx{#1}{eps}}}%
+\fi
+% \end{macrocode}
+% Step the counter and we're done with the usual work.
+% \begin{macrocode}
+\stepcounter{ST@plot}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ST@inclgrfx}
+% This command includes the requested graphics file (|#2| is the
+% extension) with the requested options (|#1|) if the file exists. Note
+% that it just needs to know the extension, since we use a counter for
+% the filename. If we are paused, it just puts in a little box saying
+% so.
+% \begin{macrocode}
+\newcommand{\ST@inclgrfx}[2]{\ifST@paused
+ \fbox{\rule[-1cm]{0cm}{2cm}Sage\TeX{} is paused; no graphic}
+\else
+ \IfFileExists{\ST@plotdir/plot-\theST@plot.#2}%
+ {\includegraphics[#1]{\ST@plotdir/plot-\theST@plot.#2}}%
+% \end{macrocode}
+% If the file doesn't exist, we insert a little box to indicate it
+% wasn't found, issue a warning that we didn't find a graphics file,
+% then set a flag that, at the end of the run, tells the user to run
+% Sage again.
+% \begin{macrocode}
+ {\ST@missingfilebox%
+ \PackageWarning{sagetex}{Graphics file
+ \ST@plotdir/plot-\theST@plot.#2\space on page \thepage\space does not
+ exist. Plot command is}%
+ \gdef\ST@rerun{x}}
+\fi}
+% \end{macrocode}
+% \autoref{f:stig} makes this a bit clearer.
+% \begin{figure}
+% \centering
+% \begin{tikzpicture}
+% \tikzstyle{level 1}=[sibling distance=4cm]
+% \node [box] {Paused?}
+% child {node [box] {Insert ``we're paused'' box}
+% edge from parent node[left] {yes}}
+% child {node [box] {Does EXT file exist?}
+% child {node [box, text width = 2.125cm] {Warn user to rerun Sage}
+% edge from parent node[left] {no}}
+% child {node [box] {Use \texttt{includegraphics}}
+% edge from parent node[right] {yes}}
+% edge from parent node[right] {no}};
+% \end{tikzpicture}
+% \caption{The logic used by the \texttt{\bslash ST@inclgrfx}
+% command.}
+% \label{f:stig}
+% \end{figure}
+% \end{macro}
+%
+% \subsubsection{Verbatim-like environments}
+% \label{sec:verbatim-envs}
+%
+% \begin{macro}{\ST@beginsfbl}
+% This is ``begin |.sage| file block'', an internal-use abbreviation
+% that sets things up when we start writing a chunk of Sage code to
+% the |.sage| file. It begins with some \TeX{} magic that fixes
+% spacing, then puts the start of a try/except block in the |.sage|
+% file---this not only allows the user to indent code without
+% Sage/Python complaining about indentation, but lets us tell the user
+% where things went wrong. The |blockbegin| and |blockend| functions
+% are documented on page~\pageref{blocksbeginend}. The last bit is some
+% magic from the |verbatim| package manual that makes \LTX respect
+% line breaks.
+% \begin{macrocode}
+\newcommand{\ST@beginsfbl}{%
+ \@bsphack\ST@wsf{%
+_st_.blockbegin()^^Jtry:}%
+ \let\do\@makeother\dospecials\catcode`\^^M\active}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ST@endsfbl}
+% The companion to |\ST@beginsfbl|.
+% \begin{macrocode}
+\newcommand{\ST@endsfbl}{%
+\ST@wsf{except:^^J
+ _st_.goboom(\the\inputlineno)^^J_st_.blockend()}}
+% \end{macrocode}
+% \end{macro}
+%
+% Now let's define the ``verbatim-like'' environments. There are four
+% possibilities, corresponding to the two independent choices of
+% typesetting the code or not, and writing to the |.sage| file or not.
+%
+% \begin{environment}{sageblock}
+% This environment does both: it typesets your code and puts it into the
+% |.sage| file for execution by Sage.
+% \begin{macrocode}
+\newenvironment{sageblock}{\ST@beginsfbl%
+% \end{macrocode}
+% The space between |\ST@wsf{| and |\the| is crucial! It, along with the
+% ``|try:|'', is what allows the user to indent code if they like. This
+% line sends stuff to the |.sage| file.
+% \begin{macrocode}
+\def\verbatim@processline{\ST@wsf{ \the\verbatim@line}%
+% \end{macrocode}
+% Next, we typeset your code and start the verbatim environment.
+% \begin{macrocode}
+\hspace{\sagetexindent}\the\verbatim@line\par}%
+\verbatim}%
+% \end{macrocode}
+% At the end of the environment, we put a chunk into the |.sage| file
+% and stop the verbatim environment.
+% \begin{macrocode}
+{\ST@endsfbl\endverbatim}
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{sagesilent}
+% This is from the |verbatim| package manual. It's just like the above,
+% except we don't typeset anything.
+% \begin{macrocode}
+\newenvironment{sagesilent}{\ST@beginsfbl%
+\def\verbatim@processline{\ST@wsf{ \the\verbatim@line}}%
+\verbatim@start}%
+{\ST@endsfbl\@esphack}
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{sageverbatim}
+% The opposite of |sagesilent|. This is exactly the same as the verbatim
+% environment, except that we include some indentation to be consistent
+% with other typeset Sage code.
+% \begin{macrocode}
+\newenvironment{sageverbatim}{%
+\def\verbatim@processline{\hspace{\sagetexindent}\the\verbatim@line\par}%
+\verbatim}%
+{\endverbatim}
+% \end{macrocode}
+% \end{environment}
+%
+% Logically, we now need an environment which neither typesets
+% \emph{nor} writes code to the |.sage| file. The verbatim package's
+% |comment| environment does that.\\
+%
+% \subsubsection{Pausing \ST}
+% \label{sec:pausing-sagetex}
+%
+% How can one have Sage to stop processing \ST output for a little
+% while, and then start again? At first I thought I would need some sort
+% of ``goto'' statement in Python, but later realized that there's a
+% dead simple solution: write triple quotes to the |.sage| file to
+% comment out the code. Okay, so this isn't \emph{really} commenting out
+% the code; PEP 8 says block comments should use ``|#|'' and Sage will
+% read in the ``commented-out'' code as a string literal. For the
+% purposes of \ST, I think this is a good decision, though, since (1)
+% the pausing mechanism is orthogonal to everything else, which makes it
+% easier to not screw up other code, and (2) it will always work.
+%
+% This illustrates what I really like about \ST: it mixes \LTX and
+% Sage/Python, and often what is difficult or impossible in one system
+% is trivial in the other.
+%
+% \begin{macro}{sagetexpause}
+% This macro pauses \ST by effectively commenting out code in the
+% |.sage| file. When running the corresponding |.sage| file, Sage will
+% skip over any commands issued while \ST is paused.
+% \begin{macrocode}
+\newcommand{\sagetexpause}{\ifST@paused\relax\else
+\ST@wsf{print 'SageTeX paused on \jobname.tex line \the\inputlineno'^^J"""}
+\ST@pausedtrue
+\fi}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{sagetexunpause}
+% This is the obvious companion to |\sagetexpause|.
+% \begin{macrocode}
+\newcommand{\sagetexunpause}{\ifST@paused
+\ST@wsf{"""^^Jprint 'SageTeX unpaused on \jobname.tex line \the\inputlineno'}
+\ST@pausedfalse
+\fi}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{End-of-document cleanup}
+% \label{sec:end-of-doc-cleanup}
+%
+% We tell the Sage script to write some information to the |.sout| file,
+% then check to see if |ST@rerun| ever got defined. If not, all the
+% inline formulas and plots worked, so do nothing. We check to see if
+% we're paused first, so that we can finish the triple-quoted string in
+% the |.sage| file.
+% \begin{macrocode}
+\AtEndDocument{\ifST@paused
+\ST@wsf{"""^^Jprint 'SageTeX unpaused at end of \jobname.tex'}
+\fi
+\ST@wsf{_st_.endofdoc()}%
+\@ifundefined{ST@rerun}{}%
+% \end{macrocode}
+% Otherwise, we issue a warning to tell the user to run Sage on the
+% |.sage| file. Part of the reason we do this is that, by using |\ref|
+% to pull in the inlines, \LTX will complain about undefined references
+% if you haven't run the Sage script---and for many \LTX users, myself
+% included, the warning ``there were undefined references'' is a signal
+% to run \LTX again. But to fix these particular undefined references,
+% you need to run \emph{Sage}. We also suppressed file-not-found errors
+% for graphics files, and need to tell the user what to do about that.
+%
+% At any rate, we tell the user to run Sage if it's necessary.
+% \begin{macrocode}
+{\PackageWarningNoLine{sagetex}{There were undefined Sage formulas
+and/or plots.^^JRun Sage on \jobname.sage, and then run
+LaTeX on \jobname.tex again}}}
+% \end{macrocode}
+%
+%
+% \subsection{The Python module}
+% \label{sec:py-file}
+%
+% \iffalse
+% Hey, docstrip! Stop putting code into the .sty file, and start
+% putting it into the .py file.
+%</latex>
+%<*python>
+% Thanks.
+% \fi
+%
+% The style file writes things to the |.sage| file and reads them from
+% the |.sout| file. The Python module provides functions that help
+% produce the |.sout| file from the |.sage| file.
+%
+% \paragraph{A note on Python and \textsf{Docstrip}} There is one tiny
+% potential source of confusion when documenting Python code with
+% \textsf{Docstrip}: the percent sign. If you have a long line of Python
+% code which includes a percent sign for string formatting and you break
+% the line with a backslash and begin the next line with a percent sign,
+% that line \emph{will not} be written to the output file. This is only
+% a problem if you \emph{begin} the line with a (single) percent sign;
+% there are no troubles otherwise.\\
+%
+% On to the code: the |sagetex.py| file is intended to be used as a
+% module and doesn't do anything useful when called directly, so if
+% someone does that, warn them. We do this right away so that we print
+% this and exit before trying to import any Sage modules; that way, this
+% error message gets printed whether you run the script with Sage or
+% with Python.
+% \begin{macrocode}
+import sys
+if __name__ == "__main__":
+ print("""This file is part of the SageTeX package.
+It is not meant to be called directly.
+
+This file will be automatically used by Sage scripts generated from a
+LaTeX document using the SageTeX package.""")
+ sys.exit()
+% \end{macrocode}
+% Import what we need:
+% \begin{macrocode}
+from sage.misc.latex import latex
+import os
+import os.path
+import hashlib
+import traceback
+import subprocess
+import shutil
+% \end{macrocode}
+% We define a class so that it's a bit easier to carry around internal
+% state. We used to just have some global variables and a bunch of
+% functions, but this seems a bit nicer and easier.
+% \begin{macrocode}
+class SageTeXProcessor():
+ def __init__(self, jobname):
+ self.progress('Processing Sage code for %s.tex...' % jobname)
+ self.didinitplot = False
+ self.useimagemagick = False
+ self.useepstopdf = False
+ self.plotdir = 'sage-plots-for-' + jobname + '.tex'
+ self.filename = jobname
+% \end{macrocode}
+% Open a |.sout.tmp| file and write all our output to that. Then, when
+% we're done, we move that to |.sout|. The ``autogenerated'' line is
+% basically the same as the lines that get put at the top of preparsed
+% Sage files; we are automatically generating a file with Sage, so it
+% seems reasonable to add it.
+% \begin{macrocode}
+ self.souttmp = open(self.filename + '.sout.tmp', 'w')
+ s = '% This file was *autogenerated* from the file ' + \
+ os.path.splitext(jobname)[0] + '.sage.\n'
+ self.souttmp.write(s)
+% \end{macrocode}
+%
+% \begin{macro}{progress}
+% This function just prints stuff. It allows us to not print a
+% linebreak, so you can get ``|start...|'' (little time spent
+% processing) ``|end|'' on one line.
+% \begin{macrocode}
+ def progress(self, t,linebreak=True):
+ if linebreak:
+ print(t)
+ else:
+ sys.stdout.write(t)
+ sys.stdout.flush()
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{initplot}
+% \phantomsection\label{initplot}
+% We only want to create the plots directory if the user actually plots
+% something. This function creates the directory and sets the
+% |didinitplot| flag after doing so. We make a directory based on the
+% \LTX file being processed so that if there are multiple |.tex| files
+% in a directory, we don't overwrite plots from another file.
+% \begin{macrocode}
+ def initplot(self):
+ self.progress('Initializing plots directory')
+% \end{macrocode}
+% We hard-code the |.tex| extension, which is fine in the overwhelming
+% majority of cases, although it does cause minor confusion when
+% building the documentation. If it turns out lots of people use, say, a
+% |ltx| extension or whatever, We could find out the correct extension,
+% but it would involve a lot of irritating mucking around---on
+% |comp.text.tex|, the best solution I found for finding the file
+% extension is to look through the |.log| file.
+% \begin{macrocode}
+ if os.path.isdir(self.plotdir):
+ shutil.rmtree(self.plotdir)
+ os.mkdir(self.plotdir)
+ self.didinitplot = True
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{inline}
+% \phantomsection\label{inlinefn}
+% This function works with |\sage| from the style file (see
+% \autoref{sec:sagemacro}) to put Sage output into your \LTX file.
+% Usually, when you use |\label|, it writes a line such as
+% \begin{center}
+% |\newlabel{labelname}{{section number}{page number}}|
+% \end{center}
+% to the |.aux| file. When you use the |hyperref| package, there are
+% more fields in the second argument, but the first two are the same.
+% The |\ref| command just pulls in what's in the first field of the
+% second argument, so we can hijack this mechanism for our own nefarious
+% purposes. The function writes a |\newlabel| line with a label made
+% from a counter and the text from running Sage on |s|.
+%
+% We print out the line number so if something goes wrong, the user can
+% more easily track down the offending |\sage| command in the source
+% file.
+%
+% That's a lot of explanation for a very short function:
+% \begin{macrocode}
+ def inline(self, counter, s):
+ self.progress('Inline formula %s' % counter)
+ self.souttmp.write('\\newlabel{@sageinline' + str(counter) + '}{{' + \
+ latex(s).rstrip() + '}{}{}{}{}}\n')
+% \end{macrocode}
+% We are using five fields, just like |hyperref| does, because that
+% works whether or not |hyperref| is loaded. Using two fields, as in
+% plain \LTX, doesn't work if |hyperref| is loaded.
+% \end{macro}
+%
+% \begin{macro}{blockbegin}
+% \begin{macro}{blockend}
+% \phantomsection\label{blocksbeginend}
+% This function and its companion used to write stuff to the |.sout|
+% file, but now they just update the user on our progress evaluating a
+% code block. The verbatim-like environments of
+% \autoref{sec:verbatim-envs} use these functions.
+% \begin{macrocode}
+ def blockbegin(self):
+ self.progress('Code block begin...', False)
+ def blockend(self):
+ self.progress('end')
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{plot}
+% \phantomsection\label{plotfn}
+% I hope it's obvious that this function does plotting. It's the Python
+% counterpart of |\ST@sageplot| described in \autoref{sec:sageplotmacro}. As
+% mentioned in the |\sageplot| code, we're taking advantage of two
+% things: first, that \LTX doesn't treat commas and spaces in macro
+% arguments specially, and second, that Python (and Sage plotting
+% functions) has nice support for keyword arguments. The |#3| argument
+% to |\sageplot| becomes |_p_| and |**kwargs| below.
+% \begin{macrocode}
+ def plot(self, counter, _p_, format='notprovided', **kwargs):
+ if not self.didinitplot:
+ self.initplot()
+ self.progress('Plot %s' % counter)
+% \end{macrocode}
+% If the user says nothing about file formats, we default to producing
+% PDF and EPS. This allows the user to transparently switch between
+% using a DVI previewer (which usually automatically updates when the
+% DVI changes, and has support for source specials, which makes the
+% writing process easier) and making PDFs.\footnote{Yes, there's
+% \texttt{pdfsync}, but full support for that is still rare in Linux, so
+% producing EPS and PDF is the best solution for now.}
+% \begin{macrocode}
+ if format == 'notprovided':
+ formats = ['eps', 'pdf']
+ else:
+ formats = [format]
+ for fmt in formats:
+% \end{macrocode}
+% If we're making a PDF and have been told to use |epstopdf|, do so,
+% then skip the rest of the loop.
+% \begin{macrocode}
+ if fmt == 'pdf' and self.useepstopdf:
+ epsfile = os.path.join(self.plotdir, 'plot-%s.eps' % counter)
+ self.progress('Calling epstopdf to convert plot-%s.eps to PDF' % \
+ counter)
+ subprocess.check_call(['epstopdf', epsfile])
+ continue
+ plotfilename = os.path.join(self.plotdir, 'plot-%s.%s' % (counter, fmt))
+ _p_.save(filename=plotfilename, **kwargs)
+% \end{macrocode}
+% If the user provides a format \emph{and} specifies the |imagemagick|
+% option, we try to convert the newly-created file into EPS format.
+% \begin{macrocode}
+ if format != 'notprovided' and self.useimagemagick:
+ self.progress('Calling Imagemagick to convert plot-%s.%s to EPS' % \
+ (counter, format))
+ self.toeps(counter, format)
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{toeps}
+% This function calls the Imagmagick utility |convert| to, well, convert
+% something into EPS format. This gets called when the user has
+% requested the ``|imagemagick|'' option to the \ST\ style file and is
+% making a graphic file with a nondefault extension.
+% \begin{macrocode}
+ def toeps(self, counter, ext):
+ subprocess.check_call(['convert',\
+ '%s/plot-%s.%s' % (self.plotdir, counter, ext), \
+ '%s/plot-%s.eps' % (self.plotdir, counter)])
+% \end{macrocode}
+% We are blindly assuming that the |convert| command exists and will do
+% the conversion for us; the |check_call| function raises an exception
+% which, since all these calls get wrapped in try/excepts in the |.sage|
+% file, should result in a reasonable error message if something strange
+% happens.
+% \end{macro}
+%
+% \begin{macro}{goboom}
+% \phantomsection\label{macro:goboom}
+% When a chunk of Sage code blows up, this function bears the bad news
+% to the user. Normally in Python the traceback is good enough for
+% this, but in this case, we start with a |.sage| file (which is
+% autogenerated) which itself autogenerates a |.py| file---and the
+% tracebacks the user sees refer to that file, whose line numbers are
+% basically useless. We want to tell them where in the \LTX file
+% things went bad, so we do that, give them the traceback, and exit
+% after removing the |.sout.tmp| file.
+% \begin{macrocode}
+ def goboom(self, line):
+ print('\n**** Error in Sage code on line %s of %s.tex! Traceback\
+ follows.' % (line, self.filename))
+ traceback.print_exc()
+ print('\n**** Running Sage on %s.sage failed! Fix %s.tex and try\
+ again.' % ((self.filename,) * 2))
+ self.souttmp.close()
+ os.remove(self.filename + '.sout.tmp')
+ sys.exit(int(1))
+% \end{macrocode}
+% We use |int(1)| above to make sure |sys.exit| sees a Python integer;
+% see
+% \href{http://trac.sagemath.org/sage_trac/ticket/2861#comment:5}{ticket
+% \#2861}.
+% \changes{v2.0.2}{2008/04/21}{Make sure sys.exit sees a Python integer}
+% \end{macro}
+%
+% \begin{macro}{endofdoc}
+% When we're done processing, we have some cleanup tasks. We
+% want to put the MD5 sum of the |.sage| file that produced the |.sout|
+% file we're about to write into the |.sout| file, so that external
+% programs that build \LTX documents can determine if they need to call Sage
+% to update the |.sout| file. But there is a problem: we write line
+% numbers to the |.sage| file so that we can provide useful error
+% messages---but that means that adding non-\ST text to your
+% source file will change the MD5 sum, and your program will think it
+% needs to rerun Sage even though none of the actual \ST macros
+% changed.
+%
+% How do we include line numbers for our error messages but still allow
+% a program to discover a ``genuine'' change to the |.sage| file?
+%
+% The answer is to only find the MD5 sum of \emph{part} of the |.sage|
+% file. By design, the source file line numbers only appear in calls to
+% |goboom| and pause/unpause lines, so we will strip those lines out.
+% What we do below is exactly equivalent to running
+% \begin{center}
+% \verb+egrep '^( _st_.goboom|print .SageT)' filename.sage | md5sum+
+% \end{center}
+% in a shell.
+% \begin{macrocode}
+ def endofdoc(self):
+ sagef = open(self.filename + '.sage', 'r')
+ m = hashlib.md5()
+ for line in sagef:
+ if line[0:12] != " _st_.goboom" and line[0:12] != "print 'SageT":
+ m.update(line)
+ s = '%' + m.hexdigest() + '% md5sum of corresponding .sage file\
+ (minus "goboom" and pause/unpause lines)\n'
+ self.souttmp.write(s)
+% \end{macrocode}
+% Now, we do issue warnings to run Sage on the |.sage| file and an
+% external program might look for those to detect the need to rerun
+% Sage, but those warnings do not quite capture all situations. (If
+% you've already produced the |.sout| file and change a |\sage| call, no
+% warning will be issued since all the |\ref|s find a |\newlabel|.)
+% Anyway, I think it's easier to grab an MD5 sum out of the end of the
+% file than parse the output from running |latex| on your file. (The
+% regular expression |^%[0-9a-f]{32}%| will find the MD5 sum. Note that
+% there are percent signs on each side of the hex string.)
+%
+% Now we are done with the |.sout.tmp| file. Close it, rename it, and
+% tell the user we're done.
+% \begin{macrocode}
+ self.souttmp.close()
+ os.rename(self.filename + '.sout.tmp', self.filename + '.sout')
+ self.progress('Sage processing complete. Run LaTeX on %s.tex again.' %\
+ self.filename)
+% \end{macrocode}
+% % \changes{v2.1.1}{2009/05/14}{Fix bug in finding md5 sum introduced by
+% pause facility}
+% \end{macro}
+
+% \endinput
+%</python>
+% Local Variables:
+% mode: doctex
+% TeX-master: "sagetexpackage"
+% End:
diff --git a/Master/texmf-dist/source/latex/sagetex/remote-sagetex.dtx b/Master/texmf-dist/source/latex/sagetex/remote-sagetex.dtx
new file mode 100644
index 00000000000..2360e220277
--- /dev/null
+++ b/Master/texmf-dist/source/latex/sagetex/remote-sagetex.dtx
@@ -0,0 +1,438 @@
+% \section{The \texttt{remote-sagetex} script}
+% \label{sec:remote-sagetex-code}
+%
+%
+% Here we describe the Python code for |remote-sagetex.py|. Since its
+% job is to replicate the functionality of using Sage and |sagetex.py|,
+% there is some overlap with the Python module.
+%
+% \iffalse
+%<*remotesagetex>
+% \fi
+%
+% The |#!/usr/bin/env python| line is provided for us by the |.ins|
+% file's preamble, so we don't put it here.
+% \begin{macrocode}
+from __future__ import print_function
+import json
+import sys
+import time
+import re
+import urllib
+import hashlib
+import os
+import os.path
+import shutil
+import getopt
+from contextlib import closing
+
+#########################################################################
+# You can provide a filename here and the script will read your login #
+# information from that file. The format must be: #
+# #
+# server = 'http://foo.com:8000' #
+# username = 'my_name' #
+# password = 's33krit' #
+# #
+# You can omit one or more of those lines, use " quotes, and put hash #
+# marks at the beginning of a line for comments. Command-line args #
+# take precedence over information from the file. #
+#########################################################################
+login_info_file = None # e.g. '/home/foo/Private/sagetex-login.txt'
+
+
+usage = """Process a SageTeX-generated .sage file using a remote Sage server.
+
+Usage: {0} [options] inputfile.sage
+
+Options:
+
+ -h, --help: print this message
+ -s, --server: the Sage server to contact
+ -u, --username: username on the server
+ -p, --password: your password
+ -f, --file: get login information from a file
+
+If the server does not begin with the four characters `http', then
+`https://' will be prepended to the server name.
+
+You can hard-code the filename from which to read login information into
+the remote-sagetex script. Command-line arguments take precedence over
+the contents of that file. See the SageTeX documentation for formatting
+details.
+
+If any of the server, username, and password are omitted, you will be
+asked to provide them.
+
+See the SageTeX documentation for more details on usage and limitations
+of remote-sagetex.""".format(sys.argv[0])
+
+server, username, password = (None,) * 3
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], 'hs:u:p:f:',
+ ['help', 'server=', 'user=', 'password=', 'file='])
+except getopt.GetoptError as err:
+ print(str(err), usage, sep='\n\n')
+ sys.exit(2)
+
+for o, a in opts:
+ if o in ('-h', '--help'):
+ print(usage)
+ sys.exit()
+ elif o in ('-s', '--server'):
+ server = a
+ elif o in ('-u', '--user'):
+ username = a
+ elif o in ('-p', '--password'):
+ password = a
+ elif o in ('-f', '--file'):
+ login_info_file = a
+
+if len(args) != 1:
+ print('Error: must specify exactly one file. Please specify options first.',
+ usage, sep='\n\n')
+ sys.exit(2)
+
+jobname = os.path.splitext(args[0])[0]
+% \end{macrocode}
+% When we send things to the server, we get everything back as a string,
+% including tracebacks. We can search through output using regexps to
+% look for typical traceback strings, but there's a more robust way: put
+% in a special string that changes every time and is printed when
+% there's an error, and look for that. Then it is massively unlikely
+% that a user's code could produce output that we'll mistake for an
+% actual traceback. System time will work well enough for these
+% purposes. We produce this string now, and we it when parsing the
+% |.sage| file (we insert it into code blocks) and when parsing the
+% output that the remote server gives us.
+% \begin{macrocode}
+traceback_str = 'Exception in SageTeX session {0}:'.format(time.time())
+% \end{macrocode}
+% \begin{macro}{parsedotsage}
+% To figure out what commands to send the remote server, we actually
+% read in the |.sage| file as strings and parse it. This seems a bit
+% strange, but since we know exactly what the format of that file is, we
+% can parse it with a couple flags and a handful of regexps.
+% \begin{macrocode}
+def parsedotsage(fn):
+ with open(fn, 'r') as f:
+% \end{macrocode}
+% Here are the regexps we use to snarf the interesting bits out of the
+% |.sage| file. Below we'll use the |re| module's |match| function so we
+% needn't anchor any of these at the beginning of the line.
+% \begin{macrocode}
+ inline = re.compile(r" _st_.inline\((?P<num>\d+), (?P<code>.*)\)")
+ plot = re.compile(r" _st_.plot\((?P<num>\d+), (?P<code>.*)\)")
+ goboom = re.compile(r" _st_.goboom\((?P<num>\d+)\)")
+ pausemsg = re.compile(r"print.'(?P<msg>SageTeX (un)?paused.*)'")
+ blockbegin = re.compile(r"_st_.blockbegin\(\)")
+ ignore = re.compile(r"(try:)|(except):")
+ in_comment = False
+ in_block = False
+ cmds = []
+% \end{macrocode}
+% Okay, let's go through the file. We're going to make a list of
+% dictionaries. Each dictionary corresponds to something we have to do
+% with the remote server, except for the pause/unpause ones, which we
+% only use to print out information for the user. All the dictionaries
+% have a |type| key, which obviously tells you type they are. The
+% pause/unpause dictionaries then just have a |msg| which we toss out to
+% the user. The ``real'' dictionaries all have the following keys:
+% \begin{itemize}
+% \item |type|: one of |inline|, |plot|, and |block|.
+% \item |goboom|: used to help the user pinpoint errors, just like the
+% |goboom| function (page \pageref{macro:goboom}) does.
+% \item |code|: the code to be executed.
+% \end{itemize}
+% Additionally, the |inline| and |plot| dicts have a |num| key for the
+% label we write to the |.sout| file.
+%
+% Here's the whole parser loop. The interesting bits are for parsing
+% blocks because there we need to accumulate several lines of code.
+% \begin{macrocode}
+ for line in f.readlines():
+ if line.startswith('"""'):
+ in_comment = not in_comment
+ elif not in_comment:
+ m = pausemsg.match(line)
+ if m:
+ cmds.append({'type': 'pause',
+ 'msg': m.group('msg')})
+ m = inline.match(line)
+ if m:
+ cmds.append({'type': 'inline',
+ 'num': m.group('num'),
+ 'code': m.group('code')})
+ m = plot.match(line)
+ if m:
+ cmds.append({'type': 'plot',
+ 'num': m.group('num'),
+ 'code': m.group('code')})
+% \end{macrocode}
+% The order of the next three ``if''s is important, since we need the
+% ``goboom'' line and the ``blockbegin'' line to \emph{not} get included
+% into the block's code. Note that the lines in the |.sage| file already
+% have some indentation, which we'll use when sending the block to the
+% server---we wrap the text in a try/except.
+% \begin{macrocode}
+ m = goboom.match(line)
+ if m:
+ cmds[-1]['goboom'] = m.group('num')
+ if in_block:
+ in_block = False
+ if in_block and not ignore.match(line):
+ cmds[-1]['code'] += line
+ if blockbegin.match(line):
+ cmds.append({'type': 'block',
+ 'code': ''})
+ in_block = True
+ return cmds
+% \end{macrocode}
+% \end{macro}
+% Parsing the |.sage| file is simple enough so that we can write one
+% function and just do it. Interacting with the remote server is a bit
+% more complicated, and requires us to carry some state, so let's make a
+% class.
+%
+% \begin{macro}{RemoteSage}
+% \changes{v2.2.1}{2009/06/20}{Fix stupid bug in \texttt{do\_inline()}
+% so that we actually write output to .sout file}
+%
+% This is pretty simple; it's more or less a translation of the examples
+% in \texttt{sage/server/simple/twist.py}.
+% \begin{macrocode}
+debug = False
+class RemoteSage:
+ def __init__(self, server, user, password):
+ self._srv = server.rstrip('/')
+ sep = '___S_A_G_E___'
+ self._response = re.compile('(?P<header>.*)' + sep +
+ '\n*(?P<output>.*)', re.DOTALL)
+ self._404 = re.compile('404 Not Found')
+ self._session = self._get_url('login',
+ urllib.urlencode({'username': user,
+ 'password':
+ password}))['session']
+% \end{macrocode}
+% In the string below, we want to do ``partial formatting'': we format
+% in the traceback string now, and want to be able to format in the code
+% later. The double braces get ignored by |format()| now, and are picked
+% up by |format()| when we use this later.
+% \begin{macrocode}
+ self._codewrap = """try:
+{{0}}
+except:
+ print('{0}')
+ traceback.print_exc()""".format(traceback_str)
+ self.do_block("""
+ import traceback
+ def __st_plot__(counter, _p_, format='notprovided', **kwargs):
+ if format == 'notprovided':
+ formats = ['eps', 'pdf']
+ else:
+ formats = [format]
+ for fmt in formats:
+ plotfilename = 'plot-%s.%s' % (counter, fmt)
+ _p_.save(filename=plotfilename, **kwargs)""")
+
+ def _encode(self, d):
+ return 'session={0}&'.format(self._session) + urllib.urlencode(d)
+
+ def _get_url(self, action, u):
+ with closing(urllib.urlopen(self._srv + '/simple/' + action +
+ '?' + u)) as h:
+ data = self._response.match(h.read())
+ result = json.loads(data.group('header'))
+ result['output'] = data.group('output').rstrip()
+ return result
+
+ def _get_file(self, fn, cell, ofn=None):
+ with closing(urllib.urlopen(self._srv + '/simple/' + 'file' + '?' +
+ self._encode({'cell': cell, 'file': fn}))) as h:
+ myfn = ofn if ofn else fn
+ data = h.read()
+ if not self._404.search(data):
+ with open(myfn, 'w') as f:
+ f.write(data)
+ else:
+ print('Remote server reported {0} could not be found:'.format(
+ fn))
+ print(data)
+% \end{macrocode}
+% The |code| below gets stuffed between a try/except, so make sure it's
+% indented!
+% \begin{macrocode}
+ def _do_cell(self, code):
+ realcode = self._codewrap.format(code)
+ result = self._get_url('compute', self._encode({'code': realcode}))
+ if result['status'] == 'computing':
+ cell = result['cell_id']
+ while result['status'] == 'computing':
+ sys.stdout.write('working...')
+ sys.stdout.flush()
+ time.sleep(10)
+ result = self._get_url('status', self._encode({'cell': cell}))
+ if debug:
+ print('cell: <<<', realcode, '>>>', 'result: <<<',
+ result['output'], '>>>', sep='\n')
+ return result
+
+ def do_inline(self, code):
+ return self._do_cell(' print(latex({0}))'.format(code))
+
+ def do_block(self, code):
+ result = self._do_cell(code)
+ for fn in result['files']:
+ self._get_file(fn, result['cell_id'])
+ return result
+
+ def do_plot(self, num, code, plotdir):
+ result = self._do_cell(' __st_plot__({0}, {1})'.format(num, code))
+ for fn in result['files']:
+ self._get_file(fn, result['cell_id'], os.path.join(plotdir, fn))
+ return result
+% \end{macrocode}
+% When using the simple server API, it's important to log out so the
+% server doesn't accumulate idle sessions that take up lots of memory.
+% We define a |close()| method and use this class with the |closing|
+% context manager that always calls |close()| on the way out.
+% \begin{macrocode}
+ def close(self):
+ sys.stdout.write('Logging out of {0}...'.format(server))
+ sys.stdout.flush()
+ self._get_url('logout', self._encode({}))
+ print('done')
+% \end{macrocode}
+% \end{macro}
+% Next we have a little pile of miscellaneous functions and variables
+% that we want to have at hand while doing our work. Note that we again
+% use the traceback string in the error-finding regular expression.
+% \begin{macrocode}
+def do_plot_setup(plotdir):
+ printc('initializing plots directory...')
+ if os.path.isdir(plotdir):
+ shutil.rmtree(plotdir)
+ os.mkdir(plotdir)
+ return True
+
+did_plot_setup = False
+plotdir = 'sage-plots-for-' + jobname + '.tex'
+
+def labelline(n, s):
+ return r'\newlabel{@sageinline' + str(n) + '}{{' + s + '}{}{}{}{}}\n'
+
+def printc(s):
+ print(s, end='')
+ sys.stdout.flush()
+
+error = re.compile("(^" + traceback_str + ")|(^Syntax Error:)", re.MULTILINE)
+
+def check_for_error(string, line):
+ if error.search(string):
+ print("""
+**** Error in Sage code on line {0} of {1}.tex!
+{2}
+**** Running Sage on {1}.sage failed! Fix {1}.tex and try again.""".format(
+ line, jobname, string))
+ sys.exit(1)
+% \end{macrocode}
+% Now let's actually start doing stuff.
+% \begin{macrocode}
+print('Processing Sage code for {0}.tex using remote Sage server.'.format(
+ jobname))
+
+if login_info_file:
+ with open(login_info_file, 'r') as f:
+ print('Reading login information from {0}.'.format(login_info_file))
+ get_val = lambda x: x.split('=')[1].strip().strip('\'"')
+ for line in f:
+ print(line)
+ if not line.startswith('#'):
+ if line.startswith('server') and not server:
+ server = get_val(line)
+ if line.startswith('username') and not username:
+ username = get_val(line)
+ if line.startswith('password') and not password:
+ password = get_val(line)
+
+if not server:
+ server = raw_input('Enter server: ')
+
+if not server.startswith('http'):
+ server = 'https://' + server
+
+if not username:
+ username = raw_input('Enter username: ')
+
+if not password:
+ from getpass import getpass
+ password = getpass('Please enter password for user {0} on {1}: '.format(
+ username, server))
+
+printc('Parsing {0}.sage...'.format(jobname))
+cmds = parsedotsage(jobname + '.sage')
+print('done.')
+
+sout = '% This file was *autogenerated* from the file {0}.sage.\n'.format(
+ os.path.splitext(jobname)[0])
+
+printc('Logging into {0} and starting session...'.format(server))
+with closing(RemoteSage(server, username, password)) as sage:
+ print('done.')
+ for cmd in cmds:
+ if cmd['type'] == 'inline':
+ printc('Inline formula {0}...'.format(cmd['num']))
+ result = sage.do_inline(cmd['code'])
+ check_for_error(result['output'], cmd['goboom'])
+ sout += labelline(cmd['num'], result['output'])
+ print('done.')
+ if cmd['type'] == 'block':
+ printc('Code block begin...')
+ result = sage.do_block(cmd['code'])
+ check_for_error(result['output'], cmd['goboom'])
+ print('end.')
+ if cmd['type'] == 'plot':
+ printc('Plot {0}...'.format(cmd['num']))
+ if not did_plot_setup:
+ did_plot_setup = do_plot_setup(plotdir)
+ result = sage.do_plot(cmd['num'], cmd['code'], plotdir)
+ check_for_error(result['output'], cmd['goboom'])
+ print('done.')
+ if cmd['type'] == 'pause':
+ print(cmd['msg'])
+ if int(time.time()) % 2280 == 0:
+ printc('Unscheduled offworld activation; closing iris...')
+ time.sleep(1)
+ print('end.')
+
+with open(jobname + '.sage', 'r') as sagef:
+ h = hashlib.md5()
+ for line in sagef:
+ if (not line.startswith(' _st_.goboom') and
+ not line.startswith("print 'SageT")):
+ h.update(line)
+% \end{macrocode}
+% Putting the |{1}| in the string, just to replace it with |%|, seems a
+% bit weird, but if I put a single percent sign there, Docstrip won't
+% put that line into the resulting |.py| file---and if I put two percent
+% signs, it replaces them with |\MetaPrefix| which is |##| when this
+% file is generated. This is a quick and easy workaround.
+% \begin{macrocode}
+ sout += """%{0}% md5sum of corresponding .sage file
+{1} (minus "goboom" and pause/unpause lines)
+""".format(h.hexdigest(), '%')
+
+printc('Writing .sout file...')
+with open(jobname + '.sout', 'w') as soutf:
+ soutf.write(sout)
+ print('done.')
+print('Sage processing complete. Run LaTeX on {0}.tex again.'.format(jobname))
+% \end{macrocode}
+
+% \endinput
+%</remotesagetex>
+% Local Variables:
+% mode: doctex
+% TeX-master: "sagetexpackage"
+% End:
diff --git a/Master/texmf-dist/source/latex/sagetex/sagetexpackage.dtx b/Master/texmf-dist/source/latex/sagetex/sagetexpackage.dtx
index 95be02d58d0..6b6acfd8f4e 100644
--- a/Master/texmf-dist/source/latex/sagetex/sagetexpackage.dtx
+++ b/Master/texmf-dist/source/latex/sagetex/sagetexpackage.dtx
@@ -1,22 +1,24 @@
% \iffalse meta-comment
%
-% Copyright (C) 2008 by Dan Drake <ddrake@member.ams.org>
+% Copyright (C) 2009 by Dan Drake <ddrake (at) member (dot) ams (dot) org>
% -------------------------------------------------------
%
-% See the "Copying and licenses" section for the terms under which this
-% source code and documentation may be modified and distributed.
+% See the "Copying and licenses" section in this file for the terms
+% under which this source code and documentation may be modified and
+% distributed.
%
% This package is not licensed under the LPPL, but it seems reasonable
% to say:
%
% This work has the LPPL maintenance status `maintained'.
-%
+%
% The Current Maintainer of this work is Dan Drake.
%
-% This work consists of the files sagetexpackage.dtx,
-% sagetexpackage.ins, example.tex, and the derived files sagetex.sty
-% and sagetex.py.
-%
+% This work consists of the files sagetexpackage.dtx, py-and-sty.dtx,
+% scripts.dtx, remote-sagetex.dtx, sagetexpackage.ins, example.tex,
+% and the derived files sagetex.sty, sagetex.py, sagetexparse.py,
+% makestatic.py, extractsagecode.py, and remote-sagetex.py.
+%
% \fi
%
% \iffalse
@@ -25,27 +27,112 @@
%</driver>
%<latex>\NeedsTeXFormat{LaTeX2e}
%<latex>\ProvidesPackage{sagetex}
-%<*latex>
- [2008/03/12 v1.4 embedding Sage into LaTeX documents]
-%</latex>
+%<python>__version__ = """
+%<*latex|python>
+ [2009/06/17 v2.2.1 embedding Sage into LaTeX documents]
+%</latex|python>
+%<python>"""
%<*driver>
\documentclass{ltxdoc}
\usepackage{sagetex}
\usepackage{xspace}
\usepackage{tikz}
\usepackage{hyperref}
-\EnableCrossrefs
+% \iffalse
+% Work around a problem with using Docstrip and hyperref; for macros and
+% such described with DescribeMacro and friends, plain Docstrip puts
+% something like this into the .idx file:
+%
+% \indexentry{sage=\verb!*+\sage+|usage}{5}
+%
+% and defines \usage{}. hyperref comes along and sneakily alters those
+% lines and adds:
+%
+% \indexentry{sage=\verb!*+\sage+|usage|hyperpage}{5}
+%
+% and makeindex gets confused because you can't have two | things in one
+% indexentry. I could probably figure out how to fix this in LaTeX, but
+% it's easier to run sed on the .idx file to remove the extra | and
+% define a new macro that makes the text italic and puts in the
+% hyperlink.
+%
+% Another option is to forget about all this and just pass the
+% hyperindex=false option to hyperref, but then you don't get
+% hyperlinked page numbers.
+% \fi
+\newcommand{\usagehyperpage}[1]{\textit{\hyperpage{#1}}}
+
+\renewcommand{\subsubsectionautorefname}{section}
+\renewcommand{\subsectionautorefname}{section}
+\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
- \DocInput{sagetexpackage.dtx}
- \PrintChanges
- \PrintIndex
+\DocInput{sagetexpackage.dtx}
+\StopEventually{
+\section{Credits and acknowledgments}
+
+According to the original README file, this system was originally done
+by Gonzalo Tornaria and Joe Wetherell. Later Harald Schilly made some
+improvements and modifications. Almost all the examples in the
+|example.tex| file are from Harald.
+
+Dan Drake rewrote and extended the style file (there is effectively zero
+original code there), made significant changes to the Python module, put
+both files into \textsf{Docstrip} format, and wrote all the
+documentation and extra Python scripts.
+
+Many thanks to Jason Grout for his numerous comments, suggestions, and
+feedback.
+
+\section{Copying and licenses}
+\label{sec:copying-licenses}
+
+If you are unnaturally curious about the current state of the \ST
+package, you can visit \url{http://www.bitbucket.org/ddrake/sagetex/}.
+There is a Mercurial repository and other stuff there.
+
+As for the terms and conditions under which you can copy and modify \ST:
+
+The \emph{source code} of the \ST package may be redistributed and/or
+modified under the terms of the GNU General Public License as published
+by the Free Software Foundation, either version 2 of the License, or (at
+your option) any later version. To view a copy of this license, see
+\url{http://www.gnu.org/licenses/} or send a letter to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.
+
+The \emph{documentation} of the \ST package is licensed under the
+Creative Commons Attribution-Noncommercial-Share Alike 3.0 License. To
+view a copy of this license, visit
+\url{http://creativecommons.org/licenses/by-nc-sa/3.0/} or send a letter
+to Creative Commons, 171 Second Street, Suite 300, San Francisco,
+California, 94105, USA.
+
+\iffalse meta-comment
+ I've run into a situation where the index wants to start on the very
+ last line of the page, and I actually get errors: ``Package multicol
+ Error: Error saving partial page.'' The problem goes away if I fiddle
+ with some lines so that the index starts elsewhere. Putting in a
+ clearpage below makes the index start nicely in the middle of a page
+ (until my change history gets too long!) and solves all those
+ problems. It can be removed/pulled into this comment if you're
+ confident the page break problems won't occur.
+\clearpage
+\fi
+}
+
+\DocInput{py-and-sty.dtx}
+\DocInput{scripts.dtx}
+\DocInput{remote-sagetex.dtx}
+\Finale
+\PrintChanges
+\PrintIndex
\end{document}
%</driver>
% \fi
%
-% \CheckSum{0}
+% \CheckSum{335}
%
% \CharacterTable
% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
@@ -65,47 +152,62 @@
%
% \changes{v1.0}{2008/03/03}{Initial version}
% \changes{v1.1}{2008/03/05}{Wrapped user-provided Sage code in
-% try/except clauses; plotting now has optional format argument.}
+% try/except clauses; plotting now has optional format argument}
% \changes{v1.2}{2008/03/07}{Imagemagick option; better documentation}
% \changes{v1.3.1}{2008/03/10}{Internal variables renamed; fixed typos}
% \changes{v1.4}{2008/03/11}{MD5 fix, percent sign macro, CTAN upload}
+% \changes{v2.0}{2008/12/16}{External Python scripts for parsing
+% SageTeX-ified documents, tons of documentation improvements,
+% sagetex.py refactored, include in Sage as spkg}
+% \changes{v2.0}{2009/01/09}{Miscellaneous fixes, final 2.0 version}
+% \changes{v2.1}{2009/05/12}{Add pausing support}
+% \changes{v2.1}{2009/05/12}{Get version written to .py file}
+% \changes{v2.2}{2009/06/17}{Add remote-sagetex.py script}
%
-% \GetFileInfo{sagetexpackage.dtx}
+% \GetFileInfo{sagetex.sty}
%
% \DoNotIndex{\newcommand,\newenvironment,\the}
-%
-% \newcommand{\ST}{\textsf{sagetex}\xspace}
+%
+% \newcommand{\ST}{\textsf{Sage\TeX}\xspace}
% \iffalse
% so I don't have to put \ or {} after \LaTeX:
% \fi
% \newcommand{\LTX}{\LaTeX\xspace}
%
+% \newcommand{\TikZ}{Ti\emph{k}Z\xspace}
+%
+% \newcommand{\warningbox}[1]{\colorbox[rgb]{1, 0.6, 0.6}%
+% {\parbox{.97\textwidth}{#1}}}
+%
+% \tikzstyle{box}=[draw, shape=rectangle, thick]
+%
+% \title{The \ST{} package\thanks{This document corresponds to
+% \ST \fileversion, dated \filedate.}}
+%
+% \author{Dan Drake and others\thanks{Author's website:
+% \href{http://mathsci.kaist.ac.kr/~drake/}
+% {\texttt{mathsci.kaist.ac.kr/$\sim$drake/}}.}}
+%
% \iffalse
-% For some reason, getting a blackslash in a typewriter font to print
-% inside an fbox is really hard. Verbatim stuff doesn't work because
-% it's fragile. This code works; it's copied out of Scott Pakin's
-% dtxtut.tex.
-%
-% There is \textbackslash but I don't like how that looks.
+% Don't put any other code from this file into the .sty or .py
+% file:
+%<*!latex&!python>
+% This lets us use verbatim environments in the documentation.
% \fi
-% {\catcode`\|=0 \catcode`\\=12
-% |gdef|bslash{\}}
-%
-% \title{The \ST{} package\thanks{This document
-% corresponds to \textsf{sagetex}~\fileversion, dated \filedate.}}
-% \author{Dan Drake (\texttt{ddrake@member.ams.org}) and others}
%
% \maketitle
%
% \section{Introduction}
%
-% Why should the Haskell folks have all the fun?
-%
+% Why should the Haskell and R folks have all the fun?
% \href{http://www.haskell.org/haskellwiki/Literate_programming}{Literate
-% Haskell} is a popular way to mix Haskell source code and \LTX
-% documents. (Well, actually any kind of text or document, but here
-% we're concerned only with \LTX.) You can even embed Haskell code in
-% your document that writes part of your document for you.
+% Haskell} is a popular way to mix Haskell source code and \LTX
+% documents. (Actually any kind of text or document, but here we're
+% concerned only with \LTX.) You can even embed Haskell code in your
+% document that writes part of your document for you. Similarly, the R
+% statistical computing environment includes
+% \href{http://tug.org/pracjourn/2008-1/zahn/}{Sweave}, which lets you
+% do the same thing with R code and \LTX.
%
% The \ST package allows you to do (roughly) the same thing with the
% Sage mathematics software suite (see \url{http://sagemath.org}) and
@@ -116,27 +218,28 @@
% digits. With this package, you can write something like this:
% \begin{quote}
% |There are $26$ choices for each letter, and $10$ choices for|\\
-% |each digit, for a total of $26^3*10^3 = \sage{26^3*10^3}$|\\
-% |license plates.|
+% |each digit, for a total of $26^3 \cdot 10^3 =|\\
+% |\sage{26^3*10^3}$ license plates.|
% \end{quote}
% and it will produce
% \begin{quote}
% There are $26$ choices for each letter, and $10$ choices for each
-% digit, for a total of $\sage{26^3 * 10^3}$ license plates.
+% digit, for a total of $26^3 \cdot 10^3 = \sage{26^3 * 10^3}$ license
+% plates.
% \end{quote}
% The great thing is, you don't have to do the multiplication. Sage does
-% it for you. This process mirrors one of the great aspects of
-% \LTX: when writing a \LTX document, you can concentrate on the
-% logical structure of the document and trust \LTX and its army of
-% packages to deal with the presentation and typesetting. Similarly,
-% with \ST, you can concentrate on the mathematical
-% structure (``I need the product of $26^3$ and $10^3$'') and let Sage
-% deal with the base-$10$ presentation of the number.
+% it for you. This process mirrors one of the great aspects of \LTX:
+% when writing a \LTX document, you can concentrate on the logical
+% structure of the document and trust \LTX and its army of packages to
+% deal with the presentation and typesetting. Similarly, with \ST, you
+% can concentrate on the mathematical structure (``I need the product of
+% $26^3$ and $10^3$'') and let Sage deal with the base-$10$ presentation
+% of the number.
%
% A less trivial, and perhaps more useful example is plotting. You can
% include a plot of the sine curve without manually producing a plot,
-% saving an EPS or PDF file, and doing the |\includegraphics|
-% business with the correct filename yourself. If you write this:
+% saving an EPS or PDF file, and doing the |\includegraphics| business
+% with the correct filename yourself. If you write this:
% \begin{quote}
% |Here is a lovely graph of the sine curve:|
%
@@ -157,8 +260,8 @@
% convince you that \ST makes putting nice graphics into your document
% very easy; let me turn around and warn you that using graphics
% \emph{well} is not easy, and no \LTX package or Python script will
-% ever make it easy. What \ST does is make it easy to \emph{use Sage}
-% to create graphics; it doesn't magically make your graphics good,
+% ever make it easy. What \ST does is make it easy to \emph{use Sage} to
+% create graphics; it doesn't magically make your graphics good,
% appropriate, or useful. (For instance, look at the sine plot above---I
% would say that a truly lovely plot of the sine curve would not mark
% integer points on the $x$-axis, but rather $\pi/2$, $\pi$, $3\pi/2$,
@@ -166,7 +269,7 @@
%
% Till Tantau has some good commentary on the use of graphics in
% \href{http://www.ctan.org/tex-archive/graphics/pgf/}{section 6 of the
-% \textsc{pgf} manual}. You should always give careful thought and
+% \textsc{pgf} manual}. You should always give careful thought and
% attention to creating graphics for your document; I have in mind that
% a good workflow for using \ST for plotting is something like this:
%
@@ -183,44 +286,132 @@
% Sage commands to make your lovely plot, but they do eliminate the need
% to muck around with saving the result to a file, remembering the
% filename, including it into your document, and so on. In
-% \autoref{s:usage}, we will see what what we can do with \ST.
-%
-%
-% \section{Installation}
+% \autoref{sec:usage}, we will see what what we can do with \ST.
%
-% The simplest way to ``install'' \ST is to copy the files
-% |sagetex.sty| and |sagetex.py| into the same directory
-% as your document. This will always work, as \LTX and Python search the
-% current directory for files. It is also convenient for zipping up a
-% directory to send to a colleague who is not yet enlightened enough to
-% be using \ST.
%
-% Rather than make lots of copies of those files, you can keep them in
-% one place and update the TEXINPUTS and PYTHONPATH environment
-% variables appropriately.
-%
-% Perhaps the best solution is to put the files into a directory
-% searched by \TeX{} and friends, and then edit the |sagetex.sty| file
-% so that the |.sage| files we generate update Python's path
-% appropriately---look for ``Python path'' in |sagetex.sty|. This is
-% suitable for a system-wide installation, or if you are the kind of
-% person who keeps a |texmf| tree in your home directory.
+% \section{Installation}
+% \label{sec:installation}
+% \changes{v2.0}{2009/01/14}{Fixed up installation section, final
+% \emph{final} 2.0}
+%
+% To install \ST, you need to do two things: make \ST known to Sage, and
+% to \LTX. There are two basic methods to do those two things.
+%
+% \newcommand{\sageroot}{\$SAGE\_ROOT}
+%
+% In what follows, ``\texttt{\sageroot}'' refers to the root directory
+% of your Sage installation.
+%
+% \subsection{As a Sage spkg}
+% \label{sec:install-spkg}
+%
+% The easiest way to install \ST is by using Sage's own spkg
+% installation facility; visit the
+% \href{http://sagemath.org/packages/optional/}{optional packages page}
+% and run \texttt{sage -i} with the appropriate file name. This will let
+% Sage know about \ST; you still need to let \LTX know about it.
+%
+% The simplest way to ``install'' \ST for \LTX is to copy the file
+% |sagetex.sty| from \texttt{\sageroot/local/share/texmf} to the same
+% directory as your document. This will always work, as \LTX always
+% searches the current directory for files.
+%
+% Rather than make lots of copies of |sagetex.sty|, you can keep it (and
+% the rest of the \ST documentation) in a |texmf| directory. The easiest
+% thing to do is to create a |texmf| directory in your home directory
+% and use the |texhash| utility so that your \TeX{} system can find the
+% new files. See
+% \href{http://www.tex.ac.uk/cgi-bin/texfaq2html?label=privinst}
+% {\texttt{www.tex.ac.uk/cgi-bin/texfaq2html?label=privinst}} which
+% describes the basic ideas, and also
+% \href{http://www.tex.ac.uk/cgi-bin/texfaq2html?label=what-TDS}
+% {\texttt{www.tex.ac.uk/cgi-bin/texfaq2html?label=what-TDS}} which has
+% some information specific to MiK\TeX. Linux/Unix users can use
+% |$HOME/texmf| and users of Mac\TeX{} should use |$HOME/Library/texmf|.
+%
+% To copy the files that \LTX needs into your |texmf| directory, simply
+% do
+% \begin{quote}
+% \texttt{cp -r \sageroot/local/share/texmf/* HOMEPREFIX/texmf/}
+% \end{quote}
+% where |HOMEPREFIX| is the appropriate prefix for your own |texmf|
+% tree. Then you need to make \TeX{} aware of the new files by running
+% \begin{quote}
+% \texttt{texhash HOMEPREFIX/texmf/}
+% \end{quote}
%
+% \subsection{From CTAN}
+% \label{sec:install-ctan}
+%
+% You can also get \ST from \href{http://tug.ctan.org/pkg/sagetex}{its
+% CTAN page}. This is not the recommended way to get \ST, but it will
+% work.
+%
+% If you get \ST from CTAN, you will need to make the |sagetex.sty| file
+% available to \LTX using any of the methods described above, and you
+% will also need to make |sagetex.py| known to Sage. You can either keep
+% a copy of that file in the same directory as your document or put it
+% where Sage will find it. You can use the |$SAGE_PATH| environment
+% variable (which is analogous to the |$PYTHONPATH| variable) to tell
+% Sage where the file is, or manually copy |sagetex.py| into
+% \texttt{\sageroot/local/lib/python/site-packages}.
+%
+% \subsection{Using \TeX Shop}
+% \label{sec:using-texshop}
+% \changes{v2.0.1}{2009/03/10}{Add \TeX Shop info}
+%
+% Starting with version 2.25,
+% \href{http://www.uoregon.edu/~koch/texshop/}{\TeX Shop} includes
+% support for \ST. If you move the file |sage.engine| from
+% |~/Library/TeXShop/Engines/Inactive/Sage| to
+% |~/Library/TeXShop/Engines| and put the line
+% \begin{quotation}
+% |%!TEX TS-program = sage|
+% \end{quotation}
+% at the top of your document, then \TeX Shop will automatically run Sage
+% for you when compiling your document.
+%
+% Note that you will need to make |sagetex.sty| and |sagetex.py| known
+% to \LTX and Sage using any of the methods described above (although
+% note that \TeX Shop includes copies of these files for you). You also
+% might need to edit the |sage.engine| script to reflect the location of
+% your Sage installation.
+%
+% \subsection{Other scripts included with \ST}
+% \label{sec:inst-other-scripts}
+%
+% \ST includes several Python files which may be useful for working with
+% ``\ST-ified'' documents. The |remote-sagetex.py| script allows you to
+% use \ST on a computer that doesn't have Sage installed; see
+% \autoref{sec:remote-sagetex} for more information.
+%
+% Also included are |makestatic.py| and |extractsagecode.py|, which are
+% convenience scripts that you can use after you've written your
+% document. See \autoref{sec:makestatic-usage} and
+% \autoref{sec:extractsagecode} for information on using those scripts.
+% The file |sagetexparse.py| is a module used by both those scripts.
+% These three files are independent of \ST. If you install from a spkg,
+% these scripts can be found in \texttt{\sageroot/local/share/texmf/}.
+%
+% \section{Usage}
+% \label{sec:usage}
%
-% \section{Usage} \label{s:usage}
-%
% Let's begin with a rough description of how \ST works. Naturally the
% very first step is to put |\usepackage{sagetex}| in the preamble of
% your document. When you use macros from this package and run \LTX on
% your file, along with the usual zoo of auxiliary files, a |.sage| file
-% is written. This is a Sage source file that uses the Python module
-% from this package and when you run Sage on that file, it will produce
-% a |.sout| file. That file contains \LTX code which, when you run \LTX
-% on your source file again, will pull in all the results of Sage's
-% computation.
+% is written with the same basename as your document. This is a Sage
+% source file that uses the Python module from this package and when you
+% run Sage on that file, it will produce a |.sout| file. That file
+% contains \LTX code that, when you run \LTX on your source file again,
+% will pull in all the results of Sage's computation.
%
% All you really need to know is that to typeset your document, you need
-% to run \LTX, then run Sage, then run \LTX again.
+% to run \LTX, then run Sage, then run \LTX again. You can even ``run
+% Sage'' on a computer that doesn't have Sage installed by using the
+% |remote-sagetex.py| script; see \autoref{sec:remote-sagetex}. Whenever
+% this manual says ``run Sage'', you can either directly run Sage, or
+% use the |remote-sagetex.py| script.
%
% Also keep in mind that everything you send to Sage is done within one
% Sage session. This means you can define variables and reuse them
@@ -235,15 +426,31 @@
% look through the |example.tex| file included with this
% package.\footnote{Then again, if you're such a person, you're probably
% not reading this, and are already fiddling with
-% \texttt{example.tex}\dots}
+% \texttt{example.tex}\dots}\\
+%
+% \noindent\warningbox{\textbf{WARNING!} When you run \LTX on a file
+% named \texttt{\meta{filename}.tex}, the file
+% \texttt{\meta{filename}.sage} is created---and will be
+% \emph{automatically overwritten} if it already exists. If you keep
+% Sage scripts in the same directory as your \ST-ified \LTX documents,
+% use a different file name!}
+%
+% \paragraph{The final option} On a similar note, \ST, like many \LTX
+% packages, accepts the |final| option. When passed this option, either
+% directly in the |\usepackage| line, or from the |\documentclass| line,
+% \ST will not write a |.sage| file. It will try to read in the |.sout|
+% file so that the \ST macros can pull in their results. However, this
+% will not allow you to have an independent Sage script with the same
+% basename as your document, since to get the |.sout| file, you need the
+% |.sage| file.
%
% \subsection{Inline Sage}
+% \label{sec:sagemacro-usage}
%
-% \DescribeMacro{\sage}
+% \DescribeMacro{sage}
% \fbox{\texttt{\bslash sage}\marg{Sage code}}
-%
-% \noindent takes whatever Sage code you give it, runs Sage's |latex|
-% function on it, and puts the result into your document.
+% takes whatever Sage code you give it, runs Sage's |latex| function on
+% it, and puts the result into your document.
%
% For example, if you do |\sage{matrix([[1, 2], [3,4]])^2}|, then that
% macro will get replaced by
@@ -265,14 +472,28 @@
% you have defined the Sage variable |foo| to be $12$ (using, say, the
% |sageblock| environment), then you can do something like this:
% \begin{quote}
-% |The prime factorization of the current page plus foo is|\\
-% |$\sage{factor(foo + \thepage)}$|.
+% |The prime factorization of the current page number plus foo|\\
+% |is $\sage{factor(foo + \thepage)}$|.
% \end{quote}
-% Here, I'll do just that right now: the prime factorization of the
-% current page plus $12$ is $\sage{factor(\thepage + 12)}$.
%
-% The |\sage| command doesn't automatically use math mode for its
-% output, so be sure to use dollar signs or a displayed math environment
+% Here, I'll do just that right now: the prime factorization of the
+% current page number plus $12$ is $\sage{factor(\thepage + 12)}$.
+% (Wrong answer? See footnote.\footnote{Is the above factorization
+% wrong? If the current page number plus $12$ is one larger than the
+% claimed factorization, another Sage/\LTX cycle on this source file
+% should fix it. Why? The first time you run \LTX on this file, the
+% sine graph isn't available, so the text where I've talked about the
+% prime factorization is back one page. Then you run Sage, and it
+% creates the sine graph and does the factorization. When you run \LTX
+% again, the sine graph pushes the text onto the next page, but it
+% uses the Sage-computed value from the previous page. Meanwhile, the
+% |.sage| file has been rewritten with the correct page number, so if
+% you do another Sage/\LTX cycle, you should get the correct value
+% above. However, in some cases, even \emph{that} doesn't work because
+% of some kind of \TeX{} weirdness in ending the one page a bit short
+% and starting another.}) The |\sage| command doesn't automatically
+% use math mode for its output, so be sure to use dollar signs or a
+% displayed math environment
% as appropriate.\\
%
% \DescribeMacro{\percent} If you are doing modular arithmetic or string
@@ -284,17 +505,17 @@
% will get confused. The |\percent| macro makes everyone happy.
%
% Note that using |\percent| inside the verbatim-like environments
-% described in \autoref{s:codeblockenv} isn't necessary; a literal
+% described in \autoref{sec:codeblockenv} isn't necessary; a literal
% ``\percent'' inside such an environment will get written, uh, verbatim
% to the |.sage| file.
%
% \subsection{Graphics and plotting}
+% \label{sec:graphics-plotting}
%
% \noindent \DescribeMacro{\sageplot}
% \fbox{\texttt{\bslash sageplot}\oarg{ltx opts}\oarg{fmt}\{\meta{graphics
% obj}, \meta{keyword args}\}}
-%
-% \noindent plots the given Sage graphics object and runs an
+% plots the given Sage graphics object and runs an
% |\includegraphics| command to put it into your document. It does not
% have to actually be a plot of a function; it can be any Sage graphics
% object. The options are described in \autoref{t:sageplotopts}.
@@ -351,9 +572,12 @@
% to colleagues.
%
% If you ask for, say, a PNG file, keep in mind that ordinary |latex|
-% and DVI files have no support for DVI files; \ST detects this and will
-% warn you that it cannot find a suitable file if using |latex|. If you
-% use |pdflatex|, there will be no problems because PDF files can
+% and DVI files have no support for PNG files; \ST detects this and will
+% warn you that it cannot find a suitable file if using
+% |latex|.\footnote{We use a typewriter font here to indicate the
+% executables which produce DVI and PDF files, respectively, as
+% opposed to ``\LTX'' which refers to the entire typesetting system.}
+% If you use |pdflatex|, there will be no problems because PDF files can
% include PNG graphics.
%
% When \ST cannot find a graphics file, it inserts this into your
@@ -362,7 +586,7 @@
% \begin{center}
% \framebox[2cm]{\rule[-1cm]{0cm}{2cm}\textbf{??}}
% \end{center}
-%
+%
% \noindent That's supposed to resemble the image-not-found graphics
% used by web browsers and use the traditional ``\textbf{??}'' that \LTX
% uses to indicate missing references.
@@ -373,42 +597,47 @@
% anytime; if \ST can't find the files, it will warn you to run Sage to
% regenerate them.\\
%
-% \noindent\fbox{\parbox{\textwidth}{\textbf{WARNING!} When you run Sage
-% on your |.sage| file, all files in the
-% \texttt{sage-plots-for-filename.tex} directory \emph{will be deleted!}
-% Do not put any files into that directory that you do not want to get
-% automatically deleted.}}
+% \noindent\warningbox{\textbf{WARNING!} When you run Sage on your
+% |.sage| file, all files in the
+% \texttt{sage-plots-for-\meta{filename}.tex} directory \emph{will be
+% deleted!} Do not put any files into that directory that you do not
+% want to get automatically deleted.}
+%
+% \paragraph{The epstopdf option} One of the graphics-related options
+% supported by \ST is |epstopdf|. This option causes \ST to use the
+% |epstopdf| command to convert EPS files into PDF files. Like with the
+% |imagemagick| option, it doesn't check to see if the |epstopdf|
+% command exists or add options: it just runs the command. This option
+% was motivated by a bug in the matplotlib PDF backend which caused it
+% to create invalid PDFs. Ideally, this option should never be
+% necessary; if you do need to use it, file a bug!
%
% \subsubsection{3D plotting}
%
% Right now there is, to put it nicely, a bit of tension between the
% sort of graphics formats supported by |latex| and |pdflatex|, and the
-% graphics formats supported by Sage's 3D plotting systems.\footnote{We
-% use a typewriter font here to indicate the binaries which produce DVI
-% and PDF files, respectively, as opposed to ``\LTX'' which refers to
-% the entire typesetting system.} \LTX is happiest, and produces the
-% best output, with EPS and PDF files, which are vector formats.
-% Tachyon, Sage's 3D plotting system, produces bitmap formats like BMP
-% and PNG.
-%
-% Because of this, when producing 3D plots with |\sageplot|,
-% \emph{you must specify a file format}. The PNG format is compressed
-% and lossless and is by far the best choice, so use that whenever
-% possible. (Right now, it is always possible.) If you do not specify a
-% file format, or specify one that Tachyon does not understand, it will
-% produce files in the Targa format with an incorrect extension and \LTX
-% (both |latex| and |pdflatex|) will be profoundly confused. Don't do
-% that.
-%
+% graphics formats supported by Sage's 3D plotting systems. \LTX is
+% happiest, and produces the best output, with EPS and PDF files, which
+% are vector formats. Tachyon, Sage's 3D plotting system, produces
+% bitmap formats like BMP and PNG.
+%
+% Because of this, when producing 3D plots with |\sageplot|, \emph{you
+% must specify a file format}. The PNG format is compressed and lossless
+% and is by far the best choice, so use that whenever possible. (Right
+% now, it is always possible.) If you do not specify a file format, or
+% specify one that Tachyon does not understand, it will produce files in
+% the Targa format with an incorrect extension and \LTX (both |latex|
+% and |pdflatex|) will be profoundly confused. Don't do that.
+%
% Since |latex| does not support PNGs, when using 3D plotting (and
-% therefore a bitmap format like PNG), \ST will \emph{always} issue a
-% warning about incompatible graphics if you use |latex|, provided
-% you've processed the |.sage| file and the PNG file exists. (Running
-% |pdflatex| on the same file will work, since PDF files can include PNG
-% files.)
+% therefore a bitmap format like PNG), \ST will always issue a warning
+% about incompatible graphics if you use |latex|, provided you've
+% processed the |.sage| file and the PNG file exists. The only exception
+% is if you're using the |imagemagick| option below. (Running |pdflatex|
+% on the same file will work, since PDF files can include PNG files.)
%
% \paragraph{The imagemagick option} As a response to the above issue,
-% the \ST package has one option: |imagemagick|. If you specify this
+% the \ST package has an |imagemagick| option. If you specify this
% option in the preamble of your document with the usual
% ``|\usepackage[imagemagick]{sagetex}|'', then when you are compiling
% your document using |latex|, any |\sageplot| command which requests a
@@ -423,7 +652,9 @@
% to see your graphics when you use |latex| and DVI files while writing
% your document.
%
-% \paragraph{But that's not good enough!} \label{s:notgoodenough}
+% \subsubsection{But that's not good enough!}
+% \label{sec:notgoodenough}
+%
% The |\sageplot| command tries to be both flexible and easy to use, but
% if you are just not happy with it, you can always do things manually:
% inside a |sagesilent| environment (see the next section) you could do
@@ -437,10 +668,10 @@
% turn off anything in \LTX, so you can always do things manually.
%
% \subsection{Verbatim-like environments}
-% \label{s:codeblockenv}
+% \label{sec:codeblockenv}
%
% The \ST package provides several environments for typesetting and
-% executing Sage code.\\
+% executing blocks of Sage code.\\
%
% \DescribeEnv{sageblock} Any text between |\begin{sageblock}| and
% |\end{sageblock}| will be typeset into your file, and also written into
@@ -449,9 +680,9 @@
% \begin{quote}
% |\begin{sageblock}|\\
% | var('x')|\\
-% | f = sin(x) - 1|\\
-% | g = log(x)|\\
-% | h = diff(f(x) * g(x), x)|\\
+% | f(x) = sin(x) - 1|\\
+% | g(x) = log(x)|\\
+% | h(x) = diff(f(x) * g(x), x)|\\
% |\end{sageblock}|
% \end{quote}
% and then anytime later write in your source file
@@ -460,7 +691,7 @@
% |the product of $f$ and $g$.|
% \end{quote}
% and the |\sage| call will get correctly replaced by $\sage{
-% diff((sin(x) - 1)*log(x), x)(1)}$. You can use any Sage or Python
+% diff((sin(x) - 1)*log(x), x)(x=1)}$. You can use any Sage or Python
% commands inside a |sageblock|; all the commands get sent directly to
% Sage.\\
%
@@ -471,9 +702,9 @@
% *don't* prefix the lines with percent signs, those lines get written
% into the .sty or .py file. It's just too tricky to get docstrip and
% the verbatim stuff to play nicely together. I'd have to redefine how
-% those environments work, and get them to strip off initial percents.
+% those environments work, and get them to strip off initial percents.
% \fi
-%
+%
% \DescribeEnv{sagesilent} This environment is like |sageblock|, but it
% does not typeset any of the code; it just writes it to the |.sage|
% file. This is useful if you have to do some setup in Sage that is not
@@ -495,15 +726,46 @@
% length |\sagetexindent|, which controls how much the Sage code is
% indented when typeset. You can change this length however you like
% with |\setlength|: do |\setlength{\sagetexindent}{6ex}| or whatever.
-%
+%
+% \subsection{Pausing \ST}
+% \label{sec:pausing-st-usage}
+%
+% Sometimes when you are writing a document, you may wish to temporarily
+% turn off or pause \ST to concentrate more on your document than on the
+% Sage computations, or to simply have your document typeset faster. You
+% can do this with the following commands.
+%
+% \DescribeMacro{\sagetexpause} \DescribeMacro{\sagetexunpause} Use
+% these macros to ``pause'' and ``unpause'' \ST. After issuing this
+% macro, \ST will simply skip over the corresponding calculations.
+% Anywhere a |\sage| macro is used while paused, you will simply see
+% \sagetexpause ``\sage{dummy call to sage to illustrate
+% pausing}'', and anywhere a |\sageplot| macro is used, you will see:\\
+%
+% \noindent
+% \sageplot{dummy call to sageplot to illustrate pausing}
+% \sagetexunpause\\
+%
+% \noindent Anything in the verbatim-like environments of
+% \autoref{sec:codeblockenv} will be typeset or not as usual, but none
+% of the Sage code will be executed.
+%
+% Obviously, you use |\sagetexunpause| to unpause \ST and return to the
+% usual state of affairs. Both commands are idempotent; issuing them
+% twice or more in a row is the same as issuing them once. This means
+% you don't need to precisely match pause and unpause commands: once
+% paused, \ST stays paused until it sees |\sagetexunpause| and
+% vice versa.
%
% \section{Other notes}
%
% Here are some other notes on using \ST.
%
-% \paragraph{Using Beamer} The \textsc{beamer} package does not play
-% nicely with verbatim-like environments. To use code block environments
-% in a \textsc{beamer} presentation, do:
+% \subsection{Using Beamer}
+%
+% The \textsc{beamer} package does not play nicely with verbatim-like
+% environments unless you ask it to. To use code block environments in a
+% \textsc{beamer} presentation, do:
% \begin{quote}
% |\begin{frame}[fragile]|\\
% |\begin{sageblock}|\\
@@ -513,24 +775,26 @@
% \end{quote}
% For some reason, \textsc{beamer} inserts an extra line break at the
% end of the environment; if you put the |\end{sageblock}| on the same
-% line as the last line of your code, it works properly.
+% line as the last line of your code, it works properly. See section
+% 12.9, ``Verbatim and Fragile Text'', in the \textsc{beamer} manual.
%
% Thanks to Franco Saliola for reporting this.
%
-% \paragraph{Plotting from Mathematica, Maple, etc.} Sage can use
-% Mathematica, Maple, and friends and can tell them to do plotting, but
-% since it cannot get those plots into a Sage graphics object, you
-% cannot use |\sageplot| to use such graphics. You'll need to use the
-% method described in ``But that's not good enough!''
-% (\hyperref[s:notgoodenough]{page~\pageref*{s:notgoodenough}}) with
-% some additional bits to get the directory right---otherwise your file
-% will get saved to someplace in a hidden directory.
+% \subsection{Plotting from Mathematica, Maple, etc.}
+%
+% Sage can use Mathematica, Maple, and friends and can tell them to do
+% plotting, but since it cannot get those plots into a Sage graphics
+% object, you cannot use |\sageplot| to use such graphics. You'll need
+% to use the method described in ``But that's not good enough!''
+% (\autoref{sec:notgoodenough}) with some additional bits to get the
+% directory right---otherwise your file will get saved to someplace in a
+% hidden directory.
%
% For Mathematica, you can do something like this inside a |sagesilent|
% or |sageblock| environment:
% \begin{quote}
-% |mathematica('plot = commands to make your plot')|\\
-% |mathematica('Export["%s/graphicsfile.eps", plot]' % os.getcwd())|
+% |mathematica('myplot = commands to make your plot')|\\
+% |mathematica('Export["%s/graphicsfile.eps", myplot]' % os.getcwd())|
% \end{quote}
% then put |\includegraphics[opts]{graphicsfile}| in your file.
%
@@ -545,795 +809,166 @@
% These interfaces, especially when plotting, can be finicky. The above
% commands are just meant to be a starting point.
%
+% \subsection{Sending \ST files to others who don't use Sage}
+% \label{sec:makestatic-usage}
+%
+% What can you do when sending a \LTX document that uses \ST to a
+% colleague who doesn't use Sage?\footnote{Or who cannot use Sage, since
+% currently \ST is not very useful on Windows.} The best option is to
+% bring your colleague into the light and get him or her using Sage! But
+% this may not be feasible, because some (most?) mathematicians are
+% fiercely crotchety about their choice of computer algebra system, or
+% you may be sending a paper to a journal or the arXiv, and such places
+% will not run Sage just so they can typeset your paper---at least not
+% until Sage is much closer to its goal of world domination.
+%
+% How can you send your \ST-enabled document to someone else who doesn't
+% use Sage? The easiest way is to simply include with your document the
+% following files:
+% \begin{enumerate}
+% \item |sagetex.sty|
+% \item the generated |.sout| file
+% \item the \texttt{sage-plots-for-\meta{filename}.tex} directory and
+% its contents
+% \end{enumerate}
+% As long as |sagetex.sty| is available, your document can be typeset
+% using any reasonable \LTX system. Since it is very common to include
+% graphics files with a paper submission, this is a solution that should
+% always work. (In particular, it will work with arXiv submissions.)
%
-% \StopEventually{}
-%
-% \section{Implementation}
-%
-% There are two pieces to this package: a \LTX style file, and a
-% Python module. They are mutually interdependent, so it makes sense to
-% document them both here.
-%
-% \subsection{The style file}
-%
-% \iffalse
-% tell docstrip to put code into the .sty file
-%<*latex>
-% \fi
-%
-% All macros and counters intended for use internal to this package
-% begin with ``|ST@|''.
-%
-% Let's begin by loading some packages. The key bits of |sageblock| and
-% friends are stol---um, adapted from the |verbatim| package manual. So
-% grab the |verbatim| package.
-% \begin{macrocode}
-\RequirePackage{verbatim}
-% \end{macrocode}
-% Unsurprisingly, the |\sageplot| command works poorly without graphics
-% support.
-% \begin{macrocode}
-\RequirePackage{graphicx}
-% \end{macrocode}
-% The |makecmds| package gives us a |\provideenvironment| which we need,
-% and we use |ifpdf| and |ifthen| in |\sageplot| so we know what kind of
-% files to look for.
-% \begin{macrocode}
-\RequirePackage{makecmds}
-\RequirePackage{ifpdf}
-\RequirePackage{ifthen}
-% \end{macrocode}
-%
-% Next set up the counters and the default indent.
-% \begin{macrocode}
-\newcounter{ST@inline}
-\newcounter{ST@plot}
-\setcounter{ST@inline}{0}
-\setcounter{ST@plot}{0}
-\newlength{\sagetexindent}
-\setlength{\sagetexindent}{5ex}
-% \end{macrocode}
-%
-% \begin{macro}{\ST@epsim}
-% By default, we don't use ImageMagick to create EPS files when a
-% non-default format is specified.
-% \begin{macrocode}
-\newcommand{\ST@epsim}{False}
-% \end{macrocode}
-% The expansion of that macro gets put into a Python function call, so
-% it works to have it be one of the strings ``|True|'' or ``|False|''.
-% \end{macro}
-%
-% Declare the |imagemagick| option and process it:
-% \begin{macrocode}
-\DeclareOption{imagemagick}{\renewcommand{\ST@epsim}{True}}
-\ProcessOptions\relax
-% \end{macrocode}
-% The |\relax| is a little incantation suggested by the ``\LaTeXe{} for
-% class and package writers'' manual, section 4.7.
-%
-% It's time to deal with files. Open the |.sage| file:
-% \begin{macrocode}
-\newwrite\ST@sf
-\immediate\openout\ST@sf=\jobname.sage
-% \end{macrocode}
-%
-% \begin{macro}{\ST@wsf}
-% We will write a lot of stuff to that file, so make a convenient
-% abbreviation, then use it to put the initial commands into the |.sage|
-% file. If you know what directory |sagetex.py| will be kept in, delete
-% the |\iffalse| and |\fi| lines in the generated style file
-% (\emph{don't} do it in the |.dtx| file) and change the directory
-% appropriately. This is useful if you have a |texmf| tree in your home
-% directory or are installing \ST system-wide; then you don't need to
-% copy |sagetex.py| into the same directory as your document.
-% \begin{macrocode}
-\newcommand{\ST@wsf}[1]{\immediate\write\ST@sf{#1}}
-\iffalse
-%% To get .sage files to automatically change the Python path to find
-%% sagetex.py, delete the \iffalse and \fi lines surrounding this and
-%% change the directory below to where sagetex.py can be found.
-\ST@wsf{import sys}
-\ST@wsf{sys.path.insert(0, 'directory with sagetex.py')}
-\fi
-\ST@wsf{import sagetex}
-\ST@wsf{sagetex.openout('\jobname')}
-% \end{macrocode}
-% \end{macro}
-% Pull in the |.sout| file if it exists, or do nothing if it doesn't. I
-% suppose we could do this inside an |AtBeginDocument| but I don't see
-% any particular reason to do that. It will work whenever we load it.
-% \begin{macrocode}
-\InputIfFileExists{\jobname.sout}{}{}
-% \end{macrocode}
-%
-% Now let's define the cool stuff.
-%
-% \begin{macro}{\sage}
-% This macro combines |\ref|, |\label|, and Sage all at once. First, we
-% use Sage to get a \LTX representation of whatever you give this
-% function. The Sage script writes a |\newlabel| line into the |.sout|
-% file, and we read the output using the |\ref| command. Usually, |\ref|
-% pulls in a section or theorem number, but it will pull in arbitrary
-% text just as well.
-%
-% The first thing it does it write its argument into the |.sage| file,
-% along with a counter so we can produce a unique label. We wrap a
-% try/except around the function call so that we can provide a more
-% helpful error message in case something goes wrong. (In particular, we
-% can tell the user which line of the |.tex| file contains the offending
-% code.)
-% \begin{macrocode}
-\newcommand{\sage}[1]{%
-\ST@wsf{try:}%
-\ST@wsf{ sagetex.inline(\theST@inline, #1)}%
-\ST@wsf{except:}%
-\ST@wsf{ sagetex.goboom(\the\inputlineno)}%
-% \end{macrocode}
-% Our use of |\newlabel| and |\ref| seems awfully clever until you load
-% the |hyperref| package, which gleefully tries to hyperlink the hell
-% out of everything. This is great until it hits one of our special
-% |\newlabel|s and gets deeply confused. Fortunately the |hyperref|
-% folks are willing to accomodate people like us, and give us a
-% |NoHyper| environment.
-% \begin{macrocode}
-\begin{NoHyper}\ref{@sagelabel\theST@inline}\end{NoHyper}%
-% \end{macrocode}
-% Now check to see if the label has already been defined. (The internal
-% implementation of labels in \LTX involves defining a function
-% ``|r@@labelname|''.) If it hasn't, we set a flag so that we can tell
-% the user to run Sage on the |.sage| file at the end of the run.
-% Finally, step the counter.
-% \begin{macrocode}
-\@ifundefined{r@@sagelabel\theST@inline}{\gdef\ST@rerun{x}}{}%
-\stepcounter{ST@inline}}
-% \end{macrocode}
-% \end{macro}
-% The user might load the |hyperref| package after this one (indeed, the
-% |hyperref| documentation insists that it be loaded last) or not at
-% all---so when we hit the beginning of the document, provide a dummy
-% |NoHyper| environment if one hasn't been defined by the |hyperref|
-% package.
-% \begin{macrocode}
-\AtBeginDocument{\provideenvironment{NoHyper}{}{}}
-% \end{macrocode}
-%
-% \begin{macro}{\percent}
-% A macro that inserts a percent sign. This is more-or-less stolen from the
-% \textsf{Docstrip} manual; there they change the catcode inside a group
-% and use |gdef|, but here we try to be more \LaTeX y and use
-% |\newcommand|.
-% \begin{macrocode}
-\catcode`\%=12
-\newcommand{\percent}{%}
-\catcode`\%=14
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\ST@plotdir}
-% A little abbreviation for the plot directory. We don't use
-% |\graphicspath| because it's
-% \href{http://www.tex.ac.uk/cgi-bin/texfaq2html?label=graphicspath}{
-% apparently slow}---also, since we know right where our plots are
-% going, no need to have \LTX looking for them.
-% \begin{macrocode}
-\newcommand{\ST@plotdir}{sage-plots-for-\jobname.tex}
-% \end{macrocode}
-% \end{macro}
-%
-% \tikzstyle{box}=[draw, shape=rectangle, thick]
-%
-% \begin{macro}{\sageplot}
-% \changes{v1.3}{2008/03/08}{Iron out warnings, cool Ti\emph{k}Z flowchart}
-% This function is similar to |\sage|. The neat thing that we take
-% advantage of is that commas aren't special for arguments to \LTX
-% commands, so it's easy to capture a bunch of keyword arguments that
-% get passed right into a Python function.
-%
-% This macro has two optional arguments, which can't be defined using
-% \LTX's |\newcommand|; we use Scott Pakin's brilliant
-% \href{http://tug.ctan.org/tex-archive/support/newcommand/}{|newcommand|}
-% package to create this macro; the options I fed to his script were
-% similar to this:
-%\begin{center}
-% |MACRO sageplot OPT[#1={width}] OPT[#2={notprovided}] #3|
-%\end{center}
-% Observe that we are using a Python script to write \LTX code which
-% writes Python code which writes \LTX code. Crazy!
-%
-% Here's the wrapper command which does whatever magic we need to get
-% two optional arguments.
-% \begin{macrocode}
-\newcommand{\sageplot}[1][width=.75\textwidth]{%
- \@ifnextchar[{\ST@sageplot[#1]}{\ST@sageplot[#1][notprovided]}%]
-}
-% \end{macrocode}
-% That percent sign followed by a square bracket seems necessary; I have
-% no idea why.
-%
-% The first optional argument |#1| will get shoved right into the
-% optional argument for |\includegraphics|, so the user has easy control
-% over the \LTX aspects of the plotting. We define a
-% default size of $3/4$ the textwidth, which seems reasonable. (Perhaps
-% a future version of \ST will allow the user to specify in the package
-% options a set of default options to be used throughout.) The
-% second optional argument |#2| is the file format and allows us to tell
-% what files to look for. It defaults to ``notprovided'', which tells
-% the Python module to create EPS and PDF files. Everything in |#3| gets
-% put into the Python function call, so the user can put in keyword
-% arguments there which get interpreted correctly by Python.
-%
-% \begin{macro}{\ST@sageplot} Let's see the real code here. We write a
-% couple lines to the |.sage| file, including a counter, input line
-% number, and all of the mandatory argument; all this is wrapped in
-% another try/except. Note that the |\write| gobbles up line endings, so
-% the |sageplot| bits below get written to the |.sage| file as one line.
-% \begin{macrocode}
-\def\ST@sageplot[#1][#2]#3{%
-\ST@wsf{try:}%
-\ST@wsf{ sagetex.initplot('\jobname')}%
-\ST@wsf{ sagetex.plot(\theST@plot, #3, format='#2', epsmagick=\ST@epsim)}%
-\ST@wsf{except:}%
-\ST@wsf{ sagetex.goboom(\the\inputlineno)}%
-% \end{macrocode}
-% Now we include the appropriate graphics file. Because the user might
-% be producing DVI or PDF files, and have supplied a file format or not,
-% and so on, the logic we follow is a bit complicated.
-% \autoref{f:sageplottree} shows what we do; for completeness, we show
-% what |\ST@inclgrfx| does in \autoref{f:stig}. This entire
-% complicated business is intended to avoid doing an |\includegraphics|
-% command on a file that doesn't exist, and to issue warnings
-% appropriate to the situation.
-%
-% \tikzstyle{box}=[draw, shape=rectangle, thick]
+% There is another option, and that is to use the |makestatic.py| script
+% included with \ST.
%
-% \begin{figure}
-% \centering
-% \begin{tikzpicture}
-% \tikzstyle{level 1}=[sibling distance=6cm]
-% \tikzstyle{level 2}=[sibling distance=3cm]
-% \node [box] {DVI or PDF?}
-% child {node [box] {Format provided?}
-% child {node [box] {STig EPS}
-% edge from parent node[left] {no}}
-% child {node [box] {IM option set?}
-% child {node [box, text width=3cm] {Warn that DVI + PNG = bad}
-% edge from parent node[left] {no}}
-% child {node [box] {STig EPS}
-% edge from parent node[right] {yes}}
-% edge from parent node[right] {yes}}
-% edge from parent node[left] {DVI}}
-% child {node [box] {Format provided?}
-% child {node [box] {STig PDF}
-% edge from parent node[left] {no}}
-% child {node [box] {STig \texttt{\#2}}
-% edge from parent node[right] {yes}}
-% edge from parent node[right] {PDF}};
-% \end{tikzpicture}
-% \caption{The logic tree that \texttt{\bslash sageplot} uses to
-% decide whether to run \texttt{\bslash includegraphics} or to yell at
-% the user. ``Format'' is the \texttt{\#2} argument to \texttt{\bslash
-% sageplot}, ``STig ext''
-% means a call to \texttt{\bslash ST@inclgrfx} with ``ext'' as the
-% second argument, and ``IM'' is Imagemagick.}
-% \label{f:sageplottree}
-% \end{figure}
-%
-% If we are creating a PDF, we check to see if the user asked for a
-% different format, and use that if necessary:
-% \begin{macrocode}
-\ifpdf
- \ifthenelse{\equal{#2}{notprovided}}%
- {\ST@inclgrfx{#1}{pdf}}%
- {\ST@inclgrfx{#1}{#2}}%
-% \end{macrocode}
-% Otherwise, we are creating a DVI file, which only supports EPS. If the
-% user provided a format anyway, don't include the file (since it won't
-% work) and warn the user about this. (Unless the file doesn't exist, in
-% which case we do the same thing that |\ST@inclgrfx| does.)
-% \begin{macrocode}
-\else
- \ifthenelse{\equal{#2}{notprovided}}%
- {\ST@inclgrfx{#1}{eps}}%
-% \end{macrocode}
-% If a format is provided, we check to see if we're using the
-% imagemagick option. If so, try to include an EPS file anyway.
-% \begin{macrocode}
- {\ifthenelse{\equal{\ST@epsim}{True}}
- {\ST@inclgrfx{#1}{eps}}%
-% \end{macrocode}
-% If we're not using the imagemagick option, we're going to issue some
-% sort of warning, depending on whether the file exists yet or not.
-% \begin{macrocode}
- {\IfFileExists{\ST@plotdir/plot-\theST@plot.#2}%
- {\framebox[2cm]{\rule[-1cm]{0cm}{2cm}\textbf{??}}%
- \PackageWarning{sagetex}{Graphics file
- \ST@plotdir/plot-\theST@plot.#2\space on page \thepage\space
- cannot be used with DVI output. Use pdflatex or create an EPS
- file. Plot command is}}%
- {\framebox[2cm]{\rule[-1cm]{0cm}{2cm}\textbf{??}}%
- \PackageWarning{sagetex}{Graphics file
- \ST@plotdir/plot-\theST@plot.#2\space on page \thepage\space
- does not exist}%
- \gdef\ST@rerun{x}}}}%
-\fi
-% \end{macrocode}
-% Finally, step the counter and we're done.
-% \begin{macrocode}
-\stepcounter{ST@plot}}
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\ST@inclgrfx}
-% This command includes the requested graphics file (|#2| is the
-% extension) with the requested options (|#1|) if the file exists. Note
-% that it just needs to know the extension, since we use a counter for
-% the filename.
-% \begin{macrocode}
-\newcommand{\ST@inclgrfx}[2]{%
- \IfFileExists{\ST@plotdir/plot-\theST@plot.#2}%
- {\includegraphics[#1]{\ST@plotdir/plot-\theST@plot.#2}}%
-% \end{macrocode}
-% If the file doesn't exist, we insert a little box to indicate it
-% wasn't found, issue a warning that we didn't find a graphics file,
-% then set a flag that, at the end of the run, tells the user to run
-% Sage again.
-% \begin{macrocode}
- {\framebox[2cm]{\rule[-1cm]{0cm}{2cm}\textbf{??}}%
- \PackageWarning{sagetex}{Graphics file
- \ST@plotdir/plot-\theST@plot.#2\space on page \thepage\space does not
- exist}%
- \gdef\ST@rerun{x}}}
-% \end{macrocode}
-% \autoref{f:stig} makes this a bit clearer.
-% \begin{figure}
-% \centering
-% \begin{tikzpicture}
-% \tikzstyle{level 1}=[sibling distance=4cm]
-% \node [box] {Does EXT file exist?}
-% child {node [box, text width = 2.125cm] {Warn user to rerun Sage}
-% edge from parent node[left] {no}}
-% child {node [box] {Use \texttt{includegraphics}}
-% edge from parent node[right] {yes}};
-% \end{tikzpicture}
-% \caption{The logic used by the \texttt{\bslash ST@inclgrfx}
-% command.}
-% \label{f:stig}
-% \end{figure}
-% \end{macro}
-%
-% \begin{macro}{\ST@beginsfbl}
-% This is ``begin |.sage| file block'', an internal-use abbreviation
-% that sets things up when we start writing a chunk of Sage code to the
-% |.sage| file. It begins with some \TeX{} magic that fixes spacing,
-% then puts the start of a try/except block in the |.sage| file---this
-% not only allows the user to indent code without Sage/Python
-% complaining about indentation, but lets us tell the user where things
-% went wrong. The last bit is some magic from the |verbatim| package
-% manual that makes \LTX respect line breaks.
-% \begin{macrocode}
-\newcommand{\ST@beginsfbl}{%
- \@bsphack%
- \ST@wsf{sagetex.blockbegin()}%
- \ST@wsf{try:}%
- \let\do\@makeother\dospecials\catcode`\^^M\active}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\ST@endsfbl}
-% The companion to |\ST@beginsfbl|.
-% \begin{macrocode}
-\newcommand{\ST@endsfbl}{%
-\ST@wsf{except:}%
-\ST@wsf{ sagetex.goboom(\the\inputlineno)}%
-\ST@wsf{sagetex.blockend()}}
-% \end{macrocode}
-% \end{macro}
-%
-% Now let's define the ``verbatim-like'' environments. There are four
-% possibilities, corresponding to two independent choices of
-% typesetting the code or not, and writing to the |.sage| file or not.
-%
-% \begin{environment}{sageblock}
-% This environment does both: it typesets your code and puts it into the
-% |.sage| file for execution by Sage.
-% \begin{macrocode}
-\newenvironment{sageblock}{\ST@beginsfbl%
-% \end{macrocode}
-% The space between |\ST@wsf{| and |\the| is crucial! It, along with the
-% ``|try:|'', is what allows the user to indent code if they like.
-% This line sends stuff to the |.sage| file.
-% \begin{macrocode}
-\def\verbatim@processline{\ST@wsf{ \the\verbatim@line}%
-% \end{macrocode}
-% Next, we typeset your code and start the verbatim environment.
-% \begin{macrocode}
-\hspace{\sagetexindent}\the\verbatim@line\par}%
-\verbatim}%
-% \end{macrocode}
-% At the end of the environment, we put a chunk into the |.sage| file
-% and stop the verbatim environment.
-% \begin{macrocode}
-{\ST@endsfbl\endverbatim}
-% \end{macrocode}
-% \end{environment}
-%
-% \begin{environment}{sagesilent}
-% This is from the |verbatim| package manual. It's just like the above,
-% except we don't typeset anything.
-% \begin{macrocode}
-\newenvironment{sagesilent}{\ST@beginsfbl%
-\def\verbatim@processline{\ST@wsf{ \the\verbatim@line}}%
-\verbatim@start}%
-{\ST@endsfbl\@esphack}
-% \end{macrocode}
-% \end{environment}
-%
-% \begin{environment}{sageverbatim}
-% The opposite of |sagesilent|. This is exactly the same as the verbatim
-% environment, except that we include some indentation to be consistent
-% with other typeset Sage code.
-% \begin{macrocode}
-\newenvironment{sageverbatim}{%
-\def\verbatim@processline{\hspace{\sagetexindent}\the\verbatim@line\par}%
-\verbatim}%
-{\endverbatim}
-% \end{macrocode}
-% \end{environment}
-%
-% Logically, we now need an environment which neither typesets
-% \emph{nor} writes code to the |.sage| file. The verbatim package's
-% |comment| environment does that.\\
-%
-% Now we deal with some end-of-file cleanup.
-%
-% We tell the Sage script to write some information to the |.sout| file,
-% then check to see if |ST@rerun| ever got defined. If not, all the
-% inline formulas and plots worked, so do nothing.
-% \begin{macrocode}
-\AtEndDocument{\ST@wsf{sagetex.endofdoc()}%
-\@ifundefined{ST@rerun}{}%
-% \end{macrocode}
-% Otherwise, we issue a warning to tell the user to run Sage on the
-% |.sage| file. Part of the reason we do this is that, by using |\ref|
-% to pull in the inlines, \LTX will complain about undefined
-% references if you haven't run the Sage script---and for many \LTX
-% users, myself included, the warning ``there were undefined
-% references'' is a signal to run \LTX again. But to fix these
-% particular undefined references, you need to run \emph{Sage}. We also
-% suppressed file-not-found errors for graphics files, and need to tell
-% the user what to do about that.
-%
-% At any rate, we tell the user to run Sage if it's necessary.
-% \begin{macrocode}
-{\PackageWarningNoLine{sagetex}{There were undefined Sage formulas
-and/or plots}%
-\PackageWarningNoLine{sagetex}{Run Sage on \jobname.sage, and then run
-LaTeX on \jobname.tex again}}}
-% \end{macrocode}
-%
-%
-% \subsection{The Python module}
+% Use of the script is quite simple. Copy it and |sagetexparse.py| to
+% the directory with your document, and run
+% \begin{quote}
+% |python makestatic.py inputfile [outputfile]|
+% \end{quote}
+% where |inputfile| is your document. (You can also set the executable
+% bit of |makestatic.py| and use |./makestatic.py|.) This script needs
+% the \href{http://pyparsing.wikispaces.com}{pyparsing} module to be
+% installed.\footnote{If you don't have pyparsing installed, you can
+% simply copy the file
+% \texttt{\sageroot/local/lib/python/matplotlib/pyparsing.py} into
+% your directory.} You may optionally specify |outputfile|; if you do
+% so, the results will be written to that file. If the file exists, it
+% won't be overwritten unless you also specify the |-o| switch.
+%
+% You will need to run this after you've compiled your document and run
+% Sage on the |.sage| file. The script reads in the |.sout| file and
+% replaces all the calls to |\sage| and |\sageplot| with their plain
+% \LTX equivalent, and turns the |sageblock| and |sageverbatim|
+% environments into |verbatim| environments. Any |sagesilent|
+% environment is turned into a |comment| environment. The resulting
+% document should compile to something identical, or very nearly so, to
+% the original file.
+%
+% One large limitation of this script is that it can't change anything
+% while \ST is paused, since Sage doesn't compute anything for such
+% parts of your document. It also doesn't check to see if pause and
+% unpause commands are inside comments or verbatim environments. If
+% you're going to use |makestatic.py|, just remove all pause/unpause
+% statements.
+%
+% The parsing that |makestatic.py| does is pretty good, but not perfect.
+% Right now it doesn't support having a comma-separated list of
+% packages, so you can't have |\usepackage{sagetex, foo}|. You need to
+% have just |\usepackage{sagetex}|. (Along with package options; those
+% are handled correctly.) If you find other parsing errors, please let
+% me know.
+%
+% \subsection{Extracting the Sage code from a document}
+% \label{sec:extractsagecode}
+%
+% This next script is probably not so useful, but having done the above,
+% this was pretty easy. The |extractsagecode.py| script does the
+% opposite of |makestatic.py|, in some sense: given a document, it
+% extracts all the Sage code and removes all the \LTX.
+%
+% Its usage is the same as |makestatic.py|.
+%
+% Note that the resulting file will almost certainly \emph{not} be a
+% runnable Sage script, since there might be \LTX commands in it, the
+% indentation may not be correct, and the plot options just get written
+% verbatim to the file. Nevertheless, it might be useful if you just
+% want to look at the Sage code in a file.
+%
+% \section{Using \ST without Sage installed}
+% \label{sec:remote-sagetex}
+%
+% You may want to edit and typeset a \ST-ified file on a computer that
+% doesn't have Sage installed. How can you do that? We need to somehow
+% run Sage on the |.sage| file. The included script
+% \texttt{remote-sagetex.py} takes advantage of Sage's network
+% transparency and will use a remote server to do all the computations.
+% Anywhere in this manual where you are told to ``run Sage'', instead of
+% actually running Sage, you can run
+% \begin{center}
+% \texttt{python remote-sagetex.py filename.sage}
+% \end{center}
+% The script will ask you for a server, username, and password, then
+% process all your code and write a |.sout| file and graphics files
+% exactly as if you had used a local copy of Sage to process the |.sage|
+% script. (With some minor limitations and differences; see below.)
+%
+% One important point: \emph{the script requires Python 2.6}. It will
+% not work with earlier versions. (It will work with Python 3.0 or later
+% with some trivial changes.)
+%
+% You can provide the server, username and password with the
+% command-line switches |--server|, |--username|, and |--password|, or
+% you can put that information into a file and use the |--file| switch
+% to specify that file. The format of the file must be like the
+% following:
+% \begin{verbatim}
+ # hash mark at beginning of line marks a comment
+ server = "http://example.com:1234"
+ username = 'my_user_name'
+ password = 's33krit'\end{verbatim}
+% As you can see, it's really just like assigning a string to a variable
+% in Python. You can use single or double quotes and use hash marks to
+% start comments. You can't have comments on the same line as an
+% assignment, though. You can omit any of those pieces of information
+% information; the script will ask for anything it needs to know.
+% Information provided as a command line switch takes precedence over
+% anything found in the file.
+%
+% You can keep this file separate from your \LTX documents in a secure
+% location; for example, on a USB thumb drive or in an automatically
+% encrypted directory (like |~/Private| in Ubuntu). This makes it much
+% harder to accidentally upload your private login information to the
+% arXiv, put it on a website, send it to a colleague, or otherwise make
+% your private information public.
+%
+% \subsection{Limitations of \texttt{remote-sagetex.py}}
+% \label{sec:remote-sagetex-limitations}
+%
+% The |remote-sagetex.py| script has several limitations. It completely
+% ignores the |epstopdf| and |imagemagick| flags. The |epstopdf| flag is
+% not a big deal, since it was originally introduced to work around a
+% matplotlib bug which has since been fixed. Not having |imagemagick|
+% support means that you cannot automatically convert 3D graphics to eps
+% format; using |pdflatex| to make PDFs works around this issue.
+%
+%
+% \subsection{Other caveats}
+% \label{sec:remote-sagetex-caveats}
+%
+% Right now, the ``simple server API'' that |remote-sagetex.py| uses is
+% not terribly robust, and if you interrupt the script, it's possible to
+% leave an idle session running on the server. If many idle sessions
+% accumulate on the server, it can use up a lot of memory and cause the
+% server to be slow, unresponsive, or maybe even crash. For now, I
+% recommend that you only run the script manually. It's probably best to
+% not configure your \TeX{} editing environment to automatically run
+% |remote-sagetex.py| whenever you typeset your document, at least not
+% without showing you the output or alerting you about errors.
%
+
+
% \iffalse
-% Hey, docstrip! Stop putting code into the .sty file, and start
-% putting it into the .py file.
-%</latex>
-%<*python>
-% Thanks.
+% Local Variables:
+% mode: doctex
+% TeX-master: t
+% End:
% \fi
-%
-% The style file writes things to the |.sage| file and reads them from
-% the |.sout| file. The Python module provides functions that help
-% produce the |.sout| file from the |.sage| file.
-%
-% \paragraph{A note on Python and \textsf{Docstrip}} There is one tiny
-% potential source of confusion when documenting Python code with
-% \textsf{Docstrip}: the percent sign. If you have a long line of Python
-% code which includes a percent sign for string formatting and you break
-% the line with a backslash and begin the next line with a percent sign,
-% that line \emph{will not} be written to the output file. This is only
-% a problem if you \emph{begin} the line with a percent sign; there are
-% no troubles otherwise.\\
-%
-% On to the code:
-%
-% The |sagetex.py| file is intended to be used as a module and doesn't
-% do anything useful when called directly, so if someone does that, warn
-% them. We do this right away so that we print this and exit before
-% trying to import any Sage modules; that way, this error message gets
-% printed whether you run the script with Sage or with Python.
-% \begin{macrocode}
-import sys
-if __name__ == "__main__":
- print("""This file is part of the SageTeX package.
-It is not meant to be called directly.
-
-This file will be used by Sage scripts generated from a LaTeX document
-using the sagetex package. Keep it somewhere where Sage and Python can
-find it and it will automatically be imported.""")
- sys.exit()
-% \end{macrocode}
-% We start with some imports and definitions of our global variables.
-% This is a relatively specialized use of Sage, so using global
-% variables isn't a bad idea. Plus I think when we import this module,
-% they will all stay inside the |sagetex| namespace anyway.
-% \begin{macrocode}
-from sage.misc.latex import latex
-import os
-import os.path
-import hashlib
-import traceback
-import subprocess
-import shutil
-initplot_done = False
-dirname = None
-filename = ""
-% \end{macrocode}
-%
-% \begin{macro}{progress}
-% This function justs prints stuff. It allows us to not print a
-% linebreak, so you can get ``|start...|'' (little time spent
-% processing) ``|end|'' on one line.
-% \begin{macrocode}
-def progress(t,linebreak=True):
- if linebreak:
- print(t)
- else:
- sys.stdout.write(t)
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{openout}
-% This function opens a |.sout.tmp| file and writes all our output to
-% that. Then, when we're done, we move that to |.sout|. The
-% ``autogenerated'' line is basically the same as the lines that get put
-% at the top of preparsed Sage files; we are automatically generating a
-% file with Sage, so it seems reasonable to add it.
-% \begin{macrocode}
-def openout(f):
- global filename
- filename = f
- global _file_
- _file_ = open(f + '.sout.tmp', 'w')
- s = '% This file was *autogenerated* from the file ' + \
- os.path.splitext(filename)[0] + '.sage.\n'
- _file_.write(s)
- progress('Processing Sage code for %s.tex...' % filename)
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{initplot}
-% We only want to create the plots directory if the user actually plots
-% something. This function creates the directory and sets the
-% |initplot_done| flag after doing so. We make a directory based on the
-% \LTX file being processed so that if there are multiple |.tex|
-% files in a directory, we don't overwrite plots from another file.
-% \begin{macrocode}
-def initplot(f):
- global initplot_done
- if not initplot_done:
- progress('Initializing plots directory')
- global dirname
-% \end{macrocode}
-% We hard-code the |.tex| extension, which is fine in the overwhelming
-% majority of cases, although it does cause minor confusion when
-% building the documentation. If it turns out lots of people use, say, a
-% |ltx| extension or whatever, I think we could find out the correct
-% extension, but it would involve a lot of irritating mucking around.
-% \begin{macrocode}
- dirname = 'sage-plots-for-' + f + '.tex'
- if os.path.isdir(dirname):
- shutil.rmtree(dirname)
- os.mkdir(dirname)
- initplot_done = True
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{inline}
-% This function works with |\sage| from the style file to put Sage
-% output into your \LTX file. Usually, when you use |\label|, it
-% writes a line such as
-% \begin{center}
-% |\newlabel{labelname}{{section number}{page number}}|
-% \end{center}
-% to the |.aux| file. When you use the |hyperref| package, there are
-% more fields in the second argument, but the first two are the same.
-% The |\ref| command just pulls in what's in the first field, so we can
-% hijack this mechanism for our own nefarious purposes. The function
-% writes a |\newlabel| line with a label made from a counter and the
-% text from running Sage on |s|.
-%
-% We print out the line number so if something goes wrong, the user can
-% more easily track down the offending |\sage| command in the source
-% file.
-%
-% That's a lot of explanation for a very short function:
-% \begin{macrocode}
-def inline(counter, s):
- progress('Inline formula %s' % counter)
- _file_.write('\\newlabel{@sagelabel' + str(counter) + '}{{' + \
- latex(s) + '}{}{}{}{}}\n')
-% \end{macrocode}
-% We are using five fields, just like |hyperref| does, because that
-% works whether or not |hyperref| is loaded. Using two fields, as in plain
-% \LTX, doesn't work if |hyperref| is loaded.
-% \end{macro}
-%
-% \begin{macro}{blockbegin}
-% \begin{macro}{blockend}
-% This function and its companion used to write stuff to the |.sout|
-% file, but now they just update the user on our progress evaluating a
-% code block.
-% \begin{macrocode}
-def blockbegin():
- progress('Code block begin...', False)
-def blockend():
- progress('end')
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{plot}
-% I hope it's obvious that this function does plotting. As mentioned in
-% the |\sageplot| code, we're taking advantage of two things: first,
-% that \LTX doesn't treat commas and spaces in macro arguments
-% specially, and second, that Python (and Sage plotting functions) has
-% nice support for keyword arguments. The |#3| argument to |\sageplot|
-% becomes |p| and |**kwargs| below.
-% \begin{macrocode}
-def plot(counter, p, format='notprovided', epsmagick=False, **kwargs):
- global dirname
- progress('Plot %s' % counter)
-% \end{macrocode}
-% If the user says nothing about file formats, we default to producing
-% PDF and EPS. This allows the user to transparently switch between
-% using a DVI previewer (which usually automatically updates when the
-% DVI changes, and has support for source specials, which makes the
-% writing process easier) and making PDFs.
-% \begin{macrocode}
- if format == 'notprovided':
- formats = ['eps', 'pdf']
- else:
- formats = [format]
- for fmt in formats:
- plotfilename = os.path.join(dirname, 'plot-%s.%s' % (counter, fmt))
- #print(' plotting %s with args %s' % (plotfilename, kwargs))
- p.save(filename=plotfilename, **kwargs)
-% \end{macrocode}
-% If the user provides a format \emph{and} specifies the |imagemagick|
-% option, we try to convert the newly-created file into EPS format.
-% \begin{macrocode}
- if format != 'notprovided' and epsmagick is True:
- print('Calling Imagemagick to convert plot-%s.%s to EPS' % \
- (counter, format))
- toeps(counter, format)
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{toeps}
-% This function calls the Imagmagick utility |convert| to, well, convert
-% something into EPS format. This gets called when the user has
-% requested the ``|imagemagick|'' option to the \ST\ style file and is
-% making a graphic file with a nondefault extension.
-% \begin{macrocode}
-def toeps(counter, ext):
- global dirname
- subprocess.check_call(['convert',\
- '%s/plot-%s.%s' % (dirname, counter, ext), \
- '%s/plot-%s.eps' % (dirname, counter)])
-% \end{macrocode}
-% We are blindly assuming that the |convert| command exists and will do
-% the conversion for us; the |check_call| function raises an exception
-% which, since all these calls get wrapped in try/excepts in the |.sage|
-% file, should result in a reasonable error message if something strange
-% happens.
-% \end{macro}
-%
-% \begin{macro}{goboom}
-% When a chunk of Sage code blows up, this function bears the bad news
-% to the user. Normally in Python the traceback is good enough for this,
-% but in this case, we start with a |.sage| file (which is
-% autogenerated) which autogenerates a |.py| file---and the tracebacks
-% the user sees refer to that file, whose line numbers are basically
-% useless. We want to tell them where in the \LTX file things went
-% bad, so we do that, give them the traceback, and exit after removing
-% the |.sout.tmp| file.
-% \begin{macrocode}
-def goboom(line):
- global filename
- print('\n**** Error in Sage code on line %s of %s.tex! Traceback\
- follows.' % (line, filename))
- traceback.print_exc()
- print('\n**** Running Sage on %s.sage failed! Fix %s.tex and try\
- again.' % (filename, filename))
- os.remove(filename + '.sout.tmp')
- sys.exit(1)
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{endofdoc}
-% When we're done processing, we have a couple little cleanup tasks. We
-% want to put the MD5 sm of the |.sage| file that produced the |.sout|
-% file we're about to write into the |.sout| file, so that external
-% programs that build \LTX documents can tell if they need to call Sage
-% to update the |.sout| file. But there is a problem: we write line
-% numbers to the |.sage| file so that we can provide useful error
-% messages---but that means that adding, say, a line break to your
-% source file will change the MD5 sum, and your program will think it
-% needs to rerun Sage even though none of the actual calls to Sage have
-% changed.
-%
-% How do we include line numbers for our error messages but still allow
-% a program to discover a ``genuine'' change to the |.sage| file?
-%
-% The answer is to only find the MD5 sum of \emph{part} of the |.sage|
-% file. By design, the source file line numbers only appear in calls to
-% |goboom|, so we will strip those lines out. Basically we are doing
-% \begin{center}
-% \verb+grep -v '^ sagetex.goboom' filename.sage | md5sum+
-% \end{center}
-% (In fact, what we do below produces exactly the same sum.)
-% \begin{macrocode}
-def endofdoc():
- global filename
- sagef = open(filename + '.sage', 'r')
- m = hashlib.md5()
- for line in sagef:
- if line[0:15] != ' sagetex.goboom':
- m.update(line)
- s = '%' + m.hexdigest() + '% md5sum of .sage file (minus "goboom" \
-lines) that produced this\n'
- _file_.write(s)
-% \end{macrocode}
-% Now, we do issue warnings to run Sage on the |.sage| file and an
-% external program might look for those to detect the need to rerun
-% Sage, but those warnings do not quite capture all situations. (If
-% you've already produced the |.sout| file and change a |\sage| call, no
-% warning will be issued since all the |\ref|s find a |\newlabel|.)
-% Anyway, I think it's easier to grab an MD5 sum out of the end of the
-% file than parse the output from running |latex| on your file. (The
-% regular expression |^%[0-9a-f]{32}%| will find the MD5 sum.)
-%
-% Now we are done with the |.sout| file. Close it, rename it, and tell
-% the user we're done.
-% \begin{macrocode}
- _file_.close()
- os.rename(filename + '.sout.tmp', filename + '.sout')
- progress('Sage processing complete. Run LaTeX on %s.tex again.' %\
- filename)
-% \end{macrocode}
-% \end{macro}
-%
-% \section{Credits and acknowledgements}
-%
-% According to the original README file, this system was originally
-% done by Gonzalo Tornaria and Joe Wetherell. Later Harald Schilly made
-% some improvements and modifications. Almost all the examples in the
-% |example.tex| file are from Harald.
-%
-% Dan Drake rewrote and extended the style file (there is almost zero
-% original code there), made significant changes to the Python module,
-% put both files into \textsf{Docstrip} format, and wrote all the
-% documentation.
-%
-% Many thanks to Jason Grout for his numerous comments, suggestions, and
-% feedback.
-%
-% \section{Copying and licenses}
-%
-% The \emph{source code} of the \ST package may be redistributed and/or
-% modified under the terms of the GNU General Public License as
-% published by the Free Software Foundation, either version 2 of the
-% License, or (at your option) any later version. To view a copy of this
-% license, see \url{http://www.gnu.org/licenses/} or send a letter to
-% the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-% Boston, MA 02110-1301, USA.
-%
-% The \emph{documentation} of the \ST package is licensed under the
-% Creative Commons Attribution-Noncommercial-Share Alike 3.0 License. To
-% view a copy of this license, visit
-% \url{http://creativecommons.org/licenses/by-nc-sa/3.0/} or send a
-% letter to Creative Commons, 171 Second Street, Suite 300, San
-% Francisco, California, 94105, USA.
diff --git a/Master/texmf-dist/source/latex/sagetex/sagetexpackage.ins b/Master/texmf-dist/source/latex/sagetex/sagetexpackage.ins
index b91433f7b34..f759ec4ad71 100644
--- a/Master/texmf-dist/source/latex/sagetex/sagetexpackage.ins
+++ b/Master/texmf-dist/source/latex/sagetex/sagetexpackage.ins
@@ -1,19 +1,19 @@
%% This is `sagetexpackage.ins', part of the sagetex package.
-%
-%% Copyright (C) 2008 by Dan Drake <ddrake@member.ams.org>
+%%
+%% Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
%%
%% 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 of the License, 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 should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
+%% along with this program. If not, see <http://www.gnu.org/licenses/>.
\input docstrip.tex
\keepsilent
@@ -22,9 +22,9 @@
\declarepreamble\defaultpreamble
-This is a generated file.
+This is a generated file. It is part of the SageTeX package.
-Copyright (C) 2008 by Dan Drake <ddrake@member.ams.org>
+Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
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
@@ -33,44 +33,75 @@ 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.
-
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>
+with this program. If not, see <http://www.gnu.org/licenses/>.
\endpreamble
% We use a name other than `sagetex' because when using the sagetex
-% package in a file called `foo.dtx', a file `foo.py' will be produced
-% -- and below, we generate a file called sagetex.py. Thus we use a name
-% other than `sagetex.dtx' so that building the documentation doesn't
-% clobber the very Python file we need to build the documentation!
+% package in a file called `foo.dtx', a file `foo.py' will be
+% produced---and below, we generate a file called sagetex.py. Thus we
+% use a name other than `sagetex.dtx' so that building the documentation
+% doesn't clobber the very Python file we need to build the
+% documentation!
+
+\generate{\file{sagetex.sty}{\from{sagetexpackage.dtx}{latex}
+ \from{py-and-sty.dtx}{latex}}}
+
+% Define a new preamble with #'s as comment characters for the Python
+% files. I hate copying the same text, but defining a "\boilerplate"
+% macro requires me to manually do \MetaPrefix\space and ^^J everywhere
+% and it's more annoying than this.
-\generate{\file{sagetex.sty}{\from{sagetexpackage.dtx}{latex}}}
+\catcode`\#=12
+\def\hash{#}
+\catcode`\#=6
+
+\def\MetaPrefix{\hash\hash}
+\declarepreamble\pypreamble
+
+This is a generated file. It is part of the SageTeX package.
+
+Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
+
+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 of the License, 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 should have received a copy of the GNU General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+
+\endpreamble
+\usepreamble\pypreamble
+\nopostamble
+\generate{\file{sagetex.py}{\from{sagetexpackage.dtx}{python}
+ \from{py-and-sty.dtx}{python}}}
+\generate{\file{sagetexparse.py}{\from{scripts.dtx}{parsermod}}}
-% Some trickery to get triple quotes around the {pre,post}amble. This is
-% a modification of what the Docstrip manual suggests; their method
-% resulted in some bits being printed twice because, I think, of a
-% problem in \declare{pre,post}amble. At any rate, this gives us a
-% properly commented Python file with the same preamble as the .sty
-% file.
+% Now define a new preamble with the shebang line at the top.
-\edef\defaultpreamble{"""^^J%
- \defaultpreamble^^J%
- """}
-\edef\defaultpostamble{"""^^J%
- \defaultpostamble^^J%
- """}
+\def\envpypreamble{\hash!/usr/bin/env python^^J\pypreamble}
+\usepreamble\envpypreamble
-\generate{\file{sagetex.py}{\from{sagetexpackage.dtx}{python}}}
+\generate{\file{makestatic.py}{\from{scripts.dtx}{staticscript}}}
+\generate{\file{extractsagecode.py}{\from{scripts.dtx}{extractscript}}}
+\generate{\file{remote-sagetex.py}{\from{remote-sagetex.dtx}{remotesagetex}}}
\obeyspaces
\Msg{******************************************************************}
\Msg{* *}
\Msg{* To finish the installation, move the following files *}
-\Msg{* into directories searched by TeX and Sage, respectively. *}
+\Msg{* into directories searched by TeX and Sage, respectively: *}
\Msg{* *}
\Msg{* sagetex.sty *}
\Msg{* sagetex.py *}
diff --git a/Master/texmf-dist/source/latex/sagetex/scripts.dtx b/Master/texmf-dist/source/latex/sagetex/scripts.dtx
new file mode 100644
index 00000000000..40914a4165b
--- /dev/null
+++ b/Master/texmf-dist/source/latex/sagetex/scripts.dtx
@@ -0,0 +1,424 @@
+% \section{Included Python scripts}
+% \label{sec:included-scripts}
+%
+% Here we describe the Python code for |makestatic.py|, which removes
+% \ST commands to produce a ``static'' file, and |extractsagecode.py|,
+% which extracts all the Sage code from a |.tex| file.
+%
+% \subsection{makestatic.py}
+% \label{sec:makestatic}
+% \iffalse
+%<*staticscript>
+% \fi
+%
+% First, |makestatic.py| script. It's about the most basic, generic
+% Python script taking command-line arguments that you'll find. The
+% |#!/usr/bin/env python| line is provided for us by the |.ins| file's
+% preamble, so we don't put it here.
+% \begin{macrocode}
+import sys
+import time
+import getopt
+import os.path
+from sagetexparse import DeSageTex
+
+def usage():
+ print("""Usage: %s [-h|--help] [-o|--overwrite] inputfile [outputfile]
+
+Removes SageTeX macros from `inputfile' and replaces them with the
+Sage-computed results to make a "static" file. You'll need to have run
+Sage on `inputfile' already.
+
+`inputfile' can include the .tex extension or not. If you provide
+`outputfile', the results will be written to a file of that name.
+Specify `-o' or `--overwrite' to overwrite the file if it exists.
+
+See the SageTeX documentation for more details.""" % sys.argv[0])
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], 'ho', ['help', 'overwrite'])
+except getopt.GetoptError, err:
+ print str(err)
+ usage()
+ sys.exit(2)
+
+overwrite = False
+for o, a in opts:
+ if o in ('-h', '--help'):
+ usage()
+ sys.exit()
+ elif o in ('-o', '--overwrite'):
+ overwrite = True
+
+if len(args) == 0 or len(args) > 2:
+ print('Error: wrong number of arguments. Make sure to specify options first.\n')
+ usage()
+ sys.exit(2)
+
+if len(args) == 2 and (os.path.exists(args[1]) and not overwrite):
+ print('Error: %s exists and overwrite option not specified.' % args[1])
+ sys.exit(1)
+
+src, ext = os.path.splitext(args[0])
+% \end{macrocode}
+% All the real work gets done in the line below. Sorry it's not more
+% exciting-looking.
+% \begin{macrocode}
+desagetexed = DeSageTex(src)
+% \end{macrocode}
+% This part is cool: we need double percent signs at the beginning of
+% the line because Python needs them (so they get turned into single
+% percent signs) \emph{and} because \textsf{Docstrip} needs them (so the
+% line gets passed into the generated file). It's perfect!
+% \begin{macrocode}
+header = """\
+%% SageTeX commands have been automatically removed from this file and
+%% replaced with plain LaTeX. Processed %s.
+
+""" % time.strftime('%a %d %b %Y %H:%M:%S', time.localtime())
+
+if len(args) == 2:
+ dest = open(args[1], 'w')
+else:
+ dest = sys.stdout
+
+dest.write(header)
+dest.write(desagetexed.result)
+% \end{macrocode}
+%
+% \iffalse
+%</staticscript>
+%<*extractscript>
+% \fi
+%
+% \subsection{extractsagecode.py}
+%
+% Same idea as |makestatic.py|, except this does basically the opposite
+% thing.
+% \begin{macrocode}
+import sys
+import time
+import getopt
+import os.path
+from sagetexparse import SageCodeExtractor
+
+def usage():
+ print("""Usage: %s [-h|--help] [-o|--overwrite] inputfile [outputfile]
+
+Extracts Sage code from `inputfile'.
+
+`inputfile' can include the .tex extension or not. If you provide
+`outputfile', the results will be written to a file of that name,
+otherwise the result will be printed to stdout.
+
+Specify `-o' or `--overwrite' to overwrite the file if it exists.
+
+See the SageTeX documentation for more details.""" % sys.argv[0])
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], 'ho', ['help', 'overwrite'])
+except getopt.GetoptError, err:
+ print str(err)
+ usage()
+ sys.exit(2)
+
+overwrite = False
+for o, a in opts:
+ if o in ('-h', '--help'):
+ usage()
+ sys.exit()
+ elif o in ('-o', '--overwrite'):
+ overwrite = True
+
+if len(args) == 0 or len(args) > 2:
+ print('Error: wrong number of arguments. Make sure to specify options first.\n')
+ usage()
+ sys.exit(2)
+
+if len(args) == 2 and (os.path.exists(args[1]) and not overwrite):
+ print('Error: %s exists and overwrite option not specified.' % args[1])
+ sys.exit(1)
+
+src, ext = os.path.splitext(args[0])
+sagecode = SageCodeExtractor(src)
+header = """\
+# This file contains Sage code extracted from %s%s.
+# Processed %s.
+
+""" % (src, ext, time.strftime('%a %d %b %Y %H:%M:%S', time.localtime()))
+
+if len(args) == 2:
+ dest = open(args[1], 'w')
+else:
+ dest = sys.stdout
+
+dest.write(header)
+dest.write(sagecode.result)
+% \end{macrocode}
+%
+% \iffalse
+%</extractscript>
+%<*parsermod>
+% \fi
+%
+% \subsection{The parser module}
+% \changes{v2.2}{2009/06/17}{Update parser module to handle pause/unpause}
+%
+% Here's the module that does the actual parsing and replacing. It's
+% really quite simple, thanks to the awesome
+% \href{http://pyparsing.wikispaces.com}{Pyparsing module}. The parsing
+% code below is nearly self-documenting! Compare that to fancy regular
+% expressions, which sometimes look like someone sneezed punctuation all
+% over the screen.
+% \begin{macrocode}
+import sys
+from pyparsing import *
+% \end{macrocode}
+% First, we define this very helpful parser: it finds the matching
+% bracket, and doesn't parse any of the intervening text. It's basically
+% like hitting the percent sign in Vim. This is useful for parsing \LTX
+% stuff, when you want to just grab everything enclosed by matching
+% brackets.
+% \begin{macrocode}
+def skipToMatching(opener, closer):
+ nest = nestedExpr(opener, closer)
+ nest.setParseAction(lambda l, s, t: l[s:getTokensEndLoc()])
+ return nest
+
+curlybrackets = skipToMatching('{', '}')
+squarebrackets = skipToMatching('[', ']')
+% \end{macrocode}
+% Next, parser for |\sage|, |\sageplot|, and pause/unpause calls:
+% \begin{macrocode}
+sagemacroparser = r'\sage' + curlybrackets('code')
+sageplotparser = (r'\sageplot'
+ + Optional(squarebrackets)('opts')
+ + Optional(squarebrackets)('format')
+ + curlybrackets('code'))
+sagetexpause = Literal(r'\sagetexpause')
+sagetexunpause = Literal(r'\sagetexunpause')
+% \end{macrocode}
+%
+% With those defined, let's move on to our classes.
+%
+% \begin{macro}{SoutParser}
+% Here's the parser for the generated |.sout| file. The code below does
+% all the parsing of the |.sout| file and puts the results into a
+% list. Notice that it's on the order of 10 lines of code---hooray
+% for Pyparsing!
+% \begin{macrocode}
+class SoutParser():
+ def __init__(self, fn):
+ self.label = []
+% \end{macrocode}
+% A label line looks like
+% \begin{quote}
+% |\newlabel{@sageinline|\meta{integer}|}{|\marg{bunch of \LTX code}|{}{}{}{}}|
+% \end{quote}
+% which makes the parser definition below pretty obvious. We assign some
+% names to the interesting bits so the |newlabel| method can make the
+% \meta{integer} and \meta{bunch of \LTX code} into the keys and values
+% of a dictionary. The |DeSageTeX| class then uses that dictionary to
+% replace bits in the |.tex| file with their Sage-computed results.
+% \begin{macrocode}
+ parselabel = (r'\newlabel{@sageinline'
+ + Word(nums)('num')
+ + '}{'
+ + curlybrackets('result')
+ + '{}{}{}{}}')
+% \end{macrocode}
+% We tell it to ignore comments, and hook up the list-making method.
+% \begin{macrocode}
+ parselabel.ignore('%' + restOfLine)
+ parselabel.setParseAction(self.newlabel)
+% \end{macrocode}
+% A |.sout| file consists of one or more such lines. Now go parse the
+% file we were given.
+% \begin{macrocode}
+ try:
+ OneOrMore(parselabel).parseFile(fn)
+ except IOError:
+ print 'Error accessing %s; exiting. Does your .sout file exist?' % fn
+ sys.exit(1)
+% \end{macrocode}
+% Pyparser's parse actions get called with three arguments: the string
+% that matched, the location of the beginning, and the resulting parse
+% object. Here we just add a new key-value pair to the dictionary,
+% remembering to strip off the enclosing brackets from the ``result''
+% bit.
+% \begin{macrocode}
+ def newlabel(self, s, l, t):
+ self.label.append(t.result[1:-1])
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{DeSageTeX}
+% Now we define a parser for \LTX files that use \ST commands. We assume
+% that the provided |fn| is just a basename.
+% \begin{macrocode}
+class DeSageTex():
+ def __init__(self, fn):
+ self.sagen = 0
+ self.plotn = 0
+ self.fn = fn
+ self.sout = SoutParser(fn + '.sout')
+% \end{macrocode}
+% Parse |\sage| macros. We just need to pull in the result from the
+% |.sout| file and increment the counter---that's what |self.sage| does.
+% \begin{macrocode}
+ smacro = sagemacroparser
+ smacro.setParseAction(self.sage)
+% \end{macrocode}
+% Parse the |\usepackage{sagetex}| line. Right now we don't support
+% comma-separated lists of packages.
+% \begin{macrocode}
+ usepackage = (r'\usepackage'
+ + Optional(squarebrackets)
+ + '{sagetex}')
+ usepackage.setParseAction(replaceWith(r"""% "\usepackage{sagetex}" line was here:
+\RequirePackage{verbatim}
+\RequirePackage{graphicx}
+\newcommand{\sagetexpause}{\relax}
+\newcommand{\sagetexunpause}{\relax}"""))
+% \end{macrocode}
+% Parse |\sageplot| macros.
+% \begin{macrocode}
+ splot = sageplotparser
+ splot.setParseAction(self.plot)
+% \end{macrocode}
+% The printed environments (|sageblock| and |sageverbatim|) get turned
+% into |verbatim| environments.
+% \begin{macrocode}
+ beginorend = oneOf('begin end')
+ blockorverb = 'sage' + oneOf('block verbatim')
+ blockorverb.setParseAction(replaceWith('verbatim'))
+ senv = '\\' + beginorend + '{' + blockorverb + '}'
+% \end{macrocode}
+% The non-printed |sagesilent| environment gets commented out. We could
+% remove all the text, but this works and makes going back to \ST
+% commands (de-de-\ST{}ing?) easier.
+% \begin{macrocode}
+ silent = Literal('sagesilent')
+ silent.setParseAction(replaceWith('comment'))
+ ssilent = '\\' + beginorend + '{' + silent + '}'
+% \end{macrocode}
+% The |\sagetexindent| macro is no longer relevant, so remove it from
+% the output (``suppress'', in Pyparsing terms).
+% \begin{macrocode}
+ stexindent = Suppress(r'\setlength{\sagetexindent}' + curlybrackets)
+% \end{macrocode}
+% Now we define the parser that actually goes through the file. It just
+% looks for any one of the above bits, while ignoring anything that
+% should be ignored.
+% \begin{macrocode}
+ doit = smacro | senv | ssilent | usepackage | splot | stexindent
+ doit.ignore('%' + restOfLine)
+ doit.ignore(r'\begin{verbatim}' + SkipTo(r'\end{verbatim}'))
+ doit.ignore(r'\begin{comment}' + SkipTo(r'\end{comment}'))
+ doit.ignore(r'\sagetexpause' + SkipTo(r'\sagetexunpause'))
+% \end{macrocode}
+% We can't use the |parseFile| method, because that expects a ``complete
+% grammar'' in which everything falls into some piece of the parser.
+% Instead we suck in the whole file as a single string, and run
+% |transformString| on it, since that will just pick out the interesting
+% bits and munge them according to the above definitions.
+% \begin{macrocode}
+ str = ''.join(open(fn + '.tex', 'r').readlines())
+ self.result = doit.transformString(str)
+% \end{macrocode}
+% That's the end of the class constructor, and it's all we need to do
+% here. You access the results of parsing via the |result| string.
+%
+% We do have two methods to define. The first does the same thing that
+% |\ref| does in your \LTX file: returns the content of the label and
+% increments a counter.
+% \begin{macrocode}
+ def sage(self, s, l, t):
+ self.sagen += 1
+ return self.sout.label[self.sagen - 1]
+% \end{macrocode}
+% The second method returns the appropriate |\includegraphics| command.
+% It does need to account for the default argument.
+% \begin{macrocode}
+ def plot(self, s, l, t):
+ self.plotn += 1
+ if len(t.opts) == 0:
+ opts = r'[width=.75\textwidth]'
+ else:
+ opts = t.opts[0]
+ return (r'\includegraphics%s{sage-plots-for-%s.tex/plot-%s}' %
+ (opts, self.fn, self.plotn - 1))
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{SageCodeExtractor}
+% This class does the opposite of the first: instead of removing Sage
+% stuff and leaving only \LTX, this removes all the \LTX and leaves only
+% Sage.
+% \begin{macrocode}
+class SageCodeExtractor():
+ def __init__(self, fn):
+ smacro = sagemacroparser
+ smacro.setParseAction(self.macroout)
+
+ splot = sageplotparser
+ splot.setParseAction(self.plotout)
+% \end{macrocode}
+% Above, we used the general parsers for |\sage| and |\sageplot|. We
+% have to redo the environment parsers because it seems too hard to
+% define one parser object that will do both things we want: above, we
+% just wanted to change the environment name, and here we want to suck
+% out the code. Here, it's important that we find matching begin/end
+% pairs; above it wasn't. At any rate, it's not a big deal to redo this
+% parser.
+% \begin{macrocode}
+ env_names = oneOf('sageblock sageverbatim sagesilent')
+ senv = r'\begin{' + env_names('env') + '}' + SkipTo(
+ r'\end{' + matchPreviousExpr(env_names) + '}')('code')
+ senv.leaveWhitespace()
+ senv.setParseAction(self.envout)
+
+ spause = sagetexpause
+ spause.setParseAction(self.pause)
+
+ sunpause = sagetexunpause
+ sunpause.setParseAction(self.unpause)
+
+ doit = smacro | splot | senv | spause | sunpause
+
+ str = ''.join(open(fn + '.tex', 'r').readlines())
+ self.result = ''
+
+ doit.transformString(str)
+
+ def macroout(self, s, l, t):
+ self.result += '# \\sage{} from line %s\n' % lineno(l, s)
+ self.result += t.code[1:-1] + '\n\n'
+
+ def plotout(self, s, l, t):
+ self.result += '# \\sageplot{} from line %s:\n' % lineno(l, s)
+ if t.format is not '':
+ self.result += '# format: %s' % t.format[0][1:-1] + '\n'
+ self.result += t.code[1:-1] + '\n\n'
+
+ def envout(self, s, l, t):
+ self.result += '# %s environment from line %s:' % (t.env,
+ lineno(l, s))
+ self.result += t.code[0] + '\n'
+
+ def pause(self, s, l, t):
+ self.result += ('# SageTeX (probably) paused on input line %s.\n\n' %
+ (lineno(l, s)))
+
+ def unpause(self, s, l, t):
+ self.result += ('# SageTeX (probably) unpaused on input line %s.\n\n' %
+ (lineno(l, s)))
+% \end{macrocode}
+% \end{macro}
+
+% \endinput
+%</parsermod>
+% Local Variables:
+% mode: doctex
+% TeX-master: "sagetexpackage"
+% End:
diff --git a/Master/texmf-dist/tex/latex/sagetex/sagetex.sty b/Master/texmf-dist/tex/latex/sagetex/sagetex.sty
index 16e9a2aefb1..79fccf61d07 100644
--- a/Master/texmf-dist/tex/latex/sagetex/sagetex.sty
+++ b/Master/texmf-dist/tex/latex/sagetex/sagetex.sty
@@ -5,10 +5,11 @@
%% The original source files were:
%%
%% sagetexpackage.dtx (with options: `latex')
+%% py-and-sty.dtx (with options: `latex')
%%
-%% This is a generated file.
+%% This is a generated file. It is part of the SageTeX package.
%%
-%% Copyright (C) 2008 by Dan Drake <ddrake@member.ams.org>
+%% Copyright (C) 2009 by Dan Drake <ddrake@member.ams.org>
%%
%% 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
@@ -17,15 +18,15 @@
%%
%% 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.
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+%% Public License for more details.
%%
%% You should have received a copy of the GNU General Public License along
-%% with this program. If not, see <http://www.gnu.org/licenses/>
+%% with this program. If not, see <http://www.gnu.org/licenses/>.
%%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{sagetex}
- [2008/03/12 v1.4 embedding Sage into LaTeX documents]
+ [2009/06/17 v2.2.1 embedding Sage into LaTeX documents]
\RequirePackage{verbatim}
\RequirePackage{graphicx}
\RequirePackage{makecmds}
@@ -37,44 +38,55 @@
\setcounter{ST@plot}{0}
\newlength{\sagetexindent}
\setlength{\sagetexindent}{5ex}
-\newcommand{\ST@epsim}{False}
-\DeclareOption{imagemagick}{\renewcommand{\ST@epsim}{True}}
+\newif\ifST@paused
+\ST@pausedfalse
+\AtBeginDocument{\@ifundefined{ST@final}{%
+\newwrite\ST@sf%
+\immediate\openout\ST@sf=\jobname.sage%
+\newcommand{\ST@wsf}[1]{\immediate\write\ST@sf{#1}}%
+\ST@wsf{# This file (\jobname.sage) was *autogenerated* from the file \jobname.tex.}%
+\ST@wsf{import sagetex}%
+\ST@wsf{_st_ = sagetex.SageTeXProcessor('\jobname')}}%
+{\newcommand{\ST@wsf}[1]{\relax}}}
+\DeclareOption{final}{%
+ \newcommand{\ST@final}{x}%
+ \IfFileExists{\jobname.sout}{}{\AtEndDocument{\PackageWarningNoLine{sagetex}%
+ {`final' option provided, but \jobname.sout^^Jdoesn't exist! No Sage
+ input will appear in your document. Remove the `final'^^Joption and
+ rerun LaTeX on your document}}}}
+\DeclareOption{imagemagick}{%
+ \newcommand{\ST@useimagemagick}{x}%
+ \AtBeginDocument{%
+ \@ifundefined{ST@final}{%
+ \ST@wsf{_st_.useimagemagick = True}}{}}}
+\DeclareOption{epstopdf}{%
+\AtBeginDocument{%
+\@ifundefined{ST@final}{%
+ \ST@wsf{_st_.useepstopdf = True}}{}}}
\ProcessOptions\relax
-\newwrite\ST@sf
-\immediate\openout\ST@sf=\jobname.sage
-\newcommand{\ST@wsf}[1]{\immediate\write\ST@sf{#1}}
-\iffalse
-%% To get .sage files to automatically change the Python path to find
-%% sagetex.py, delete the \iffalse and \fi lines surrounding this and
-%% change the directory below to where sagetex.py can be found.
-\ST@wsf{import sys}
-\ST@wsf{sys.path.insert(0, 'directory with sagetex.py')}
+\InputIfFileExists{\jobname.sout}{}{\typeout{No file \jobname.sout.}}
+\AtBeginDocument{\provideenvironment{NoHyper}{}{}}
+\newcommand{\sage}[1]{\ST@wsf{%
+try:^^J
+ _st_.inline(\theST@inline, #1)^^Jexcept:^^J
+ _st_.goboom(\the\inputlineno)}%
+\ifST@paused
+ \mbox{(Sage\TeX{} is paused)}%
+\else
+ \begin{NoHyper}\ref{@sageinline\theST@inline}\end{NoHyper}
+ \@ifundefined{r@@sageinline\theST@inline}{\gdef\ST@rerun{x}}{}
\fi
-\ST@wsf{import sagetex}
-\ST@wsf{sagetex.openout('\jobname')}
-\InputIfFileExists{\jobname.sout}{}{}
-\newcommand{\sage}[1]{%
-\ST@wsf{try:}%
-\ST@wsf{ sagetex.inline(\theST@inline, #1)}%
-\ST@wsf{except:}%
-\ST@wsf{ sagetex.goboom(\the\inputlineno)}%
-\begin{NoHyper}\ref{@sagelabel\theST@inline}\end{NoHyper}%
-\@ifundefined{r@@sagelabel\theST@inline}{\gdef\ST@rerun{x}}{}%
\stepcounter{ST@inline}}
-\AtBeginDocument{\provideenvironment{NoHyper}{}{}}
\catcode`\%=12
\newcommand{\percent}{%}
\catcode`\%=14
\newcommand{\ST@plotdir}{sage-plots-for-\jobname.tex}
+\newcommand{\ST@missingfilebox}{\framebox[2cm]{\rule[-1cm]{0cm}{2cm}\textbf{??}}}
\newcommand{\sageplot}[1][width=.75\textwidth]{%
- \@ifnextchar[{\ST@sageplot[#1]}{\ST@sageplot[#1][notprovided]}%]
-}
-\def\ST@sageplot[#1][#2]#3{%
-\ST@wsf{try:}%
-\ST@wsf{ sagetex.initplot('\jobname')}%
-\ST@wsf{ sagetex.plot(\theST@plot, #3, format='#2', epsmagick=\ST@epsim)}%
-\ST@wsf{except:}%
-\ST@wsf{ sagetex.goboom(\the\inputlineno)}%
+ \@ifnextchar[{\ST@sageplot[#1]}{\ST@sageplot[#1][notprovided]}}
+\def\ST@sageplot[#1][#2]#3{\ST@wsf{try:^^J
+ _st_.plot(\theST@plot, format='#2', _p_=#3)^^Jexcept:^^J
+ _st_.goboom(\the\inputlineno)}%
\ifpdf
\ifthenelse{\equal{#2}{notprovided}}%
{\ST@inclgrfx{#1}{pdf}}%
@@ -82,38 +94,39 @@
\else
\ifthenelse{\equal{#2}{notprovided}}%
{\ST@inclgrfx{#1}{eps}}%
- {\ifthenelse{\equal{\ST@epsim}{True}}
- {\ST@inclgrfx{#1}{eps}}%
+ {\@ifundefined{ST@useimagemagick}%
{\IfFileExists{\ST@plotdir/plot-\theST@plot.#2}%
- {\framebox[2cm]{\rule[-1cm]{0cm}{2cm}\textbf{??}}%
+ {\ST@missingfilebox%
\PackageWarning{sagetex}{Graphics file
\ST@plotdir/plot-\theST@plot.#2\space on page \thepage\space
cannot be used with DVI output. Use pdflatex or create an EPS
file. Plot command is}}%
- {\framebox[2cm]{\rule[-1cm]{0cm}{2cm}\textbf{??}}%
+ {\ST@missingfilebox%
\PackageWarning{sagetex}{Graphics file
\ST@plotdir/plot-\theST@plot.#2\space on page \thepage\space
- does not exist}%
- \gdef\ST@rerun{x}}}}%
+ does not exist. Plot command is}%
+ \gdef\ST@rerun{x}}}%
+ {\ST@inclgrfx{#1}{eps}}}%
\fi
\stepcounter{ST@plot}}
-\newcommand{\ST@inclgrfx}[2]{%
+\newcommand{\ST@inclgrfx}[2]{\ifST@paused
+ \fbox{\rule[-1cm]{0cm}{2cm}Sage\TeX{} is paused; no graphic}
+\else
\IfFileExists{\ST@plotdir/plot-\theST@plot.#2}%
{\includegraphics[#1]{\ST@plotdir/plot-\theST@plot.#2}}%
- {\framebox[2cm]{\rule[-1cm]{0cm}{2cm}\textbf{??}}%
+ {\ST@missingfilebox%
\PackageWarning{sagetex}{Graphics file
\ST@plotdir/plot-\theST@plot.#2\space on page \thepage\space does not
- exist}%
- \gdef\ST@rerun{x}}}
+ exist. Plot command is}%
+ \gdef\ST@rerun{x}}
+\fi}
\newcommand{\ST@beginsfbl}{%
- \@bsphack%
- \ST@wsf{sagetex.blockbegin()}%
- \ST@wsf{try:}%
+ \@bsphack\ST@wsf{%
+_st_.blockbegin()^^Jtry:}%
\let\do\@makeother\dospecials\catcode`\^^M\active}
\newcommand{\ST@endsfbl}{%
-\ST@wsf{except:}%
-\ST@wsf{ sagetex.goboom(\the\inputlineno)}%
-\ST@wsf{sagetex.blockend()}}
+\ST@wsf{except:^^J
+ _st_.goboom(\the\inputlineno)^^J_st_.blockend()}}
\newenvironment{sageblock}{\ST@beginsfbl%
\def\verbatim@processline{\ST@wsf{ \the\verbatim@line}%
\hspace{\sagetexindent}\the\verbatim@line\par}%
@@ -127,11 +140,21 @@
\def\verbatim@processline{\hspace{\sagetexindent}\the\verbatim@line\par}%
\verbatim}%
{\endverbatim}
-\AtEndDocument{\ST@wsf{sagetex.endofdoc()}%
+\newcommand{\sagetexpause}{\ifST@paused\relax\else
+\ST@wsf{print 'SageTeX paused on \jobname.tex line \the\inputlineno'^^J"""}
+\ST@pausedtrue
+\fi}
+\newcommand{\sagetexunpause}{\ifST@paused
+\ST@wsf{"""^^Jprint 'SageTeX unpaused on \jobname.tex line \the\inputlineno'}
+\ST@pausedfalse
+\fi}
+\AtEndDocument{\ifST@paused
+\ST@wsf{"""^^Jprint 'SageTeX unpaused at end of \jobname.tex'}
+\fi
+\ST@wsf{_st_.endofdoc()}%
\@ifundefined{ST@rerun}{}%
{\PackageWarningNoLine{sagetex}{There were undefined Sage formulas
-and/or plots}%
-\PackageWarningNoLine{sagetex}{Run Sage on \jobname.sage, and then run
+and/or plots.^^JRun Sage on \jobname.sage, and then run
LaTeX on \jobname.tex again}}}
\endinput
%%