summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/sagetex
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/sagetex')
-rw-r--r--macros/latex/contrib/sagetex/PKG-INFO19
-rw-r--r--macros/latex/contrib/sagetex/README.md10
-rw-r--r--macros/latex/contrib/sagetex/example.pdfbin276082 -> 277744 bytes
-rw-r--r--macros/latex/contrib/sagetex/py-and-sty.dtx14
-rw-r--r--macros/latex/contrib/sagetex/sagetex.dtx28
-rw-r--r--macros/latex/contrib/sagetex/sagetex.ins9
-rw-r--r--macros/latex/contrib/sagetex/sagetex.pdfbin497692 -> 501661 bytes
-rw-r--r--macros/latex/contrib/sagetex/scripts.dtx410
-rw-r--r--macros/latex/contrib/sagetex/setup.py11
9 files changed, 259 insertions, 242 deletions
diff --git a/macros/latex/contrib/sagetex/PKG-INFO b/macros/latex/contrib/sagetex/PKG-INFO
index 628c7e2da9..6cc7afeaa0 100644
--- a/macros/latex/contrib/sagetex/PKG-INFO
+++ b/macros/latex/contrib/sagetex/PKG-INFO
@@ -1,12 +1,15 @@
-Metadata-Version: 1.0
+Metadata-Version: 2.1
Name: sagetex
-Version: 3.5
+Version: 3.6.1
Summary: Embed Sage code and plots into LaTeX
Home-page: https://github.com/sagemath/sagetex
-Author: SageMath developers
-Author-email: sage-devel@googlegroups.com
+Author: Dan Drake
+Author-email: dr.dan.drake@gmail.com
+Maintainer: SageMath developers
+Maintainer-email: sage-devel@googlegroups.com
License: GPLv2+
-Description: The SageTeX package allows you to embed code,
- results of computations, and plots from the Sage mathematics
- software suite (http://sagemath.org) into LaTeX documents.
-Platform: UNKNOWN
+License-File: LICENSE
+
+The SageTeX package allows you to embed code,
+ results of computations, and plots from the Sage mathematics
+ software suite (http://sagemath.org) into LaTeX documents.
diff --git a/macros/latex/contrib/sagetex/README.md b/macros/latex/contrib/sagetex/README.md
index f6e75ac061..2864569f39 100644
--- a/macros/latex/contrib/sagetex/README.md
+++ b/macros/latex/contrib/sagetex/README.md
@@ -8,7 +8,7 @@ computations, and plots from the Sage mathematics software suite
SageTeX is included with Sage, so to use it, you only need to make the
file sagetex.sty known to TeX; that file will be in
-SAGE_ROOT/local/share/texmf/tex/latex/sagetex, along with
+SAGE_ROOT/venv/share/texmf/tex/latex/sagetex, along with
documentation and examples. See the Sage tutorial at
https://doc.sagemath.org/html/en/tutorial/sagetex.html
for a quick usage introduction, and for complete installation
@@ -23,14 +23,14 @@ the SAGE_ROOT/... directory mentioned above.
If you want to extract any of SageTeX's files from the .dtx sources, you
can do
- 0. Run `latex sagetex.ins'
+ 0. Run `latex sagetex.ins`
To regenerate the documentation, do
- 1. Run `latex sagetex.dtx'
- 2. Run `sage sagetex.sage'
+ 1. Run `latex sagetex.dtx`
+ 2. Run `sage sagetex.sage`
3. Run the indexing commands that the .ins file told you about.
- 4. Run `latex sagetex.dtx' again.
+ 4. Run `latex sagetex.dtx` again.
You can skip step 3 if you don't care about the index. You will need the
pgf and tikz packages installed to typeset the figures.
diff --git a/macros/latex/contrib/sagetex/example.pdf b/macros/latex/contrib/sagetex/example.pdf
index af815f0b56..2f8c9347d5 100644
--- a/macros/latex/contrib/sagetex/example.pdf
+++ b/macros/latex/contrib/sagetex/example.pdf
Binary files differ
diff --git a/macros/latex/contrib/sagetex/py-and-sty.dtx b/macros/latex/contrib/sagetex/py-and-sty.dtx
index 49bf5cd05e..acd92c08e2 100644
--- a/macros/latex/contrib/sagetex/py-and-sty.dtx
+++ b/macros/latex/contrib/sagetex/py-and-sty.dtx
@@ -29,7 +29,7 @@
% and |listings| for the |sagecommandline| environment.
% \begin{macrocode}
\RequirePackage{listings}
-\RequirePackage{color}
+\RequirePackage{xcolor}
\lstdefinelanguage{Sage}[]{Python}
{morekeywords={False,sage,True},sensitive=true}
\lstdefinelanguage{SageOutput}[]{}
@@ -68,9 +68,9 @@
\lstdefinestyle{SageOutput}{
style=DefaultSageOutput,
}
-\definecolor{dbluecolor}{rgb}{0.01,0.02,0.7}
-\definecolor{dgreencolor}{rgb}{0.2,0.4,0.0}
-\definecolor{dgraycolor}{rgb}{0.30,0.3,0.30}
+\providecolor{dbluecolor}{rgb}{0.01,0.02,0.7}
+\providecolor{dgreencolor}{rgb}{0.2,0.4,0.0}
+\providecolor{dgraycolor}{rgb}{0.30,0.3,0.30}
% \end{macrocode}
% Unsurprisingly, the |\sageplot| command works poorly without graphics
% support.
@@ -1243,7 +1243,7 @@ http://doc.sagemath.org/html/en/tutorial/sagetex.html.""".format(jobname,
raise SyntaxError(""" SageTeX no longer supports "..." for line continuation in sagexample and
sagecommandline environments. Use "....:", which matches what the Sage
interpreter uses. See the documentation and example file in
-SAGE_ROOT/local/share/doc/sagetex.""")
+SAGE_ROOT/venv/share/doc/sagetex.""")
if has_cont:
cmd.append(line[has_cont.end():])
ret.append((start, end, '\n'.join(cmd)))
@@ -1521,9 +1521,9 @@ SAGE_ROOT/local/share/doc/sagetex.""")
% \begin{center}
% \verb+egrep -v '^( _st_.goboom| ?_st_.current_tex_line|print(.SageT)' filename.sage | md5sum+
% \end{center}
-% in a shell. The included |run-sagetex-if-necessary| uses this
+% in a shell. The included |sagetex-run| uses this
% mechanism to, well, only run Sage when necessary; see
-% \autoref{sec:run-sagetex-if-necessary}.
+% \autoref{sec:sagetex-run}.
% \begin{macrocode}
def endofdoc(self):
sagef = open(self.filename + '.sagetex.sage', 'r')
diff --git a/macros/latex/contrib/sagetex/sagetex.dtx b/macros/latex/contrib/sagetex/sagetex.dtx
index b5598d990e..e028698816 100644
--- a/macros/latex/contrib/sagetex/sagetex.dtx
+++ b/macros/latex/contrib/sagetex/sagetex.dtx
@@ -30,10 +30,10 @@
%<latex>\ProvidesPackage{sagetex}
%<python>__version__ = """
%<*latex|python>
- [2020/08/12 v3.5 embedding Sage into LaTeX documents]
+ [2022/08/21 v3.6.1 embedding Sage into LaTeX documents]
%</latex|python>
%<python>""".strip()
-%<latex>\newcommand{\ST@ver}{2020/08/12 v3.5}
+%<latex>\newcommand{\ST@ver}{2022/08/21 v3.6.1}
%<*driver>
\documentclass{ltxdoc}
\usepackage{sagetex}
@@ -261,9 +261,9 @@ suggestions.
% |sage.plot.plot?| and look for |ticks| and |tick_formatter|.)
%
% Till Tantau has some good commentary on the use of graphics in the
-% \href{http://www.ctan.org/tex-archive/help/Catalogue/entries/pgf.html}{``Guidelines
+% \href{https://pgf-tikz.github.io/pgf/pgfmanual.pdf}{``Guidelines
% on Graphics'' section of the \textsc{pgf} manual} (chapter 7 of the
-% manual for version 2.10). You should always give careful thought and
+% manual for version 3.1.9). 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:
%
@@ -539,7 +539,7 @@ suggestions.
% ``\percent'' inside such an environment will get written, uh, verbatim
% to the |.sage| file.
%
-% \paragraph{Arguments with side effects}
+% \subsubsection{Arguments with side effects}
%
% Be careful when feeding |\sage| and |\sagestr| arguments that have
% side effects, since in some situations they can get evaluated more
@@ -763,7 +763,7 @@ suggestions.
% indented when typeset. You can change this length however you like
% with |\setlength|: do |\setlength{\sagetexindent}{6ex}| or whatever.
%
-% \DescribeEnv{sageexample} This environment allow you to include
+% \DescribeEnv{sageexample} This environment allows you to include
% doctest-like snippets in your document that will be nicely typeset.
% For example,
% \begin{quote}
@@ -811,7 +811,7 @@ suggestions.
% Thi\'ery.\\
%
% \DescribeEnv{sagecommandline} This environment is similar to the
-% sageexample environment in that it allow you to use \ST as a
+% sageexample environment in that it allows you to use \ST as a
% pretty-printing command line, or to include doctest-like snippets in
% your document. The difference is that the output is typeset as text,
% much like running Sage on the command line, using the
@@ -839,7 +839,7 @@ suggestions.
% You have a choice of either explicitly providing the Sage output or
% leaving it up to the computer to fill in the blanks. Above, the output
% for $t$ was provided, but the output for the |factor()| command
-% wasn't. Moreover, any Sage comment that starts with a ``at'' sign is
+% wasn't. Moreover, any Sage comment that starts with an ``at'' sign is
% escaped to \LTX. In particular, you can use |\label| to mark line
% numbers in order to |\ref|erence and |\pageref|erence them as usual.
% See the example file to see this mechanism in action.
@@ -960,8 +960,8 @@ suggestions.
% the typesetting engine dropdown menu and then typeset.
%
% (You can also replace "|sage|" above with the
-% |run-sagetex-if-necessary| script---see
-% \autoref{sec:run-sagetex-if-necessary}.)
+% |sagetex-run| script---see
+% \autoref{sec:sagetex-run}.)
%
% \subsection{Using Beamer}
%
@@ -1054,11 +1054,11 @@ suggestions.
%
% \subsubsection{The 21st century way}
%
-% The SageMathCloud
-% (\href{http://cloud.sagemath.com}{\texttt{cloud.sagemath.com}}) service has
+% CoCalc
+% (\href{https://cocalc.com/}{\texttt{cocalc.com/}}) has
% full support for \ST, is free to use, and has many fantastic
% collaboration features. If you somehow want to collaborate on a
-% \ST-enabled \TeX document with a colleague, using SageMathCloud is one
+% \ST-enabled \TeX document with a colleague, using CoCalc is one
% of the best and easiest ways to do it. You and your collaborators
% simply create an account, then make a project for your collaboration,
% and add all the collaborators to the project. Then you can all enjoy
@@ -1066,7 +1066,7 @@ suggestions.
%
% \subsubsection{The $N$th century way, for $N < 21$}
%
-% Using anything other than SageMathCloud, |git|, or similar tools these
+% Using anything other than CoCalc, |git|, or similar tools these
% days seems pretty primitive. If emailing |.tex| files back and forth
% seems perfectly reasonable to you, or if you have to send a file to a
% journal, the easiest way is to simply include with your document the
diff --git a/macros/latex/contrib/sagetex/sagetex.ins b/macros/latex/contrib/sagetex/sagetex.ins
index dd8dabb80a..bbbbe1388a 100644
--- a/macros/latex/contrib/sagetex/sagetex.ins
+++ b/macros/latex/contrib/sagetex/sagetex.ins
@@ -84,7 +84,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
\from{py-and-sty.dtx}{python}}}
\generate{\file{sagetexparse.py}{\from{scripts.dtx}{parsermod}}}
-
\usedir{scripts/sagetex}
% Now define a new preamble with the shebang line at the top.
@@ -92,10 +91,10 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
\def\envpypreamble{\hash!/usr/bin/env python^^J\pypreamble}
\usepreamble\envpypreamble
-\generate{\file{run-sagetex-if-necessary.py}{\from{scripts.dtx}{ifnecessaryscript}}}
-\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}}}
+\generate{\file{sagetex-run.py}{\from{scripts.dtx}{ifnecessaryscript}}}
+\generate{\file{sagetex-makestatic.py}{\from{scripts.dtx}{staticscript}}}
+\generate{\file{sagetex-extract.py}{\from{scripts.dtx}{extractscript}}}
+\generate{\file{sagetex-remote.py}{\from{remote-sagetex.dtx}{remotesagetex}}}
\obeyspaces
\Msg{******************************************************************}
diff --git a/macros/latex/contrib/sagetex/sagetex.pdf b/macros/latex/contrib/sagetex/sagetex.pdf
index 4ad0f319e8..66f93e8add 100644
--- a/macros/latex/contrib/sagetex/sagetex.pdf
+++ b/macros/latex/contrib/sagetex/sagetex.pdf
Binary files differ
diff --git a/macros/latex/contrib/sagetex/scripts.dtx b/macros/latex/contrib/sagetex/scripts.dtx
index 8f7048dcef..988f9732dc 100644
--- a/macros/latex/contrib/sagetex/scripts.dtx
+++ b/macros/latex/contrib/sagetex/scripts.dtx
@@ -1,27 +1,26 @@
% \section{Included Python scripts}
% \label{sec:included-scripts}
%
-% Here we describe the Python code for |run-sagetex-if-necessary|, and
-% also |makestatic.py|, which removes \ST commands to produce a
-% ``static'' file, and |extractsagecode.py|, which extracts all the Sage
-% code from a |.tex| file.
+% Here we describe the Python code for \ST scripts, for running
+% Sage only if necessary, substituting in Sage outputs to produce
+% a ``static'' file, and extracting all Sage code from a |.tex| file.
%
-% \subsection{run-sagetex-if-necessary}
-% \label{sec:run-sagetex-if-necessary}
+% \subsection{\texttt{sagetex-run}}
+% \label{sec:sagetex-run}
% \iffalse
%<*ifnecessaryscript>
% \fi
%
% When working on a document that uses \ST, running Sage every time you
% typeset your document may take too long, especially since it often
-% won't be necessary. This script is a drop-in replacement for Sage:
+% is not necessary. This script is a drop-in replacement for Sage:
% instead of
% \begin{center}
% |sage document.sagetex.sage|
% \end{center}
% you can do
% \begin{center}
-% |run-sagetex-if-necessary.py document.sagetex.sage|
+% |sagetex-run document.sagetex.sage|
% \end{center}
% and it will use the MD5 mechanism described in the |endofdoc| macro
% (page~{\pageref{macro:endofdoc}). With this, you can set up your editor
@@ -29,105 +28,114 @@
% that does
% \begin{quote}
% |pdflatex $1|\\
-% |run-sagetex-if-necessary.py $1|
+% |sagetex-run $1|
% \end{quote}
% which will only, of course, run Sage when necessary.
% \begin{macrocode}
-
-# given a filename f, examines f.sagetex.sage and f.sagetex.sout and
-# runs Sage if necessary.
+"""
+Given a filename f, examines f.sagetex.sage and f.sagetex.sout and
+runs Sage if necessary.
+"""
import hashlib
import sys
import os
import re
import subprocess
-from six import PY3
-
-# CHANGE THIS AS APPROPRIATE
-path_to_sage = os.path.expanduser('~/bin/sage')
-# or try to auto-find it:
-# path_to_sage = subprocess.check_output(['which', 'sage']).strip()
-# or just tell me:
-# path_to_sage = '/usr/local/bin/sage'
-
-if sys.argv[1].endswith('.sagetex.sage'):
- src = sys.argv[1][:-13]
-else:
- src = os.path.splitext(sys.argv[1])[0]
-
-usepackage = r'usepackage(\[.*\])?{sagetex}'
-uses_sagetex = False
-
-# if it does not use sagetex, obviously running sage is unnecessary
-with open(src + '.tex') as texf:
- for line in texf:
- if line.strip().startswith(r'\usepackage') and re.search(usepackage, line):
- uses_sagetex = True
- break
-
-if not uses_sagetex:
- print(src + ".tex doesn't seem to use SageTeX, exiting.")
- sys.exit(0)
-
-# if something goes wrong, assume we need to run Sage
-run_sage = True
-ignore = r"^( _st_.goboom|print\('SageT| ?_st_.current_tex_line)"
-
-try:
- with open(src + '.sagetex.sage', 'r') as sagef:
- h = hashlib.md5()
- for line in sagef:
- if not re.search(ignore, line):
- if PY3:
- h.update(bytearray(line,'utf8'))
- else:
- h.update(bytearray(line))
-except IOError:
- print('{0}.sagetex.sage not found, I think you need to typeset {0}.tex first.'.format(src))
- sys.exit(1)
-
-try:
- with open(src + '.sagetex.sout', 'r') as outf:
- for line in outf:
- m = re.match('%([0-9a-f]+)% md5sum', line)
- if m:
- print('computed md5:', h.hexdigest())
- print('sagetex.sout md5:', m.group(1))
- if h.hexdigest() == m.group(1):
- run_sage = False
+import shutil
+import argparse
+
+def argparser():
+ p = argparse.ArgumentParser(description=__doc__.strip())
+ p.add_argument('--sage', action='store', default=find_sage(),
+ help="Location of the Sage executable")
+ p.add_argument('src', help="Input file name (basename or .sagetex.sage)")
+ return p
+
+def find_sage():
+ return shutil.which('sage') or 'sage'
+
+def run(args):
+ src = args.src
+ path_to_sage = args.sage
+
+ if src.endswith('.sagetex.sage'):
+ src = src[:-13]
+ else:
+ src = os.path.splitext(src)[0]
+
+ # Ensure results are output in the same directory as the source files
+ os.chdir(os.path.dirname(src))
+ src = os.path.basename(src)
+
+ usepackage = r'usepackage(\[.*\])?{sagetex}'
+ uses_sagetex = False
+
+ # If it does not use sagetex, obviously running sage is unnecessary.
+ if os.path.isfile(src + '.tex'):
+ with open(src + '.tex') as texf:
+ for line in texf:
+ if line.strip().startswith(r'\usepackage') and re.search(usepackage, line):
+ uses_sagetex = True
break
-except IOError:
- pass
-
-if run_sage:
- print('Need to run Sage on {0}.'.format(src))
- sys.exit(subprocess.call([path_to_sage, src + '.sagetex.sage']))
-else:
- print('Not necessary to run Sage on {0}.'.format(src))
+ else:
+ # The .tex file might not exist if LaTeX output was put to a different
+ # directory, so in that case just assume we need to build.
+ uses_sagetex = True
+
+ if not uses_sagetex:
+ print(src + ".tex doesn't seem to use SageTeX, exiting.", file=sys.stderr)
+ sys.exit(1)
+
+ # if something goes wrong, assume we need to run Sage
+ run_sage = True
+ ignore = r"^( _st_.goboom|print\('SageT| ?_st_.current_tex_line)"
+
+ try:
+ with open(src + '.sagetex.sage', 'r') as sagef:
+ h = hashlib.md5()
+ for line in sagef:
+ if not re.search(ignore, line):
+ h.update(bytearray(line,'utf8'))
+ except IOError:
+ print('{0}.sagetex.sage not found, I think you need to typeset {0}.tex first.'
+ ''.format(src), file=sys.stderr)
+ sys.exit(1)
+
+ try:
+ with open(src + '.sagetex.sout', 'r') as outf:
+ for line in outf:
+ m = re.match('%([0-9a-f]+)% md5sum', line)
+ if m:
+ print('computed md5:', h.hexdigest())
+ print('sagetex.sout md5:', m.group(1))
+ if h.hexdigest() == m.group(1):
+ run_sage = False
+ break
+ except IOError:
+ pass
+
+ if run_sage:
+ print('Need to run Sage on {0}.'.format(src))
+ sys.exit(subprocess.call([path_to_sage, src + '.sagetex.sage']))
+ else:
+ print('Not necessary to run Sage on {0}.'.format(src))
+
+if __name__ == "__main__":
+ run(argparser().parse_args())
% \end{macrocode}
%
-% \subsection{makestatic.py}
-% \label{sec:makestatic}
+% \subsection{\texttt{sagetex-makestatic}}
+% \label{sec:sagetex-makestatic}
% \iffalse
%</ifnecessaryscript>
%<*staticscript>
% \fi
%
-% Now the |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.
+% Now the |sagetex-makestatic|:
+%
% \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.
@@ -136,53 +144,61 @@ Sage on `inputfile' already.
`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 as 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])
+See the SageTeX documentation for more details.
+"""
+import sys
+import time
+import os.path
+import argparse
+
+from sagetexparse import DeSageTex
+
+def argparser():
+ p = argparse.ArgumentParser(description=__doc__.strip())
+ p.add_argument('inputfile', help="Input file name (basename or .tex)")
+ p.add_argument('outputfile', nargs='?', default=None, help="Output file name")
+ p.add_argument('-o', '--overwrite', action="store_true", default=False,
+ help="Overwrite output file if it exists")
+ p.add_argument('-s', '--sout', action="store", default=None,
+ help="Location of the .sagetex.sout file")
+ return p
+
+def run(args):
+ src, dst, overwrite = args.inputfile, args.outputfile, args.overwrite
+
+ if dst is not None and (os.path.exists(dst) and not overwrite):
+ print('Error: %s exists and overwrite option not specified.' % dst,
+ file=sys.stderr)
+ sys.exit(1)
+
+ src, ext = os.path.splitext(src)
+ texfn = src + '.tex'
+ soutfn = args.sout if args.sout is not None else src + '.sagetex.sout'
% \end{macrocode}
% All the real work gets done in the line below. Sorry it's not more
% exciting-looking.
% \begin{macrocode}
-desagetexed = DeSageTex(src)
+ desagetexed = DeSageTex(texfn, soutfn)
% \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\n%% replaced with plain LaTeX. Processed %s.\n" % time.strftime('%a %d %b %Y %H:%M:%S', time.localtime())
+ header = ("%% SageTeX commands have been automatically removed from this file and\n"
+ "%% replaced with plain LaTeX. Processed %s.\n"
+ "" % time.strftime('%a %d %b %Y %H:%M:%S', time.localtime()))
-if len(args) == 2:
- dest = open(args[1], 'w')
-else:
- dest = sys.stdout
+ if dst is not None:
+ dest = open(dst, 'w')
+ else:
+ dest = sys.stdout
-dest.write(header)
-dest.write(desagetexed.result)
+ dest.write(header)
+ dest.write(desagetexed.result)
+
+if __name__ == "__main__":
+ run(argparser().parse_args())
% \end{macrocode}
%
% \iffalse
@@ -190,20 +206,12 @@ dest.write(desagetexed.result)
%<*extractscript>
% \fi
%
-% \subsection{extractsagecode.py}
+% \subsection{\texttt{sagetex-extract}}
%
-% Same idea as |makestatic.py|, except this does basically the opposite
+% Same idea as |sagetex-makestatic|, 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
@@ -212,47 +220,49 @@ 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 as 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)
+See the SageTeX documentation for more details.
+"""
+import sys
+import time
+import os.path
+import argparse
+
+from sagetexparse import SageCodeExtractor
+
+def argparser():
+ p = argparse.ArgumentParser(description=__doc__.strip())
+ p.add_argument('inputfile', help="Input file name (basename or .tex)")
+ p.add_argument('outputfile', nargs='?', default=None, help="Output file name")
+ p.add_argument('-o', '--overwrite', action="store_true", default=False,
+ help="Overwrite output file if it exists")
+ p.add_argument('--no-inline', action="store_true", default=False,
+ help="Extract code only from Sage environments")
+ return p
+
+def run(args):
+ src, dst, overwrite = args.inputfile, args.outputfile, args.overwrite
+
+ if dst is not None and (os.path.exists(dst) and not overwrite):
+ print('Error: %s exists and overwrite option not specified.' % dst,
+ file=sys.stderr)
+ sys.exit(1)
+
+ src, ext = os.path.splitext(src)
+ sagecode = SageCodeExtractor(src + '.tex', inline=not args.no_inline)
+ header = ("#> This file contains Sage code extracted from %s%s.\n"
+ "#> Processed %s.\n"
+ "" % (src, ext, time.strftime('%a %d %b %Y %H:%M:%S', time.localtime())))
+
+ if dst is not None:
+ dest = open(dst, 'w')
+ else:
+ dest = sys.stdout
+
+ dest.write(header)
+ dest.write(sagecode.result)
+
+if __name__ == "__main__":
+ run(argparser().parse_args())
% \end{macrocode}
%
% \iffalse
@@ -271,6 +281,8 @@ dest.write(sagecode.result)
% over the screen.
% \begin{macrocode}
import sys
+import os
+import textwrap
from pyparsing import *
% \end{macrocode}
% First, we define this very helpful parser: it finds the matching
@@ -281,8 +293,7 @@ from pyparsing import *
% \begin{macrocode}
def skipToMatching(opener, closer):
nest = nestedExpr(opener, closer)
- nest.setParseAction(lambda l, s, t: l[s:getTokensEndLoc()])
- return nest
+ return originalTextFor(nest)
curlybrackets = skipToMatching('{', '}')
squarebrackets = skipToMatching('[', ']')
@@ -290,6 +301,7 @@ squarebrackets = skipToMatching('[', ']')
% Next, parser for |\sage|, |\sageplot|, and pause/unpause calls:
% \begin{macrocode}
sagemacroparser = r'\sage' + curlybrackets('code')
+sagestrmacroparser = r'\sagestr' + curlybrackets('code')
sageplotparser = (r'\sageplot'
+ Optional(squarebrackets)('opts')
+ Optional(squarebrackets)('format')
@@ -356,17 +368,19 @@ class SoutParser():
% that the provided |fn| is just a basename.
% \begin{macrocode}
class DeSageTex():
- def __init__(self, fn):
+ def __init__(self, texfn, soutfn):
self.sagen = 0
self.plotn = 0
- self.fn = fn
- self.sout = SoutParser(fn + '.sagetex.sout')
+ self.fn = os.path.basename(texfn)
+ self.sout = SoutParser(soutfn)
% \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}
+ strmacro = sagestrmacroparser
smacro = sagemacroparser
smacro.setParseAction(self.sage)
+ strmacro.setParseAction(self.sage)
% \end{macrocode}
% Parse the |\usepackage{sagetex}| line. Right now we don't support
% comma-separated lists of packages.
@@ -410,7 +424,7 @@ class DeSageTex():
% 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 = smacro | senv | ssilent | usepackage | splot | stexindent |strmacro
doit.ignore('%' + restOfLine)
doit.ignore(r'\begin{verbatim}' + SkipTo(r'\end{verbatim}'))
doit.ignore(r'\begin{comment}' + SkipTo(r'\end{comment}'))
@@ -422,7 +436,7 @@ class DeSageTex():
% |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())
+ str = ''.join(open(texfn, '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
@@ -456,7 +470,7 @@ class DeSageTex():
% Sage.
% \begin{macrocode}
class SageCodeExtractor():
- def __init__(self, fn):
+ def __init__(self, texfn, inline=True):
smacro = sagemacroparser
smacro.setParseAction(self.macroout)
@@ -483,34 +497,38 @@ class SageCodeExtractor():
sunpause = sagetexunpause
sunpause.setParseAction(self.unpause)
- doit = smacro | splot | senv | spause | sunpause
+ if inline:
+ doit = smacro | splot | senv | spause | sunpause
+ else:
+ doit = senv | spause | sunpause
+ doit.ignore('%' + restOfLine)
- str = ''.join(open(fn + '.tex', 'r').readlines())
+ str = ''.join(open(texfn, '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'
+ self.result += '#> \\sage{} from line %s\n' % lineno(l, s)
+ self.result += textwrap.dedent(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'
+ self.result += '#> \\sageplot{} from line %s:\n' % lineno(l, s)
+ if t.format != '':
+ self.result += '#> format: %s' % t.format[0][1:-1] + '\n'
+ self.result += textwrap.dedent(t.code[1:-1]) + '\n\n'
def envout(self, s, l, t):
- self.result += '# %s environment from line %s:' % (t.env,
+ self.result += '#> %s environment from line %s:' % (t.env,
lineno(l, s))
- self.result += t.code[0] + '\n'
+ self.result += textwrap.dedent(''.join(t.code)) + '\n'
def pause(self, s, l, t):
- self.result += ('# SageTeX (probably) paused on input line %s.\n\n' %
+ 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' %
+ self.result += ('#> SageTeX (probably) unpaused on input line %s.\n\n' %
(lineno(l, s)))
% \end{macrocode}
% \end{macro}
diff --git a/macros/latex/contrib/sagetex/setup.py b/macros/latex/contrib/sagetex/setup.py
index 28e2712065..b83a6bbac8 100644
--- a/macros/latex/contrib/sagetex/setup.py
+++ b/macros/latex/contrib/sagetex/setup.py
@@ -4,27 +4,24 @@ setup(name='sagetex',
long_description="""The SageTeX package allows you to embed code,
results of computations, and plots from the Sage mathematics
software suite (http://sagemath.org) into LaTeX documents.""",
- version='3.5',
+ version='3.6.1',
author='Dan Drake',
author_email='dr.dan.drake@gmail.com',
maintainer='SageMath developers',
maintainer_email='sage-devel@googlegroups.com',
url='https://github.com/sagemath/sagetex',
license='GPLv2+',
- py_modules=['sagetex'],
+ py_modules=['sagetex', 'sagetexparse'],
+ scripts=['sagetex-run', 'sagetex-extract', 'sagetex-makestatic', 'sagetex-remote'],
+ install_requires=['pyparsing'],
data_files = [('share/texmf/tex/latex/sagetex',
['example.tex',
'CONTRIBUTORS',
- 'extractsagecode.py',
- 'run-sagetex-if-necessary.py',
- 'makestatic.py',
'scripts.dtx',
'remote-sagetex.dtx',
- 'remote-sagetex.py',
'py-and-sty.dtx',
'sagetex.dtx',
'sagetex.ins',
- 'sagetexparse.py',
'sagetex.sty']),
('share/doc/sagetex', [
'example.tex',